ar71xx: reset the mdio bus on ar7241/ar7242
[openwrt/svn-archive/archive.git] / target / linux / ar71xx / files / arch / mips / ar71xx / devices.c
1 /*
2 * Atheros AR71xx SoC platform devices
3 *
4 * Copyright (C) 2008-2009 Gabor Juhos <juhosg@openwrt.org>
5 * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
6 *
7 * Parts of this file are based on Atheros' 2.6.15 BSP
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License version 2 as published
11 * by the Free Software Foundation.
12 */
13
14 #include <linux/kernel.h>
15 #include <linux/init.h>
16 #include <linux/delay.h>
17 #include <linux/etherdevice.h>
18 #include <linux/platform_device.h>
19 #include <linux/serial_8250.h>
20
21 #include <asm/mach-ar71xx/ar71xx.h>
22
23 #include "devices.h"
24
25 static u8 ar71xx_mac_base[ETH_ALEN] __initdata;
26
27 static struct resource ar71xx_uart_resources[] = {
28 {
29 .start = AR71XX_UART_BASE,
30 .end = AR71XX_UART_BASE + AR71XX_UART_SIZE - 1,
31 .flags = IORESOURCE_MEM,
32 },
33 };
34
35 #define AR71XX_UART_FLAGS (UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP)
36 static struct plat_serial8250_port ar71xx_uart_data[] = {
37 {
38 .mapbase = AR71XX_UART_BASE,
39 .irq = AR71XX_MISC_IRQ_UART,
40 .flags = AR71XX_UART_FLAGS,
41 .iotype = UPIO_MEM32,
42 .regshift = 2,
43 }, {
44 /* terminating entry */
45 }
46 };
47
48 static struct platform_device ar71xx_uart_device = {
49 .name = "serial8250",
50 .id = PLAT8250_DEV_PLATFORM,
51 .resource = ar71xx_uart_resources,
52 .num_resources = ARRAY_SIZE(ar71xx_uart_resources),
53 .dev = {
54 .platform_data = ar71xx_uart_data
55 },
56 };
57
58 void __init ar71xx_add_device_uart(void)
59 {
60 ar71xx_uart_data[0].uartclk = ar71xx_ahb_freq;
61 platform_device_register(&ar71xx_uart_device);
62 }
63
64 static struct resource ar71xx_mdio_resources[] = {
65 {
66 .name = "mdio_base",
67 .flags = IORESOURCE_MEM,
68 .start = AR71XX_GE0_BASE,
69 .end = AR71XX_GE0_BASE + 0x200 - 1,
70 }
71 };
72
73 static struct ag71xx_mdio_platform_data ar71xx_mdio_data;
74
75 struct platform_device ar71xx_mdio_device = {
76 .name = "ag71xx-mdio",
77 .id = -1,
78 .resource = ar71xx_mdio_resources,
79 .num_resources = ARRAY_SIZE(ar71xx_mdio_resources),
80 .dev = {
81 .platform_data = &ar71xx_mdio_data,
82 },
83 };
84
85 void __init ar71xx_add_device_mdio(u32 phy_mask)
86 {
87 switch (ar71xx_soc) {
88 case AR71XX_SOC_AR7240:
89 case AR71XX_SOC_AR7241:
90 case AR71XX_SOC_AR7242:
91 ar71xx_mdio_data.is_ar7240 = 1;
92 break;
93 default:
94 break;
95 }
96
97 ar71xx_mdio_data.phy_mask = phy_mask;
98
99 platform_device_register(&ar71xx_mdio_device);
100 }
101
102 static void ar71xx_set_pll(u32 cfg_reg, u32 pll_reg, u32 pll_val, u32 shift)
103 {
104 void __iomem *base;
105 u32 t;
106
107 base = ioremap_nocache(AR71XX_PLL_BASE, AR71XX_PLL_SIZE);
108
109 t = __raw_readl(base + cfg_reg);
110 t &= ~(3 << shift);
111 t |= (2 << shift);
112 __raw_writel(t, base + cfg_reg);
113 udelay(100);
114
115 __raw_writel(pll_val, base + pll_reg);
116
117 t |= (3 << shift);
118 __raw_writel(t, base + cfg_reg);
119 udelay(100);
120
121 t &= ~(3 << shift);
122 __raw_writel(t, base + cfg_reg);
123 udelay(100);
124
125 printk(KERN_DEBUG "ar71xx: pll_reg %#x: %#x\n",
126 (unsigned int)(base + pll_reg), __raw_readl(base + pll_reg));
127
128 iounmap(base);
129 }
130
131 struct ar71xx_eth_pll_data ar71xx_eth0_pll_data;
132 struct ar71xx_eth_pll_data ar71xx_eth1_pll_data;
133
134 static u32 ar71xx_get_eth_pll(unsigned int mac, int speed)
135 {
136 struct ar71xx_eth_pll_data *pll_data;
137 u32 pll_val;
138
139 switch (mac) {
140 case 0:
141 pll_data = &ar71xx_eth0_pll_data;
142 break;
143 case 1:
144 pll_data = &ar71xx_eth1_pll_data;
145 break;
146 default:
147 BUG();
148 }
149
150 switch (speed) {
151 case SPEED_10:
152 pll_val = pll_data->pll_10;
153 break;
154 case SPEED_100:
155 pll_val = pll_data->pll_100;
156 break;
157 case SPEED_1000:
158 pll_val = pll_data->pll_1000;
159 break;
160 default:
161 BUG();
162 }
163
164 return pll_val;
165 }
166
167 static void ar71xx_set_pll_ge0(int speed)
168 {
169 u32 val = ar71xx_get_eth_pll(0, speed);
170
171 ar71xx_set_pll(AR71XX_PLL_REG_SEC_CONFIG, AR71XX_PLL_REG_ETH0_INT_CLOCK,
172 val, AR71XX_ETH0_PLL_SHIFT);
173 }
174
175 static void ar71xx_set_pll_ge1(int speed)
176 {
177 u32 val = ar71xx_get_eth_pll(1, speed);
178
179 ar71xx_set_pll(AR71XX_PLL_REG_SEC_CONFIG, AR71XX_PLL_REG_ETH1_INT_CLOCK,
180 val, AR71XX_ETH1_PLL_SHIFT);
181 }
182
183 static void ar724x_set_pll_ge0(int speed)
184 {
185 /* TODO */
186 }
187
188 static void ar724x_set_pll_ge1(int speed)
189 {
190 /* TODO */
191 }
192
193 static void ar91xx_set_pll_ge0(int speed)
194 {
195 u32 val = ar71xx_get_eth_pll(0, speed);
196
197 ar71xx_set_pll(AR91XX_PLL_REG_ETH_CONFIG, AR91XX_PLL_REG_ETH0_INT_CLOCK,
198 val, AR91XX_ETH0_PLL_SHIFT);
199 }
200
201 static void ar91xx_set_pll_ge1(int speed)
202 {
203 u32 val = ar71xx_get_eth_pll(1, speed);
204
205 ar71xx_set_pll(AR91XX_PLL_REG_ETH_CONFIG, AR91XX_PLL_REG_ETH1_INT_CLOCK,
206 val, AR91XX_ETH1_PLL_SHIFT);
207 }
208
209 static void ar71xx_ddr_flush_ge0(void)
210 {
211 ar71xx_ddr_flush(AR71XX_DDR_REG_FLUSH_GE0);
212 }
213
214 static void ar71xx_ddr_flush_ge1(void)
215 {
216 ar71xx_ddr_flush(AR71XX_DDR_REG_FLUSH_GE1);
217 }
218
219 static void ar724x_ddr_flush_ge0(void)
220 {
221 ar71xx_ddr_flush(AR724X_DDR_REG_FLUSH_GE0);
222 }
223
224 static void ar724x_ddr_flush_ge1(void)
225 {
226 ar71xx_ddr_flush(AR724X_DDR_REG_FLUSH_GE1);
227 }
228
229 static void ar91xx_ddr_flush_ge0(void)
230 {
231 ar71xx_ddr_flush(AR91XX_DDR_REG_FLUSH_GE0);
232 }
233
234 static void ar91xx_ddr_flush_ge1(void)
235 {
236 ar71xx_ddr_flush(AR91XX_DDR_REG_FLUSH_GE1);
237 }
238
239 static struct resource ar71xx_eth0_resources[] = {
240 {
241 .name = "mac_base",
242 .flags = IORESOURCE_MEM,
243 .start = AR71XX_GE0_BASE,
244 .end = AR71XX_GE0_BASE + 0x200 - 1,
245 }, {
246 .name = "mii_ctrl",
247 .flags = IORESOURCE_MEM,
248 .start = AR71XX_MII_BASE + MII_REG_MII0_CTRL,
249 .end = AR71XX_MII_BASE + MII_REG_MII0_CTRL + 3,
250 }, {
251 .name = "mac_irq",
252 .flags = IORESOURCE_IRQ,
253 .start = AR71XX_CPU_IRQ_GE0,
254 .end = AR71XX_CPU_IRQ_GE0,
255 },
256 };
257
258 struct ag71xx_platform_data ar71xx_eth0_data = {
259 .reset_bit = RESET_MODULE_GE0_MAC,
260 };
261
262 struct platform_device ar71xx_eth0_device = {
263 .name = "ag71xx",
264 .id = 0,
265 .resource = ar71xx_eth0_resources,
266 .num_resources = ARRAY_SIZE(ar71xx_eth0_resources),
267 .dev = {
268 .platform_data = &ar71xx_eth0_data,
269 },
270 };
271
272 static struct resource ar71xx_eth1_resources[] = {
273 {
274 .name = "mac_base",
275 .flags = IORESOURCE_MEM,
276 .start = AR71XX_GE1_BASE,
277 .end = AR71XX_GE1_BASE + 0x200 - 1,
278 }, {
279 .name = "mii_ctrl",
280 .flags = IORESOURCE_MEM,
281 .start = AR71XX_MII_BASE + MII_REG_MII1_CTRL,
282 .end = AR71XX_MII_BASE + MII_REG_MII1_CTRL + 3,
283 }, {
284 .name = "mac_irq",
285 .flags = IORESOURCE_IRQ,
286 .start = AR71XX_CPU_IRQ_GE1,
287 .end = AR71XX_CPU_IRQ_GE1,
288 },
289 };
290
291 struct ag71xx_platform_data ar71xx_eth1_data = {
292 .reset_bit = RESET_MODULE_GE1_MAC,
293 };
294
295 struct platform_device ar71xx_eth1_device = {
296 .name = "ag71xx",
297 .id = 1,
298 .resource = ar71xx_eth1_resources,
299 .num_resources = ARRAY_SIZE(ar71xx_eth1_resources),
300 .dev = {
301 .platform_data = &ar71xx_eth1_data,
302 },
303 };
304
305 #define AR71XX_PLL_VAL_1000 0x00110000
306 #define AR71XX_PLL_VAL_100 0x00001099
307 #define AR71XX_PLL_VAL_10 0x00991099
308
309 #define AR724X_PLL_VAL_1000 0x00110000
310 #define AR724X_PLL_VAL_100 0x00001099
311 #define AR724X_PLL_VAL_10 0x00991099
312
313 #define AR91XX_PLL_VAL_1000 0x1a000000
314 #define AR91XX_PLL_VAL_100 0x13000a44
315 #define AR91XX_PLL_VAL_10 0x00441099
316
317 static void __init ar71xx_init_eth_pll_data(unsigned int id)
318 {
319 struct ar71xx_eth_pll_data *pll_data;
320 u32 pll_10, pll_100, pll_1000;
321
322 switch (id) {
323 case 0:
324 pll_data = &ar71xx_eth0_pll_data;
325 break;
326 case 1:
327 pll_data = &ar71xx_eth1_pll_data;
328 break;
329 default:
330 BUG();
331 }
332
333 switch (ar71xx_soc) {
334 case AR71XX_SOC_AR7130:
335 case AR71XX_SOC_AR7141:
336 case AR71XX_SOC_AR7161:
337 pll_10 = AR71XX_PLL_VAL_10;
338 pll_100 = AR71XX_PLL_VAL_100;
339 pll_1000 = AR71XX_PLL_VAL_1000;
340 break;
341
342 case AR71XX_SOC_AR7240:
343 case AR71XX_SOC_AR7241:
344 case AR71XX_SOC_AR7242:
345 pll_10 = AR724X_PLL_VAL_10;
346 pll_100 = AR724X_PLL_VAL_100;
347 pll_1000 = AR724X_PLL_VAL_1000;
348 break;
349
350 case AR71XX_SOC_AR9130:
351 case AR71XX_SOC_AR9132:
352 pll_10 = AR91XX_PLL_VAL_10;
353 pll_100 = AR91XX_PLL_VAL_100;
354 pll_1000 = AR91XX_PLL_VAL_1000;
355 break;
356 default:
357 BUG();
358 }
359
360 if (!pll_data->pll_10)
361 pll_data->pll_10 = pll_10;
362
363 if (!pll_data->pll_100)
364 pll_data->pll_100 = pll_100;
365
366 if (!pll_data->pll_1000)
367 pll_data->pll_1000 = pll_1000;
368 }
369
370 static int ar71xx_eth_instance __initdata;
371 void __init ar71xx_add_device_eth(unsigned int id)
372 {
373 struct platform_device *pdev;
374 struct ag71xx_platform_data *pdata;
375
376 ar71xx_init_eth_pll_data(id);
377
378 switch (id) {
379 case 0:
380 switch (ar71xx_eth0_data.phy_if_mode) {
381 case PHY_INTERFACE_MODE_MII:
382 ar71xx_eth0_data.mii_if = MII0_CTRL_IF_MII;
383 break;
384 case PHY_INTERFACE_MODE_GMII:
385 ar71xx_eth0_data.mii_if = MII0_CTRL_IF_GMII;
386 break;
387 case PHY_INTERFACE_MODE_RGMII:
388 ar71xx_eth0_data.mii_if = MII0_CTRL_IF_RGMII;
389 break;
390 case PHY_INTERFACE_MODE_RMII:
391 ar71xx_eth0_data.mii_if = MII0_CTRL_IF_RMII;
392 break;
393 default:
394 printk(KERN_ERR "ar71xx: invalid PHY interface mode "
395 "for eth0\n");
396 return;
397 }
398 pdev = &ar71xx_eth0_device;
399 break;
400 case 1:
401 switch (ar71xx_eth1_data.phy_if_mode) {
402 case PHY_INTERFACE_MODE_RMII:
403 ar71xx_eth1_data.mii_if = MII1_CTRL_IF_RMII;
404 break;
405 case PHY_INTERFACE_MODE_RGMII:
406 ar71xx_eth1_data.mii_if = MII1_CTRL_IF_RGMII;
407 break;
408 default:
409 printk(KERN_ERR "ar71xx: invalid PHY interface mode "
410 "for eth1\n");
411 return;
412 }
413 pdev = &ar71xx_eth1_device;
414 break;
415 default:
416 printk(KERN_ERR "ar71xx: invalid ethernet id %d\n", id);
417 return;
418 }
419
420 pdata = pdev->dev.platform_data;
421
422 switch (ar71xx_soc) {
423 case AR71XX_SOC_AR7130:
424 pdata->ddr_flush = id ? ar71xx_ddr_flush_ge1
425 : ar71xx_ddr_flush_ge0;
426 pdata->set_pll = id ? ar71xx_set_pll_ge1
427 : ar71xx_set_pll_ge0;
428 break;
429
430 case AR71XX_SOC_AR7141:
431 case AR71XX_SOC_AR7161:
432 pdata->ddr_flush = id ? ar71xx_ddr_flush_ge1
433 : ar71xx_ddr_flush_ge0;
434 pdata->set_pll = id ? ar71xx_set_pll_ge1
435 : ar71xx_set_pll_ge0;
436 pdata->has_gbit = 1;
437 break;
438
439 case AR71XX_SOC_AR7241:
440 case AR71XX_SOC_AR7242:
441 ar71xx_eth0_data.reset_bit |= AR724X_RESET_GE0_MDIO;
442 ar71xx_eth1_data.reset_bit |= AR724X_RESET_GE1_MDIO;
443 /* fall through */
444 case AR71XX_SOC_AR7240:
445 pdata->ddr_flush = id ? ar724x_ddr_flush_ge1
446 : ar724x_ddr_flush_ge0;
447 pdata->set_pll = id ? ar724x_set_pll_ge1
448 : ar724x_set_pll_ge0;
449 pdata->is_ar724x = 1;
450 break;
451
452 case AR71XX_SOC_AR9130:
453 pdata->ddr_flush = id ? ar91xx_ddr_flush_ge1
454 : ar91xx_ddr_flush_ge0;
455 pdata->set_pll = id ? ar91xx_set_pll_ge1
456 : ar91xx_set_pll_ge0;
457 pdata->is_ar91xx = 1;
458 break;
459
460 case AR71XX_SOC_AR9132:
461 pdata->ddr_flush = id ? ar91xx_ddr_flush_ge1
462 : ar91xx_ddr_flush_ge0;
463 pdata->set_pll = id ? ar91xx_set_pll_ge1
464 : ar91xx_set_pll_ge0;
465 pdata->is_ar91xx = 1;
466 pdata->has_gbit = 1;
467 break;
468
469 default:
470 BUG();
471 }
472
473 switch (pdata->phy_if_mode) {
474 case PHY_INTERFACE_MODE_GMII:
475 case PHY_INTERFACE_MODE_RGMII:
476 if (!pdata->has_gbit) {
477 printk(KERN_ERR "ar71xx: no gbit available on eth%d\n",
478 id);
479 return;
480 }
481 /* fallthrough */
482 default:
483 break;
484 }
485
486 if (is_valid_ether_addr(ar71xx_mac_base)) {
487 memcpy(pdata->mac_addr, ar71xx_mac_base, ETH_ALEN);
488 pdata->mac_addr[5] += ar71xx_eth_instance;
489 } else {
490 random_ether_addr(pdata->mac_addr);
491 printk(KERN_DEBUG
492 "ar71xx: using random MAC address for eth%d\n",
493 ar71xx_eth_instance);
494 }
495
496 if (pdata->mii_bus_dev == NULL)
497 pdata->mii_bus_dev = &ar71xx_mdio_device.dev;
498
499 /* Reset the device */
500 ar71xx_device_stop(pdata->reset_bit);
501 mdelay(100);
502
503 ar71xx_device_start(pdata->reset_bit);
504 mdelay(100);
505
506 platform_device_register(pdev);
507 ar71xx_eth_instance++;
508 }
509
510 static struct resource ar71xx_spi_resources[] = {
511 [0] = {
512 .start = AR71XX_SPI_BASE,
513 .end = AR71XX_SPI_BASE + AR71XX_SPI_SIZE - 1,
514 .flags = IORESOURCE_MEM,
515 },
516 };
517
518 static struct platform_device ar71xx_spi_device = {
519 .name = "ar71xx-spi",
520 .id = -1,
521 .resource = ar71xx_spi_resources,
522 .num_resources = ARRAY_SIZE(ar71xx_spi_resources),
523 };
524
525 void __init ar71xx_add_device_spi(struct ar71xx_spi_platform_data *pdata,
526 struct spi_board_info const *info,
527 unsigned n)
528 {
529 spi_register_board_info(info, n);
530 ar71xx_spi_device.dev.platform_data = pdata;
531 platform_device_register(&ar71xx_spi_device);
532 }
533
534 void __init ar71xx_add_device_wdt(void)
535 {
536 platform_device_register_simple("ar71xx-wdt", -1, NULL, 0);
537 }
538
539 void __init ar71xx_set_mac_base(unsigned char *mac)
540 {
541 memcpy(ar71xx_mac_base, mac, ETH_ALEN);
542 }
543
544 void __init ar71xx_parse_mac_addr(char *mac_str)
545 {
546 u8 tmp[ETH_ALEN];
547 int t;
548
549 t = sscanf(mac_str, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
550 &tmp[0], &tmp[1], &tmp[2], &tmp[3], &tmp[4], &tmp[5]);
551
552 if (t != ETH_ALEN)
553 t = sscanf(mac_str, "%02hhx.%02hhx.%02hhx.%02hhx.%02hhx.%02hhx",
554 &tmp[0], &tmp[1], &tmp[2], &tmp[3], &tmp[4], &tmp[5]);
555
556 if (t == ETH_ALEN)
557 ar71xx_set_mac_base(tmp);
558 else
559 printk(KERN_DEBUG "ar71xx: failed to parse mac address "
560 "\"%s\"\n", mac_str);
561 }
562
563 static int __init ar71xx_ethaddr_setup(char *str)
564 {
565 ar71xx_parse_mac_addr(str);
566 return 1;
567 }
568 __setup("ethaddr=", ar71xx_ethaddr_setup);
569
570 static int __init ar71xx_kmac_setup(char *str)
571 {
572 ar71xx_parse_mac_addr(str);
573 return 1;
574 }
575 __setup("kmac=", ar71xx_kmac_setup);