Commit 198ea9e294e38cea49f9f2d9b911bdfdd20e48dc
1 parent
b2daeb8e0f
Exists in
master
and in
54 other branches
Last minute fixes / cleanup.
Showing 3 changed files with 9 additions and 8 deletions Inline Diff
board/evb64260/pci.c
1 | /* PCI.c - PCI functions */ | 1 | /* PCI.c - PCI functions */ |
2 | 2 | ||
3 | /* Copyright - Galileo technology. */ | 3 | /* Copyright - Galileo technology. */ |
4 | 4 | ||
5 | #include <common.h> | 5 | #include <common.h> |
6 | #include <pci.h> | 6 | #include <pci.h> |
7 | 7 | ||
8 | #include <galileo/pci.h> | 8 | #include <galileo/pci.h> |
9 | 9 | ||
10 | static const unsigned char pci_irq_swizzle[2][PCI_MAX_DEVICES] = { | 10 | static const unsigned char pci_irq_swizzle[2][PCI_MAX_DEVICES] = { |
11 | #ifdef CONFIG_ZUMA_V2 | 11 | #ifdef CONFIG_ZUMA_V2 |
12 | {0, 0, 0, 0, 0, 0, 0, 29,[8...PCI_MAX_DEVICES - 1] = 0}, | 12 | {0, 0, 0, 0, 0, 0, 0, 29,[8 ... PCI_MAX_DEVICES - 1] = 0}, |
13 | {0, 0, 0, 0, 0, 0, 0, 28,[8...PCI_MAX_DEVICES - 1] = 0} | 13 | {0, 0, 0, 0, 0, 0, 0, 28,[8 ... PCI_MAX_DEVICES - 1] = 0} |
14 | #else /* EVB??? This is a guess */ | 14 | #else /* EVB??? This is a guess */ |
15 | {0, 0, 0, 0, 0, 0, 0, 27, 27,[9...PCI_MAX_DEVICES - 1] = 0}, | 15 | {0, 0, 0, 0, 0, 0, 0, 27, 27,[9 ... PCI_MAX_DEVICES - 1] = 0}, |
16 | {0, 0, 0, 0, 0, 0, 0, 29, 29,[9...PCI_MAX_DEVICES - 1] = 0} | 16 | {0, 0, 0, 0, 0, 0, 0, 29, 29,[9 ... PCI_MAX_DEVICES - 1] = 0} |
17 | #endif | 17 | #endif |
18 | }; | 18 | }; |
19 | 19 | ||
20 | static const unsigned int pci_p2p_configuration_reg[] = { | 20 | static const unsigned int pci_p2p_configuration_reg[] = { |
21 | PCI_0P2P_CONFIGURATION, PCI_1P2P_CONFIGURATION | 21 | PCI_0P2P_CONFIGURATION, PCI_1P2P_CONFIGURATION |
22 | }; | 22 | }; |
23 | 23 | ||
24 | static const unsigned int pci_configuration_address[] = { | 24 | static const unsigned int pci_configuration_address[] = { |
25 | PCI_0CONFIGURATION_ADDRESS, PCI_1CONFIGURATION_ADDRESS | 25 | PCI_0CONFIGURATION_ADDRESS, PCI_1CONFIGURATION_ADDRESS |
26 | }; | 26 | }; |
27 | 27 | ||
28 | static const unsigned int pci_configuration_data[] = { | 28 | static const unsigned int pci_configuration_data[] = { |
29 | PCI_0CONFIGURATION_DATA_VIRTUAL_REGISTER, | 29 | PCI_0CONFIGURATION_DATA_VIRTUAL_REGISTER, |
30 | PCI_1CONFIGURATION_DATA_VIRTUAL_REGISTER | 30 | PCI_1CONFIGURATION_DATA_VIRTUAL_REGISTER |
31 | }; | 31 | }; |
32 | 32 | ||
33 | static const unsigned int pci_error_cause_reg[] = { | 33 | static const unsigned int pci_error_cause_reg[] = { |
34 | PCI_0ERROR_CAUSE, PCI_1ERROR_CAUSE | 34 | PCI_0ERROR_CAUSE, PCI_1ERROR_CAUSE |
35 | }; | 35 | }; |
36 | 36 | ||
37 | static const unsigned int pci_arbiter_control[] = { | 37 | static const unsigned int pci_arbiter_control[] = { |
38 | PCI_0ARBITER_CONTROL, PCI_1ARBITER_CONTROL | 38 | PCI_0ARBITER_CONTROL, PCI_1ARBITER_CONTROL |
39 | }; | 39 | }; |
40 | 40 | ||
41 | static const unsigned int pci_snoop_control_base_0_low[] = { | 41 | static const unsigned int pci_snoop_control_base_0_low[] = { |
42 | PCI_0SNOOP_CONTROL_BASE_0_LOW, PCI_1SNOOP_CONTROL_BASE_0_LOW | 42 | PCI_0SNOOP_CONTROL_BASE_0_LOW, PCI_1SNOOP_CONTROL_BASE_0_LOW |
43 | }; | 43 | }; |
44 | static const unsigned int pci_snoop_control_top_0[] = { | 44 | static const unsigned int pci_snoop_control_top_0[] = { |
45 | PCI_0SNOOP_CONTROL_TOP_0, PCI_1SNOOP_CONTROL_TOP_0 | 45 | PCI_0SNOOP_CONTROL_TOP_0, PCI_1SNOOP_CONTROL_TOP_0 |
46 | }; | 46 | }; |
47 | 47 | ||
48 | static const unsigned int pci_access_control_base_0_low[] = { | 48 | static const unsigned int pci_access_control_base_0_low[] = { |
49 | PCI_0ACCESS_CONTROL_BASE_0_LOW, PCI_1ACCESS_CONTROL_BASE_0_LOW | 49 | PCI_0ACCESS_CONTROL_BASE_0_LOW, PCI_1ACCESS_CONTROL_BASE_0_LOW |
50 | }; | 50 | }; |
51 | static const unsigned int pci_access_control_top_0[] = { | 51 | static const unsigned int pci_access_control_top_0[] = { |
52 | PCI_0ACCESS_CONTROL_TOP_0, PCI_1ACCESS_CONTROL_TOP_0 | 52 | PCI_0ACCESS_CONTROL_TOP_0, PCI_1ACCESS_CONTROL_TOP_0 |
53 | }; | 53 | }; |
54 | 54 | ||
55 | static const unsigned int pci_scs_bank_size[2][4] = { | 55 | static const unsigned int pci_scs_bank_size[2][4] = { |
56 | {PCI_0SCS_0_BANK_SIZE, PCI_0SCS_1_BANK_SIZE, | 56 | {PCI_0SCS_0_BANK_SIZE, PCI_0SCS_1_BANK_SIZE, |
57 | PCI_0SCS_2_BANK_SIZE, PCI_0SCS_3_BANK_SIZE}, | 57 | PCI_0SCS_2_BANK_SIZE, PCI_0SCS_3_BANK_SIZE}, |
58 | {PCI_1SCS_0_BANK_SIZE, PCI_1SCS_1_BANK_SIZE, | 58 | {PCI_1SCS_0_BANK_SIZE, PCI_1SCS_1_BANK_SIZE, |
59 | PCI_1SCS_2_BANK_SIZE, PCI_1SCS_3_BANK_SIZE} | 59 | PCI_1SCS_2_BANK_SIZE, PCI_1SCS_3_BANK_SIZE} |
60 | }; | 60 | }; |
61 | 61 | ||
62 | static const unsigned int pci_p2p_configuration[] = { | 62 | static const unsigned int pci_p2p_configuration[] = { |
63 | PCI_0P2P_CONFIGURATION, PCI_1P2P_CONFIGURATION | 63 | PCI_0P2P_CONFIGURATION, PCI_1P2P_CONFIGURATION |
64 | }; | 64 | }; |
65 | 65 | ||
66 | static unsigned int local_buses[] = { 0, 0 }; | 66 | static unsigned int local_buses[] = { 0, 0 }; |
67 | 67 | ||
68 | /******************************************************************** | 68 | /******************************************************************** |
69 | * pciWriteConfigReg - Write to a PCI configuration register | 69 | * pciWriteConfigReg - Write to a PCI configuration register |
70 | * - Make sure the GT is configured as a master before writing | 70 | * - Make sure the GT is configured as a master before writing |
71 | * to another device on the PCI. | 71 | * to another device on the PCI. |
72 | * - The function takes care of Big/Little endian conversion. | 72 | * - The function takes care of Big/Little endian conversion. |
73 | * | 73 | * |
74 | * | 74 | * |
75 | * Inputs: unsigned int regOffset: The register offset as it apears in the GT spec | 75 | * Inputs: unsigned int regOffset: The register offset as it apears in the GT spec |
76 | * (or any other PCI device spec) | 76 | * (or any other PCI device spec) |
77 | * pciDevNum: The device number needs to be addressed. | 77 | * pciDevNum: The device number needs to be addressed. |
78 | * | 78 | * |
79 | * Configuration Address 0xCF8: | 79 | * Configuration Address 0xCF8: |
80 | * | 80 | * |
81 | * 31 30 24 23 16 15 11 10 8 7 2 0 <=bit Number | 81 | * 31 30 24 23 16 15 11 10 8 7 2 0 <=bit Number |
82 | * |congif|Reserved| Bus |Device|Function|Register|00| | 82 | * |congif|Reserved| Bus |Device|Function|Register|00| |
83 | * |Enable| |Number|Number| Number | Number | | <=field Name | 83 | * |Enable| |Number|Number| Number | Number | | <=field Name |
84 | * | 84 | * |
85 | *********************************************************************/ | 85 | *********************************************************************/ |
86 | void pciWriteConfigReg (PCI_HOST host, unsigned int regOffset, | 86 | void pciWriteConfigReg (PCI_HOST host, unsigned int regOffset, |
87 | unsigned int pciDevNum, unsigned int data) | 87 | unsigned int pciDevNum, unsigned int data) |
88 | { | 88 | { |
89 | volatile unsigned int DataForAddrReg; | 89 | volatile unsigned int DataForAddrReg; |
90 | unsigned int functionNum; | 90 | unsigned int functionNum; |
91 | unsigned int busNum = PCI_BUS (pciDevNum); | 91 | unsigned int busNum = PCI_BUS (pciDevNum); |
92 | unsigned int addr; | 92 | unsigned int addr; |
93 | 93 | ||
94 | if (pciDevNum > 32) /* illegal device Number */ | 94 | if (pciDevNum > 32) /* illegal device Number */ |
95 | return; | 95 | return; |
96 | if (pciDevNum == SELF) { /* configure our configuration space. */ | 96 | if (pciDevNum == SELF) { /* configure our configuration space. */ |
97 | pciDevNum = | 97 | pciDevNum = |
98 | (GTREGREAD (pci_p2p_configuration_reg[host]) >> 24) & | 98 | (GTREGREAD (pci_p2p_configuration_reg[host]) >> 24) & |
99 | 0x1f; | 99 | 0x1f; |
100 | busNum = GTREGREAD (pci_p2p_configuration_reg[host]) & | 100 | busNum = GTREGREAD (pci_p2p_configuration_reg[host]) & |
101 | 0xff0000; | 101 | 0xff0000; |
102 | } | 102 | } |
103 | functionNum = regOffset & 0x00000700; | 103 | functionNum = regOffset & 0x00000700; |
104 | pciDevNum = pciDevNum << 11; | 104 | pciDevNum = pciDevNum << 11; |
105 | regOffset = regOffset & 0xfc; | 105 | regOffset = regOffset & 0xfc; |
106 | DataForAddrReg = | 106 | DataForAddrReg = |
107 | (regOffset | pciDevNum | functionNum | busNum) | BIT31; | 107 | (regOffset | pciDevNum | functionNum | busNum) | BIT31; |
108 | GT_REG_WRITE (pci_configuration_address[host], DataForAddrReg); | 108 | GT_REG_WRITE (pci_configuration_address[host], DataForAddrReg); |
109 | GT_REG_READ (pci_configuration_address[host], &addr); | 109 | GT_REG_READ (pci_configuration_address[host], &addr); |
110 | if (addr != DataForAddrReg) | 110 | if (addr != DataForAddrReg) |
111 | return; | 111 | return; |
112 | GT_REG_WRITE (pci_configuration_data[host], data); | 112 | GT_REG_WRITE (pci_configuration_data[host], data); |
113 | } | 113 | } |
114 | 114 | ||
115 | /******************************************************************** | 115 | /******************************************************************** |
116 | * pciReadConfigReg - Read from a PCI0 configuration register | 116 | * pciReadConfigReg - Read from a PCI0 configuration register |
117 | * - Make sure the GT is configured as a master before reading | 117 | * - Make sure the GT is configured as a master before reading |
118 | * from another device on the PCI. | 118 | * from another device on the PCI. |
119 | * - The function takes care of Big/Little endian conversion. | 119 | * - The function takes care of Big/Little endian conversion. |
120 | * INPUTS: regOffset: The register offset as it apears in the GT spec (or PCI | 120 | * INPUTS: regOffset: The register offset as it apears in the GT spec (or PCI |
121 | * spec) | 121 | * spec) |
122 | * pciDevNum: The device number needs to be addressed. | 122 | * pciDevNum: The device number needs to be addressed. |
123 | * RETURNS: data , if the data == 0xffffffff check the master abort bit in the | 123 | * RETURNS: data , if the data == 0xffffffff check the master abort bit in the |
124 | * cause register to make sure the data is valid | 124 | * cause register to make sure the data is valid |
125 | * | 125 | * |
126 | * Configuration Address 0xCF8: | 126 | * Configuration Address 0xCF8: |
127 | * | 127 | * |
128 | * 31 30 24 23 16 15 11 10 8 7 2 0 <=bit Number | 128 | * 31 30 24 23 16 15 11 10 8 7 2 0 <=bit Number |
129 | * |congif|Reserved| Bus |Device|Function|Register|00| | 129 | * |congif|Reserved| Bus |Device|Function|Register|00| |
130 | * |Enable| |Number|Number| Number | Number | | <=field Name | 130 | * |Enable| |Number|Number| Number | Number | | <=field Name |
131 | * | 131 | * |
132 | *********************************************************************/ | 132 | *********************************************************************/ |
133 | unsigned int pciReadConfigReg (PCI_HOST host, unsigned int regOffset, | 133 | unsigned int pciReadConfigReg (PCI_HOST host, unsigned int regOffset, |
134 | unsigned int pciDevNum) | 134 | unsigned int pciDevNum) |
135 | { | 135 | { |
136 | volatile unsigned int DataForAddrReg; | 136 | volatile unsigned int DataForAddrReg; |
137 | unsigned int data; | 137 | unsigned int data; |
138 | unsigned int functionNum; | 138 | unsigned int functionNum; |
139 | unsigned int busNum = PCI_BUS (pciDevNum); | 139 | unsigned int busNum = PCI_BUS (pciDevNum); |
140 | 140 | ||
141 | if (pciDevNum > 32) /* illegal device Number */ | 141 | if (pciDevNum > 32) /* illegal device Number */ |
142 | return 0xffffffff; | 142 | return 0xffffffff; |
143 | if (pciDevNum == SELF) { /* configure our configuration space. */ | 143 | if (pciDevNum == SELF) { /* configure our configuration space. */ |
144 | pciDevNum = | 144 | pciDevNum = |
145 | (GTREGREAD (pci_p2p_configuration_reg[host]) >> 24) & | 145 | (GTREGREAD (pci_p2p_configuration_reg[host]) >> 24) & |
146 | 0x1f; | 146 | 0x1f; |
147 | busNum = GTREGREAD (pci_p2p_configuration_reg[host]) & | 147 | busNum = GTREGREAD (pci_p2p_configuration_reg[host]) & |
148 | 0xff0000; | 148 | 0xff0000; |
149 | } | 149 | } |
150 | functionNum = regOffset & 0x00000700; | 150 | functionNum = regOffset & 0x00000700; |
151 | pciDevNum = pciDevNum << 11; | 151 | pciDevNum = pciDevNum << 11; |
152 | regOffset = regOffset & 0xfc; | 152 | regOffset = regOffset & 0xfc; |
153 | DataForAddrReg = | 153 | DataForAddrReg = |
154 | (regOffset | pciDevNum | functionNum | busNum) | BIT31; | 154 | (regOffset | pciDevNum | functionNum | busNum) | BIT31; |
155 | GT_REG_WRITE (pci_configuration_address[host], DataForAddrReg); | 155 | GT_REG_WRITE (pci_configuration_address[host], DataForAddrReg); |
156 | GT_REG_READ (pci_configuration_address[host], &data); | 156 | GT_REG_READ (pci_configuration_address[host], &data); |
157 | if (data != DataForAddrReg) | 157 | if (data != DataForAddrReg) |
158 | return 0xffffffff; | 158 | return 0xffffffff; |
159 | GT_REG_READ (pci_configuration_data[host], &data); | 159 | GT_REG_READ (pci_configuration_data[host], &data); |
160 | return data; | 160 | return data; |
161 | } | 161 | } |
162 | 162 | ||
163 | /******************************************************************** | 163 | /******************************************************************** |
164 | * pciOverBridgeWriteConfigReg - Write to a PCI configuration register where | 164 | * pciOverBridgeWriteConfigReg - Write to a PCI configuration register where |
165 | * the agent is placed on another Bus. For more | 165 | * the agent is placed on another Bus. For more |
166 | * information read P2P in the PCI spec. | 166 | * information read P2P in the PCI spec. |
167 | * | 167 | * |
168 | * Inputs: unsigned int regOffset - The register offset as it apears in the | 168 | * Inputs: unsigned int regOffset - The register offset as it apears in the |
169 | * GT spec (or any other PCI device spec). | 169 | * GT spec (or any other PCI device spec). |
170 | * unsigned int pciDevNum - The device number needs to be addressed. | 170 | * unsigned int pciDevNum - The device number needs to be addressed. |
171 | * unsigned int busNum - On which bus does the Target agent connect | 171 | * unsigned int busNum - On which bus does the Target agent connect |
172 | * to. | 172 | * to. |
173 | * unsigned int data - data to be written. | 173 | * unsigned int data - data to be written. |
174 | * | 174 | * |
175 | * Configuration Address 0xCF8: | 175 | * Configuration Address 0xCF8: |
176 | * | 176 | * |
177 | * 31 30 24 23 16 15 11 10 8 7 2 0 <=bit Number | 177 | * 31 30 24 23 16 15 11 10 8 7 2 0 <=bit Number |
178 | * |congif|Reserved| Bus |Device|Function|Register|01| | 178 | * |congif|Reserved| Bus |Device|Function|Register|01| |
179 | * |Enable| |Number|Number| Number | Number | | <=field Name | 179 | * |Enable| |Number|Number| Number | Number | | <=field Name |
180 | * | 180 | * |
181 | * The configuration Address is configure as type-I (bits[1:0] = '01') due to | 181 | * The configuration Address is configure as type-I (bits[1:0] = '01') due to |
182 | * PCI spec referring to P2P. | 182 | * PCI spec referring to P2P. |
183 | * | 183 | * |
184 | *********************************************************************/ | 184 | *********************************************************************/ |
185 | void pciOverBridgeWriteConfigReg (PCI_HOST host, | 185 | void pciOverBridgeWriteConfigReg (PCI_HOST host, |
186 | unsigned int regOffset, | 186 | unsigned int regOffset, |
187 | unsigned int pciDevNum, | 187 | unsigned int pciDevNum, |
188 | unsigned int busNum, unsigned int data) | 188 | unsigned int busNum, unsigned int data) |
189 | { | 189 | { |
190 | unsigned int DataForReg; | 190 | unsigned int DataForReg; |
191 | unsigned int functionNum; | 191 | unsigned int functionNum; |
192 | 192 | ||
193 | functionNum = regOffset & 0x00000700; | 193 | functionNum = regOffset & 0x00000700; |
194 | pciDevNum = pciDevNum << 11; | 194 | pciDevNum = pciDevNum << 11; |
195 | regOffset = regOffset & 0xff; | 195 | regOffset = regOffset & 0xff; |
196 | busNum = busNum << 16; | 196 | busNum = busNum << 16; |
197 | if (pciDevNum == SELF) { /* This board */ | 197 | if (pciDevNum == SELF) { /* This board */ |
198 | DataForReg = (regOffset | pciDevNum | functionNum) | BIT0; | 198 | DataForReg = (regOffset | pciDevNum | functionNum) | BIT0; |
199 | } else { | 199 | } else { |
200 | DataForReg = (regOffset | pciDevNum | functionNum | busNum) | | 200 | DataForReg = (regOffset | pciDevNum | functionNum | busNum) | |
201 | BIT31 | BIT0; | 201 | BIT31 | BIT0; |
202 | } | 202 | } |
203 | GT_REG_WRITE (pci_configuration_address[host], DataForReg); | 203 | GT_REG_WRITE (pci_configuration_address[host], DataForReg); |
204 | if (pciDevNum == SELF) { /* This board */ | 204 | if (pciDevNum == SELF) { /* This board */ |
205 | GT_REG_WRITE (pci_configuration_data[host], data); | 205 | GT_REG_WRITE (pci_configuration_data[host], data); |
206 | } else { /* configuration Transaction over the pci. */ | 206 | } else { /* configuration Transaction over the pci. */ |
207 | 207 | ||
208 | /* The PCI is working in LE Mode So it swap the Data. */ | 208 | /* The PCI is working in LE Mode So it swap the Data. */ |
209 | GT_REG_WRITE (pci_configuration_data[host], WORD_SWAP (data)); | 209 | GT_REG_WRITE (pci_configuration_data[host], WORD_SWAP (data)); |
210 | } | 210 | } |
211 | } | 211 | } |
212 | 212 | ||
213 | 213 | ||
214 | /******************************************************************** | 214 | /******************************************************************** |
215 | * pciOverBridgeReadConfigReg - Read from a PCIn configuration register where | 215 | * pciOverBridgeReadConfigReg - Read from a PCIn configuration register where |
216 | * the agent target locate on another PCI bus. | 216 | * the agent target locate on another PCI bus. |
217 | * - Make sure the GT is configured as a master | 217 | * - Make sure the GT is configured as a master |
218 | * before reading from another device on the PCI. | 218 | * before reading from another device on the PCI. |
219 | * - The function takes care of Big/Little endian | 219 | * - The function takes care of Big/Little endian |
220 | * conversion. | 220 | * conversion. |
221 | * INPUTS: regOffset: The register offset as it apears in the GT spec (or PCI | 221 | * INPUTS: regOffset: The register offset as it apears in the GT spec (or PCI |
222 | * spec). (configuration register offset.) | 222 | * spec). (configuration register offset.) |
223 | * pciDevNum: The device number needs to be addressed. | 223 | * pciDevNum: The device number needs to be addressed. |
224 | * busNum: the Bus number where the agent is place. | 224 | * busNum: the Bus number where the agent is place. |
225 | * RETURNS: data , if the data == 0xffffffff check the master abort bit in the | 225 | * RETURNS: data , if the data == 0xffffffff check the master abort bit in the |
226 | * cause register to make sure the data is valid | 226 | * cause register to make sure the data is valid |
227 | * | 227 | * |
228 | * Configuration Address 0xCF8: | 228 | * Configuration Address 0xCF8: |
229 | * | 229 | * |
230 | * 31 30 24 23 16 15 11 10 8 7 2 0 <=bit Number | 230 | * 31 30 24 23 16 15 11 10 8 7 2 0 <=bit Number |
231 | * |congif|Reserved| Bus |Device|Function|Register|01| | 231 | * |congif|Reserved| Bus |Device|Function|Register|01| |
232 | * |Enable| |Number|Number| Number | Number | | <=field Name | 232 | * |Enable| |Number|Number| Number | Number | | <=field Name |
233 | * | 233 | * |
234 | *********************************************************************/ | 234 | *********************************************************************/ |
235 | unsigned int pciOverBridgeReadConfigReg (PCI_HOST host, | 235 | unsigned int pciOverBridgeReadConfigReg (PCI_HOST host, |
236 | unsigned int regOffset, | 236 | unsigned int regOffset, |
237 | unsigned int pciDevNum, | 237 | unsigned int pciDevNum, |
238 | unsigned int busNum) | 238 | unsigned int busNum) |
239 | { | 239 | { |
240 | unsigned int DataForReg; | 240 | unsigned int DataForReg; |
241 | unsigned int data; | 241 | unsigned int data; |
242 | unsigned int functionNum; | 242 | unsigned int functionNum; |
243 | 243 | ||
244 | functionNum = regOffset & 0x00000700; | 244 | functionNum = regOffset & 0x00000700; |
245 | pciDevNum = pciDevNum << 11; | 245 | pciDevNum = pciDevNum << 11; |
246 | regOffset = regOffset & 0xff; | 246 | regOffset = regOffset & 0xff; |
247 | busNum = busNum << 16; | 247 | busNum = busNum << 16; |
248 | if (pciDevNum == SELF) { /* This board */ | 248 | if (pciDevNum == SELF) { /* This board */ |
249 | DataForReg = (regOffset | pciDevNum | functionNum) | BIT31; | 249 | DataForReg = (regOffset | pciDevNum | functionNum) | BIT31; |
250 | } else { /* agent on another bus */ | 250 | } else { /* agent on another bus */ |
251 | 251 | ||
252 | DataForReg = (regOffset | pciDevNum | functionNum | busNum) | | 252 | DataForReg = (regOffset | pciDevNum | functionNum | busNum) | |
253 | BIT0 | BIT31; | 253 | BIT0 | BIT31; |
254 | } | 254 | } |
255 | GT_REG_WRITE (pci_configuration_address[host], DataForReg); | 255 | GT_REG_WRITE (pci_configuration_address[host], DataForReg); |
256 | if (pciDevNum == SELF) { /* This board */ | 256 | if (pciDevNum == SELF) { /* This board */ |
257 | GT_REG_READ (pci_configuration_data[host], &data); | 257 | GT_REG_READ (pci_configuration_data[host], &data); |
258 | return data; | 258 | return data; |
259 | } else { /* The PCI is working in LE Mode So it swap the Data. */ | 259 | } else { /* The PCI is working in LE Mode So it swap the Data. */ |
260 | 260 | ||
261 | GT_REG_READ (pci_configuration_data[host], &data); | 261 | GT_REG_READ (pci_configuration_data[host], &data); |
262 | return WORD_SWAP (data); | 262 | return WORD_SWAP (data); |
263 | } | 263 | } |
264 | } | 264 | } |
265 | 265 | ||
266 | /******************************************************************** | 266 | /******************************************************************** |
267 | * pciGetRegOffset - Gets the register offset for this region config. | 267 | * pciGetRegOffset - Gets the register offset for this region config. |
268 | * | 268 | * |
269 | * INPUT: Bus, Region - The bus and region we ask for its base address. | 269 | * INPUT: Bus, Region - The bus and region we ask for its base address. |
270 | * OUTPUT: N/A | 270 | * OUTPUT: N/A |
271 | * RETURNS: PCI register base address | 271 | * RETURNS: PCI register base address |
272 | *********************************************************************/ | 272 | *********************************************************************/ |
273 | static unsigned int pciGetRegOffset (PCI_HOST host, PCI_REGION region) | 273 | static unsigned int pciGetRegOffset (PCI_HOST host, PCI_REGION region) |
274 | { | 274 | { |
275 | switch (host) { | 275 | switch (host) { |
276 | case PCI_HOST0: | 276 | case PCI_HOST0: |
277 | switch (region) { | 277 | switch (region) { |
278 | case PCI_IO: | 278 | case PCI_IO: |
279 | return PCI_0I_O_LOW_DECODE_ADDRESS; | 279 | return PCI_0I_O_LOW_DECODE_ADDRESS; |
280 | case PCI_REGION0: | 280 | case PCI_REGION0: |
281 | return PCI_0MEMORY0_LOW_DECODE_ADDRESS; | 281 | return PCI_0MEMORY0_LOW_DECODE_ADDRESS; |
282 | case PCI_REGION1: | 282 | case PCI_REGION1: |
283 | return PCI_0MEMORY1_LOW_DECODE_ADDRESS; | 283 | return PCI_0MEMORY1_LOW_DECODE_ADDRESS; |
284 | case PCI_REGION2: | 284 | case PCI_REGION2: |
285 | return PCI_0MEMORY2_LOW_DECODE_ADDRESS; | 285 | return PCI_0MEMORY2_LOW_DECODE_ADDRESS; |
286 | case PCI_REGION3: | 286 | case PCI_REGION3: |
287 | return PCI_0MEMORY3_LOW_DECODE_ADDRESS; | 287 | return PCI_0MEMORY3_LOW_DECODE_ADDRESS; |
288 | } | 288 | } |
289 | case PCI_HOST1: | 289 | case PCI_HOST1: |
290 | switch (region) { | 290 | switch (region) { |
291 | case PCI_IO: | 291 | case PCI_IO: |
292 | return PCI_1I_O_LOW_DECODE_ADDRESS; | 292 | return PCI_1I_O_LOW_DECODE_ADDRESS; |
293 | case PCI_REGION0: | 293 | case PCI_REGION0: |
294 | return PCI_1MEMORY0_LOW_DECODE_ADDRESS; | 294 | return PCI_1MEMORY0_LOW_DECODE_ADDRESS; |
295 | case PCI_REGION1: | 295 | case PCI_REGION1: |
296 | return PCI_1MEMORY1_LOW_DECODE_ADDRESS; | 296 | return PCI_1MEMORY1_LOW_DECODE_ADDRESS; |
297 | case PCI_REGION2: | 297 | case PCI_REGION2: |
298 | return PCI_1MEMORY2_LOW_DECODE_ADDRESS; | 298 | return PCI_1MEMORY2_LOW_DECODE_ADDRESS; |
299 | case PCI_REGION3: | 299 | case PCI_REGION3: |
300 | return PCI_1MEMORY3_LOW_DECODE_ADDRESS; | 300 | return PCI_1MEMORY3_LOW_DECODE_ADDRESS; |
301 | } | 301 | } |
302 | } | 302 | } |
303 | return PCI_0MEMORY0_LOW_DECODE_ADDRESS; | 303 | return PCI_0MEMORY0_LOW_DECODE_ADDRESS; |
304 | } | 304 | } |
305 | 305 | ||
306 | static unsigned int pciGetRemapOffset (PCI_HOST host, PCI_REGION region) | 306 | static unsigned int pciGetRemapOffset (PCI_HOST host, PCI_REGION region) |
307 | { | 307 | { |
308 | switch (host) { | 308 | switch (host) { |
309 | case PCI_HOST0: | 309 | case PCI_HOST0: |
310 | switch (region) { | 310 | switch (region) { |
311 | case PCI_IO: | 311 | case PCI_IO: |
312 | return PCI_0I_O_ADDRESS_REMAP; | 312 | return PCI_0I_O_ADDRESS_REMAP; |
313 | case PCI_REGION0: | 313 | case PCI_REGION0: |
314 | return PCI_0MEMORY0_ADDRESS_REMAP; | 314 | return PCI_0MEMORY0_ADDRESS_REMAP; |
315 | case PCI_REGION1: | 315 | case PCI_REGION1: |
316 | return PCI_0MEMORY1_ADDRESS_REMAP; | 316 | return PCI_0MEMORY1_ADDRESS_REMAP; |
317 | case PCI_REGION2: | 317 | case PCI_REGION2: |
318 | return PCI_0MEMORY2_ADDRESS_REMAP; | 318 | return PCI_0MEMORY2_ADDRESS_REMAP; |
319 | case PCI_REGION3: | 319 | case PCI_REGION3: |
320 | return PCI_0MEMORY3_ADDRESS_REMAP; | 320 | return PCI_0MEMORY3_ADDRESS_REMAP; |
321 | } | 321 | } |
322 | case PCI_HOST1: | 322 | case PCI_HOST1: |
323 | switch (region) { | 323 | switch (region) { |
324 | case PCI_IO: | 324 | case PCI_IO: |
325 | return PCI_1I_O_ADDRESS_REMAP; | 325 | return PCI_1I_O_ADDRESS_REMAP; |
326 | case PCI_REGION0: | 326 | case PCI_REGION0: |
327 | return PCI_1MEMORY0_ADDRESS_REMAP; | 327 | return PCI_1MEMORY0_ADDRESS_REMAP; |
328 | case PCI_REGION1: | 328 | case PCI_REGION1: |
329 | return PCI_1MEMORY1_ADDRESS_REMAP; | 329 | return PCI_1MEMORY1_ADDRESS_REMAP; |
330 | case PCI_REGION2: | 330 | case PCI_REGION2: |
331 | return PCI_1MEMORY2_ADDRESS_REMAP; | 331 | return PCI_1MEMORY2_ADDRESS_REMAP; |
332 | case PCI_REGION3: | 332 | case PCI_REGION3: |
333 | return PCI_1MEMORY3_ADDRESS_REMAP; | 333 | return PCI_1MEMORY3_ADDRESS_REMAP; |
334 | } | 334 | } |
335 | } | 335 | } |
336 | return PCI_0MEMORY0_ADDRESS_REMAP; | 336 | return PCI_0MEMORY0_ADDRESS_REMAP; |
337 | } | 337 | } |
338 | 338 | ||
339 | bool pciMapSpace (PCI_HOST host, PCI_REGION region, unsigned int remapBase, | 339 | bool pciMapSpace (PCI_HOST host, PCI_REGION region, unsigned int remapBase, |
340 | unsigned int bankBase, unsigned int bankLength) | 340 | unsigned int bankBase, unsigned int bankLength) |
341 | { | 341 | { |
342 | unsigned int low = 0xfff; | 342 | unsigned int low = 0xfff; |
343 | unsigned int high = 0x0; | 343 | unsigned int high = 0x0; |
344 | unsigned int regOffset = pciGetRegOffset (host, region); | 344 | unsigned int regOffset = pciGetRegOffset (host, region); |
345 | unsigned int remapOffset = pciGetRemapOffset (host, region); | 345 | unsigned int remapOffset = pciGetRemapOffset (host, region); |
346 | 346 | ||
347 | if (bankLength != 0) { | 347 | if (bankLength != 0) { |
348 | low = (bankBase >> 20) & 0xfff; | 348 | low = (bankBase >> 20) & 0xfff; |
349 | high = ((bankBase + bankLength) >> 20) - 1; | 349 | high = ((bankBase + bankLength) >> 20) - 1; |
350 | } | 350 | } |
351 | 351 | ||
352 | GT_REG_WRITE (regOffset, low | (1 << 24)); /* no swapping */ | 352 | GT_REG_WRITE (regOffset, low | (1 << 24)); /* no swapping */ |
353 | GT_REG_WRITE (regOffset + 8, high); | 353 | GT_REG_WRITE (regOffset + 8, high); |
354 | 354 | ||
355 | if (bankLength != 0) { /* must do AFTER writing maps */ | 355 | if (bankLength != 0) { /* must do AFTER writing maps */ |
356 | GT_REG_WRITE (remapOffset, remapBase >> 20); /* sorry, 32 bits only. | 356 | GT_REG_WRITE (remapOffset, remapBase >> 20); /* sorry, 32 bits only. |
357 | dont support upper 32 | 357 | dont support upper 32 |
358 | in this driver */ | 358 | in this driver */ |
359 | } | 359 | } |
360 | return true; | 360 | return true; |
361 | } | 361 | } |
362 | 362 | ||
363 | unsigned int pciGetSpaceBase (PCI_HOST host, PCI_REGION region) | 363 | unsigned int pciGetSpaceBase (PCI_HOST host, PCI_REGION region) |
364 | { | 364 | { |
365 | unsigned int low; | 365 | unsigned int low; |
366 | unsigned int regOffset = pciGetRegOffset (host, region); | 366 | unsigned int regOffset = pciGetRegOffset (host, region); |
367 | 367 | ||
368 | GT_REG_READ (regOffset, &low); | 368 | GT_REG_READ (regOffset, &low); |
369 | return (low & 0xfff) << 20; | 369 | return (low & 0xfff) << 20; |
370 | } | 370 | } |
371 | 371 | ||
372 | unsigned int pciGetSpaceSize (PCI_HOST host, PCI_REGION region) | 372 | unsigned int pciGetSpaceSize (PCI_HOST host, PCI_REGION region) |
373 | { | 373 | { |
374 | unsigned int low, high; | 374 | unsigned int low, high; |
375 | unsigned int regOffset = pciGetRegOffset (host, region); | 375 | unsigned int regOffset = pciGetRegOffset (host, region); |
376 | 376 | ||
377 | GT_REG_READ (regOffset, &low); | 377 | GT_REG_READ (regOffset, &low); |
378 | GT_REG_READ (regOffset + 8, &high); | 378 | GT_REG_READ (regOffset + 8, &high); |
379 | high &= 0xfff; | 379 | high &= 0xfff; |
380 | low &= 0xfff; | 380 | low &= 0xfff; |
381 | if (high <= low) | 381 | if (high <= low) |
382 | return 0; | 382 | return 0; |
383 | return (high + 1 - low) << 20; | 383 | return (high + 1 - low) << 20; |
384 | } | 384 | } |
385 | 385 | ||
386 | /******************************************************************** | 386 | /******************************************************************** |
387 | * pciMapMemoryBank - Maps PCI_host memory bank "bank" for the slave. | 387 | * pciMapMemoryBank - Maps PCI_host memory bank "bank" for the slave. |
388 | * | 388 | * |
389 | * Inputs: base and size of PCI SCS | 389 | * Inputs: base and size of PCI SCS |
390 | *********************************************************************/ | 390 | *********************************************************************/ |
391 | void pciMapMemoryBank (PCI_HOST host, MEMORY_BANK bank, | 391 | void pciMapMemoryBank (PCI_HOST host, MEMORY_BANK bank, |
392 | unsigned int pciDramBase, unsigned int pciDramSize) | 392 | unsigned int pciDramBase, unsigned int pciDramSize) |
393 | { | 393 | { |
394 | pciDramBase = pciDramBase & 0xfffff000; | 394 | pciDramBase = pciDramBase & 0xfffff000; |
395 | pciDramBase = pciDramBase | (pciReadConfigReg (host, | 395 | pciDramBase = pciDramBase | (pciReadConfigReg (host, |
396 | PCI_SCS_0_BASE_ADDRESS | 396 | PCI_SCS_0_BASE_ADDRESS |
397 | + 4 * bank, | 397 | + 4 * bank, |
398 | SELF) & 0x00000fff); | 398 | SELF) & 0x00000fff); |
399 | pciWriteConfigReg (host, PCI_SCS_0_BASE_ADDRESS + 4 * bank, SELF, | 399 | pciWriteConfigReg (host, PCI_SCS_0_BASE_ADDRESS + 4 * bank, SELF, |
400 | pciDramBase); | 400 | pciDramBase); |
401 | if (pciDramSize == 0) | 401 | if (pciDramSize == 0) |
402 | pciDramSize++; | 402 | pciDramSize++; |
403 | GT_REG_WRITE (pci_scs_bank_size[host][bank], pciDramSize - 1); | 403 | GT_REG_WRITE (pci_scs_bank_size[host][bank], pciDramSize - 1); |
404 | } | 404 | } |
405 | 405 | ||
406 | 406 | ||
407 | /******************************************************************** | 407 | /******************************************************************** |
408 | * pciSetRegionFeatures - This function modifys one of the 8 regions with | 408 | * pciSetRegionFeatures - This function modifys one of the 8 regions with |
409 | * feature bits given as an input. | 409 | * feature bits given as an input. |
410 | * - Be advised to check the spec before modifying them. | 410 | * - Be advised to check the spec before modifying them. |
411 | * Inputs: PCI_PROTECT_REGION region - one of the eight regions. | 411 | * Inputs: PCI_PROTECT_REGION region - one of the eight regions. |
412 | * unsigned int features - See file: pci.h there are defintion for those | 412 | * unsigned int features - See file: pci.h there are defintion for those |
413 | * region features. | 413 | * region features. |
414 | * unsigned int baseAddress - The region base Address. | 414 | * unsigned int baseAddress - The region base Address. |
415 | * unsigned int topAddress - The region top Address. | 415 | * unsigned int topAddress - The region top Address. |
416 | * Returns: false if one of the parameters is erroneous true otherwise. | 416 | * Returns: false if one of the parameters is erroneous true otherwise. |
417 | *********************************************************************/ | 417 | *********************************************************************/ |
418 | bool pciSetRegionFeatures (PCI_HOST host, PCI_ACCESS_REGIONS region, | 418 | bool pciSetRegionFeatures (PCI_HOST host, PCI_ACCESS_REGIONS region, |
419 | unsigned int features, unsigned int baseAddress, | 419 | unsigned int features, unsigned int baseAddress, |
420 | unsigned int regionLength) | 420 | unsigned int regionLength) |
421 | { | 421 | { |
422 | unsigned int accessLow; | 422 | unsigned int accessLow; |
423 | unsigned int accessHigh; | 423 | unsigned int accessHigh; |
424 | unsigned int accessTop = baseAddress + regionLength; | 424 | unsigned int accessTop = baseAddress + regionLength; |
425 | 425 | ||
426 | if (regionLength == 0) { /* close the region. */ | 426 | if (regionLength == 0) { /* close the region. */ |
427 | pciDisableAccessRegion (host, region); | 427 | pciDisableAccessRegion (host, region); |
428 | return true; | 428 | return true; |
429 | } | 429 | } |
430 | /* base Address is store is bits [11:0] */ | 430 | /* base Address is store is bits [11:0] */ |
431 | accessLow = (baseAddress & 0xfff00000) >> 20; | 431 | accessLow = (baseAddress & 0xfff00000) >> 20; |
432 | /* All the features are update according to the defines in pci.h (to be on | 432 | /* All the features are update according to the defines in pci.h (to be on |
433 | the safe side we disable bits: [11:0] */ | 433 | the safe side we disable bits: [11:0] */ |
434 | accessLow = accessLow | (features & 0xfffff000); | 434 | accessLow = accessLow | (features & 0xfffff000); |
435 | /* write to the Low Access Region register */ | 435 | /* write to the Low Access Region register */ |
436 | GT_REG_WRITE (pci_access_control_base_0_low[host] + 0x10 * region, | 436 | GT_REG_WRITE (pci_access_control_base_0_low[host] + 0x10 * region, |
437 | accessLow); | 437 | accessLow); |
438 | 438 | ||
439 | accessHigh = (accessTop & 0xfff00000) >> 20; | 439 | accessHigh = (accessTop & 0xfff00000) >> 20; |
440 | 440 | ||
441 | /* write to the High Access Region register */ | 441 | /* write to the High Access Region register */ |
442 | GT_REG_WRITE (pci_access_control_top_0[host] + 0x10 * region, | 442 | GT_REG_WRITE (pci_access_control_top_0[host] + 0x10 * region, |
443 | accessHigh - 1); | 443 | accessHigh - 1); |
444 | return true; | 444 | return true; |
445 | } | 445 | } |
446 | 446 | ||
447 | /******************************************************************** | 447 | /******************************************************************** |
448 | * pciDisableAccessRegion - Disable The given Region by writing MAX size | 448 | * pciDisableAccessRegion - Disable The given Region by writing MAX size |
449 | * to its low Address and MIN size to its high Address. | 449 | * to its low Address and MIN size to its high Address. |
450 | * | 450 | * |
451 | * Inputs: PCI_ACCESS_REGIONS region - The region we to be Disabled. | 451 | * Inputs: PCI_ACCESS_REGIONS region - The region we to be Disabled. |
452 | * Returns: N/A. | 452 | * Returns: N/A. |
453 | *********************************************************************/ | 453 | *********************************************************************/ |
454 | void pciDisableAccessRegion (PCI_HOST host, PCI_ACCESS_REGIONS region) | 454 | void pciDisableAccessRegion (PCI_HOST host, PCI_ACCESS_REGIONS region) |
455 | { | 455 | { |
456 | /* writing back the registers default values. */ | 456 | /* writing back the registers default values. */ |
457 | GT_REG_WRITE (pci_access_control_base_0_low[host] + 0x10 * region, | 457 | GT_REG_WRITE (pci_access_control_base_0_low[host] + 0x10 * region, |
458 | 0x01001fff); | 458 | 0x01001fff); |
459 | GT_REG_WRITE (pci_access_control_top_0[host] + 0x10 * region, 0); | 459 | GT_REG_WRITE (pci_access_control_top_0[host] + 0x10 * region, 0); |
460 | } | 460 | } |
461 | 461 | ||
462 | /******************************************************************** | 462 | /******************************************************************** |
463 | * pciArbiterEnable - Enables PCI-0`s Arbitration mechanism. | 463 | * pciArbiterEnable - Enables PCI-0`s Arbitration mechanism. |
464 | * | 464 | * |
465 | * Inputs: N/A | 465 | * Inputs: N/A |
466 | * Returns: true. | 466 | * Returns: true. |
467 | *********************************************************************/ | 467 | *********************************************************************/ |
468 | bool pciArbiterEnable (PCI_HOST host) | 468 | bool pciArbiterEnable (PCI_HOST host) |
469 | { | 469 | { |
470 | unsigned int regData; | 470 | unsigned int regData; |
471 | 471 | ||
472 | GT_REG_READ (pci_arbiter_control[host], ®Data); | 472 | GT_REG_READ (pci_arbiter_control[host], ®Data); |
473 | GT_REG_WRITE (pci_arbiter_control[host], regData | BIT31); | 473 | GT_REG_WRITE (pci_arbiter_control[host], regData | BIT31); |
474 | return true; | 474 | return true; |
475 | } | 475 | } |
476 | 476 | ||
477 | /******************************************************************** | 477 | /******************************************************************** |
478 | * pciArbiterDisable - Disable PCI-0`s Arbitration mechanism. | 478 | * pciArbiterDisable - Disable PCI-0`s Arbitration mechanism. |
479 | * | 479 | * |
480 | * Inputs: N/A | 480 | * Inputs: N/A |
481 | * Returns: true | 481 | * Returns: true |
482 | *********************************************************************/ | 482 | *********************************************************************/ |
483 | bool pciArbiterDisable (PCI_HOST host) | 483 | bool pciArbiterDisable (PCI_HOST host) |
484 | { | 484 | { |
485 | unsigned int regData; | 485 | unsigned int regData; |
486 | 486 | ||
487 | GT_REG_READ (pci_arbiter_control[host], ®Data); | 487 | GT_REG_READ (pci_arbiter_control[host], ®Data); |
488 | GT_REG_WRITE (pci_arbiter_control[host], regData & 0x7fffffff); | 488 | GT_REG_WRITE (pci_arbiter_control[host], regData & 0x7fffffff); |
489 | return true; | 489 | return true; |
490 | } | 490 | } |
491 | 491 | ||
492 | /******************************************************************** | 492 | /******************************************************************** |
493 | * pciParkingDisable - Park on last option disable, with this function you can | 493 | * pciParkingDisable - Park on last option disable, with this function you can |
494 | * disable the park on last mechanism for each agent. | 494 | * disable the park on last mechanism for each agent. |
495 | * disabling this option for all agents results parking | 495 | * disabling this option for all agents results parking |
496 | * on the internal master. | 496 | * on the internal master. |
497 | * | 497 | * |
498 | * Inputs: PCI_AGENT_PARK internalAgent - parking Disable for internal agent. | 498 | * Inputs: PCI_AGENT_PARK internalAgent - parking Disable for internal agent. |
499 | * PCI_AGENT_PARK externalAgent0 - parking Disable for external#0 agent. | 499 | * PCI_AGENT_PARK externalAgent0 - parking Disable for external#0 agent. |
500 | * PCI_AGENT_PARK externalAgent1 - parking Disable for external#1 agent. | 500 | * PCI_AGENT_PARK externalAgent1 - parking Disable for external#1 agent. |
501 | * PCI_AGENT_PARK externalAgent2 - parking Disable for external#2 agent. | 501 | * PCI_AGENT_PARK externalAgent2 - parking Disable for external#2 agent. |
502 | * PCI_AGENT_PARK externalAgent3 - parking Disable for external#3 agent. | 502 | * PCI_AGENT_PARK externalAgent3 - parking Disable for external#3 agent. |
503 | * PCI_AGENT_PARK externalAgent4 - parking Disable for external#4 agent. | 503 | * PCI_AGENT_PARK externalAgent4 - parking Disable for external#4 agent. |
504 | * PCI_AGENT_PARK externalAgent5 - parking Disable for external#5 agent. | 504 | * PCI_AGENT_PARK externalAgent5 - parking Disable for external#5 agent. |
505 | * Returns: true | 505 | * Returns: true |
506 | *********************************************************************/ | 506 | *********************************************************************/ |
507 | bool pciParkingDisable (PCI_HOST host, PCI_AGENT_PARK internalAgent, | 507 | bool pciParkingDisable (PCI_HOST host, PCI_AGENT_PARK internalAgent, |
508 | PCI_AGENT_PARK externalAgent0, | 508 | PCI_AGENT_PARK externalAgent0, |
509 | PCI_AGENT_PARK externalAgent1, | 509 | PCI_AGENT_PARK externalAgent1, |
510 | PCI_AGENT_PARK externalAgent2, | 510 | PCI_AGENT_PARK externalAgent2, |
511 | PCI_AGENT_PARK externalAgent3, | 511 | PCI_AGENT_PARK externalAgent3, |
512 | PCI_AGENT_PARK externalAgent4, | 512 | PCI_AGENT_PARK externalAgent4, |
513 | PCI_AGENT_PARK externalAgent5) | 513 | PCI_AGENT_PARK externalAgent5) |
514 | { | 514 | { |
515 | unsigned int regData; | 515 | unsigned int regData; |
516 | unsigned int writeData; | 516 | unsigned int writeData; |
517 | 517 | ||
518 | GT_REG_READ (pci_arbiter_control[host], ®Data); | 518 | GT_REG_READ (pci_arbiter_control[host], ®Data); |
519 | writeData = (internalAgent << 14) + (externalAgent0 << 15) + | 519 | writeData = (internalAgent << 14) + (externalAgent0 << 15) + |
520 | (externalAgent1 << 16) + (externalAgent2 << 17) + | 520 | (externalAgent1 << 16) + (externalAgent2 << 17) + |
521 | (externalAgent3 << 18) + (externalAgent4 << 19) + | 521 | (externalAgent3 << 18) + (externalAgent4 << 19) + |
522 | (externalAgent5 << 20); | 522 | (externalAgent5 << 20); |
523 | regData = (regData & ~(0x7f << 14)) | writeData; | 523 | regData = (regData & ~(0x7f << 14)) | writeData; |
524 | GT_REG_WRITE (pci_arbiter_control[host], regData); | 524 | GT_REG_WRITE (pci_arbiter_control[host], regData); |
525 | return true; | 525 | return true; |
526 | } | 526 | } |
527 | 527 | ||
528 | /******************************************************************** | 528 | /******************************************************************** |
529 | * pciSetRegionSnoopMode - This function modifys one of the 4 regions which | 529 | * pciSetRegionSnoopMode - This function modifys one of the 4 regions which |
530 | * supports Cache Coherency in the PCI_n interface. | 530 | * supports Cache Coherency in the PCI_n interface. |
531 | * Inputs: region - One of the four regions. | 531 | * Inputs: region - One of the four regions. |
532 | * snoopType - There is four optional Types: | 532 | * snoopType - There is four optional Types: |
533 | * 1. No Snoop. | 533 | * 1. No Snoop. |
534 | * 2. Snoop to WT region. | 534 | * 2. Snoop to WT region. |
535 | * 3. Snoop to WB region. | 535 | * 3. Snoop to WB region. |
536 | * 4. Snoop & Invalidate to WB region. | 536 | * 4. Snoop & Invalidate to WB region. |
537 | * baseAddress - Base Address of this region. | 537 | * baseAddress - Base Address of this region. |
538 | * regionLength - Region length. | 538 | * regionLength - Region length. |
539 | * Returns: false if one of the parameters is wrong otherwise return true. | 539 | * Returns: false if one of the parameters is wrong otherwise return true. |
540 | *********************************************************************/ | 540 | *********************************************************************/ |
541 | bool pciSetRegionSnoopMode (PCI_HOST host, PCI_SNOOP_REGION region, | 541 | bool pciSetRegionSnoopMode (PCI_HOST host, PCI_SNOOP_REGION region, |
542 | PCI_SNOOP_TYPE snoopType, | 542 | PCI_SNOOP_TYPE snoopType, |
543 | unsigned int baseAddress, | 543 | unsigned int baseAddress, |
544 | unsigned int regionLength) | 544 | unsigned int regionLength) |
545 | { | 545 | { |
546 | unsigned int snoopXbaseAddress; | 546 | unsigned int snoopXbaseAddress; |
547 | unsigned int snoopXtopAddress; | 547 | unsigned int snoopXtopAddress; |
548 | unsigned int data; | 548 | unsigned int data; |
549 | unsigned int snoopHigh = baseAddress + regionLength; | 549 | unsigned int snoopHigh = baseAddress + regionLength; |
550 | 550 | ||
551 | if ((region > PCI_SNOOP_REGION3) || (snoopType > PCI_SNOOP_WB)) | 551 | if ((region > PCI_SNOOP_REGION3) || (snoopType > PCI_SNOOP_WB)) |
552 | return false; | 552 | return false; |
553 | snoopXbaseAddress = | 553 | snoopXbaseAddress = |
554 | pci_snoop_control_base_0_low[host] + 0x10 * region; | 554 | pci_snoop_control_base_0_low[host] + 0x10 * region; |
555 | snoopXtopAddress = pci_snoop_control_top_0[host] + 0x10 * region; | 555 | snoopXtopAddress = pci_snoop_control_top_0[host] + 0x10 * region; |
556 | if (regionLength == 0) { /* closing the region */ | 556 | if (regionLength == 0) { /* closing the region */ |
557 | GT_REG_WRITE (snoopXbaseAddress, 0x0000ffff); | 557 | GT_REG_WRITE (snoopXbaseAddress, 0x0000ffff); |
558 | GT_REG_WRITE (snoopXtopAddress, 0); | 558 | GT_REG_WRITE (snoopXtopAddress, 0); |
559 | return true; | 559 | return true; |
560 | } | 560 | } |
561 | baseAddress = baseAddress & 0xfff00000; /* Granularity of 1MByte */ | 561 | baseAddress = baseAddress & 0xfff00000; /* Granularity of 1MByte */ |
562 | data = (baseAddress >> 20) | snoopType << 12; | 562 | data = (baseAddress >> 20) | snoopType << 12; |
563 | GT_REG_WRITE (snoopXbaseAddress, data); | 563 | GT_REG_WRITE (snoopXbaseAddress, data); |
564 | snoopHigh = (snoopHigh & 0xfff00000) >> 20; | 564 | snoopHigh = (snoopHigh & 0xfff00000) >> 20; |
565 | GT_REG_WRITE (snoopXtopAddress, snoopHigh - 1); | 565 | GT_REG_WRITE (snoopXtopAddress, snoopHigh - 1); |
566 | return true; | 566 | return true; |
567 | } | 567 | } |
568 | 568 | ||
569 | /* | 569 | /* |
570 | * | 570 | * |
571 | */ | 571 | */ |
572 | 572 | ||
573 | static int gt_read_config_dword (struct pci_controller *hose, | 573 | static int gt_read_config_dword (struct pci_controller *hose, |
574 | pci_dev_t dev, int offset, u32 * value) | 574 | pci_dev_t dev, int offset, u32 * value) |
575 | { | 575 | { |
576 | int bus = PCI_BUS (dev); | 576 | int bus = PCI_BUS (dev); |
577 | 577 | ||
578 | if ((bus == local_buses[0]) || (bus == local_buses[1])) { | 578 | if ((bus == local_buses[0]) || (bus == local_buses[1])) { |
579 | *value = pciReadConfigReg ((PCI_HOST) hose->cfg_addr, offset, | 579 | *value = pciReadConfigReg ((PCI_HOST) hose->cfg_addr, offset, |
580 | PCI_DEV (dev)); | 580 | PCI_DEV (dev)); |
581 | } else { | 581 | } else { |
582 | *value = pciOverBridgeReadConfigReg ((PCI_HOST) hose-> | 582 | *value = pciOverBridgeReadConfigReg ((PCI_HOST) hose-> |
583 | cfg_addr, offset, | 583 | cfg_addr, offset, |
584 | PCI_DEV (dev), bus); | 584 | PCI_DEV (dev), bus); |
585 | } | 585 | } |
586 | return 0; | 586 | return 0; |
587 | } | 587 | } |
588 | 588 | ||
589 | static int gt_write_config_dword (struct pci_controller *hose, | 589 | static int gt_write_config_dword (struct pci_controller *hose, |
590 | pci_dev_t dev, int offset, u32 value) | 590 | pci_dev_t dev, int offset, u32 value) |
591 | { | 591 | { |
592 | int bus = PCI_BUS (dev); | 592 | int bus = PCI_BUS (dev); |
593 | 593 | ||
594 | if ((bus == local_buses[0]) || (bus == local_buses[1])) { | 594 | if ((bus == local_buses[0]) || (bus == local_buses[1])) { |
595 | pciWriteConfigReg ((PCI_HOST) hose->cfg_addr, offset, | 595 | pciWriteConfigReg ((PCI_HOST) hose->cfg_addr, offset, |
596 | PCI_DEV (dev), value); | 596 | PCI_DEV (dev), value); |
597 | } else { | 597 | } else { |
598 | pciOverBridgeWriteConfigReg ((PCI_HOST) hose->cfg_addr, | 598 | pciOverBridgeWriteConfigReg ((PCI_HOST) hose->cfg_addr, |
599 | offset, PCI_DEV (dev), value, | 599 | offset, PCI_DEV (dev), value, |
600 | bus); | 600 | bus); |
601 | } | 601 | } |
602 | return 0; | 602 | return 0; |
603 | } | 603 | } |
604 | 604 | ||
605 | /* | 605 | /* |
606 | * | 606 | * |
607 | */ | 607 | */ |
608 | 608 | ||
609 | static void gt_setup_ide (struct pci_controller *hose, | 609 | static void gt_setup_ide (struct pci_controller *hose, |
610 | pci_dev_t dev, struct pci_config_table *entry) | 610 | pci_dev_t dev, struct pci_config_table *entry) |
611 | { | 611 | { |
612 | static const int ide_bar[] = { 8, 4, 8, 4, 0, 0 }; | 612 | static const int ide_bar[] = { 8, 4, 8, 4, 0, 0 }; |
613 | u32 bar_response, bar_value; | 613 | u32 bar_response, bar_value; |
614 | int bar; | 614 | int bar; |
615 | 615 | ||
616 | for (bar = 0; bar < 6; bar++) { | 616 | for (bar = 0; bar < 6; bar++) { |
617 | pci_write_config_dword (dev, PCI_BASE_ADDRESS_0 + bar * 4, | 617 | pci_write_config_dword (dev, PCI_BASE_ADDRESS_0 + bar * 4, |
618 | 0x0); | 618 | 0x0); |
619 | pci_read_config_dword (dev, PCI_BASE_ADDRESS_0 + bar * 4, | 619 | pci_read_config_dword (dev, PCI_BASE_ADDRESS_0 + bar * 4, |
620 | &bar_response); | 620 | &bar_response); |
621 | 621 | ||
622 | pciauto_region_allocate (bar_response & | 622 | pciauto_region_allocate (bar_response & |
623 | PCI_BASE_ADDRESS_SPACE_IO ? hose-> | 623 | PCI_BASE_ADDRESS_SPACE_IO ? hose-> |
624 | pci_io : hose->pci_mem, ide_bar[bar], | 624 | pci_io : hose->pci_mem, ide_bar[bar], |
625 | &bar_value); | 625 | &bar_value); |
626 | 626 | ||
627 | pci_write_config_dword (dev, PCI_BASE_ADDRESS_0 + bar * 4, | 627 | pci_write_config_dword (dev, PCI_BASE_ADDRESS_0 + bar * 4, |
628 | bar_value); | 628 | bar_value); |
629 | } | 629 | } |
630 | } | 630 | } |
631 | 631 | ||
632 | static void gt_fixup_irq (struct pci_controller *hose, pci_dev_t dev) | 632 | static void gt_fixup_irq (struct pci_controller *hose, pci_dev_t dev) |
633 | { | 633 | { |
634 | unsigned char pin, irq; | 634 | unsigned char pin, irq; |
635 | 635 | ||
636 | pci_read_config_byte (dev, PCI_INTERRUPT_PIN, &pin); | 636 | pci_read_config_byte (dev, PCI_INTERRUPT_PIN, &pin); |
637 | 637 | ||
638 | if (pin == 1) { /* only allow INT A */ | 638 | if (pin == 1) { /* only allow INT A */ |
639 | irq = pci_irq_swizzle[(PCI_HOST) hose-> | 639 | irq = pci_irq_swizzle[(PCI_HOST) hose-> |
640 | cfg_addr][PCI_DEV (dev)]; | 640 | cfg_addr][PCI_DEV (dev)]; |
641 | if (irq) | 641 | if (irq) |
642 | pci_write_config_byte (dev, PCI_INTERRUPT_LINE, irq); | 642 | pci_write_config_byte (dev, PCI_INTERRUPT_LINE, irq); |
643 | } | 643 | } |
644 | } | 644 | } |
645 | 645 | ||
646 | struct pci_config_table gt_config_table[] = { | 646 | struct pci_config_table gt_config_table[] = { |
647 | {PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_IDE, | 647 | {PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_IDE, |
648 | PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, gt_setup_ide}, | 648 | PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, gt_setup_ide}, |
649 | 649 | ||
650 | {} | 650 | {} |
651 | }; | 651 | }; |
652 | 652 | ||
653 | struct pci_controller pci0_hose = { | 653 | struct pci_controller pci0_hose = { |
654 | fixup_irq:gt_fixup_irq, | 654 | fixup_irq:gt_fixup_irq, |
655 | config_table:gt_config_table, | 655 | config_table:gt_config_table, |
656 | }; | 656 | }; |
657 | 657 | ||
658 | struct pci_controller pci1_hose = { | 658 | struct pci_controller pci1_hose = { |
659 | fixup_irq:gt_fixup_irq, | 659 | fixup_irq:gt_fixup_irq, |
660 | config_table:gt_config_table, | 660 | config_table:gt_config_table, |
661 | }; | 661 | }; |
662 | 662 | ||
663 | void pci_init_board (void) | 663 | void pci_init_board (void) |
664 | { | 664 | { |
665 | unsigned int command; | 665 | unsigned int command; |
666 | 666 | ||
667 | pci0_hose.first_busno = 0; | 667 | pci0_hose.first_busno = 0; |
668 | pci0_hose.last_busno = 0xff; | 668 | pci0_hose.last_busno = 0xff; |
669 | local_buses[0] = pci0_hose.first_busno; | 669 | local_buses[0] = pci0_hose.first_busno; |
670 | /* PCI memory space */ | 670 | /* PCI memory space */ |
671 | pci_set_region (pci0_hose.regions + 0, | 671 | pci_set_region (pci0_hose.regions + 0, |
672 | CFG_PCI0_0_MEM_SPACE, | 672 | CFG_PCI0_0_MEM_SPACE, |
673 | CFG_PCI0_0_MEM_SPACE, | 673 | CFG_PCI0_0_MEM_SPACE, |
674 | CFG_PCI0_MEM_SIZE, PCI_REGION_MEM); | 674 | CFG_PCI0_MEM_SIZE, PCI_REGION_MEM); |
675 | 675 | ||
676 | /* PCI I/O space */ | 676 | /* PCI I/O space */ |
677 | pci_set_region (pci0_hose.regions + 1, | 677 | pci_set_region (pci0_hose.regions + 1, |
678 | CFG_PCI0_IO_SPACE_PCI, | 678 | CFG_PCI0_IO_SPACE_PCI, |
679 | CFG_PCI0_IO_SPACE, CFG_PCI0_IO_SIZE, PCI_REGION_IO); | 679 | CFG_PCI0_IO_SPACE, CFG_PCI0_IO_SIZE, PCI_REGION_IO); |
680 | 680 | ||
681 | pci_set_ops (&pci0_hose, | 681 | pci_set_ops (&pci0_hose, |
682 | pci_hose_read_config_byte_via_dword, | 682 | pci_hose_read_config_byte_via_dword, |
683 | pci_hose_read_config_word_via_dword, | 683 | pci_hose_read_config_word_via_dword, |
684 | gt_read_config_dword, | 684 | gt_read_config_dword, |
685 | pci_hose_write_config_byte_via_dword, | 685 | pci_hose_write_config_byte_via_dword, |
686 | pci_hose_write_config_word_via_dword, | 686 | pci_hose_write_config_word_via_dword, |
687 | gt_write_config_dword); | 687 | gt_write_config_dword); |
688 | 688 | ||
689 | pci0_hose.region_count = 2; | 689 | pci0_hose.region_count = 2; |
690 | 690 | ||
691 | pci0_hose.cfg_addr = (unsigned int *) PCI_HOST0; | 691 | pci0_hose.cfg_addr = (unsigned int *) PCI_HOST0; |
692 | 692 | ||
693 | pci_register_hose (&pci0_hose); | 693 | pci_register_hose (&pci0_hose); |
694 | 694 | ||
695 | pciArbiterEnable (PCI_HOST0); | 695 | pciArbiterEnable (PCI_HOST0); |
696 | pciParkingDisable (PCI_HOST0, 1, 1, 1, 1, 1, 1, 1); | 696 | pciParkingDisable (PCI_HOST0, 1, 1, 1, 1, 1, 1, 1); |
697 | 697 | ||
698 | command = pciReadConfigReg (PCI_HOST0, PCI_COMMAND, SELF); | 698 | command = pciReadConfigReg (PCI_HOST0, PCI_COMMAND, SELF); |
699 | command |= PCI_COMMAND_MASTER; | 699 | command |= PCI_COMMAND_MASTER; |
700 | pciWriteConfigReg (PCI_HOST0, PCI_COMMAND, SELF, command); | 700 | pciWriteConfigReg (PCI_HOST0, PCI_COMMAND, SELF, command); |
701 | 701 | ||
702 | pci0_hose.last_busno = pci_hose_scan (&pci0_hose); | 702 | pci0_hose.last_busno = pci_hose_scan (&pci0_hose); |
703 | 703 | ||
704 | command = pciReadConfigReg (PCI_HOST0, PCI_COMMAND, SELF); | 704 | command = pciReadConfigReg (PCI_HOST0, PCI_COMMAND, SELF); |
705 | command |= PCI_COMMAND_MEMORY; | 705 | command |= PCI_COMMAND_MEMORY; |
706 | pciWriteConfigReg (PCI_HOST0, PCI_COMMAND, SELF, command); | 706 | pciWriteConfigReg (PCI_HOST0, PCI_COMMAND, SELF, command); |
707 | 707 | ||
708 | pci1_hose.first_busno = pci0_hose.last_busno + 1; | 708 | pci1_hose.first_busno = pci0_hose.last_busno + 1; |
709 | pci1_hose.last_busno = 0xff; | 709 | pci1_hose.last_busno = 0xff; |
710 | pci1_hose.current_busno = pci0_hose.current_busno; | 710 | pci1_hose.current_busno = pci0_hose.current_busno; |
711 | local_buses[1] = pci1_hose.first_busno; | 711 | local_buses[1] = pci1_hose.first_busno; |
712 | 712 | ||
713 | /* PCI memory space */ | 713 | /* PCI memory space */ |
714 | pci_set_region (pci1_hose.regions + 0, | 714 | pci_set_region (pci1_hose.regions + 0, |
715 | CFG_PCI1_0_MEM_SPACE, | 715 | CFG_PCI1_0_MEM_SPACE, |
716 | CFG_PCI1_0_MEM_SPACE, | 716 | CFG_PCI1_0_MEM_SPACE, |
717 | CFG_PCI1_MEM_SIZE, PCI_REGION_MEM); | 717 | CFG_PCI1_MEM_SIZE, PCI_REGION_MEM); |
718 | 718 | ||
719 | /* PCI I/O space */ | 719 | /* PCI I/O space */ |
720 | pci_set_region (pci1_hose.regions + 1, | 720 | pci_set_region (pci1_hose.regions + 1, |
721 | CFG_PCI1_IO_SPACE_PCI, | 721 | CFG_PCI1_IO_SPACE_PCI, |
722 | CFG_PCI1_IO_SPACE, CFG_PCI1_IO_SIZE, PCI_REGION_IO); | 722 | CFG_PCI1_IO_SPACE, CFG_PCI1_IO_SIZE, PCI_REGION_IO); |
723 | 723 | ||
724 | pci_set_ops (&pci1_hose, | 724 | pci_set_ops (&pci1_hose, |
725 | pci_hose_read_config_byte_via_dword, | 725 | pci_hose_read_config_byte_via_dword, |
726 | pci_hose_read_config_word_via_dword, | 726 | pci_hose_read_config_word_via_dword, |
727 | gt_read_config_dword, | 727 | gt_read_config_dword, |
728 | pci_hose_write_config_byte_via_dword, | 728 | pci_hose_write_config_byte_via_dword, |
729 | pci_hose_write_config_word_via_dword, | 729 | pci_hose_write_config_word_via_dword, |
730 | gt_write_config_dword); | 730 | gt_write_config_dword); |
731 | 731 | ||
732 | pci1_hose.region_count = 2; | 732 | pci1_hose.region_count = 2; |
733 | 733 | ||
734 | pci1_hose.cfg_addr = (unsigned int *) PCI_HOST1; | 734 | pci1_hose.cfg_addr = (unsigned int *) PCI_HOST1; |
735 | 735 | ||
736 | pci_register_hose (&pci1_hose); | 736 | pci_register_hose (&pci1_hose); |
737 | 737 | ||
738 | pciArbiterEnable (PCI_HOST1); | 738 | pciArbiterEnable (PCI_HOST1); |
739 | pciParkingDisable (PCI_HOST1, 1, 1, 1, 1, 1, 1, 1); | 739 | pciParkingDisable (PCI_HOST1, 1, 1, 1, 1, 1, 1, 1); |
740 | 740 | ||
741 | command = pciReadConfigReg (PCI_HOST1, PCI_COMMAND, SELF); | 741 | command = pciReadConfigReg (PCI_HOST1, PCI_COMMAND, SELF); |
742 | command |= PCI_COMMAND_MASTER; | 742 | command |= PCI_COMMAND_MASTER; |
743 | pciWriteConfigReg (PCI_HOST1, PCI_COMMAND, SELF, command); | 743 | pciWriteConfigReg (PCI_HOST1, PCI_COMMAND, SELF, command); |
744 | 744 | ||
745 | pci1_hose.last_busno = pci_hose_scan (&pci1_hose); | 745 | pci1_hose.last_busno = pci_hose_scan (&pci1_hose); |
746 | 746 | ||
747 | command = pciReadConfigReg (PCI_HOST1, PCI_COMMAND, SELF); | 747 | command = pciReadConfigReg (PCI_HOST1, PCI_COMMAND, SELF); |
748 | command |= PCI_COMMAND_MEMORY; | 748 | command |= PCI_COMMAND_MEMORY; |
749 | pciWriteConfigReg (PCI_HOST1, PCI_COMMAND, SELF, command); | 749 | pciWriteConfigReg (PCI_HOST1, PCI_COMMAND, SELF, command); |
750 | } | 750 | } |
751 | 751 |
board/omap1610inn/flash.c
1 | /* | 1 | /* |
2 | * (C) Copyright 2001 | 2 | * (C) Copyright 2001 |
3 | * Kyle Harris, Nexus Technologies, Inc. kharris@nexus-tech.net | 3 | * Kyle Harris, Nexus Technologies, Inc. kharris@nexus-tech.net |
4 | * | 4 | * |
5 | * (C) Copyright 2001 | 5 | * (C) Copyright 2001-2004 |
6 | * Wolfgang Denk, DENX Software Engineering, wd@denx.de. | 6 | * Wolfgang Denk, DENX Software Engineering, wd@denx.de. |
7 | * | 7 | * |
8 | * (C) Copyright 2003 | 8 | * (C) Copyright 2003 |
9 | * Texas Instruments, <www.ti.com> | 9 | * Texas Instruments, <www.ti.com> |
10 | * Kshitij Gupta <Kshitij@ti.com> | 10 | * Kshitij Gupta <Kshitij@ti.com> |
11 | * | 11 | * |
12 | * See file CREDITS for list of people who contributed to this | 12 | * See file CREDITS for list of people who contributed to this |
13 | * project. | 13 | * project. |
14 | * | 14 | * |
15 | * This program is free software; you can redistribute it and/or | 15 | * This program is free software; you can redistribute it and/or |
16 | * modify it under the terms of the GNU General Public License as | 16 | * modify it under the terms of the GNU General Public License as |
17 | * published by the Free Software Foundation; either version 2 of | 17 | * published by the Free Software Foundation; either version 2 of |
18 | * the License, or (at your option) any later version. | 18 | * the License, or (at your option) any later version. |
19 | * | 19 | * |
20 | * This program is distributed in the hope that it will be useful, | 20 | * This program is distributed in the hope that it will be useful, |
21 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 21 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
22 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 22 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
23 | * GNU General Public License for more details. | 23 | * GNU General Public License for more details. |
24 | * | 24 | * |
25 | * You should have received a copy of the GNU General Public License | 25 | * You should have received a copy of the GNU General Public License |
26 | * along with this program; if not, write to the Free Software | 26 | * along with this program; if not, write to the Free Software |
27 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, | 27 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, |
28 | * MA 02111-1307 USA | 28 | * MA 02111-1307 USA |
29 | */ | 29 | */ |
30 | 30 | ||
31 | #include <common.h> | 31 | #include <common.h> |
32 | #include <linux/byteorder/swab.h> | 32 | #include <linux/byteorder/swab.h> |
33 | 33 | ||
34 | #define PHYS_FLASH_SECT_SIZE 0x00020000 /* 256 KB sectors (x2) */ | 34 | #define PHYS_FLASH_SECT_SIZE 0x00020000 /* 256 KB sectors (x2) */ |
35 | flash_info_t flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips */ | 35 | flash_info_t flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips */ |
36 | 36 | ||
37 | /* Board support for 1 or 2 flash devices */ | 37 | /* Board support for 1 or 2 flash devices */ |
38 | #undef FLASH_PORT_WIDTH32 | 38 | #undef FLASH_PORT_WIDTH32 |
39 | #define FLASH_PORT_WIDTH16 | 39 | #define FLASH_PORT_WIDTH16 |
40 | 40 | ||
41 | #ifdef FLASH_PORT_WIDTH16 | 41 | #ifdef FLASH_PORT_WIDTH16 |
42 | #define FLASH_PORT_WIDTH ushort | 42 | #define FLASH_PORT_WIDTH ushort |
43 | #define FLASH_PORT_WIDTHV vu_short | 43 | #define FLASH_PORT_WIDTHV vu_short |
44 | #define SWAP(x) __swab16(x) | 44 | #define SWAP(x) __swab16(x) |
45 | #else | 45 | #else |
46 | #define FLASH_PORT_WIDTH ulong | 46 | #define FLASH_PORT_WIDTH ulong |
47 | #define FLASH_PORT_WIDTHV vu_long | 47 | #define FLASH_PORT_WIDTHV vu_long |
48 | #define SWAP(x) __swab32(x) | 48 | #define SWAP(x) __swab32(x) |
49 | #endif | 49 | #endif |
50 | 50 | ||
51 | #define FPW FLASH_PORT_WIDTH | 51 | #define FPW FLASH_PORT_WIDTH |
52 | #define FPWV FLASH_PORT_WIDTHV | 52 | #define FPWV FLASH_PORT_WIDTHV |
53 | 53 | ||
54 | #define mb() __asm__ __volatile__ ("" : : : "memory") | 54 | #define mb() __asm__ __volatile__ ("" : : : "memory") |
55 | 55 | ||
56 | 56 | ||
57 | /* Flash Organization Structure */ | 57 | /* Flash Organization Structure */ |
58 | typedef struct OrgDef { | 58 | typedef struct OrgDef { |
59 | unsigned int sector_number; | 59 | unsigned int sector_number; |
60 | unsigned int sector_size; | 60 | unsigned int sector_size; |
61 | } OrgDef; | 61 | } OrgDef; |
62 | 62 | ||
63 | 63 | ||
64 | /* Flash Organizations */ | 64 | /* Flash Organizations */ |
65 | OrgDef OrgIntel_28F256L18T[] = { | 65 | OrgDef OrgIntel_28F256L18T[] = { |
66 | {4, 32 * 1024}, /* 4 * 32kBytes sectors */ | 66 | {4, 32 * 1024}, /* 4 * 32kBytes sectors */ |
67 | {255, 128 * 1024}, /* 255 * 128kBytes sectors */ | 67 | {255, 128 * 1024}, /* 255 * 128kBytes sectors */ |
68 | }; | 68 | }; |
69 | 69 | ||
70 | 70 | ||
71 | /*----------------------------------------------------------------------- | 71 | /*----------------------------------------------------------------------- |
72 | * Functions | 72 | * Functions |
73 | */ | 73 | */ |
74 | unsigned long flash_init (void); | 74 | unsigned long flash_init (void); |
75 | static ulong flash_get_size (FPW * addr, flash_info_t * info); | 75 | static ulong flash_get_size (FPW * addr, flash_info_t * info); |
76 | static int write_data (flash_info_t * info, ulong dest, FPW data); | 76 | static int write_data (flash_info_t * info, ulong dest, FPW data); |
77 | static void flash_get_offsets (ulong base, flash_info_t * info); | 77 | static void flash_get_offsets (ulong base, flash_info_t * info); |
78 | void inline spin_wheel (void); | 78 | void inline spin_wheel (void); |
79 | void flash_print_info (flash_info_t * info); | 79 | void flash_print_info (flash_info_t * info); |
80 | void flash_unprotect_sectors (FPWV * addr); | 80 | void flash_unprotect_sectors (FPWV * addr); |
81 | int flash_erase (flash_info_t * info, int s_first, int s_last); | 81 | int flash_erase (flash_info_t * info, int s_first, int s_last); |
82 | int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt); | 82 | int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt); |
83 | void flash_unlock(flash_info_t * info); | ||
83 | 84 | ||
84 | /*----------------------------------------------------------------------- | 85 | /*----------------------------------------------------------------------- |
85 | */ | 86 | */ |
86 | 87 | ||
87 | unsigned long flash_init (void) | 88 | unsigned long flash_init (void) |
88 | { | 89 | { |
89 | int i; | 90 | int i; |
90 | ulong size = 0; | 91 | ulong size = 0; |
91 | for (i = 0; i < CFG_MAX_FLASH_BANKS; i++) { | 92 | for (i = 0; i < CFG_MAX_FLASH_BANKS; i++) { |
92 | switch (i) { | 93 | switch (i) { |
93 | case 0: | 94 | case 0: |
94 | flash_get_size ((FPW *) PHYS_FLASH_1, &flash_info[i]); | 95 | flash_get_size ((FPW *) PHYS_FLASH_1, &flash_info[i]); |
95 | flash_get_offsets (PHYS_FLASH_1, &flash_info[i]); | 96 | flash_get_offsets (PHYS_FLASH_1, &flash_info[i]); |
96 | /* to reset the lock bit */ | 97 | /* to reset the lock bit */ |
97 | flash_unlock(&flash_info[i]); | 98 | flash_unlock(&flash_info[i]); |
98 | break; | 99 | break; |
99 | default: | 100 | default: |
100 | panic ("configured too many flash banks!\n"); | 101 | panic ("configured too many flash banks!\n"); |
101 | break; | 102 | break; |
102 | } | 103 | } |
103 | size += flash_info[i].size; | 104 | size += flash_info[i].size; |
104 | } | 105 | } |
105 | 106 | ||
106 | /* Protect monitor and environment sectors | 107 | /* Protect monitor and environment sectors |
107 | */ | 108 | */ |
108 | flash_protect (FLAG_PROTECT_SET, | 109 | flash_protect (FLAG_PROTECT_SET, |
109 | CFG_FLASH_BASE, | 110 | CFG_FLASH_BASE, |
110 | CFG_FLASH_BASE + monitor_flash_len - 1, &flash_info[0]); | 111 | CFG_FLASH_BASE + monitor_flash_len - 1, &flash_info[0]); |
111 | 112 | ||
112 | flash_protect (FLAG_PROTECT_SET, | 113 | flash_protect (FLAG_PROTECT_SET, |
113 | CFG_ENV_ADDR, | 114 | CFG_ENV_ADDR, |
114 | CFG_ENV_ADDR + CFG_ENV_SIZE - 1, &flash_info[0]); | 115 | CFG_ENV_ADDR + CFG_ENV_SIZE - 1, &flash_info[0]); |
115 | 116 | ||
116 | return size; | 117 | return size; |
117 | } | 118 | } |
118 | 119 | ||
119 | /*----------------------------------------------------------------------- | 120 | /*----------------------------------------------------------------------- |
120 | */ | 121 | */ |
121 | flash_unlock(flash_info_t * info) | 122 | void flash_unlock(flash_info_t * info) |
122 | { | 123 | { |
123 | int j; | 124 | int j; |
124 | for (j=2;j<CFG_MAX_FLASH_SECT;j++){ | 125 | for (j=2;j<CFG_MAX_FLASH_SECT;j++){ |
125 | FPWV *addr = (FPWV *) (info->start[j]); | 126 | FPWV *addr = (FPWV *) (info->start[j]); |
126 | flash_unprotect_sectors (addr); | 127 | flash_unprotect_sectors (addr); |
127 | *addr = (FPW) 0x00500050;/* clear status register */ | 128 | *addr = (FPW) 0x00500050;/* clear status register */ |
128 | *addr = (FPW) 0x00FF00FF;/* resest to read mode */ | 129 | *addr = (FPW) 0x00FF00FF;/* resest to read mode */ |
129 | } | 130 | } |
130 | } | 131 | } |
131 | 132 | ||
132 | /*----------------------------------------------------------------------- | 133 | /*----------------------------------------------------------------------- |
133 | */ | 134 | */ |
134 | static void flash_get_offsets (ulong base, flash_info_t * info) | 135 | static void flash_get_offsets (ulong base, flash_info_t * info) |
135 | { | 136 | { |
136 | int i; | 137 | int i; |
137 | OrgDef *pOrgDef; | 138 | OrgDef *pOrgDef; |
138 | 139 | ||
139 | pOrgDef = OrgIntel_28F256L18T; | 140 | pOrgDef = OrgIntel_28F256L18T; |
140 | if (info->flash_id == FLASH_UNKNOWN) { | 141 | if (info->flash_id == FLASH_UNKNOWN) { |
141 | return; | 142 | return; |
142 | } | 143 | } |
143 | 144 | ||
144 | if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL) { | 145 | if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL) { |
145 | for (i = 0; i < info->sector_count; i++) { | 146 | for (i = 0; i < info->sector_count; i++) { |
146 | if (i > 255) { | 147 | if (i > 255) { |
147 | info->start[i] = base + (i * 0x8000); | 148 | info->start[i] = base + (i * 0x8000); |
148 | info->protect[i] = 0; | 149 | info->protect[i] = 0; |
149 | } else { | 150 | } else { |
150 | info->start[i] = base + | 151 | info->start[i] = base + |
151 | (i * PHYS_FLASH_SECT_SIZE); | 152 | (i * PHYS_FLASH_SECT_SIZE); |
152 | info->protect[i] = 0; | 153 | info->protect[i] = 0; |
153 | } | 154 | } |
154 | } | 155 | } |
155 | } | 156 | } |
156 | } | 157 | } |
157 | 158 | ||
158 | /*----------------------------------------------------------------------- | 159 | /*----------------------------------------------------------------------- |
159 | */ | 160 | */ |
160 | void flash_print_info (flash_info_t * info) | 161 | void flash_print_info (flash_info_t * info) |
161 | { | 162 | { |
162 | int i; | 163 | int i; |
163 | 164 | ||
164 | if (info->flash_id == FLASH_UNKNOWN) { | 165 | if (info->flash_id == FLASH_UNKNOWN) { |
165 | printf ("missing or unknown FLASH type\n"); | 166 | printf ("missing or unknown FLASH type\n"); |
166 | return; | 167 | return; |
167 | } | 168 | } |
168 | 169 | ||
169 | switch (info->flash_id & FLASH_VENDMASK) { | 170 | switch (info->flash_id & FLASH_VENDMASK) { |
170 | case FLASH_MAN_INTEL: | 171 | case FLASH_MAN_INTEL: |
171 | printf ("INTEL "); | 172 | printf ("INTEL "); |
172 | break; | 173 | break; |
173 | default: | 174 | default: |
174 | printf ("Unknown Vendor "); | 175 | printf ("Unknown Vendor "); |
175 | break; | 176 | break; |
176 | } | 177 | } |
177 | 178 | ||
178 | switch (info->flash_id & FLASH_TYPEMASK) { | 179 | switch (info->flash_id & FLASH_TYPEMASK) { |
179 | case FLASH_28F256L18T: | 180 | case FLASH_28F256L18T: |
180 | printf ("FLASH 28F256L18T\n"); | 181 | printf ("FLASH 28F256L18T\n"); |
181 | break; | 182 | break; |
182 | default: | 183 | default: |
183 | printf ("Unknown Chip Type\n"); | 184 | printf ("Unknown Chip Type\n"); |
184 | break; | 185 | break; |
185 | } | 186 | } |
186 | 187 | ||
187 | printf (" Size: %ld MB in %d Sectors\n", | 188 | printf (" Size: %ld MB in %d Sectors\n", |
188 | info->size >> 20, info->sector_count); | 189 | info->size >> 20, info->sector_count); |
189 | 190 | ||
190 | printf (" Sector Start Addresses:"); | 191 | printf (" Sector Start Addresses:"); |
191 | for (i = 0; i < info->sector_count; ++i) { | 192 | for (i = 0; i < info->sector_count; ++i) { |
192 | if ((i % 5) == 0) | 193 | if ((i % 5) == 0) |
193 | printf ("\n "); | 194 | printf ("\n "); |
194 | printf (" %08lX%s", | 195 | printf (" %08lX%s", |
195 | info->start[i], info->protect[i] ? " (RO)" : " "); | 196 | info->start[i], info->protect[i] ? " (RO)" : " "); |
196 | } | 197 | } |
197 | printf ("\n"); | 198 | printf ("\n"); |
198 | return; | 199 | return; |
199 | } | 200 | } |
200 | 201 | ||
201 | /* | 202 | /* |
202 | * The following code cannot be run from FLASH! | 203 | * The following code cannot be run from FLASH! |
203 | */ | 204 | */ |
204 | static ulong flash_get_size (FPW * addr, flash_info_t * info) | 205 | static ulong flash_get_size (FPW * addr, flash_info_t * info) |
205 | { | 206 | { |
206 | volatile FPW value; | 207 | volatile FPW value; |
207 | 208 | ||
208 | /* Write auto select command: read Manufacturer ID */ | 209 | /* Write auto select command: read Manufacturer ID */ |
209 | addr[0x5555] = (FPW) 0x00AA00AA; | 210 | addr[0x5555] = (FPW) 0x00AA00AA; |
210 | addr[0x2AAA] = (FPW) 0x00550055; | 211 | addr[0x2AAA] = (FPW) 0x00550055; |
211 | addr[0x5555] = (FPW) 0x00900090; | 212 | addr[0x5555] = (FPW) 0x00900090; |
212 | 213 | ||
213 | mb (); | 214 | mb (); |
214 | value = addr[0]; | 215 | value = addr[0]; |
215 | 216 | ||
216 | switch (value) { | 217 | switch (value) { |
217 | 218 | ||
218 | case (FPW) INTEL_MANUFACT: | 219 | case (FPW) INTEL_MANUFACT: |
219 | info->flash_id = FLASH_MAN_INTEL; | 220 | info->flash_id = FLASH_MAN_INTEL; |
220 | break; | 221 | break; |
221 | 222 | ||
222 | default: | 223 | default: |
223 | info->flash_id = FLASH_UNKNOWN; | 224 | info->flash_id = FLASH_UNKNOWN; |
224 | info->sector_count = 0; | 225 | info->sector_count = 0; |
225 | info->size = 0; | 226 | info->size = 0; |
226 | addr[0] = (FPW) 0x00FF00FF; /* restore read mode */ | 227 | addr[0] = (FPW) 0x00FF00FF; /* restore read mode */ |
227 | return (0); /* no or unknown flash */ | 228 | return (0); /* no or unknown flash */ |
228 | } | 229 | } |
229 | 230 | ||
230 | mb (); | 231 | mb (); |
231 | value = addr[1]; /* device ID */ | 232 | value = addr[1]; /* device ID */ |
232 | switch (value) { | 233 | switch (value) { |
233 | 234 | ||
234 | case (FPW) (INTEL_ID_28F256L18T): | 235 | case (FPW) (INTEL_ID_28F256L18T): |
235 | info->flash_id += FLASH_28F256L18T; | 236 | info->flash_id += FLASH_28F256L18T; |
236 | info->sector_count = 259; | 237 | info->sector_count = 259; |
237 | info->size = 0x02000000; | 238 | info->size = 0x02000000; |
238 | break; /* => 32 MB */ | 239 | break; /* => 32 MB */ |
239 | 240 | ||
240 | default: | 241 | default: |
241 | info->flash_id = FLASH_UNKNOWN; | 242 | info->flash_id = FLASH_UNKNOWN; |
242 | break; | 243 | break; |
243 | } | 244 | } |
244 | 245 | ||
245 | if (info->sector_count > CFG_MAX_FLASH_SECT) { | 246 | if (info->sector_count > CFG_MAX_FLASH_SECT) { |
246 | printf ("** ERROR: sector count %d > max (%d) **\n", | 247 | printf ("** ERROR: sector count %d > max (%d) **\n", |
247 | info->sector_count, CFG_MAX_FLASH_SECT); | 248 | info->sector_count, CFG_MAX_FLASH_SECT); |
248 | info->sector_count = CFG_MAX_FLASH_SECT; | 249 | info->sector_count = CFG_MAX_FLASH_SECT; |
249 | } | 250 | } |
250 | 251 | ||
251 | addr[0] = (FPW) 0x00FF00FF; /* restore read mode */ | 252 | addr[0] = (FPW) 0x00FF00FF; /* restore read mode */ |
252 | 253 | ||
253 | return (info->size); | 254 | return (info->size); |
254 | } | 255 | } |
255 | 256 | ||
256 | 257 | ||
257 | /* unprotects a sector for write and erase | 258 | /* unprotects a sector for write and erase |
258 | * on some intel parts, this unprotects the entire chip, but it | 259 | * on some intel parts, this unprotects the entire chip, but it |
259 | * wont hurt to call this additional times per sector... | 260 | * wont hurt to call this additional times per sector... |
260 | */ | 261 | */ |
261 | void flash_unprotect_sectors (FPWV * addr) | 262 | void flash_unprotect_sectors (FPWV * addr) |
262 | { | 263 | { |
263 | #define PD_FINTEL_WSMS_READY_MASK 0x0080 | 264 | #define PD_FINTEL_WSMS_READY_MASK 0x0080 |
264 | 265 | ||
265 | *addr = (FPW) 0x00500050; /* clear status register */ | 266 | *addr = (FPW) 0x00500050; /* clear status register */ |
266 | 267 | ||
267 | /* this sends the clear lock bit command */ | 268 | /* this sends the clear lock bit command */ |
268 | *addr = (FPW) 0x00600060; | 269 | *addr = (FPW) 0x00600060; |
269 | *addr = (FPW) 0x00D000D0; | 270 | *addr = (FPW) 0x00D000D0; |
270 | } | 271 | } |
271 | 272 | ||
272 | 273 | ||
273 | /*----------------------------------------------------------------------- | 274 | /*----------------------------------------------------------------------- |
274 | */ | 275 | */ |
275 | 276 | ||
276 | int flash_erase (flash_info_t * info, int s_first, int s_last) | 277 | int flash_erase (flash_info_t * info, int s_first, int s_last) |
277 | { | 278 | { |
278 | int flag, prot, sect; | 279 | int flag, prot, sect; |
279 | ulong type, start, last; | 280 | ulong type, start, last; |
280 | int rcode = 0; | 281 | int rcode = 0; |
281 | 282 | ||
282 | if ((s_first < 0) || (s_first > s_last)) { | 283 | if ((s_first < 0) || (s_first > s_last)) { |
283 | if (info->flash_id == FLASH_UNKNOWN) { | 284 | if (info->flash_id == FLASH_UNKNOWN) { |
284 | printf ("- missing\n"); | 285 | printf ("- missing\n"); |
285 | } else { | 286 | } else { |
286 | printf ("- no sectors to erase\n"); | 287 | printf ("- no sectors to erase\n"); |
287 | } | 288 | } |
288 | return 1; | 289 | return 1; |
289 | } | 290 | } |
290 | 291 | ||
291 | type = (info->flash_id & FLASH_VENDMASK); | 292 | type = (info->flash_id & FLASH_VENDMASK); |
292 | if ((type != FLASH_MAN_INTEL)) { | 293 | if ((type != FLASH_MAN_INTEL)) { |
293 | printf ("Can't erase unknown flash type %08lx - aborted\n", | 294 | printf ("Can't erase unknown flash type %08lx - aborted\n", |
294 | info->flash_id); | 295 | info->flash_id); |
295 | return 1; | 296 | return 1; |
296 | } | 297 | } |
297 | 298 | ||
298 | prot = 0; | 299 | prot = 0; |
299 | for (sect = s_first; sect <= s_last; ++sect) { | 300 | for (sect = s_first; sect <= s_last; ++sect) { |
300 | if (info->protect[sect]) { | 301 | if (info->protect[sect]) { |
301 | prot++; | 302 | prot++; |
302 | } | 303 | } |
303 | } | 304 | } |
304 | 305 | ||
305 | if (prot) { | 306 | if (prot) { |
306 | printf ("- Warning: %d protected sectors will not be erased!\n", | 307 | printf ("- Warning: %d protected sectors will not be erased!\n", |
307 | prot); | 308 | prot); |
308 | } else { | 309 | } else { |
309 | printf ("\n"); | 310 | printf ("\n"); |
310 | } | 311 | } |
311 | 312 | ||
312 | 313 | ||
313 | start = get_timer (0); | 314 | start = get_timer (0); |
314 | last = start; | 315 | last = start; |
315 | 316 | ||
316 | /* Disable interrupts which might cause a timeout here */ | 317 | /* Disable interrupts which might cause a timeout here */ |
317 | flag = disable_interrupts (); | 318 | flag = disable_interrupts (); |
318 | 319 | ||
319 | /* Start erase on unprotected sectors */ | 320 | /* Start erase on unprotected sectors */ |
320 | for (sect = s_first; sect <= s_last; sect++) { | 321 | for (sect = s_first; sect <= s_last; sect++) { |
321 | if (info->protect[sect] == 0) { /* not protected */ | 322 | if (info->protect[sect] == 0) { /* not protected */ |
322 | FPWV *addr = (FPWV *) (info->start[sect]); | 323 | FPWV *addr = (FPWV *) (info->start[sect]); |
323 | FPW status; | 324 | FPW status; |
324 | 325 | ||
325 | printf ("Erasing sector %2d ... ", sect); | 326 | printf ("Erasing sector %2d ... ", sect); |
326 | 327 | ||
327 | flash_unprotect_sectors (addr); | 328 | flash_unprotect_sectors (addr); |
328 | 329 | ||
329 | /* arm simple, non interrupt dependent timer */ | 330 | /* arm simple, non interrupt dependent timer */ |
330 | reset_timer_masked (); | 331 | reset_timer_masked (); |
331 | 332 | ||
332 | *addr = (FPW) 0x00500050;/* clear status register */ | 333 | *addr = (FPW) 0x00500050;/* clear status register */ |
333 | *addr = (FPW) 0x00200020;/* erase setup */ | 334 | *addr = (FPW) 0x00200020;/* erase setup */ |
334 | *addr = (FPW) 0x00D000D0;/* erase confirm */ | 335 | *addr = (FPW) 0x00D000D0;/* erase confirm */ |
335 | 336 | ||
336 | while (((status = | 337 | while (((status = |
337 | *addr) & (FPW) 0x00800080) != | 338 | *addr) & (FPW) 0x00800080) != |
338 | (FPW) 0x00800080) { | 339 | (FPW) 0x00800080) { |
339 | if (get_timer_masked () > | 340 | if (get_timer_masked () > |
340 | CFG_FLASH_ERASE_TOUT) { | 341 | CFG_FLASH_ERASE_TOUT) { |
341 | printf ("Timeout\n"); | 342 | printf ("Timeout\n"); |
342 | /* suspend erase */ | 343 | /* suspend erase */ |
343 | *addr = (FPW) 0x00B000B0; | 344 | *addr = (FPW) 0x00B000B0; |
344 | /* reset to read mode */ | 345 | /* reset to read mode */ |
345 | *addr = (FPW) 0x00FF00FF; | 346 | *addr = (FPW) 0x00FF00FF; |
346 | rcode = 1; | 347 | rcode = 1; |
347 | break; | 348 | break; |
348 | } | 349 | } |
349 | } | 350 | } |
350 | 351 | ||
351 | /* clear status register cmd. */ | 352 | /* clear status register cmd. */ |
352 | *addr = (FPW) 0x00500050; | 353 | *addr = (FPW) 0x00500050; |
353 | *addr = (FPW) 0x00FF00FF;/* resest to read mode */ | 354 | *addr = (FPW) 0x00FF00FF;/* resest to read mode */ |
354 | printf (" done\n"); | 355 | printf (" done\n"); |
355 | } | 356 | } |
356 | } | 357 | } |
357 | return rcode; | 358 | return rcode; |
358 | } | 359 | } |
359 | 360 | ||
360 | /*----------------------------------------------------------------------- | 361 | /*----------------------------------------------------------------------- |
361 | * Copy memory to flash, returns: | 362 | * Copy memory to flash, returns: |
362 | * 0 - OK | 363 | * 0 - OK |
363 | * 1 - write timeout | 364 | * 1 - write timeout |
364 | * 2 - Flash not erased | 365 | * 2 - Flash not erased |
365 | * 4 - Flash not identified | 366 | * 4 - Flash not identified |
366 | */ | 367 | */ |
367 | 368 | ||
368 | int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt) | 369 | int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt) |
369 | { | 370 | { |
370 | ulong cp, wp; | 371 | ulong cp, wp; |
371 | FPW data; | 372 | FPW data; |
372 | int count, i, l, rc, port_width; | 373 | int count, i, l, rc, port_width; |
373 | 374 | ||
374 | if (info->flash_id == FLASH_UNKNOWN) { | 375 | if (info->flash_id == FLASH_UNKNOWN) { |
375 | return 4; | 376 | return 4; |
376 | } | 377 | } |
377 | /* get lower word aligned address */ | 378 | /* get lower word aligned address */ |
378 | #ifdef FLASH_PORT_WIDTH16 | 379 | #ifdef FLASH_PORT_WIDTH16 |
379 | wp = (addr & ~1); | 380 | wp = (addr & ~1); |
380 | port_width = 2; | 381 | port_width = 2; |
381 | #else | 382 | #else |
382 | wp = (addr & ~3); | 383 | wp = (addr & ~3); |
383 | port_width = 4; | 384 | port_width = 4; |
384 | #endif | 385 | #endif |
385 | 386 | ||
386 | /* | 387 | /* |
387 | * handle unaligned start bytes | 388 | * handle unaligned start bytes |
388 | */ | 389 | */ |
389 | if ((l = addr - wp) != 0) { | 390 | if ((l = addr - wp) != 0) { |
390 | data = 0; | 391 | data = 0; |
391 | for (i = 0, cp = wp; i < l; ++i, ++cp) { | 392 | for (i = 0, cp = wp; i < l; ++i, ++cp) { |
392 | data = (data << 8) | (*(uchar *) cp); | 393 | data = (data << 8) | (*(uchar *) cp); |
393 | } | 394 | } |
394 | for (; i < port_width && cnt > 0; ++i) { | 395 | for (; i < port_width && cnt > 0; ++i) { |
395 | data = (data << 8) | *src++; | 396 | data = (data << 8) | *src++; |
396 | --cnt; | 397 | --cnt; |
397 | ++cp; | 398 | ++cp; |
398 | } | 399 | } |
399 | for (; cnt == 0 && i < port_width; ++i, ++cp) { | 400 | for (; cnt == 0 && i < port_width; ++i, ++cp) { |
400 | data = (data << 8) | (*(uchar *) cp); | 401 | data = (data << 8) | (*(uchar *) cp); |
401 | } | 402 | } |
402 | 403 | ||
403 | if ((rc = write_data (info, wp, SWAP (data))) != 0) { | 404 | if ((rc = write_data (info, wp, SWAP (data))) != 0) { |
404 | return (rc); | 405 | return (rc); |
405 | } | 406 | } |
406 | wp += port_width; | 407 | wp += port_width; |
407 | } | 408 | } |
408 | 409 | ||
409 | /* | 410 | /* |
410 | * handle word aligned part | 411 | * handle word aligned part |
411 | */ | 412 | */ |
412 | count = 0; | 413 | count = 0; |
413 | while (cnt >= port_width) { | 414 | while (cnt >= port_width) { |
414 | data = 0; | 415 | data = 0; |
415 | for (i = 0; i < port_width; ++i) { | 416 | for (i = 0; i < port_width; ++i) { |
416 | data = (data << 8) | *src++; | 417 | data = (data << 8) | *src++; |
417 | } | 418 | } |
418 | if ((rc = write_data (info, wp, SWAP (data))) != 0) { | 419 | if ((rc = write_data (info, wp, SWAP (data))) != 0) { |
419 | return (rc); | 420 | return (rc); |
420 | } | 421 | } |
421 | wp += port_width; | 422 | wp += port_width; |
422 | cnt -= port_width; | 423 | cnt -= port_width; |
423 | if (count++ > 0x800) { | 424 | if (count++ > 0x800) { |
424 | spin_wheel (); | 425 | spin_wheel (); |
425 | count = 0; | 426 | count = 0; |
426 | } | 427 | } |
427 | } | 428 | } |
428 | 429 | ||
429 | if (cnt == 0) { | 430 | if (cnt == 0) { |
430 | return (0); | 431 | return (0); |
431 | } | 432 | } |
432 | 433 | ||
433 | /* | 434 | /* |
434 | * handle unaligned tail bytes | 435 | * handle unaligned tail bytes |
435 | */ | 436 | */ |
436 | data = 0; | 437 | data = 0; |
437 | for (i = 0, cp = wp; i < port_width && cnt > 0; ++i, ++cp) { | 438 | for (i = 0, cp = wp; i < port_width && cnt > 0; ++i, ++cp) { |
438 | data = (data << 8) | *src++; | 439 | data = (data << 8) | *src++; |
439 | --cnt; | 440 | --cnt; |
440 | } | 441 | } |
441 | for (; i < port_width; ++i, ++cp) { | 442 | for (; i < port_width; ++i, ++cp) { |
442 | data = (data << 8) | (*(uchar *) cp); | 443 | data = (data << 8) | (*(uchar *) cp); |
443 | } | 444 | } |
444 | 445 | ||
445 | return (write_data (info, wp, SWAP (data))); | 446 | return (write_data (info, wp, SWAP (data))); |
446 | } | 447 | } |
447 | 448 | ||
448 | /*----------------------------------------------------------------------- | 449 | /*----------------------------------------------------------------------- |
449 | * Write a word or halfword to Flash, returns: | 450 | * Write a word or halfword to Flash, returns: |
450 | * 0 - OK | 451 | * 0 - OK |
451 | * 1 - write timeout | 452 | * 1 - write timeout |
452 | * 2 - Flash not erased | 453 | * 2 - Flash not erased |
453 | */ | 454 | */ |
454 | static int write_data (flash_info_t * info, ulong dest, FPW data) | 455 | static int write_data (flash_info_t * info, ulong dest, FPW data) |
455 | { | 456 | { |
456 | FPWV *addr = (FPWV *) dest; | 457 | FPWV *addr = (FPWV *) dest; |
457 | ulong status; | 458 | ulong status; |
458 | int flag; | 459 | int flag; |
459 | 460 | ||
460 | /* Check if Flash is (sufficiently) erased */ | 461 | /* Check if Flash is (sufficiently) erased */ |
461 | if ((*addr & data) != data) { | 462 | if ((*addr & data) != data) { |
462 | printf ("not erased at %08lx (%x)\n", (ulong) addr, *addr); | 463 | printf ("not erased at %08lx (%x)\n", (ulong) addr, *addr); |
463 | return (2); | 464 | return (2); |
464 | } | 465 | } |
465 | /* Disable interrupts which might cause a timeout here */ | 466 | /* Disable interrupts which might cause a timeout here */ |
466 | flag = disable_interrupts (); | 467 | flag = disable_interrupts (); |
467 | *addr = (FPW) 0x00400040; /* write setup */ | 468 | *addr = (FPW) 0x00400040; /* write setup */ |
468 | *addr = data; | 469 | *addr = data; |
469 | 470 | ||
470 | /* arm simple, non interrupt dependent timer */ | 471 | /* arm simple, non interrupt dependent timer */ |
471 | reset_timer_masked (); | 472 | reset_timer_masked (); |
472 | 473 | ||
473 | /* wait while polling the status register */ | 474 | /* wait while polling the status register */ |
474 | while (((status = *addr) & (FPW) 0x00800080) != (FPW) 0x00800080) { | 475 | while (((status = *addr) & (FPW) 0x00800080) != (FPW) 0x00800080) { |
475 | if (get_timer_masked () > CFG_FLASH_WRITE_TOUT) { | 476 | if (get_timer_masked () > CFG_FLASH_WRITE_TOUT) { |
476 | *addr = (FPW) 0x00FF00FF; /* restore read mode */ | 477 | *addr = (FPW) 0x00FF00FF; /* restore read mode */ |
477 | return (1); | 478 | return (1); |
478 | } | 479 | } |
479 | } | 480 | } |
480 | *addr = (FPW) 0x00FF00FF; /* restore read mode */ | 481 | *addr = (FPW) 0x00FF00FF; /* restore read mode */ |
481 | return (0); | 482 | return (0); |
482 | } | 483 | } |
483 | 484 | ||
484 | void inline spin_wheel (void) | 485 | void inline spin_wheel (void) |
485 | { | 486 | { |
486 | static int p = 0; | 487 | static int p = 0; |
487 | static char w[] = "\\/-"; | 488 | static char w[] = "\\/-"; |
488 | 489 | ||
489 | printf ("\010%c", w[p]); | 490 | printf ("\010%c", w[p]); |
490 | (++p == 3) ? (p = 0) : 0; | 491 | (++p == 3) ? (p = 0) : 0; |
491 | } | 492 | } |
492 | 493 |
rtc/ds1306.c
1 | /* | 1 | /* |
2 | * (C) Copyright 2002 SIXNET, dge@sixnetio.com. | 2 | * (C) Copyright 2002 SIXNET, dge@sixnetio.com. |
3 | * | 3 | * |
4 | * (C) Copyright 2004, Li-Pro.Net <www.li-pro.net> | 4 | * (C) Copyright 2004, Li-Pro.Net <www.li-pro.net> |
5 | * Stephan Linz <linz@li-pro.net> | 5 | * Stephan Linz <linz@li-pro.net> |
6 | * | 6 | * |
7 | * See file CREDITS for list of people who contributed to this | 7 | * See file CREDITS for list of people who contributed to this |
8 | * project. | 8 | * project. |
9 | * | 9 | * |
10 | * This program is free software; you can redistribute it and/or | 10 | * This program is free software; you can redistribute it and/or |
11 | * modify it under the terms of the GNU General Public License as | 11 | * modify it under the terms of the GNU General Public License as |
12 | * published by the Free Software Foundation; either version 2 of | 12 | * published by the Free Software Foundation; either version 2 of |
13 | * the License, or (at your option) any later version. | 13 | * the License, or (at your option) any later version. |
14 | * | 14 | * |
15 | * This program is distributed in the hope that it will be useful, | 15 | * This program is distributed in the hope that it will be useful, |
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
18 | * GNU General Public License for more details. | 18 | * GNU General Public License for more details. |
19 | * | 19 | * |
20 | * You should have received a copy of the GNU General Public License | 20 | * You should have received a copy of the GNU General Public License |
21 | * along with this program; if not, write to the Free Software | 21 | * along with this program; if not, write to the Free Software |
22 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, | 22 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, |
23 | * MA 02111-1307 USA | 23 | * MA 02111-1307 USA |
24 | */ | 24 | */ |
25 | 25 | ||
26 | /* | 26 | /* |
27 | * Date & Time support for DS1306 RTC using SPI: | 27 | * Date & Time support for DS1306 RTC using SPI: |
28 | * | 28 | * |
29 | * - SXNI855T: it uses its own soft SPI here in this file | 29 | * - SXNI855T: it uses its own soft SPI here in this file |
30 | * - all other: use the external spi_xfer() function | 30 | * - all other: use the external spi_xfer() function |
31 | * (see include/spi.h) | 31 | * (see include/spi.h) |
32 | */ | 32 | */ |
33 | 33 | ||
34 | #include <common.h> | 34 | #include <common.h> |
35 | #include <command.h> | 35 | #include <command.h> |
36 | #include <rtc.h> | 36 | #include <rtc.h> |
37 | #include <spi.h> | 37 | #include <spi.h> |
38 | 38 | ||
39 | #if defined(CONFIG_RTC_DS1306) && (CONFIG_COMMANDS & CFG_CMD_DATE) | 39 | #if defined(CONFIG_RTC_DS1306) && (CONFIG_COMMANDS & CFG_CMD_DATE) |
40 | 40 | ||
41 | #define RTC_SECONDS 0x00 | 41 | #define RTC_SECONDS 0x00 |
42 | #define RTC_MINUTES 0x01 | 42 | #define RTC_MINUTES 0x01 |
43 | #define RTC_HOURS 0x02 | 43 | #define RTC_HOURS 0x02 |
44 | #define RTC_DAY_OF_WEEK 0x03 | 44 | #define RTC_DAY_OF_WEEK 0x03 |
45 | #define RTC_DATE_OF_MONTH 0x04 | 45 | #define RTC_DATE_OF_MONTH 0x04 |
46 | #define RTC_MONTH 0x05 | 46 | #define RTC_MONTH 0x05 |
47 | #define RTC_YEAR 0x06 | 47 | #define RTC_YEAR 0x06 |
48 | 48 | ||
49 | #define RTC_SECONDS_ALARM0 0x07 | 49 | #define RTC_SECONDS_ALARM0 0x07 |
50 | #define RTC_MINUTES_ALARM0 0x08 | 50 | #define RTC_MINUTES_ALARM0 0x08 |
51 | #define RTC_HOURS_ALARM0 0x09 | 51 | #define RTC_HOURS_ALARM0 0x09 |
52 | #define RTC_DAY_OF_WEEK_ALARM0 0x0a | 52 | #define RTC_DAY_OF_WEEK_ALARM0 0x0a |
53 | 53 | ||
54 | #define RTC_SECONDS_ALARM1 0x0b | 54 | #define RTC_SECONDS_ALARM1 0x0b |
55 | #define RTC_MINUTES_ALARM1 0x0c | 55 | #define RTC_MINUTES_ALARM1 0x0c |
56 | #define RTC_HOURS_ALARM1 0x0d | 56 | #define RTC_HOURS_ALARM1 0x0d |
57 | #define RTC_DAY_OF_WEEK_ALARM1 0x0e | 57 | #define RTC_DAY_OF_WEEK_ALARM1 0x0e |
58 | 58 | ||
59 | #define RTC_CONTROL 0x0f | 59 | #define RTC_CONTROL 0x0f |
60 | #define RTC_STATUS 0x10 | 60 | #define RTC_STATUS 0x10 |
61 | #define RTC_TRICKLE_CHARGER 0x11 | 61 | #define RTC_TRICKLE_CHARGER 0x11 |
62 | 62 | ||
63 | #define RTC_USER_RAM_BASE 0x20 | 63 | #define RTC_USER_RAM_BASE 0x20 |
64 | 64 | ||
65 | /* | 65 | /* |
66 | * External table of chip select functions (see the appropriate board | 66 | * External table of chip select functions (see the appropriate board |
67 | * support for the actual definition of the table). | 67 | * support for the actual definition of the table). |
68 | */ | 68 | */ |
69 | extern spi_chipsel_type spi_chipsel[]; | 69 | extern spi_chipsel_type spi_chipsel[]; |
70 | extern int spi_chipsel_cnt; | 70 | extern int spi_chipsel_cnt; |
71 | 71 | ||
72 | static unsigned int bin2bcd (unsigned int n); | 72 | static unsigned int bin2bcd (unsigned int n); |
73 | static unsigned char bcd2bin (unsigned char c); | 73 | static unsigned char bcd2bin (unsigned char c); |
74 | static unsigned char rtc_read (unsigned char reg); | ||
75 | static void rtc_write (unsigned char reg, unsigned char val); | ||
76 | 74 | ||
77 | /* ************************************************************************* */ | 75 | /* ************************************************************************* */ |
78 | #ifdef CONFIG_SXNI855T /* !!! SHOULD BE CHANGED TO NEW CODE !!! */ | 76 | #ifdef CONFIG_SXNI855T /* !!! SHOULD BE CHANGED TO NEW CODE !!! */ |
79 | 77 | ||
78 | static unsigned char rtc_read (unsigned char reg); | ||
79 | static void rtc_write (unsigned char reg, unsigned char val); | ||
80 | static void soft_spi_send (unsigned char n); | 80 | static void soft_spi_send (unsigned char n); |
81 | static unsigned char soft_spi_read (void); | 81 | static unsigned char soft_spi_read (void); |
82 | static void init_spi (void); | 82 | static void init_spi (void); |
83 | 83 | ||
84 | /*----------------------------------------------------------------------- | 84 | /*----------------------------------------------------------------------- |
85 | * Definitions | 85 | * Definitions |
86 | */ | 86 | */ |
87 | 87 | ||
88 | #define PB_SPISCK 0x00000002 /* PB 30 */ | 88 | #define PB_SPISCK 0x00000002 /* PB 30 */ |
89 | #define PB_SPIMOSI 0x00000004 /* PB 29 */ | 89 | #define PB_SPIMOSI 0x00000004 /* PB 29 */ |
90 | #define PB_SPIMISO 0x00000008 /* PB 28 */ | 90 | #define PB_SPIMISO 0x00000008 /* PB 28 */ |
91 | #define PB_SPI_CE 0x00010000 /* PB 15 */ | 91 | #define PB_SPI_CE 0x00010000 /* PB 15 */ |
92 | 92 | ||
93 | /* ------------------------------------------------------------------------- */ | 93 | /* ------------------------------------------------------------------------- */ |
94 | 94 | ||
95 | /* read clock time from DS1306 and return it in *tmp */ | 95 | /* read clock time from DS1306 and return it in *tmp */ |
96 | void rtc_get (struct rtc_time *tmp) | 96 | void rtc_get (struct rtc_time *tmp) |
97 | { | 97 | { |
98 | volatile immap_t *immap = (immap_t *) CFG_IMMR; | 98 | volatile immap_t *immap = (immap_t *) CFG_IMMR; |
99 | unsigned char spi_byte; /* Data Byte */ | 99 | unsigned char spi_byte; /* Data Byte */ |
100 | 100 | ||
101 | init_spi (); /* set port B for software SPI */ | 101 | init_spi (); /* set port B for software SPI */ |
102 | 102 | ||
103 | /* Now we can enable the DS1306 RTC */ | 103 | /* Now we can enable the DS1306 RTC */ |
104 | immap->im_cpm.cp_pbdat |= PB_SPI_CE; | 104 | immap->im_cpm.cp_pbdat |= PB_SPI_CE; |
105 | udelay (10); | 105 | udelay (10); |
106 | 106 | ||
107 | /* Shift out the address (0) of the time in the Clock Chip */ | 107 | /* Shift out the address (0) of the time in the Clock Chip */ |
108 | soft_spi_send (0); | 108 | soft_spi_send (0); |
109 | 109 | ||
110 | /* Put the clock readings into the rtc_time structure */ | 110 | /* Put the clock readings into the rtc_time structure */ |
111 | tmp->tm_sec = bcd2bin (soft_spi_read ()); /* Read seconds */ | 111 | tmp->tm_sec = bcd2bin (soft_spi_read ()); /* Read seconds */ |
112 | tmp->tm_min = bcd2bin (soft_spi_read ()); /* Read minutes */ | 112 | tmp->tm_min = bcd2bin (soft_spi_read ()); /* Read minutes */ |
113 | 113 | ||
114 | /* Hours are trickier */ | 114 | /* Hours are trickier */ |
115 | spi_byte = soft_spi_read (); /* Read Hours into temporary value */ | 115 | spi_byte = soft_spi_read (); /* Read Hours into temporary value */ |
116 | if (spi_byte & 0x40) { | 116 | if (spi_byte & 0x40) { |
117 | /* 12 hour mode bit is set (time is in 1-12 format) */ | 117 | /* 12 hour mode bit is set (time is in 1-12 format) */ |
118 | if (spi_byte & 0x20) { | 118 | if (spi_byte & 0x20) { |
119 | /* since PM we add 11 to get 0-23 for hours */ | 119 | /* since PM we add 11 to get 0-23 for hours */ |
120 | tmp->tm_hour = (bcd2bin (spi_byte & 0x1F)) + 11; | 120 | tmp->tm_hour = (bcd2bin (spi_byte & 0x1F)) + 11; |
121 | } else { | 121 | } else { |
122 | /* since AM we subtract 1 to get 0-23 for hours */ | 122 | /* since AM we subtract 1 to get 0-23 for hours */ |
123 | tmp->tm_hour = (bcd2bin (spi_byte & 0x1F)) - 1; | 123 | tmp->tm_hour = (bcd2bin (spi_byte & 0x1F)) - 1; |
124 | } | 124 | } |
125 | } else { | 125 | } else { |
126 | /* Otherwise, 0-23 hour format */ | 126 | /* Otherwise, 0-23 hour format */ |
127 | tmp->tm_hour = (bcd2bin (spi_byte & 0x3F)); | 127 | tmp->tm_hour = (bcd2bin (spi_byte & 0x3F)); |
128 | } | 128 | } |
129 | 129 | ||
130 | soft_spi_read (); /* Read and discard Day of week */ | 130 | soft_spi_read (); /* Read and discard Day of week */ |
131 | tmp->tm_mday = bcd2bin (soft_spi_read ()); /* Read Day of the Month */ | 131 | tmp->tm_mday = bcd2bin (soft_spi_read ()); /* Read Day of the Month */ |
132 | tmp->tm_mon = bcd2bin (soft_spi_read ()); /* Read Month */ | 132 | tmp->tm_mon = bcd2bin (soft_spi_read ()); /* Read Month */ |
133 | 133 | ||
134 | /* Read Year and convert to this century */ | 134 | /* Read Year and convert to this century */ |
135 | tmp->tm_year = bcd2bin (soft_spi_read ()) + 2000; | 135 | tmp->tm_year = bcd2bin (soft_spi_read ()) + 2000; |
136 | 136 | ||
137 | /* Now we can disable the DS1306 RTC */ | 137 | /* Now we can disable the DS1306 RTC */ |
138 | immap->im_cpm.cp_pbdat &= ~PB_SPI_CE; /* Disable DS1306 Chip */ | 138 | immap->im_cpm.cp_pbdat &= ~PB_SPI_CE; /* Disable DS1306 Chip */ |
139 | udelay (10); | 139 | udelay (10); |
140 | 140 | ||
141 | GregorianDay (tmp); /* Determine the day of week */ | 141 | GregorianDay (tmp); /* Determine the day of week */ |
142 | 142 | ||
143 | debug ("Get DATE: %4d-%02d-%02d (wday=%d) TIME: %2d:%02d:%02d\n", | 143 | debug ("Get DATE: %4d-%02d-%02d (wday=%d) TIME: %2d:%02d:%02d\n", |
144 | tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday, | 144 | tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday, |
145 | tmp->tm_hour, tmp->tm_min, tmp->tm_sec); | 145 | tmp->tm_hour, tmp->tm_min, tmp->tm_sec); |
146 | } | 146 | } |
147 | 147 | ||
148 | /* ------------------------------------------------------------------------- */ | 148 | /* ------------------------------------------------------------------------- */ |
149 | 149 | ||
150 | /* set clock time in DS1306 RTC and in MPC8xx RTC */ | 150 | /* set clock time in DS1306 RTC and in MPC8xx RTC */ |
151 | void rtc_set (struct rtc_time *tmp) | 151 | void rtc_set (struct rtc_time *tmp) |
152 | { | 152 | { |
153 | volatile immap_t *immap = (immap_t *) CFG_IMMR; | 153 | volatile immap_t *immap = (immap_t *) CFG_IMMR; |
154 | 154 | ||
155 | init_spi (); /* set port B for software SPI */ | 155 | init_spi (); /* set port B for software SPI */ |
156 | 156 | ||
157 | /* Now we can enable the DS1306 RTC */ | 157 | /* Now we can enable the DS1306 RTC */ |
158 | immap->im_cpm.cp_pbdat |= PB_SPI_CE; /* Enable DS1306 Chip */ | 158 | immap->im_cpm.cp_pbdat |= PB_SPI_CE; /* Enable DS1306 Chip */ |
159 | udelay (10); | 159 | udelay (10); |
160 | 160 | ||
161 | /* First disable write protect in the clock chip control register */ | 161 | /* First disable write protect in the clock chip control register */ |
162 | soft_spi_send (0x8F); /* send address of the control register */ | 162 | soft_spi_send (0x8F); /* send address of the control register */ |
163 | soft_spi_send (0x00); /* send control register contents */ | 163 | soft_spi_send (0x00); /* send control register contents */ |
164 | 164 | ||
165 | /* Now disable the DS1306 to terminate the write */ | 165 | /* Now disable the DS1306 to terminate the write */ |
166 | immap->im_cpm.cp_pbdat &= ~PB_SPI_CE; | 166 | immap->im_cpm.cp_pbdat &= ~PB_SPI_CE; |
167 | udelay (10); | 167 | udelay (10); |
168 | 168 | ||
169 | /* Now enable the DS1306 to initiate a new write */ | 169 | /* Now enable the DS1306 to initiate a new write */ |
170 | immap->im_cpm.cp_pbdat |= PB_SPI_CE; | 170 | immap->im_cpm.cp_pbdat |= PB_SPI_CE; |
171 | udelay (10); | 171 | udelay (10); |
172 | 172 | ||
173 | /* Next, send the address of the clock time write registers */ | 173 | /* Next, send the address of the clock time write registers */ |
174 | soft_spi_send (0x80); /* send address of the first time register */ | 174 | soft_spi_send (0x80); /* send address of the first time register */ |
175 | 175 | ||
176 | /* Use Burst Mode to send all of the time data to the clock */ | 176 | /* Use Burst Mode to send all of the time data to the clock */ |
177 | bin2bcd (tmp->tm_sec); | 177 | bin2bcd (tmp->tm_sec); |
178 | soft_spi_send (bin2bcd (tmp->tm_sec)); /* Send Seconds */ | 178 | soft_spi_send (bin2bcd (tmp->tm_sec)); /* Send Seconds */ |
179 | soft_spi_send (bin2bcd (tmp->tm_min)); /* Send Minutes */ | 179 | soft_spi_send (bin2bcd (tmp->tm_min)); /* Send Minutes */ |
180 | soft_spi_send (bin2bcd (tmp->tm_hour)); /* Send Hour */ | 180 | soft_spi_send (bin2bcd (tmp->tm_hour)); /* Send Hour */ |
181 | soft_spi_send (bin2bcd (tmp->tm_wday)); /* Send Day of the Week */ | 181 | soft_spi_send (bin2bcd (tmp->tm_wday)); /* Send Day of the Week */ |
182 | soft_spi_send (bin2bcd (tmp->tm_mday)); /* Send Day of Month */ | 182 | soft_spi_send (bin2bcd (tmp->tm_mday)); /* Send Day of Month */ |
183 | soft_spi_send (bin2bcd (tmp->tm_mon)); /* Send Month */ | 183 | soft_spi_send (bin2bcd (tmp->tm_mon)); /* Send Month */ |
184 | soft_spi_send (bin2bcd (tmp->tm_year - 2000)); /* Send Year */ | 184 | soft_spi_send (bin2bcd (tmp->tm_year - 2000)); /* Send Year */ |
185 | 185 | ||
186 | /* Now we can disable the Clock chip to terminate the burst write */ | 186 | /* Now we can disable the Clock chip to terminate the burst write */ |
187 | immap->im_cpm.cp_pbdat &= ~PB_SPI_CE; /* Disable DS1306 Chip */ | 187 | immap->im_cpm.cp_pbdat &= ~PB_SPI_CE; /* Disable DS1306 Chip */ |
188 | udelay (10); | 188 | udelay (10); |
189 | 189 | ||
190 | /* Now we can enable the Clock chip to initiate a new write */ | 190 | /* Now we can enable the Clock chip to initiate a new write */ |
191 | immap->im_cpm.cp_pbdat |= PB_SPI_CE; /* Enable DS1306 Chip */ | 191 | immap->im_cpm.cp_pbdat |= PB_SPI_CE; /* Enable DS1306 Chip */ |
192 | udelay (10); | 192 | udelay (10); |
193 | 193 | ||
194 | /* First we Enable write protect in the clock chip control register */ | 194 | /* First we Enable write protect in the clock chip control register */ |
195 | soft_spi_send (0x8F); /* send address of the control register */ | 195 | soft_spi_send (0x8F); /* send address of the control register */ |
196 | soft_spi_send (0x40); /* send out Control Register contents */ | 196 | soft_spi_send (0x40); /* send out Control Register contents */ |
197 | 197 | ||
198 | /* Now disable the DS1306 */ | 198 | /* Now disable the DS1306 */ |
199 | immap->im_cpm.cp_pbdat &= ~PB_SPI_CE; /* Disable DS1306 Chip */ | 199 | immap->im_cpm.cp_pbdat &= ~PB_SPI_CE; /* Disable DS1306 Chip */ |
200 | udelay (10); | 200 | udelay (10); |
201 | 201 | ||
202 | /* Set standard MPC8xx clock to the same time so Linux will | 202 | /* Set standard MPC8xx clock to the same time so Linux will |
203 | * see the time even if it doesn't have a DS1306 clock driver. | 203 | * see the time even if it doesn't have a DS1306 clock driver. |
204 | * This helps with experimenting with standard kernels. | 204 | * This helps with experimenting with standard kernels. |
205 | */ | 205 | */ |
206 | { | 206 | { |
207 | ulong tim; | 207 | ulong tim; |
208 | 208 | ||
209 | tim = mktime (tmp->tm_year, tmp->tm_mon, tmp->tm_mday, | 209 | tim = mktime (tmp->tm_year, tmp->tm_mon, tmp->tm_mday, |
210 | tmp->tm_hour, tmp->tm_min, tmp->tm_sec); | 210 | tmp->tm_hour, tmp->tm_min, tmp->tm_sec); |
211 | 211 | ||
212 | immap->im_sitk.sitk_rtck = KAPWR_KEY; | 212 | immap->im_sitk.sitk_rtck = KAPWR_KEY; |
213 | immap->im_sit.sit_rtc = tim; | 213 | immap->im_sit.sit_rtc = tim; |
214 | } | 214 | } |
215 | 215 | ||
216 | debug ("Set DATE: %4d-%02d-%02d (wday=%d) TIME: %2d:%02d:%02d\n", | 216 | debug ("Set DATE: %4d-%02d-%02d (wday=%d) TIME: %2d:%02d:%02d\n", |
217 | tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday, | 217 | tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday, |
218 | tmp->tm_hour, tmp->tm_min, tmp->tm_sec); | 218 | tmp->tm_hour, tmp->tm_min, tmp->tm_sec); |
219 | } | 219 | } |
220 | 220 | ||
221 | /* ------------------------------------------------------------------------- */ | 221 | /* ------------------------------------------------------------------------- */ |
222 | 222 | ||
223 | /* Initialize Port B for software SPI */ | 223 | /* Initialize Port B for software SPI */ |
224 | static void init_spi (void) | 224 | static void init_spi (void) |
225 | { | 225 | { |
226 | volatile immap_t *immap = (immap_t *) CFG_IMMR; | 226 | volatile immap_t *immap = (immap_t *) CFG_IMMR; |
227 | 227 | ||
228 | /* Force output pins to begin at logic 0 */ | 228 | /* Force output pins to begin at logic 0 */ |
229 | immap->im_cpm.cp_pbdat &= ~(PB_SPI_CE | PB_SPIMOSI | PB_SPISCK); | 229 | immap->im_cpm.cp_pbdat &= ~(PB_SPI_CE | PB_SPIMOSI | PB_SPISCK); |
230 | 230 | ||
231 | /* Set these 3 signals as outputs */ | 231 | /* Set these 3 signals as outputs */ |
232 | immap->im_cpm.cp_pbdir |= (PB_SPIMOSI | PB_SPI_CE | PB_SPISCK); | 232 | immap->im_cpm.cp_pbdir |= (PB_SPIMOSI | PB_SPI_CE | PB_SPISCK); |
233 | 233 | ||
234 | immap->im_cpm.cp_pbdir &= ~PB_SPIMISO; /* Make MISO pin an input */ | 234 | immap->im_cpm.cp_pbdir &= ~PB_SPIMISO; /* Make MISO pin an input */ |
235 | udelay (10); | 235 | udelay (10); |
236 | } | 236 | } |
237 | 237 | ||
238 | /* ------------------------------------------------------------------------- */ | 238 | /* ------------------------------------------------------------------------- */ |
239 | 239 | ||
240 | /* NOTE: soft_spi_send() assumes that the I/O lines are configured already */ | 240 | /* NOTE: soft_spi_send() assumes that the I/O lines are configured already */ |
241 | static void soft_spi_send (unsigned char n) | 241 | static void soft_spi_send (unsigned char n) |
242 | { | 242 | { |
243 | volatile immap_t *immap = (immap_t *) CFG_IMMR; | 243 | volatile immap_t *immap = (immap_t *) CFG_IMMR; |
244 | unsigned char bitpos; /* bit position to receive */ | 244 | unsigned char bitpos; /* bit position to receive */ |
245 | unsigned char i; /* Loop Control */ | 245 | unsigned char i; /* Loop Control */ |
246 | 246 | ||
247 | /* bit position to send, start with most significant bit */ | 247 | /* bit position to send, start with most significant bit */ |
248 | bitpos = 0x80; | 248 | bitpos = 0x80; |
249 | 249 | ||
250 | /* Send 8 bits to software SPI */ | 250 | /* Send 8 bits to software SPI */ |
251 | for (i = 0; i < 8; i++) { /* Loop for 8 bits */ | 251 | for (i = 0; i < 8; i++) { /* Loop for 8 bits */ |
252 | immap->im_cpm.cp_pbdat |= PB_SPISCK; /* Raise SCK */ | 252 | immap->im_cpm.cp_pbdat |= PB_SPISCK; /* Raise SCK */ |
253 | 253 | ||
254 | if (n & bitpos) | 254 | if (n & bitpos) |
255 | immap->im_cpm.cp_pbdat |= PB_SPIMOSI; /* Set MOSI to 1 */ | 255 | immap->im_cpm.cp_pbdat |= PB_SPIMOSI; /* Set MOSI to 1 */ |
256 | else | 256 | else |
257 | immap->im_cpm.cp_pbdat &= ~PB_SPIMOSI; /* Set MOSI to 0 */ | 257 | immap->im_cpm.cp_pbdat &= ~PB_SPIMOSI; /* Set MOSI to 0 */ |
258 | udelay (10); | 258 | udelay (10); |
259 | 259 | ||
260 | immap->im_cpm.cp_pbdat &= ~PB_SPISCK; /* Lower SCK */ | 260 | immap->im_cpm.cp_pbdat &= ~PB_SPISCK; /* Lower SCK */ |
261 | udelay (10); | 261 | udelay (10); |
262 | 262 | ||
263 | bitpos >>= 1; /* Shift for next bit position */ | 263 | bitpos >>= 1; /* Shift for next bit position */ |
264 | } | 264 | } |
265 | } | 265 | } |
266 | 266 | ||
267 | /* ------------------------------------------------------------------------- */ | 267 | /* ------------------------------------------------------------------------- */ |
268 | 268 | ||
269 | /* NOTE: soft_spi_read() assumes that the I/O lines are configured already */ | 269 | /* NOTE: soft_spi_read() assumes that the I/O lines are configured already */ |
270 | static unsigned char soft_spi_read (void) | 270 | static unsigned char soft_spi_read (void) |
271 | { | 271 | { |
272 | volatile immap_t *immap = (immap_t *) CFG_IMMR; | 272 | volatile immap_t *immap = (immap_t *) CFG_IMMR; |
273 | 273 | ||
274 | unsigned char spi_byte = 0; /* Return value, assume success */ | 274 | unsigned char spi_byte = 0; /* Return value, assume success */ |
275 | unsigned char bitpos; /* bit position to receive */ | 275 | unsigned char bitpos; /* bit position to receive */ |
276 | unsigned char i; /* Loop Control */ | 276 | unsigned char i; /* Loop Control */ |
277 | 277 | ||
278 | /* bit position to receive, start with most significant bit */ | 278 | /* bit position to receive, start with most significant bit */ |
279 | bitpos = 0x80; | 279 | bitpos = 0x80; |
280 | 280 | ||
281 | /* Read 8 bits here */ | 281 | /* Read 8 bits here */ |
282 | for (i = 0; i < 8; i++) { /* Do 8 bits in loop */ | 282 | for (i = 0; i < 8; i++) { /* Do 8 bits in loop */ |
283 | immap->im_cpm.cp_pbdat |= PB_SPISCK; /* Raise SCK */ | 283 | immap->im_cpm.cp_pbdat |= PB_SPISCK; /* Raise SCK */ |
284 | udelay (10); | 284 | udelay (10); |
285 | if (immap->im_cpm.cp_pbdat & PB_SPIMISO) /* Get a bit of data */ | 285 | if (immap->im_cpm.cp_pbdat & PB_SPIMISO) /* Get a bit of data */ |
286 | spi_byte |= bitpos; /* Set data accordingly */ | 286 | spi_byte |= bitpos; /* Set data accordingly */ |
287 | immap->im_cpm.cp_pbdat &= ~PB_SPISCK; /* Lower SCK */ | 287 | immap->im_cpm.cp_pbdat &= ~PB_SPISCK; /* Lower SCK */ |
288 | udelay (10); | 288 | udelay (10); |
289 | bitpos >>= 1; /* Shift for next bit position */ | 289 | bitpos >>= 1; /* Shift for next bit position */ |
290 | } | 290 | } |
291 | 291 | ||
292 | return spi_byte; /* Return the byte read */ | 292 | return spi_byte; /* Return the byte read */ |
293 | } | 293 | } |
294 | 294 | ||
295 | /* ------------------------------------------------------------------------- */ | 295 | /* ------------------------------------------------------------------------- */ |
296 | 296 | ||
297 | void rtc_reset (void) | 297 | void rtc_reset (void) |
298 | { | 298 | { |
299 | return; /* nothing to do */ | 299 | return; /* nothing to do */ |
300 | } | 300 | } |
301 | 301 | ||
302 | #else /* not CONFIG_SXNI855T */ | 302 | #else /* not CONFIG_SXNI855T */ |
303 | /* ************************************************************************* */ | 303 | /* ************************************************************************* */ |
304 | 304 | ||
305 | /* read clock time from DS1306 and return it in *tmp */ | 305 | /* read clock time from DS1306 and return it in *tmp */ |
306 | void rtc_get (struct rtc_time *tmp) | 306 | void rtc_get (struct rtc_time *tmp) |
307 | { | 307 | { |
308 | unsigned char sec, min, hour, mday, wday, mon, year; | 308 | unsigned char sec, min, hour, mday, wday, mon, year; |
309 | 309 | ||
310 | sec = rtc_read (RTC_SECONDS); | 310 | sec = rtc_read (RTC_SECONDS); |
311 | min = rtc_read (RTC_MINUTES); | 311 | min = rtc_read (RTC_MINUTES); |
312 | hour = rtc_read (RTC_HOURS); | 312 | hour = rtc_read (RTC_HOURS); |
313 | mday = rtc_read (RTC_DATE_OF_MONTH); | 313 | mday = rtc_read (RTC_DATE_OF_MONTH); |
314 | wday = rtc_read (RTC_DAY_OF_WEEK); | 314 | wday = rtc_read (RTC_DAY_OF_WEEK); |
315 | mon = rtc_read (RTC_MONTH); | 315 | mon = rtc_read (RTC_MONTH); |
316 | year = rtc_read (RTC_YEAR); | 316 | year = rtc_read (RTC_YEAR); |
317 | 317 | ||
318 | debug ("Get RTC year: %02x mon: %02x mday: %02x wday: %02x " | 318 | debug ("Get RTC year: %02x mon: %02x mday: %02x wday: %02x " |
319 | "hr: %02x min: %02x sec: %02x\n", | 319 | "hr: %02x min: %02x sec: %02x\n", |
320 | year, mon, mday, wday, hour, min, sec); | 320 | year, mon, mday, wday, hour, min, sec); |
321 | debug ("Alarms[0]: wday: %02x hour: %02x min: %02x sec: %02x\n", | 321 | debug ("Alarms[0]: wday: %02x hour: %02x min: %02x sec: %02x\n", |
322 | rtc_read (RTC_DAY_OF_WEEK_ALARM0), | 322 | rtc_read (RTC_DAY_OF_WEEK_ALARM0), |
323 | rtc_read (RTC_HOURS_ALARM0), | 323 | rtc_read (RTC_HOURS_ALARM0), |
324 | rtc_read (RTC_MINUTES_ALARM0), rtc_read (RTC_SECONDS_ALARM0)); | 324 | rtc_read (RTC_MINUTES_ALARM0), rtc_read (RTC_SECONDS_ALARM0)); |
325 | debug ("Alarms[1]: wday: %02x hour: %02x min: %02x sec: %02x\n", | 325 | debug ("Alarms[1]: wday: %02x hour: %02x min: %02x sec: %02x\n", |
326 | rtc_read (RTC_DAY_OF_WEEK_ALARM1), | 326 | rtc_read (RTC_DAY_OF_WEEK_ALARM1), |
327 | rtc_read (RTC_HOURS_ALARM1), | 327 | rtc_read (RTC_HOURS_ALARM1), |
328 | rtc_read (RTC_MINUTES_ALARM1), rtc_read (RTC_SECONDS_ALARM1)); | 328 | rtc_read (RTC_MINUTES_ALARM1), rtc_read (RTC_SECONDS_ALARM1)); |
329 | 329 | ||
330 | tmp->tm_sec = bcd2bin (sec & 0x7F); /* convert Seconds */ | 330 | tmp->tm_sec = bcd2bin (sec & 0x7F); /* convert Seconds */ |
331 | tmp->tm_min = bcd2bin (min & 0x7F); /* convert Minutes */ | 331 | tmp->tm_min = bcd2bin (min & 0x7F); /* convert Minutes */ |
332 | 332 | ||
333 | /* convert Hours */ | 333 | /* convert Hours */ |
334 | tmp->tm_hour = (hour & 0x40) | 334 | tmp->tm_hour = (hour & 0x40) |
335 | ? ((hour & 0x20) /* 12 hour mode */ | 335 | ? ((hour & 0x20) /* 12 hour mode */ |
336 | ? bcd2bin (hour & 0x1F) + 11 /* PM */ | 336 | ? bcd2bin (hour & 0x1F) + 11 /* PM */ |
337 | : bcd2bin (hour & 0x1F) - 1 /* AM */ | 337 | : bcd2bin (hour & 0x1F) - 1 /* AM */ |
338 | ) | 338 | ) |
339 | : bcd2bin (hour & 0x3F); /* 24 hour mode */ | 339 | : bcd2bin (hour & 0x3F); /* 24 hour mode */ |
340 | 340 | ||
341 | tmp->tm_mday = bcd2bin (mday & 0x3F); /* convert Day of the Month */ | 341 | tmp->tm_mday = bcd2bin (mday & 0x3F); /* convert Day of the Month */ |
342 | tmp->tm_mon = bcd2bin (mon & 0x1F); /* convert Month */ | 342 | tmp->tm_mon = bcd2bin (mon & 0x1F); /* convert Month */ |
343 | tmp->tm_year = bcd2bin (year) + 2000; /* convert Year */ | 343 | tmp->tm_year = bcd2bin (year) + 2000; /* convert Year */ |
344 | tmp->tm_wday = bcd2bin (wday & 0x07) - 1; /* convert Day of the Week */ | 344 | tmp->tm_wday = bcd2bin (wday & 0x07) - 1; /* convert Day of the Week */ |
345 | tmp->tm_yday = 0; | 345 | tmp->tm_yday = 0; |
346 | tmp->tm_isdst = 0; | 346 | tmp->tm_isdst = 0; |
347 | 347 | ||
348 | debug ("Get DATE: %4d-%02d-%02d (wday=%d) TIME: %2d:%02d:%02d\n", | 348 | debug ("Get DATE: %4d-%02d-%02d (wday=%d) TIME: %2d:%02d:%02d\n", |
349 | tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday, | 349 | tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday, |
350 | tmp->tm_hour, tmp->tm_min, tmp->tm_sec); | 350 | tmp->tm_hour, tmp->tm_min, tmp->tm_sec); |
351 | } | 351 | } |
352 | 352 | ||
353 | /* ------------------------------------------------------------------------- */ | 353 | /* ------------------------------------------------------------------------- */ |
354 | 354 | ||
355 | /* set clock time from *tmp in DS1306 RTC */ | 355 | /* set clock time from *tmp in DS1306 RTC */ |
356 | void rtc_set (struct rtc_time *tmp) | 356 | void rtc_set (struct rtc_time *tmp) |
357 | { | 357 | { |
358 | debug ("Set DATE: %4d-%02d-%02d (wday=%d) TIME: %2d:%02d:%02d\n", | 358 | debug ("Set DATE: %4d-%02d-%02d (wday=%d) TIME: %2d:%02d:%02d\n", |
359 | tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday, | 359 | tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday, |
360 | tmp->tm_hour, tmp->tm_min, tmp->tm_sec); | 360 | tmp->tm_hour, tmp->tm_min, tmp->tm_sec); |
361 | 361 | ||
362 | rtc_write (RTC_YEAR, bin2bcd (tmp->tm_year - 2000)); | 362 | rtc_write (RTC_YEAR, bin2bcd (tmp->tm_year - 2000)); |
363 | rtc_write (RTC_MONTH, bin2bcd (tmp->tm_mon)); | 363 | rtc_write (RTC_MONTH, bin2bcd (tmp->tm_mon)); |
364 | rtc_write (RTC_DATE_OF_MONTH, bin2bcd (tmp->tm_mday)); | 364 | rtc_write (RTC_DATE_OF_MONTH, bin2bcd (tmp->tm_mday)); |
365 | rtc_write (RTC_DAY_OF_WEEK, bin2bcd (tmp->tm_wday + 1)); | 365 | rtc_write (RTC_DAY_OF_WEEK, bin2bcd (tmp->tm_wday + 1)); |
366 | rtc_write (RTC_HOURS, bin2bcd (tmp->tm_hour)); | 366 | rtc_write (RTC_HOURS, bin2bcd (tmp->tm_hour)); |
367 | rtc_write (RTC_MINUTES, bin2bcd (tmp->tm_min)); | 367 | rtc_write (RTC_MINUTES, bin2bcd (tmp->tm_min)); |
368 | rtc_write (RTC_SECONDS, bin2bcd (tmp->tm_sec)); | 368 | rtc_write (RTC_SECONDS, bin2bcd (tmp->tm_sec)); |
369 | } | 369 | } |
370 | 370 | ||
371 | /* ------------------------------------------------------------------------- */ | 371 | /* ------------------------------------------------------------------------- */ |
372 | 372 | ||
373 | /* reset the DS1306 */ | 373 | /* reset the DS1306 */ |
374 | void rtc_reset (void) | 374 | void rtc_reset (void) |
375 | { | 375 | { |
376 | /* clear the control register */ | 376 | /* clear the control register */ |
377 | rtc_write (RTC_CONTROL, 0x00); /* 1st step: reset WP */ | 377 | rtc_write (RTC_CONTROL, 0x00); /* 1st step: reset WP */ |
378 | rtc_write (RTC_CONTROL, 0x00); /* 2nd step: reset 1Hz, AIE1, AIE0 */ | 378 | rtc_write (RTC_CONTROL, 0x00); /* 2nd step: reset 1Hz, AIE1, AIE0 */ |
379 | 379 | ||
380 | /* reset all alarms */ | 380 | /* reset all alarms */ |
381 | rtc_write (RTC_SECONDS_ALARM0, 0x00); | 381 | rtc_write (RTC_SECONDS_ALARM0, 0x00); |
382 | rtc_write (RTC_SECONDS_ALARM1, 0x00); | 382 | rtc_write (RTC_SECONDS_ALARM1, 0x00); |
383 | rtc_write (RTC_MINUTES_ALARM0, 0x00); | 383 | rtc_write (RTC_MINUTES_ALARM0, 0x00); |
384 | rtc_write (RTC_MINUTES_ALARM1, 0x00); | 384 | rtc_write (RTC_MINUTES_ALARM1, 0x00); |
385 | rtc_write (RTC_HOURS_ALARM0, 0x00); | 385 | rtc_write (RTC_HOURS_ALARM0, 0x00); |
386 | rtc_write (RTC_HOURS_ALARM1, 0x00); | 386 | rtc_write (RTC_HOURS_ALARM1, 0x00); |
387 | rtc_write (RTC_DAY_OF_WEEK_ALARM0, 0x00); | 387 | rtc_write (RTC_DAY_OF_WEEK_ALARM0, 0x00); |
388 | rtc_write (RTC_DAY_OF_WEEK_ALARM1, 0x00); | 388 | rtc_write (RTC_DAY_OF_WEEK_ALARM1, 0x00); |
389 | } | 389 | } |
390 | 390 | ||
391 | /* ------------------------------------------------------------------------- */ | 391 | /* ------------------------------------------------------------------------- */ |
392 | 392 | ||
393 | static unsigned char rtc_read (unsigned char reg) | 393 | static unsigned char rtc_read (unsigned char reg) |
394 | { | 394 | { |
395 | unsigned char dout[2]; /* SPI Output Data Bytes */ | 395 | unsigned char dout[2]; /* SPI Output Data Bytes */ |
396 | unsigned char din[2]; /* SPI Input Data Bytes */ | 396 | unsigned char din[2]; /* SPI Input Data Bytes */ |
397 | 397 | ||
398 | dout[0] = reg; | 398 | dout[0] = reg; |
399 | 399 | ||
400 | if (spi_xfer (spi_chipsel[CFG_SPI_RTC_DEVID], 16, dout, din) != 0) { | 400 | if (spi_xfer (spi_chipsel[CFG_SPI_RTC_DEVID], 16, dout, din) != 0) { |
401 | return 0; | 401 | return 0; |
402 | } else { | 402 | } else { |
403 | return din[1]; | 403 | return din[1]; |
404 | } | 404 | } |
405 | } | 405 | } |
406 | 406 | ||
407 | /* ------------------------------------------------------------------------- */ | 407 | /* ------------------------------------------------------------------------- */ |
408 | 408 | ||
409 | static void rtc_write (unsigned char reg, unsigned char val) | 409 | static void rtc_write (unsigned char reg, unsigned char val) |
410 | { | 410 | { |
411 | unsigned char dout[2]; /* SPI Output Data Bytes */ | 411 | unsigned char dout[2]; /* SPI Output Data Bytes */ |
412 | unsigned char din[2]; /* SPI Input Data Bytes */ | 412 | unsigned char din[2]; /* SPI Input Data Bytes */ |
413 | 413 | ||
414 | dout[0] = 0x80 | reg; | 414 | dout[0] = 0x80 | reg; |
415 | dout[1] = val; | 415 | dout[1] = val; |
416 | 416 | ||
417 | spi_xfer (spi_chipsel[CFG_SPI_RTC_DEVID], 16, dout, din); | 417 | spi_xfer (spi_chipsel[CFG_SPI_RTC_DEVID], 16, dout, din); |
418 | } | 418 | } |
419 | 419 | ||
420 | #endif /* end of code exclusion (see #ifdef CONFIG_SXNI855T above) */ | 420 | #endif /* end of code exclusion (see #ifdef CONFIG_SXNI855T above) */ |
421 | 421 | ||
422 | /* ------------------------------------------------------------------------- */ | 422 | /* ------------------------------------------------------------------------- */ |
423 | 423 | ||
424 | static unsigned char bcd2bin (unsigned char n) | 424 | static unsigned char bcd2bin (unsigned char n) |
425 | { | 425 | { |
426 | return ((((n >> 4) & 0x0F) * 10) + (n & 0x0F)); | 426 | return ((((n >> 4) & 0x0F) * 10) + (n & 0x0F)); |
427 | } | 427 | } |
428 | 428 | ||
429 | /* ------------------------------------------------------------------------- */ | 429 | /* ------------------------------------------------------------------------- */ |
430 | 430 | ||
431 | static unsigned int bin2bcd (unsigned int n) | 431 | static unsigned int bin2bcd (unsigned int n) |
432 | { | 432 | { |
433 | return (((n / 10) << 4) | (n % 10)); | 433 | return (((n / 10) << 4) | (n % 10)); |
434 | } | 434 | } |
435 | /* ------------------------------------------------------------------------- */ | 435 | /* ------------------------------------------------------------------------- */ |
436 | 436 |