Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * Copyright (C) 2006,2007 Felix Fietkau <nbd@openwrt.org>
0004  * Copyright (C) 2006,2007 Eugene Konev <ejka@openwrt.org>
0005  */
0006 
0007 #include <linux/init.h>
0008 #include <linux/types.h>
0009 #include <linux/delay.h>
0010 #include <linux/dma-mapping.h>
0011 #include <linux/platform_device.h>
0012 #include <linux/mtd/physmap.h>
0013 #include <linux/serial.h>
0014 #include <linux/serial_8250.h>
0015 #include <linux/ioport.h>
0016 #include <linux/io.h>
0017 #include <linux/vlynq.h>
0018 #include <linux/leds.h>
0019 #include <linux/string.h>
0020 #include <linux/etherdevice.h>
0021 #include <linux/phy.h>
0022 #include <linux/phy_fixed.h>
0023 #include <linux/gpio.h>
0024 #include <linux/clk.h>
0025 
0026 #include <asm/addrspace.h>
0027 #include <asm/mach-ar7/ar7.h>
0028 #include <asm/mach-ar7/prom.h>
0029 
0030 /*****************************************************************************
0031  * VLYNQ Bus
0032  ****************************************************************************/
0033 struct plat_vlynq_data {
0034     struct plat_vlynq_ops ops;
0035     int gpio_bit;
0036     int reset_bit;
0037 };
0038 
0039 static int vlynq_on(struct vlynq_device *dev)
0040 {
0041     int ret;
0042     struct plat_vlynq_data *pdata = dev->dev.platform_data;
0043 
0044     ret = gpio_request(pdata->gpio_bit, "vlynq");
0045     if (ret)
0046         goto out;
0047 
0048     ar7_device_reset(pdata->reset_bit);
0049 
0050     ret = ar7_gpio_disable(pdata->gpio_bit);
0051     if (ret)
0052         goto out_enabled;
0053 
0054     ret = ar7_gpio_enable(pdata->gpio_bit);
0055     if (ret)
0056         goto out_enabled;
0057 
0058     ret = gpio_direction_output(pdata->gpio_bit, 0);
0059     if (ret)
0060         goto out_gpio_enabled;
0061 
0062     msleep(50);
0063 
0064     gpio_set_value(pdata->gpio_bit, 1);
0065 
0066     msleep(50);
0067 
0068     return 0;
0069 
0070 out_gpio_enabled:
0071     ar7_gpio_disable(pdata->gpio_bit);
0072 out_enabled:
0073     ar7_device_disable(pdata->reset_bit);
0074     gpio_free(pdata->gpio_bit);
0075 out:
0076     return ret;
0077 }
0078 
0079 static void vlynq_off(struct vlynq_device *dev)
0080 {
0081     struct plat_vlynq_data *pdata = dev->dev.platform_data;
0082 
0083     ar7_gpio_disable(pdata->gpio_bit);
0084     gpio_free(pdata->gpio_bit);
0085     ar7_device_disable(pdata->reset_bit);
0086 }
0087 
0088 static struct resource vlynq_low_res[] = {
0089     {
0090         .name   = "regs",
0091         .flags  = IORESOURCE_MEM,
0092         .start  = AR7_REGS_VLYNQ0,
0093         .end    = AR7_REGS_VLYNQ0 + 0xff,
0094     },
0095     {
0096         .name   = "irq",
0097         .flags  = IORESOURCE_IRQ,
0098         .start  = 29,
0099         .end    = 29,
0100     },
0101     {
0102         .name   = "mem",
0103         .flags  = IORESOURCE_MEM,
0104         .start  = 0x04000000,
0105         .end    = 0x04ffffff,
0106     },
0107     {
0108         .name   = "devirq",
0109         .flags  = IORESOURCE_IRQ,
0110         .start  = 80,
0111         .end    = 111,
0112     },
0113 };
0114 
0115 static struct resource vlynq_high_res[] = {
0116     {
0117         .name   = "regs",
0118         .flags  = IORESOURCE_MEM,
0119         .start  = AR7_REGS_VLYNQ1,
0120         .end    = AR7_REGS_VLYNQ1 + 0xff,
0121     },
0122     {
0123         .name   = "irq",
0124         .flags  = IORESOURCE_IRQ,
0125         .start  = 33,
0126         .end    = 33,
0127     },
0128     {
0129         .name   = "mem",
0130         .flags  = IORESOURCE_MEM,
0131         .start  = 0x0c000000,
0132         .end    = 0x0cffffff,
0133     },
0134     {
0135         .name   = "devirq",
0136         .flags  = IORESOURCE_IRQ,
0137         .start  = 112,
0138         .end    = 143,
0139     },
0140 };
0141 
0142 static struct plat_vlynq_data vlynq_low_data = {
0143     .ops = {
0144         .on = vlynq_on,
0145         .off    = vlynq_off,
0146     },
0147     .reset_bit  = 20,
0148     .gpio_bit   = 18,
0149 };
0150 
0151 static struct plat_vlynq_data vlynq_high_data = {
0152     .ops = {
0153         .on = vlynq_on,
0154         .off    = vlynq_off,
0155     },
0156     .reset_bit  = 16,
0157     .gpio_bit   = 19,
0158 };
0159 
0160 static struct platform_device vlynq_low = {
0161     .id     = 0,
0162     .name       = "vlynq",
0163     .dev = {
0164         .platform_data  = &vlynq_low_data,
0165     },
0166     .resource   = vlynq_low_res,
0167     .num_resources  = ARRAY_SIZE(vlynq_low_res),
0168 };
0169 
0170 static struct platform_device vlynq_high = {
0171     .id     = 1,
0172     .name       = "vlynq",
0173     .dev = {
0174         .platform_data  = &vlynq_high_data,
0175     },
0176     .resource   = vlynq_high_res,
0177     .num_resources  = ARRAY_SIZE(vlynq_high_res),
0178 };
0179 
0180 /*****************************************************************************
0181  * Flash
0182  ****************************************************************************/
0183 static struct resource physmap_flash_resource = {
0184     .name   = "mem",
0185     .flags  = IORESOURCE_MEM,
0186     .start  = 0x10000000,
0187     .end    = 0x107fffff,
0188 };
0189 
0190 static const char *ar7_probe_types[] = { "ar7part", NULL };
0191 
0192 static struct physmap_flash_data physmap_flash_data = {
0193     .width  = 2,
0194     .part_probe_types = ar7_probe_types,
0195 };
0196 
0197 static struct platform_device physmap_flash = {
0198     .name       = "physmap-flash",
0199     .dev = {
0200         .platform_data  = &physmap_flash_data,
0201     },
0202     .resource   = &physmap_flash_resource,
0203     .num_resources  = 1,
0204 };
0205 
0206 /*****************************************************************************
0207  * Ethernet
0208  ****************************************************************************/
0209 static struct resource cpmac_low_res[] = {
0210     {
0211         .name   = "regs",
0212         .flags  = IORESOURCE_MEM,
0213         .start  = AR7_REGS_MAC0,
0214         .end    = AR7_REGS_MAC0 + 0x7ff,
0215     },
0216     {
0217         .name   = "irq",
0218         .flags  = IORESOURCE_IRQ,
0219         .start  = 27,
0220         .end    = 27,
0221     },
0222 };
0223 
0224 static struct resource cpmac_high_res[] = {
0225     {
0226         .name   = "regs",
0227         .flags  = IORESOURCE_MEM,
0228         .start  = AR7_REGS_MAC1,
0229         .end    = AR7_REGS_MAC1 + 0x7ff,
0230     },
0231     {
0232         .name   = "irq",
0233         .flags  = IORESOURCE_IRQ,
0234         .start  = 41,
0235         .end    = 41,
0236     },
0237 };
0238 
0239 static struct fixed_phy_status fixed_phy_status __initdata = {
0240     .link       = 1,
0241     .speed      = 100,
0242     .duplex     = 1,
0243 };
0244 
0245 static struct plat_cpmac_data cpmac_low_data = {
0246     .reset_bit  = 17,
0247     .power_bit  = 20,
0248     .phy_mask   = 0x80000000,
0249 };
0250 
0251 static struct plat_cpmac_data cpmac_high_data = {
0252     .reset_bit  = 21,
0253     .power_bit  = 22,
0254     .phy_mask   = 0x7fffffff,
0255 };
0256 
0257 static u64 cpmac_dma_mask = DMA_BIT_MASK(32);
0258 
0259 static struct platform_device cpmac_low = {
0260     .id     = 0,
0261     .name       = "cpmac",
0262     .dev = {
0263         .dma_mask       = &cpmac_dma_mask,
0264         .coherent_dma_mask  = DMA_BIT_MASK(32),
0265         .platform_data      = &cpmac_low_data,
0266     },
0267     .resource   = cpmac_low_res,
0268     .num_resources  = ARRAY_SIZE(cpmac_low_res),
0269 };
0270 
0271 static struct platform_device cpmac_high = {
0272     .id     = 1,
0273     .name       = "cpmac",
0274     .dev = {
0275         .dma_mask       = &cpmac_dma_mask,
0276         .coherent_dma_mask  = DMA_BIT_MASK(32),
0277         .platform_data      = &cpmac_high_data,
0278     },
0279     .resource   = cpmac_high_res,
0280     .num_resources  = ARRAY_SIZE(cpmac_high_res),
0281 };
0282 
0283 static void __init cpmac_get_mac(int instance, unsigned char *dev_addr)
0284 {
0285     char name[5], *mac;
0286 
0287     sprintf(name, "mac%c", 'a' + instance);
0288     mac = prom_getenv(name);
0289     if (!mac && instance) {
0290         sprintf(name, "mac%c", 'a');
0291         mac = prom_getenv(name);
0292     }
0293 
0294     if (mac) {
0295         if (!mac_pton(mac, dev_addr)) {
0296             pr_warn("cannot parse mac address, using random address\n");
0297             eth_random_addr(dev_addr);
0298         }
0299     } else
0300         eth_random_addr(dev_addr);
0301 }
0302 
0303 /*****************************************************************************
0304  * USB
0305  ****************************************************************************/
0306 static struct resource usb_res[] = {
0307     {
0308         .name   = "regs",
0309         .flags  = IORESOURCE_MEM,
0310         .start  = AR7_REGS_USB,
0311         .end    = AR7_REGS_USB + 0xff,
0312     },
0313     {
0314         .name   = "irq",
0315         .flags  = IORESOURCE_IRQ,
0316         .start  = 32,
0317         .end    = 32,
0318     },
0319     {
0320         .name   = "mem",
0321         .flags  = IORESOURCE_MEM,
0322         .start  = 0x03400000,
0323         .end    = 0x03401fff,
0324     },
0325 };
0326 
0327 static struct platform_device ar7_udc = {
0328     .name       = "ar7_udc",
0329     .resource   = usb_res,
0330     .num_resources  = ARRAY_SIZE(usb_res),
0331 };
0332 
0333 /*****************************************************************************
0334  * LEDs
0335  ****************************************************************************/
0336 static const struct gpio_led default_leds[] = {
0337     {
0338         .name           = "status",
0339         .gpio           = 8,
0340         .active_low     = 1,
0341     },
0342 };
0343 
0344 static const struct gpio_led titan_leds[] = {
0345     { .name = "status", .gpio = 8, .active_low = 1, },
0346     { .name = "wifi", .gpio = 13, .active_low = 1, },
0347 };
0348 
0349 static const struct gpio_led dsl502t_leds[] = {
0350     {
0351         .name           = "status",
0352         .gpio           = 9,
0353         .active_low     = 1,
0354     },
0355     {
0356         .name           = "ethernet",
0357         .gpio           = 7,
0358         .active_low     = 1,
0359     },
0360     {
0361         .name           = "usb",
0362         .gpio           = 12,
0363         .active_low     = 1,
0364     },
0365 };
0366 
0367 static const struct gpio_led dg834g_leds[] = {
0368     {
0369         .name           = "ppp",
0370         .gpio           = 6,
0371         .active_low     = 1,
0372     },
0373     {
0374         .name           = "status",
0375         .gpio           = 7,
0376         .active_low     = 1,
0377     },
0378     {
0379         .name           = "adsl",
0380         .gpio           = 8,
0381         .active_low     = 1,
0382     },
0383     {
0384         .name           = "wifi",
0385         .gpio           = 12,
0386         .active_low     = 1,
0387     },
0388     {
0389         .name           = "power",
0390         .gpio           = 14,
0391         .active_low     = 1,
0392         .default_trigger    = "default-on",
0393     },
0394 };
0395 
0396 static const struct gpio_led fb_sl_leds[] = {
0397     {
0398         .name           = "1",
0399         .gpio           = 7,
0400     },
0401     {
0402         .name           = "2",
0403         .gpio           = 13,
0404         .active_low     = 1,
0405     },
0406     {
0407         .name           = "3",
0408         .gpio           = 10,
0409         .active_low     = 1,
0410     },
0411     {
0412         .name           = "4",
0413         .gpio           = 12,
0414         .active_low     = 1,
0415     },
0416     {
0417         .name           = "5",
0418         .gpio           = 9,
0419         .active_low     = 1,
0420     },
0421 };
0422 
0423 static const struct gpio_led fb_fon_leds[] = {
0424     {
0425         .name           = "1",
0426         .gpio           = 8,
0427     },
0428     {
0429         .name           = "2",
0430         .gpio           = 3,
0431         .active_low     = 1,
0432     },
0433     {
0434         .name           = "3",
0435         .gpio           = 5,
0436     },
0437     {
0438         .name           = "4",
0439         .gpio           = 4,
0440         .active_low     = 1,
0441     },
0442     {
0443         .name           = "5",
0444         .gpio           = 11,
0445         .active_low     = 1,
0446     },
0447 };
0448 
0449 static const struct gpio_led gt701_leds[] = {
0450     {
0451         .name           = "inet:green",
0452         .gpio           = 13,
0453         .active_low     = 1,
0454     },
0455     {
0456         .name           = "usb",
0457         .gpio           = 12,
0458         .active_low     = 1,
0459     },
0460     {
0461         .name           = "inet:red",
0462         .gpio           = 9,
0463         .active_low     = 1,
0464     },
0465     {
0466         .name           = "power:red",
0467         .gpio           = 7,
0468         .active_low     = 1,
0469     },
0470     {
0471         .name           = "power:green",
0472         .gpio           = 8,
0473         .active_low     = 1,
0474         .default_trigger    = "default-on",
0475     },
0476     {
0477         .name           = "ethernet",
0478         .gpio           = 10,
0479         .active_low     = 1,
0480     },
0481 };
0482 
0483 static struct gpio_led_platform_data ar7_led_data;
0484 
0485 static struct platform_device ar7_gpio_leds = {
0486     .name = "leds-gpio",
0487     .dev = {
0488         .platform_data = &ar7_led_data,
0489     }
0490 };
0491 
0492 static void __init detect_leds(void)
0493 {
0494     char *prid, *usb_prod;
0495 
0496     /* Default LEDs */
0497     ar7_led_data.num_leds = ARRAY_SIZE(default_leds);
0498     ar7_led_data.leds = default_leds;
0499 
0500     /* FIXME: the whole thing is unreliable */
0501     prid = prom_getenv("ProductID");
0502     usb_prod = prom_getenv("usb_prod");
0503 
0504     /* If we can't get the product id from PROM, use the default LEDs */
0505     if (!prid)
0506         return;
0507 
0508     if (strstr(prid, "Fritz_Box_FON")) {
0509         ar7_led_data.num_leds = ARRAY_SIZE(fb_fon_leds);
0510         ar7_led_data.leds = fb_fon_leds;
0511     } else if (strstr(prid, "Fritz_Box_")) {
0512         ar7_led_data.num_leds = ARRAY_SIZE(fb_sl_leds);
0513         ar7_led_data.leds = fb_sl_leds;
0514     } else if ((!strcmp(prid, "AR7RD") || !strcmp(prid, "AR7DB"))
0515         && usb_prod != NULL && strstr(usb_prod, "DSL-502T")) {
0516         ar7_led_data.num_leds = ARRAY_SIZE(dsl502t_leds);
0517         ar7_led_data.leds = dsl502t_leds;
0518     } else if (strstr(prid, "DG834")) {
0519         ar7_led_data.num_leds = ARRAY_SIZE(dg834g_leds);
0520         ar7_led_data.leds = dg834g_leds;
0521     } else if (strstr(prid, "CYWM") || strstr(prid, "CYWL")) {
0522         ar7_led_data.num_leds = ARRAY_SIZE(titan_leds);
0523         ar7_led_data.leds = titan_leds;
0524     } else if (strstr(prid, "GT701")) {
0525         ar7_led_data.num_leds = ARRAY_SIZE(gt701_leds);
0526         ar7_led_data.leds = gt701_leds;
0527     }
0528 }
0529 
0530 /*****************************************************************************
0531  * Watchdog
0532  ****************************************************************************/
0533 static struct resource ar7_wdt_res = {
0534     .name       = "regs",
0535     .flags      = IORESOURCE_MEM,
0536     .start      = -1,   /* Filled at runtime */
0537     .end        = -1,   /* Filled at runtime */
0538 };
0539 
0540 static struct platform_device ar7_wdt = {
0541     .name       = "ar7_wdt",
0542     .resource   = &ar7_wdt_res,
0543     .num_resources  = 1,
0544 };
0545 
0546 /*****************************************************************************
0547  * Init
0548  ****************************************************************************/
0549 static int __init ar7_register_uarts(void)
0550 {
0551 #ifdef CONFIG_SERIAL_8250
0552     static struct uart_port uart_port __initdata;
0553     struct clk *bus_clk;
0554     int res;
0555 
0556     memset(&uart_port, 0, sizeof(struct uart_port));
0557 
0558     bus_clk = clk_get(NULL, "bus");
0559     if (IS_ERR(bus_clk))
0560         panic("unable to get bus clk");
0561 
0562     uart_port.type      = PORT_AR7;
0563     uart_port.uartclk   = clk_get_rate(bus_clk) / 2;
0564     uart_port.iotype    = UPIO_MEM32;
0565     uart_port.flags     = UPF_FIXED_TYPE | UPF_BOOT_AUTOCONF;
0566     uart_port.regshift  = 2;
0567 
0568     uart_port.line      = 0;
0569     uart_port.irq       = AR7_IRQ_UART0;
0570     uart_port.mapbase   = AR7_REGS_UART0;
0571     uart_port.membase   = ioremap(uart_port.mapbase, 256);
0572 
0573     res = early_serial_setup(&uart_port);
0574     if (res)
0575         return res;
0576 
0577     /* Only TNETD73xx have a second serial port */
0578     if (ar7_has_second_uart()) {
0579         uart_port.line      = 1;
0580         uart_port.irq       = AR7_IRQ_UART1;
0581         uart_port.mapbase   = UR8_REGS_UART1;
0582         uart_port.membase   = ioremap(uart_port.mapbase, 256);
0583 
0584         res = early_serial_setup(&uart_port);
0585         if (res)
0586             return res;
0587     }
0588 #endif
0589 
0590     return 0;
0591 }
0592 
0593 static void __init titan_fixup_devices(void)
0594 {
0595     /* Set vlynq0 data */
0596     vlynq_low_data.reset_bit = 15;
0597     vlynq_low_data.gpio_bit = 14;
0598 
0599     /* Set vlynq1 data */
0600     vlynq_high_data.reset_bit = 16;
0601     vlynq_high_data.gpio_bit = 7;
0602 
0603     /* Set vlynq0 resources */
0604     vlynq_low_res[0].start = TITAN_REGS_VLYNQ0;
0605     vlynq_low_res[0].end = TITAN_REGS_VLYNQ0 + 0xff;
0606     vlynq_low_res[1].start = 33;
0607     vlynq_low_res[1].end = 33;
0608     vlynq_low_res[2].start = 0x0c000000;
0609     vlynq_low_res[2].end = 0x0fffffff;
0610     vlynq_low_res[3].start = 80;
0611     vlynq_low_res[3].end = 111;
0612 
0613     /* Set vlynq1 resources */
0614     vlynq_high_res[0].start = TITAN_REGS_VLYNQ1;
0615     vlynq_high_res[0].end = TITAN_REGS_VLYNQ1 + 0xff;
0616     vlynq_high_res[1].start = 34;
0617     vlynq_high_res[1].end = 34;
0618     vlynq_high_res[2].start = 0x40000000;
0619     vlynq_high_res[2].end = 0x43ffffff;
0620     vlynq_high_res[3].start = 112;
0621     vlynq_high_res[3].end = 143;
0622 
0623     /* Set cpmac0 data */
0624     cpmac_low_data.phy_mask = 0x40000000;
0625 
0626     /* Set cpmac1 data */
0627     cpmac_high_data.phy_mask = 0x80000000;
0628 
0629     /* Set cpmac0 resources */
0630     cpmac_low_res[0].start = TITAN_REGS_MAC0;
0631     cpmac_low_res[0].end = TITAN_REGS_MAC0 + 0x7ff;
0632 
0633     /* Set cpmac1 resources */
0634     cpmac_high_res[0].start = TITAN_REGS_MAC1;
0635     cpmac_high_res[0].end = TITAN_REGS_MAC1 + 0x7ff;
0636 }
0637 
0638 static int __init ar7_register_devices(void)
0639 {
0640     void __iomem *bootcr;
0641     u32 val;
0642     int res;
0643 
0644     res = ar7_gpio_init();
0645     if (res)
0646         pr_warn("unable to register gpios: %d\n", res);
0647 
0648     res = ar7_register_uarts();
0649     if (res)
0650         pr_err("unable to setup uart(s): %d\n", res);
0651 
0652     res = platform_device_register(&physmap_flash);
0653     if (res)
0654         pr_warn("unable to register physmap-flash: %d\n", res);
0655 
0656     if (ar7_is_titan())
0657         titan_fixup_devices();
0658 
0659     ar7_device_disable(vlynq_low_data.reset_bit);
0660     res = platform_device_register(&vlynq_low);
0661     if (res)
0662         pr_warn("unable to register vlynq-low: %d\n", res);
0663 
0664     if (ar7_has_high_vlynq()) {
0665         ar7_device_disable(vlynq_high_data.reset_bit);
0666         res = platform_device_register(&vlynq_high);
0667         if (res)
0668             pr_warn("unable to register vlynq-high: %d\n", res);
0669     }
0670 
0671     if (ar7_has_high_cpmac()) {
0672         res = fixed_phy_add(PHY_POLL, cpmac_high.id,
0673                     &fixed_phy_status);
0674         if (!res) {
0675             cpmac_get_mac(1, cpmac_high_data.dev_addr);
0676 
0677             res = platform_device_register(&cpmac_high);
0678             if (res)
0679                 pr_warn("unable to register cpmac-high: %d\n",
0680                     res);
0681         } else
0682             pr_warn("unable to add cpmac-high phy: %d\n", res);
0683     } else
0684         cpmac_low_data.phy_mask = 0xffffffff;
0685 
0686     res = fixed_phy_add(PHY_POLL, cpmac_low.id, &fixed_phy_status);
0687     if (!res) {
0688         cpmac_get_mac(0, cpmac_low_data.dev_addr);
0689         res = platform_device_register(&cpmac_low);
0690         if (res)
0691             pr_warn("unable to register cpmac-low: %d\n", res);
0692     } else
0693         pr_warn("unable to add cpmac-low phy: %d\n", res);
0694 
0695     detect_leds();
0696     res = platform_device_register(&ar7_gpio_leds);
0697     if (res)
0698         pr_warn("unable to register leds: %d\n", res);
0699 
0700     res = platform_device_register(&ar7_udc);
0701     if (res)
0702         pr_warn("unable to register usb slave: %d\n", res);
0703 
0704     /* Register watchdog only if enabled in hardware */
0705     bootcr = ioremap(AR7_REGS_DCL, 4);
0706     val = readl(bootcr);
0707     iounmap(bootcr);
0708     if (val & AR7_WDT_HW_ENA) {
0709         if (ar7_has_high_vlynq())
0710             ar7_wdt_res.start = UR8_REGS_WDT;
0711         else
0712             ar7_wdt_res.start = AR7_REGS_WDT;
0713 
0714         ar7_wdt_res.end = ar7_wdt_res.start + 0x20;
0715         res = platform_device_register(&ar7_wdt);
0716         if (res)
0717             pr_warn("unable to register watchdog: %d\n", res);
0718     }
0719 
0720     return 0;
0721 }
0722 device_initcall(ar7_register_devices);