source: trunk/target/linux/ar71xx/files/arch/mips/ar71xx/devices.c @ 22700

Last change on this file since 22700 was 22700, checked in by juhosg, 6 years ago

ar71xx: change mac address initialization

  • Property svn:eol-style set to native
File size: 13.0 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
25unsigned char 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                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
451                if (!pdata->fifo_cfg1)
452                        pdata->fifo_cfg1 = 0x0010ffff;
453                if (!pdata->fifo_cfg2)
454                        pdata->fifo_cfg2 = 0x015500aa;
455                if (!pdata->fifo_cfg3)
456                        pdata->fifo_cfg3 = 0x01f00140;
457                break;
458
459        case AR71XX_SOC_AR9130:
460                pdata->ddr_flush = id ? ar91xx_ddr_flush_ge1
461                                      : ar91xx_ddr_flush_ge0;
462                pdata->set_pll =  id ? ar91xx_set_pll_ge1
463                                     : ar91xx_set_pll_ge0;
464                pdata->is_ar91xx = 1;
465                break;
466
467        case AR71XX_SOC_AR9132:
468                pdata->ddr_flush = id ? ar91xx_ddr_flush_ge1
469                                      : ar91xx_ddr_flush_ge0;
470                pdata->set_pll =  id ? ar91xx_set_pll_ge1
471                                      : ar91xx_set_pll_ge0;
472                pdata->is_ar91xx = 1;
473                pdata->has_gbit = 1;
474                break;
475
476        default:
477                BUG();
478        }
479
480        switch (pdata->phy_if_mode) {
481        case PHY_INTERFACE_MODE_GMII:
482        case PHY_INTERFACE_MODE_RGMII:
483                if (!pdata->has_gbit) {
484                        printk(KERN_ERR "ar71xx: no gbit available on eth%d\n",
485                                        id);
486                        return;
487                }
488                /* fallthrough */
489        default:
490                break;
491        }
492
493        if (!is_valid_ether_addr(pdata->mac_addr)) {
494                random_ether_addr(pdata->mac_addr);
495                printk(KERN_DEBUG
496                        "ar71xx: using random MAC address for eth%d\n",
497                        ar71xx_eth_instance);
498        }
499
500        if (pdata->mii_bus_dev == NULL)
501                pdata->mii_bus_dev = &ar71xx_mdio_device.dev;
502
503        /* Reset the device */
504        ar71xx_device_stop(pdata->reset_bit);
505        mdelay(100);
506
507        ar71xx_device_start(pdata->reset_bit);
508        mdelay(100);
509
510        platform_device_register(pdev);
511        ar71xx_eth_instance++;
512}
513
514static struct resource ar71xx_spi_resources[] = {
515        [0] = {
516                .start  = AR71XX_SPI_BASE,
517                .end    = AR71XX_SPI_BASE + AR71XX_SPI_SIZE - 1,
518                .flags  = IORESOURCE_MEM,
519        },
520};
521
522static struct platform_device ar71xx_spi_device = {
523        .name           = "ar71xx-spi",
524        .id             = -1,
525        .resource       = ar71xx_spi_resources,
526        .num_resources  = ARRAY_SIZE(ar71xx_spi_resources),
527};
528
529void __init ar71xx_add_device_spi(struct ar71xx_spi_platform_data *pdata,
530                                struct spi_board_info const *info,
531                                unsigned n)
532{
533        spi_register_board_info(info, n);
534        ar71xx_spi_device.dev.platform_data = pdata;
535        platform_device_register(&ar71xx_spi_device);
536}
537
538void __init ar71xx_add_device_wdt(void)
539{
540        platform_device_register_simple("ar71xx-wdt", -1, NULL, 0);
541}
542
543void __init ar71xx_set_mac_base(unsigned char *mac)
544{
545        memcpy(ar71xx_mac_base, mac, ETH_ALEN);
546}
547
548void __init ar71xx_parse_mac_addr(char *mac_str)
549{
550        u8 tmp[ETH_ALEN];
551        int t;
552
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                t = sscanf(mac_str, "%02hhx.%02hhx.%02hhx.%02hhx.%02hhx.%02hhx",
558                        &tmp[0], &tmp[1], &tmp[2], &tmp[3], &tmp[4], &tmp[5]);
559
560        if (t == ETH_ALEN)
561                ar71xx_set_mac_base(tmp);
562        else
563                printk(KERN_DEBUG "ar71xx: failed to parse mac address "
564                                "\"%s\"\n", mac_str);
565}
566
567static int __init ar71xx_ethaddr_setup(char *str)
568{
569        ar71xx_parse_mac_addr(str);
570        return 1;
571}
572__setup("ethaddr=", ar71xx_ethaddr_setup);
573
574static int __init ar71xx_kmac_setup(char *str)
575{
576        ar71xx_parse_mac_addr(str);
577        return 1;
578}
579__setup("kmac=", ar71xx_kmac_setup);
580
581void __init ar71xx_init_mac(unsigned char *dst, const unsigned char *src,
582                            unsigned offset)
583{
584        u32 t;
585
586        if (!is_valid_ether_addr(src)) {
587                memset(dst, '\0', ETH_ALEN);
588                return;
589        }
590
591        t = (((u32) src[3]) << 16) + (((u32) src[4]) << 8) + ((u32) src[5]);
592        t += offset;
593
594        dst[0] = src[0];
595        dst[1] = src[1];
596        dst[2] = src[2];
597        dst[3] = (t >> 16) & 0xff;
598        dst[4] = (t >> 8) & 0xff;
599        dst[5] = t & 0xff;
600}
Note: See TracBrowser for help on using the repository browser.