]>
Commit | Line | Data |
---|---|---|
f7264c36 HS |
1 | /* |
2 | * (C) Copyright 2011 | |
3 | * Heiko Schocher, DENX Software Engineering, hs@denx.de. | |
4 | * | |
5 | * Based on: | |
6 | * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/ | |
7 | * | |
8 | * Based on da830evm.c. Original Copyrights follow: | |
9 | * | |
10 | * Copyright (C) 2009 Nick Thompson, GE Fanuc, Ltd. <nick.thompson@gefanuc.com> | |
11 | * Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net> | |
12 | * | |
1a459660 | 13 | * SPDX-License-Identifier: GPL-2.0+ |
f7264c36 HS |
14 | */ |
15 | ||
16 | #include <common.h> | |
17 | #include <command.h> | |
18 | #include <environment.h> | |
19 | #include <hwconfig.h> | |
20 | #include <i2c.h> | |
21 | #include <malloc.h> | |
22 | #include <miiphy.h> | |
23 | #include <mmc.h> | |
24 | #include <net.h> | |
25 | #include <netdev.h> | |
14b9f16c HS |
26 | #include <spi.h> |
27 | #include <linux/ctype.h> | |
f7264c36 HS |
28 | #include <asm/gpio.h> |
29 | #include <asm/io.h> | |
30 | #include <asm/arch/da850_lowlevel.h> | |
31 | #include <asm/arch/davinci_misc.h> | |
32 | #include <asm/arch/emif_defs.h> | |
33 | #include <asm/arch/emac_defs.h> | |
34 | #include <asm/arch/gpio.h> | |
35 | #include <asm/arch/pinmux_defs.h> | |
36 | #include <asm/arch/hardware.h> | |
37 | #include <asm/arch/sdmmc_defs.h> | |
38 | #include <asm/arch/timer_defs.h> | |
39 | ||
40 | DECLARE_GLOBAL_DATA_PTR; | |
41 | ||
6b873dca | 42 | const struct lpsc_resource lpsc[] = { |
f7264c36 HS |
43 | { DAVINCI_LPSC_AEMIF }, |
44 | { DAVINCI_LPSC_SPI1 }, | |
45 | { DAVINCI_LPSC_ARM_RAM_ROM }, | |
46 | { DAVINCI_LPSC_UART0 }, | |
47 | { DAVINCI_LPSC_EMAC }, | |
48 | { DAVINCI_LPSC_UART0 }, | |
49 | { DAVINCI_LPSC_GPIO }, | |
50 | { DAVINCI_LPSC_DDR_EMIF }, | |
51 | { DAVINCI_LPSC_UART1 }, | |
52 | { DAVINCI_LPSC_UART2 }, | |
53 | { DAVINCI_LPSC_MMC_SD1 }, | |
54 | { DAVINCI_LPSC_USB20 }, | |
55 | { DAVINCI_LPSC_USB11 }, | |
56 | }; | |
57 | ||
6b873dca SG |
58 | const int lpsc_size = ARRAY_SIZE(lpsc); |
59 | ||
f7264c36 HS |
60 | static const struct pinmux_config enbw_pins[] = { |
61 | { pinmux(0), 8, 0 }, | |
62 | { pinmux(0), 8, 1 }, | |
63 | { pinmux(0), 8, 2 }, | |
64 | { pinmux(0), 8, 3 }, | |
65 | { pinmux(0), 8, 4 }, | |
66 | { pinmux(0), 8, 5 }, | |
67 | { pinmux(1), 4, 0 }, | |
68 | { pinmux(1), 8, 1 }, | |
69 | { pinmux(1), 8, 2 }, | |
70 | { pinmux(1), 8, 3 }, | |
71 | { pinmux(1), 8, 4 }, | |
72 | { pinmux(1), 8, 5 }, | |
73 | { pinmux(1), 8, 6 }, | |
74 | { pinmux(1), 4, 7 }, | |
75 | { pinmux(2), 8, 0 }, | |
76 | { pinmux(5), 1, 0 }, | |
77 | { pinmux(5), 1, 3 }, | |
78 | { pinmux(5), 1, 7 }, | |
14b9f16c HS |
79 | { pinmux(5), 1, 5 }, |
80 | { pinmux(5), 1, 4 }, | |
81 | { pinmux(5), 1, 3 }, | |
82 | { pinmux(5), 1, 2 }, | |
83 | { pinmux(5), 1, 1 }, | |
84 | { pinmux(5), 1, 0 }, | |
85 | { pinmux(6), 8, 0 }, | |
86 | { pinmux(6), 8, 1 }, | |
f7264c36 HS |
87 | { pinmux(6), 8, 2 }, |
88 | { pinmux(6), 8, 3 }, | |
14b9f16c | 89 | { pinmux(6), 8, 4 }, |
f7264c36 HS |
90 | { pinmux(6), 8, 5 }, |
91 | { pinmux(6), 1, 7 }, | |
92 | { pinmux(7), 8, 2 }, | |
93 | { pinmux(7), 1, 3 }, | |
14b9f16c | 94 | { pinmux(7), 8, 6 }, |
f7264c36 HS |
95 | { pinmux(7), 1, 7 }, |
96 | { pinmux(13), 8, 2 }, | |
97 | { pinmux(13), 8, 3 }, | |
98 | { pinmux(13), 8, 4 }, | |
99 | { pinmux(13), 8, 5 }, | |
100 | { pinmux(13), 8, 6 }, | |
101 | { pinmux(13), 8, 7 }, | |
102 | { pinmux(14), 8, 0 }, | |
103 | { pinmux(14), 8, 1 }, | |
104 | { pinmux(16), 8, 1 }, | |
105 | { pinmux(16), 8, 2 }, | |
106 | { pinmux(16), 8, 3 }, | |
107 | { pinmux(16), 8, 4 }, | |
108 | { pinmux(16), 8, 5 }, | |
109 | { pinmux(16), 8, 6 }, | |
110 | { pinmux(16), 8, 7 }, | |
111 | { pinmux(17), 1, 0 }, | |
112 | { pinmux(17), 1, 1 }, | |
113 | { pinmux(17), 1, 2 }, | |
114 | { pinmux(17), 8, 3 }, | |
115 | { pinmux(17), 8, 4 }, | |
116 | { pinmux(17), 8, 5 }, | |
117 | { pinmux(17), 8, 6 }, | |
118 | { pinmux(17), 8, 7 }, | |
119 | { pinmux(18), 8, 0 }, | |
120 | { pinmux(18), 8, 1 }, | |
121 | { pinmux(18), 2, 2 }, | |
122 | { pinmux(18), 2, 3 }, | |
123 | { pinmux(18), 2, 4 }, | |
124 | { pinmux(18), 8, 6 }, | |
125 | { pinmux(18), 8, 7 }, | |
126 | { pinmux(19), 8, 0 }, | |
127 | { pinmux(19), 2, 1 }, | |
128 | { pinmux(19), 2, 2 }, | |
129 | { pinmux(19), 2, 3 }, | |
130 | { pinmux(19), 2, 4 }, | |
131 | { pinmux(19), 8, 5 }, | |
132 | { pinmux(19), 8, 6 }, | |
133 | }; | |
134 | ||
135 | const struct pinmux_resource pinmuxes[] = { | |
136 | PINMUX_ITEM(emac_pins_mii), | |
137 | PINMUX_ITEM(emac_pins_mdio), | |
138 | PINMUX_ITEM(i2c0_pins), | |
139 | PINMUX_ITEM(emifa_pins_cs2), | |
140 | PINMUX_ITEM(emifa_pins_cs3), | |
141 | PINMUX_ITEM(emifa_pins_cs4), | |
142 | PINMUX_ITEM(emifa_pins_nand), | |
143 | PINMUX_ITEM(emifa_pins_nor), | |
144 | PINMUX_ITEM(spi1_pins_base), | |
145 | PINMUX_ITEM(spi1_pins_scs0), | |
146 | PINMUX_ITEM(uart1_pins_txrx), | |
147 | PINMUX_ITEM(uart2_pins_txrx), | |
148 | PINMUX_ITEM(uart2_pins_rtscts), | |
149 | PINMUX_ITEM(enbw_pins), | |
150 | }; | |
151 | ||
152 | const int pinmuxes_size = ARRAY_SIZE(pinmuxes); | |
153 | ||
154 | struct gpio_config { | |
155 | char name[GPIO_NAME_SIZE]; | |
156 | unsigned char bank; | |
157 | unsigned char gpio; | |
158 | unsigned char out; | |
159 | unsigned char value; | |
160 | }; | |
161 | ||
14b9f16c HS |
162 | static const struct gpio_config enbw_gpio_config_hut[] = { |
163 | { "RS485 enable", 8, 11, 1, 0 }, | |
164 | { "RS485 iso", 8, 10, 1, 1 }, | |
165 | { "W2HUT RS485 Rx ena", 8, 9, 1, 0 }, | |
166 | { "W2HUT RS485 iso", 8, 8, 1, 1 }, | |
167 | }; | |
168 | ||
169 | static const struct gpio_config enbw_gpio_config_w[] = { | |
f7264c36 HS |
170 | { "RS485 enable", 8, 11, 1, 0 }, |
171 | { "RS485 iso", 8, 10, 1, 0 }, | |
172 | { "W2HUT RS485 Rx ena", 8, 9, 1, 0 }, | |
173 | { "W2HUT RS485 iso", 8, 8, 1, 0 }, | |
14b9f16c HS |
174 | }; |
175 | ||
176 | static const struct gpio_config enbw_gpio_config[] = { | |
f7264c36 HS |
177 | { "LAN reset", 7, 15, 1, 1 }, |
178 | { "ena 11V PLC", 7, 14, 1, 0 }, | |
179 | { "ena 1.5V PLC", 7, 13, 1, 0 }, | |
180 | { "disable VBUS", 7, 12, 1, 1 }, | |
14b9f16c | 181 | { "PLC reset", 6, 13, 1, 0 }, |
f7264c36 HS |
182 | { "LCM RS", 6, 12, 1, 0 }, |
183 | { "LCM R/W", 6, 11, 1, 0 }, | |
184 | { "PLC pairing", 6, 10, 1, 1 }, | |
185 | { "PLC MDIO CLK", 6, 9, 1, 0 }, | |
186 | { "HK218", 6, 8, 1, 0 }, | |
187 | { "HK218 Rx", 6, 1, 1, 1 }, | |
14b9f16c HS |
188 | { "TPM reset", 6, 0, 1, 0 }, |
189 | { "Board-Type", 3, 9, 0, 0 }, | |
190 | { "HW-ID0", 2, 7, 0, 0 }, | |
191 | { "HW-ID1", 2, 6, 0, 0 }, | |
192 | { "HW-ID2", 2, 3, 0, 0 }, | |
f7264c36 HS |
193 | { "PV-IF RxD ena", 0, 15, 1, 1 }, |
194 | { "LED1", 1, 15, 1, 1 }, | |
195 | { "LED2", 0, 1, 1, 1 }, | |
196 | { "LED3", 0, 2, 1, 1 }, | |
197 | { "LED4", 0, 3, 1, 1 }, | |
198 | { "LED5", 0, 4, 1, 1 }, | |
199 | { "LED6", 0, 5, 1, 0 }, | |
200 | { "LED7", 0, 6, 1, 0 }, | |
201 | { "LED8", 0, 14, 1, 0 }, | |
202 | { "USER1", 0, 12, 0, 0 }, | |
203 | { "USER2", 0, 13, 0, 0 }, | |
204 | }; | |
205 | ||
206 | #define PHY_POWER 0x0800 | |
207 | ||
208 | static void enbw_cmc_switch(int port, int on) | |
209 | { | |
210 | const char *devname; | |
211 | unsigned char phyaddr = 3; | |
212 | unsigned char reg = 0; | |
213 | unsigned short data; | |
214 | ||
215 | if (port == 1) | |
216 | phyaddr = 2; | |
217 | ||
218 | devname = miiphy_get_current_dev(); | |
219 | if (!devname) { | |
220 | printf("Error: no mii device\n"); | |
221 | return; | |
222 | } | |
223 | if (miiphy_read(devname, phyaddr, reg, &data) != 0) { | |
224 | printf("Error reading from the PHY addr=%02x reg=%02x\n", | |
225 | phyaddr, reg); | |
226 | return; | |
227 | } | |
228 | ||
229 | if (on) | |
230 | data &= ~PHY_POWER; | |
231 | else | |
232 | data |= PHY_POWER; | |
233 | ||
234 | if (miiphy_write(devname, phyaddr, reg, data) != 0) { | |
235 | printf("Error writing to the PHY addr=%02x reg=%02x\n", | |
236 | phyaddr, reg); | |
237 | return; | |
238 | } | |
239 | } | |
240 | ||
14b9f16c | 241 | static int enbw_cmc_init_gpio(const struct gpio_config *conf, int sz) |
f7264c36 HS |
242 | { |
243 | int i, ret; | |
244 | ||
14b9f16c HS |
245 | for (i = 0; i < sz; i++) { |
246 | int gpio = conf[i].bank * 16 + | |
247 | conf[i].gpio; | |
f7264c36 | 248 | |
14b9f16c | 249 | ret = gpio_request(gpio, conf[i].name); |
f7264c36 HS |
250 | if (ret) { |
251 | printf("%s: Could not get %s gpio\n", __func__, | |
14b9f16c HS |
252 | conf[i].name); |
253 | return ret; | |
f7264c36 HS |
254 | } |
255 | ||
14b9f16c | 256 | if (conf[i].out) |
f7264c36 | 257 | gpio_direction_output(gpio, |
14b9f16c | 258 | conf[i].value); |
f7264c36 HS |
259 | else |
260 | gpio_direction_input(gpio); | |
261 | } | |
262 | ||
14b9f16c HS |
263 | return 0; |
264 | } | |
265 | ||
266 | int board_init(void) | |
267 | { | |
268 | int board_type, hw_id; | |
269 | ||
270 | #ifndef CONFIG_USE_IRQ | |
271 | irq_init(); | |
272 | #endif | |
273 | /* address of boot parameters, not used as booting with DTT */ | |
274 | gd->bd->bi_boot_params = 0; | |
275 | ||
276 | enbw_cmc_init_gpio(enbw_gpio_config, ARRAY_SIZE(enbw_gpio_config)); | |
277 | ||
278 | /* detect HW version */ | |
279 | board_type = gpio_get_value(CONFIG_ENBW_CMC_BOARD_TYPE); | |
280 | hw_id = gpio_get_value(CONFIG_ENBW_CMC_HW_ID_BIT0) + | |
281 | (gpio_get_value(CONFIG_ENBW_CMC_HW_ID_BIT1) << 1) + | |
282 | (gpio_get_value(CONFIG_ENBW_CMC_HW_ID_BIT2) << 2); | |
283 | printf("BOARD: CMC-%s hw id: %d\n", (board_type ? "w2" : "hut"), | |
284 | hw_id); | |
285 | if (board_type) | |
286 | enbw_cmc_init_gpio(enbw_gpio_config_w, | |
287 | ARRAY_SIZE(enbw_gpio_config_w)); | |
288 | else | |
289 | enbw_cmc_init_gpio(enbw_gpio_config_hut, | |
290 | ARRAY_SIZE(enbw_gpio_config_hut)); | |
291 | ||
f7264c36 HS |
292 | /* setup the SUSPSRC for ARM to control emulation suspend */ |
293 | clrbits_le32(&davinci_syscfg_regs->suspsrc, | |
294 | (DAVINCI_SYSCFG_SUSPSRC_EMAC | DAVINCI_SYSCFG_SUSPSRC_I2C | | |
295 | DAVINCI_SYSCFG_SUSPSRC_SPI1 | DAVINCI_SYSCFG_SUSPSRC_TIMER0 | | |
296 | DAVINCI_SYSCFG_SUSPSRC_UART2)); | |
297 | ||
298 | return 0; | |
299 | } | |
300 | ||
301 | #ifdef CONFIG_DRIVER_TI_EMAC | |
14b9f16c HS |
302 | |
303 | #define KSZ_CMD_READ 0x03 | |
304 | #define KSZ_CMD_WRITE 0x02 | |
305 | #define KSZ_ID 0x95 | |
306 | ||
307 | static int enbw_cmc_switch_read(struct spi_slave *spi, u8 reg, u8 *val) | |
308 | { | |
309 | unsigned long flags = SPI_XFER_BEGIN; | |
310 | int ret; | |
311 | int cmd_len; | |
312 | u8 cmd[2]; | |
313 | ||
314 | cmd[0] = KSZ_CMD_READ; | |
315 | cmd[1] = reg; | |
316 | cmd_len = 2; | |
317 | ||
318 | ret = spi_xfer(spi, cmd_len * 8, cmd, NULL, flags); | |
319 | if (ret) { | |
320 | debug("Failed to send command (%zu bytes): %d\n", | |
321 | cmd_len, ret); | |
322 | return -EINVAL; | |
323 | } | |
324 | flags |= SPI_XFER_END; | |
325 | *val = 0; | |
326 | cmd_len = 1; | |
327 | ret = spi_xfer(spi, cmd_len * 8, NULL, val, flags); | |
328 | if (ret) { | |
329 | debug("Failed to read (%zu bytes): %d\n", | |
330 | cmd_len, ret); | |
331 | return -EINVAL; | |
332 | } | |
333 | ||
334 | return 0; | |
335 | } | |
336 | ||
337 | static int enbw_cmc_switch_read_ident(struct spi_slave *spi) | |
338 | { | |
339 | int ret; | |
340 | u8 val; | |
341 | ||
342 | ret = enbw_cmc_switch_read(spi, 0, &val); | |
343 | if (ret) { | |
344 | debug("Failed to read\n"); | |
345 | return -EINVAL; | |
346 | } | |
347 | ||
348 | if (val != KSZ_ID) | |
349 | return -EINVAL; | |
350 | ||
351 | return 0; | |
352 | } | |
353 | ||
354 | static int enbw_cmc_switch_write(struct spi_slave *spi, unsigned long reg, | |
355 | unsigned long val) | |
356 | { | |
357 | unsigned long flags = SPI_XFER_BEGIN; | |
358 | int ret; | |
359 | int cmd_len; | |
360 | u8 cmd[3]; | |
361 | ||
362 | cmd[0] = KSZ_CMD_WRITE; | |
363 | cmd[1] = reg; | |
364 | cmd[2] = val; | |
365 | cmd_len = 3; | |
366 | flags |= SPI_XFER_END; | |
367 | ||
368 | ret = spi_xfer(spi, cmd_len * 8, cmd, NULL, flags); | |
369 | if (ret) { | |
370 | debug("Failed to send command (%zu bytes): %d\n", | |
371 | cmd_len, ret); | |
372 | return -EINVAL; | |
373 | } | |
374 | ||
375 | udelay(1000); | |
376 | ret = enbw_cmc_switch_read(spi, reg, &cmd[0]); | |
377 | if (ret) { | |
378 | debug("Failed to read\n"); | |
379 | return -EINVAL; | |
380 | } | |
381 | if (val != cmd[0]) | |
382 | debug("warning: reg: %lx va: %x soll: %lx\n", | |
383 | reg, cmd[0], val); | |
384 | ||
385 | return 0; | |
386 | } | |
387 | ||
388 | static int enbw_cmc_eof(unsigned char *ptr) | |
389 | { | |
390 | if (*ptr == 0xff) | |
391 | return 1; | |
392 | ||
393 | return 0; | |
394 | } | |
395 | ||
396 | static char *enbw_cmc_getnewline(char *ptr) | |
397 | { | |
398 | while (*ptr != 0x0a) { | |
399 | ptr++; | |
400 | if (enbw_cmc_eof((unsigned char *)ptr)) | |
401 | return NULL; | |
402 | } | |
403 | ||
404 | ptr++; | |
405 | return ptr; | |
406 | } | |
407 | ||
408 | static char *enbw_cmc_getvalue(char *ptr, int *value) | |
409 | { | |
410 | int end = 0; | |
411 | ||
412 | *value = -EINVAL; | |
413 | ||
414 | if (!isxdigit(*ptr)) | |
415 | end = 1; | |
416 | ||
417 | while (end) { | |
418 | if ((*ptr == '#') || (*ptr == ';')) { | |
419 | ptr = enbw_cmc_getnewline(ptr); | |
420 | return ptr; | |
421 | } | |
422 | if (ptr != NULL) { | |
423 | if (isxdigit(*ptr)) { | |
424 | end = 0; | |
425 | } else if (*ptr == 0x0a) { | |
426 | ptr++; | |
427 | return ptr; | |
428 | } else { | |
429 | ptr++; | |
430 | if (enbw_cmc_eof((unsigned char *)ptr)) | |
431 | return NULL; | |
432 | } | |
433 | } else { | |
434 | return NULL; | |
435 | } | |
436 | } | |
437 | *value = (int)simple_strtoul((const char *)ptr, &ptr, 16); | |
438 | ptr++; | |
439 | return ptr; | |
440 | } | |
441 | ||
1bb0946b | 442 | static struct spi_slave *enbw_cmc_init_spi(void) |
14b9f16c HS |
443 | { |
444 | struct spi_slave *spi; | |
14b9f16c | 445 | int ret; |
14b9f16c | 446 | |
1bb0946b | 447 | spi = spi_setup_slave(0, 0, 1000000, 0); |
14b9f16c HS |
448 | if (!spi) { |
449 | printf("Failed to set up slave\n"); | |
1bb0946b | 450 | return NULL; |
14b9f16c HS |
451 | } |
452 | ||
453 | ret = spi_claim_bus(spi); | |
454 | if (ret) { | |
455 | debug("Failed to claim SPI bus: %d\n", ret); | |
456 | goto err_claim_bus; | |
457 | } | |
458 | ||
459 | ret = enbw_cmc_switch_read_ident(spi); | |
460 | if (ret) | |
1bb0946b HS |
461 | goto err_read; |
462 | ||
463 | return spi; | |
464 | err_read: | |
465 | spi_release_bus(spi); | |
466 | err_claim_bus: | |
467 | spi_free_slave(spi); | |
468 | return NULL; | |
469 | } | |
470 | ||
471 | static int enbw_cmc_config_switch(unsigned long addr) | |
472 | { | |
473 | struct spi_slave *spi; | |
474 | char *ptr = (char *)addr; | |
475 | int value, reg; | |
476 | int ret = 0; | |
477 | ||
478 | debug("configure switch with file on addr: 0x%lx\n", addr); | |
479 | ||
480 | spi = enbw_cmc_init_spi(); | |
481 | if (!spi) | |
482 | return -EINVAL; | |
14b9f16c | 483 | |
14b9f16c HS |
484 | while (ptr != NULL) { |
485 | ptr = enbw_cmc_getvalue(ptr, ®); | |
486 | if (ptr != NULL) { | |
487 | ptr = enbw_cmc_getvalue(ptr, &value); | |
488 | if ((ptr != NULL) && (value >= 0)) | |
1bb0946b HS |
489 | if (enbw_cmc_switch_write(spi, reg, value)) { |
490 | /* error writing to switch */ | |
491 | ptr = NULL; | |
492 | ret = -EINVAL; | |
493 | } | |
14b9f16c HS |
494 | } |
495 | } | |
14b9f16c | 496 | |
14b9f16c | 497 | spi_release_bus(spi); |
14b9f16c | 498 | spi_free_slave(spi); |
1bb0946b | 499 | return ret; |
14b9f16c HS |
500 | } |
501 | ||
502 | static int do_switch(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) | |
503 | { | |
504 | unsigned long addr; | |
505 | ||
506 | if (argc < 2) | |
507 | return cmd_usage(cmdtp); | |
508 | ||
509 | addr = simple_strtoul(argv[1], NULL, 16); | |
510 | enbw_cmc_config_switch(addr); | |
511 | ||
512 | return 0; | |
513 | } | |
514 | ||
515 | U_BOOT_CMD(switch, 3, 1, do_switch, | |
516 | "switch addr", | |
517 | "[addr]" | |
518 | ); | |
519 | ||
f7264c36 HS |
520 | /* |
521 | * Initializes on-board ethernet controllers. | |
522 | */ | |
523 | int board_eth_init(bd_t *bis) | |
524 | { | |
1bb0946b | 525 | struct spi_slave *spi; |
14b9f16c | 526 | const char *s; |
1bb0946b HS |
527 | size_t len = 0; |
528 | int config = 1; | |
14b9f16c | 529 | |
f7264c36 | 530 | davinci_emac_mii_mode_sel(0); |
14b9f16c HS |
531 | |
532 | /* send a config file to the switch */ | |
533 | s = hwconfig_subarg("switch", "config", &len); | |
534 | if (len) { | |
535 | unsigned long addr = simple_strtoul(s, NULL, 16); | |
536 | ||
1bb0946b | 537 | config = enbw_cmc_config_switch(addr); |
14b9f16c | 538 | } |
f7264c36 | 539 | |
1bb0946b HS |
540 | if (config) { |
541 | /* | |
542 | * no valid config file -> do we have some args in | |
543 | * hwconfig ? | |
544 | */ | |
545 | if ((hwconfig_subarg("switch", "lan", &len)) || | |
546 | (hwconfig_subarg("switch", "lmn", &len))) { | |
547 | /* If so start switch */ | |
548 | spi = enbw_cmc_init_spi(); | |
549 | if (spi) { | |
550 | if (enbw_cmc_switch_write(spi, 1, 0)) | |
551 | config = 0; | |
552 | udelay(10000); | |
553 | if (enbw_cmc_switch_write(spi, 1, 1)) | |
554 | config = 0; | |
555 | spi_release_bus(spi); | |
556 | spi_free_slave(spi); | |
557 | } | |
558 | } else { | |
559 | config = 0; | |
560 | } | |
561 | } | |
f7264c36 HS |
562 | if (!davinci_emac_initialize()) { |
563 | printf("Error: Ethernet init failed!\n"); | |
564 | return -1; | |
565 | } | |
566 | ||
1bb0946b HS |
567 | if (config) { |
568 | if (hwconfig_subarg_cmp("switch", "lan", "on")) | |
569 | /* Switch port lan on */ | |
570 | enbw_cmc_switch(1, 1); | |
571 | else | |
572 | enbw_cmc_switch(1, 0); | |
f7264c36 | 573 | |
1bb0946b HS |
574 | if (hwconfig_subarg_cmp("switch", "lmn", "on")) |
575 | /* Switch port pwl on */ | |
576 | enbw_cmc_switch(2, 1); | |
577 | else | |
578 | enbw_cmc_switch(2, 0); | |
579 | } | |
f7264c36 HS |
580 | |
581 | return 0; | |
582 | } | |
583 | #endif /* CONFIG_DRIVER_TI_EMAC */ | |
584 | ||
585 | #ifdef CONFIG_PREBOOT | |
586 | static uchar kbd_magic_prefix[] = "key_magic_"; | |
587 | static uchar kbd_command_prefix[] = "key_cmd_"; | |
588 | ||
589 | struct kbd_data_t { | |
590 | char s1; | |
591 | }; | |
592 | ||
593 | struct kbd_data_t *get_keys(struct kbd_data_t *kbd_data) | |
594 | { | |
595 | /* read SW1 + SW2 */ | |
596 | kbd_data->s1 = gpio_get_value(12) + | |
597 | (gpio_get_value(13) << 1); | |
598 | return kbd_data; | |
599 | } | |
600 | ||
601 | static int compare_magic(const struct kbd_data_t *kbd_data, char *str) | |
602 | { | |
603 | char s1 = str[0]; | |
604 | ||
605 | if (s1 >= '0' && s1 <= '9') | |
606 | s1 -= '0'; | |
607 | else if (s1 >= 'a' && s1 <= 'f') | |
608 | s1 = s1 - 'a' + 10; | |
609 | else if (s1 >= 'A' && s1 <= 'F') | |
610 | s1 = s1 - 'A' + 10; | |
611 | else | |
612 | return -1; | |
613 | ||
614 | if (s1 != kbd_data->s1) | |
615 | return -1; | |
616 | ||
617 | return 0; | |
618 | } | |
619 | ||
620 | static char *key_match(const struct kbd_data_t *kbd_data) | |
621 | { | |
622 | char magic[sizeof(kbd_magic_prefix) + 1]; | |
623 | char *suffix; | |
624 | char *kbd_magic_keys; | |
625 | ||
626 | /* | |
627 | * The following string defines the characters that can be appended | |
628 | * to "key_magic" to form the names of environment variables that | |
629 | * hold "magic" key codes, i. e. such key codes that can cause | |
630 | * pre-boot actions. If the string is empty (""), then only | |
631 | * "key_magic" is checked (old behaviour); the string "125" causes | |
632 | * checks for "key_magic1", "key_magic2" and "key_magic5", etc. | |
633 | */ | |
634 | kbd_magic_keys = getenv("magic_keys"); | |
635 | if (kbd_magic_keys == NULL) | |
636 | kbd_magic_keys = ""; | |
637 | ||
638 | /* | |
639 | * loop over all magic keys; | |
640 | * use '\0' suffix in case of empty string | |
641 | */ | |
642 | for (suffix = kbd_magic_keys; *suffix || | |
643 | suffix == kbd_magic_keys; ++suffix) { | |
644 | sprintf(magic, "%s%c", kbd_magic_prefix, *suffix); | |
645 | ||
646 | if (compare_magic(kbd_data, getenv(magic)) == 0) { | |
647 | char cmd_name[sizeof(kbd_command_prefix) + 1]; | |
648 | char *cmd; | |
649 | ||
650 | sprintf(cmd_name, "%s%c", kbd_command_prefix, *suffix); | |
651 | cmd = getenv(cmd_name); | |
652 | ||
653 | return cmd; | |
654 | } | |
655 | } | |
656 | ||
657 | return NULL; | |
658 | } | |
659 | #endif /* CONFIG_PREBOOT */ | |
660 | ||
661 | int misc_init_r(void) | |
662 | { | |
663 | char *s, buf[32]; | |
664 | #ifdef CONFIG_PREBOOT | |
665 | struct kbd_data_t kbd_data; | |
666 | /* Decode keys */ | |
667 | char *str = strdup(key_match(get_keys(&kbd_data))); | |
668 | /* Set or delete definition */ | |
669 | setenv("preboot", str); | |
670 | free(str); | |
671 | #endif /* CONFIG_PREBOOT */ | |
672 | ||
673 | /* count all restarts, and save this in an environment var */ | |
674 | s = getenv("restartcount"); | |
675 | ||
676 | if (s) | |
677 | sprintf(buf, "%ld", simple_strtoul(s, NULL, 10) + 1); | |
678 | else | |
679 | strcpy(buf, "1"); | |
680 | ||
681 | setenv("restartcount", buf); | |
682 | saveenv(); | |
683 | ||
684 | #ifdef CONFIG_HW_WATCHDOG | |
685 | davinci_hw_watchdog_enable(); | |
686 | #endif | |
687 | ||
688 | return 0; | |
689 | } | |
690 | ||
691 | struct cmc_led { | |
692 | char name[20]; | |
693 | unsigned char bank; | |
694 | unsigned char gpio; | |
695 | }; | |
696 | ||
697 | struct cmc_led led_table[] = { | |
698 | {"led1", 1, 15}, | |
699 | {"led2", 0, 1}, | |
700 | {"led3", 0, 2}, | |
701 | {"led4", 0, 3}, | |
702 | {"led5", 0, 4}, | |
703 | {"led6", 0, 5}, | |
704 | {"led7", 0, 6}, | |
705 | {"led8", 0, 14}, | |
706 | }; | |
707 | ||
708 | static int cmc_get_led_state(struct cmc_led *led) | |
709 | { | |
710 | int value; | |
711 | int gpio = led->bank * 16 + led->gpio; | |
712 | ||
713 | value = gpio_get_value(gpio); | |
714 | ||
715 | return value; | |
716 | } | |
717 | ||
718 | static int cmc_set_led_state(struct cmc_led *led, int state) | |
719 | { | |
720 | int gpio = led->bank * 16 + led->gpio; | |
721 | ||
722 | gpio_set_value(gpio, state); | |
723 | return 0; | |
724 | } | |
725 | ||
726 | static int do_led(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) | |
727 | { | |
728 | struct cmc_led *led; | |
729 | int found = 0; | |
730 | int i = 0; | |
731 | int only_print = 0; | |
732 | int len = ARRAY_SIZE(led_table); | |
733 | ||
734 | if (argc < 2) | |
735 | return cmd_usage(cmdtp); | |
736 | ||
737 | if (argc < 3) | |
738 | only_print = 1; | |
739 | ||
740 | led = led_table; | |
741 | while ((!found) && (i < len)) { | |
742 | if (strcmp(argv[1], led->name) == 0) { | |
743 | found = 1; | |
744 | } else { | |
745 | led++; | |
746 | i++; | |
747 | } | |
748 | } | |
749 | if (!found) | |
750 | return cmd_usage(cmdtp); | |
751 | ||
752 | if (only_print) { | |
753 | if (cmc_get_led_state(led)) | |
754 | printf("on\n"); | |
755 | else | |
756 | printf("off\n"); | |
757 | ||
758 | return 0; | |
759 | } | |
760 | if (strcmp(argv[2], "on") == 0) | |
761 | cmc_set_led_state(led, 1); | |
762 | else | |
763 | cmc_set_led_state(led, 0); | |
764 | ||
765 | return 0; | |
766 | } | |
767 | ||
768 | U_BOOT_CMD(led, 3, 1, do_led, | |
769 | "switch on/off board led", | |
770 | "[name] [on/off]" | |
771 | ); | |
772 | ||
773 | #ifdef CONFIG_HW_WATCHDOG | |
774 | void hw_watchdog_reset(void) | |
775 | { | |
776 | davinci_hw_watchdog_reset(); | |
777 | } | |
778 | #endif | |
779 | ||
780 | #if defined(CONFIG_POST) | |
781 | void arch_memory_failure_handle(void) | |
782 | { | |
783 | struct davinci_gpio *gpio = davinci_gpio_bank01; | |
784 | int state = 1; | |
785 | ||
786 | /* | |
787 | * if memor< failure blink with the LED 1,2 and 3 | |
788 | * as we running from flash, we cannot use the gpio | |
789 | * api here, so access the gpio pin direct through | |
790 | * the gpio register. | |
791 | */ | |
792 | while (1) { | |
793 | if (state) { | |
794 | clrbits_le32(&gpio->out_data, 0x80000006); | |
795 | state = 0; | |
796 | } else { | |
797 | setbits_le32(&gpio->out_data, 0x80000006); | |
798 | state = 1; | |
799 | } | |
800 | udelay(500); | |
801 | } | |
802 | } | |
803 | #endif | |
804 | ||
14b9f16c HS |
805 | ulong post_word_load(void) |
806 | { | |
807 | struct davinci_rtc *reg = | |
808 | (struct davinci_rtc *)CONFIG_SYS_POST_WORD_ADDR; | |
809 | ||
810 | return in_be32(®->scratch2); | |
811 | } | |
812 | ||
813 | void post_word_store(ulong value) | |
814 | { | |
815 | struct davinci_rtc *reg = | |
816 | (struct davinci_rtc *)CONFIG_SYS_POST_WORD_ADDR; | |
817 | ||
818 | /* | |
819 | * write RTC kick register to enable write | |
820 | * for RTC Scratch registers. Cratch0 and 1 are | |
821 | * used for bootcount values. | |
822 | */ | |
823 | writel(RTC_KICK0R_WE, ®->kick0r); | |
824 | writel(RTC_KICK1R_WE, ®->kick1r); | |
825 | out_be32(®->scratch2, value); | |
826 | } | |
827 | ||
f7264c36 HS |
828 | void board_gpio_init(void) |
829 | { | |
830 | struct davinci_gpio *gpio = davinci_gpio_bank01; | |
831 | ||
f7264c36 HS |
832 | /* |
833 | * set LED (gpio Interface not usable here) | |
834 | * set LED pins to output and state 0 | |
835 | */ | |
836 | clrbits_le32(&gpio->dir, 0x8000407e); | |
837 | clrbits_le32(&gpio->out_data, 0x8000407e); | |
838 | /* set LED 1 - 5 to state on */ | |
839 | setbits_le32(&gpio->out_data, 0x8000001e); | |
14b9f16c HS |
840 | |
841 | /* | |
842 | * set some gpio pins to low, this is needed early, | |
843 | * so we have no gpio Interface here | |
844 | * gpios: | |
845 | * 8[8] Mode PV select low | |
846 | * 8[9] Debug Rx Enable low | |
847 | * 8[10] Mode Select PV low | |
848 | * 8[11] Counter Interface RS485 Rx-Enable low | |
849 | */ | |
850 | gpio = davinci_gpio_bank8; | |
851 | clrbits_le32(&gpio->dir, 0x00000f00); | |
852 | clrbits_le32(&gpio->out_data, 0x0f00); | |
f7264c36 HS |
853 | } |
854 | ||
855 | int board_late_init(void) | |
856 | { | |
857 | cmc_set_led_state(&led_table[4], 0); | |
858 | ||
859 | return 0; | |
860 | } | |
861 | ||
862 | void show_boot_progress(int val) | |
863 | { | |
864 | switch (val) { | |
865 | case 1: | |
866 | cmc_set_led_state(&led_table[4], 1); | |
867 | break; | |
868 | case 4: | |
869 | cmc_set_led_state(&led_table[4], 0); | |
870 | break; | |
871 | case 15: | |
872 | cmc_set_led_state(&led_table[4], 1); | |
873 | break; | |
874 | } | |
875 | } | |
876 | ||
877 | #ifdef CONFIG_DAVINCI_MMC | |
878 | static struct davinci_mmc mmc_sd1 = { | |
879 | .reg_base = (struct davinci_mmc_regs *)DAVINCI_MMC_SD1_BASE, | |
880 | .input_clk = 228000000, | |
881 | .host_caps = MMC_MODE_4BIT, | |
882 | .voltages = MMC_VDD_32_33 | MMC_VDD_33_34, | |
883 | .version = MMC_CTLR_VERSION_2, | |
884 | }; | |
885 | ||
886 | int board_mmc_init(bd_t *bis) | |
887 | { | |
888 | mmc_sd1.input_clk = clk_get(DAVINCI_MMC_CLKID); | |
889 | /* Add slot-0 to mmc subsystem */ | |
890 | return davinci_mmc_init(bis, &mmc_sd1); | |
891 | } | |
892 | #endif |