162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (C) 2006,2007 Felix Fietkau <nbd@openwrt.org> 462306a36Sopenharmony_ci * Copyright (C) 2006,2007 Eugene Konev <ejka@openwrt.org> 562306a36Sopenharmony_ci */ 662306a36Sopenharmony_ci 762306a36Sopenharmony_ci#include <linux/init.h> 862306a36Sopenharmony_ci#include <linux/types.h> 962306a36Sopenharmony_ci#include <linux/delay.h> 1062306a36Sopenharmony_ci#include <linux/dma-mapping.h> 1162306a36Sopenharmony_ci#include <linux/platform_device.h> 1262306a36Sopenharmony_ci#include <linux/mtd/physmap.h> 1362306a36Sopenharmony_ci#include <linux/serial.h> 1462306a36Sopenharmony_ci#include <linux/serial_8250.h> 1562306a36Sopenharmony_ci#include <linux/ioport.h> 1662306a36Sopenharmony_ci#include <linux/io.h> 1762306a36Sopenharmony_ci#include <linux/vlynq.h> 1862306a36Sopenharmony_ci#include <linux/leds.h> 1962306a36Sopenharmony_ci#include <linux/string.h> 2062306a36Sopenharmony_ci#include <linux/etherdevice.h> 2162306a36Sopenharmony_ci#include <linux/phy.h> 2262306a36Sopenharmony_ci#include <linux/phy_fixed.h> 2362306a36Sopenharmony_ci#include <linux/gpio.h> 2462306a36Sopenharmony_ci#include <linux/clk.h> 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_ci#include <asm/addrspace.h> 2762306a36Sopenharmony_ci#include <asm/mach-ar7/ar7.h> 2862306a36Sopenharmony_ci#include <asm/mach-ar7/prom.h> 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_ci/***************************************************************************** 3162306a36Sopenharmony_ci * VLYNQ Bus 3262306a36Sopenharmony_ci ****************************************************************************/ 3362306a36Sopenharmony_cistruct plat_vlynq_data { 3462306a36Sopenharmony_ci struct plat_vlynq_ops ops; 3562306a36Sopenharmony_ci int gpio_bit; 3662306a36Sopenharmony_ci int reset_bit; 3762306a36Sopenharmony_ci}; 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_cistatic int vlynq_on(struct vlynq_device *dev) 4062306a36Sopenharmony_ci{ 4162306a36Sopenharmony_ci int ret; 4262306a36Sopenharmony_ci struct plat_vlynq_data *pdata = dev->dev.platform_data; 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci ret = gpio_request(pdata->gpio_bit, "vlynq"); 4562306a36Sopenharmony_ci if (ret) 4662306a36Sopenharmony_ci goto out; 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_ci ar7_device_reset(pdata->reset_bit); 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_ci ret = ar7_gpio_disable(pdata->gpio_bit); 5162306a36Sopenharmony_ci if (ret) 5262306a36Sopenharmony_ci goto out_enabled; 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_ci ret = ar7_gpio_enable(pdata->gpio_bit); 5562306a36Sopenharmony_ci if (ret) 5662306a36Sopenharmony_ci goto out_enabled; 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_ci ret = gpio_direction_output(pdata->gpio_bit, 0); 5962306a36Sopenharmony_ci if (ret) 6062306a36Sopenharmony_ci goto out_gpio_enabled; 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ci msleep(50); 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ci gpio_set_value(pdata->gpio_bit, 1); 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ci msleep(50); 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_ci return 0; 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_ciout_gpio_enabled: 7162306a36Sopenharmony_ci ar7_gpio_disable(pdata->gpio_bit); 7262306a36Sopenharmony_ciout_enabled: 7362306a36Sopenharmony_ci ar7_device_disable(pdata->reset_bit); 7462306a36Sopenharmony_ci gpio_free(pdata->gpio_bit); 7562306a36Sopenharmony_ciout: 7662306a36Sopenharmony_ci return ret; 7762306a36Sopenharmony_ci} 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_cistatic void vlynq_off(struct vlynq_device *dev) 8062306a36Sopenharmony_ci{ 8162306a36Sopenharmony_ci struct plat_vlynq_data *pdata = dev->dev.platform_data; 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_ci ar7_gpio_disable(pdata->gpio_bit); 8462306a36Sopenharmony_ci gpio_free(pdata->gpio_bit); 8562306a36Sopenharmony_ci ar7_device_disable(pdata->reset_bit); 8662306a36Sopenharmony_ci} 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_cistatic struct resource vlynq_low_res[] = { 8962306a36Sopenharmony_ci { 9062306a36Sopenharmony_ci .name = "regs", 9162306a36Sopenharmony_ci .flags = IORESOURCE_MEM, 9262306a36Sopenharmony_ci .start = AR7_REGS_VLYNQ0, 9362306a36Sopenharmony_ci .end = AR7_REGS_VLYNQ0 + 0xff, 9462306a36Sopenharmony_ci }, 9562306a36Sopenharmony_ci { 9662306a36Sopenharmony_ci .name = "irq", 9762306a36Sopenharmony_ci .flags = IORESOURCE_IRQ, 9862306a36Sopenharmony_ci .start = 29, 9962306a36Sopenharmony_ci .end = 29, 10062306a36Sopenharmony_ci }, 10162306a36Sopenharmony_ci { 10262306a36Sopenharmony_ci .name = "mem", 10362306a36Sopenharmony_ci .flags = IORESOURCE_MEM, 10462306a36Sopenharmony_ci .start = 0x04000000, 10562306a36Sopenharmony_ci .end = 0x04ffffff, 10662306a36Sopenharmony_ci }, 10762306a36Sopenharmony_ci { 10862306a36Sopenharmony_ci .name = "devirq", 10962306a36Sopenharmony_ci .flags = IORESOURCE_IRQ, 11062306a36Sopenharmony_ci .start = 80, 11162306a36Sopenharmony_ci .end = 111, 11262306a36Sopenharmony_ci }, 11362306a36Sopenharmony_ci}; 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_cistatic struct resource vlynq_high_res[] = { 11662306a36Sopenharmony_ci { 11762306a36Sopenharmony_ci .name = "regs", 11862306a36Sopenharmony_ci .flags = IORESOURCE_MEM, 11962306a36Sopenharmony_ci .start = AR7_REGS_VLYNQ1, 12062306a36Sopenharmony_ci .end = AR7_REGS_VLYNQ1 + 0xff, 12162306a36Sopenharmony_ci }, 12262306a36Sopenharmony_ci { 12362306a36Sopenharmony_ci .name = "irq", 12462306a36Sopenharmony_ci .flags = IORESOURCE_IRQ, 12562306a36Sopenharmony_ci .start = 33, 12662306a36Sopenharmony_ci .end = 33, 12762306a36Sopenharmony_ci }, 12862306a36Sopenharmony_ci { 12962306a36Sopenharmony_ci .name = "mem", 13062306a36Sopenharmony_ci .flags = IORESOURCE_MEM, 13162306a36Sopenharmony_ci .start = 0x0c000000, 13262306a36Sopenharmony_ci .end = 0x0cffffff, 13362306a36Sopenharmony_ci }, 13462306a36Sopenharmony_ci { 13562306a36Sopenharmony_ci .name = "devirq", 13662306a36Sopenharmony_ci .flags = IORESOURCE_IRQ, 13762306a36Sopenharmony_ci .start = 112, 13862306a36Sopenharmony_ci .end = 143, 13962306a36Sopenharmony_ci }, 14062306a36Sopenharmony_ci}; 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_cistatic struct plat_vlynq_data vlynq_low_data = { 14362306a36Sopenharmony_ci .ops = { 14462306a36Sopenharmony_ci .on = vlynq_on, 14562306a36Sopenharmony_ci .off = vlynq_off, 14662306a36Sopenharmony_ci }, 14762306a36Sopenharmony_ci .reset_bit = 20, 14862306a36Sopenharmony_ci .gpio_bit = 18, 14962306a36Sopenharmony_ci}; 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_cistatic struct plat_vlynq_data vlynq_high_data = { 15262306a36Sopenharmony_ci .ops = { 15362306a36Sopenharmony_ci .on = vlynq_on, 15462306a36Sopenharmony_ci .off = vlynq_off, 15562306a36Sopenharmony_ci }, 15662306a36Sopenharmony_ci .reset_bit = 16, 15762306a36Sopenharmony_ci .gpio_bit = 19, 15862306a36Sopenharmony_ci}; 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_cistatic struct platform_device vlynq_low = { 16162306a36Sopenharmony_ci .id = 0, 16262306a36Sopenharmony_ci .name = "vlynq", 16362306a36Sopenharmony_ci .dev = { 16462306a36Sopenharmony_ci .platform_data = &vlynq_low_data, 16562306a36Sopenharmony_ci }, 16662306a36Sopenharmony_ci .resource = vlynq_low_res, 16762306a36Sopenharmony_ci .num_resources = ARRAY_SIZE(vlynq_low_res), 16862306a36Sopenharmony_ci}; 16962306a36Sopenharmony_ci 17062306a36Sopenharmony_cistatic struct platform_device vlynq_high = { 17162306a36Sopenharmony_ci .id = 1, 17262306a36Sopenharmony_ci .name = "vlynq", 17362306a36Sopenharmony_ci .dev = { 17462306a36Sopenharmony_ci .platform_data = &vlynq_high_data, 17562306a36Sopenharmony_ci }, 17662306a36Sopenharmony_ci .resource = vlynq_high_res, 17762306a36Sopenharmony_ci .num_resources = ARRAY_SIZE(vlynq_high_res), 17862306a36Sopenharmony_ci}; 17962306a36Sopenharmony_ci 18062306a36Sopenharmony_ci/***************************************************************************** 18162306a36Sopenharmony_ci * Flash 18262306a36Sopenharmony_ci ****************************************************************************/ 18362306a36Sopenharmony_cistatic struct resource physmap_flash_resource = { 18462306a36Sopenharmony_ci .name = "mem", 18562306a36Sopenharmony_ci .flags = IORESOURCE_MEM, 18662306a36Sopenharmony_ci .start = 0x10000000, 18762306a36Sopenharmony_ci .end = 0x107fffff, 18862306a36Sopenharmony_ci}; 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_cistatic const char *ar7_probe_types[] = { "ar7part", NULL }; 19162306a36Sopenharmony_ci 19262306a36Sopenharmony_cistatic struct physmap_flash_data physmap_flash_data = { 19362306a36Sopenharmony_ci .width = 2, 19462306a36Sopenharmony_ci .part_probe_types = ar7_probe_types, 19562306a36Sopenharmony_ci}; 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_cistatic struct platform_device physmap_flash = { 19862306a36Sopenharmony_ci .name = "physmap-flash", 19962306a36Sopenharmony_ci .dev = { 20062306a36Sopenharmony_ci .platform_data = &physmap_flash_data, 20162306a36Sopenharmony_ci }, 20262306a36Sopenharmony_ci .resource = &physmap_flash_resource, 20362306a36Sopenharmony_ci .num_resources = 1, 20462306a36Sopenharmony_ci}; 20562306a36Sopenharmony_ci 20662306a36Sopenharmony_ci/***************************************************************************** 20762306a36Sopenharmony_ci * Ethernet 20862306a36Sopenharmony_ci ****************************************************************************/ 20962306a36Sopenharmony_cistatic struct resource cpmac_low_res[] = { 21062306a36Sopenharmony_ci { 21162306a36Sopenharmony_ci .name = "regs", 21262306a36Sopenharmony_ci .flags = IORESOURCE_MEM, 21362306a36Sopenharmony_ci .start = AR7_REGS_MAC0, 21462306a36Sopenharmony_ci .end = AR7_REGS_MAC0 + 0x7ff, 21562306a36Sopenharmony_ci }, 21662306a36Sopenharmony_ci { 21762306a36Sopenharmony_ci .name = "irq", 21862306a36Sopenharmony_ci .flags = IORESOURCE_IRQ, 21962306a36Sopenharmony_ci .start = 27, 22062306a36Sopenharmony_ci .end = 27, 22162306a36Sopenharmony_ci }, 22262306a36Sopenharmony_ci}; 22362306a36Sopenharmony_ci 22462306a36Sopenharmony_cistatic struct resource cpmac_high_res[] = { 22562306a36Sopenharmony_ci { 22662306a36Sopenharmony_ci .name = "regs", 22762306a36Sopenharmony_ci .flags = IORESOURCE_MEM, 22862306a36Sopenharmony_ci .start = AR7_REGS_MAC1, 22962306a36Sopenharmony_ci .end = AR7_REGS_MAC1 + 0x7ff, 23062306a36Sopenharmony_ci }, 23162306a36Sopenharmony_ci { 23262306a36Sopenharmony_ci .name = "irq", 23362306a36Sopenharmony_ci .flags = IORESOURCE_IRQ, 23462306a36Sopenharmony_ci .start = 41, 23562306a36Sopenharmony_ci .end = 41, 23662306a36Sopenharmony_ci }, 23762306a36Sopenharmony_ci}; 23862306a36Sopenharmony_ci 23962306a36Sopenharmony_cistatic struct fixed_phy_status fixed_phy_status __initdata = { 24062306a36Sopenharmony_ci .link = 1, 24162306a36Sopenharmony_ci .speed = 100, 24262306a36Sopenharmony_ci .duplex = 1, 24362306a36Sopenharmony_ci}; 24462306a36Sopenharmony_ci 24562306a36Sopenharmony_cistatic struct plat_cpmac_data cpmac_low_data = { 24662306a36Sopenharmony_ci .reset_bit = 17, 24762306a36Sopenharmony_ci .power_bit = 20, 24862306a36Sopenharmony_ci .phy_mask = 0x80000000, 24962306a36Sopenharmony_ci}; 25062306a36Sopenharmony_ci 25162306a36Sopenharmony_cistatic struct plat_cpmac_data cpmac_high_data = { 25262306a36Sopenharmony_ci .reset_bit = 21, 25362306a36Sopenharmony_ci .power_bit = 22, 25462306a36Sopenharmony_ci .phy_mask = 0x7fffffff, 25562306a36Sopenharmony_ci}; 25662306a36Sopenharmony_ci 25762306a36Sopenharmony_cistatic u64 cpmac_dma_mask = DMA_BIT_MASK(32); 25862306a36Sopenharmony_ci 25962306a36Sopenharmony_cistatic struct platform_device cpmac_low = { 26062306a36Sopenharmony_ci .id = 0, 26162306a36Sopenharmony_ci .name = "cpmac", 26262306a36Sopenharmony_ci .dev = { 26362306a36Sopenharmony_ci .dma_mask = &cpmac_dma_mask, 26462306a36Sopenharmony_ci .coherent_dma_mask = DMA_BIT_MASK(32), 26562306a36Sopenharmony_ci .platform_data = &cpmac_low_data, 26662306a36Sopenharmony_ci }, 26762306a36Sopenharmony_ci .resource = cpmac_low_res, 26862306a36Sopenharmony_ci .num_resources = ARRAY_SIZE(cpmac_low_res), 26962306a36Sopenharmony_ci}; 27062306a36Sopenharmony_ci 27162306a36Sopenharmony_cistatic struct platform_device cpmac_high = { 27262306a36Sopenharmony_ci .id = 1, 27362306a36Sopenharmony_ci .name = "cpmac", 27462306a36Sopenharmony_ci .dev = { 27562306a36Sopenharmony_ci .dma_mask = &cpmac_dma_mask, 27662306a36Sopenharmony_ci .coherent_dma_mask = DMA_BIT_MASK(32), 27762306a36Sopenharmony_ci .platform_data = &cpmac_high_data, 27862306a36Sopenharmony_ci }, 27962306a36Sopenharmony_ci .resource = cpmac_high_res, 28062306a36Sopenharmony_ci .num_resources = ARRAY_SIZE(cpmac_high_res), 28162306a36Sopenharmony_ci}; 28262306a36Sopenharmony_ci 28362306a36Sopenharmony_cistatic void __init cpmac_get_mac(int instance, unsigned char *dev_addr) 28462306a36Sopenharmony_ci{ 28562306a36Sopenharmony_ci char name[5], *mac; 28662306a36Sopenharmony_ci 28762306a36Sopenharmony_ci sprintf(name, "mac%c", 'a' + instance); 28862306a36Sopenharmony_ci mac = prom_getenv(name); 28962306a36Sopenharmony_ci if (!mac && instance) { 29062306a36Sopenharmony_ci sprintf(name, "mac%c", 'a'); 29162306a36Sopenharmony_ci mac = prom_getenv(name); 29262306a36Sopenharmony_ci } 29362306a36Sopenharmony_ci 29462306a36Sopenharmony_ci if (mac) { 29562306a36Sopenharmony_ci if (!mac_pton(mac, dev_addr)) { 29662306a36Sopenharmony_ci pr_warn("cannot parse mac address, using random address\n"); 29762306a36Sopenharmony_ci eth_random_addr(dev_addr); 29862306a36Sopenharmony_ci } 29962306a36Sopenharmony_ci } else 30062306a36Sopenharmony_ci eth_random_addr(dev_addr); 30162306a36Sopenharmony_ci} 30262306a36Sopenharmony_ci 30362306a36Sopenharmony_ci/***************************************************************************** 30462306a36Sopenharmony_ci * USB 30562306a36Sopenharmony_ci ****************************************************************************/ 30662306a36Sopenharmony_cistatic struct resource usb_res[] = { 30762306a36Sopenharmony_ci { 30862306a36Sopenharmony_ci .name = "regs", 30962306a36Sopenharmony_ci .flags = IORESOURCE_MEM, 31062306a36Sopenharmony_ci .start = AR7_REGS_USB, 31162306a36Sopenharmony_ci .end = AR7_REGS_USB + 0xff, 31262306a36Sopenharmony_ci }, 31362306a36Sopenharmony_ci { 31462306a36Sopenharmony_ci .name = "irq", 31562306a36Sopenharmony_ci .flags = IORESOURCE_IRQ, 31662306a36Sopenharmony_ci .start = 32, 31762306a36Sopenharmony_ci .end = 32, 31862306a36Sopenharmony_ci }, 31962306a36Sopenharmony_ci { 32062306a36Sopenharmony_ci .name = "mem", 32162306a36Sopenharmony_ci .flags = IORESOURCE_MEM, 32262306a36Sopenharmony_ci .start = 0x03400000, 32362306a36Sopenharmony_ci .end = 0x03401fff, 32462306a36Sopenharmony_ci }, 32562306a36Sopenharmony_ci}; 32662306a36Sopenharmony_ci 32762306a36Sopenharmony_cistatic struct platform_device ar7_udc = { 32862306a36Sopenharmony_ci .name = "ar7_udc", 32962306a36Sopenharmony_ci .resource = usb_res, 33062306a36Sopenharmony_ci .num_resources = ARRAY_SIZE(usb_res), 33162306a36Sopenharmony_ci}; 33262306a36Sopenharmony_ci 33362306a36Sopenharmony_ci/***************************************************************************** 33462306a36Sopenharmony_ci * LEDs 33562306a36Sopenharmony_ci ****************************************************************************/ 33662306a36Sopenharmony_cistatic const struct gpio_led default_leds[] = { 33762306a36Sopenharmony_ci { 33862306a36Sopenharmony_ci .name = "status", 33962306a36Sopenharmony_ci .gpio = 8, 34062306a36Sopenharmony_ci .active_low = 1, 34162306a36Sopenharmony_ci }, 34262306a36Sopenharmony_ci}; 34362306a36Sopenharmony_ci 34462306a36Sopenharmony_cistatic const struct gpio_led titan_leds[] = { 34562306a36Sopenharmony_ci { .name = "status", .gpio = 8, .active_low = 1, }, 34662306a36Sopenharmony_ci { .name = "wifi", .gpio = 13, .active_low = 1, }, 34762306a36Sopenharmony_ci}; 34862306a36Sopenharmony_ci 34962306a36Sopenharmony_cistatic const struct gpio_led dsl502t_leds[] = { 35062306a36Sopenharmony_ci { 35162306a36Sopenharmony_ci .name = "status", 35262306a36Sopenharmony_ci .gpio = 9, 35362306a36Sopenharmony_ci .active_low = 1, 35462306a36Sopenharmony_ci }, 35562306a36Sopenharmony_ci { 35662306a36Sopenharmony_ci .name = "ethernet", 35762306a36Sopenharmony_ci .gpio = 7, 35862306a36Sopenharmony_ci .active_low = 1, 35962306a36Sopenharmony_ci }, 36062306a36Sopenharmony_ci { 36162306a36Sopenharmony_ci .name = "usb", 36262306a36Sopenharmony_ci .gpio = 12, 36362306a36Sopenharmony_ci .active_low = 1, 36462306a36Sopenharmony_ci }, 36562306a36Sopenharmony_ci}; 36662306a36Sopenharmony_ci 36762306a36Sopenharmony_cistatic const struct gpio_led dg834g_leds[] = { 36862306a36Sopenharmony_ci { 36962306a36Sopenharmony_ci .name = "ppp", 37062306a36Sopenharmony_ci .gpio = 6, 37162306a36Sopenharmony_ci .active_low = 1, 37262306a36Sopenharmony_ci }, 37362306a36Sopenharmony_ci { 37462306a36Sopenharmony_ci .name = "status", 37562306a36Sopenharmony_ci .gpio = 7, 37662306a36Sopenharmony_ci .active_low = 1, 37762306a36Sopenharmony_ci }, 37862306a36Sopenharmony_ci { 37962306a36Sopenharmony_ci .name = "adsl", 38062306a36Sopenharmony_ci .gpio = 8, 38162306a36Sopenharmony_ci .active_low = 1, 38262306a36Sopenharmony_ci }, 38362306a36Sopenharmony_ci { 38462306a36Sopenharmony_ci .name = "wifi", 38562306a36Sopenharmony_ci .gpio = 12, 38662306a36Sopenharmony_ci .active_low = 1, 38762306a36Sopenharmony_ci }, 38862306a36Sopenharmony_ci { 38962306a36Sopenharmony_ci .name = "power", 39062306a36Sopenharmony_ci .gpio = 14, 39162306a36Sopenharmony_ci .active_low = 1, 39262306a36Sopenharmony_ci .default_trigger = "default-on", 39362306a36Sopenharmony_ci }, 39462306a36Sopenharmony_ci}; 39562306a36Sopenharmony_ci 39662306a36Sopenharmony_cistatic const struct gpio_led fb_sl_leds[] = { 39762306a36Sopenharmony_ci { 39862306a36Sopenharmony_ci .name = "1", 39962306a36Sopenharmony_ci .gpio = 7, 40062306a36Sopenharmony_ci }, 40162306a36Sopenharmony_ci { 40262306a36Sopenharmony_ci .name = "2", 40362306a36Sopenharmony_ci .gpio = 13, 40462306a36Sopenharmony_ci .active_low = 1, 40562306a36Sopenharmony_ci }, 40662306a36Sopenharmony_ci { 40762306a36Sopenharmony_ci .name = "3", 40862306a36Sopenharmony_ci .gpio = 10, 40962306a36Sopenharmony_ci .active_low = 1, 41062306a36Sopenharmony_ci }, 41162306a36Sopenharmony_ci { 41262306a36Sopenharmony_ci .name = "4", 41362306a36Sopenharmony_ci .gpio = 12, 41462306a36Sopenharmony_ci .active_low = 1, 41562306a36Sopenharmony_ci }, 41662306a36Sopenharmony_ci { 41762306a36Sopenharmony_ci .name = "5", 41862306a36Sopenharmony_ci .gpio = 9, 41962306a36Sopenharmony_ci .active_low = 1, 42062306a36Sopenharmony_ci }, 42162306a36Sopenharmony_ci}; 42262306a36Sopenharmony_ci 42362306a36Sopenharmony_cistatic const struct gpio_led fb_fon_leds[] = { 42462306a36Sopenharmony_ci { 42562306a36Sopenharmony_ci .name = "1", 42662306a36Sopenharmony_ci .gpio = 8, 42762306a36Sopenharmony_ci }, 42862306a36Sopenharmony_ci { 42962306a36Sopenharmony_ci .name = "2", 43062306a36Sopenharmony_ci .gpio = 3, 43162306a36Sopenharmony_ci .active_low = 1, 43262306a36Sopenharmony_ci }, 43362306a36Sopenharmony_ci { 43462306a36Sopenharmony_ci .name = "3", 43562306a36Sopenharmony_ci .gpio = 5, 43662306a36Sopenharmony_ci }, 43762306a36Sopenharmony_ci { 43862306a36Sopenharmony_ci .name = "4", 43962306a36Sopenharmony_ci .gpio = 4, 44062306a36Sopenharmony_ci .active_low = 1, 44162306a36Sopenharmony_ci }, 44262306a36Sopenharmony_ci { 44362306a36Sopenharmony_ci .name = "5", 44462306a36Sopenharmony_ci .gpio = 11, 44562306a36Sopenharmony_ci .active_low = 1, 44662306a36Sopenharmony_ci }, 44762306a36Sopenharmony_ci}; 44862306a36Sopenharmony_ci 44962306a36Sopenharmony_cistatic const struct gpio_led gt701_leds[] = { 45062306a36Sopenharmony_ci { 45162306a36Sopenharmony_ci .name = "inet:green", 45262306a36Sopenharmony_ci .gpio = 13, 45362306a36Sopenharmony_ci .active_low = 1, 45462306a36Sopenharmony_ci }, 45562306a36Sopenharmony_ci { 45662306a36Sopenharmony_ci .name = "usb", 45762306a36Sopenharmony_ci .gpio = 12, 45862306a36Sopenharmony_ci .active_low = 1, 45962306a36Sopenharmony_ci }, 46062306a36Sopenharmony_ci { 46162306a36Sopenharmony_ci .name = "inet:red", 46262306a36Sopenharmony_ci .gpio = 9, 46362306a36Sopenharmony_ci .active_low = 1, 46462306a36Sopenharmony_ci }, 46562306a36Sopenharmony_ci { 46662306a36Sopenharmony_ci .name = "power:red", 46762306a36Sopenharmony_ci .gpio = 7, 46862306a36Sopenharmony_ci .active_low = 1, 46962306a36Sopenharmony_ci }, 47062306a36Sopenharmony_ci { 47162306a36Sopenharmony_ci .name = "power:green", 47262306a36Sopenharmony_ci .gpio = 8, 47362306a36Sopenharmony_ci .active_low = 1, 47462306a36Sopenharmony_ci .default_trigger = "default-on", 47562306a36Sopenharmony_ci }, 47662306a36Sopenharmony_ci { 47762306a36Sopenharmony_ci .name = "ethernet", 47862306a36Sopenharmony_ci .gpio = 10, 47962306a36Sopenharmony_ci .active_low = 1, 48062306a36Sopenharmony_ci }, 48162306a36Sopenharmony_ci}; 48262306a36Sopenharmony_ci 48362306a36Sopenharmony_cistatic struct gpio_led_platform_data ar7_led_data; 48462306a36Sopenharmony_ci 48562306a36Sopenharmony_cistatic struct platform_device ar7_gpio_leds = { 48662306a36Sopenharmony_ci .name = "leds-gpio", 48762306a36Sopenharmony_ci .dev = { 48862306a36Sopenharmony_ci .platform_data = &ar7_led_data, 48962306a36Sopenharmony_ci } 49062306a36Sopenharmony_ci}; 49162306a36Sopenharmony_ci 49262306a36Sopenharmony_cistatic void __init detect_leds(void) 49362306a36Sopenharmony_ci{ 49462306a36Sopenharmony_ci char *prid, *usb_prod; 49562306a36Sopenharmony_ci 49662306a36Sopenharmony_ci /* Default LEDs */ 49762306a36Sopenharmony_ci ar7_led_data.num_leds = ARRAY_SIZE(default_leds); 49862306a36Sopenharmony_ci ar7_led_data.leds = default_leds; 49962306a36Sopenharmony_ci 50062306a36Sopenharmony_ci /* FIXME: the whole thing is unreliable */ 50162306a36Sopenharmony_ci prid = prom_getenv("ProductID"); 50262306a36Sopenharmony_ci usb_prod = prom_getenv("usb_prod"); 50362306a36Sopenharmony_ci 50462306a36Sopenharmony_ci /* If we can't get the product id from PROM, use the default LEDs */ 50562306a36Sopenharmony_ci if (!prid) 50662306a36Sopenharmony_ci return; 50762306a36Sopenharmony_ci 50862306a36Sopenharmony_ci if (strstr(prid, "Fritz_Box_FON")) { 50962306a36Sopenharmony_ci ar7_led_data.num_leds = ARRAY_SIZE(fb_fon_leds); 51062306a36Sopenharmony_ci ar7_led_data.leds = fb_fon_leds; 51162306a36Sopenharmony_ci } else if (strstr(prid, "Fritz_Box_")) { 51262306a36Sopenharmony_ci ar7_led_data.num_leds = ARRAY_SIZE(fb_sl_leds); 51362306a36Sopenharmony_ci ar7_led_data.leds = fb_sl_leds; 51462306a36Sopenharmony_ci } else if ((!strcmp(prid, "AR7RD") || !strcmp(prid, "AR7DB")) 51562306a36Sopenharmony_ci && usb_prod != NULL && strstr(usb_prod, "DSL-502T")) { 51662306a36Sopenharmony_ci ar7_led_data.num_leds = ARRAY_SIZE(dsl502t_leds); 51762306a36Sopenharmony_ci ar7_led_data.leds = dsl502t_leds; 51862306a36Sopenharmony_ci } else if (strstr(prid, "DG834")) { 51962306a36Sopenharmony_ci ar7_led_data.num_leds = ARRAY_SIZE(dg834g_leds); 52062306a36Sopenharmony_ci ar7_led_data.leds = dg834g_leds; 52162306a36Sopenharmony_ci } else if (strstr(prid, "CYWM") || strstr(prid, "CYWL")) { 52262306a36Sopenharmony_ci ar7_led_data.num_leds = ARRAY_SIZE(titan_leds); 52362306a36Sopenharmony_ci ar7_led_data.leds = titan_leds; 52462306a36Sopenharmony_ci } else if (strstr(prid, "GT701")) { 52562306a36Sopenharmony_ci ar7_led_data.num_leds = ARRAY_SIZE(gt701_leds); 52662306a36Sopenharmony_ci ar7_led_data.leds = gt701_leds; 52762306a36Sopenharmony_ci } 52862306a36Sopenharmony_ci} 52962306a36Sopenharmony_ci 53062306a36Sopenharmony_ci/***************************************************************************** 53162306a36Sopenharmony_ci * Watchdog 53262306a36Sopenharmony_ci ****************************************************************************/ 53362306a36Sopenharmony_cistatic struct resource ar7_wdt_res = { 53462306a36Sopenharmony_ci .name = "regs", 53562306a36Sopenharmony_ci .flags = IORESOURCE_MEM, 53662306a36Sopenharmony_ci .start = -1, /* Filled at runtime */ 53762306a36Sopenharmony_ci .end = -1, /* Filled at runtime */ 53862306a36Sopenharmony_ci}; 53962306a36Sopenharmony_ci 54062306a36Sopenharmony_cistatic struct platform_device ar7_wdt = { 54162306a36Sopenharmony_ci .name = "ar7_wdt", 54262306a36Sopenharmony_ci .resource = &ar7_wdt_res, 54362306a36Sopenharmony_ci .num_resources = 1, 54462306a36Sopenharmony_ci}; 54562306a36Sopenharmony_ci 54662306a36Sopenharmony_ci/***************************************************************************** 54762306a36Sopenharmony_ci * Init 54862306a36Sopenharmony_ci ****************************************************************************/ 54962306a36Sopenharmony_cistatic int __init ar7_register_uarts(void) 55062306a36Sopenharmony_ci{ 55162306a36Sopenharmony_ci#ifdef CONFIG_SERIAL_8250 55262306a36Sopenharmony_ci static struct uart_port uart_port __initdata; 55362306a36Sopenharmony_ci struct clk *bus_clk; 55462306a36Sopenharmony_ci int res; 55562306a36Sopenharmony_ci 55662306a36Sopenharmony_ci memset(&uart_port, 0, sizeof(struct uart_port)); 55762306a36Sopenharmony_ci 55862306a36Sopenharmony_ci bus_clk = clk_get(NULL, "bus"); 55962306a36Sopenharmony_ci if (IS_ERR(bus_clk)) 56062306a36Sopenharmony_ci panic("unable to get bus clk"); 56162306a36Sopenharmony_ci 56262306a36Sopenharmony_ci uart_port.type = PORT_AR7; 56362306a36Sopenharmony_ci uart_port.uartclk = clk_get_rate(bus_clk) / 2; 56462306a36Sopenharmony_ci uart_port.iotype = UPIO_MEM32; 56562306a36Sopenharmony_ci uart_port.flags = UPF_FIXED_TYPE | UPF_BOOT_AUTOCONF; 56662306a36Sopenharmony_ci uart_port.regshift = 2; 56762306a36Sopenharmony_ci 56862306a36Sopenharmony_ci uart_port.line = 0; 56962306a36Sopenharmony_ci uart_port.irq = AR7_IRQ_UART0; 57062306a36Sopenharmony_ci uart_port.mapbase = AR7_REGS_UART0; 57162306a36Sopenharmony_ci uart_port.membase = ioremap(uart_port.mapbase, 256); 57262306a36Sopenharmony_ci 57362306a36Sopenharmony_ci res = early_serial_setup(&uart_port); 57462306a36Sopenharmony_ci if (res) 57562306a36Sopenharmony_ci return res; 57662306a36Sopenharmony_ci 57762306a36Sopenharmony_ci /* Only TNETD73xx have a second serial port */ 57862306a36Sopenharmony_ci if (ar7_has_second_uart()) { 57962306a36Sopenharmony_ci uart_port.line = 1; 58062306a36Sopenharmony_ci uart_port.irq = AR7_IRQ_UART1; 58162306a36Sopenharmony_ci uart_port.mapbase = UR8_REGS_UART1; 58262306a36Sopenharmony_ci uart_port.membase = ioremap(uart_port.mapbase, 256); 58362306a36Sopenharmony_ci 58462306a36Sopenharmony_ci res = early_serial_setup(&uart_port); 58562306a36Sopenharmony_ci if (res) 58662306a36Sopenharmony_ci return res; 58762306a36Sopenharmony_ci } 58862306a36Sopenharmony_ci#endif 58962306a36Sopenharmony_ci 59062306a36Sopenharmony_ci return 0; 59162306a36Sopenharmony_ci} 59262306a36Sopenharmony_ci 59362306a36Sopenharmony_cistatic void __init titan_fixup_devices(void) 59462306a36Sopenharmony_ci{ 59562306a36Sopenharmony_ci /* Set vlynq0 data */ 59662306a36Sopenharmony_ci vlynq_low_data.reset_bit = 15; 59762306a36Sopenharmony_ci vlynq_low_data.gpio_bit = 14; 59862306a36Sopenharmony_ci 59962306a36Sopenharmony_ci /* Set vlynq1 data */ 60062306a36Sopenharmony_ci vlynq_high_data.reset_bit = 16; 60162306a36Sopenharmony_ci vlynq_high_data.gpio_bit = 7; 60262306a36Sopenharmony_ci 60362306a36Sopenharmony_ci /* Set vlynq0 resources */ 60462306a36Sopenharmony_ci vlynq_low_res[0].start = TITAN_REGS_VLYNQ0; 60562306a36Sopenharmony_ci vlynq_low_res[0].end = TITAN_REGS_VLYNQ0 + 0xff; 60662306a36Sopenharmony_ci vlynq_low_res[1].start = 33; 60762306a36Sopenharmony_ci vlynq_low_res[1].end = 33; 60862306a36Sopenharmony_ci vlynq_low_res[2].start = 0x0c000000; 60962306a36Sopenharmony_ci vlynq_low_res[2].end = 0x0fffffff; 61062306a36Sopenharmony_ci vlynq_low_res[3].start = 80; 61162306a36Sopenharmony_ci vlynq_low_res[3].end = 111; 61262306a36Sopenharmony_ci 61362306a36Sopenharmony_ci /* Set vlynq1 resources */ 61462306a36Sopenharmony_ci vlynq_high_res[0].start = TITAN_REGS_VLYNQ1; 61562306a36Sopenharmony_ci vlynq_high_res[0].end = TITAN_REGS_VLYNQ1 + 0xff; 61662306a36Sopenharmony_ci vlynq_high_res[1].start = 34; 61762306a36Sopenharmony_ci vlynq_high_res[1].end = 34; 61862306a36Sopenharmony_ci vlynq_high_res[2].start = 0x40000000; 61962306a36Sopenharmony_ci vlynq_high_res[2].end = 0x43ffffff; 62062306a36Sopenharmony_ci vlynq_high_res[3].start = 112; 62162306a36Sopenharmony_ci vlynq_high_res[3].end = 143; 62262306a36Sopenharmony_ci 62362306a36Sopenharmony_ci /* Set cpmac0 data */ 62462306a36Sopenharmony_ci cpmac_low_data.phy_mask = 0x40000000; 62562306a36Sopenharmony_ci 62662306a36Sopenharmony_ci /* Set cpmac1 data */ 62762306a36Sopenharmony_ci cpmac_high_data.phy_mask = 0x80000000; 62862306a36Sopenharmony_ci 62962306a36Sopenharmony_ci /* Set cpmac0 resources */ 63062306a36Sopenharmony_ci cpmac_low_res[0].start = TITAN_REGS_MAC0; 63162306a36Sopenharmony_ci cpmac_low_res[0].end = TITAN_REGS_MAC0 + 0x7ff; 63262306a36Sopenharmony_ci 63362306a36Sopenharmony_ci /* Set cpmac1 resources */ 63462306a36Sopenharmony_ci cpmac_high_res[0].start = TITAN_REGS_MAC1; 63562306a36Sopenharmony_ci cpmac_high_res[0].end = TITAN_REGS_MAC1 + 0x7ff; 63662306a36Sopenharmony_ci} 63762306a36Sopenharmony_ci 63862306a36Sopenharmony_cistatic int __init ar7_register_devices(void) 63962306a36Sopenharmony_ci{ 64062306a36Sopenharmony_ci void __iomem *bootcr; 64162306a36Sopenharmony_ci u32 val; 64262306a36Sopenharmony_ci int res; 64362306a36Sopenharmony_ci 64462306a36Sopenharmony_ci res = ar7_gpio_init(); 64562306a36Sopenharmony_ci if (res) 64662306a36Sopenharmony_ci pr_warn("unable to register gpios: %d\n", res); 64762306a36Sopenharmony_ci 64862306a36Sopenharmony_ci res = ar7_register_uarts(); 64962306a36Sopenharmony_ci if (res) 65062306a36Sopenharmony_ci pr_err("unable to setup uart(s): %d\n", res); 65162306a36Sopenharmony_ci 65262306a36Sopenharmony_ci res = platform_device_register(&physmap_flash); 65362306a36Sopenharmony_ci if (res) 65462306a36Sopenharmony_ci pr_warn("unable to register physmap-flash: %d\n", res); 65562306a36Sopenharmony_ci 65662306a36Sopenharmony_ci if (ar7_is_titan()) 65762306a36Sopenharmony_ci titan_fixup_devices(); 65862306a36Sopenharmony_ci 65962306a36Sopenharmony_ci ar7_device_disable(vlynq_low_data.reset_bit); 66062306a36Sopenharmony_ci res = platform_device_register(&vlynq_low); 66162306a36Sopenharmony_ci if (res) 66262306a36Sopenharmony_ci pr_warn("unable to register vlynq-low: %d\n", res); 66362306a36Sopenharmony_ci 66462306a36Sopenharmony_ci if (ar7_has_high_vlynq()) { 66562306a36Sopenharmony_ci ar7_device_disable(vlynq_high_data.reset_bit); 66662306a36Sopenharmony_ci res = platform_device_register(&vlynq_high); 66762306a36Sopenharmony_ci if (res) 66862306a36Sopenharmony_ci pr_warn("unable to register vlynq-high: %d\n", res); 66962306a36Sopenharmony_ci } 67062306a36Sopenharmony_ci 67162306a36Sopenharmony_ci if (ar7_has_high_cpmac()) { 67262306a36Sopenharmony_ci res = fixed_phy_add(PHY_POLL, cpmac_high.id, 67362306a36Sopenharmony_ci &fixed_phy_status); 67462306a36Sopenharmony_ci if (!res) { 67562306a36Sopenharmony_ci cpmac_get_mac(1, cpmac_high_data.dev_addr); 67662306a36Sopenharmony_ci 67762306a36Sopenharmony_ci res = platform_device_register(&cpmac_high); 67862306a36Sopenharmony_ci if (res) 67962306a36Sopenharmony_ci pr_warn("unable to register cpmac-high: %d\n", 68062306a36Sopenharmony_ci res); 68162306a36Sopenharmony_ci } else 68262306a36Sopenharmony_ci pr_warn("unable to add cpmac-high phy: %d\n", res); 68362306a36Sopenharmony_ci } else 68462306a36Sopenharmony_ci cpmac_low_data.phy_mask = 0xffffffff; 68562306a36Sopenharmony_ci 68662306a36Sopenharmony_ci res = fixed_phy_add(PHY_POLL, cpmac_low.id, &fixed_phy_status); 68762306a36Sopenharmony_ci if (!res) { 68862306a36Sopenharmony_ci cpmac_get_mac(0, cpmac_low_data.dev_addr); 68962306a36Sopenharmony_ci res = platform_device_register(&cpmac_low); 69062306a36Sopenharmony_ci if (res) 69162306a36Sopenharmony_ci pr_warn("unable to register cpmac-low: %d\n", res); 69262306a36Sopenharmony_ci } else 69362306a36Sopenharmony_ci pr_warn("unable to add cpmac-low phy: %d\n", res); 69462306a36Sopenharmony_ci 69562306a36Sopenharmony_ci detect_leds(); 69662306a36Sopenharmony_ci res = platform_device_register(&ar7_gpio_leds); 69762306a36Sopenharmony_ci if (res) 69862306a36Sopenharmony_ci pr_warn("unable to register leds: %d\n", res); 69962306a36Sopenharmony_ci 70062306a36Sopenharmony_ci res = platform_device_register(&ar7_udc); 70162306a36Sopenharmony_ci if (res) 70262306a36Sopenharmony_ci pr_warn("unable to register usb slave: %d\n", res); 70362306a36Sopenharmony_ci 70462306a36Sopenharmony_ci /* Register watchdog only if enabled in hardware */ 70562306a36Sopenharmony_ci bootcr = ioremap(AR7_REGS_DCL, 4); 70662306a36Sopenharmony_ci val = readl(bootcr); 70762306a36Sopenharmony_ci iounmap(bootcr); 70862306a36Sopenharmony_ci if (val & AR7_WDT_HW_ENA) { 70962306a36Sopenharmony_ci if (ar7_has_high_vlynq()) 71062306a36Sopenharmony_ci ar7_wdt_res.start = UR8_REGS_WDT; 71162306a36Sopenharmony_ci else 71262306a36Sopenharmony_ci ar7_wdt_res.start = AR7_REGS_WDT; 71362306a36Sopenharmony_ci 71462306a36Sopenharmony_ci ar7_wdt_res.end = ar7_wdt_res.start + 0x20; 71562306a36Sopenharmony_ci res = platform_device_register(&ar7_wdt); 71662306a36Sopenharmony_ci if (res) 71762306a36Sopenharmony_ci pr_warn("unable to register watchdog: %d\n", res); 71862306a36Sopenharmony_ci } 71962306a36Sopenharmony_ci 72062306a36Sopenharmony_ci return 0; 72162306a36Sopenharmony_ci} 72262306a36Sopenharmony_cidevice_initcall(ar7_register_devices); 723