From 186e6bdd5352b20d8b28a70b8c5a0f214d775c57 Mon Sep 17 00:00:00 2001 From: nbd Date: Wed, 10 Aug 2011 18:50:12 +0000 Subject: [PATCH] ar71xx: backport ar7241/ar7242 fixes from trunk git-svn-id: svn://svn.openwrt.org/openwrt/branches/backfire@27949 3c298f89-4303-0410-b956-a3cf2f4a3e73 --- .../files/arch/mips/ar71xx/dev-ap91-pci.c | 24 ++++- .../ar71xx/files/arch/mips/ar71xx/dev-usb.c | 37 +++++--- .../ar71xx/files/arch/mips/ar71xx/devices.c | 89 +++++++++++++++---- .../mips/include/asm/mach-ar71xx/ar71xx.h | 5 ++ 4 files changed, 123 insertions(+), 32 deletions(-) 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 index 912a0e4d9..abcb6b67e 100644 --- a/target/linux/ar71xx/files/arch/mips/ar71xx/dev-ap91-pci.c +++ b/target/linux/ar71xx/files/arch/mips/ar71xx/dev-ap91-pci.c @@ -47,6 +47,7 @@ static void ap91_pci_fixup(struct pci_dev *dev) void __iomem *mem; u16 *cal_data; u16 cmd; + u32 bar0; u32 val; if (!ap91_pci_fixup_enabled) @@ -69,7 +70,22 @@ static void ap91_pci_fixup(struct pci_dev *dev) } /* Setup the PCI device to allow access to the internal registers */ - pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, 0xffff); + pci_read_config_dword(dev, PCI_BASE_ADDRESS_0, &bar0); + + switch (ar71xx_soc) { + case AR71XX_SOC_AR7240: + pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, 0xffff); + break; + + case AR71XX_SOC_AR7241: + case AR71XX_SOC_AR7242: + pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, 0x1000ffff); + break; + + default: + break; + } + pci_read_config_word(dev, PCI_COMMAND, &cmd); cmd |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY; pci_write_config_word(dev, PCI_COMMAND, cmd); @@ -94,6 +110,12 @@ static void ap91_pci_fixup(struct pci_dev *dev) dev->revision = val & 0xff; dev->class = val >> 8; /* upper 3 bytes */ + pci_read_config_word(dev, PCI_COMMAND, &cmd); + cmd &= ~(PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY); + pci_write_config_word(dev, PCI_COMMAND, cmd); + + pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, bar0); + iounmap(mem); } DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_ATHEROS, PCI_ANY_ID, ap91_pci_fixup); diff --git a/target/linux/ar71xx/files/arch/mips/ar71xx/dev-usb.c b/target/linux/ar71xx/files/arch/mips/ar71xx/dev-usb.c index fb006c705..20ab17f0c 100644 --- a/target/linux/ar71xx/files/arch/mips/ar71xx/dev-usb.c +++ b/target/linux/ar71xx/files/arch/mips/ar71xx/dev-usb.c @@ -64,7 +64,7 @@ static struct platform_device ar71xx_ohci_device = { }; /* - * EHCI (USB full speed host controller) + * EHCI (USB high/full speed host controller) */ static struct resource ar71xx_ehci_resources[] = { [0] = { @@ -128,16 +128,26 @@ static void __init ar7240_usb_setup(void) /* WAR for HW bug. Here it adjusts the duration between two SOFS */ ar71xx_usb_ctrl_wr(USB_CTRL_REG_FLADJ, 0x3); - if (ar71xx_soc == AR71XX_SOC_AR7241 || ar71xx_soc == AR71XX_SOC_AR7242) { - ar71xx_ehci_data.is_ar91xx = 1; - ar71xx_ehci_device.resource = ar7240_ohci_resources; - ar71xx_ehci_device.num_resources = ARRAY_SIZE(ar7240_ohci_resources); - platform_device_register(&ar71xx_ehci_device); - } else { - ar71xx_ohci_device.resource = ar7240_ohci_resources; - ar71xx_ohci_device.num_resources = ARRAY_SIZE(ar7240_ohci_resources); - platform_device_register(&ar71xx_ohci_device); - } + ar71xx_ohci_device.resource = ar7240_ohci_resources; + ar71xx_ohci_device.num_resources = ARRAY_SIZE(ar7240_ohci_resources); + platform_device_register(&ar71xx_ohci_device); +} + +static void __init ar7241_usb_setup(void) +{ + ar71xx_device_start(AR724X_RESET_USBSUS_OVERRIDE); + mdelay(10); + + ar71xx_device_start(AR724X_RESET_USB_HOST); + mdelay(10); + + ar71xx_device_start(AR724X_RESET_USB_PHY); + mdelay(10); + + ar71xx_ehci_data.is_ar91xx = 1; + ar71xx_ehci_device.resource = ar7240_ohci_resources; + ar71xx_ehci_device.num_resources = ARRAY_SIZE(ar7240_ohci_resources); + platform_device_register(&ar71xx_ehci_device); } static void __init ar91xx_usb_setup(void) @@ -159,9 +169,12 @@ void __init ar71xx_add_device_usb(void) { switch (ar71xx_soc) { case AR71XX_SOC_AR7240: + ar7240_usb_setup(); + break; + case AR71XX_SOC_AR7241: case AR71XX_SOC_AR7242: - ar7240_usb_setup(); + ar7241_usb_setup(); break; case AR71XX_SOC_AR7130: diff --git a/target/linux/ar71xx/files/arch/mips/ar71xx/devices.c b/target/linux/ar71xx/files/arch/mips/ar71xx/devices.c index 43226c1da..455b2cd03 100644 --- a/target/linux/ar71xx/files/arch/mips/ar71xx/devices.c +++ b/target/linux/ar71xx/files/arch/mips/ar71xx/devices.c @@ -82,23 +82,6 @@ struct platform_device ar71xx_mdio_device = { }, }; -void __init ar71xx_add_device_mdio(u32 phy_mask) -{ - switch (ar71xx_soc) { - case AR71XX_SOC_AR7240: - case AR71XX_SOC_AR7241: - case AR71XX_SOC_AR7242: - ar71xx_mdio_data.is_ar7240 = 1; - break; - default: - break; - } - - ar71xx_mdio_data.phy_mask = phy_mask; - - platform_device_register(&ar71xx_mdio_device); -} - static void ar71xx_set_pll(u32 cfg_reg, u32 pll_reg, u32 pll_val, u32 shift) { void __iomem *base; @@ -128,6 +111,31 @@ static void ar71xx_set_pll(u32 cfg_reg, u32 pll_reg, u32 pll_val, u32 shift) iounmap(base); } +void __init ar71xx_add_device_mdio(u32 phy_mask) +{ + switch (ar71xx_soc) { + case AR71XX_SOC_AR7240: + ar71xx_mdio_data.is_ar7240 = 1; + break; + case AR71XX_SOC_AR7241: + ar71xx_mdio_data.is_ar7240 = 1; + ar71xx_mdio_resources[0].start = AR71XX_GE1_BASE; + ar71xx_mdio_resources[0].end = AR71XX_GE1_BASE + 0x200 - 1; + break; + case AR71XX_SOC_AR7242: + ar71xx_set_pll(AR71XX_PLL_REG_SEC_CONFIG, + AR7242_PLL_REG_ETH0_INT_CLOCK, 0x62000000, + AR71XX_ETH0_PLL_SHIFT); + break; + default: + break; + } + + ar71xx_mdio_data.phy_mask = phy_mask; + + platform_device_register(&ar71xx_mdio_device); +} + struct ar71xx_eth_pll_data ar71xx_eth0_pll_data; struct ar71xx_eth_pll_data ar71xx_eth1_pll_data; @@ -190,6 +198,14 @@ static void ar724x_set_pll_ge1(int speed) /* TODO */ } +static void ar7242_set_pll_ge0(int speed) +{ + u32 val = ar71xx_get_eth_pll(0, speed); + + ar71xx_set_pll(AR71XX_PLL_REG_SEC_CONFIG, AR7242_PLL_REG_ETH0_INT_CLOCK, + val, AR71XX_ETH0_PLL_SHIFT); +} + static void ar91xx_set_pll_ge0(int speed) { u32 val = ar71xx_get_eth_pll(0, speed); @@ -310,6 +326,10 @@ struct platform_device ar71xx_eth1_device = { #define AR724X_PLL_VAL_100 0x00001099 #define AR724X_PLL_VAL_10 0x00991099 +#define AR7242_PLL_VAL_1000 0x1c000000 +#define AR7242_PLL_VAL_100 0x00000101 +#define AR7242_PLL_VAL_10 0x00001616 + #define AR91XX_PLL_VAL_1000 0x1a000000 #define AR91XX_PLL_VAL_100 0x13000a44 #define AR91XX_PLL_VAL_10 0x00441099 @@ -341,12 +361,17 @@ static void __init ar71xx_init_eth_pll_data(unsigned int id) case AR71XX_SOC_AR7240: case AR71XX_SOC_AR7241: - case AR71XX_SOC_AR7242: pll_10 = AR724X_PLL_VAL_10; pll_100 = AR724X_PLL_VAL_100; pll_1000 = AR724X_PLL_VAL_1000; break; + case AR71XX_SOC_AR7242: + pll_10 = AR7242_PLL_VAL_10; + pll_100 = AR7242_PLL_VAL_100; + pll_1000 = AR7242_PLL_VAL_1000; + break; + case AR71XX_SOC_AR9130: case AR71XX_SOC_AR9132: pll_10 = AR91XX_PLL_VAL_10; @@ -436,8 +461,27 @@ void __init ar71xx_add_device_eth(unsigned int id) pdata->has_gbit = 1; break; - case AR71XX_SOC_AR7241: case AR71XX_SOC_AR7242: + ar71xx_eth0_data.reset_bit |= AR724X_RESET_GE0_MDIO | + RESET_MODULE_GE0_PHY; + ar71xx_eth1_data.reset_bit |= AR724X_RESET_GE1_MDIO | + RESET_MODULE_GE1_PHY; + pdata->ddr_flush = id ? ar724x_ddr_flush_ge1 + : ar724x_ddr_flush_ge0; + pdata->set_pll = id ? ar724x_set_pll_ge1 + : ar7242_set_pll_ge0; + 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; + + case AR71XX_SOC_AR7241: ar71xx_eth0_data.reset_bit |= AR724X_RESET_GE0_MDIO; ar71xx_eth1_data.reset_bit |= AR724X_RESET_GE1_MDIO; /* fall through */ @@ -449,6 +493,13 @@ void __init ar71xx_add_device_eth(unsigned int id) pdata->set_pll = id ? ar724x_set_pll_ge1 : ar724x_set_pll_ge0; 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; case AR71XX_SOC_AR9130: 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 c6a5a4099..c802354db 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 @@ -152,6 +152,8 @@ extern enum ar71xx_soc_type ar71xx_soc; #define AR724X_DDR_DIV_SHIFT 22 #define AR724X_DDR_DIV_MASK 0x3 +#define AR7242_PLL_REG_ETH0_INT_CLOCK 0x2c + #define AR91XX_PLL_REG_CPU_CONFIG 0x00 #define AR91XX_PLL_REG_ETH_CONFIG 0x04 #define AR91XX_PLL_REG_ETH0_INT_CLOCK 0x14 @@ -432,6 +434,9 @@ void ar71xx_ddr_flush(u32 reg); #define AR724X_RESET_PCIE_PHY_SERIAL BIT(10) #define AR724X_RESET_PCIE_PHY BIT(7) #define AR724X_RESET_PCIE BIT(6) +#define AR724X_RESET_USB_HOST BIT(5) +#define AR724X_RESET_USB_PHY BIT(4) +#define AR724X_RESET_USBSUS_OVERRIDE BIT(3) #define REV_ID_MAJOR_MASK 0xfff0 #define REV_ID_MAJOR_AR71XX 0x00a0 -- 2.35.1