]>
Commit | Line | Data |
---|---|---|
ae691e57 SR |
1 | /* |
2 | * (C) Copyright 2008 Stefan Roese <sr@denx.de>, DENX Software Engineering | |
3 | * | |
4 | * Copyright 2005, Seagate Technology LLC | |
5 | * | |
6 | * See file CREDITS for list of people who contributed to this | |
7 | * project. | |
8 | * | |
9 | * This program is free software; you can redistribute it and/or modify | |
10 | * it under the terms of the GNU General Public License version 2 as | |
11 | * published by the Free Software Foundation. | |
12 | * | |
13 | * This program is distributed in the hope that it will be useful, | |
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 | * GNU General Public License for more details. | |
17 | * | |
18 | * You should have received a copy of the GNU General Public License | |
19 | * along with this program; if not, write to the Free Software | |
20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, | |
21 | * MA 02111-1307 USA | |
22 | * | |
23 | */ | |
24 | ||
25 | #undef DEBUG | |
26 | ||
27 | #include <common.h> | |
28 | #include <command.h> | |
29 | #include <config.h> | |
30 | #include <net.h> | |
31 | ||
32 | #include "vct.h" | |
33 | ||
34 | #define SMSC9118_BASE CONFIG_DRIVER_SMC911X_BASE | |
35 | #define BYTE_TEST (SMSC9118_BASE + 0x64) | |
36 | #define GPIO_CFG (SMSC9118_BASE + 0x88) | |
37 | #define MAC_CSR_CMD (SMSC9118_BASE + 0xA4) | |
38 | #define MAC_CSR_CMD_CSR_BUSY (0x80000000) | |
39 | #define MAC_CSR_CMD_RNW (0x40000000) | |
40 | #define MAC_RD_CMD(reg) ((reg & 0x000000FF) | \ | |
41 | (MAC_CSR_CMD_CSR_BUSY | MAC_CSR_CMD_RNW)) | |
42 | #define MAC_WR_CMD(reg) ((reg & 0x000000FF) | \ | |
43 | (MAC_CSR_CMD_CSR_BUSY)) | |
44 | #define MAC_CSR_DATA (SMSC9118_BASE + 0xA8) | |
45 | #define E2P_CMD (SMSC9118_BASE + 0xB0) | |
46 | #define E2P_CMD_EPC_BUSY_ (0x80000000UL) /* Self Clearing */ | |
47 | #define E2P_CMD_EPC_CMD_ (0x70000000UL) /* R/W */ | |
48 | #define E2P_CMD_EPC_CMD_READ_ (0x00000000UL) /* R/W */ | |
49 | #define E2P_CMD_EPC_CMD_EWDS_ (0x10000000UL) /* R/W */ | |
50 | #define E2P_CMD_EPC_CMD_EWEN_ (0x20000000UL) /* R/W */ | |
51 | #define E2P_CMD_EPC_CMD_WRITE_ (0x30000000UL) /* R/W */ | |
52 | #define E2P_CMD_EPC_CMD_WRAL_ (0x40000000UL) /* R/W */ | |
53 | #define E2P_CMD_EPC_CMD_ERASE_ (0x50000000UL) /* R/W */ | |
54 | #define E2P_CMD_EPC_CMD_ERAL_ (0x60000000UL) /* R/W */ | |
55 | #define E2P_CMD_EPC_CMD_RELOAD_ (0x70000000UL) /* R/W */ | |
56 | #define E2P_CMD_EPC_TIMEOUT_ (0x00000200UL) /* R */ | |
57 | #define E2P_CMD_MAC_ADDR_LOADED_ (0x00000100UL) /* RO */ | |
58 | #define E2P_CMD_EPC_ADDR_ (0x000000FFUL) /* R/W */ | |
59 | #define E2P_DATA (SMSC9118_BASE + 0xB4) | |
60 | ||
61 | #define MAC_ADDRH (0x2) | |
62 | #define MAC_ADDRL (0x3) | |
63 | ||
64 | #define MAC_TIMEOUT 200 | |
65 | ||
66 | #define HIBYTE(word) ((u8)(((u16)(word)) >> 8)) | |
67 | #define LOBYTE(word) ((u8)(((u16)(word)) & 0x00FFU)) | |
68 | #define HIWORD(dword) ((u16)(((u32)(dword)) >> 16)) | |
69 | #define LOWORD(dword) ((u16)(((u32)(dword)) & 0x0000FFFFUL)) | |
70 | ||
71 | static int mac_busy(int req_to) | |
72 | { | |
73 | int timeout = req_to; | |
74 | ||
75 | while (timeout--) { | |
76 | if (!(smc911x_reg_read(MAC_CSR_CMD) & MAC_CSR_CMD_CSR_BUSY)) | |
77 | goto done; | |
78 | } | |
79 | return 1; /* Timeout */ | |
80 | ||
81 | done: | |
82 | return 0; /* No timeout */ | |
83 | } | |
84 | ||
85 | static ulong get_mac_reg(int reg) | |
86 | { | |
87 | ulong reg_val = 0xffffffff; | |
88 | ||
89 | if (smc911x_reg_read(MAC_CSR_CMD) & MAC_CSR_CMD_CSR_BUSY) { | |
90 | printf("get_mac_reg: previous command not complete\n"); | |
91 | goto done; | |
92 | } | |
93 | ||
94 | smc911x_reg_write(MAC_CSR_CMD, MAC_RD_CMD(reg)); | |
95 | udelay(10000); | |
96 | ||
97 | if (mac_busy(MAC_TIMEOUT) == 1) { | |
98 | printf("get_mac_reg: timeout waiting for response from MAC\n"); | |
99 | goto done; | |
100 | } | |
101 | ||
102 | reg_val = smc911x_reg_read(MAC_CSR_DATA); | |
103 | ||
104 | done: | |
105 | return (reg_val); | |
106 | } | |
107 | ||
108 | static ulong eeprom_enable_access(void) | |
109 | { | |
110 | ulong gpio; | |
111 | ||
112 | gpio = smc911x_reg_read(GPIO_CFG); | |
113 | debug("%s: gpio= 0x%08lx ---> 0x%08lx\n", __func__, gpio, | |
114 | (gpio & 0xFF0FFFFFUL)); | |
115 | ||
116 | smc911x_reg_write(GPIO_CFG, (gpio & 0xFF0FFFFFUL)); | |
117 | return gpio; | |
118 | } | |
119 | ||
120 | static void eeprom_disable_access(ulong gpio) | |
121 | { | |
122 | debug("%s: gpio= 0x%08lx\n", __func__, gpio); | |
123 | smc911x_reg_write(GPIO_CFG, gpio); | |
124 | } | |
125 | ||
126 | static int eeprom_is_mac_address_loaded(void) | |
127 | { | |
128 | int ret; | |
129 | ||
130 | ret = smc911x_reg_read(MAC_CSR_CMD) & E2P_CMD_MAC_ADDR_LOADED_; | |
131 | debug("%s: ret = %x\n", __func__, ret); | |
132 | ||
133 | return ret; | |
134 | } | |
135 | ||
136 | static int eeprom_read_location(unchar address, u8 *data) | |
137 | { | |
138 | ulong timeout = 100000; | |
139 | ulong temp = 0; | |
140 | ||
141 | if ((temp = smc911x_reg_read(E2P_CMD)) & E2P_CMD_EPC_BUSY_) { | |
142 | printf("%s: Busy at start, E2P_CMD=0x%08lX\n", __func__, temp); | |
143 | return 0; | |
144 | } | |
145 | ||
146 | smc911x_reg_write(E2P_CMD, | |
147 | (E2P_CMD_EPC_BUSY_ | E2P_CMD_EPC_CMD_READ_ | | |
148 | ((ulong) address))); | |
149 | ||
150 | while ((timeout > 0) && (smc911x_reg_read(E2P_CMD) & E2P_CMD_EPC_BUSY_)) { | |
151 | udelay(10); | |
152 | timeout--; | |
153 | } | |
154 | ||
155 | if (timeout == 0) { | |
156 | printf("Timeout\n"); | |
157 | return 0; | |
158 | } | |
159 | (*data) = (unchar) (smc911x_reg_read(E2P_DATA)); | |
160 | debug("%s: ret = %x\n", __func__, (*data)); | |
161 | ||
162 | return 1; | |
163 | } | |
164 | ||
165 | static int eeprom_enable_erase_and_write(void) | |
166 | { | |
167 | ulong timeout = 100000; | |
168 | ||
169 | if (smc911x_reg_read(E2P_CMD) & E2P_CMD_EPC_BUSY_) { | |
170 | printf("%s: Busy at start\n", __func__); | |
171 | return 0; | |
172 | } | |
173 | smc911x_reg_write(E2P_CMD, (E2P_CMD_EPC_BUSY_ | E2P_CMD_EPC_CMD_EWEN_)); | |
174 | ||
175 | while ((timeout > 0) && (smc911x_reg_read(E2P_CMD) & E2P_CMD_EPC_BUSY_)) { | |
176 | udelay(10); | |
177 | timeout--; | |
178 | } | |
179 | ||
180 | if (timeout == 0) { | |
181 | printf("Timeout[1]\n"); | |
182 | return 0; | |
183 | } | |
184 | ||
185 | return 1; | |
186 | } | |
187 | ||
188 | static int eeprom_disable_erase_and_write(void) | |
189 | { | |
190 | ulong timeout = 100000; | |
191 | ||
192 | if (smc911x_reg_read(E2P_CMD) & E2P_CMD_EPC_BUSY_) { | |
193 | printf("%s: Busy at start\n", __func__); | |
194 | return 0; | |
195 | } | |
196 | smc911x_reg_write(E2P_CMD, (E2P_CMD_EPC_BUSY_ | E2P_CMD_EPC_CMD_EWDS_)); | |
197 | ||
198 | while ((timeout > 0) && (smc911x_reg_read(E2P_CMD) & E2P_CMD_EPC_BUSY_)) { | |
199 | udelay(10); | |
200 | timeout--; | |
201 | } | |
202 | ||
203 | if (timeout == 0) { | |
204 | printf("Timeout[2]\n"); | |
205 | return 0; | |
206 | } | |
207 | ||
208 | return 1; | |
209 | } | |
210 | ||
211 | static int eeprom_write_location(unchar address, unchar data) | |
212 | { | |
213 | ulong timeout = 100000; | |
214 | ||
215 | debug("%s: address: %x data = %x\n", __func__, address, data); | |
216 | ||
217 | if (smc911x_reg_read(E2P_CMD) & E2P_CMD_EPC_BUSY_) { | |
218 | printf("%s: Busy at start\n", __func__); | |
219 | return 0; | |
220 | } | |
221 | ||
222 | smc911x_reg_write(E2P_DATA, ((ulong) data)); | |
223 | smc911x_reg_write(E2P_CMD, | |
224 | (E2P_CMD_EPC_BUSY_ | E2P_CMD_EPC_CMD_WRITE_ | | |
225 | ((ulong) address))); | |
226 | ||
227 | while ((timeout > 0) && (smc911x_reg_read(E2P_CMD) & E2P_CMD_EPC_BUSY_)) { | |
228 | udelay(10); | |
229 | timeout--; | |
230 | } | |
231 | ||
232 | if (timeout == 0) { | |
233 | printf("Timeout[3]\n"); | |
234 | return 0; | |
235 | } | |
236 | ||
237 | return 1; | |
238 | } | |
239 | ||
240 | static int eeprom_erase_all(void) | |
241 | { | |
242 | ulong timeout = 100000; | |
243 | ||
244 | if (smc911x_reg_read(E2P_CMD) & E2P_CMD_EPC_BUSY_) { | |
245 | printf("%s: Busy at start\n", __func__); | |
246 | return 0; | |
247 | } | |
248 | ||
249 | smc911x_reg_write(E2P_CMD, (E2P_CMD_EPC_BUSY_ | E2P_CMD_EPC_CMD_ERAL_)); | |
250 | ||
251 | while ((timeout > 0) && (smc911x_reg_read(E2P_CMD) & E2P_CMD_EPC_BUSY_)) { | |
252 | udelay(10); | |
253 | timeout--; | |
254 | } | |
255 | ||
256 | if (timeout == 0) { | |
257 | printf("Timeout[4]\n"); | |
258 | return 0; | |
259 | } | |
260 | ||
261 | return 1; | |
262 | } | |
263 | ||
264 | static int eeprom_reload(void) | |
265 | { | |
266 | ulong timeout = 100000; | |
267 | ||
268 | if (smc911x_reg_read(E2P_CMD) & E2P_CMD_EPC_BUSY_) { | |
269 | printf("%s: Busy at start\n", __func__); | |
270 | return -1; | |
271 | } | |
272 | smc911x_reg_write(E2P_CMD, | |
273 | (E2P_CMD_EPC_BUSY_ | E2P_CMD_EPC_CMD_RELOAD_)); | |
274 | ||
275 | while ((timeout > 0) && (smc911x_reg_read(E2P_CMD) & E2P_CMD_EPC_BUSY_)) { | |
276 | udelay(10); | |
277 | timeout--; | |
278 | } | |
279 | ||
280 | if (timeout == 0) | |
281 | return 0; | |
282 | ||
283 | return 1; | |
284 | } | |
285 | ||
286 | static int eeprom_save_mac_address(ulong dwHi16, ulong dwLo32) | |
287 | { | |
288 | int result = 0; | |
289 | ||
290 | debug("%s: dwHI: 0x%08lx dwLO: %08lx, \n", __func__, dwHi16, dwLo32); | |
291 | ||
292 | if (!eeprom_enable_erase_and_write()) | |
293 | goto DONE; | |
294 | if (!eeprom_erase_all()) | |
295 | goto DONE; | |
296 | if (!eeprom_write_location(0, 0xA5)) | |
297 | goto DONE; | |
298 | if (!eeprom_write_location(1, LOBYTE(LOWORD(dwLo32)))) | |
299 | goto DONE; | |
300 | if (!eeprom_write_location(2, HIBYTE(LOWORD(dwLo32)))) | |
301 | goto DONE; | |
302 | if (!eeprom_write_location(3, LOBYTE(HIWORD(dwLo32)))) | |
303 | goto DONE; | |
304 | if (!eeprom_write_location(4, HIBYTE(HIWORD(dwLo32)))) | |
305 | goto DONE; | |
306 | if (!eeprom_write_location(5, LOBYTE(LOWORD(dwHi16)))) | |
307 | goto DONE; | |
308 | if (!eeprom_write_location(6, HIBYTE(LOWORD(dwHi16)))) | |
309 | goto DONE; | |
310 | if (!eeprom_disable_erase_and_write()) | |
311 | goto DONE; | |
312 | ||
313 | result = 1; | |
314 | ||
315 | DONE: | |
316 | return result; | |
317 | } | |
318 | ||
319 | static int do_eeprom_dump(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) | |
320 | { | |
321 | unchar data = 0, index = 0; | |
322 | ulong gpio_old_val; | |
323 | ||
324 | gpio_old_val = eeprom_enable_access(); | |
325 | ||
326 | printf("EEPROM content: \n"); | |
327 | for (index = 0; index < 8; index++) { | |
328 | if (eeprom_read_location(index, &data)) | |
329 | printf("%02x ", data); | |
330 | else | |
331 | printf("FAILED"); | |
332 | } | |
333 | ||
334 | eeprom_disable_access(gpio_old_val); | |
335 | printf("\n"); | |
336 | ||
337 | return 0; | |
338 | } | |
339 | ||
340 | static int do_eeprom_erase_all(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) | |
341 | { | |
342 | eeprom_erase_all(); | |
343 | ||
344 | return 0; | |
345 | } | |
346 | ||
347 | static int do_eeprom_save_mac(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) | |
348 | { | |
349 | ulong hi16, lo32; | |
350 | unchar ethaddr[6], i; | |
351 | ulong gpio; | |
352 | char *tmp, *end; | |
353 | ||
354 | tmp = argv[1]; | |
355 | for (i = 0; i < 6; i++) { | |
356 | ethaddr[i] = tmp ? simple_strtoul(tmp, &end, 16) : 0; | |
357 | if (tmp) | |
358 | tmp = (*end) ? end + 1 : end; | |
359 | } | |
360 | ||
361 | hi16 = (ethaddr[5] << 8) | (ethaddr[4]); | |
362 | lo32 = (ethaddr[3] << 24) | (ethaddr[2] << 16) | | |
363 | (ethaddr[1] << 8) | (ethaddr[0]); | |
364 | ||
365 | gpio = eeprom_enable_access(); | |
366 | ||
367 | eeprom_save_mac_address(hi16, lo32); | |
368 | ||
369 | eeprom_reload(); | |
370 | ||
371 | /* Check new values */ | |
372 | if (eeprom_is_mac_address_loaded()) { | |
373 | ulong mac_hi16, mac_lo32; | |
374 | ||
375 | mac_hi16 = get_mac_reg(MAC_ADDRH); | |
376 | mac_lo32 = get_mac_reg(MAC_ADDRL); | |
377 | printf("New MAC address: %lx, %lx\n", mac_hi16, mac_lo32); | |
378 | } else { | |
379 | printf("Address is not reloaded \n"); | |
380 | } | |
381 | eeprom_disable_access(gpio); | |
382 | ||
383 | return 0; | |
384 | } | |
385 | ||
386 | U_BOOT_CMD(smcee, 1, 0, do_eeprom_erase_all, | |
a89c33db | 387 | "smcee - Erase content of SMC EEPROM",); |
ae691e57 SR |
388 | |
389 | U_BOOT_CMD(smced, 1, 0, do_eeprom_dump, | |
a89c33db | 390 | "smced - Dump content of SMC EEPROM",); |
ae691e57 SR |
391 | |
392 | U_BOOT_CMD(smcew, 2, 0, do_eeprom_save_mac, | |
393 | "smcew - Write MAC address to SMC EEPROM\n", | |
a89c33db | 394 | "aa:bb:cc:dd:ee:ff new mac address"); |