source: branches/backfire/target/linux/ar71xx/files/arch/mips/ar71xx/devices.c @ 27706

Last change on this file since 27706 was 27706, checked in by nbd, 5 years ago

ar71xx: merge ar7240 fixes from trunk

  • Property svn:eol-style set to native
File size: 12.6 KB
Line 
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
25static u8 ar71xx_mac_base[ETH_ALEN] __initdata;
26
27static 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)
36static 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
48static 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
58void __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
64static 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
73static struct ag71xx_mdio_platform_data ar71xx_mdio_data;
74
75struct 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
85void __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
102static 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
131struct ar71xx_eth_pll_data ar71xx_eth0_pll_data;
132struct ar71xx_eth_pll_data ar71xx_eth1_pll_data;
133
134static 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
167static 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
175static 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
183static void ar724x_set_pll_ge0(int speed)
184{
185        /* TODO */
186}
187
188static void ar724x_set_pll_ge1(int speed)
189{
190        /* TODO */
191}
192
193static 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
201static 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
209static void ar71xx_ddr_flush_ge0(void)
210{
211        ar71xx_ddr_flush(AR71XX_DDR_REG_FLUSH_GE0);
212}
213
214static void ar71xx_ddr_flush_ge1(void)
215{
216        ar71xx_ddr_flush(AR71XX_DDR_REG_FLUSH_GE1);
217}
218
219static void ar724x_ddr_flush_ge0(void)
220{
221        ar71xx_ddr_flush(AR724X_DDR_REG_FLUSH_GE0);
222}
223
224static void ar724x_ddr_flush_ge1(void)
225{
226        ar71xx_ddr_flush(AR724X_DDR_REG_FLUSH_GE1);
227}
228
229static void ar91xx_ddr_flush_ge0(void)
230{
231        ar71xx_ddr_flush(AR91XX_DDR_REG_FLUSH_GE0);
232}
233
234static void ar91xx_ddr_flush_ge1(void)
235{
236        ar71xx_ddr_flush(AR91XX_DDR_REG_FLUSH_GE1);
237}
238
239static 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
258struct ag71xx_platform_data ar71xx_eth0_data = {
259        .reset_bit      = RESET_MODULE_GE0_MAC,
260};
261
262struct 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
272static 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
291struct ag71xx_platform_data ar71xx_eth1_data = {
292        .reset_bit      = RESET_MODULE_GE1_MAC,
293};
294
295struct 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
317static 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
370static int ar71xx_eth_instance __initdata;
371void __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                ar71xx_eth0_data.reset_bit |= RESET_MODULE_GE0_PHY;
446                ar71xx_eth1_data.reset_bit |= RESET_MODULE_GE1_PHY;
447                pdata->ddr_flush = id ? ar724x_ddr_flush_ge1
448                                      : ar724x_ddr_flush_ge0;
449                pdata->set_pll =  id ? ar724x_set_pll_ge1
450                                     : ar724x_set_pll_ge0;
451                pdata->is_ar724x = 1;
452                break;
453
454        case AR71XX_SOC_AR9130:
455                pdata->ddr_flush = id ? ar91xx_ddr_flush_ge1
456                                      : ar91xx_ddr_flush_ge0;
457                pdata->set_pll =  id ? ar91xx_set_pll_ge1
458                                     : ar91xx_set_pll_ge0;
459                pdata->is_ar91xx = 1;
460                break;
461
462        case AR71XX_SOC_AR9132:
463                pdata->ddr_flush = id ? ar91xx_ddr_flush_ge1
464                                      : ar91xx_ddr_flush_ge0;
465                pdata->set_pll =  id ? ar91xx_set_pll_ge1
466                                      : ar91xx_set_pll_ge0;
467                pdata->is_ar91xx = 1;
468                pdata->has_gbit = 1;
469                break;
470
471        default:
472                BUG();
473        }
474
475        switch (pdata->phy_if_mode) {
476        case PHY_INTERFACE_MODE_GMII:
477        case PHY_INTERFACE_MODE_RGMII:
478                if (!pdata->has_gbit) {
479                        printk(KERN_ERR "ar71xx: no gbit available on eth%d\n",
480                                        id);
481                        return;
482                }
483                /* fallthrough */
484        default:
485                break;
486        }
487
488        if (is_valid_ether_addr(ar71xx_mac_base)) {
489                memcpy(pdata->mac_addr, ar71xx_mac_base, ETH_ALEN);
490                pdata->mac_addr[5] += ar71xx_eth_instance;
491        } else {
492                random_ether_addr(pdata->mac_addr);
493                printk(KERN_DEBUG
494                        "ar71xx: using random MAC address for eth%d\n",
495                        ar71xx_eth_instance);
496        }
497
498        if (pdata->mii_bus_dev == NULL)
499                pdata->mii_bus_dev = &ar71xx_mdio_device.dev;
500
501        /* Reset the device */
502        ar71xx_device_stop(pdata->reset_bit);
503        mdelay(100);
504
505        ar71xx_device_start(pdata->reset_bit);
506        mdelay(100);
507
508        platform_device_register(pdev);
509        ar71xx_eth_instance++;
510}
511
512static struct resource ar71xx_spi_resources[] = {
513        [0] = {
514                .start  = AR71XX_SPI_BASE,
515                .end    = AR71XX_SPI_BASE + AR71XX_SPI_SIZE - 1,
516                .flags  = IORESOURCE_MEM,
517        },
518};
519
520static struct platform_device ar71xx_spi_device = {
521        .name           = "ar71xx-spi",
522        .id             = -1,
523        .resource       = ar71xx_spi_resources,
524        .num_resources  = ARRAY_SIZE(ar71xx_spi_resources),
525};
526
527void __init ar71xx_add_device_spi(struct ar71xx_spi_platform_data *pdata,
528                                struct spi_board_info const *info,
529                                unsigned n)
530{
531        spi_register_board_info(info, n);
532        ar71xx_spi_device.dev.platform_data = pdata;
533        platform_device_register(&ar71xx_spi_device);
534}
535
536void __init ar71xx_add_device_wdt(void)
537{
538        platform_device_register_simple("ar71xx-wdt", -1, NULL, 0);
539}
540
541void __init ar71xx_set_mac_base(unsigned char *mac)
542{
543        memcpy(ar71xx_mac_base, mac, ETH_ALEN);
544}
545
546void __init ar71xx_parse_mac_addr(char *mac_str)
547{
548        u8 tmp[ETH_ALEN];
549        int t;
550
551        t = sscanf(mac_str, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
552                        &tmp[0], &tmp[1], &tmp[2], &tmp[3], &tmp[4], &tmp[5]);
553
554        if (t != ETH_ALEN)
555                t = sscanf(mac_str, "%02hhx.%02hhx.%02hhx.%02hhx.%02hhx.%02hhx",
556                        &tmp[0], &tmp[1], &tmp[2], &tmp[3], &tmp[4], &tmp[5]);
557
558        if (t == ETH_ALEN)
559                ar71xx_set_mac_base(tmp);
560        else
561                printk(KERN_DEBUG "ar71xx: failed to parse mac address "
562                                "\"%s\"\n", mac_str);
563}
564
565static int __init ar71xx_ethaddr_setup(char *str)
566{
567        ar71xx_parse_mac_addr(str);
568        return 1;
569}
570__setup("ethaddr=", ar71xx_ethaddr_setup);
571
572static int __init ar71xx_kmac_setup(char *str)
573{
574        ar71xx_parse_mac_addr(str);
575        return 1;
576}
577__setup("kmac=", ar71xx_kmac_setup);
Note: See TracBrowser for help on using the repository browser.