blob: b5a552134e799aaac1b09b56250bfdac83b876e5 [file] [log] [blame]
Stefan Roeseae691e52009-01-21 17:24:49 +01001/*
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
71static 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
81done:
82 return 0; /* No timeout */
83}
84
85static 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
104done:
105 return (reg_val);
106}
107
108static 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
120static 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
126static 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
136static 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
165static 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
188static 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
211static 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
240static 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
264static 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
286static 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
315DONE:
316 return result;
317}
318
Wolfgang Denk54841ab2010-06-28 22:00:46 +0200319static int do_eeprom_dump(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
Stefan Roeseae691e52009-01-21 17:24:49 +0100320{
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
Wolfgang Denk54841ab2010-06-28 22:00:46 +0200340static int do_eeprom_erase_all(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
Stefan Roeseae691e52009-01-21 17:24:49 +0100341{
342 eeprom_erase_all();
343
344 return 0;
345}
346
Wolfgang Denk54841ab2010-06-28 22:00:46 +0200347static int do_eeprom_save_mac(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
Stefan Roeseae691e52009-01-21 17:24:49 +0100348{
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
386U_BOOT_CMD(smcee, 1, 0, do_eeprom_erase_all,
Wolfgang Denka89c33d2009-05-24 17:06:54 +0200387 "smcee - Erase content of SMC EEPROM",);
Stefan Roeseae691e52009-01-21 17:24:49 +0100388
389U_BOOT_CMD(smced, 1, 0, do_eeprom_dump,
Wolfgang Denka89c33d2009-05-24 17:06:54 +0200390 "smced - Dump content of SMC EEPROM",);
Stefan Roeseae691e52009-01-21 17:24:49 +0100391
392U_BOOT_CMD(smcew, 2, 0, do_eeprom_save_mac,
393 "smcew - Write MAC address to SMC EEPROM\n",
Wolfgang Denka89c33d2009-05-24 17:06:54 +0200394 "aa:bb:cc:dd:ee:ff new mac address");