diff options
author | Gabor Juhos <juhosg@openwrt.org> | 2009-12-20 13:46:23 +0000 |
---|---|---|
committer | Gabor Juhos <juhosg@openwrt.org> | 2009-12-20 13:46:23 +0000 |
commit | bb9123ebbee23af32cf16f2581fe5ac714a1fe8f (patch) | |
tree | 71887ef93327a548d5b93d654985d74fb4295449 /target/linux/ar71xx/files | |
parent | 6d3d1504cf17e95b670e7ef83bcc42021b7fb9b6 (diff) | |
download | mtk-20170518-bb9123ebbee23af32cf16f2581fe5ac714a1fe8f.zip mtk-20170518-bb9123ebbee23af32cf16f2581fe5ac714a1fe8f.tar.gz mtk-20170518-bb9123ebbee23af32cf16f2581fe5ac714a1fe8f.tar.bz2 |
ar71xx: update AR7240 PCI code
SVN-Revision: 18860
Diffstat (limited to 'target/linux/ar71xx/files')
8 files changed, 223 insertions, 84 deletions
diff --git a/target/linux/ar71xx/files/arch/mips/ar71xx/Kconfig b/target/linux/ar71xx/files/arch/mips/ar71xx/Kconfig index ebc6649..2bc7e7a 100644 --- a/target/linux/ar71xx/files/arch/mips/ar71xx/Kconfig +++ b/target/linux/ar71xx/files/arch/mips/ar71xx/Kconfig @@ -91,6 +91,7 @@ config AR71XX_MACH_MZK_W300NH config AR71XX_MACH_TL_WR741ND bool "TP-LINK TL-WR741ND support" select AR71XX_DEV_M25P80 + select AR71XX_DEV_AP91_PCI if PCI default y config AR71XX_MACH_TL_WR941ND @@ -114,6 +115,7 @@ config AR71XX_MACH_TEW_632BRP config AR71XX_MACH_UBNT bool "Ubiquiti AR71xx based boards support" select AR71XX_DEV_M25P80 + select AR71XX_DEV_AP91_PCI if PCI default y endmenu @@ -121,6 +123,9 @@ endmenu config AR71XX_DEV_M25P80 def_bool n +config AR71XX_DEV_AP91_PCI + def_bool n + config AR71XX_DEV_AP94_PCI def_bool n diff --git a/target/linux/ar71xx/files/arch/mips/ar71xx/Makefile b/target/linux/ar71xx/files/arch/mips/ar71xx/Makefile index 54d4513..0d6ae9a 100644 --- a/target/linux/ar71xx/files/arch/mips/ar71xx/Makefile +++ b/target/linux/ar71xx/files/arch/mips/ar71xx/Makefile @@ -13,6 +13,7 @@ obj-y := prom.o irq.o setup.o devices.o gpio.o ar71xx.o obj-$(CONFIG_EARLY_PRINTK) += early_printk.o obj-$(CONFIG_PCI) += pci.o +obj-$(CONFIG_AR71XX_DEV_AP91_PCI) += dev-ap91-pci.o obj-$(CONFIG_AR71XX_DEV_AP94_PCI) += dev-ap94-pci.o obj-$(CONFIG_AR71XX_DEV_AR913X_WMAC) += dev-ar913x-wmac.o obj-$(CONFIG_AR71XX_DEV_M25P80) += dev-m25p80.o diff --git a/target/linux/ar71xx/files/arch/mips/ar71xx/dev-ap91-pci.c b/target/linux/ar71xx/files/arch/mips/ar71xx/dev-ap91-pci.c new file mode 100644 index 0000000..e81a01a --- /dev/null +++ b/target/linux/ar71xx/files/arch/mips/ar71xx/dev-ap91-pci.c @@ -0,0 +1,114 @@ +/* + * Atheros AP91 reference board PCI initialization + * + * Copyright (C) 2009 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/ath9k_platform.h> +#include <linux/delay.h> + +#include <asm/mach-ar71xx/ar71xx.h> +#include <asm/mach-ar71xx/pci.h> + +#include "dev-ap91-pci.h" + +static struct ath9k_platform_data ap91_wmac_data; +static char ap91_wmac_mac[6]; +static int ap91_pci_fixup_enabled; + +static struct ar71xx_pci_irq ap91_pci_irqs[] __initdata = { + { + .slot = 0, + .pin = 1, + .irq = AR71XX_PCI_IRQ_DEV0, + } +}; + +static int ap91_pci_plat_dev_init(struct pci_dev *dev) +{ + switch(PCI_SLOT(dev->devfn)) { + case 0: + dev->dev.platform_data = &ap91_wmac_data; + break; + } + + return 0; +} + +static void ap91_pci_fixup(struct pci_dev *dev) +{ + void __iomem *mem; + u16 *cal_data; + u16 cmd; + u32 val; + + if (!ap91_pci_fixup_enabled) + return; + + printk(KERN_INFO "PCI: fixup device %s\n", pci_name(dev)); + + cal_data = ap91_wmac_data.eeprom_data; + if (*cal_data != 0xa55a) { + printk(KERN_ERR "PCI: no calibration data found for %s\n", + pci_name(dev)); + return; + } + + mem = ioremap(AR71XX_PCI_MEM_BASE, 0x10000); + if (!mem) { + printk(KERN_ERR "PCI: ioremap error for device %s\n", + pci_name(dev)); + return; + } + + /* Setup the PCI device to allow access to the internal registers */ + pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, 0xffff); + pci_read_config_word(dev, PCI_COMMAND, &cmd); + cmd |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY; + pci_write_config_word(dev, PCI_COMMAND, cmd); + + /* set pointer to first reg address */ + cal_data += 3; + while (*cal_data != 0xffff) { + u32 reg; + reg = *cal_data++; + val = *cal_data++; + val |= (*cal_data++) << 16; + + __raw_writel(val, mem + reg); + udelay(100); + } + + pci_read_config_dword(dev, PCI_VENDOR_ID, &val); + dev->vendor = val & 0xffff; + dev->device = (val >> 16) & 0xffff; + + pci_read_config_dword(dev, PCI_CLASS_REVISION, &val); + dev->revision = val & 0xff; + dev->class = val >> 8; /* upper 3 bytes */ + + iounmap(mem); +} +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_ATHEROS, PCI_ANY_ID, ap91_pci_fixup); + +void __init ap91_pci_init(u8 *cal_data, u8 *mac_addr) +{ + if (cal_data) + memcpy(ap91_wmac_data.eeprom_data, cal_data, + sizeof(ap91_wmac_data.eeprom_data)); + + if (mac_addr) { + memcpy(ap91_wmac_mac, mac_addr, sizeof(ap91_wmac_mac)); + ap91_wmac_data.macaddr = ap91_wmac_mac; + } + + ar71xx_pci_plat_dev_init = ap91_pci_plat_dev_init; + ar71xx_pci_init(ARRAY_SIZE(ap91_pci_irqs), ap91_pci_irqs); + + ap91_pci_fixup_enabled = 1; +} diff --git a/target/linux/ar71xx/files/arch/mips/ar71xx/dev-ap91-pci.h b/target/linux/ar71xx/files/arch/mips/ar71xx/dev-ap91-pci.h new file mode 100644 index 0000000..5d30e96 --- /dev/null +++ b/target/linux/ar71xx/files/arch/mips/ar71xx/dev-ap91-pci.h @@ -0,0 +1,23 @@ +/* + * Atheros AP91 reference board PCI initialization + * + * Copyright (C) 2009 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 _AR71XX_DEV_AP91_PCI_H +#define _AR71XX_DEV_AP91_PCI_H + +#include <linux/spi/flash.h> + +#if defined(CONFIG_AR71XX_DEV_AP94_PCI) +void ap91_pci_init(u8 *cal_data, u8 *mac_addr) __init; +#else +static inline void ap91_pci_init(u8 *cal_data, u8 *mac_addr) { } +#endif + +#endif /* _AR71XX_DEV_AP91_PCI_H */ + diff --git a/target/linux/ar71xx/files/arch/mips/ar71xx/mach-tl-wr741nd.c b/target/linux/ar71xx/files/arch/mips/ar71xx/mach-tl-wr741nd.c index 859ef6a..e3abf1e 100644 --- a/target/linux/ar71xx/files/arch/mips/ar71xx/mach-tl-wr741nd.c +++ b/target/linux/ar71xx/files/arch/mips/ar71xx/mach-tl-wr741nd.c @@ -8,20 +8,18 @@ * by the Free Software Foundation. */ -#include <linux/pci.h> #include <linux/platform_device.h> #include <linux/mtd/mtd.h> #include <linux/mtd/partitions.h> #include <linux/input.h> -#include <linux/ath9k_platform.h> #include <asm/mips_machine.h> #include <asm/mach-ar71xx/ar71xx.h> -#include <asm/mach-ar71xx/pci.h> #include "devices.h" #include "dev-m25p80.h" +#include "dev-ap91-pci.h" #define TL_WR741ND_GPIO_LED_QSS 0 #define TL_WR741ND_GPIO_LED_SYSTEM 1 @@ -96,41 +94,10 @@ static struct gpio_button tl_wr741nd_gpio_buttons[] __initdata = { } }; -#ifdef CONFIG_PCI -static struct ar71xx_pci_irq tl_wr741nd_pci_irqs[] __initdata = { - { - .slot = 0, - .pin = 1, - .irq = AR71XX_PCI_IRQ_DEV0, - } -}; - -static struct ath9k_platform_data tl_wr741nd_wmac_data; - -static int tl_wr741nd_pci_plat_dev_init(struct pci_dev *dev) -{ - dev->dev.platform_data = &tl_wr741nd_wmac_data; - return 0; -} - -static void tl_wr741nd_pci_init(void) -{ - u8 *ee = (u8 *) KSEG1ADDR(0x1fff1000); - - memcpy(tl_wr741nd_wmac_data.eeprom_data, ee, - sizeof(tl_wr741nd_wmac_data.eeprom_data)); - - ar71xx_pci_plat_dev_init = tl_wr741nd_pci_plat_dev_init; - - ar71xx_pci_init(ARRAY_SIZE(tl_wr741nd_pci_irqs), tl_wr741nd_pci_irqs); -} -#else -static inline void tl_wr741nd_pci_init(void) { }; -#endif /* CONFIG_PCI */ - static void __init tl_wr741nd_setup(void) { u8 *mac = (u8 *) KSEG1ADDR(0x1f01fc00); + u8 *ee = (u8 *) KSEG1ADDR(0x1fff1000); ar71xx_set_mac_base(mac); ar71xx_add_device_mdio(0x0); @@ -165,6 +132,6 @@ static void __init tl_wr741nd_setup(void) ARRAY_SIZE(tl_wr741nd_gpio_buttons), tl_wr741nd_gpio_buttons); - tl_wr741nd_pci_init(); + ap91_pci_init(ee, NULL); } MIPS_MACHINE(AR71XX_MACH_TL_WR741ND, "TP-LINK TL-WR741ND", tl_wr741nd_setup); diff --git a/target/linux/ar71xx/files/arch/mips/ar71xx/mach-ubnt.c b/target/linux/ar71xx/files/arch/mips/ar71xx/mach-ubnt.c index 5182cbf..fb9f8c5 100644 --- a/target/linux/ar71xx/files/arch/mips/ar71xx/mach-ubnt.c +++ b/target/linux/ar71xx/files/arch/mips/ar71xx/mach-ubnt.c @@ -13,7 +13,6 @@ #include <linux/pci.h> #include <linux/platform_device.h> #include <linux/input.h> -#include <linux/ath9k_platform.h> #include <asm/mips_machine.h> #include <asm/mach-ar71xx/ar71xx.h> @@ -21,6 +20,7 @@ #include "devices.h" #include "dev-m25p80.h" +#include "dev-ap91-pci.h" #define UBNT_RS_GPIO_LED_RF 2 #define UBNT_RS_GPIO_SW4 8 @@ -235,42 +235,10 @@ static void __init ubnt_lssr71_setup(void) MIPS_MACHINE(AR71XX_MACH_UBNT_LSSR71, "Ubiquiti LS-SR71", ubnt_lssr71_setup); -#ifdef CONFIG_PCI -static struct ar71xx_pci_irq ubnt_m_pci_irqs[] __initdata = { - { - .slot = 0, - .pin = 1, - .irq = AR71XX_PCI_IRQ_DEV0, - } -}; - -static struct ath9k_platform_data ubnt_m_wmac_data; - -static int ubmnt_m_pci_plat_dev_init(struct pci_dev *dev) -{ - dev->dev.platform_data = &ubnt_m_wmac_data; - return 0; -} - -static void __init ubnt_m_pci_init(void) -{ - u8 *ee = (u8 *) KSEG1ADDR(0x1fff1000); - - memcpy(ubnt_m_wmac_data.eeprom_data, ee, - sizeof(ubnt_m_wmac_data.eeprom_data)); - - ar71xx_pci_plat_dev_init = ubmnt_m_pci_plat_dev_init; - - ar71xx_pci_init(ARRAY_SIZE(ubnt_m_pci_irqs), - ubnt_m_pci_irqs); -} -#else -static inline void ubnt_m_pci_init(void) { }; -#endif /* CONFIG_PCI */ - static void __init ubnt_m_setup(void) { u8 *mac = (u8 *) KSEG1ADDR(0x1fff0000); + u8 *ee = (u8 *) KSEG1ADDR(0x1fff1000); ar71xx_set_mac_base(mac); @@ -288,7 +256,7 @@ static void __init ubnt_m_setup(void) ar71xx_add_device_eth(0); - ubnt_m_pci_init(); + ap91_pci_init(ee, NULL); ar71xx_add_device_leds_gpio(-1, ARRAY_SIZE(ubnt_m_leds_gpio), ubnt_m_leds_gpio); diff --git a/target/linux/ar71xx/files/arch/mips/include/asm/mach-ar71xx/ar71xx.h b/target/linux/ar71xx/files/arch/mips/include/asm/mach-ar71xx/ar71xx.h index 6526e35..74cdfb3 100644 --- a/target/linux/ar71xx/files/arch/mips/include/asm/mach-ar71xx/ar71xx.h +++ b/target/linux/ar71xx/files/arch/mips/include/asm/mach-ar71xx/ar71xx.h @@ -178,6 +178,7 @@ extern enum ar71xx_mach_type ar71xx_mach; #define AR71XX_ETH1_PLL_SHIFT 19 #define AR724X_PLL_REG_CPU_CONFIG 0x00 +#define AR724X_PLL_REG_PCIE_CONFIG 0x18 #define AR724X_PLL_DIV_SHIFT 0 #define AR724X_PLL_DIV_MASK 0x3ff @@ -384,9 +385,13 @@ void ar71xx_ddr_flush(u32 reg); #define AR724X_PCI_CFG_BASE (AR71XX_PCI_MEM_BASE + 0x4000000) #define AR724X_PCI_CFG_SIZE 0x1000 +#define AR724X_PCI_REG_APP 0x00 +#define AR724X_PCI_REG_RESET 0x18 #define AR724X_PCI_REG_INT_STATUS 0x4c #define AR724X_PCI_REG_INT_MASK 0x50 +#define AR724X_PCI_APP_LTSSM_ENABLE BIT(0) + #define AR724X_PCI_INT_DEV0 BIT(14) static inline void ar724x_pci_wr(unsigned reg, u32 val) @@ -398,6 +403,14 @@ static inline void ar724x_pci_wr(unsigned reg, u32 val) iounmap(base); } +static inline void ar724x_pci_wr_nf(unsigned reg, u32 val) +{ + void __iomem *base; + + base = ioremap_nocache(AR724X_PCI_CTRL_BASE, AR724X_PCI_CTRL_SIZE); + iounmap(base); +} + static inline u32 ar724x_pci_rr(unsigned reg) { void __iomem *base; @@ -477,6 +490,10 @@ static inline u32 ar724x_pci_rr(unsigned reg) #define RESET_MODULE_PCI_BUS BIT(1) #define RESET_MODULE_PCI_CORE BIT(0) +#define AR724X_RESET_PCIE_PHY_SERIAL BIT(10) +#define AR724X_RESET_PCIE_PHY BIT(7) +#define AR724X_RESET_PCIE BIT(6) + #define REV_ID_MAJOR_MASK 0xf0 #define REV_ID_MAJOR_AR71XX 0xa0 #define REV_ID_MAJOR_AR913X 0xb0 diff --git a/target/linux/ar71xx/files/arch/mips/pci/pci-ar724x.c b/target/linux/ar71xx/files/arch/mips/pci/pci-ar724x.c index 139af94..5fcfc87 100644 --- a/target/linux/ar71xx/files/arch/mips/pci/pci-ar724x.c +++ b/target/linux/ar71xx/files/arch/mips/pci/pci-ar724x.c @@ -131,7 +131,7 @@ static int ar724x_pci_write_config(struct pci_bus *bus, unsigned int devfn, static void ar724x_pci_fixup(struct pci_dev *dev) { - u32 t; + u16 cmd; if (!ar724x_pci_fixup_enable) return; @@ -139,14 +139,13 @@ static void ar724x_pci_fixup(struct pci_dev *dev) if (dev->bus->number != 0 || dev->devfn != 0) return; - DBG("PCI: fixup host controller %s (%04x:%04x)\n", pci_name(dev), - dev->vendor, dev->device); - /* setup COMMAND register */ - t = PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE - | PCI_COMMAND_PARITY | PCI_COMMAND_SERR | PCI_COMMAND_FAST_BACK; + pci_read_config_word(dev, PCI_COMMAND, &cmd); + cmd |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | + PCI_COMMAND_INVALIDATE | PCI_COMMAND_PARITY | PCI_COMMAND_SERR | + PCI_COMMAND_FAST_BACK; - pci_write_config_word(dev, PCI_COMMAND, t); + pci_write_config_word(dev, PCI_COMMAND, cmd); } DECLARE_PCI_FIXUP_EARLY(PCI_ANY_ID, PCI_ANY_ID, ar724x_pci_fixup); @@ -201,21 +200,66 @@ static struct pci_controller ar724x_pci_controller = { .io_resource = &ar724x_pci_io_resource, }; -int __init ar724x_pcibios_init(void) +static void __init ar724x_pci_reset(void) +{ + ar71xx_device_stop(AR724X_RESET_PCIE); + ar71xx_device_stop(AR724X_RESET_PCIE_PHY); + ar71xx_device_stop(AR724X_RESET_PCIE_PHY_SERIAL); + udelay(100); + + ar71xx_device_start(AR724X_RESET_PCIE_PHY_SERIAL); + udelay(100); + ar71xx_device_start(AR724X_RESET_PCIE_PHY); + ar71xx_device_start(AR724X_RESET_PCIE); +} + +static int __init ar724x_pci_setup(void) { u32 t; + /* setup COMMAND register */ + t = PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE | + PCI_COMMAND_PARITY|PCI_COMMAND_SERR|PCI_COMMAND_FAST_BACK; + + ar724x_pci_write(ar724x_pci_localcfg_base, PCI_COMMAND, 4, t); + ar724x_pci_write(ar724x_pci_localcfg_base, 0x20, 4, 0x1ff01000); + ar724x_pci_write(ar724x_pci_localcfg_base, 0x24, 4, 0x1ff01000); + + t = ar724x_pci_rr(AR724X_PCI_REG_RESET); + if (t != 0x7) { + udelay(100000); + ar724x_pci_wr_nf(AR724X_PCI_REG_RESET, 0); + udelay(100); + ar724x_pci_wr_nf(AR724X_PCI_REG_RESET, 4); + udelay(100000); + } + + ar724x_pci_wr(AR724X_PCI_REG_APP, AR724X_PCI_APP_LTSSM_ENABLE); + udelay(1000); + + t = ar724x_pci_rr(AR724X_PCI_REG_APP); + if ((t & AR724X_PCI_APP_LTSSM_ENABLE) == 0x0) { + printk(KERN_WARNING "PCI: no PCIe module found\n"); + return -ENODEV; + } + + return 0; +} + +int __init ar724x_pcibios_init(void) +{ + int ret; + ar724x_pci_localcfg_base = ioremap_nocache(AR724X_PCI_CRP_BASE, AR724X_PCI_CRP_SIZE); ar724x_pci_devcfg_base = ioremap_nocache(AR724X_PCI_CFG_BASE, AR724X_PCI_CFG_SIZE); - /* setup COMMAND register */ - t = PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE | - PCI_COMMAND_PARITY | PCI_COMMAND_SERR | PCI_COMMAND_FAST_BACK; - - ar724x_pci_write(ar724x_pci_localcfg_base, PCI_COMMAND, 4, t); + ar724x_pci_reset(); + ret = ar724x_pci_setup(); + if (ret) + return ret; ar724x_pci_fixup_enable = 1; register_pci_controller(&ar724x_pci_controller); |