]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - board/micronas/vct/smc_eeprom.c
Make sure that argv[] argument pointers are not modified.
[karo-tx-uboot.git] / board / micronas / vct / smc_eeprom.c
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 * const 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 * const 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 * const 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,
387            "smcee   - Erase content of SMC EEPROM",);
388
389 U_BOOT_CMD(smced, 1, 0, do_eeprom_dump,
390            "smced   - Dump content of SMC EEPROM",);
391
392 U_BOOT_CMD(smcew, 2, 0, do_eeprom_save_mac,
393            "smcew   - Write MAC address to SMC EEPROM\n",
394            "aa:bb:cc:dd:ee:ff  new mac address");