diff options
Diffstat (limited to 'target/linux/ar71xx/files')
56 files changed, 3870 insertions, 253 deletions
diff --git a/target/linux/ar71xx/files/arch/mips/ath79/dev-ap9x-pci.c b/target/linux/ar71xx/files/arch/mips/ath79/dev-ap9x-pci.c index c08e43808..d382453b1 100644 --- a/target/linux/ar71xx/files/arch/mips/ath79/dev-ap9x-pci.c +++ b/target/linux/ar71xx/files/arch/mips/ath79/dev-ap9x-pci.c @@ -109,6 +109,12 @@ __init void ap91_pci_init(u8 *cal_data, u8 *mac_addr) pci_enable_ath9k_fixup(0, ap9x_wmac0_data.eeprom_data); } +__init void ap91_pci_init_simple(void) +{ + ap91_pci_init(NULL, NULL); + ap9x_wmac0_data.eeprom_name = "pci_wmac0.eeprom"; +} + static int ap94_pci_plat_dev_init(struct pci_dev *dev) { switch (PCI_SLOT(dev->devfn)) { diff --git a/target/linux/ar71xx/files/arch/mips/ath79/dev-ap9x-pci.h b/target/linux/ar71xx/files/arch/mips/ath79/dev-ap9x-pci.h index d56f7136b..ad288cbdf 100644 --- a/target/linux/ar71xx/files/arch/mips/ath79/dev-ap9x-pci.h +++ b/target/linux/ar71xx/files/arch/mips/ath79/dev-ap9x-pci.h @@ -22,6 +22,7 @@ void ap9x_pci_setup_wmac_leds(unsigned wmac, struct gpio_led *leds, struct ath9k_platform_data *ap9x_pci_get_wmac_data(unsigned wmac); void ap91_pci_init(u8 *cal_data, u8 *mac_addr); +void ap91_pci_init_simple(void); void ap94_pci_init(u8 *cal_data0, u8 *mac_addr0, u8 *cal_data1, u8 *mac_addr1); @@ -38,6 +39,7 @@ static inline struct ath9k_platform_data *ap9x_pci_get_wmac_data(unsigned wmac) } static inline void ap91_pci_init(u8 *cal_data, u8 *mac_addr) {} +static inline void ap91_pci_init_simple(void) {} static inline void ap94_pci_init(u8 *cal_data0, u8 *mac_addr0, u8 *cal_data1, u8 *mac_addr1) {} #endif diff --git a/target/linux/ar71xx/files/arch/mips/ath79/dev-eth.c b/target/linux/ar71xx/files/arch/mips/ath79/dev-eth.c index d2d0ee87f..d7f3595b8 100644 --- a/target/linux/ar71xx/files/arch/mips/ath79/dev-eth.c +++ b/target/linux/ar71xx/files/arch/mips/ath79/dev-eth.c @@ -181,6 +181,7 @@ void __init ath79_register_mdio(unsigned int id, u32 phy_mask) if (ath79_soc == ATH79_SOC_AR9341 || ath79_soc == ATH79_SOC_AR9342 || ath79_soc == ATH79_SOC_AR9344 || + ath79_soc == ATH79_SOC_QCA9556 || ath79_soc == ATH79_SOC_QCA9558) max_id = 1; else @@ -202,6 +203,7 @@ void __init ath79_register_mdio(unsigned int id, u32 phy_mask) case ATH79_SOC_AR9341: case ATH79_SOC_AR9342: case ATH79_SOC_AR9344: + case ATH79_SOC_QCA9556: case ATH79_SOC_QCA9558: if (id == 0) { mdio_dev = &ath79_mdio0_device; @@ -250,12 +252,17 @@ void __init ath79_register_mdio(unsigned int id, u32 phy_mask) } mdio_data->is_ar934x = 1; break; + case ATH79_SOC_QCA9558: if (id == 1) mdio_data->builtin_switch = 1; mdio_data->is_ar934x = 1; break; + case ATH79_SOC_QCA9556: + mdio_data->is_ar934x = 1; + break; + default: break; } @@ -355,6 +362,26 @@ static void ar934x_set_speed_ge0(int speed) iounmap(base); } +static void qca955x_set_speed_xmii(int speed) +{ + void __iomem *base; + u32 val = ath79_get_eth_pll(0, speed); + + base = ioremap_nocache(AR71XX_PLL_BASE, AR71XX_PLL_SIZE); + __raw_writel(val, base + QCA955X_PLL_ETH_XMII_CONTROL_REG); + iounmap(base); +} + +static void qca955x_set_speed_sgmii(int speed) +{ + void __iomem *base; + u32 val = ath79_get_eth_pll(1, speed); + + base = ioremap_nocache(AR71XX_PLL_BASE, AR71XX_PLL_SIZE); + __raw_writel(val, base + QCA955X_PLL_ETH_SGMII_CONTROL_REG); + iounmap(base); +} + static void ath79_set_speed_dummy(int speed) { } @@ -412,8 +439,8 @@ static struct resource ath79_eth0_resources[] = { }, { .name = "mac_irq", .flags = IORESOURCE_IRQ, - .start = ATH79_CPU_IRQ_GE0, - .end = ATH79_CPU_IRQ_GE0, + .start = ATH79_CPU_IRQ(4), + .end = ATH79_CPU_IRQ(4), }, }; @@ -440,8 +467,8 @@ static struct resource ath79_eth1_resources[] = { }, { .name = "mac_irq", .flags = IORESOURCE_IRQ, - .start = ATH79_CPU_IRQ_GE1, - .end = ATH79_CPU_IRQ_GE1, + .start = ATH79_CPU_IRQ(5), + .end = ATH79_CPU_IRQ(5), }, }; @@ -540,6 +567,7 @@ static void __init ath79_init_eth_pll_data(unsigned int id) case ATH79_SOC_AR9341: case ATH79_SOC_AR9342: case ATH79_SOC_AR9344: + case ATH79_SOC_QCA9556: case ATH79_SOC_QCA9558: pll_10 = AR934X_PLL_VAL_10; pll_100 = AR934X_PLL_VAL_100; @@ -605,7 +633,6 @@ static int __init ath79_setup_phy_if_mode(unsigned int id, case ATH79_SOC_AR9341: case ATH79_SOC_AR9342: case ATH79_SOC_AR9344: - case ATH79_SOC_QCA9558: switch (pdata->phy_if_mode) { case PHY_INTERFACE_MODE_MII: case PHY_INTERFACE_MODE_GMII: @@ -617,6 +644,18 @@ static int __init ath79_setup_phy_if_mode(unsigned int id, } break; + case ATH79_SOC_QCA9556: + case ATH79_SOC_QCA9558: + switch (pdata->phy_if_mode) { + case PHY_INTERFACE_MODE_MII: + case PHY_INTERFACE_MODE_RGMII: + case PHY_INTERFACE_MODE_SGMII: + break; + default: + return -EINVAL; + } + break; + default: BUG(); } @@ -654,7 +693,6 @@ static int __init ath79_setup_phy_if_mode(unsigned int id, case ATH79_SOC_AR9341: case ATH79_SOC_AR9342: case ATH79_SOC_AR9344: - case ATH79_SOC_QCA9558: switch (pdata->phy_if_mode) { case PHY_INTERFACE_MODE_MII: case PHY_INTERFACE_MODE_GMII: @@ -664,6 +702,18 @@ static int __init ath79_setup_phy_if_mode(unsigned int id, } break; + case ATH79_SOC_QCA9556: + case ATH79_SOC_QCA9558: + switch (pdata->phy_if_mode) { + case PHY_INTERFACE_MODE_MII: + case PHY_INTERFACE_MODE_RGMII: + case PHY_INTERFACE_MODE_SGMII: + break; + default: + return -EINVAL; + } + break; + default: BUG(); } @@ -691,6 +741,30 @@ void __init ath79_setup_ar933x_phy4_switch(bool mac, bool mdio) iounmap(base); } +void __init ath79_setup_ar934x_eth_cfg(u32 mask) +{ + void __iomem *base; + u32 t; + + base = ioremap(AR934X_GMAC_BASE, AR934X_GMAC_SIZE); + + t = __raw_readl(base + AR934X_GMAC_REG_ETH_CFG); + + t &= ~(AR934X_ETH_CFG_RGMII_GMAC0 | + AR934X_ETH_CFG_MII_GMAC0 | + AR934X_ETH_CFG_GMII_GMAC0 | + AR934X_ETH_CFG_SW_ONLY_MODE | + AR934X_ETH_CFG_SW_PHY_SWAP); + + t |= mask; + + __raw_writel(t, base + AR934X_GMAC_REG_ETH_CFG); + /* flush write */ + __raw_readl(base + AR934X_GMAC_REG_ETH_CFG); + + iounmap(base); +} + static int ath79_eth_instance __initdata; void __init ath79_register_eth(unsigned int id) { @@ -861,7 +935,6 @@ void __init ath79_register_eth(unsigned int id) case ATH79_SOC_AR9341: case ATH79_SOC_AR9342: case ATH79_SOC_AR9344: - case ATH79_SOC_QCA9558: if (id == 0) { pdata->reset_bit = AR934X_RESET_GE0_MAC | AR934X_RESET_GE0_MDIO; @@ -890,6 +963,30 @@ void __init ath79_register_eth(unsigned int id) pdata->fifo_cfg3 = 0x01f00140; break; + case ATH79_SOC_QCA9556: + case ATH79_SOC_QCA9558: + if (id == 0) { + pdata->reset_bit = QCA955X_RESET_GE0_MAC | + QCA955X_RESET_GE0_MDIO; + pdata->set_speed = qca955x_set_speed_xmii; + } else { + pdata->reset_bit = QCA955X_RESET_GE1_MAC | + QCA955X_RESET_GE1_MDIO; + pdata->set_speed = qca955x_set_speed_sgmii; + } + + pdata->ddr_flush = ath79_ddr_no_flush; + pdata->has_gbit = 1; + pdata->is_ar724x = 1; + + if (!pdata->fifo_cfg1) + pdata->fifo_cfg1 = 0x0010ffff; + if (!pdata->fifo_cfg2) + pdata->fifo_cfg2 = 0x015500aa; + if (!pdata->fifo_cfg3) + pdata->fifo_cfg3 = 0x01f00140; + break; + default: BUG(); } @@ -897,6 +994,7 @@ void __init ath79_register_eth(unsigned int id) switch (pdata->phy_if_mode) { case PHY_INTERFACE_MODE_GMII: case PHY_INTERFACE_MODE_RGMII: + case PHY_INTERFACE_MODE_SGMII: if (!pdata->has_gbit) { printk(KERN_ERR "ar71xx: no gbit available on eth%d\n", id); @@ -919,7 +1017,6 @@ void __init ath79_register_eth(unsigned int id) case ATH79_SOC_AR9341: case ATH79_SOC_AR9342: case ATH79_SOC_AR9344: - case ATH79_SOC_QCA9558: if (id == 0) pdata->mii_bus_dev = &ath79_mdio0_device.dev; else @@ -932,6 +1029,11 @@ void __init ath79_register_eth(unsigned int id) pdata->mii_bus_dev = &ath79_mdio1_device.dev; break; + case ATH79_SOC_QCA9556: + case ATH79_SOC_QCA9558: + /* don't assign any MDIO device by default */ + break; + default: pdata->mii_bus_dev = &ath79_mdio0_device.dev; break; @@ -992,7 +1094,10 @@ void __init ath79_init_mac(unsigned char *dst, const unsigned char *src, { int t; - if (!is_valid_ether_addr(src)) { + if (!dst) + return; + + if (!src || !is_valid_ether_addr(src)) { memset(dst, '\0', ETH_ALEN); return; } @@ -1012,7 +1117,10 @@ void __init ath79_init_local_mac(unsigned char *dst, const unsigned char *src) { int i; - if (!is_valid_ether_addr(src)) { + if (!dst) + return; + + if (!src || !is_valid_ether_addr(src)) { memset(dst, '\0', ETH_ALEN); return; } diff --git a/target/linux/ar71xx/files/arch/mips/ath79/dev-eth.h b/target/linux/ar71xx/files/arch/mips/ath79/dev-eth.h index d4f27d9cf..561bf3ff8 100644 --- a/target/linux/ar71xx/files/arch/mips/ath79/dev-eth.h +++ b/target/linux/ar71xx/files/arch/mips/ath79/dev-eth.h @@ -44,5 +44,6 @@ extern struct platform_device ath79_mdio1_device; void ath79_register_mdio(unsigned int id, u32 phy_mask); void ath79_setup_ar933x_phy4_switch(bool mac, bool mdio); +void ath79_setup_ar934x_eth_cfg(u32 mask); #endif /* _ATH79_DEV_ETH_H */ diff --git a/target/linux/ar71xx/files/arch/mips/ath79/dev-m25p80.c b/target/linux/ar71xx/files/arch/mips/ath79/dev-m25p80.c index 66115b1c4..9323b3123 100644 --- a/target/linux/ar71xx/files/arch/mips/ath79/dev-m25p80.c +++ b/target/linux/ar71xx/files/arch/mips/ath79/dev-m25p80.c @@ -113,5 +113,6 @@ void __init ath79_register_m25p80_multi(struct flash_platform_data *pdata) add_mtd_concat_notifier(); ath79_spi_data.bus_num = 0; ath79_spi_data.num_chipselect = 2; + ath79_spi0_cdata.is_flash = true; ath79_register_spi(&ath79_spi_data, ath79_spi_info, 2); } diff --git a/target/linux/ar71xx/files/arch/mips/ath79/dev-nfc.c b/target/linux/ar71xx/files/arch/mips/ath79/dev-nfc.c new file mode 100644 index 000000000..5208279ad --- /dev/null +++ b/target/linux/ar71xx/files/arch/mips/ath79/dev-nfc.c @@ -0,0 +1,136 @@ +/* + * Atheros AR934X SoCs built-in NAND flash controller support + * + * Copyright (C) 2011-2012 Gabor Juhos <juhosg@openwrt.org> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + */ + +#include <linux/kernel.h> +#include <linux/delay.h> +#include <linux/init.h> +#include <linux/irq.h> +#include <linux/dma-mapping.h> +#include <linux/etherdevice.h> +#include <linux/platform_device.h> +#include <linux/platform/ar934x_nfc.h> + +#include <asm/mach-ath79/ath79.h> +#include <asm/mach-ath79/ar71xx_regs.h> + +#include "dev-nfc.h" + +static struct resource ath79_nfc_resources[2]; +static u64 ar934x_nfc_dmamask = DMA_BIT_MASK(32); +static struct ar934x_nfc_platform_data ath79_nfc_data; + +static struct platform_device ath79_nfc_device = { + .name = AR934X_NFC_DRIVER_NAME, + .id = -1, + .resource = ath79_nfc_resources, + .num_resources = ARRAY_SIZE(ath79_nfc_resources), + .dev = { + .dma_mask = &ar934x_nfc_dmamask, + .coherent_dma_mask = DMA_BIT_MASK(32), + .platform_data = &ath79_nfc_data, + }, +}; + +static void __init ath79_nfc_init_resource(struct resource res[2], + unsigned long base, + unsigned long size, + int irq) +{ + memset(res, 0, sizeof(res)); + + res[0].flags = IORESOURCE_MEM; + res[0].start = base; + res[0].end = base + size - 1; + + res[1].flags = IORESOURCE_IRQ; + res[1].start = irq; + res[1].end = irq; +} + +static void ar934x_nfc_hw_reset(bool active) +{ + if (active) { + ath79_device_reset_set(AR934X_RESET_NANDF); + udelay(100); + + ath79_device_reset_set(AR934X_RESET_ETH_SWITCH_ANALOG); + udelay(250); + } else { + ath79_device_reset_clear(AR934X_RESET_ETH_SWITCH_ANALOG); + udelay(250); + + ath79_device_reset_clear(AR934X_RESET_NANDF); + udelay(100); + } +} + +static void ar934x_nfc_setup(void) +{ + ath79_nfc_data.hw_reset = ar934x_nfc_hw_reset; + + ath79_nfc_init_resource(ath79_nfc_resources, + AR934X_NFC_BASE, AR934X_NFC_SIZE, + ATH79_MISC_IRQ(21)); + + platform_device_register(&ath79_nfc_device); +} + +static void qca955x_nfc_hw_reset(bool active) +{ + if (active) { + ath79_device_reset_set(QCA955X_RESET_NANDF); + udelay(250); + } else { + ath79_device_reset_clear(QCA955X_RESET_NANDF); + udelay(100); + } +} + +static void qca955x_nfc_setup(void) +{ + ath79_nfc_data.hw_reset = qca955x_nfc_hw_reset; + + ath79_nfc_init_resource(ath79_nfc_resources, + QCA955X_NFC_BASE, QCA955X_NFC_SIZE, + ATH79_MISC_IRQ(21)); + + platform_device_register(&ath79_nfc_device); +} + +void __init ath79_nfc_set_select_chip(void (*f)(int chip_no)) +{ + ath79_nfc_data.select_chip = f; +} + +void __init ath79_nfc_set_scan_fixup(int (*f)(struct mtd_info *mtd)) +{ + ath79_nfc_data.scan_fixup = f; +} + +void __init ath79_nfc_set_swap_dma(bool enable) +{ + ath79_nfc_data.swap_dma = enable; +} + +void __init ath79_nfc_set_parts(struct mtd_partition *parts, int nr_parts) +{ + ath79_nfc_data.parts = parts; + ath79_nfc_data.nr_parts = nr_parts; +} + +void __init ath79_register_nfc(void) +{ + if (soc_is_ar934x()) + ar934x_nfc_setup(); + else if (soc_is_qca955x()) + qca955x_nfc_setup(); + else + BUG(); +} diff --git a/target/linux/ar71xx/files/arch/mips/ath79/dev-nfc.h b/target/linux/ar71xx/files/arch/mips/ath79/dev-nfc.h new file mode 100644 index 000000000..46a090d9b --- /dev/null +++ b/target/linux/ar71xx/files/arch/mips/ath79/dev-nfc.h @@ -0,0 +1,31 @@ +/* + * Atheros AR934X SoCs built-in NAND Flash Controller support + * + * Copyright (C) 2011-2012 Gabor Juhos <juhosg@openwrt.org> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + */ + +#ifndef _ATH79_DEV_NFC_H +#define _ATH79_DEV_NFC_H + +struct mtd_partition; + +#ifdef CONFIG_ATH79_DEV_NFC +void ath79_nfc_set_parts(struct mtd_partition *parts, int nr_parts); +void ath79_nfc_set_select_chip(void (*f)(int chip_no)); +void ath79_nfc_set_scan_fixup(int (*f)(struct mtd_info *mtd)); +void ath79_nfc_set_swap_dma(bool enable); +void ath79_register_nfc(void); +#else +static inline void ath79_nfc_set_parts(struct mtd_partition *parts, + int nr_parts) {} +static inline void ath79_nfc_set_select_chip(void (*f)(int chip_no)) {} +static inline void ath79_nfc_set_scan_fixup(int (*f)(struct mtd_info *mtd)) {} +static inline void ath79_nfc_set_swap_dma(bool enable) {} +static inline void ath79_register_nfc(void) {} +#endif + +#endif /* _ATH79_DEV_NFC_H */ diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-ap132.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-ap132.c new file mode 100644 index 000000000..86fd8bd7a --- /dev/null +++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-ap132.c @@ -0,0 +1,189 @@ +/* + * Atheros AP132 reference board support + * + * Copyright (c) 2012 Qualcomm Atheros + * Copyright (c) 2012 Gabor Juhos <juhosg@openwrt.org> + * Copyright (c) 2013 Embedded Wireless GmbH <info@embeddedwireless.de> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#include <linux/platform_device.h> +#include <linux/ar8216_platform.h> + +#include <asm/mach-ath79/ar71xx_regs.h> + +#include "common.h" +#include "dev-ap9x-pci.h" +#include "dev-gpio-buttons.h" +#include "dev-eth.h" +#include "dev-leds-gpio.h" +#include "dev-m25p80.h" +#include "dev-usb.h" +#include "dev-wmac.h" +#include "machtypes.h" + +#define AP132_GPIO_LED_USB 4 +#define AP132_GPIO_LED_WLAN_5G 12 +#define AP132_GPIO_LED_WLAN_2G 13 +#define AP132_GPIO_LED_STATUS_RED 14 +#define AP132_GPIO_LED_WPS_RED 15 + +#define AP132_GPIO_BTN_WPS 16 + +#define AP132_KEYS_POLL_INTERVAL 20 /* msecs */ +#define AP132_KEYS_DEBOUNCE_INTERVAL (3 * AP132_KEYS_POLL_INTERVAL) + +#define AP132_MAC0_OFFSET 0 +#define AP132_WMAC_CALDATA_OFFSET 0x1000 + +static struct gpio_led ap132_leds_gpio[] __initdata = { + { + .name = "ap132:red:status", + .gpio = AP132_GPIO_LED_STATUS_RED, + .active_low = 1, + }, + { + .name = "ap132:red:wps", + .gpio = AP132_GPIO_LED_WPS_RED, + .active_low = 1, + }, + { + .name = "ap132:red:wlan-2g", + .gpio = AP132_GPIO_LED_WLAN_2G, + .active_low = 1, + }, + { + .name = "ap132:red:usb", + .gpio = AP132_GPIO_LED_USB, + .active_low = 1, + } +}; + +static struct gpio_keys_button ap132_gpio_keys[] __initdata = { + { + .desc = "WPS button", + .type = EV_KEY, + .code = KEY_WPS_BUTTON, + .debounce_interval = AP132_KEYS_DEBOUNCE_INTERVAL, + .gpio = AP132_GPIO_BTN_WPS, + .active_low = 1, + }, +}; + +static struct ar8327_pad_cfg ap132_ar8327_pad0_cfg; + +static struct ar8327_platform_data ap132_ar8327_data = { + .pad0_cfg = &ap132_ar8327_pad0_cfg, + .port0_cfg = { + .force_link = 1, + .speed = AR8327_PORT_SPEED_1000, + .duplex = 1, + .txpause = 1, + .rxpause = 1, + }, +}; + +static struct mdio_board_info ap132_mdio1_info[] = { + { + .bus_id = "ag71xx-mdio.1", + .phy_addr = 0, + .platform_data = &ap132_ar8327_data, + }, +}; + +static void __init ap132_mdio_setup(void) +{ + void __iomem *base; + u32 t; + +#define GPIO_IN_ENABLE3_ADDRESS 0x0050 +#define GPIO_IN_ENABLE3_MII_GE1_MDI_MASK 0x00ff0000 +#define GPIO_IN_ENABLE3_MII_GE1_MDI_LSB 16 +#define GPIO_IN_ENABLE3_MII_GE1_MDI_SET(x) (((x) << GPIO_IN_ENABLE3_MII_GE1_MDI_LSB) & GPIO_IN_ENABLE3_MII_GE1_MDI_MASK) +#define GPIO_OUT_FUNCTION4_ADDRESS 0x003c +#define GPIO_OUT_FUNCTION4_ENABLE_GPIO_19_MASK 0xff000000 +#define GPIO_OUT_FUNCTION4_ENABLE_GPIO_19_LSB 24 +#define GPIO_OUT_FUNCTION4_ENABLE_GPIO_19_SET(x) (((x) << GPIO_OUT_FUNCTION4_ENABLE_GPIO_19_LSB) & GPIO_OUT_FUNCTION4_ENABLE_GPIO_19_MASK) +#define GPIO_OUT_FUNCTION4_ENABLE_GPIO_17_MASK 0x0000ff00 +#define GPIO_OUT_FUNCTION4_ENABLE_GPIO_17_LSB 8 +#define GPIO_OUT_FUNCTION4_ENABLE_GPIO_17_SET(x) (((x) << GPIO_OUT_FUNCTION4_ENABLE_GPIO_17_LSB) & GPIO_OUT_FUNCTION4_ENABLE_GPIO_17_MASK) + + base = ioremap(AR71XX_GPIO_BASE, AR71XX_GPIO_SIZE); + + t = __raw_readl(base + GPIO_IN_ENABLE3_ADDRESS); + t &= ~GPIO_IN_ENABLE3_MII_GE1_MDI_MASK; + t |= GPIO_IN_ENABLE3_MII_GE1_MDI_SET(19); + __raw_writel(t, base + GPIO_IN_ENABLE3_ADDRESS); + + + __raw_writel(__raw_readl(base + AR71XX_GPIO_REG_OE) & ~(1 << 19), base + AR71XX_GPIO_REG_OE); + + __raw_writel(__raw_readl(base + AR71XX_GPIO_REG_OE) & ~(1 << 17), base + AR71XX_GPIO_REG_OE); + + + t = __raw_readl(base + GPIO_OUT_FUNCTION4_ADDRESS); + t &= ~(GPIO_OUT_FUNCTION4_ENABLE_GPIO_19_MASK | GPIO_OUT_FUNCTION4_ENABLE_GPIO_17_MASK); + t |= GPIO_OUT_FUNCTION4_ENABLE_GPIO_19_SET(0x20) | GPIO_OUT_FUNCTION4_ENABLE_GPIO_17_SET(0x21); + __raw_writel(t, base + GPIO_OUT_FUNCTION4_ADDRESS); + + iounmap(base); + +} + +static void __init ap132_setup(void) +{ + u8 *art = (u8 *) KSEG1ADDR(0x1fff0000); + + ath79_register_m25p80(NULL); + + ath79_register_leds_gpio(-1, ARRAY_SIZE(ap132_leds_gpio), + ap132_leds_gpio); + ath79_register_gpio_keys_polled(-1, AP132_KEYS_POLL_INTERVAL, + ARRAY_SIZE(ap132_gpio_keys), + ap132_gpio_keys); + + ath79_register_usb(); + + ath79_register_wmac(art + AP132_WMAC_CALDATA_OFFSET, NULL); + + /* GMAC0 of the AR8327 switch is connected to GMAC1 via SGMII */ + ap132_ar8327_pad0_cfg.mode = AR8327_PAD_MAC_SGMII; + ap132_ar8327_pad0_cfg.sgmii_delay_en = true; + + ath79_eth1_pll_data.pll_1000 = 0x03000101; + + ap132_mdio_setup(); + + ath79_register_mdio(1, 0x0); + + ath79_init_mac(ath79_eth1_data.mac_addr, art + AP132_MAC0_OFFSET, 0); + + mdiobus_register_board_info(ap132_mdio1_info, + ARRAY_SIZE(ap132_mdio1_info)); + + /* GMAC1 is connected to the SGMII interface */ + ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_SGMII; + ath79_eth1_data.speed = SPEED_1000; + ath79_eth1_data.duplex = DUPLEX_FULL; + ath79_eth1_data.phy_mask = BIT(0); + ath79_eth1_data.mii_bus_dev = &ath79_mdio1_device.dev; + + ath79_register_eth(1); +} + +MIPS_MACHINE(ATH79_MACH_AP132, "AP132", + "Atheros AP132 reference board", + ap132_setup); + diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-cap4200ag.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-cap4200ag.c new file mode 100644 index 000000000..18944c40f --- /dev/null +++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-cap4200ag.c @@ -0,0 +1,131 @@ +/* + * Senao CAP4200AG board support + * + * Copyright (C) 2012 Gabor Juhos <juhosg@openwrt.org> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + */ + +#include <linux/pci.h> +#include <linux/phy.h> +#include <linux/platform_device.h> +#include <linux/ath9k_platform.h> + +#include <asm/mach-ath79/ar71xx_regs.h> + +#include "common.h" +#include "dev-ap9x-pci.h" +#include "dev-eth.h" +#include "dev-gpio-buttons.h" +#include "dev-leds-gpio.h" +#include "dev-m25p80.h" +#include "dev-spi.h" +#include "dev-usb.h" +#include "dev-wmac.h" +#include "machtypes.h" + +#define CAP4200AG_GPIO_LED_PWR_GREEN 12 +#define CAP4200AG_GPIO_LED_PWR_AMBER 13 +#define CAP4200AG_GPIO_LED_LAN_GREEN 14 +#define CAP4200AG_GPIO_LED_LAN_AMBER 15 +#define CAP4200AG_GPIO_LED_WLAN_GREEN 18 +#define CAP4200AG_GPIO_LED_WLAN_AMBER 19 + +#define CAP4200AG_GPIO_BTN_RESET 17 + +#define CAP4200AG_KEYS_POLL_INTERVAL 20 /* msecs */ +#define CAP4200AG_KEYS_DEBOUNCE_INTERVAL (3 * CAP4200AG_KEYS_POLL_INTERVAL) + +#define CAP4200AG_MAC_OFFSET 0 +#define CAP4200AG_WMAC_CALDATA_OFFSET 0x1000 +#define CAP4200AG_PCIE_CALDATA_OFFSET 0x5000 + +static struct gpio_led cap4200ag_leds_gpio[] __initdata = { + { + .name = "senao:green:pwr", + .gpio = CAP4200AG_GPIO_LED_PWR_GREEN, + .active_low = 1, + }, + { + .name = "senao:amber:pwr", + .gpio = CAP4200AG_GPIO_LED_PWR_AMBER, + .active_low = 1, + }, + { + .name = "senao:green:lan", + .gpio = CAP4200AG_GPIO_LED_LAN_GREEN, + .active_low = 1, + }, + { + .name = "senao:amber:lan", + .gpio = CAP4200AG_GPIO_LED_LAN_AMBER, + .active_low = 1, + }, + { + .name = "senao:green:wlan", + .gpio = CAP4200AG_GPIO_LED_WLAN_GREEN, + .active_low = 1, + }, + { + .name = "senao:amber:wlan", + .gpio = CAP4200AG_GPIO_LED_WLAN_AMBER, + .active_low = 1, + }, +}; + +static struct gpio_keys_button cap4200ag_gpio_keys[] __initdata = { + { + .desc = "Reset button", + .type = EV_KEY, + .code = KEY_RESTART, + .debounce_interval = CAP4200AG_KEYS_DEBOUNCE_INTERVAL, + .gpio = CAP4200AG_GPIO_BTN_RESET, + .active_low = 1, + }, +}; + +static void __init cap4200ag_setup(void) +{ + u8 *art = (u8 *) KSEG1ADDR(0x1fff0000); + u8 mac[6]; + + ath79_gpio_output_select(CAP4200AG_GPIO_LED_LAN_GREEN, + AR934X_GPIO_OUT_GPIO); + ath79_gpio_output_select(CAP4200AG_GPIO_LED_LAN_AMBER, + AR934X_GPIO_OUT_GPIO); + + ath79_register_m25p80(NULL); + + ath79_register_leds_gpio(-1, ARRAY_SIZE(cap4200ag_leds_gpio), + cap4200ag_leds_gpio); + ath79_register_gpio_keys_polled(-1, CAP4200AG_KEYS_POLL_INTERVAL, + ARRAY_SIZE(cap4200ag_gpio_keys), + cap4200ag_gpio_keys); + + ath79_init_mac(mac, art + CAP4200AG_MAC_OFFSET, -1); + ath79_wmac_disable_2ghz(); + ath79_register_wmac(art + CAP4200AG_WMAC_CALDATA_OFFSET, mac); + + ath79_init_mac(mac, art + CAP4200AG_MAC_OFFSET, -2); + ap91_pci_init(art + CAP4200AG_PCIE_CALDATA_OFFSET, mac); + + ath79_setup_ar934x_eth_cfg(AR934X_ETH_CFG_RGMII_GMAC0 | + AR934X_ETH_CFG_SW_ONLY_MODE); + + ath79_register_mdio(0, 0x0); + + ath79_init_mac(ath79_eth0_data.mac_addr, + art + CAP4200AG_MAC_OFFSET, -2); + + /* GMAC0 is connected to an external PHY */ + ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; + ath79_eth0_data.phy_mask = BIT(0); + ath79_eth0_data.mii_bus_dev = &ath79_mdio0_device.dev; + ath79_eth0_pll_data.pll_1000 = 0x06000000; + ath79_register_eth(0); +} + +MIPS_MACHINE(ATH79_MACH_CAP4200AG, "CAP4200AG", "Senao CAP4200AG", + cap4200ag_setup); diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-dir-825-b1.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-dir-825-b1.c index 1b4b49075..c95866444 100644 --- a/target/linux/ar71xx/files/arch/mips/ath79/mach-dir-825-b1.c +++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-dir-825-b1.c @@ -40,11 +40,13 @@ #define DIR825B1_KEYS_POLL_INTERVAL 20 /* msecs */ #define DIR825B1_KEYS_DEBOUNCE_INTERVAL (3 * DIR825B1_KEYS_POLL_INTERVAL) -#define DIR825B1_CAL_LOCATION_0 0x1f661000 -#define DIR825B1_CAL_LOCATION_1 0x1f665000 +#define DIR825B1_CAL0_OFFSET 0x1000 +#define DIR825B1_CAL1_OFFSET 0x5000 +#define DIR825B1_MAC0_OFFSET 0xffa0 +#define DIR825B1_MAC1_OFFSET 0xffb4 -#define DIR825B1_MAC_LOCATION_0 0x1f66ffa0 -#define DIR825B1_MAC_LOCATION_1 0x1f66ffb4 +#define DIR825B1_CAL_LOCATION_0 0x1f660000 +#define DIR825B1_CAL_LOCATION_1 0x1f7f0000 static struct gpio_led dir825b1_leds_gpio[] __initdata = { { @@ -111,10 +113,9 @@ static struct platform_device dir825b1_rtl8366s_device = { } }; -static void dir825b1_read_ascii_mac(u8 *dest, unsigned int src_addr) +static void dir825b1_read_ascii_mac(u8 *dest, u8 *src) { int ret; - u8 *src = (u8 *)KSEG1ADDR(src_addr); ret = sscanf(src, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx", &dest[0], &dest[1], &dest[2], @@ -124,23 +125,58 @@ static void dir825b1_read_ascii_mac(u8 *dest, unsigned int src_addr) memset(dest, 0, ETH_ALEN); } -static void __init dir825b1_setup(void) +static bool __init dir825b1_is_caldata_valid(u8 *p) +{ + u16 *magic0, *magic1; + + magic0 = (u16 *)(p + DIR825B1_CAL0_OFFSET); + magic1 = (u16 *)(p + DIR825B1_CAL1_OFFSET); + + return (*magic0 == 0xa55a && *magic1 == 0xa55a); +} + +static void __init dir825b1_wlan_init(void) { - u8 mac1[ETH_ALEN], mac2[ETH_ALEN]; + u8 *caldata; + u8 mac0[ETH_ALEN], mac1[ETH_ALEN]; + u8 wmac0[ETH_ALEN], wmac1[ETH_ALEN]; + + caldata = (u8 *) KSEG1ADDR(DIR825B1_CAL_LOCATION_0); + if (!dir825b1_is_caldata_valid(caldata)) { + caldata = (u8 *)KSEG1ADDR(DIR825B1_CAL_LOCATION_1); + if (!dir825b1_is_caldata_valid(caldata)) { + pr_err("no calibration data found\n"); + return; + } + } + + dir825b1_read_ascii_mac(mac0, caldata + DIR825B1_MAC0_OFFSET); + dir825b1_read_ascii_mac(mac1, caldata + DIR825B1_MAC1_OFFSET); + + ath79_init_mac(ath79_eth0_data.mac_addr, mac0, 0); + ath79_init_mac(ath79_eth1_data.mac_addr, mac1, 0); + ath79_init_mac(wmac0, mac0, 0); + ath79_init_mac(wmac1, mac1, 1); + + ap9x_pci_setup_wmac_led_pin(0, 5); + ap9x_pci_setup_wmac_led_pin(1, 5); - dir825b1_read_ascii_mac(mac1, DIR825B1_MAC_LOCATION_0); - dir825b1_read_ascii_mac(mac2, DIR825B1_MAC_LOCATION_1); + ap94_pci_init(caldata + DIR825B1_CAL0_OFFSET, wmac0, + caldata + DIR825B1_CAL1_OFFSET, wmac1); +} + +static void __init dir825b1_setup(void) +{ + dir825b1_wlan_init(); ath79_register_mdio(0, 0x0); - ath79_init_mac(ath79_eth0_data.mac_addr, mac1, 2); ath79_eth0_data.mii_bus_dev = &dir825b1_rtl8366s_device.dev; ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ath79_eth0_data.speed = SPEED_1000; ath79_eth0_data.duplex = DUPLEX_FULL; ath79_eth0_pll_data.pll_1000 = 0x11110000; - ath79_init_mac(ath79_eth1_data.mac_addr, mac1, 3); ath79_eth1_data.mii_bus_dev = &dir825b1_rtl8366s_device.dev; ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ath79_eth1_data.phy_mask = 0x10; @@ -161,12 +197,6 @@ static void __init dir825b1_setup(void) ath79_register_usb(); platform_device_register(&dir825b1_rtl8366s_device); - - ap9x_pci_setup_wmac_led_pin(0, 5); - ap9x_pci_setup_wmac_led_pin(1, 5); - - ap94_pci_init((u8 *) KSEG1ADDR(DIR825B1_CAL_LOCATION_0), mac1, - (u8 *) KSEG1ADDR(DIR825B1_CAL_LOCATION_1), mac2); } MIPS_MACHINE(ATH79_MACH_DIR_825_B1, "DIR-825-B1", "D-Link DIR-825 rev. B1", diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-dir-825-c1.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-dir-825-c1.c new file mode 100644 index 000000000..423b91855 --- /dev/null +++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-dir-825-c1.c @@ -0,0 +1,248 @@ +/* + * D-Link DIR-825 rev. C1 board support + * + * Copyright (C) 2013 Alexander Stadler + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + */ + +#include <linux/pci.h> +#include <linux/phy.h> +#include <linux/gpio.h> +#include <linux/platform_device.h> +#include <linux/ath9k_platform.h> +#include <linux/ar8216_platform.h> + +#include <asm/mach-ath79/ar71xx_regs.h> + +#include "common.h" +#include "dev-ap9x-pci.h" +#include "dev-eth.h" +#include "dev-gpio-buttons.h" +#include "dev-leds-gpio.h" +#include "dev-m25p80.h" +#include "dev-spi.h" +#include "dev-usb.h" +#include "dev-wmac.h" +#include "machtypes.h" + +#define DIR825C1_GPIO_LED_BLUE_USB 11 +#define DIR825C1_GPIO_LED_ORANGE_POWER 14 +#define DIR825C1_GPIO_LED_BLUE_POWER 22 +#define DIR825C1_GPIO_LED_BLUE_WPS 15 +#define DIR825C1_GPIO_LED_ORANGE_PLANET 19 +#define DIR825C1_GPIO_LED_BLUE_PLANET 18 + +#define DIR825C1_GPIO_BTN_RESET 17 +#define DIR825C1_GPIO_BTN_WPS 16 + +#define DIR825C1_KEYS_POLL_INTERVAL 20 /* msecs */ +#define DIR825C1_KEYS_DEBOUNCE_INTERVAL (3 * DIR825C1_KEYS_POLL_INTERVAL) + +#define DIR825C1_MAC0_OFFSET 0x4 +#define DIR825C1_MAC1_OFFSET 0x18 +#define DIR825C1_WMAC_CALDATA_OFFSET 0x1000 +#define DIR825C1_PCIE_CALDATA_OFFSET 0x5000 + +static struct gpio_led dir825c1_leds_gpio[] __initdata = { + { + .name = "d-link:blue:usb", + .gpio = DIR825C1_GPIO_LED_BLUE_USB, + .active_low = 1, + }, + { + .name = "d-link:orange:power", + .gpio = DIR825C1_GPIO_LED_ORANGE_POWER, + .active_low = 1, + }, + { + .name = "d-link:blue:power", + .gpio = DIR825C1_GPIO_LED_BLUE_POWER, + .active_low = 1, + }, + { + .name = "d-link:blue:wps", + .gpio = DIR825C1_GPIO_LED_BLUE_WPS, + .active_low = 1, + }, + { + .name = "d-link:orange:planet", + .gpio = DIR825C1_GPIO_LED_ORANGE_PLANET, + .active_low = 1, + }, + { + .name = "d-link:blue:planet", + .gpio = DIR825C1_GPIO_LED_BLUE_PLANET, + .active_low = 1, + }, +}; + +static struct gpio_led dir835a1_leds_gpio[] __initdata = { + { + .name = "d-link:orange:power", + .gpio = DIR825C1_GPIO_LED_ORANGE_POWER, + .active_low = 1, + }, + { + .name = "d-link:green:power", + .gpio = DIR825C1_GPIO_LED_BLUE_POWER, + .active_low = 1, + }, + { + .name = "d-link:blue:wps", + .gpio = DIR825C1_GPIO_LED_BLUE_WPS, + .active_low = 1, + }, + { + .name = "d-link:orange:planet", + .gpio = DIR825C1_GPIO_LED_ORANGE_PLANET, + .active_low = 1, + }, + { + .name = "d-link:green:planet", + .gpio = DIR825C1_GPIO_LED_BLUE_PLANET, + .active_low = 1, + }, +}; + +static struct gpio_keys_button dir825c1_gpio_keys[] __initdata = { + { + .desc = "reset", + .type = EV_KEY, + .code = KEY_RESTART, + .debounce_interval = DIR825C1_KEYS_DEBOUNCE_INTERVAL, + .gpio = DIR825C1_GPIO_BTN_RESET, + .active_low = 1, + }, + { + .desc = "wps", + .type = EV_KEY, + .code = KEY_WPS_BUTTON, + .debounce_interval = DIR825C1_KEYS_DEBOUNCE_INTERVAL, + .gpio = DIR825C1_GPIO_BTN_WPS, + .active_low = 1, + }, +}; + +static struct ar8327_pad_cfg dir825c1_ar8327_pad0_cfg = { + .mode = AR8327_PAD_MAC_RGMII, + .txclk_delay_en = true, + .rxclk_delay_en = true, + .txclk_delay_sel = AR8327_CLK_DELAY_SEL1, + .rxclk_delay_sel = AR8327_CLK_DELAY_SEL2, +}; + +static struct ar8327_led_cfg dir825c1_ar8327_led_cfg = { + .led_ctrl0 = 0xc737c737, + .led_ctrl1 = 0x00000000, + .led_ctrl2 = 0x00000000, + .led_ctrl3 = 0x0030c300, + .open_drain = false, +}; + +static struct ar8327_platform_data dir825c1_ar8327_data = { + .pad0_cfg = &dir825c1_ar8327_pad0_cfg, + .port0_cfg = { + .force_link = 1, + .speed = AR8327_PORT_SPEED_1000, + .duplex = 1, + .txpause = 1, + .rxpause = 1, + }, + .led_cfg = &dir825c1_ar8327_led_cfg, +}; + +static struct mdio_board_info dir825c1_mdio0_info[] = { + { + .bus_id = "ag71xx-mdio.0", + .phy_addr = 0, + .platform_data = &dir825c1_ar8327_data, + }, +}; + +static void dir825c1_read_ascii_mac(u8 *dest, u8 *src) +{ + int ret; + + ret = sscanf(src, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx", + &dest[0], &dest[1], &dest[2], + &dest[3], &dest[4], &dest[5]); + + if (ret != ETH_ALEN) + memset(dest, 0, ETH_ALEN); +} + +static void __init dir825c1_generic_setup(void) +{ + u8 *mac = (u8 *) KSEG1ADDR(0x1ffe0000); + u8 *art = (u8 *) KSEG1ADDR(0x1fff0000); + u8 mac0[ETH_ALEN], mac1[ETH_ALEN]; + u8 wmac0[ETH_ALEN], wmac1[ETH_ALEN]; + + dir825c1_read_ascii_mac(mac0, mac + DIR825C1_MAC0_OFFSET); + dir825c1_read_ascii_mac(mac1, mac + DIR825C1_MAC1_OFFSET); + + ath79_register_m25p80(NULL); + + ath79_register_gpio_keys_polled(-1, DIR825C1_KEYS_POLL_INTERVAL, + ARRAY_SIZE(dir825c1_gpio_keys), + dir825c1_gpio_keys); + + ath79_init_mac(wmac0, mac0, 0); + ath79_register_wmac(art + DIR825C1_WMAC_CALDATA_OFFSET, wmac0); + + ath79_init_mac(wmac1, mac1, 1); + ap91_pci_init(art + DIR825C1_PCIE_CALDATA_OFFSET, wmac1); + + ath79_setup_ar934x_eth_cfg(AR934X_ETH_CFG_RGMII_GMAC0); + + mdiobus_register_board_info(dir825c1_mdio0_info, + ARRAY_SIZE(dir825c1_mdio0_info)); + + ath79_register_mdio(0, 0x0); + + ath79_init_mac(ath79_eth0_data.mac_addr, mac0, 0); + + /* GMAC0 is connected to an AR8327N switch */ + ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; + ath79_eth0_data.phy_mask = BIT(0); + ath79_eth0_data.mii_bus_dev = &ath79_mdio0_device.dev; + ath79_eth0_pll_data.pll_1000 = 0x06000000; + ath79_register_eth(0); + + ath79_register_usb(); +} + +static void __init dir825c1_setup(void) +{ + ath79_gpio_output_select(DIR825C1_GPIO_LED_BLUE_USB, + AR934X_GPIO_OUT_GPIO); + + ath79_register_leds_gpio(-1, ARRAY_SIZE(dir825c1_leds_gpio), + dir825c1_leds_gpio); + + ap9x_pci_setup_wmac_led_pin(0, 13); + ap9x_pci_setup_wmac_led_pin(1, 32); + + dir825c1_generic_setup(); +} + +static void __init dir835a1_setup(void) +{ + dir825c1_ar8327_data.led_cfg = NULL; + + ath79_register_leds_gpio(-1, ARRAY_SIZE(dir835a1_leds_gpio), + dir835a1_leds_gpio); + + dir825c1_generic_setup(); +} + +MIPS_MACHINE(ATH79_MACH_DIR_825_C1, "DIR-825-C1", + "D-Link DIR-825 rev. C1", + dir825c1_setup); + +MIPS_MACHINE(ATH79_MACH_DIR_835_A1, "DIR-835-A1", + "D-Link DIR-835 rev. A1", + dir835a1_setup); diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-hornet-ub.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-hornet-ub.c index f8870e711..d2cfb0972 100644 --- a/target/linux/ar71xx/files/arch/mips/ath79/mach-hornet-ub.c +++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-hornet-ub.c @@ -101,8 +101,9 @@ static void __init hornet_ub_gpio_setup(void) t |= AR933X_BOOTSTRAP_MDIO_GPIO_EN; ath79_reset_wr(AR933X_RESET_REG_BOOTSTRAP, t); - ath79_set_usb_power_gpio(HORNET_UB_GPIO_USB_POWER, GPIOF_OUT_INIT_HIGH, - "USB power"); + gpio_request_one(HORNET_UB_GPIO_USB_POWER, + GPIOF_OUT_INIT_HIGH | GPIOF_EXPORT_DIR_FIXED, + "USB power"); } static void __init hornet_ub_setup(void) diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-mr600.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-mr600.c new file mode 100644 index 000000000..496956446 --- /dev/null +++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-mr600.c @@ -0,0 +1,176 @@ +/* + * OpenMesh OM2P board support + * + * Copyright (C) 2012 Marek Lindner <marek@open-mesh.com> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#include <linux/pci.h> +#include <linux/phy.h> +#include <linux/platform_device.h> +#include <linux/ath9k_platform.h> + +#include <asm/mach-ath79/ar71xx_regs.h> + +#include "common.h" +#include "dev-ap9x-pci.h" +#include "dev-eth.h" +#include "dev-gpio-buttons.h" +#include "dev-leds-gpio.h" +#include "dev-m25p80.h" +#include "dev-spi.h" +#include "dev-wmac.h" +#include "machtypes.h" + +#define MR600_GPIO_LED_WLAN58 12 +#define MR600_GPIO_LED_WPS 13 +#define MR600_GPIO_LED_POWER 14 + +#define MR600V2_GPIO_LED_WLAN58_RED 12 +#define MR600V2_GPIO_LED_WPS 13 +#define MR600V2_GPIO_LED_POWER 14 +#define MR600V2_GPIO_LED_WLAN24_GREEN 18 +#define MR600V2_GPIO_LED_WLAN24_YELLOW 19 +#define MR600V2_GPIO_LED_WLAN24_RED 20 +#define MR600V2_GPIO_LED_WLAN58_GREEN 21 +#define MR600V2_GPIO_LED_WLAN58_YELLOW 22 + +#define MR600_GPIO_BTN_RESET 17 + +#define MR600_KEYS_POLL_INTERVAL 20 /* msecs */ +#define MR600_KEYS_DEBOUNCE_INTERVAL (3 * MR600_KEYS_POLL_INTERVAL) + +#define MR600_MAC_OFFSET 0 +#define MR600_WMAC_CALDATA_OFFSET 0x1000 +#define MR600_PCIE_CALDATA_OFFSET 0x5000 + +static struct gpio_led mr600_leds_gpio[] __initdata = { + { + .name = "mr600:orange:power", + .gpio = MR600_GPIO_LED_POWER, + .active_low = 1, + }, + { + .name = "mr600:blue:wps", + .gpio = MR600_GPIO_LED_WPS, + .active_low = 1, + }, + { + .name = "mr600:green:wlan58", + .gpio = MR600_GPIO_LED_WLAN58, + .active_low = 1, + }, +}; + +static struct gpio_led mr600v2_leds_gpio[] __initdata = { + { + .name = "mr600:blue:power", + .gpio = MR600V2_GPIO_LED_POWER, + .active_low = 1, + }, + { + .name = "mr600:blue:wps", + .gpio = MR600V2_GPIO_LED_WPS, + .active_low = 1, + }, + { + .name = "mr600:red:wlan24", + .gpio = MR600V2_GPIO_LED_WLAN24_RED, + .active_low = 1, + }, + { + .name = "mr600:yellow:wlan24", + .gpio = MR600V2_GPIO_LED_WLAN24_YELLOW, + .active_low = 1, + }, + { + .name = "mr600:green:wlan24", + .gpio = MR600V2_GPIO_LED_WLAN24_GREEN, + .active_low = 1, + }, + { + .name = "mr600:red:wlan58", + .gpio = MR600V2_GPIO_LED_WLAN58_RED, + .active_low = 1, + }, + { + .name = "mr600:yellow:wlan58", + .gpio = MR600V2_GPIO_LED_WLAN58_YELLOW, + .active_low = 1, + }, + { + .name = "mr600:green:wlan58", + .gpio = MR600V2_GPIO_LED_WLAN58_GREEN, + .active_low = 1, + }, +}; + +static struct gpio_keys_button mr600_gpio_keys[] __initdata = { + { + .desc = "Reset button", + .type = EV_KEY, + .code = KEY_RESTART, + .debounce_interval = MR600_KEYS_DEBOUNCE_INTERVAL, + .gpio = MR600_GPIO_BTN_RESET, + .active_low = 1, + }, +}; + +static void __init mr600_base_setup(unsigned num_leds, struct gpio_led *leds) +{ + u8 *art = (u8 *)KSEG1ADDR(0x1fff0000); + u8 mac[6]; + + ath79_register_m25p80(NULL); + + ath79_register_leds_gpio(-1, num_leds, leds); + ath79_register_gpio_keys_polled(-1, MR600_KEYS_POLL_INTERVAL, + ARRAY_SIZE(mr600_gpio_keys), + mr600_gpio_keys); + + ath79_init_mac(mac, art + MR600_MAC_OFFSET, 1); + ath79_register_wmac(art + MR600_WMAC_CALDATA_OFFSET, mac); + + ath79_init_mac(mac, art + MR600_MAC_OFFSET, 8); + ap91_pci_init(art + MR600_PCIE_CALDATA_OFFSET, mac); + + ath79_setup_ar934x_eth_cfg(AR934X_ETH_CFG_RGMII_GMAC0 | + AR934X_ETH_CFG_SW_ONLY_MODE); + + ath79_register_mdio(0, 0x0); + + ath79_init_mac(ath79_eth0_data.mac_addr, art + MR600_MAC_OFFSET, 0); + + /* GMAC0 is connected to an external PHY */ + ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; + ath79_eth0_data.phy_mask = BIT(0); + ath79_eth0_data.mii_bus_dev = &ath79_mdio0_device.dev; + ath79_eth0_pll_data.pll_1000 = 0x06000000; + ath79_register_eth(0); +} + +static void __init mr600_setup(void) +{ + mr600_base_setup(ARRAY_SIZE(mr600_leds_gpio), mr600_leds_gpio); +} + +MIPS_MACHINE(ATH79_MACH_MR600, "MR600", "OpenMesh MR600", mr600_setup); + +static void __init mr600v2_setup(void) +{ + mr600_base_setup(ARRAY_SIZE(mr600v2_leds_gpio), mr600v2_leds_gpio); +} + +MIPS_MACHINE(ATH79_MACH_MR600V2, "MR600v2", "OpenMesh MR600v2", mr600v2_setup); diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-nbg460n.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-nbg460n.c index 8aa7331d4..ca007779e 100644 --- a/target/linux/ar71xx/files/arch/mips/ath79/mach-nbg460n.c +++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-nbg460n.c @@ -151,7 +151,7 @@ static struct i2c_board_info nbg460n_i2c_devs[] __initdata = { }, }; -static void __devinit nbg460n_i2c_init(void) +static void nbg460n_i2c_init(void) { /* The gpio interface */ platform_device_register(&nbg460n_i2c_device); diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-om2p.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-om2p.c index faeb49a51..8adac0f65 100644 --- a/target/linux/ar71xx/files/arch/mips/ath79/mach-om2p.c +++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-om2p.c @@ -174,3 +174,50 @@ static void __init om2p_lc_setup(void) } MIPS_MACHINE(ATH79_MACH_OM2P_LC, "OM2P-LC", "OpenMesh OM2P LC", om2p_lc_setup); + +static void __init om2p_hs_setup(void) +{ + u8 *mac1 = (u8 *)KSEG1ADDR(0x1ffc0000); + u8 *mac2 = (u8 *)KSEG1ADDR(0x1ffc0000 + ETH_ALEN); + u8 *art = (u8 *)KSEG1ADDR(0x1ffc1000); + + /* make lan / wan leds software controllable */ + ath79_gpio_output_select(OM2P_GPIO_LED_LAN, AR934X_GPIO_OUT_GPIO); + ath79_gpio_output_select(OM2P_GPIO_LED_WAN, AR934X_GPIO_OUT_GPIO); + + /* enable reset button */ + ath79_gpio_output_select(OM2P_GPIO_BTN_RESET, AR934X_GPIO_OUT_GPIO); + ath79_gpio_function_enable(AR934X_GPIO_FUNC_JTAG_DISABLE); + + om2p_leds_gpio[4].gpio = OM2P_GPIO_LED_WAN; + om2p_leds_gpio[5].gpio = OM2P_GPIO_LED_LAN; + + ath79_register_m25p80(&om2p_lc_flash_data); + ath79_register_leds_gpio(-1, ARRAY_SIZE(om2p_leds_gpio), + om2p_leds_gpio); + ath79_register_gpio_keys_polled(-1, OM2P_KEYS_POLL_INTERVAL, + ARRAY_SIZE(om2p_gpio_keys), + om2p_gpio_keys); + + ath79_register_wmac(art, NULL); + + ath79_setup_ar934x_eth_cfg(AR934X_ETH_CFG_SW_PHY_SWAP); + ath79_register_mdio(1, 0x0); + + ath79_init_mac(ath79_eth0_data.mac_addr, mac1, 0); + ath79_init_mac(ath79_eth1_data.mac_addr, mac2, 0); + + /* GMAC0 is connected to the PHY0 of the internal switch */ + ath79_switch_data.phy4_mii_en = 1; + ath79_switch_data.phy_poll_mask = BIT(0); + ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_MII; + ath79_eth0_data.phy_mask = BIT(0); + ath79_eth0_data.mii_bus_dev = &ath79_mdio1_device.dev; + ath79_register_eth(0); + + /* GMAC1 is connected to the internal switch */ + ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_GMII; + ath79_register_eth(1); +} + +MIPS_MACHINE(ATH79_MACH_OM2P_HS, "OM2P-HS", "OpenMesh OM2P HS", om2p_hs_setup); diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-rb2011.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-rb2011.c index 4c7dc6dda..46b8a053d 100644 --- a/target/linux/ar71xx/files/arch/mips/ath79/mach-rb2011.c +++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-rb2011.c @@ -12,15 +12,18 @@ #define pr_fmt(fmt) "rb2011: " fmt #include <linux/phy.h> +#include <linux/delay.h> #include <linux/platform_device.h> #include <linux/ath9k_platform.h> #include <linux/ar8216_platform.h> #include <linux/mtd/mtd.h> +#include <linux/mtd/nand.h> #include <linux/mtd/partitions.h> #include <linux/spi/spi.h> #include <linux/spi/flash.h> #include <linux/rle.h> #include <linux/routerboot.h> +#include <linux/gpio.h> #include <asm/mach-ath79/ath79.h> #include <asm/mach-ath79/ar71xx_regs.h> @@ -28,16 +31,18 @@ #include "common.h" #include "dev-eth.h" #include "dev-m25p80.h" +#include "dev-nfc.h" #include "dev-wmac.h" #include "machtypes.h" #include "routerboot.h" +#define RB2011_GPIO_NAND_NCE 14 + #define RB_ROUTERBOOT_OFFSET 0x0000 -#define RB_ROUTERBOOT_SIZE 0xb000 -#define RB_HARD_CFG_OFFSET 0xb000 +#define RB_ROUTERBOOT_MIN_SIZE 0xb000 #define RB_HARD_CFG_SIZE 0x1000 #define RB_BIOS_OFFSET 0xd000 -#define RB_BIOS_SIZE 0x2000 +#define RB_BIOS_SIZE 0x1000 #define RB_SOFT_CFG_OFFSET 0xf000 #define RB_SOFT_CFG_SIZE 0x1000 @@ -47,11 +52,9 @@ static struct mtd_partition rb2011_spi_partitions[] = { { .name = "routerboot", .offset = RB_ROUTERBOOT_OFFSET, - .size = RB_ROUTERBOOT_SIZE, .mask_flags = MTD_WRITEABLE, }, { .name = "hard_config", - .offset = RB_HARD_CFG_OFFSET, .size = RB_HARD_CFG_SIZE, .mask_flags = MTD_WRITEABLE, }, { @@ -61,11 +64,48 @@ static struct mtd_partition rb2011_spi_partitions[] = { .mask_flags = MTD_WRITEABLE, }, { .name = "soft_config", - .offset = RB_SOFT_CFG_OFFSET, .size = RB_SOFT_CFG_SIZE, } }; + +static void __init rb2011_init_partitions(void) +{ + u8 *addr = (u8 *) KSEG1ADDR(0x1f000000); + u32 next = RB_ROUTERBOOT_MIN_SIZE; + + if (routerboot_find_magic(addr, 0x10000, &next, true)) + printk(KERN_ERR "Warning: could not find a valid RouterBOOT hard config\n"); + rb2011_spi_partitions[0].size = next; + rb2011_spi_partitions[1].offset = next; + + next = RB_BIOS_OFFSET + RB_BIOS_SIZE; + if (routerboot_find_magic(addr, 0x10000, &next, false)) + printk(KERN_ERR "Warning: could not find a valid RouterBOOT soft config\n"); + + rb2011_spi_partitions[3].offset = next; +} + + +static struct mtd_partition rb2011_nand_partitions[] = { + { + .name = "booter", + .offset = 0, + .size = (256 * 1024), + .mask_flags = MTD_WRITEABLE, + }, + { + .name = "kernel", + .offset = (256 * 1024), + .size = (4 * 1024 * 1024) - (256 * 1024), + }, + { + .name = "rootfs", + .offset = MTDPART_OFS_NXTBLK, + .size = MTDPART_SIZ_FULL, + }, +}; + static struct flash_platform_data rb2011_spi_flash_data = { .parts = rb2011_spi_partitions, .nr_parts = ARRAY_SIZE(rb2011_spi_partitions), @@ -81,7 +121,7 @@ static struct ar8327_pad_cfg rb2011_ar8327_pad0_cfg = { static struct ar8327_platform_data rb2011_ar8327_data = { .pad0_cfg = &rb2011_ar8327_pad0_cfg, - .cpuport_cfg = { + .port0_cfg = { .force_link = 1, .speed = AR8327_PORT_SPEED_1000, .duplex = 1, @@ -98,32 +138,16 @@ static struct mdio_board_info rb2011_mdio0_info[] = { }, }; -static void __init rb2011_gmac_setup(void) -{ - void __iomem *base; - u32 t; - - base = ioremap(AR934X_GMAC_BASE, AR934X_GMAC_SIZE); - - t = __raw_readl(base + AR934X_GMAC_REG_ETH_CFG); - t &= ~(AR934X_ETH_CFG_RGMII_GMAC0 | AR934X_ETH_CFG_MII_GMAC0 | - AR934X_ETH_CFG_GMII_GMAC0 | AR934X_ETH_CFG_SW_ONLY_MODE); - t |= AR934X_ETH_CFG_RGMII_GMAC0 | AR934X_ETH_CFG_SW_ONLY_MODE; - - __raw_writel(t, base + AR934X_GMAC_REG_ETH_CFG); - - iounmap(base); -} - static void __init rb2011_wlan_init(void) { - u8 *hard_cfg = (u8 *) KSEG1ADDR(0x1f000000 + RB_HARD_CFG_OFFSET); + u8 *hard_cfg = (u8 *) KSEG1ADDR(0x1f000000); u16 tag_len; u8 *tag; char *art_buf; u8 wlan_mac[ETH_ALEN]; int err; + hard_cfg += rb2011_spi_partitions[1].offset; err = routerboot_find_tag(hard_cfg, RB_HARD_CFG_SIZE, RB_ID_WLAN_DATA, &tag, &tag_len); if (err) { @@ -151,11 +175,66 @@ free: kfree(art_buf); } +static void rb2011_nand_select_chip(int chip_no) +{ + switch (chip_no) { + case 0: + gpio_set_value(RB2011_GPIO_NAND_NCE, 0); + break; + default: + gpio_set_value(RB2011_GPIO_NAND_NCE, 1); + break; + } + ndelay(500); +} + +static struct nand_ecclayout rb2011_nand_ecclayout = { + .eccbytes = 6, + .eccpos = { 8, 9, 10, 13, 14, 15 }, + .oobavail = 9, + .oobfree = { { 0, 4 }, { 6, 2 }, { 11, 2 }, { 4, 1 } } +}; + +static int rb2011_nand_scan_fixup(struct mtd_info *mtd) +{ + struct nand_chip *chip = mtd->priv; + + if (mtd->writesize == 512) { + /* + * Use the OLD Yaffs-1 OOB layout, otherwise RouterBoot + * will not be able to find the kernel that we load. + */ + chip->ecc.layout = &rb2011_nand_ecclayout; + } + + return 0; +} + +static void __init rb2011_nand_init(void) +{ + ath79_nfc_set_scan_fixup(rb2011_nand_scan_fixup); + ath79_nfc_set_parts(rb2011_nand_partitions, + ARRAY_SIZE(rb2011_nand_partitions)); + ath79_nfc_set_select_chip(rb2011_nand_select_chip); + ath79_nfc_set_swap_dma(true); + ath79_register_nfc(); +} + +static void __init rb2011_gpio_init(void) +{ + gpio_request_one(RB2011_GPIO_NAND_NCE, GPIOF_OUT_INIT_HIGH, "NAND nCE"); +} + static void __init rb2011_setup(void) { + rb2011_init_partitions(); + rb2011_gpio_init(); + ath79_register_m25p80(&rb2011_spi_flash_data); + rb2011_nand_init(); - rb2011_gmac_setup(); + ath79_setup_ar934x_eth_cfg(AR934X_ETH_CFG_RGMII_GMAC0 | + AR934X_ETH_CFG_SW_ONLY_MODE); ath79_register_mdio(1, 0x0); ath79_register_mdio(0, 0x0); diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-rb4xx.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-rb4xx.c index 1604a5c56..1a61b458d 100644 --- a/target/linux/ar71xx/files/arch/mips/ath79/mach-rb4xx.c +++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-rb4xx.c @@ -107,8 +107,36 @@ static struct ath79_pci_irq rb4xx_pci_irqs[] __initdata = { .irq = ATH79_PCI_IRQ(1), }, { .slot = 19, + .pin = 2, + .irq = ATH79_PCI_IRQ(2), + }, { + .slot = 20, .pin = 1, .irq = ATH79_PCI_IRQ(2), + }, { + .slot = 20, + .pin = 2, + .irq = ATH79_PCI_IRQ(0), + }, { + .slot = 21, + .pin = 1, + .irq = ATH79_PCI_IRQ(0), + }, { + .slot = 22, + .pin = 1, + .irq = ATH79_PCI_IRQ(1), + }, { + .slot = 22, + .pin = 2, + .irq = ATH79_PCI_IRQ(2), + }, { + .slot = 23, + .pin = 1, + .irq = ATH79_PCI_IRQ(2), + }, { + .slot = 23, + .pin = 2, + .irq = ATH79_PCI_IRQ(0), } }; @@ -277,6 +305,35 @@ static void __init rb433u_setup(void) MIPS_MACHINE(ATH79_MACH_RB_433U, "433U", "MikroTik RouterBOARD 433UAH", rb433u_setup); +static void __init rb435g_setup(void) +{ + rb4xx_generic_setup(); + + spi_register_board_info(rb4xx_microsd_info, + ARRAY_SIZE(rb4xx_microsd_info)); + + ath79_register_mdio(0, ~RB433_MDIO_PHYMASK); + + ath79_init_mac(ath79_eth0_data.mac_addr, ath79_mac_base, 1); + ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; + ath79_eth0_data.phy_mask = RB433_LAN_PHYMASK; + + ath79_init_mac(ath79_eth1_data.mac_addr, ath79_mac_base, 0); + ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; + ath79_eth1_data.phy_mask = RB433_WAN_PHYMASK; + + ath79_register_eth(1); + ath79_register_eth(0); + + ath79_pci_set_irq_map(ARRAY_SIZE(rb4xx_pci_irqs), rb4xx_pci_irqs); + ath79_register_pci(); + + ath79_register_usb(); +} + +MIPS_MACHINE(ATH79_MACH_RB_435G, "435G", "MikroTik RouterBOARD 435G", + rb435g_setup); + #define RB450_LAN_PHYMASK BIT(0) #define RB450_WAN_PHYMASK BIT(4) #define RB450_MDIO_PHYMASK (RB450_LAN_PHYMASK | RB450_WAN_PHYMASK) @@ -372,6 +429,9 @@ static void __init rb493g_setup(void) rb4xx_leds_gpio); spi_register_board_info(rb4xx_spi_info, ARRAY_SIZE(rb4xx_spi_info)); + spi_register_board_info(rb4xx_microsd_info, + ARRAY_SIZE(rb4xx_microsd_info)); + platform_device_register(&rb4xx_spi_device); platform_device_register(&rb4xx_nand_device); diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-rb750.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-rb750.c index bee8bdf9c..5656d3c1f 100644 --- a/target/linux/ar71xx/files/arch/mips/ath79/mach-rb750.c +++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-rb750.c @@ -184,9 +184,9 @@ static struct ar8327_pad_cfg rb750gr3_ar8327_pad0_cfg = { static struct ar8327_platform_data rb750gr3_ar8327_data = { .pad0_cfg = &rb750gr3_ar8327_pad0_cfg, - .cpuport_cfg = { + .port0_cfg = { .force_link = 1, - .speed = AR8327_PORT_SPEED_100, + .speed = AR8327_PORT_SPEED_1000, .duplex = 1, .txpause = 1, .rxpause = 1, @@ -261,6 +261,7 @@ static void __init rb750gr3_setup(void) ath79_init_mac(ath79_eth0_data.mac_addr, ath79_mac_base, 0); ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ath79_eth0_data.phy_mask = BIT(0); + ath79_eth0_pll_data.pll_1000 = 0x62000000; ath79_register_eth(0); @@ -281,7 +282,6 @@ MIPS_MACHINE(ATH79_MACH_RB_750G_R3, "750Gr3", "MikroTik RouterBOARD 750GL", #define RB751_HARDCONFIG 0x1f00b000 #define RB751_HARDCONFIG_SIZE 0x1000 -#define RB751_MAC_ADDRESS_OFFSET 0xE80 static void __init rb751_wlan_setup(void) { @@ -289,6 +289,8 @@ static void __init rb751_wlan_setup(void) struct ath9k_platform_data *wmac_data; u16 tag_len; u8 *tag; + u16 mac_len; + u8 *mac; int err; wmac_data = ap9x_pci_get_wmac_data(0); @@ -313,7 +315,14 @@ static void __init rb751_wlan_setup(void) return; } - ap91_pci_init(NULL, hardconfig + RB751_MAC_ADDRESS_OFFSET); + err = routerboot_find_tag(hardconfig, RB751_HARDCONFIG_SIZE, + RB_ID_MAC_ADDRESS_PACK, &mac, &mac_len); + if (err) { + pr_err("rb75x: no mac address found\n"); + return; + } + + ap91_pci_init(NULL, mac); } static void __init rb751_setup(void) diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-rb95x.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-rb95x.c new file mode 100644 index 000000000..f59c14c53 --- /dev/null +++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-rb95x.c @@ -0,0 +1,214 @@ +/* + * MikroTik RouterBOARD 95X support + * + * Copyright (C) 2012 Stijn Tintel <stijn@linux-ipv6.be> + * Copyright (C) 2012 Gabor Juhos <juhosg@openwrt.org> + * Copyright (C) 2013 Kamil Trzcinski <ayufan@ayufan.eu> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + */ + +#define pr_fmt(fmt) "rb95x: " fmt + +#include <linux/phy.h> +#include <linux/delay.h> +#include <linux/platform_device.h> +#include <linux/ath9k_platform.h> +#include <linux/ar8216_platform.h> +#include <linux/mtd/mtd.h> +#include <linux/mtd/nand.h> +#include <linux/mtd/partitions.h> +#include <linux/spi/spi.h> +#include <linux/spi/flash.h> +#include <linux/rle.h> +#include <linux/routerboot.h> +#include <linux/gpio.h> + +#include <asm/mach-ath79/ath79.h> +#include <asm/mach-ath79/ar71xx_regs.h> + +#include "common.h" +#include "dev-eth.h" +#include "dev-m25p80.h" +#include "dev-nfc.h" +#include "dev-usb.h" +#include "dev-wmac.h" +#include "machtypes.h" +#include "routerboot.h" + +#define RB95X_GPIO_NAND_NCE 14 + +#define RB_ROUTERBOOT_OFFSET 0x0000 +#define RB_ROUTERBOOT_SIZE 0xb000 +#define RB_HARD_CFG_OFFSET 0xc000 +#define RB_HARD_CFG_SIZE 0x1000 +#define RB_BIOS_OFFSET 0xd000 +#define RB_BIOS_SIZE 0x2000 +#define RB_SOFT_CFG_OFFSET 0xe000 +#define RB_SOFT_CFG_SIZE 0x1000 + +#define RB_ART_SIZE 0x10000 + +static struct mtd_partition rb95x_nand_partitions[] = { + { + .name = "booter", + .offset = 0, + .size = (256 * 1024), + .mask_flags = MTD_WRITEABLE, + }, + { + .name = "kernel", + .offset = (256 * 1024), + .size = (4 * 1024 * 1024) - (256 * 1024), + }, + { + .name = "rootfs", + .offset = MTDPART_OFS_NXTBLK, + .size = MTDPART_SIZ_FULL, + }, +}; + +static struct ar8327_pad_cfg rb95x_ar8327_pad0_cfg = { + .mode = AR8327_PAD_MAC_RGMII, + .txclk_delay_en = true, + .rxclk_delay_en = true, + .txclk_delay_sel = AR8327_CLK_DELAY_SEL1, + .rxclk_delay_sel = AR8327_CLK_DELAY_SEL2, +}; + +static struct ar8327_platform_data rb95x_ar8327_data = { + .pad0_cfg = &rb95x_ar8327_pad0_cfg, + .port0_cfg = { + .force_link = 1, + .speed = AR8327_PORT_SPEED_1000, + .duplex = 1, + .txpause = 1, + .rxpause = 1, + } +}; + +static struct mdio_board_info rb95x_mdio0_info[] = { + { + .bus_id = "ag71xx-mdio.0", + .phy_addr = 0, + .platform_data = &rb95x_ar8327_data, + }, +}; + +void __init rb95x_wlan_init(void) +{ + u8 *hard_cfg = (u8 *) KSEG1ADDR(0x1f000000 + RB_HARD_CFG_OFFSET); + u16 tag_len; + u8 *tag; + char *art_buf; + u8 wlan_mac[ETH_ALEN]; + int err; + + err = routerboot_find_tag(hard_cfg, RB_HARD_CFG_SIZE, RB_ID_WLAN_DATA, + &tag, &tag_len); + if (err) { + pr_err("no calibration data found\n"); + return; + } + + art_buf = kmalloc(RB_ART_SIZE, GFP_KERNEL); + if (art_buf == NULL) { + pr_err("no memory for calibration data\n"); + return; + } + + err = rle_decode((char *) tag, tag_len, art_buf, RB_ART_SIZE, + NULL, NULL); + if (err) { + pr_err("unable to decode calibration data\n"); + goto free; + } + + ath79_init_mac(wlan_mac, ath79_mac_base, 11); + ath79_register_wmac(art_buf + 0x1000, wlan_mac); + +free: + kfree(art_buf); +} + +static void rb95x_nand_select_chip(int chip_no) +{ + switch (chip_no) { + case 0: + gpio_set_value(RB95X_GPIO_NAND_NCE, 0); + break; + default: + gpio_set_value(RB95X_GPIO_NAND_NCE, 1); + break; + } + ndelay(500); +} + +static struct nand_ecclayout rb95x_nand_ecclayout = { + .eccbytes = 6, + .eccpos = { 8, 9, 10, 13, 14, 15 }, + .oobavail = 9, + .oobfree = { { 0, 4 }, { 6, 2 }, { 11, 2 }, { 4, 1 } } +}; + +static int rb95x_nand_scan_fixup(struct mtd_info *mtd) +{ + struct nand_chip *chip = mtd->priv; + + if (mtd->writesize == 512) { + /* + * Use the OLD Yaffs-1 OOB layout, otherwise RouterBoot + * will not be able to find the kernel that we load. + */ + chip->ecc.layout = &rb95x_nand_ecclayout; + } + + return 0; +} + +void __init rb95x_nand_init(void) +{ + ath79_nfc_set_scan_fixup(rb95x_nand_scan_fixup); + ath79_nfc_set_parts(rb95x_nand_partitions, + ARRAY_SIZE(rb95x_nand_partitions)); + ath79_nfc_set_select_chip(rb95x_nand_select_chip); + ath79_nfc_set_swap_dma(true); + ath79_register_nfc(); +} + +void __init rb95x_gpio_init(void) +{ + gpio_request_one(RB95X_GPIO_NAND_NCE, GPIOF_OUT_INIT_HIGH, "NAND nCE"); +} + +static void __init rb95x_setup(void) +{ + rb95x_gpio_init(); + rb95x_nand_init(); + + ath79_setup_ar934x_eth_cfg(AR934X_ETH_CFG_RGMII_GMAC0 | + AR934X_ETH_CFG_SW_ONLY_MODE); + + ath79_register_mdio(0, 0x0); + + mdiobus_register_board_info(rb95x_mdio0_info, + ARRAY_SIZE(rb95x_mdio0_info)); + + ath79_init_mac(ath79_eth0_data.mac_addr, ath79_mac_base, 0); + ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; + ath79_eth0_data.phy_mask = BIT(0); + + ath79_register_eth(0); +} + +static void __init rb951g_setup(void) +{ + rb95x_setup(); + rb95x_wlan_init(); + ath79_register_usb(); +} + +MIPS_MACHINE(ATH79_MACH_RB_951G, "951G", "MikroTik RouterBOARD 951G-2HnD", + rb951g_setup); diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-rw2458n.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-rw2458n.c index 28d9de4f3..bb7c2475b 100644 --- a/target/linux/ar71xx/files/arch/mips/ath79/mach-rw2458n.c +++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-rw2458n.c @@ -1,7 +1,7 @@ /* * Redwave RW2458N support * - * Copyright (C) 2011-2012 Cezary Jackiewicz <cezary@eko.one.pl> + * Copyright (C) 2011-2013 Cezary Jackiewicz <cezary@eko.one.pl> * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published @@ -17,6 +17,7 @@ #include "dev-m25p80.h" #include "dev-usb.h" #include "machtypes.h" +#include "pci.h" #define RW2458N_GPIO_LED_D3 1 #define RW2458N_GPIO_LED_D4 0 @@ -60,22 +61,12 @@ static struct gpio_led rw2458n_leds_gpio[] __initdata = { } }; -static const char *rw2458n_part_probes[] = { - "RedBoot", - NULL, -}; - -static struct flash_platform_data rw2458n_flash_data = { - .part_probes = rw2458n_part_probes, -}; - static void __init rw2458n_setup(void) { u8 *mac1 = (u8 *) KSEG1ADDR(0x1fff0000); u8 *mac2 = (u8 *) KSEG1ADDR(0x1fff0000 + ETH_ALEN); - u8 *ee = (u8 *) KSEG1ADDR(0x1fff1000); - ath79_register_m25p80(&rw2458n_flash_data); + ath79_register_m25p80(NULL); ath79_register_mdio(0, ~RW2458N_WAN_PHYMASK); @@ -85,8 +76,6 @@ static void __init rw2458n_setup(void) ath79_register_eth(0); ath79_register_eth(1); - ap91_pci_init(ee, NULL); - ath79_register_leds_gpio(-1, ARRAY_SIZE(rw2458n_leds_gpio), rw2458n_leds_gpio); @@ -94,6 +83,8 @@ static void __init rw2458n_setup(void) ARRAY_SIZE(rw2458n_gpio_keys), rw2458n_gpio_keys); ath79_register_usb(); + + ath79_register_pci(); } MIPS_MACHINE(ATH79_MACH_RW2458N, "RW2458N", "Redwave RW2458N", diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-tew-673gru.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-tew-673gru.c index 8fe825936..207384f99 100644 --- a/target/linux/ar71xx/files/arch/mips/ath79/mach-tew-673gru.c +++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-tew-673gru.c @@ -40,11 +40,13 @@ #define TEW673GRU_KEYS_POLL_INTERVAL 20 /* msecs */ #define TEW673GRU_KEYS_DEBOUNCE_INTERVAL (3 * TEW673GRU_KEYS_POLL_INTERVAL) -#define TEW673GRU_CAL_LOCATION_0 0x1f661000 -#define TEW673GRU_CAL_LOCATION_1 0x1f665000 +#define TEW673GRU_CAL0_OFFSET 0x1000 +#define TEW673GRU_CAL1_OFFSET 0x5000 +#define TEW673GRU_MAC0_OFFSET 0xffa0 +#define TEW673GRU_MAC1_OFFSET 0xffb4 -#define TEW673GRU_MAC_LOCATION_0 0x1f66ffa0 -#define TEW673GRU_MAC_LOCATION_1 0x1f66ffb4 +#define TEW673GRU_CAL_LOCATION_0 0x1f660000 +#define TEW673GRU_CAL_LOCATION_1 0x1f7f0000 static struct gpio_led tew673gru_leds_gpio[] __initdata = { { @@ -117,35 +119,67 @@ static struct platform_device tew673gru_spi_device = { }, }; -static void tew673gru_read_ascii_mac(u8 *dest, unsigned int src_addr) +static void tew673gru_read_ascii_mac(u8 *dest, u8 *src) { int ret; - u8 *src = (u8 *)KSEG1ADDR(src_addr); ret = sscanf(src, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx", &dest[0], &dest[1], &dest[2], &dest[3], &dest[4], &dest[5]); - if (ret != ETH_ALEN) memset(dest, 0, ETH_ALEN); + if (ret != ETH_ALEN) + memset(dest, 0, ETH_ALEN); } -static void __init tew673gru_setup(void) +static bool __init tew673gru_is_caldata_valid(u8 *p) +{ + u16 *magic0, *magic1; + + magic0 = (u16 *)(p + TEW673GRU_CAL0_OFFSET); + magic1 = (u16 *)(p + TEW673GRU_CAL1_OFFSET); + + return (*magic0 == 0xa55a && *magic1 == 0xa55a); +} + +static void __init tew673gru_wlan_init(void) { u8 mac1[ETH_ALEN], mac2[ETH_ALEN]; + u8 *caldata; + + caldata = (u8 *) KSEG1ADDR(TEW673GRU_CAL_LOCATION_0); + if (!tew673gru_is_caldata_valid(caldata)) { + caldata = (u8 *)KSEG1ADDR(TEW673GRU_CAL_LOCATION_1); + if (!tew673gru_is_caldata_valid(caldata)) { + pr_err("no calibration data found\n"); + return; + } + } + + tew673gru_read_ascii_mac(mac1, caldata + TEW673GRU_MAC0_OFFSET); + tew673gru_read_ascii_mac(mac2, caldata + TEW673GRU_MAC1_OFFSET); + + ath79_init_mac(ath79_eth0_data.mac_addr, mac1, 2); + ath79_init_mac(ath79_eth1_data.mac_addr, mac1, 3); + + ap9x_pci_setup_wmac_led_pin(0, 5); + ap9x_pci_setup_wmac_led_pin(1, 5); + + ap94_pci_init(caldata + TEW673GRU_CAL0_OFFSET, mac1, + caldata + TEW673GRU_CAL1_OFFSET, mac2); +} - tew673gru_read_ascii_mac(mac1, TEW673GRU_MAC_LOCATION_0); - tew673gru_read_ascii_mac(mac2, TEW673GRU_MAC_LOCATION_1); +static void __init tew673gru_setup(void) +{ + tew673gru_wlan_init(); ath79_register_mdio(0, 0x0); - ath79_init_mac(ath79_eth0_data.mac_addr, mac1, 2); ath79_eth0_data.mii_bus_dev = &tew673gru_rtl8366s_device.dev; ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ath79_eth0_data.speed = SPEED_1000; ath79_eth0_data.duplex = DUPLEX_FULL; ath79_eth0_pll_data.pll_1000 = 0x11110000; - ath79_init_mac(ath79_eth1_data.mac_addr, mac1, 3); ath79_eth1_data.mii_bus_dev = &tew673gru_rtl8366s_device.dev; ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ath79_eth1_data.phy_mask = 0x10; @@ -167,12 +201,6 @@ static void __init tew673gru_setup(void) platform_device_register(&tew673gru_rtl8366s_device); - ap9x_pci_setup_wmac_led_pin(0, 5); - ap9x_pci_setup_wmac_led_pin(1, 5); - - ap94_pci_init((u8 *) KSEG1ADDR(TEW673GRU_CAL_LOCATION_0), mac1, - (u8 *) KSEG1ADDR(TEW673GRU_CAL_LOCATION_1), mac2); - spi_register_board_info(tew673gru_spi_info, ARRAY_SIZE(tew673gru_spi_info)); platform_device_register(&tew673gru_spi_device); diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-mr11u.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-mr11u.c index 87facff7f..818ed9767 100644 --- a/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-mr11u.c +++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-mr11u.c @@ -1,5 +1,5 @@ /* - * TP-LINK TL-MR11U board support + * TP-LINK TL-MR11U/TL-MR3040 board support * * Copyright (C) 2011 dongyuqi <729650915@qq.com> * Copyright (C) 2011-2012 Gabor Juhos <juhosg@openwrt.org> @@ -12,7 +12,9 @@ #include <linux/gpio.h> #include <asm/mach-ath79/ath79.h> +#include <asm/mach-ath79/ar71xx_regs.h> +#include "common.h" #include "dev-eth.h" #include "dev-gpio-buttons.h" #include "dev-leds-gpio.h" @@ -29,6 +31,7 @@ #define TL_MR11U_GPIO_BTN_RESET 11 #define TL_MR11U_GPIO_USB_POWER 8 +#define TL_MR3040_GPIO_USB_POWER 18 #define TL_MR11U_KEYS_POLL_INTERVAL 20 /* msecs */ #define TL_MR11U_KEYS_DEBOUNCE_INTERVAL (3 * TL_MR11U_KEYS_POLL_INTERVAL) @@ -62,49 +65,74 @@ static struct gpio_led tl_mr11u_leds_gpio[] __initdata = { static struct gpio_keys_button tl_mr11u_gpio_keys[] __initdata = { { - .desc = "wps", + .desc = "reset", .type = EV_KEY, - .code = KEY_WPS_BUTTON, + .code = KEY_RESTART, .debounce_interval = TL_MR11U_KEYS_DEBOUNCE_INTERVAL, - .gpio = TL_MR11U_GPIO_BTN_WPS, + .gpio = TL_MR11U_GPIO_BTN_RESET, .active_low = 0, }, { - .desc = "reset", + .desc = "wps", .type = EV_KEY, - .code = KEY_RESTART, + .code = KEY_WPS_BUTTON, .debounce_interval = TL_MR11U_KEYS_DEBOUNCE_INTERVAL, - .gpio = TL_MR11U_GPIO_BTN_RESET, + .gpio = TL_MR11U_GPIO_BTN_WPS, .active_low = 0, - } + }, }; -static void __init tl_mr11u_setup(void) +static void __init common_setup(void) { u8 *mac = (u8 *) KSEG1ADDR(0x1f01fc00); u8 *ee = (u8 *) KSEG1ADDR(0x1fff1000); - ath79_setup_ar933x_phy4_switch(false, true); + /* Disable hardware control LAN1 and LAN2 LEDs, enabling GPIO14 and GPIO15 */ + ath79_gpio_function_disable(AR933X_GPIO_FUNC_ETH_SWITCH_LED1_EN | + AR933X_GPIO_FUNC_ETH_SWITCH_LED2_EN); + + /* disable PHY_SWAP and PHY_ADDR_SWAP bits */ + ath79_setup_ar933x_phy4_switch(false, false); ath79_register_m25p80(&tl_mr11u_flash_data); ath79_register_leds_gpio(-1, ARRAY_SIZE(tl_mr11u_leds_gpio), tl_mr11u_leds_gpio); - ath79_register_gpio_keys_polled(-1, TL_MR11U_KEYS_POLL_INTERVAL, - ARRAY_SIZE(tl_mr11u_gpio_keys), - tl_mr11u_gpio_keys); - ath79_set_usb_power_gpio(TL_MR11U_GPIO_USB_POWER, GPIOF_OUT_INIT_HIGH, - "USB power"); ath79_register_usb(); ath79_init_mac(ath79_eth0_data.mac_addr, mac, 0); ath79_register_mdio(0, 0x0); ath79_register_eth(0); - ath79_eth0_data.phy_mask = BIT(0); ath79_register_wmac(ee, mac); } +static void __init tl_mr11u_setup(void) +{ + common_setup(); + + ath79_register_gpio_keys_polled(-1, TL_MR11U_KEYS_POLL_INTERVAL, + ARRAY_SIZE(tl_mr11u_gpio_keys), + tl_mr11u_gpio_keys); + gpio_request_one(TL_MR11U_GPIO_USB_POWER, + GPIOF_OUT_INIT_HIGH | GPIOF_EXPORT_DIR_FIXED, + "USB power"); +} + MIPS_MACHINE(ATH79_MACH_TL_MR11U, "TL-MR11U", "TP-LINK TL-MR11U", tl_mr11u_setup); + +static void __init tl_mr3040_setup(void) +{ + common_setup(); + + ath79_register_gpio_keys_polled(-1, TL_MR11U_KEYS_POLL_INTERVAL, + 1, tl_mr11u_gpio_keys); + gpio_request_one(TL_MR3040_GPIO_USB_POWER, + GPIOF_OUT_INIT_HIGH | GPIOF_EXPORT_DIR_FIXED, + "USB power"); +} + +MIPS_MACHINE(ATH79_MACH_TL_MR3040, "TL-MR3040", "TP-LINK TL-MR3040", + tl_mr3040_setup); diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-mr3020.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-mr3020.c index 8f37d7a87..0a9dfbc8a 100644 --- a/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-mr3020.c +++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-mr3020.c @@ -100,7 +100,8 @@ static void __init tl_mr3020_setup(void) u8 *mac = (u8 *) KSEG1ADDR(0x1f01fc00); u8 *ee = (u8 *) KSEG1ADDR(0x1fff1000); - ath79_setup_ar933x_phy4_switch(false, true); + /* disable PHY_SWAP and PHY_ADDR_SWAP bits */ + ath79_setup_ar933x_phy4_switch(false, false); ath79_register_m25p80(&tl_mr3020_flash_data); ath79_register_leds_gpio(-1, ARRAY_SIZE(tl_mr3020_leds_gpio), @@ -109,15 +110,15 @@ static void __init tl_mr3020_setup(void) ARRAY_SIZE(tl_mr3020_gpio_keys), tl_mr3020_gpio_keys); - ath79_set_usb_power_gpio(TL_MR3020_GPIO_USB_POWER, GPIOF_OUT_INIT_HIGH, - "USB power"); + gpio_request_one(TL_MR3020_GPIO_USB_POWER, + GPIOF_OUT_INIT_HIGH | GPIOF_EXPORT_DIR_FIXED, + "USB power"); ath79_register_usb(); ath79_init_mac(ath79_eth0_data.mac_addr, mac, 0); ath79_register_mdio(0, 0x0); ath79_register_eth(0); - ath79_eth0_data.phy_mask = BIT(0); ath79_register_wmac(ee, mac); } diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-mr3x20.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-mr3x20.c index b35f09f8a..5924ac504 100644 --- a/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-mr3x20.c +++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-mr3x20.c @@ -102,8 +102,9 @@ static void __init tl_ap99_setup(void) static void __init tl_mr3x20_usb_setup(void) { /* enable power for the USB port */ - ath79_set_usb_power_gpio(TL_MR3X20_GPIO_USB_POWER, GPIOF_OUT_INIT_HIGH, - "USB power"); + gpio_request_one(TL_MR3X20_GPIO_USB_POWER, + GPIOF_OUT_INIT_HIGH | GPIOF_EXPORT_DIR_FIXED, + "USB power"); ath79_register_usb(); } diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wa901nd.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wa901nd.c index 2f4e0c047..45e8f1287 100644 --- a/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wa901nd.c +++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wa901nd.c @@ -1,8 +1,9 @@ /* - * TP-LINK TL-WA901N/ND v1 board support + * TP-LINK TL-WA901N/ND v1, TL-WA7510N v1 board support * * Copyright (C) 2009-2012 Gabor Juhos <juhosg@openwrt.org> * Copyright (C) 2010 Pieter Hollants <pieter@hollants.com> + * Copyright (C) 2012 Stefan Helmert <helst_listen@aol.de> * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published @@ -19,6 +20,7 @@ #include "dev-leds-gpio.h" #include "dev-m25p80.h" #include "machtypes.h" +#include "pci.h" #define TL_WA901ND_GPIO_LED_QSS 0 #define TL_WA901ND_GPIO_LED_SYSTEM 1 @@ -73,6 +75,22 @@ static struct gpio_keys_button tl_wa901nd_gpio_keys[] __initdata = { } }; +static void __init common_setup(void) +{ + u8 *mac = (u8 *) KSEG1ADDR(0x1f01fc00); + + /* + * ath79_eth0 would be the WAN port, but is not connected. + * ath79_eth1 connects to the internal switch chip, however + * we have a single LAN port only. + */ + ath79_init_mac(ath79_eth1_data.mac_addr, mac, 0); + ath79_register_mdio(0, 0x0); + ath79_register_eth(1); + + ath79_register_m25p80(&tl_wa901nd_flash_data); +} + static void __init tl_wa901nd_setup(void) { u8 *mac = (u8 *) KSEG1ADDR(0x1f01fc00); @@ -84,16 +102,7 @@ static void __init tl_wa901nd_setup(void) AR724X_GPIO_FUNC_ETH_SWITCH_LED3_EN | AR724X_GPIO_FUNC_ETH_SWITCH_LED4_EN); - /* - * ath79_eth0 would be the WAN port, but is not connected on - * the TL-WA901ND. ath79_eth1 connects to the internal switch chip, - * however we have a single LAN port only. - */ - ath79_init_mac(ath79_eth1_data.mac_addr, mac, 0); - ath79_register_mdio(0, 0x0); - ath79_register_eth(1); - - ath79_register_m25p80(&tl_wa901nd_flash_data); + common_setup(); ath79_register_leds_gpio(-1, ARRAY_SIZE(tl_wa901nd_leds_gpio), tl_wa901nd_leds_gpio); @@ -107,3 +116,12 @@ static void __init tl_wa901nd_setup(void) MIPS_MACHINE(ATH79_MACH_TL_WA901ND, "TL-WA901ND", "TP-LINK TL-WA901ND", tl_wa901nd_setup); + +static void __init tl_wa7510n_v1_setup(void) +{ + common_setup(); + ath79_register_pci(); +} + +MIPS_MACHINE(ATH79_MACH_TL_WA7510N_V1, "TL-WA7510N", "TP-LINK TL-WA7510N v1", + tl_wa7510n_v1_setup); diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wdr3500.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wdr3500.c new file mode 100644 index 000000000..452c20b77 --- /dev/null +++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wdr3500.c @@ -0,0 +1,169 @@ +/* + * TP-LINK TL-WDR3500 board support + * + * Copyright (C) 2012 Gabor Juhos <juhosg@openwrt.org> + * Copyright (C) 2013 Gui Iribarren <gui@altermundi.net> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + */ + +#include <linux/pci.h> +#include <linux/phy.h> +#include <linux/gpio.h> +#include <linux/platform_device.h> +#include <linux/ath9k_platform.h> +#include <linux/ar8216_platform.h> + +#include <asm/mach-ath79/ar71xx_regs.h> + +#include "common.h" +#include "dev-ap9x-pci.h" +#include "dev-eth.h" +#include "dev-gpio-buttons.h" +#include "dev-leds-gpio.h" +#include "dev-m25p80.h" +#include "dev-spi.h" +#include "dev-usb.h" +#include "dev-wmac.h" +#include "machtypes.h" + +#define WDR3500_GPIO_LED_USB 11 +#define WDR3500_GPIO_LED_WLAN2G 13 +#define WDR3500_GPIO_LED_SYSTEM 14 +#define WDR3500_GPIO_LED_QSS 15 +#define WDR3500_GPIO_LED_WAN 18 +#define WDR3500_GPIO_LED_LAN1 19 +#define WDR3500_GPIO_LED_LAN2 20 +#define WDR3500_GPIO_LED_LAN3 21 +#define WDR3500_GPIO_LED_LAN4 22 + +#define WDR3500_GPIO_BTN_WPS 16 +#define WDR3500_GPIO_BTN_RFKILL 17 + +#define WDR3500_GPIO_USB_POWER 12 + +#define WDR3500_KEYS_POLL_INTERVAL 20 /* msecs */ +#define WDR3500_KEYS_DEBOUNCE_INTERVAL (3 * WDR3500_KEYS_POLL_INTERVAL) + +#define WDR3500_MAC0_OFFSET 0 +#define WDR3500_MAC1_OFFSET 6 +#define WDR3500_WMAC_CALDATA_OFFSET 0x1000 +#define WDR3500_PCIE_CALDATA_OFFSET 0x5000 + +static const char *wdr3500_part_probes[] = { + "tp-link", + NULL, +}; + +static struct flash_platform_data wdr3500_flash_data = { + .part_probes = wdr3500_part_probes, +}; + +static struct gpio_led wdr3500_leds_gpio[] __initdata = { + { + .name = "tp-link:green:qss", + .gpio = WDR3500_GPIO_LED_QSS, + .active_low = 1, + }, + { + .name = "tp-link:green:system", + .gpio = WDR3500_GPIO_LED_SYSTEM, + .active_low = 1, + }, + { + .name = "tp-link:green:usb", + .gpio = WDR3500_GPIO_LED_USB, + .active_low = 1, + }, + { + .name = "tp-link:green:wlan2g", + .gpio = WDR3500_GPIO_LED_WLAN2G, + .active_low = 1, + }, +}; + +static struct gpio_keys_button wdr3500_gpio_keys[] __initdata = { + { + .desc = "QSS button", + .type = EV_KEY, + .code = KEY_WPS_BUTTON, + .debounce_interval = WDR3500_KEYS_DEBOUNCE_INTERVAL, + .gpio = WDR3500_GPIO_BTN_WPS, + .active_low = 1, + }, + { + .desc = "RFKILL switch", + .type = EV_SW, + .code = KEY_RFKILL, + .debounce_interval = WDR3500_KEYS_DEBOUNCE_INTERVAL, + .gpio = WDR3500_GPIO_BTN_RFKILL, + }, +}; + + +static void __init wdr3500_setup(void) +{ + u8 *mac = (u8 *) KSEG1ADDR(0x1f01fc00); + u8 *art = (u8 *) KSEG1ADDR(0x1fff0000); + u8 tmpmac[ETH_ALEN]; + + ath79_register_m25p80(&wdr3500_flash_data); + ath79_register_leds_gpio(-1, ARRAY_SIZE(wdr3500_leds_gpio), + wdr3500_leds_gpio); + ath79_register_gpio_keys_polled(-1, WDR3500_KEYS_POLL_INTERVAL, + ARRAY_SIZE(wdr3500_gpio_keys), + wdr3500_gpio_keys); + + ath79_init_mac(tmpmac, mac, 0); + ath79_register_wmac(art + WDR3500_WMAC_CALDATA_OFFSET, tmpmac); + + ath79_init_mac(tmpmac, mac, 1); + ap9x_pci_setup_wmac_led_pin(0, 0); + ap91_pci_init(art + WDR3500_PCIE_CALDATA_OFFSET, tmpmac); + + ath79_setup_ar934x_eth_cfg(AR934X_ETH_CFG_SW_ONLY_MODE); + + ath79_register_mdio(1, 0x0); + + /* LAN */ + ath79_init_mac(ath79_eth1_data.mac_addr, mac, -1); + + /* GMAC1 is connected to the internal switch */ + ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_GMII; + + ath79_register_eth(1); + + /* WAN */ + ath79_init_mac(ath79_eth0_data.mac_addr, mac, 2); + + /* GMAC0 is connected to the PHY4 of the internal switch */ + ath79_switch_data.phy4_mii_en = 1; + ath79_switch_data.phy_poll_mask = BIT(4); + ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_MII; + ath79_eth0_data.phy_mask = BIT(4); + ath79_eth0_data.mii_bus_dev = &ath79_mdio1_device.dev; + + ath79_register_eth(0); + + gpio_request_one(WDR3500_GPIO_USB_POWER, + GPIOF_OUT_INIT_HIGH | GPIOF_EXPORT_DIR_FIXED, + "USB power"); + ath79_register_usb(); + + ath79_gpio_output_select(WDR3500_GPIO_LED_LAN1, + AR934X_GPIO_OUT_LED_LINK3); + ath79_gpio_output_select(WDR3500_GPIO_LED_LAN2, + AR934X_GPIO_OUT_LED_LINK2); + ath79_gpio_output_select(WDR3500_GPIO_LED_LAN3, + AR934X_GPIO_OUT_LED_LINK1); + ath79_gpio_output_select(WDR3500_GPIO_LED_LAN4, + AR934X_GPIO_OUT_LED_LINK0); + ath79_gpio_output_select(WDR3500_GPIO_LED_WAN, + AR934X_GPIO_OUT_LED_LINK4); +} + +MIPS_MACHINE(ATH79_MACH_TL_WDR3500, "TL-WDR3500", + "TP-LINK TL-WDR3500", + wdr3500_setup); diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wdr4300.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wdr4300.c index 331de5680..bf4cf4629 100644 --- a/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wdr4300.c +++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wdr4300.c @@ -121,7 +121,7 @@ static struct ar8327_led_cfg wdr4300_ar8327_led_cfg = { static struct ar8327_platform_data wdr4300_ar8327_data = { .pad0_cfg = &wdr4300_ar8327_pad0_cfg, - .cpuport_cfg = { + .port0_cfg = { .force_link = 1, .speed = AR8327_PORT_SPEED_1000, .duplex = 1, @@ -139,23 +139,6 @@ static struct mdio_board_info wdr4300_mdio0_info[] = { }, }; -static void __init wdr4300_gmac_setup(void) -{ - void __iomem *base; - u32 t; - - base = ioremap(AR934X_GMAC_BASE, AR934X_GMAC_SIZE); - - t = __raw_readl(base + AR934X_GMAC_REG_ETH_CFG); - t &= ~(AR934X_ETH_CFG_RGMII_GMAC0 | AR934X_ETH_CFG_MII_GMAC0 | - AR934X_ETH_CFG_GMII_GMAC0 | AR934X_ETH_CFG_SW_ONLY_MODE); - t |= AR934X_ETH_CFG_RGMII_GMAC0; - - __raw_writel(t, base + AR934X_GMAC_REG_ETH_CFG); - - iounmap(base); -} - static void __init wdr4300_setup(void) { u8 *mac = (u8 *) KSEG1ADDR(0x1f01fc00); @@ -176,7 +159,7 @@ static void __init wdr4300_setup(void) ap9x_pci_setup_wmac_led_pin(0, 0); ap91_pci_init(art + WDR4300_PCIE_CALDATA_OFFSET, tmpmac); - wdr4300_gmac_setup(); + ath79_setup_ar934x_eth_cfg(AR934X_ETH_CFG_RGMII_GMAC0); mdiobus_register_board_info(wdr4300_mdio0_info, ARRAY_SIZE(wdr4300_mdio0_info)); @@ -192,10 +175,12 @@ static void __init wdr4300_setup(void) ath79_eth0_pll_data.pll_1000 = 0x06000000; ath79_register_eth(0); - ath79_set_usb_power_gpio(WDR4300_GPIO_USB1_POWER, GPIOF_OUT_INIT_HIGH, - "USB1 power"); - ath79_set_usb_power_gpio(WDR4300_GPIO_USB2_POWER, GPIOF_OUT_INIT_HIGH, - "USB2 power"); + gpio_request_one(WDR4300_GPIO_USB1_POWER, + GPIOF_OUT_INIT_HIGH | GPIOF_EXPORT_DIR_FIXED, + "USB1 power"); + gpio_request_one(WDR4300_GPIO_USB2_POWER, + GPIOF_OUT_INIT_HIGH | GPIOF_EXPORT_DIR_FIXED, + "USB2 power"); ath79_register_usb(); } diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wr1041n-v2.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wr1041n-v2.c index ed5b2b0e6..fa8c4749c 100644 --- a/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wr1041n-v2.c +++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wr1041n-v2.c @@ -84,7 +84,7 @@ static struct ar8327_pad_cfg db120_ar8327_pad0_cfg = { static struct ar8327_platform_data db120_ar8327_data = { .pad0_cfg = &db120_ar8327_pad0_cfg, - .cpuport_cfg = { + .port0_cfg = { .force_link = 1, .speed = AR8327_PORT_SPEED_1000, .duplex = 1, @@ -101,23 +101,6 @@ static struct mdio_board_info db120_mdio0_info[] = { }, }; -static void __init db120_gmac_setup(void) -{ - void __iomem *base; - u32 t; - - base = ioremap(AR934X_GMAC_BASE, AR934X_GMAC_SIZE); - - t = __raw_readl(base + AR934X_GMAC_REG_ETH_CFG); - t &= ~(AR934X_ETH_CFG_RGMII_GMAC0 | AR934X_ETH_CFG_MII_GMAC0 | - AR934X_ETH_CFG_GMII_GMAC0 | AR934X_ETH_CFG_SW_ONLY_MODE); - t |= AR934X_ETH_CFG_RGMII_GMAC0 | AR934X_ETH_CFG_SW_ONLY_MODE; - - __raw_writel(t, base + AR934X_GMAC_REG_ETH_CFG); - - iounmap(base); -} - static void __init tl_wr1041nv2_setup(void) { u8 *mac = (u8 *) KSEG1ADDR(0x1f01fc00); @@ -132,7 +115,8 @@ static void __init tl_wr1041nv2_setup(void) tl_wr1041nv2_gpio_keys); ath79_register_wmac(ee, mac); - db120_gmac_setup(); + ath79_setup_ar934x_eth_cfg(AR934X_ETH_CFG_RGMII_GMAC0 | + AR934X_ETH_CFG_SW_ONLY_MODE); ath79_register_mdio(1, 0x0); ath79_register_mdio(0, 0x0); diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wr703n.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wr703n.c index f60f96245..90342e0b6 100644 --- a/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wr703n.c +++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wr703n.c @@ -62,6 +62,9 @@ static void __init tl_wr703n_setup(void) u8 *mac = (u8 *) KSEG1ADDR(0x1f01fc00); u8 *ee = (u8 *) KSEG1ADDR(0x1fff1000); + /* disable PHY_SWAP and PHY_ADDR_SWAP bits */ + ath79_setup_ar933x_phy4_switch(false, false); + ath79_register_m25p80(&tl_wr703n_flash_data); ath79_register_leds_gpio(-1, ARRAY_SIZE(tl_wr703n_leds_gpio), tl_wr703n_leds_gpio); @@ -69,8 +72,9 @@ static void __init tl_wr703n_setup(void) ARRAY_SIZE(tl_wr703n_gpio_keys), tl_wr703n_gpio_keys); - ath79_set_usb_power_gpio(TL_WR703N_GPIO_USB_POWER, GPIOF_OUT_INIT_HIGH, - "USB power"); + gpio_request_one(TL_WR703N_GPIO_USB_POWER, + GPIOF_OUT_INIT_HIGH | GPIOF_EXPORT_DIR_FIXED, + "USB power"); ath79_register_usb(); ath79_init_mac(ath79_eth0_data.mac_addr, mac, 0); diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wr720n-v3.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wr720n-v3.c new file mode 100644 index 000000000..80e8df685 --- /dev/null +++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wr720n-v3.c @@ -0,0 +1,109 @@ +/* + * TP-LINK TL-WR720N board support + * + * Copyright (C) 2011 dongyuqi <729650915@qq.com> + * Copyright (C) 2011-2012 Gabor Juhos <juhosg@openwrt.org> + * Copyright (C) 2013 yousong <yszhou4tech@gmail.com> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + */ + +#include <linux/gpio.h> + +#include <asm/mach-ath79/ath79.h> + +#include "dev-eth.h" +#include "dev-gpio-buttons.h" +#include "dev-leds-gpio.h" +#include "dev-m25p80.h" +#include "dev-usb.h" +#include "dev-wmac.h" +#include "machtypes.h" + +#define TL_WR720N_GPIO_LED_SYSTEM 27 +#define TL_WR720N_GPIO_BTN_RESET 11 +#define TL_WR720N_GPIO_BTN_SW1 18 +#define TL_WR720N_GPIO_BTN_SW2 20 + +#define TL_WR720N_GPIO_USB_POWER 8 + +#define TL_WR720N_KEYS_POLL_INTERVAL 20 /* msecs */ +#define TL_WR720N_KEYS_DEBOUNCE_INTERVAL (3 * TL_WR720N_KEYS_POLL_INTERVAL) + +static const char *tl_wr720n_part_probes[] = { + "tp-link", + NULL, +}; + +static struct flash_platform_data tl_wr720n_flash_data = { + .part_probes = tl_wr720n_part_probes, +}; + +static struct gpio_led tl_wr720n_leds_gpio[] __initdata = { + { + .name = "tp-link:blue:system", + .gpio = TL_WR720N_GPIO_LED_SYSTEM, + .active_low = 1, + }, +}; + +static struct gpio_keys_button tl_wr720n_gpio_keys[] __initdata = { + { + .desc = "reset", + .type = EV_KEY, + .code = KEY_RESTART, + .debounce_interval = TL_WR720N_KEYS_DEBOUNCE_INTERVAL, + .gpio = TL_WR720N_GPIO_BTN_RESET, + .active_low = 0, + }, { + .desc = "sw1", + .type = EV_KEY, + .code = BTN_0, + .debounce_interval = TL_WR720N_KEYS_DEBOUNCE_INTERVAL, + .gpio = TL_WR720N_GPIO_BTN_SW1, + .active_low = 0, + }, { + .desc = "sw2", + .type = EV_KEY, + .code = BTN_1, + .debounce_interval = TL_WR720N_KEYS_DEBOUNCE_INTERVAL, + .gpio = TL_WR720N_GPIO_BTN_SW2, + .active_low = 0, + } +}; + +static void __init tl_wr720n_v3_setup(void) +{ + u8 *mac = (u8 *) KSEG1ADDR(0x1f01fc00); + u8 *ee = (u8 *) KSEG1ADDR(0x1fff1000); + + /* disable PHY_SWAP and PHY_ADDR_SWAP bits */ + ath79_setup_ar933x_phy4_switch(false, false); + + ath79_register_m25p80(&tl_wr720n_flash_data); + ath79_register_leds_gpio(-1, ARRAY_SIZE(tl_wr720n_leds_gpio), + tl_wr720n_leds_gpio); + ath79_register_gpio_keys_polled(-1, TL_WR720N_KEYS_POLL_INTERVAL, + ARRAY_SIZE(tl_wr720n_gpio_keys), + tl_wr720n_gpio_keys); + + gpio_request_one(TL_WR720N_GPIO_USB_POWER, + GPIOF_OUT_INIT_HIGH | GPIOF_EXPORT_DIR_FIXED, + "USB power"); + ath79_register_usb(); + + ath79_init_mac(ath79_eth0_data.mac_addr, mac, 1); + ath79_init_mac(ath79_eth1_data.mac_addr, mac, 2); + + ath79_register_mdio(0, 0x0); + ath79_register_eth(0); + ath79_register_eth(1); + + ath79_register_wmac(ee, mac); +} + +MIPS_MACHINE(ATH79_MACH_TL_WR720N_V3, "TL-WR720N-v3", "TP-LINK TL-WR720N v3", + tl_wr720n_v3_setup); + diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wr741nd-v4.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wr741nd-v4.c index 0d758913f..7eb4d2fce 100644 --- a/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wr741nd-v4.c +++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wr741nd-v4.c @@ -1,5 +1,5 @@ /* - * TP-LINK TL-WR741ND v4 board support + * TP-LINK TL-WR741ND v4/TL-MR3220 v2 board support * * Copyright (C) 2011-2012 Gabor Juhos <juhosg@openwrt.org> * @@ -18,6 +18,7 @@ #include "dev-gpio-buttons.h" #include "dev-leds-gpio.h" #include "dev-m25p80.h" +#include "dev-usb.h" #include "dev-wmac.h" #include "machtypes.h" @@ -31,9 +32,11 @@ #define TL_WR741NDV4_GPIO_LED_LAN2 15 #define TL_WR741NDV4_GPIO_LED_LAN3 16 #define TL_WR741NDV4_GPIO_LED_LAN4 17 - #define TL_WR741NDV4_GPIO_LED_SYSTEM 27 +#define TL_MR3220V2_GPIO_LED_3G 26 +#define TL_MR3220V2_GPIO_USB_POWER 8 + #define TL_WR741NDV4_KEYS_POLL_INTERVAL 20 /* msecs */ #define TL_WR741NDV4_KEYS_DEBOUNCE_INTERVAL (3 * TL_WR741NDV4_KEYS_POLL_INTERVAL) @@ -79,6 +82,11 @@ static struct gpio_led tl_wr741ndv4_leds_gpio[] __initdata = { .name = "tp-link:green:wlan", .gpio = TL_WR741NDV4_GPIO_LED_WLAN, .active_low = 0, + }, { + /* the 3G LED is only present on the MR3220 v2 */ + .name = "tp-link:green:3g", + .gpio = TL_MR3220V2_GPIO_LED_3G, + .active_low = 0, }, }; @@ -91,6 +99,7 @@ static struct gpio_keys_button tl_wr741ndv4_gpio_keys[] __initdata = { .gpio = TL_WR741NDV4_GPIO_BTN_RESET, .active_low = 0, }, { + /* the WPS button is only present on the WR741ND v4 */ .desc = "WPS", .type = EV_KEY, .code = KEY_WPS_BUTTON, @@ -100,7 +109,7 @@ static struct gpio_keys_button tl_wr741ndv4_gpio_keys[] __initdata = { } }; -static void __init tl_wr741ndv4_setup(void) +static void __init tl_ap121_setup(void) { u8 *mac = (u8 *) KSEG1ADDR(0x1f01fc00); u8 *ee = (u8 *) KSEG1ADDR(0x1fff1000); @@ -113,13 +122,6 @@ static void __init tl_wr741ndv4_setup(void) AR933X_GPIO_FUNC_ETH_SWITCH_LED3_EN | AR933X_GPIO_FUNC_ETH_SWITCH_LED4_EN); - ath79_register_leds_gpio(-1, ARRAY_SIZE(tl_wr741ndv4_leds_gpio), - tl_wr741ndv4_leds_gpio); - - ath79_register_gpio_keys_polled(1, TL_WR741NDV4_KEYS_POLL_INTERVAL, - ARRAY_SIZE(tl_wr741ndv4_gpio_keys), - tl_wr741ndv4_gpio_keys); - ath79_register_m25p80(&tl_wr741ndv4_flash_data); ath79_init_mac(ath79_eth0_data.mac_addr, mac, 1); ath79_init_mac(ath79_eth1_data.mac_addr, mac, -1); @@ -131,5 +133,35 @@ static void __init tl_wr741ndv4_setup(void) ath79_register_wmac(ee, mac); } +static void __init tl_wr741ndv4_setup(void) +{ + tl_ap121_setup(); + + ath79_register_leds_gpio(-1, ARRAY_SIZE(tl_wr741ndv4_leds_gpio) - 1, + tl_wr741ndv4_leds_gpio); + ath79_register_gpio_keys_polled(1, TL_WR741NDV4_KEYS_POLL_INTERVAL, + ARRAY_SIZE(tl_wr741ndv4_gpio_keys), + tl_wr741ndv4_gpio_keys); +} + MIPS_MACHINE(ATH79_MACH_TL_WR741ND_V4, "TL-WR741ND-v4", "TP-LINK TL-WR741ND v4", tl_wr741ndv4_setup); + +static void __init tl_mr3220v2_setup(void) +{ + tl_ap121_setup(); + + gpio_request_one(TL_MR3220V2_GPIO_USB_POWER, + GPIOF_OUT_INIT_HIGH | GPIOF_EXPORT_DIR_FIXED, + "USB power"); + ath79_register_usb(); + + ath79_register_leds_gpio(-1, ARRAY_SIZE(tl_wr741ndv4_leds_gpio), + tl_wr741ndv4_leds_gpio); + ath79_register_gpio_keys_polled(1, TL_WR741NDV4_KEYS_POLL_INTERVAL, + ARRAY_SIZE(tl_wr741ndv4_gpio_keys) - 1, + tl_wr741ndv4_gpio_keys); +} + +MIPS_MACHINE(ATH79_MACH_TL_MR3220_V2, "TL-MR3220-v2", + "TP-LINK TL-MR3220 v2", tl_mr3220v2_setup); diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wr841n-v8.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wr841n-v8.c new file mode 100644 index 000000000..fd1f54c01 --- /dev/null +++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wr841n-v8.c @@ -0,0 +1,194 @@ +/* + * TP-LINK TL-WR841N/ND v8/TL-MR3420 v2 board support + * + * Copyright (C) 2012 Gabor Juhos <juhosg@openwrt.org> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + */ + +#include <linux/gpio.h> +#include <linux/platform_device.h> + +#include <asm/mach-ath79/ath79.h> +#include <asm/mach-ath79/ar71xx_regs.h> + +#include "common.h" +#include "dev-eth.h" +#include "dev-gpio-buttons.h" +#include "dev-leds-gpio.h" +#include "dev-m25p80.h" +#include "dev-usb.h" +#include "dev-wmac.h" +#include "machtypes.h" + +#define TL_WR841NV8_GPIO_LED_WLAN 13 +#define TL_WR841NV8_GPIO_LED_QSS 15 +#define TL_WR841NV8_GPIO_LED_WAN 18 +#define TL_WR841NV8_GPIO_LED_LAN1 19 +#define TL_WR841NV8_GPIO_LED_LAN2 20 +#define TL_WR841NV8_GPIO_LED_LAN3 21 +#define TL_WR841NV8_GPIO_LED_LAN4 12 +#define TL_WR841NV8_GPIO_LED_SYSTEM 14 + +#define TL_WR841NV8_GPIO_BTN_RESET 17 +#define TL_WR841NV8_GPIO_SW_RFKILL 16 /* WPS for MR3420 v2 */ + +#define TL_MR3420V2_GPIO_LED_3G 11 +#define TL_MR3420V2_GPIO_USB_POWER 4 + +#define TL_WR841NV8_KEYS_POLL_INTERVAL 20 /* msecs */ +#define TL_WR841NV8_KEYS_DEBOUNCE_INTERVAL (3 * TL_WR841NV8_KEYS_POLL_INTERVAL) + +static const char *tl_wr841n_v8_part_probes[] = { + "tp-link", + NULL, +}; + +static struct flash_platform_data tl_wr841n_v8_flash_data = { + .part_probes = tl_wr841n_v8_part_probes, +}; + +static struct gpio_led tl_wr841n_v8_leds_gpio[] __initdata = { + { + .name = "tp-link:green:lan1", + .gpio = TL_WR841NV8_GPIO_LED_LAN1, + .active_low = 1, + }, { + .name = "tp-link:green:lan2", + .gpio = TL_WR841NV8_GPIO_LED_LAN2, + .active_low = 1, + }, { + .name = "tp-link:green:lan3", + .gpio = TL_WR841NV8_GPIO_LED_LAN3, + .active_low = 1, + }, { + .name = "tp-link:green:lan4", + .gpio = TL_WR841NV8_GPIO_LED_LAN4, + .active_low = 1, + }, { + .name = "tp-link:green:qss", + .gpio = TL_WR841NV8_GPIO_LED_QSS, + .active_low = 1, + }, { + .name = "tp-link:green:system", + .gpio = TL_WR841NV8_GPIO_LED_SYSTEM, + .active_low = 1, + }, { + .name = "tp-link:green:wan", + .gpio = TL_WR841NV8_GPIO_LED_WAN, + .active_low = 1, + }, { + .name = "tp-link:green:wlan", + .gpio = TL_WR841NV8_GPIO_LED_WLAN, + .active_low = 1, + }, { + /* the 3G LED is only present on the MR3420 v2 */ + .name = "tp-link:green:3g", + .gpio = TL_MR3420V2_GPIO_LED_3G, + .active_low = 1, + }, +}; + +static struct gpio_keys_button tl_wr841n_v8_gpio_keys[] __initdata = { + { + .desc = "Reset button", + .type = EV_KEY, + .code = KEY_RESTART, + .debounce_interval = TL_WR841NV8_KEYS_DEBOUNCE_INTERVAL, + .gpio = TL_WR841NV8_GPIO_BTN_RESET, + .active_low = 1, + }, { + .desc = "RFKILL switch", + .type = EV_SW, + .code = KEY_RFKILL, + .debounce_interval = TL_WR841NV8_KEYS_DEBOUNCE_INTERVAL, + .gpio = TL_WR841NV8_GPIO_SW_RFKILL, + .active_low = 0, + } +}; + +static struct gpio_keys_button tl_mr3420v2_gpio_keys[] __initdata = { + { + .desc = "Reset button", + .type = EV_KEY, + .code = KEY_RESTART, + .debounce_interval = TL_WR841NV8_KEYS_DEBOUNCE_INTERVAL, + .gpio = TL_WR841NV8_GPIO_BTN_RESET, + .active_low = 1, + }, { + .desc = "WPS", + .type = EV_KEY, + .code = KEY_WPS_BUTTON, + .debounce_interval = TL_WR841NV8_KEYS_DEBOUNCE_INTERVAL, + .gpio = TL_WR841NV8_GPIO_SW_RFKILL, + .active_low = 0, + } +}; + +static void __init tl_ap123_setup(void) +{ + u8 *mac = (u8 *) KSEG1ADDR(0x1f01fc00); + u8 *ee = (u8 *) KSEG1ADDR(0x1fff1000); + + ath79_register_m25p80(&tl_wr841n_v8_flash_data); + + ath79_setup_ar934x_eth_cfg(AR934X_ETH_CFG_SW_PHY_SWAP); + + ath79_register_mdio(1, 0x0); + + ath79_init_mac(ath79_eth0_data.mac_addr, mac, -1); + ath79_init_mac(ath79_eth1_data.mac_addr, mac, 0); + + /* GMAC0 is connected to the PHY0 of the internal switch */ + ath79_switch_data.phy4_mii_en = 1; + ath79_switch_data.phy_poll_mask = BIT(0); + ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_MII; + ath79_eth0_data.phy_mask = BIT(0); + ath79_eth0_data.mii_bus_dev = &ath79_mdio1_device.dev; + ath79_register_eth(0); + + /* GMAC1 is connected to the internal switch */ + ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_GMII; + ath79_register_eth(1); + + ath79_register_wmac(ee, mac); +} + +static void __init tl_wr841n_v8_setup(void) +{ + tl_ap123_setup(); + + ath79_register_leds_gpio(-1, ARRAY_SIZE(tl_wr841n_v8_leds_gpio) - 1, + tl_wr841n_v8_leds_gpio); + + ath79_register_gpio_keys_polled(1, TL_WR841NV8_KEYS_POLL_INTERVAL, + ARRAY_SIZE(tl_wr841n_v8_gpio_keys), + tl_wr841n_v8_gpio_keys); +} + +MIPS_MACHINE(ATH79_MACH_TL_WR841N_V8, "TL-WR841N-v8", "TP-LINK TL-WR841N/ND v8", + tl_wr841n_v8_setup); + +static void __init tl_mr3420v2_setup(void) +{ + tl_ap123_setup(); + + ath79_register_leds_gpio(-1, ARRAY_SIZE(tl_wr841n_v8_leds_gpio), + tl_wr841n_v8_leds_gpio); + + ath79_register_gpio_keys_polled(1, TL_WR841NV8_KEYS_POLL_INTERVAL, + ARRAY_SIZE(tl_mr3420v2_gpio_keys), + tl_mr3420v2_gpio_keys); + + /* enable power for the USB port */ + gpio_request_one(TL_MR3420V2_GPIO_USB_POWER, + GPIOF_OUT_INIT_HIGH | GPIOF_EXPORT_DIR_FIXED, + "USB power"); + + ath79_register_usb(); +} + +MIPS_MACHINE(ATH79_MACH_TL_MR3420_V2, "TL-MR3420-v2", "TP-LINK TL-MR3420 v2", + tl_mr3420v2_setup); diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-wndap360.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-wndap360.c new file mode 100644 index 000000000..3d8d6b0af --- /dev/null +++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-wndap360.c @@ -0,0 +1,105 @@ +/* + * Netgear WNDAP360 board support (proper leds / button support missing) + * + * Based on AP96 + * Copyright (C) 2013 Jacek Kikiewicz + * Copyright (C) 2009 Marco Porsch + * Copyright (C) 2009-2012 Gabor Juhos <juhosg@openwrt.org> + * Copyright (C) 2010 Atheros Communications + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + */ + +#include <linux/platform_device.h> +#include <linux/delay.h> + +#include <asm/mach-ath79/ath79.h> + +#include "dev-ap9x-pci.h" +#include "dev-eth.h" +#include "dev-gpio-buttons.h" +#include "dev-leds-gpio.h" +#include "dev-m25p80.h" +#include "dev-usb.h" +#include "machtypes.h" + +#define WNDAP360_GPIO_LED_POWER_ORANGE 0 +#define WNDAP360_GPIO_LED_POWER_GREEN 2 + +/* Reset button - next to the power connector */ +#define WNDAP360_GPIO_BTN_RESET 3 +/* WPS button - next to a led on right */ +#define WNDAP360_GPIO_BTN_WPS 8 + +#define WNDAP360_KEYS_POLL_INTERVAL 20 /* msecs */ +#define WNDAP360_KEYS_DEBOUNCE_INTERVAL (3 * WNDAP360_KEYS_POLL_INTERVAL) + +#define WNDAP360_WMAC0_MAC_OFFSET 0x120c +#define WNDAP360_WMAC1_MAC_OFFSET 0x520c +#define WNDAP360_CALDATA0_OFFSET 0x1000 +#define WNDAP360_CALDATA1_OFFSET 0x5000 + +/* + * WNDAP360 this still uses leds definitions from AP96 + * + */ +static struct gpio_led wndap360_leds_gpio[] __initdata = { + { + .name = "wndap360:green:power", + .gpio = WNDAP360_GPIO_LED_POWER_GREEN, + .active_low = 1, + }, { + .name = "wndap360:orange:power", + .gpio = WNDAP360_GPIO_LED_POWER_ORANGE, + .active_low = 1, + } +}; + +static struct gpio_keys_button wndap360_gpio_keys[] __initdata = { + { + .desc = "reset", + .type = EV_KEY, + .code = KEY_RESTART, + .debounce_interval = WNDAP360_KEYS_DEBOUNCE_INTERVAL, + .gpio = WNDAP360_GPIO_BTN_RESET, + .active_low = 1, + } +}; + +#define WNDAP360_LAN_PHYMASK 0x0f + +static void __init wndap360_setup(void) +{ + u8 *art = (u8 *) KSEG1ADDR(0x1fff0000); + + ath79_register_mdio(0, ~(WNDAP360_LAN_PHYMASK)); + + ath79_init_mac(ath79_eth0_data.mac_addr, art, 0); + ath79_eth0_pll_data.pll_1000 = 0x11110000; + ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; + ath79_eth0_data.phy_mask = WNDAP360_LAN_PHYMASK; + ath79_eth0_data.speed = SPEED_1000; + ath79_eth0_data.duplex = DUPLEX_FULL; + + ath79_register_eth(0); + + ath79_register_usb(); + + ath79_register_m25p80(NULL); + + ath79_register_leds_gpio(-1, ARRAY_SIZE(wndap360_leds_gpio), + wndap360_leds_gpio); + + ath79_register_gpio_keys_polled(-1, WNDAP360_KEYS_POLL_INTERVAL, + ARRAY_SIZE(wndap360_gpio_keys), + wndap360_gpio_keys); + + ap94_pci_init(art + WNDAP360_CALDATA0_OFFSET, + art + WNDAP360_WMAC0_MAC_OFFSET, + art + WNDAP360_CALDATA1_OFFSET, + art + WNDAP360_WMAC1_MAC_OFFSET); +} + +MIPS_MACHINE(ATH79_MACH_WNDAP360, "WNDAP360", "Netgear WNDAP360", wndap360_setup); diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-wndr4300.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-wndr4300.c new file mode 100644 index 000000000..715fb064f --- /dev/null +++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-wndr4300.c @@ -0,0 +1,182 @@ +/* + * NETGEAR WNDR4300 board support + * + * Copyright (C) 2012 Gabor Juhos <juhosg@openwrt.org> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + */ + +#include <linux/pci.h> +#include <linux/phy.h> +#include <linux/gpio.h> +#include <linux/platform_device.h> +#include <linux/ath9k_platform.h> +#include <linux/ar8216_platform.h> + +#include <asm/mach-ath79/ar71xx_regs.h> + +#include "common.h" +#include "dev-ap9x-pci.h" +#include "dev-eth.h" +#include "dev-gpio-buttons.h" +#include "dev-leds-gpio.h" +#include "dev-nfc.h" +#include "dev-usb.h" +#include "dev-wmac.h" +#include "machtypes.h" + +#define WNDR4300_GPIO_LED_POWER_GREEN 0 +#define WNDR4300_GPIO_LED_POWER_ORANGE 2 +#define WNDR4300_GPIO_LED_USB 13 +#define WNDR4300_GPIO_LED_WAN_GREEN 1 +#define WNDR4300_GPIO_LED_WAN_ORANGE 3 +#define WNDR4300_GPIO_LED_WLAN5G 14 +#define WNDR4300_GPIO_LED_WPS_GREEN 16 +#define WNDR4300_GPIO_LED_WPS_ORANGE 17 + +#define WNDR4300_GPIO_BTN_RESET 21 +#define WNDR4300_GPIO_BTN_WIRELESS 15 +#define WNDR4300_GPIO_BTN_WPS 12 + +#define WNDR4300_KEYS_POLL_INTERVAL 20 /* msecs */ +#define WNDR4300_KEYS_DEBOUNCE_INTERVAL (3 * WNDR4300_KEYS_POLL_INTERVAL) + +static struct gpio_led wndr4300_leds_gpio[] __initdata = { + { + .name = "netgear:green:power", + .gpio = WNDR4300_GPIO_LED_POWER_GREEN, + .active_low = 1, + }, + { + .name = "netgear:orange:power", + .gpio = WNDR4300_GPIO_LED_POWER_ORANGE, + .active_low = 1, + }, + { + .name = "netgear:green:wan", + .gpio = WNDR4300_GPIO_LED_WAN_GREEN, + .active_low = 1, + }, + { + .name = "netgear:orange:wan", + .gpio = WNDR4300_GPIO_LED_WAN_ORANGE, + .active_low = 1, + }, + { + .name = "netgear:green:usb", + .gpio = WNDR4300_GPIO_LED_USB, + .active_low = 1, + }, + { + .name = "netgear:green:wps", + .gpio = WNDR4300_GPIO_LED_WPS_GREEN, + .active_low = 1, + }, + { + .name = "netgear:orange:wps", + .gpio = WNDR4300_GPIO_LED_WPS_ORANGE, + .active_low = 1, + }, + { + .name = "netgear:blue:wlan5g", + .gpio = WNDR4300_GPIO_LED_WLAN5G, + .active_low = 1, + }, +}; + +static struct gpio_keys_button wndr4300_gpio_keys[] __initdata = { + { + .desc = "Reset button", + .type = EV_KEY, + .code = KEY_RESTART, + .debounce_interval = WNDR4300_KEYS_DEBOUNCE_INTERVAL, + .gpio = WNDR4300_GPIO_BTN_RESET, + .active_low = 1, + }, + { + .desc = "WPS button", + .type = EV_KEY, + .code = KEY_WPS_BUTTON, + .debounce_interval = WNDR4300_KEYS_DEBOUNCE_INTERVAL, + .gpio = WNDR4300_GPIO_BTN_WPS, + .active_low = 1, + }, + { + .desc = "Wireless button", + .type = EV_KEY, + .code = BTN_0, + .debounce_interval = WNDR4300_KEYS_DEBOUNCE_INTERVAL, + .gpio = WNDR4300_GPIO_BTN_WIRELESS, + .active_low = 1, + }, +}; + +static struct ar8327_pad_cfg wndr4300_ar8327_pad0_cfg = { + .mode = AR8327_PAD_MAC_RGMII, + .txclk_delay_en = true, + .rxclk_delay_en = true, + .txclk_delay_sel = AR8327_CLK_DELAY_SEL1, + .rxclk_delay_sel = AR8327_CLK_DELAY_SEL2, +}; + +static struct ar8327_led_cfg wndr4300_ar8327_led_cfg = { + .led_ctrl0 = 0xc737c737, + .led_ctrl1 = 0x00000000, + .led_ctrl2 = 0x00000000, + .led_ctrl3 = 0x0030c300, + .open_drain = false, +}; + +static struct ar8327_platform_data wndr4300_ar8327_data = { + .pad0_cfg = &wndr4300_ar8327_pad0_cfg, + .port0_cfg = { + .force_link = 1, + .speed = AR8327_PORT_SPEED_1000, + .duplex = 1, + .txpause = 1, + .rxpause = 1, + }, + .led_cfg = &wndr4300_ar8327_led_cfg, +}; + +static struct mdio_board_info wndr4300_mdio0_info[] = { + { + .bus_id = "ag71xx-mdio.0", + .phy_addr = 0, + .platform_data = &wndr4300_ar8327_data, + }, +}; + +static void __init wndr4300_setup(void) +{ + ath79_register_leds_gpio(-1, ARRAY_SIZE(wndr4300_leds_gpio), + wndr4300_leds_gpio); + ath79_register_gpio_keys_polled(-1, WNDR4300_KEYS_POLL_INTERVAL, + ARRAY_SIZE(wndr4300_gpio_keys), + wndr4300_gpio_keys); + + ath79_setup_ar934x_eth_cfg(AR934X_ETH_CFG_RGMII_GMAC0); + + mdiobus_register_board_info(wndr4300_mdio0_info, + ARRAY_SIZE(wndr4300_mdio0_info)); + + ath79_register_mdio(0, 0x0); + + /* GMAC0 is connected to an AR8327N switch */ + ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; + ath79_eth0_data.phy_mask = BIT(0); + ath79_eth0_data.mii_bus_dev = &ath79_mdio0_device.dev; + ath79_eth0_pll_data.pll_1000 = 0x06000000; + ath79_register_eth(0); + + ath79_register_nfc(); + ath79_register_usb(); + + ath79_register_wmac_simple(); + ap91_pci_init_simple(); +} + +MIPS_MACHINE(ATH79_MACH_WNDR4300, "WNDR4300", "NETGEAR WNDR4300", + wndr4300_setup); diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-wnr2000-v3.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-wnr2000-v3.c new file mode 100644 index 000000000..bb7b24c36 --- /dev/null +++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-wnr2000-v3.c @@ -0,0 +1,91 @@ +/* + * NETGEAR WNR2000v3 board support + * + * Copytight (C) 2013 Mathieu Olivari <mathieu.olivari@gmail.com> + * Copyright (C) 2008-2009 Gabor Juhos <juhosg@openwrt.org> + * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> + * Copyright (C) 2008-2009 Andy Boyett <agb@openwrt.org> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + */ + +#include <linux/mtd/mtd.h> +#include <linux/mtd/partitions.h> + +#include <asm/mach-ath79/ath79.h> + +#include "dev-ap9x-pci.h" +#include "dev-eth.h" +#include "dev-gpio-buttons.h" +#include "dev-leds-gpio.h" +#include "dev-m25p80.h" +#include "machtypes.h" + +#define WNR2000V3_GPIO_LED_WAN_GREEN 0 +#define WNR2000V3_GPIO_LED_LAN1_AMBER 1 +#define WNR2000V3_GPIO_LED_LAN4_AMBER 12 +#define WNR2000V3_GPIO_LED_PWR_GREEN 14 +#define WNR2000V3_GPIO_BTN_WPS 11 + +#define WNR2000V3_KEYS_POLL_INTERVAL 20 /* msecs */ +#define WNR2000V3_KEYS_DEBOUNCE_INTERVAL (3 * WNR2000V3_KEYS_POLL_INTERVAL) + +#define WNR2000V3_MAC0_OFFSET 0 +#define WNR2000V3_MAC1_OFFSET 6 +#define WNR2000V3_PCIE_CALDATA_OFFSET 0x1000 + +static struct gpio_led wnr2000v3_leds_gpio[] __initdata = { + { + .name = "wnr2000v3:green:power", + .gpio = WNR2000V3_GPIO_LED_PWR_GREEN, + .active_low = 1, + }, { + .name = "wnr2000v3:green:wan", + .gpio = WNR2000V3_GPIO_LED_WAN_GREEN, + .active_low = 1, + } +}; + +static struct gpio_keys_button wnr2000v3_gpio_keys[] __initdata = { + { + .desc = "wps", + .type = EV_KEY, + .code = KEY_WPS_BUTTON, + .debounce_interval = WNR2000V3_KEYS_DEBOUNCE_INTERVAL, + .gpio = WNR2000V3_GPIO_BTN_WPS, + } +}; + +static void __init wnr2000v3_setup(void) +{ + u8 *art = (u8 *) KSEG1ADDR(0x1fff0000); + + ath79_register_mdio(0, 0x0); + + ath79_init_mac(ath79_eth0_data.mac_addr, art+WNR2000V3_MAC0_OFFSET, 0); + ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RMII; + ath79_eth0_data.speed = SPEED_100; + ath79_eth0_data.duplex = DUPLEX_FULL; + + ath79_init_mac(ath79_eth1_data.mac_addr, art+WNR2000V3_MAC1_OFFSET, 0); + ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_RMII; + ath79_eth1_data.phy_mask = 0x10; + + ath79_register_eth(0); + ath79_register_eth(1); + + ath79_register_m25p80(NULL); + + ath79_register_leds_gpio(-1, ARRAY_SIZE(wnr2000v3_leds_gpio), + wnr2000v3_leds_gpio); + + ath79_register_gpio_keys_polled(-1, WNR2000V3_KEYS_POLL_INTERVAL, + ARRAY_SIZE(wnr2000v3_gpio_keys), + wnr2000v3_gpio_keys); + + ap91_pci_init(art + WNR2000V3_PCIE_CALDATA_OFFSET, NULL); +} + +MIPS_MACHINE(ATH79_MACH_WNR2000_V3, "WNR2000V3", "NETGEAR WNR2000 V3", wnr2000v3_setup); diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-wzr-hp-ag300h.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-wzr-hp-ag300h.c index 868514c95..9ba5ecd2e 100644 --- a/target/linux/ar71xx/files/arch/mips/ath79/mach-wzr-hp-ag300h.c +++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-wzr-hp-ag300h.c @@ -185,7 +185,8 @@ static void __init wzrhpag300h_setup(void) ath79_register_eth(0); ath79_register_eth(1); - ath79_set_usb_power_gpio(2, GPIOF_OUT_INIT_HIGH, "USB power"); + gpio_request_one(2, GPIOF_OUT_INIT_HIGH | GPIOF_EXPORT_DIR_FIXED, + "USB power"); ath79_register_usb(); ath79_register_leds_gpio(-1, ARRAY_SIZE(wzrhpag300h_leds_gpio), @@ -209,5 +210,4 @@ static void __init wzrhpag300h_setup(void) } MIPS_MACHINE(ATH79_MACH_WZR_HP_AG300H, "WZR-HP-AG300H", - "Buffalo WZR-HP-AG300H", wzrhpag300h_setup); - + "Buffalo WZR-HP-AG300H/WZR-600DHP", wzrhpag300h_setup); diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-wzr-hp-g300nh2.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-wzr-hp-g300nh2.c index 6c850cee5..4087288dc 100644 --- a/target/linux/ar71xx/files/arch/mips/ath79/mach-wzr-hp-g300nh2.c +++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-wzr-hp-g300nh2.c @@ -158,7 +158,8 @@ static void __init wzrhpg300nh2_setup(void) ath79_register_eth(0); /* gpio13 is usb power. Turn it on. */ - ath79_set_usb_power_gpio(13, GPIOF_OUT_INIT_HIGH, "USB power"); + gpio_request_one(13, GPIOF_OUT_INIT_HIGH | GPIOF_EXPORT_DIR_FIXED, + "USB power"); ath79_register_usb(); ath79_register_leds_gpio(-1, ARRAY_SIZE(wzrhpg300nh2_leds_gpio), diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-wzr-hp-g450h.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-wzr-hp-g450h.c index b5292db54..2c28a55f5 100644 --- a/target/linux/ar71xx/files/arch/mips/ath79/mach-wzr-hp-g450h.c +++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-wzr-hp-g450h.c @@ -156,7 +156,8 @@ static void __init wzrhpg450h_init(void) ath79_register_eth(0); - ath79_set_usb_power_gpio(16, GPIOF_OUT_INIT_HIGH, "USB power"); + gpio_request_one(16, GPIOF_OUT_INIT_HIGH | GPIOF_EXPORT_DIR_FIXED, + "USB power"); ath79_register_usb(); ap91_pci_init(ee, NULL); diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-zcn-1523h.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-zcn-1523h.c index 3a6fe21ed..bc79ab995 100644 --- a/target/linux/ar71xx/files/arch/mips/ath79/mach-zcn-1523h.c +++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-zcn-1523h.c @@ -27,7 +27,7 @@ #define ZCN_1523H_2_GPIO_LED_MEDIUM 14 #define ZCN_1523H_2_GPIO_LED_STRONG 15 -#define ZCN_1523H_5_GPIO_LED_UNKNOWN 1 +#define ZCN_1523H_5_GPIO_LAN2_POWER 1 #define ZCN_1523H_5_GPIO_LED_LAN2 13 #define ZCN_1523H_5_GPIO_LED_WEAK 14 #define ZCN_1523H_5_GPIO_LED_MEDIUM 15 @@ -92,9 +92,6 @@ static struct gpio_led zcn_1523h_5_leds_gpio[] __initdata = { .name = "zcn-1523h:green:lan2", .gpio = ZCN_1523H_5_GPIO_LED_LAN2, .active_low = 1, - }, { - .name = "zcn-1523h:amber:unknown", - .gpio = ZCN_1523H_5_GPIO_LED_UNKNOWN, } }; diff --git a/target/linux/ar71xx/files/arch/mips/ath79/routerboot.c b/target/linux/ar71xx/files/arch/mips/ath79/routerboot.c index 3c6f9aaeb..1cb1f9d4e 100644 --- a/target/linux/ar71xx/files/arch/mips/ath79/routerboot.c +++ b/target/linux/ar71xx/files/arch/mips/ath79/routerboot.c @@ -30,6 +30,26 @@ static u16 get_u16(void *buf) } __init int +routerboot_find_magic(u8 *buf, unsigned int buflen, u32 *offset, bool hard) +{ + u32 magic_ref = hard ? RB_MAGIC_HARD : RB_MAGIC_SOFT; + u32 magic; + u32 cur = *offset; + + while (cur < buflen) { + magic = get_u32(buf + cur); + if (magic == magic_ref) { + *offset = cur; + return 0; + } + + cur += 0x1000; + } + + return -ENOENT; +} + +__init int routerboot_find_tag(u8 *buf, unsigned int buflen, u16 tag_id, u8 **tag_data, u16 *tag_len) { diff --git a/target/linux/ar71xx/files/arch/mips/ath79/routerboot.h b/target/linux/ar71xx/files/arch/mips/ath79/routerboot.h index 9a4dde59e..2489e0aee 100644 --- a/target/linux/ar71xx/files/arch/mips/ath79/routerboot.h +++ b/target/linux/ar71xx/files/arch/mips/ath79/routerboot.h @@ -14,6 +14,7 @@ #ifdef CONFIG_ATH79_ROUTERBOOT int routerboot_find_tag(u8 *buf, unsigned int buflen, u16 tag_id, u8 **tag_data, u16 *tag_len); +int routerboot_find_magic(u8 *buf, unsigned int buflen, u32 *offset, bool hard); #else static inline int routerboot_find_tag(u8 *buf, unsigned int buflen, u16 tag_id, @@ -21,6 +22,12 @@ routerboot_find_tag(u8 *buf, unsigned int buflen, u16 tag_id, { return -ENOENT; } + +static inline int +routerboot_find_magic(u8 *buf, unsigned int buflen, u32 *offset, bool hard) +{ + return -ENOENT; +} #endif #endif /* _ATH79_ROUTERBOOT_H_ */ diff --git a/target/linux/ar71xx/files/drivers/gpio/gpio-nxp-74hc153.c b/target/linux/ar71xx/files/drivers/gpio/gpio-nxp-74hc153.c index a5fec5ca7..5bdeb3d55 100644 --- a/target/linux/ar71xx/files/drivers/gpio/gpio-nxp-74hc153.c +++ b/target/linux/ar71xx/files/drivers/gpio/gpio-nxp-74hc153.c @@ -74,7 +74,7 @@ static void nxp_74hc153_set_value(struct gpio_chip *gc, /* not supported */ } -static int __devinit nxp_74hc153_probe(struct platform_device *pdev) +static int nxp_74hc153_probe(struct platform_device *pdev) { struct nxp_74hc153_platform_data *pdata; struct nxp_74hc153_chip *nxp; @@ -222,7 +222,7 @@ static int nxp_74hc153_remove(struct platform_device *pdev) static struct platform_driver nxp_74hc153_driver = { .probe = nxp_74hc153_probe, - .remove = __devexit_p(nxp_74hc153_remove), + .remove = nxp_74hc153_remove, .driver = { .name = NXP_74HC153_DRIVER_NAME, .owner = THIS_MODULE, diff --git a/target/linux/ar71xx/files/drivers/leds/leds-rb750.c b/target/linux/ar71xx/files/drivers/leds/leds-rb750.c index 483e4fc96..79e98b488 100644 --- a/target/linux/ar71xx/files/drivers/leds/leds-rb750.c +++ b/target/linux/ar71xx/files/drivers/leds/leds-rb750.c @@ -52,7 +52,7 @@ static void rb750_led_brightness_set(struct led_classdev *led_cdev, rbled->latch_change(rbled->mask, 0); } -static int __devinit rb750_led_probe(struct platform_device *pdev) +static int rb750_led_probe(struct platform_device *pdev) { struct rb750_led_platform_data *pdata; struct rb750_led_drvdata *drvdata; @@ -101,7 +101,7 @@ err: return ret; } -static int __devexit rb750_led_remove(struct platform_device *pdev) +static int rb750_led_remove(struct platform_device *pdev) { struct rb750_led_drvdata *drvdata; int i; @@ -116,7 +116,7 @@ static int __devexit rb750_led_remove(struct platform_device *pdev) static struct platform_driver rb750_led_driver = { .probe = rb750_led_probe, - .remove = __devexit_p(rb750_led_remove), + .remove = rb750_led_remove, .driver = { .name = DRV_NAME, .owner = THIS_MODULE, diff --git a/target/linux/ar71xx/files/drivers/leds/leds-wndr3700-usb.c b/target/linux/ar71xx/files/drivers/leds/leds-wndr3700-usb.c index 42f5b70bd..e6565dcdc 100644 --- a/target/linux/ar71xx/files/drivers/leds/leds-wndr3700-usb.c +++ b/target/linux/ar71xx/files/drivers/leds/leds-wndr3700-usb.c @@ -37,12 +37,12 @@ static struct led_classdev wndr3700_usb_led = { .brightness_get = wndr3700_usb_led_get, }; -static int __devinit wndr3700_usb_led_probe(struct platform_device *pdev) +static int wndr3700_usb_led_probe(struct platform_device *pdev) { return led_classdev_register(&pdev->dev, &wndr3700_usb_led); } -static int __devexit wndr3700_usb_led_remove(struct platform_device *pdev) +static int wndr3700_usb_led_remove(struct platform_device *pdev) { led_classdev_unregister(&wndr3700_usb_led); return 0; @@ -50,7 +50,7 @@ static int __devexit wndr3700_usb_led_remove(struct platform_device *pdev) static struct platform_driver wndr3700_usb_led_driver = { .probe = wndr3700_usb_led_probe, - .remove = __devexit_p(wndr3700_usb_led_remove), + .remove = wndr3700_usb_led_remove, .driver = { .name = DRIVER_NAME, .owner = THIS_MODULE, diff --git a/target/linux/ar71xx/files/drivers/mtd/nand/ar934x_nfc.c b/target/linux/ar71xx/files/drivers/mtd/nand/ar934x_nfc.c new file mode 100644 index 000000000..e932491b9 --- /dev/null +++ b/target/linux/ar71xx/files/drivers/mtd/nand/ar934x_nfc.c @@ -0,0 +1,1162 @@ +/* + * Driver for the built-in NAND controller of the Atheros AR934x SoCs + * + * Copyright (C) 2011-2012 Gabor Juhos <juhosg@openwrt.org> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + */ + +#include <linux/init.h> +#include <linux/interrupt.h> +#include <linux/module.h> +#include <linux/dma-mapping.h> +#include <linux/mtd/mtd.h> +#include <linux/mtd/nand.h> +#include <linux/mtd/partitions.h> +#include <linux/platform_device.h> +#include <linux/delay.h> +#include <linux/slab.h> + +#include <linux/platform/ar934x_nfc.h> + +#define AR934X_NFC_REG_CMD 0x00 +#define AR934X_NFC_REG_CTRL 0x04 +#define AR934X_NFC_REG_STATUS 0x08 +#define AR934X_NFC_REG_INT_MASK 0x0c +#define AR934X_NFC_REG_INT_STATUS 0x10 +#define AR934X_NFC_REG_ECC_CTRL 0x14 +#define AR934X_NFC_REG_ECC_OFFSET 0x18 +#define AR934X_NFC_REG_ADDR0_0 0x1c +#define AR934X_NFC_REG_ADDR0_1 0x24 +#define AR934X_NFC_REG_ADDR1_0 0x20 +#define AR934X_NFC_REG_ADDR1_1 0x28 +#define AR934X_NFC_REG_SPARE_SIZE 0x30 +#define AR934X_NFC_REG_PROTECT 0x38 +#define AR934X_NFC_REG_LOOKUP_EN 0x40 +#define AR934X_NFC_REG_LOOKUP(_x) (0x44 + (_i) * 4) +#define AR934X_NFC_REG_DMA_ADDR 0x64 +#define AR934X_NFC_REG_DMA_COUNT 0x68 +#define AR934X_NFC_REG_DMA_CTRL 0x6c +#define AR934X_NFC_REG_MEM_CTRL 0x80 +#define AR934X_NFC_REG_DATA_SIZE 0x84 +#define AR934X_NFC_REG_READ_STATUS 0x88 +#define AR934X_NFC_REG_TIME_SEQ 0x8c +#define AR934X_NFC_REG_TIMINGS_ASYN 0x90 +#define AR934X_NFC_REG_TIMINGS_SYN 0x94 +#define AR934X_NFC_REG_FIFO_DATA 0x98 +#define AR934X_NFC_REG_TIME_MODE 0x9c +#define AR934X_NFC_REG_DMA_ADDR_OFFS 0xa0 +#define AR934X_NFC_REG_FIFO_INIT 0xb0 +#define AR934X_NFC_REG_GEN_SEQ_CTRL 0xb4 + +#define AR934X_NFC_CMD_CMD_SEQ_S 0 +#define AR934X_NFC_CMD_CMD_SEQ_M 0x3f +#define AR934X_NFC_CMD_SEQ_1C 0x00 +#define AR934X_NFC_CMD_SEQ_ERASE 0x0e +#define AR934X_NFC_CMD_SEQ_12 0x0c +#define AR934X_NFC_CMD_SEQ_1C1AXR 0x21 +#define AR934X_NFC_CMD_SEQ_S 0x24 +#define AR934X_NFC_CMD_SEQ_1C3AXR 0x27 +#define AR934X_NFC_CMD_SEQ_1C5A1CXR 0x2a +#define AR934X_NFC_CMD_SEQ_18 0x32 +#define AR934X_NFC_CMD_INPUT_SEL_SIU 0 +#define AR934X_NFC_CMD_INPUT_SEL_DMA BIT(6) +#define AR934X_NFC_CMD_ADDR_SEL_0 0 +#define AR934X_NFC_CMD_ADDR_SEL_1 BIT(7) +#define AR934X_NFC_CMD_CMD0_S 8 +#define AR934X_NFC_CMD_CMD0_M 0xff +#define AR934X_NFC_CMD_CMD1_S 16 +#define AR934X_NFC_CMD_CMD1_M 0xff +#define AR934X_NFC_CMD_CMD2_S 24 +#define AR934X_NFC_CMD_CMD2_M 0xff + +#define AR934X_NFC_CTRL_ADDR_CYCLE0_M 0x7 +#define AR934X_NFC_CTRL_ADDR_CYCLE0_S 0 +#define AR934X_NFC_CTRL_SPARE_EN BIT(3) +#define AR934X_NFC_CTRL_INT_EN BIT(4) +#define AR934X_NFC_CTRL_ECC_EN BIT(5) +#define AR934X_NFC_CTRL_BLOCK_SIZE_S 6 +#define AR934X_NFC_CTRL_BLOCK_SIZE_M 0x3 +#define AR934X_NFC_CTRL_BLOCK_SIZE_32 0 +#define AR934X_NFC_CTRL_BLOCK_SIZE_64 1 +#define AR934X_NFC_CTRL_BLOCK_SIZE_128 2 +#define AR934X_NFC_CTRL_BLOCK_SIZE_256 3 +#define AR934X_NFC_CTRL_PAGE_SIZE_S 8 +#define AR934X_NFC_CTRL_PAGE_SIZE_M 0x7 +#define AR934X_NFC_CTRL_PAGE_SIZE_256 0 +#define AR934X_NFC_CTRL_PAGE_SIZE_512 1 +#define AR934X_NFC_CTRL_PAGE_SIZE_1024 2 +#define AR934X_NFC_CTRL_PAGE_SIZE_2048 3 +#define AR934X_NFC_CTRL_PAGE_SIZE_4096 4 +#define AR934X_NFC_CTRL_PAGE_SIZE_8192 5 +#define AR934X_NFC_CTRL_PAGE_SIZE_16384 6 +#define AR934X_NFC_CTRL_CUSTOM_SIZE_EN BIT(11) +#define AR934X_NFC_CTRL_IO_WIDTH_8BITS 0 +#define AR934X_NFC_CTRL_IO_WIDTH_16BITS BIT(12) +#define AR934X_NFC_CTRL_LOOKUP_EN BIT(13) +#define AR934X_NFC_CTRL_PROT_EN BIT(14) +#define AR934X_NFC_CTRL_WORK_MODE_ASYNC 0 +#define AR934X_NFC_CTRL_WORK_MODE_SYNC BIT(15) +#define AR934X_NFC_CTRL_ADDR0_AUTO_INC BIT(16) +#define AR934X_NFC_CTRL_ADDR1_AUTO_INC BIT(17) +#define AR934X_NFC_CTRL_ADDR_CYCLE1_M 0x7 +#define AR934X_NFC_CTRL_ADDR_CYCLE1_S 18 +#define AR934X_NFC_CTRL_SMALL_PAGE BIT(21) + +#define AR934X_NFC_DMA_CTRL_DMA_START BIT(7) +#define AR934X_NFC_DMA_CTRL_DMA_DIR_WRITE 0 +#define AR934X_NFC_DMA_CTRL_DMA_DIR_READ BIT(6) +#define AR934X_NFC_DMA_CTRL_DMA_MODE_SG BIT(5) +#define AR934X_NFC_DMA_CTRL_DMA_BURST_S 2 +#define AR934X_NFC_DMA_CTRL_DMA_BURST_0 0 +#define AR934X_NFC_DMA_CTRL_DMA_BURST_1 1 +#define AR934X_NFC_DMA_CTRL_DMA_BURST_2 2 +#define AR934X_NFC_DMA_CTRL_DMA_BURST_3 3 +#define AR934X_NFC_DMA_CTRL_DMA_BURST_4 4 +#define AR934X_NFC_DMA_CTRL_DMA_BURST_5 5 +#define AR934X_NFC_DMA_CTRL_ERR_FLAG BIT(1) +#define AR934X_NFC_DMA_CTRL_DMA_READY BIT(0) + +#define AR934X_NFC_INT_DEV_RDY(_x) BIT(4 + (_x)) +#define AR934X_NFC_INT_CMD_END BIT(1) + +/* default timing values */ +#define AR934X_NFC_TIME_SEQ_DEFAULT 0x7fff +#define AR934X_NFC_TIMINGS_ASYN_DEFAULT 0x22 +#define AR934X_NFC_TIMINGS_SYN_DEFAULT 0xf + +#define AR934X_NFC_ID_BUF_SIZE 8 +#define AR934X_NFC_DEV_READY_TIMEOUT 25 /* msecs */ +#define AR934X_NFC_DMA_READY_TIMEOUT 25 /* msecs */ +#define AR934X_NFC_DONE_TIMEOUT 1000 +#define AR934X_NFC_DMA_RETRIES 20 + +#define AR934X_NFC_USE_IRQ true +#define AR934X_NFC_IRQ_MASK AR934X_NFC_INT_DEV_RDY(0) + +#define AR934X_NFC_GENSEQ_SMALL_PAGE_READ 0x30043 + +#undef AR934X_NFC_DEBUG_DATA +#undef AR934X_NFC_DEBUG + +struct ar934x_nfc; + +static inline __attribute__ ((format (printf, 2, 3))) +void _nfc_dbg(struct ar934x_nfc *nfc, const char *fmt, ...) +{ +} + +#ifdef AR934X_NFC_DEBUG +#define nfc_dbg(_nfc, fmt, ...) \ + dev_info((_nfc)->parent, fmt, ##__VA_ARGS__) +#else +#define nfc_dbg(_nfc, fmt, ...) \ + _nfc_dbg((_nfc), fmt, ##__VA_ARGS__) +#endif /* AR934X_NFC_DEBUG */ + +#ifdef AR934X_NFC_DEBUG_DATA +static void +nfc_debug_data(const char *label, void *data, int len) +{ + print_hex_dump(KERN_WARNING, label, DUMP_PREFIX_OFFSET, 16, 1, + data, len, 0); +} +#else +static inline void +nfc_debug_data(const char *label, void *data, int len) {} +#endif /* AR934X_NFC_DEBUG_DATA */ + +struct ar934x_nfc { + struct mtd_info mtd; + struct nand_chip nand_chip; + struct device *parent; + void __iomem *base; + void (*select_chip)(int chip_no); + bool swap_dma; + int irq; + wait_queue_head_t irq_waitq; + + bool spurious_irq_expected; + u32 irq_status; + + u32 ctrl_reg; + bool small_page; + unsigned int addr_count0; + unsigned int addr_count1; + + u8 *buf; + dma_addr_t buf_dma; + unsigned int buf_size; + int buf_index; + + bool read_id; + + int erase1_page_addr; + + int rndout_page_addr; + int rndout_read_cmd; + + int seqin_page_addr; + int seqin_column; + int seqin_read_cmd; +}; + +static void ar934x_nfc_restart(struct ar934x_nfc *nfc); + +static inline void +ar934x_nfc_wr(struct ar934x_nfc *nfc, unsigned reg, u32 val) +{ + __raw_writel(val, nfc->base + reg); +} + +static inline u32 +ar934x_nfc_rr(struct ar934x_nfc *nfc, unsigned reg) +{ + return __raw_readl(nfc->base + reg); +} + +static inline struct ar934x_nfc_platform_data * +ar934x_nfc_get_platform_data(struct ar934x_nfc *nfc) +{ + return nfc->parent->platform_data; +} + +static inline struct +ar934x_nfc *mtd_to_ar934x_nfc(struct mtd_info *mtd) +{ + return container_of(mtd, struct ar934x_nfc, mtd); +} + +static inline bool ar934x_nfc_use_irq(struct ar934x_nfc *nfc) +{ + return AR934X_NFC_USE_IRQ; +} + +static inline void ar934x_nfc_write_cmd_reg(struct ar934x_nfc *nfc, u32 cmd_reg) +{ + wmb(); + + ar934x_nfc_wr(nfc, AR934X_NFC_REG_CMD, cmd_reg); + /* flush write */ + ar934x_nfc_rr(nfc, AR934X_NFC_REG_CMD); +} + +static bool +__ar934x_nfc_dev_ready(struct ar934x_nfc *nfc) +{ + u32 status; + + status = ar934x_nfc_rr(nfc, AR934X_NFC_REG_STATUS); + return (status & 0xff) == 0xff; +} + +static inline bool +__ar934x_nfc_is_dma_ready(struct ar934x_nfc *nfc) +{ + u32 status; + + status = ar934x_nfc_rr(nfc, AR934X_NFC_REG_DMA_CTRL); + return (status & AR934X_NFC_DMA_CTRL_DMA_READY) != 0; +} + +static int +ar934x_nfc_wait_dev_ready(struct ar934x_nfc *nfc) +{ + unsigned long timeout; + + timeout = jiffies + msecs_to_jiffies(AR934X_NFC_DEV_READY_TIMEOUT); + do { + if (__ar934x_nfc_dev_ready(nfc)) + return 0; + } while time_before(jiffies, timeout); + + nfc_dbg(nfc, "timeout waiting for device ready, status:%08x int:%08x\n", + ar934x_nfc_rr(nfc, AR934X_NFC_REG_STATUS), + ar934x_nfc_rr(nfc, AR934X_NFC_REG_INT_STATUS)); + return -ETIMEDOUT; +} + +static int +ar934x_nfc_wait_dma_ready(struct ar934x_nfc *nfc) +{ + unsigned long timeout; + + timeout = jiffies + msecs_to_jiffies(AR934X_NFC_DMA_READY_TIMEOUT); + do { + if (__ar934x_nfc_is_dma_ready(nfc)) + return 0; + } while time_before(jiffies, timeout); + + nfc_dbg(nfc, "timeout waiting for DMA ready, dma_ctrl:%08x\n", + ar934x_nfc_rr(nfc, AR934X_NFC_REG_DMA_CTRL)); + return -ETIMEDOUT; +} + +static int +ar934x_nfc_wait_irq(struct ar934x_nfc *nfc) +{ + long timeout; + int ret; + + timeout = wait_event_timeout(nfc->irq_waitq, + (nfc->irq_status & AR934X_NFC_IRQ_MASK) != 0, + msecs_to_jiffies(AR934X_NFC_DEV_READY_TIMEOUT)); + + ret = 0; + if (!timeout) { + ar934x_nfc_wr(nfc, AR934X_NFC_REG_INT_MASK, 0); + ar934x_nfc_wr(nfc, AR934X_NFC_REG_INT_STATUS, 0); + /* flush write */ + ar934x_nfc_rr(nfc, AR934X_NFC_REG_INT_STATUS); + + nfc_dbg(nfc, + "timeout waiting for interrupt, status:%08x\n", + nfc->irq_status); + ret = -ETIMEDOUT; + } + + nfc->irq_status = 0; + return ret; +} + +static int +ar934x_nfc_wait_done(struct ar934x_nfc *nfc) +{ + int ret; + + if (ar934x_nfc_use_irq(nfc)) + ret = ar934x_nfc_wait_irq(nfc); + else + ret = ar934x_nfc_wait_dev_ready(nfc); + + if (ret) + return ret; + + return ar934x_nfc_wait_dma_ready(nfc); +} + +static int +ar934x_nfc_alloc_buf(struct ar934x_nfc *nfc, unsigned size) +{ + nfc->buf = dma_alloc_coherent(nfc->parent, size, + &nfc->buf_dma, GFP_KERNEL); + if (nfc->buf == NULL) { + dev_err(nfc->parent, "no memory for DMA buffer\n"); + return -ENOMEM; + } + + nfc->buf_size = size; + nfc_dbg(nfc, "buf:%p size:%u\n", nfc->buf, nfc->buf_size); + + return 0; +} + +static void +ar934x_nfc_free_buf(struct ar934x_nfc *nfc) +{ + dma_free_coherent(nfc->parent, nfc->buf_size, nfc->buf, nfc->buf_dma); +} + +static void +ar934x_nfc_get_addr(struct ar934x_nfc *nfc, int column, int page_addr, + u32 *addr0, u32 *addr1) +{ + u32 a0, a1; + + a0 = 0; + a1 = 0; + + if (column == -1) { + /* ERASE1 */ + a0 = (page_addr & 0xffff) << 16; + a1 = (page_addr >> 16) & 0xf; + } else if (page_addr != -1) { + /* SEQIN, READ0, etc.. */ + + /* TODO: handle 16bit bus width */ + if (nfc->small_page) { + a0 = column & 0xff; + a0 |= (page_addr & 0xff) << 8; + a0 |= ((page_addr >> 8) & 0xff) << 16; + a0 |= ((page_addr >> 16) & 0xff) << 24; + } else { + a0 = column & 0x0FFF; + a0 |= (page_addr & 0xffff) << 16; + + if (nfc->addr_count0 > 4) + a1 = (page_addr >> 16) & 0xf; + } + } + + *addr0 = a0; + *addr1 = a1; +} + +static void +ar934x_nfc_send_cmd(struct ar934x_nfc *nfc, unsigned command) +{ + u32 cmd_reg; + + cmd_reg = AR934X_NFC_CMD_INPUT_SEL_SIU | AR934X_NFC_CMD_ADDR_SEL_0 | + AR934X_NFC_CMD_SEQ_1C; + cmd_reg |= (command & AR934X_NFC_CMD_CMD0_M) << AR934X_NFC_CMD_CMD0_S; + + ar934x_nfc_wr(nfc, AR934X_NFC_REG_INT_STATUS, 0); + ar934x_nfc_wr(nfc, AR934X_NFC_REG_CTRL, nfc->ctrl_reg); + + ar934x_nfc_write_cmd_reg(nfc, cmd_reg); + ar934x_nfc_wait_dev_ready(nfc); +} + +static void +ar934x_nfc_do_rw_command(struct ar934x_nfc *nfc, int column, int page_addr, + int len, u32 cmd_reg, u32 ctrl_reg, bool write) +{ + u32 addr0, addr1; + u32 dma_ctrl; + int dir; + int err; + int retries = 0; + + WARN_ON(len & 3); + + if (WARN_ON(len > nfc->buf_size)) + dev_err(nfc->parent, "len=%d > buf_size=%d", len, nfc->buf_size); + + if (write) { + dma_ctrl = AR934X_NFC_DMA_CTRL_DMA_DIR_WRITE; + dir = DMA_TO_DEVICE; + } else { + dma_ctrl = AR934X_NFC_DMA_CTRL_DMA_DIR_READ; + dir = DMA_FROM_DEVICE; + } + + ar934x_nfc_get_addr(nfc, column, page_addr, &addr0, &addr1); + + dma_ctrl |= AR934X_NFC_DMA_CTRL_DMA_START | + (AR934X_NFC_DMA_CTRL_DMA_BURST_3 << + AR934X_NFC_DMA_CTRL_DMA_BURST_S); + + cmd_reg |= AR934X_NFC_CMD_INPUT_SEL_DMA | AR934X_NFC_CMD_ADDR_SEL_0; + ctrl_reg |= AR934X_NFC_CTRL_INT_EN; + + nfc_dbg(nfc, "%s a0:%08x a1:%08x len:%x cmd:%08x dma:%08x ctrl:%08x\n", + (write) ? "write" : "read", + addr0, addr1, len, cmd_reg, dma_ctrl, ctrl_reg); + +retry: + ar934x_nfc_wr(nfc, AR934X_NFC_REG_INT_STATUS, 0); + ar934x_nfc_wr(nfc, AR934X_NFC_REG_ADDR0_0, addr0); + ar934x_nfc_wr(nfc, AR934X_NFC_REG_ADDR0_1, addr1); + ar934x_nfc_wr(nfc, AR934X_NFC_REG_DMA_ADDR, nfc->buf_dma); + ar934x_nfc_wr(nfc, AR934X_NFC_REG_DMA_COUNT, len); + ar934x_nfc_wr(nfc, AR934X_NFC_REG_DATA_SIZE, len); + ar934x_nfc_wr(nfc, AR934X_NFC_REG_CTRL, ctrl_reg); + ar934x_nfc_wr(nfc, AR934X_NFC_REG_DMA_CTRL, dma_ctrl); + + if (ar934x_nfc_use_irq(nfc)) { + ar934x_nfc_wr(nfc, AR934X_NFC_REG_INT_MASK, AR934X_NFC_IRQ_MASK); + /* flush write */ + ar934x_nfc_rr(nfc, AR934X_NFC_REG_INT_MASK); + } + + ar934x_nfc_write_cmd_reg(nfc, cmd_reg); + err = ar934x_nfc_wait_done(nfc); + if (err) { + dev_dbg(nfc->parent, "%s operation stuck at page %d\n", + (write) ? "write" : "read", page_addr); + + ar934x_nfc_restart(nfc); + if (retries++ < AR934X_NFC_DMA_RETRIES) + goto retry; + + dev_err(nfc->parent, "%s operation failed on page %d\n", + (write) ? "write" : "read", page_addr); + } +} + +static void +ar934x_nfc_send_readid(struct ar934x_nfc *nfc, unsigned command) +{ + u32 cmd_reg; + + nfc_dbg(nfc, "readid, cmd:%02x\n", command); + + cmd_reg = AR934X_NFC_CMD_SEQ_1C1AXR; + cmd_reg |= (command & AR934X_NFC_CMD_CMD0_M) << AR934X_NFC_CMD_CMD0_S; + + ar934x_nfc_do_rw_command(nfc, -1, -1, AR934X_NFC_ID_BUF_SIZE, cmd_reg, + nfc->ctrl_reg, false); + + nfc_debug_data("[id] ", nfc->buf, AR934X_NFC_ID_BUF_SIZE); +} + +static void +ar934x_nfc_send_read(struct ar934x_nfc *nfc, unsigned command, int column, + int page_addr, int len) +{ + u32 cmd_reg; + + nfc_dbg(nfc, "read, column=%d page=%d len=%d\n", + column, page_addr, len); + + cmd_reg = (command & AR934X_NFC_CMD_CMD0_M) << AR934X_NFC_CMD_CMD0_S; + + if (nfc->small_page) { + cmd_reg |= AR934X_NFC_CMD_SEQ_18; + } else { + cmd_reg |= NAND_CMD_READSTART << AR934X_NFC_CMD_CMD1_S; + cmd_reg |= AR934X_NFC_CMD_SEQ_1C5A1CXR; + } + + ar934x_nfc_do_rw_command(nfc, column, page_addr, len, + cmd_reg, nfc->ctrl_reg, false); + + nfc_debug_data("[data] ", nfc->buf, len); +} + +static void +ar934x_nfc_send_erase(struct ar934x_nfc *nfc, unsigned command, int column, + int page_addr) +{ + u32 addr0, addr1; + u32 ctrl_reg; + u32 cmd_reg; + + ar934x_nfc_get_addr(nfc, column, page_addr, &addr0, &addr1); + + ctrl_reg = nfc->ctrl_reg; + if (nfc->small_page) { + /* override number of address cycles for the erase command */ + ctrl_reg &= ~(AR934X_NFC_CTRL_ADDR_CYCLE0_M << + AR934X_NFC_CTRL_ADDR_CYCLE0_S); + ctrl_reg &= ~(AR934X_NFC_CTRL_ADDR_CYCLE1_M << + AR934X_NFC_CTRL_ADDR_CYCLE1_S); + ctrl_reg &= ~(AR934X_NFC_CTRL_SMALL_PAGE); + ctrl_reg |= (nfc->addr_count0 + 1) << + AR934X_NFC_CTRL_ADDR_CYCLE0_S; + } + + cmd_reg = NAND_CMD_ERASE1 << AR934X_NFC_CMD_CMD0_S; + cmd_reg |= command << AR934X_NFC_CMD_CMD1_S; + cmd_reg |= AR934X_NFC_CMD_SEQ_ERASE; + + nfc_dbg(nfc, "erase page %d, a0:%08x a1:%08x cmd:%08x ctrl:%08x\n", + page_addr, addr0, addr1, cmd_reg, ctrl_reg); + + ar934x_nfc_wr(nfc, AR934X_NFC_REG_INT_STATUS, 0); + ar934x_nfc_wr(nfc, AR934X_NFC_REG_CTRL, ctrl_reg); + ar934x_nfc_wr(nfc, AR934X_NFC_REG_ADDR0_0, addr0); + ar934x_nfc_wr(nfc, AR934X_NFC_REG_ADDR0_1, addr1); + + ar934x_nfc_write_cmd_reg(nfc, cmd_reg); + ar934x_nfc_wait_dev_ready(nfc); +} + +static void +ar934x_nfc_send_write(struct ar934x_nfc *nfc, unsigned command, int column, + int page_addr, int len) +{ + u32 cmd_reg; + + nfc_dbg(nfc, "write, column=%d page=%d len=%d\n", + column, page_addr, len); + + nfc_debug_data("[data] ", nfc->buf, len); + + cmd_reg = NAND_CMD_SEQIN << AR934X_NFC_CMD_CMD0_S; + cmd_reg |= command << AR934X_NFC_CMD_CMD1_S; + cmd_reg |= AR934X_NFC_CMD_SEQ_12; + + ar934x_nfc_do_rw_command(nfc, column, page_addr, len, + cmd_reg, nfc->ctrl_reg, true); +} + +static void +ar934x_nfc_read_status(struct ar934x_nfc *nfc) +{ + u32 cmd_reg; + u32 status; + + cmd_reg = NAND_CMD_STATUS << AR934X_NFC_CMD_CMD0_S; + cmd_reg |= AR934X_NFC_CMD_SEQ_S; + + ar934x_nfc_wr(nfc, AR934X_NFC_REG_INT_STATUS, 0); + ar934x_nfc_wr(nfc, AR934X_NFC_REG_CTRL, nfc->ctrl_reg); + + ar934x_nfc_write_cmd_reg(nfc, cmd_reg); + ar934x_nfc_wait_dev_ready(nfc); + + status = ar934x_nfc_rr(nfc, AR934X_NFC_REG_READ_STATUS); + + nfc_dbg(nfc, "read status, cmd:%08x status:%02x\n", + cmd_reg, (status & 0xff)); + + if (nfc->swap_dma) + nfc->buf[0 ^ 3] = status; + else + nfc->buf[0] = status; +} + +static void +ar934x_nfc_cmdfunc(struct mtd_info *mtd, unsigned int command, int column, + int page_addr) +{ + struct ar934x_nfc *nfc = mtd_to_ar934x_nfc(mtd); + + nfc->read_id = false; + if (command != NAND_CMD_PAGEPROG) + nfc->buf_index = 0; + + switch (command) { + case NAND_CMD_RESET: + ar934x_nfc_send_cmd(nfc, command); + break; + + case NAND_CMD_READID: + nfc->read_id = true; + ar934x_nfc_send_readid(nfc, command); + break; + + case NAND_CMD_READ0: + case NAND_CMD_READ1: + if (nfc->small_page) { + ar934x_nfc_send_read(nfc, command, column, page_addr, + mtd->writesize + mtd->oobsize); + } else { + ar934x_nfc_send_read(nfc, command, 0, page_addr, + mtd->writesize + mtd->oobsize); + nfc->buf_index = column; + nfc->rndout_page_addr = page_addr; + nfc->rndout_read_cmd = command; + } + break; + + case NAND_CMD_READOOB: + if (nfc->small_page) + ar934x_nfc_send_read(nfc, NAND_CMD_READOOB, + column, page_addr, + mtd->oobsize); + else + ar934x_nfc_send_read(nfc, NAND_CMD_READ0, + mtd->writesize, page_addr, + mtd->oobsize); + break; + + case NAND_CMD_RNDOUT: + if (WARN_ON(nfc->small_page)) + break; + + /* emulate subpage read */ + ar934x_nfc_send_read(nfc, nfc->rndout_read_cmd, 0, + nfc->rndout_page_addr, + mtd->writesize + mtd->oobsize); + nfc->buf_index = column; + break; + + case NAND_CMD_ERASE1: + nfc->erase1_page_addr = page_addr; + break; + + case NAND_CMD_ERASE2: + ar934x_nfc_send_erase(nfc, command, -1, nfc->erase1_page_addr); + break; + + case NAND_CMD_STATUS: + ar934x_nfc_read_status(nfc); + break; + + case NAND_CMD_SEQIN: + if (nfc->small_page) { + /* output read command */ + if (column >= mtd->writesize) { + column -= mtd->writesize; + nfc->seqin_read_cmd = NAND_CMD_READOOB; + } else if (column < 256) { + nfc->seqin_read_cmd = NAND_CMD_READ0; + } else { + column -= 256; + nfc->seqin_read_cmd = NAND_CMD_READ1; + } + } else { + nfc->seqin_read_cmd = NAND_CMD_READ0; + } + nfc->seqin_column = column; + nfc->seqin_page_addr = page_addr; + break; + + case NAND_CMD_PAGEPROG: + if (nfc->small_page) + ar934x_nfc_send_cmd(nfc, nfc->seqin_read_cmd); + + ar934x_nfc_send_write(nfc, command, nfc->seqin_column, + nfc->seqin_page_addr, + nfc->buf_index); + break; + + default: + dev_err(nfc->parent, + "unsupported command: %x, column:%d page_addr=%d\n", + command, column, page_addr); + break; + } +} + +static int +ar934x_nfc_dev_ready(struct mtd_info *mtd) +{ + struct ar934x_nfc *nfc = mtd_to_ar934x_nfc(mtd); + + return __ar934x_nfc_dev_ready(nfc); +} + +static void +ar934x_nfc_select_chip(struct mtd_info *mtd, int chip_no) +{ + struct ar934x_nfc *nfc = mtd_to_ar934x_nfc(mtd); + + if (nfc->select_chip) + nfc->select_chip(chip_no); +} + +static u8 +ar934x_nfc_read_byte(struct mtd_info *mtd) +{ + struct ar934x_nfc *nfc = mtd_to_ar934x_nfc(mtd); + u8 data; + + WARN_ON(nfc->buf_index >= nfc->buf_size); + + if (nfc->swap_dma || nfc->read_id) + data = nfc->buf[nfc->buf_index ^ 3]; + else + data = nfc->buf[nfc->buf_index]; + + nfc->buf_index++; + + return data; +} + +static void +ar934x_nfc_write_buf(struct mtd_info *mtd, const u8 *buf, int len) +{ + struct ar934x_nfc *nfc = mtd_to_ar934x_nfc(mtd); + int i; + + WARN_ON(nfc->buf_index + len > nfc->buf_size); + + if (nfc->swap_dma) { + for (i = 0; i < len; i++) { + nfc->buf[nfc->buf_index ^ 3] = buf[i]; + nfc->buf_index++; + } + } else { + for (i = 0; i < len; i++) { + nfc->buf[nfc->buf_index] = buf[i]; + nfc->buf_index++; + } + } +} + +static void +ar934x_nfc_read_buf(struct mtd_info *mtd, u8 *buf, int len) +{ + struct ar934x_nfc *nfc = mtd_to_ar934x_nfc(mtd); + int buf_index; + int i; + + WARN_ON(nfc->buf_index + len > nfc->buf_size); + + buf_index = nfc->buf_index; + + if (nfc->swap_dma || nfc->read_id) { + for (i = 0; i < len; i++) { + buf[i] = nfc->buf[buf_index ^ 3]; + buf_index++; + } + } else { + for (i = 0; i < len; i++) { + buf[i] = nfc->buf[buf_index]; + buf_index++; + } + } + + nfc->buf_index = buf_index; +} + +static void +ar934x_nfc_hw_init(struct ar934x_nfc *nfc) +{ + struct ar934x_nfc_platform_data *pdata; + + pdata = ar934x_nfc_get_platform_data(nfc); + if (pdata->hw_reset) { + pdata->hw_reset(true); + pdata->hw_reset(false); + } + + /* + * setup timings + * TODO: make it configurable via platform data + */ + ar934x_nfc_wr(nfc, AR934X_NFC_REG_TIME_SEQ, + AR934X_NFC_TIME_SEQ_DEFAULT); + ar934x_nfc_wr(nfc, AR934X_NFC_REG_TIMINGS_ASYN, + AR934X_NFC_TIMINGS_ASYN_DEFAULT); + ar934x_nfc_wr(nfc, AR934X_NFC_REG_TIMINGS_SYN, + AR934X_NFC_TIMINGS_SYN_DEFAULT); + + /* disable WP on all chips, and select chip 0 */ + ar934x_nfc_wr(nfc, AR934X_NFC_REG_MEM_CTRL, 0xff00); + + ar934x_nfc_wr(nfc, AR934X_NFC_REG_DMA_ADDR_OFFS, 0); + + /* initialize Control register */ + nfc->ctrl_reg = AR934X_NFC_CTRL_CUSTOM_SIZE_EN; + ar934x_nfc_wr(nfc, AR934X_NFC_REG_CTRL, nfc->ctrl_reg); + + if (nfc->small_page) { + /* Setup generic sequence register for small page reads. */ + ar934x_nfc_wr(nfc, AR934X_NFC_REG_GEN_SEQ_CTRL, + AR934X_NFC_GENSEQ_SMALL_PAGE_READ); + } +} + +static void +ar934x_nfc_restart(struct ar934x_nfc *nfc) +{ + u32 ctrl_reg; + + if (nfc->select_chip) + nfc->select_chip(-1); + + ctrl_reg = nfc->ctrl_reg; + ar934x_nfc_hw_init(nfc); + nfc->ctrl_reg = ctrl_reg; + + if (nfc->select_chip) + nfc->select_chip(0); + + ar934x_nfc_send_cmd(nfc, NAND_CMD_RESET); +} + +static irqreturn_t +ar934x_nfc_irq_handler(int irq, void *data) +{ + struct ar934x_nfc *nfc = data; + u32 status; + + status = ar934x_nfc_rr(nfc, AR934X_NFC_REG_INT_STATUS); + + ar934x_nfc_wr(nfc, AR934X_NFC_REG_INT_STATUS, 0); + /* flush write */ + ar934x_nfc_rr(nfc, AR934X_NFC_REG_INT_STATUS); + + status &= ar934x_nfc_rr(nfc, AR934X_NFC_REG_INT_MASK); + if (status) { + nfc_dbg(nfc, "got IRQ, status:%08x\n", status); + + nfc->irq_status = status; + nfc->spurious_irq_expected = true; + wake_up(&nfc->irq_waitq); + } else { + if (nfc->spurious_irq_expected) { + nfc->spurious_irq_expected = false; + } else { + dev_warn(nfc->parent, "spurious interrupt\n"); + } + } + + return IRQ_HANDLED; +} + +static int +ar934x_nfc_init_tail(struct mtd_info *mtd) +{ + struct ar934x_nfc *nfc = mtd_to_ar934x_nfc(mtd); + struct nand_chip *chip = &nfc->nand_chip; + u32 ctrl; + u32 t; + int err; + + switch (mtd->oobsize) { + case 16: + case 64: + case 128: + ar934x_nfc_wr(nfc, AR934X_NFC_REG_SPARE_SIZE, mtd->oobsize); + break; + + default: + dev_err(nfc->parent, "unsupported OOB size: %d bytes\n", + mtd->oobsize); + return -ENXIO; + } + + ctrl = AR934X_NFC_CTRL_CUSTOM_SIZE_EN; + + switch (mtd->erasesize / mtd->writesize) { + case 32: + t = AR934X_NFC_CTRL_BLOCK_SIZE_32; + break; + + case 64: + t = AR934X_NFC_CTRL_BLOCK_SIZE_64; + break; + + case 128: + t = AR934X_NFC_CTRL_BLOCK_SIZE_128; + break; + + case 256: + t = AR934X_NFC_CTRL_BLOCK_SIZE_256; + break; + + default: + dev_err(nfc->parent, "unsupported block size: %u\n", + mtd->erasesize / mtd->writesize); + return -ENXIO; + } + + ctrl |= t << AR934X_NFC_CTRL_BLOCK_SIZE_S; + + switch (mtd->writesize) { + case 256: + nfc->small_page = 1; + t = AR934X_NFC_CTRL_PAGE_SIZE_256; + break; + + case 512: + nfc->small_page = 1; + t = AR934X_NFC_CTRL_PAGE_SIZE_512; + break; + + case 1024: + t = AR934X_NFC_CTRL_PAGE_SIZE_1024; + break; + + case 2048: + t = AR934X_NFC_CTRL_PAGE_SIZE_2048; + break; + + case 4096: + t = AR934X_NFC_CTRL_PAGE_SIZE_4096; + break; + + case 8192: + t = AR934X_NFC_CTRL_PAGE_SIZE_8192; + break; + + case 16384: + t = AR934X_NFC_CTRL_PAGE_SIZE_16384; + break; + + default: + dev_err(nfc->parent, "unsupported write size: %d bytes\n", + mtd->writesize); + return -ENXIO; + } + + ctrl |= t << AR934X_NFC_CTRL_PAGE_SIZE_S; + + if (nfc->small_page) { + ctrl |= AR934X_NFC_CTRL_SMALL_PAGE; + + if (chip->chipsize > (32 << 20)) { + nfc->addr_count0 = 4; + nfc->addr_count1 = 3; + } else if (chip->chipsize > (2 << 16)) { + nfc->addr_count0 = 3; + nfc->addr_count1 = 2; + } else { + nfc->addr_count0 = 2; + nfc->addr_count1 = 1; + } + } else { + if (chip->chipsize > (128 << 20)) { + nfc->addr_count0 = 5; + nfc->addr_count1 = 3; + } else if (chip->chipsize > (8 << 16)) { + nfc->addr_count0 = 4; + nfc->addr_count1 = 2; + } else { + nfc->addr_count0 = 3; + nfc->addr_count1 = 1; + } + } + + ctrl |= nfc->addr_count0 << AR934X_NFC_CTRL_ADDR_CYCLE0_S; + ctrl |= nfc->addr_count1 << AR934X_NFC_CTRL_ADDR_CYCLE1_S; + + nfc->ctrl_reg = ctrl; + ar934x_nfc_wr(nfc, AR934X_NFC_REG_CTRL, nfc->ctrl_reg); + + ar934x_nfc_free_buf(nfc); + err = ar934x_nfc_alloc_buf(nfc, mtd->writesize + mtd->oobsize); + + return err; +} + +static int +ar934x_nfc_probe(struct platform_device *pdev) +{ + static const char *part_probes[] = { "cmdlinepart", NULL, }; + struct ar934x_nfc_platform_data *pdata; + struct ar934x_nfc *nfc; + struct resource *res; + struct mtd_info *mtd; + struct nand_chip *nand; + struct mtd_part_parser_data ppdata; + int ret; + + pdata = pdev->dev.platform_data; + if (pdata == NULL) { + dev_err(&pdev->dev, "no platform data defined\n"); + return -EINVAL; + } + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(&pdev->dev, "failed to get I/O memory\n"); + return -EINVAL; + } + + nfc = kzalloc(sizeof(struct ar934x_nfc), GFP_KERNEL); + if (!nfc) { + dev_err(&pdev->dev, "failed to allocate driver data\n"); + return -ENOMEM; + } + + nfc->base = ioremap(res->start, resource_size(res)); + if (nfc->base == NULL) { + dev_err(&pdev->dev, "failed to remap I/O memory\n"); + ret = -ENXIO; + goto err_free_nand; + } + + nfc->irq = platform_get_irq(pdev, 0); + if (nfc->irq < 0) { + dev_err(&pdev->dev, "no IRQ resource specified\n"); + ret = -EINVAL; + goto err_unmap; + } + + init_waitqueue_head(&nfc->irq_waitq); + ret = request_irq(nfc->irq, ar934x_nfc_irq_handler, IRQF_DISABLED, + dev_name(&pdev->dev), nfc); + if (ret) { + dev_err(&pdev->dev, "requast_irq failed, err:%d\n", ret); + goto err_unmap; + } + + nfc->parent = &pdev->dev; + nfc->select_chip = pdata->select_chip; + nfc->swap_dma = pdata->swap_dma; + + nand = &nfc->nand_chip; + mtd = &nfc->mtd; + + mtd->priv = nand; + mtd->owner = THIS_MODULE; + if (pdata->name) + mtd->name = pdata->name; + else + mtd->name = dev_name(&pdev->dev); + + nand->chip_delay = 25; + nand->ecc.mode = NAND_ECC_SOFT; + + nand->dev_ready = ar934x_nfc_dev_ready; + nand->cmdfunc = ar934x_nfc_cmdfunc; + nand->read_byte = ar934x_nfc_read_byte; + nand->write_buf = ar934x_nfc_write_buf; + nand->read_buf = ar934x_nfc_read_buf; + nand->select_chip = ar934x_nfc_select_chip; + + ret = ar934x_nfc_alloc_buf(nfc, AR934X_NFC_ID_BUF_SIZE); + if (ret) + goto err_free_irq; + + platform_set_drvdata(pdev, nfc); + + ar934x_nfc_hw_init(nfc); + + ret = nand_scan_ident(mtd, 1, NULL); + if (ret) { + dev_err(&pdev->dev, "nand_scan_ident failed, err:%d\n", ret); + goto err_free_buf; + } + + ret = ar934x_nfc_init_tail(mtd); + if (ret) { + dev_err(&pdev->dev, "init tail failed, err:%d\n", ret); + goto err_free_buf; + } + + if (pdata->scan_fixup) { + ret = pdata->scan_fixup(mtd); + if (ret) + goto err_free_buf; + } + + ret = nand_scan_tail(mtd); + if (ret) { + dev_err(&pdev->dev, "scan tail failed, err:%d\n", ret); + goto err_free_buf; + } + + memset(&ppdata, '\0', sizeof(ppdata)); + ret = mtd_device_parse_register(mtd, part_probes, &ppdata, + pdata->parts, pdata->nr_parts); + if (ret) { + dev_err(&pdev->dev, "unable to register mtd, err:%d\n", ret); + goto err_free_buf; + } + + return 0; + +err_free_buf: + ar934x_nfc_free_buf(nfc); +err_free_irq: + free_irq(nfc->irq, nfc); +err_unmap: + iounmap(nfc->base); +err_free_nand: + kfree(nfc); + platform_set_drvdata(pdev, NULL); + return ret; +} + +static int +ar934x_nfc_remove(struct platform_device *pdev) +{ + struct ar934x_nfc *nfc; + + nfc = platform_get_drvdata(pdev); + if (nfc) { + nand_release(&nfc->mtd); + ar934x_nfc_free_buf(nfc); + free_irq(nfc->irq, nfc); + iounmap(nfc->base); + kfree(nfc); + } + + return 0; +} + +static struct platform_driver ar934x_nfc_driver = { + .probe = ar934x_nfc_probe, + .remove = ar934x_nfc_remove, + .driver = { + .name = AR934X_NFC_DRIVER_NAME, + .owner = THIS_MODULE, + }, +}; + +module_platform_driver(ar934x_nfc_driver); + +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Gabor Juhos <juhosg@openwrt.org>"); +MODULE_DESCRIPTION("Atheros AR934x NAND Flash Controller driver"); +MODULE_ALIAS("platform:" AR934X_NFC_DRIVER_NAME); diff --git a/target/linux/ar71xx/files/drivers/mtd/nand/rb4xx_nand.c b/target/linux/ar71xx/files/drivers/mtd/nand/rb4xx_nand.c index 1cb8f8240..5b9841b76 100644 --- a/target/linux/ar71xx/files/drivers/mtd/nand/rb4xx_nand.c +++ b/target/linux/ar71xx/files/drivers/mtd/nand/rb4xx_nand.c @@ -62,7 +62,7 @@ static struct mtd_partition rb4xx_nand_partitions[] = { { .name = "kernel", .offset = (256 * 1024), - .size = (6 * 1024 * 1024) - (256 * 1024), + .size = (4 * 1024 * 1024) - (256 * 1024), }, { .name = "rootfs", @@ -136,7 +136,7 @@ static void rb4xx_nand_read_buf(struct mtd_info *mtd, unsigned char *buf, pr_err("rb4xx_nand: read buf failed, err=%d\n", err); } -static int __devinit rb4xx_nand_probe(struct platform_device *pdev) +static int rb4xx_nand_probe(struct platform_device *pdev) { struct rb4xx_nand_info *info; int ret; @@ -215,13 +215,9 @@ static int __devinit rb4xx_nand_probe(struct platform_device *pdev) info->chip.read_byte = rb4xx_nand_read_byte; info->chip.write_buf = rb4xx_nand_write_buf; info->chip.read_buf = rb4xx_nand_read_buf; -#if 0 - info->chip.verify_buf = rb4xx_nand_verify_buf; -#endif info->chip.chip_delay = 25; info->chip.ecc.mode = NAND_ECC_SOFT; - info->chip.options |= NAND_NO_AUTOINCR; platform_set_drvdata(pdev, info); @@ -265,7 +261,7 @@ err: return ret; } -static int __devexit rb4xx_nand_remove(struct platform_device *pdev) +static int rb4xx_nand_remove(struct platform_device *pdev) { struct rb4xx_nand_info *info = platform_get_drvdata(pdev); @@ -282,7 +278,7 @@ static int __devexit rb4xx_nand_remove(struct platform_device *pdev) static struct platform_driver rb4xx_nand_driver = { .probe = rb4xx_nand_probe, - .remove = __devexit_p(rb4xx_nand_remove), + .remove = rb4xx_nand_remove, .driver = { .name = DRV_NAME, .owner = THIS_MODULE, diff --git a/target/linux/ar71xx/files/drivers/mtd/nand/rb750_nand.c b/target/linux/ar71xx/files/drivers/mtd/nand/rb750_nand.c index 251e18220..a20409b10 100644 --- a/target/linux/ar71xx/files/drivers/mtd/nand/rb750_nand.c +++ b/target/linux/ar71xx/files/drivers/mtd/nand/rb750_nand.c @@ -110,8 +110,7 @@ static void rb750_nand_write(const u8 *buf, unsigned len) __raw_readl(base + AR71XX_GPIO_REG_OE); } -static int rb750_nand_read_verify(u8 *read_buf, unsigned len, - const u8 *verify_buf) +static void rb750_nand_read(u8 *read_buf, unsigned len) { void __iomem *base = ath79_gpio_base; unsigned i; @@ -131,13 +130,8 @@ static int rb750_nand_read_verify(u8 *read_buf, unsigned len, /* deactivate RE line */ __raw_writel(RB750_NAND_NRE, base + AR71XX_GPIO_REG_SET); - if (read_buf) - read_buf[i] = data; - else if (verify_buf && verify_buf[i] != data) - return -EFAULT; + read_buf[i] = data; } - - return 0; } static void rb750_nand_select_chip(struct mtd_info *mtd, int chip) @@ -212,13 +206,13 @@ static void rb750_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, static u8 rb750_nand_read_byte(struct mtd_info *mtd) { u8 data = 0; - rb750_nand_read_verify(&data, 1, NULL); + rb750_nand_read(&data, 1); return data; } static void rb750_nand_read_buf(struct mtd_info *mtd, u8 *buf, int len) { - rb750_nand_read_verify(buf, len, NULL); + rb750_nand_read(buf, len); } static void rb750_nand_write_buf(struct mtd_info *mtd, const u8 *buf, int len) @@ -226,11 +220,6 @@ static void rb750_nand_write_buf(struct mtd_info *mtd, const u8 *buf, int len) rb750_nand_write(buf, len); } -static int rb750_nand_verify_buf(struct mtd_info *mtd, const u8 *buf, int len) -{ - return rb750_nand_read_verify(NULL, len, buf); -} - static void __init rb750_nand_gpio_init(struct rb750_nand_info *info) { void __iomem *base = ath79_gpio_base; @@ -259,7 +248,7 @@ static void __init rb750_nand_gpio_init(struct rb750_nand_info *info) info->pdata->latch_change(~out & RB750_NAND_IO0, out & RB750_NAND_IO0); } -static int __devinit rb750_nand_probe(struct platform_device *pdev) +static int rb750_nand_probe(struct platform_device *pdev) { struct rb750_nand_info *info; struct rb7xx_nand_platform_data *pdata; @@ -285,11 +274,9 @@ static int __devinit rb750_nand_probe(struct platform_device *pdev) info->chip.read_byte = rb750_nand_read_byte; info->chip.write_buf = rb750_nand_write_buf; info->chip.read_buf = rb750_nand_read_buf; - info->chip.verify_buf = rb750_nand_verify_buf; info->chip.chip_delay = 25; info->chip.ecc.mode = NAND_ECC_SOFT; - info->chip.options |= NAND_NO_AUTOINCR; info->pdata = pdata; @@ -328,7 +315,7 @@ err_free_info: return ret; } -static int __devexit rb750_nand_remove(struct platform_device *pdev) +static int rb750_nand_remove(struct platform_device *pdev) { struct rb750_nand_info *info = platform_get_drvdata(pdev); @@ -341,7 +328,7 @@ static int __devexit rb750_nand_remove(struct platform_device *pdev) static struct platform_driver rb750_nand_driver = { .probe = rb750_nand_probe, - .remove = __devexit_p(rb750_nand_remove), + .remove = rb750_nand_remove, .driver = { .name = DRV_NAME, .owner = THIS_MODULE, diff --git a/target/linux/ar71xx/files/drivers/mtd/tplinkpart.c b/target/linux/ar71xx/files/drivers/mtd/tplinkpart.c index 674df6602..cabb96033 100644 --- a/target/linux/ar71xx/files/drivers/mtd/tplinkpart.c +++ b/target/linux/ar71xx/files/drivers/mtd/tplinkpart.c @@ -60,8 +60,8 @@ tplink_read_header(struct mtd_info *mtd, size_t offset) goto err; header_len = sizeof(struct tplink_fw_header); - ret = mtd->read(mtd, offset, header_len, &retlen, - (unsigned char *) header); + ret = mtd_read(mtd, offset, header_len, &retlen, + (unsigned char *) header); if (ret) goto err_free_header; @@ -91,8 +91,8 @@ static int tplink_check_rootfs_magic(struct mtd_info *mtd, size_t offset) size_t retlen; int ret; - ret = mtd->read(mtd, offset, sizeof(magic), &retlen, - (unsigned char *) &magic); + ret = mtd_read(mtd, offset, sizeof(magic), &retlen, + (unsigned char *) &magic); if (ret) return ret; diff --git a/target/linux/ar71xx/files/drivers/mtd/wrt160nl_part.c b/target/linux/ar71xx/files/drivers/mtd/wrt160nl_part.c index 72927f6f2..1ced8acc7 100644 --- a/target/linux/ar71xx/files/drivers/mtd/wrt160nl_part.c +++ b/target/linux/ar71xx/files/drivers/mtd/wrt160nl_part.c @@ -113,8 +113,8 @@ static int wrt160nl_parse_partitions(struct mtd_info *master, goto free_parts; } - ret = master->read(master, uboot_len, sizeof(*header), - &retlen, (void *) header); + ret = mtd_read(master, uboot_len, sizeof(*header), + &retlen, (void *) header); if (ret) goto free_hdr; diff --git a/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_ar7240.c b/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_ar7240.c index 49f077520..9a51f786f 100644 --- a/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_ar7240.c +++ b/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_ar7240.c @@ -209,6 +209,7 @@ #define AR934X_REG_OPER_MODE1_PHY4_MII_EN BIT(28) #define AR934X_REG_FLOOD_MASK 0x2c +#define AR934X_FLOOD_MASK_MC_DP(_p) BIT(16 + (_p)) #define AR934X_FLOOD_MASK_BC_DP(_p) BIT(25 + (_p)) #define AR934X_REG_QM_CTRL 0x3c @@ -580,9 +581,10 @@ static void ar7240sw_setup(struct ar7240sw *as) /* Enable ARP frame acknowledge */ ar7240sw_reg_set(mii, AR934X_REG_QM_CTRL, AR934X_QM_CTRL_ARP_EN); - /* Enable Broadcast frames transmitted to the CPU */ + /* Enable Broadcast/Multicast frames transmitted to the CPU */ ar7240sw_reg_set(mii, AR934X_REG_FLOOD_MASK, - AR934X_FLOOD_MASK_BC_DP(0)); + AR934X_FLOOD_MASK_BC_DP(0) | + AR934X_FLOOD_MASK_MC_DP(0)); /* Enable MIB counters */ ar7240sw_reg_set(mii, AR7240_REG_MIB_FUNCTION0, @@ -1163,7 +1165,7 @@ void ag71xx_ar7240_stop(struct ag71xx *ag) cancel_delayed_work_sync(&ag->link_work); } -int __devinit ag71xx_ar7240_init(struct ag71xx *ag) +int ag71xx_ar7240_init(struct ag71xx *ag) { struct ar7240sw *as; diff --git a/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_main.c b/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_main.c index fb99d2728..50029ffaf 100644 --- a/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_main.c +++ b/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_main.c @@ -891,7 +891,7 @@ static int ag71xx_rx_packets(struct ag71xx *ag, int limit) dev->stats.rx_packets++; dev->stats.rx_bytes += pktlen; - skb = build_skb(ring->buf[i].rx_buf); + skb = build_skb(ring->buf[i].rx_buf, 0); if (!skb) { kfree(ring->buf[i].rx_buf); goto next; @@ -1056,7 +1056,28 @@ static const struct net_device_ops ag71xx_netdev_ops = { #endif }; -static int __devinit ag71xx_probe(struct platform_device *pdev) +static const char *ag71xx_get_phy_if_mode_name(phy_interface_t mode) +{ + switch (mode) { + case PHY_INTERFACE_MODE_MII: + return "MII"; + case PHY_INTERFACE_MODE_GMII: + return "GMII"; + case PHY_INTERFACE_MODE_RMII: + return "RMII"; + case PHY_INTERFACE_MODE_RGMII: + return "RGMII"; + case PHY_INTERFACE_MODE_SGMII: + return "SGMII"; + default: + break; + } + + return "unknown"; +} + + +static int ag71xx_probe(struct platform_device *pdev) { struct net_device *dev; struct resource *res; @@ -1071,7 +1092,7 @@ static int __devinit ag71xx_probe(struct platform_device *pdev) goto err_out; } - if (pdata->mii_bus_dev == NULL) { + if (pdata->mii_bus_dev == NULL && pdata->phy_mask) { dev_err(&pdev->dev, "no MII bus device specified\n"); err = -EINVAL; goto err_out; @@ -1149,8 +1170,9 @@ static int __devinit ag71xx_probe(struct platform_device *pdev) goto err_free_desc; } - pr_info("%s: Atheros AG71xx at 0x%08lx, irq %d\n", - dev->name, dev->base_addr, dev->irq); + pr_info("%s: Atheros AG71xx at 0x%08lx, irq %d, mode:%s\n", + dev->name, dev->base_addr, dev->irq, + ag71xx_get_phy_if_mode_name(pdata->phy_if_mode)); ag71xx_dump_regs(ag); @@ -1188,7 +1210,7 @@ err_out: return err; } -static int __devexit ag71xx_remove(struct platform_device *pdev) +static int ag71xx_remove(struct platform_device *pdev) { struct net_device *dev = platform_get_drvdata(pdev); @@ -1209,7 +1231,7 @@ static int __devexit ag71xx_remove(struct platform_device *pdev) static struct platform_driver ag71xx_driver = { .probe = ag71xx_probe, - .remove = __exit_p(ag71xx_remove), + .remove = ag71xx_remove, .driver = { .name = AG71XX_DRV_NAME, } diff --git a/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_mdio.c b/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_mdio.c index e123505c7..ec8823341 100644 --- a/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_mdio.c +++ b/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_mdio.c @@ -205,7 +205,7 @@ static int ag71xx_mdio_write(struct mii_bus *bus, int addr, int reg, u16 val) return 0; } -static int __devinit ag71xx_mdio_probe(struct platform_device *pdev) +static int ag71xx_mdio_probe(struct platform_device *pdev) { struct ag71xx_mdio_platform_data *pdata; struct ag71xx_mdio *am; @@ -281,7 +281,7 @@ err_out: return err; } -static int __devexit ag71xx_mdio_remove(struct platform_device *pdev) +static int ag71xx_mdio_remove(struct platform_device *pdev) { struct ag71xx_mdio *am = platform_get_drvdata(pdev); @@ -298,7 +298,7 @@ static int __devexit ag71xx_mdio_remove(struct platform_device *pdev) static struct platform_driver ag71xx_mdio_driver = { .probe = ag71xx_mdio_probe, - .remove = __exit_p(ag71xx_mdio_remove), + .remove = ag71xx_mdio_remove, .driver = { .name = "ag71xx-mdio", } diff --git a/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_phy.c b/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_phy.c index ebdbc5b9a..71f0b1d3c 100644 --- a/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_phy.c +++ b/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_phy.c @@ -48,7 +48,7 @@ void ag71xx_phy_start(struct ag71xx *ag) if (ag->phy_dev) { phy_start(ag->phy_dev); - } else if (pdata->switch_data) { + } else if (pdata->mii_bus_dev && pdata->switch_data) { ag71xx_ar7240_start(ag); } else { ag->link = 1; @@ -63,7 +63,7 @@ void ag71xx_phy_stop(struct ag71xx *ag) if (ag->phy_dev) phy_stop(ag->phy_dev); - else if (pdata->switch_data) + else if (pdata->mii_bus_dev && pdata->switch_data) ag71xx_ar7240_stop(ag); spin_lock_irqsave(&ag->lock, flags); @@ -193,7 +193,7 @@ static struct mii_bus *dev_to_mii_bus(struct device *dev) return NULL; } -int __devinit ag71xx_phy_connect(struct ag71xx *ag) +int ag71xx_phy_connect(struct ag71xx *ag) { struct ag71xx_platform_data *pdata = ag71xx_get_pdata(ag); diff --git a/target/linux/ar71xx/files/drivers/spi/spi-rb4xx-cpld.c b/target/linux/ar71xx/files/drivers/spi/spi-rb4xx-cpld.c index 4e8ce3105..a8d52825e 100644 --- a/target/linux/ar71xx/files/drivers/spi/spi-rb4xx-cpld.c +++ b/target/linux/ar71xx/files/drivers/spi/spi-rb4xx-cpld.c @@ -356,7 +356,7 @@ static int rb4xx_cpld_gpio_init(struct rb4xx_cpld *cpld, unsigned int base) return err; } -static int __devinit rb4xx_cpld_probe(struct spi_device *spi) +static int rb4xx_cpld_probe(struct spi_device *spi) { struct rb4xx_cpld *cpld; struct rb4xx_cpld_platform_data *pdata; @@ -401,7 +401,7 @@ err_drvdata: return err; } -static int __devexit rb4xx_cpld_remove(struct spi_device *spi) +static int rb4xx_cpld_remove(struct spi_device *spi) { struct rb4xx_cpld *cpld; @@ -420,7 +420,7 @@ static struct spi_driver rb4xx_cpld_driver = { .owner = THIS_MODULE, }, .probe = rb4xx_cpld_probe, - .remove = __devexit_p(rb4xx_cpld_remove), + .remove = rb4xx_cpld_remove, }; static int __init rb4xx_cpld_init(void) diff --git a/target/linux/ar71xx/files/drivers/spi/spi-vsc7385.c b/target/linux/ar71xx/files/drivers/spi/spi-vsc7385.c index 9340df268..b712e7187 100644 --- a/target/linux/ar71xx/files/drivers/spi/spi-vsc7385.c +++ b/target/linux/ar71xx/files/drivers/spi/spi-vsc7385.c @@ -526,7 +526,7 @@ static int vsc7385_detect(struct vsc7385 *vsc) return 0; } -static int __devinit vsc7385_probe(struct spi_device *spi) +static int vsc7385_probe(struct spi_device *spi) { struct vsc7385 *vsc; struct vsc7385_platform_data *pdata; @@ -581,7 +581,7 @@ err_drvdata: return err; } -static int __devexit vsc7385_remove(struct spi_device *spi) +static int vsc7385_remove(struct spi_device *spi) { struct vsc7385_data *vsc; @@ -599,7 +599,7 @@ static struct spi_driver vsc7385_driver = { .owner = THIS_MODULE, }, .probe = vsc7385_probe, - .remove = __devexit_p(vsc7385_remove), + .remove = vsc7385_remove, }; static int __init vsc7385_init(void) diff --git a/target/linux/ar71xx/files/include/linux/platform/ar934x_nfc.h b/target/linux/ar71xx/files/include/linux/platform/ar934x_nfc.h new file mode 100644 index 000000000..2c3db156b --- /dev/null +++ b/target/linux/ar71xx/files/include/linux/platform/ar934x_nfc.h @@ -0,0 +1,31 @@ +/* + * Platform data definition for the built-in NAND controller of the + * Atheros AR934x SoCs + * + * Copyright (C) 2011-2012 Gabor Juhos <juhosg@openwrt.org> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + */ + +#ifndef _AR934X_NFC_PLATFORM_H +#define _AR934X_NFC_PLATFORM_H + +#define AR934X_NFC_DRIVER_NAME "ar934x-nfc" + +struct mtd_info; +struct mtd_partition; + +struct ar934x_nfc_platform_data { + const char *name; + struct mtd_partition *parts; + int nr_parts; + + bool swap_dma; + void (*hw_reset)(bool active); + void (*select_chip)(int chip_no); + int (*scan_fixup)(struct mtd_info *mtd); +}; + +#endif /* _AR934X_NFC_PLATFORM_H */ |