From 31ecd080e3ab771813abc400fbb429be7758b416 Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Wed, 26 Nov 2008 20:00:41 +0000 Subject: [PATCH] [ar71xx] ag71xx: introduce SoC specific fuctions for DDR flush and PLL setup git-svn-id: svn://svn.openwrt.org/openwrt/trunk@13369 3c298f89-4303-0410-b956-a3cf2f4a3e73 --- .../ar71xx/files/arch/mips/ar71xx/platform.c | 102 +++++++++++++++++- .../ar71xx/files/arch/mips/ar71xx/setup.c | 4 +- .../ar71xx/files/drivers/net/ag71xx/ag71xx.h | 4 +- .../files/drivers/net/ag71xx/ag71xx_main.c | 8 +- .../files/drivers/net/ag71xx/ag71xx_phy.c | 43 +------- .../include/asm-mips/mach-ar71xx/ar71xx.h | 22 ++-- .../include/asm-mips/mach-ar71xx/platform.h | 4 +- 7 files changed, 126 insertions(+), 61 deletions(-) diff --git a/target/linux/ar71xx/files/arch/mips/ar71xx/platform.c b/target/linux/ar71xx/files/arch/mips/ar71xx/platform.c index deda410279..b2add194f7 100644 --- a/target/linux/ar71xx/files/arch/mips/ar71xx/platform.c +++ b/target/linux/ar71xx/files/arch/mips/ar71xx/platform.c @@ -172,6 +172,79 @@ void __init ar71xx_add_device_mdio(u32 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; + u32 t; + + base = ioremap_nocache(AR71XX_PLL_BASE, AR71XX_PLL_SIZE); + + t = __raw_readl(base + cfg_reg); + t &= ~(3 << shift); + t |= (2 << shift); + __raw_writel(t, base + cfg_reg); + udelay(100); + + __raw_writel(pll_val, base + pll_reg); + + t |= (3 << shift); + __raw_writel(t, base + cfg_reg); + udelay(100); + + t &= ~(3 << shift); + __raw_writel(t, base + cfg_reg); + udelay(100); + + printk(KERN_DEBUG "ar71xx: pll_reg %#x: %#x\n", + (unsigned int)(base + pll_reg), __raw_readl(base + pll_reg)); + + iounmap(base); +} + +static void ar71xx_set_pll_ge0(u32 val) +{ + ar71xx_set_pll(AR71XX_PLL_REG_SEC_CONFIG, AR71XX_PLL_REG_ETH0_INT_CLOCK, + val, AR71XX_ETH0_PLL_SHIFT); +} + +static void ar71xx_set_pll_ge1(u32 val) +{ + ar71xx_set_pll(AR71XX_PLL_REG_SEC_CONFIG, AR71XX_PLL_REG_ETH1_INT_CLOCK, + val, AR71XX_ETH1_PLL_SHIFT); +} + +static void ar91xx_set_pll_ge0(u32 val) +{ + ar71xx_set_pll(AR91XX_PLL_REG_ETH_CONFIG, AR91XX_PLL_REG_ETH0_INT_CLOCK, + val, AR91XX_ETH0_PLL_SHIFT); +} + +static void ar91xx_set_pll_ge1(u32 val) +{ + ar71xx_set_pll(AR91XX_PLL_REG_ETH_CONFIG, AR91XX_PLL_REG_ETH1_INT_CLOCK, + val, AR91XX_ETH1_PLL_SHIFT); +} + +static void ar71xx_ddr_flush_ge0(void) +{ + ar71xx_ddr_flush(AR71XX_DDR_REG_FLUSH_GE0); +} + +static void ar71xx_ddr_flush_ge1(void) +{ + ar71xx_ddr_flush(AR71XX_DDR_REG_FLUSH_GE1); +} + +static void ar91xx_ddr_flush_ge0(void) +{ + ar71xx_ddr_flush(AR91XX_DDR_REG_FLUSH_GE0); +} + +static void ar91xx_ddr_flush_ge1(void) +{ + ar71xx_ddr_flush(AR91XX_DDR_REG_FLUSH_GE1); +} + static struct resource ar71xx_eth0_resources[] = { { .name = "mac_base", @@ -198,7 +271,6 @@ static struct resource ar71xx_eth0_resources[] = { struct ag71xx_platform_data ar71xx_eth0_data = { .reset_bit = RESET_MODULE_GE0_MAC, - .flush_reg = AR71XX_DDR_REG_FLUSH_GE0, }; static struct platform_device ar71xx_eth0_device = { @@ -237,7 +309,6 @@ static struct resource ar71xx_eth1_resources[] = { struct ag71xx_platform_data ar71xx_eth1_data = { .reset_bit = RESET_MODULE_GE1_MAC, - .flush_reg = AR71XX_DDR_REG_FLUSH_GE1, }; static struct platform_device ar71xx_eth1_device = { @@ -301,14 +372,35 @@ void __init ar71xx_add_device_eth(unsigned int id) pdata = pdev->dev.platform_data; switch (ar71xx_soc) { + case AR71XX_SOC_AR7130: + pdata->ddr_flush = id ? ar71xx_ddr_flush_ge1 + : ar71xx_ddr_flush_ge0; + pdata->set_pll = id ? ar71xx_set_pll_ge1 + : ar71xx_set_pll_ge0; + break; + case AR71XX_SOC_AR7141: case AR71XX_SOC_AR7161: - case AR71XX_SOC_AR9132: + pdata->ddr_flush = id ? ar71xx_ddr_flush_ge1 + : ar71xx_ddr_flush_ge0; + pdata->set_pll = id ? ar71xx_set_pll_ge1 + : ar71xx_set_pll_ge0; pdata->has_gbit = 1; break; - case AR71XX_SOC_AR7130: case AR71XX_SOC_AR9130: + pdata->ddr_flush = id ? ar91xx_ddr_flush_ge1 + : ar91xx_ddr_flush_ge0; + pdata->set_pll = id ? ar91xx_set_pll_ge1 + : ar91xx_set_pll_ge0; + break; + + case AR71XX_SOC_AR9132: + pdata->ddr_flush = id ? ar91xx_ddr_flush_ge1 + : ar91xx_ddr_flush_ge0; + pdata->set_pll = id ? ar91xx_set_pll_ge1 + : ar91xx_set_pll_ge0; + pdata->has_gbit = 1; break; default: @@ -319,7 +411,7 @@ void __init ar71xx_add_device_eth(unsigned int id) case PHY_INTERFACE_MODE_GMII: case PHY_INTERFACE_MODE_RGMII: if (!pdata->has_gbit) { - printk(KERN_ERR "ar71xx: no gigabit available on eth%d\n", + printk(KERN_ERR "ar71xx: no gbit available on eth%d\n", id); return; } diff --git a/target/linux/ar71xx/files/arch/mips/ar71xx/setup.c b/target/linux/ar71xx/files/arch/mips/ar71xx/setup.c index 758f541423..a5d26e72c6 100644 --- a/target/linux/ar71xx/files/arch/mips/ar71xx/setup.c +++ b/target/linux/ar71xx/files/arch/mips/ar71xx/setup.c @@ -149,7 +149,7 @@ static void __init ar91xx_detect_sys_frequency(void) u32 freq; u32 div; - pll = ar71xx_pll_rr(PLL_REG_CPU_PLL_CFG); + pll = ar71xx_pll_rr(AR91XX_PLL_REG_CPU_CONFIG); div = ((pll >> AR91XX_PLL_DIV_SHIFT) & AR91XX_PLL_DIV_MASK); freq = div * AR91XX_BASE_FREQ; @@ -169,7 +169,7 @@ static void __init ar71xx_detect_sys_frequency(void) u32 freq; u32 div; - pll = ar71xx_pll_rr(PLL_REG_CPU_PLL_CFG); + pll = ar71xx_pll_rr(AR71XX_PLL_REG_CPU_CONFIG); div = ((pll >> AR71XX_PLL_DIV_SHIFT) & AR71XX_PLL_DIV_MASK) + 1; freq = div * AR71XX_BASE_FREQ; diff --git a/target/linux/ar71xx/files/drivers/net/ag71xx/ag71xx.h b/target/linux/ar71xx/files/drivers/net/ag71xx/ag71xx.h index f7865523c3..06ec3c3bf6 100644 --- a/target/linux/ar71xx/files/drivers/net/ag71xx/ag71xx.h +++ b/target/linux/ar71xx/files/drivers/net/ag71xx/ag71xx.h @@ -37,7 +37,7 @@ #define ETH_FCS_LEN 4 #define AG71XX_DRV_NAME "ag71xx" -#define AG71XX_DRV_VERSION "0.4.4" +#define AG71XX_DRV_VERSION "0.5.0" #define AG71XX_NAPI_TX 1 @@ -331,6 +331,8 @@ static inline u32 ag71xx_rr(struct ag71xx *ag, unsigned reg) reg -= AG71XX_REG_MAC_IFCTL; ret = __raw_readl(ag->mac_base2 + reg); break; + default: + BUG(); } return ret; diff --git a/target/linux/ar71xx/files/drivers/net/ag71xx/ag71xx_main.c b/target/linux/ar71xx/files/drivers/net/ag71xx/ag71xx_main.c index 47fc674077..3d60a8bab6 100644 --- a/target/linux/ar71xx/files/drivers/net/ag71xx/ag71xx_main.c +++ b/target/linux/ar71xx/files/drivers/net/ag71xx/ag71xx_main.c @@ -384,7 +384,7 @@ static int ag71xx_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) desc = &ring->descs[i]; spin_lock_irqsave(&ag->lock, flags); - ar71xx_ddr_flush(pdata->flush_reg); + pdata->ddr_flush(); spin_unlock_irqrestore(&ag->lock, flags); if (!ag71xx_desc_empty(desc)) @@ -480,7 +480,7 @@ static void ag71xx_tx_packets(struct ag71xx *ag) DBG("%s: processing TX ring\n", ag->dev->name); #ifdef AG71XX_NAPI_TX - ar71xx_ddr_flush(pdata->flush_reg); + pdata->ddr_flush(); #endif sent = 0; @@ -523,7 +523,7 @@ static int ag71xx_rx_packets(struct ag71xx *ag, int limit) #ifndef AG71XX_NAPI_TX spin_lock_irqsave(&ag->lock, flags); - ar71xx_ddr_flush(pdata->flush_reg); + pdata->ddr_flush(); spin_unlock_irqrestore(&ag->lock, flags); #endif @@ -592,7 +592,7 @@ static int ag71xx_poll(struct napi_struct *napi, int limit) int done; #ifdef AG71XX_NAPI_TX - ar71xx_ddr_flush(pdata->flush_reg); + pdata->ddr_flush(); ag71xx_tx_packets(ag); #endif diff --git a/target/linux/ar71xx/files/drivers/net/ag71xx/ag71xx_phy.c b/target/linux/ar71xx/files/drivers/net/ag71xx/ag71xx_phy.c index 9173b48ad5..cedbfe616b 100644 --- a/target/linux/ar71xx/files/drivers/net/ag71xx/ag71xx_phy.c +++ b/target/linux/ar71xx/files/drivers/net/ag71xx/ag71xx_phy.c @@ -13,46 +13,6 @@ #include "ag71xx.h" -#define PLL_SEC_CONFIG 0x18050004 -#define PLL_ETH0_INT_CLOCK 0x18050010 -#define PLL_ETH1_INT_CLOCK 0x18050014 -#define PLL_ETH_EXT_CLOCK 0x18050018 - -#define ag71xx_pll_shift(_ag) (((_ag)->pdev->id) ? 19 : 17) -#define ag71xx_pll_offset(_ag) (((_ag)->pdev->id) ? PLL_ETH1_INT_CLOCK \ - : PLL_ETH0_INT_CLOCK) - -static void ag71xx_set_pll(struct ag71xx *ag, u32 pll_val) -{ - void __iomem *pll_reg = ioremap_nocache(ag71xx_pll_offset(ag), 4); - void __iomem *pll_cfg = ioremap_nocache(PLL_SEC_CONFIG, 4); - u32 s; - u32 t; - - s = ag71xx_pll_shift(ag); - - t = __raw_readl(pll_cfg); - t &= ~(3 << s); - t |= (2 << s); - __raw_writel(t, pll_cfg); - udelay(100); - - __raw_writel(pll_val, pll_reg); - - t |= (3 << s); - __raw_writel(t, pll_cfg); - udelay(100); - - t &= ~(3 << s); - __raw_writel(t, pll_cfg); - udelay(100); - DBG("%s: pll_reg %#x: %#x\n", ag->dev->name, - (unsigned int)pll_reg, __raw_readl(pll_reg)); - - iounmap(pll_cfg); - iounmap(pll_reg); -} - static unsigned char *ag71xx_speed_str(struct ag71xx *ag) { switch (ag->speed) { @@ -79,6 +39,7 @@ static unsigned char *ag71xx_speed_str(struct ag71xx *ag) static void ag71xx_phy_link_update(struct ag71xx *ag) { + struct ag71xx_platform_data *pdata = ag71xx_get_pdata(ag); u32 cfg2; u32 ifctl; u32 pll; @@ -126,7 +87,7 @@ static void ag71xx_phy_link_update(struct ag71xx *ag) } ag71xx_wr(ag, AG71XX_REG_FIFO_CFG3, 0x008001ff); - ag71xx_set_pll(ag, pll); + pdata->set_pll(pll); ag71xx_mii_ctrl_set_speed(ag, mii_speed); ag71xx_wr(ag, AG71XX_REG_MAC_CFG2, cfg2); diff --git a/target/linux/ar71xx/files/include/asm-mips/mach-ar71xx/ar71xx.h b/target/linux/ar71xx/files/include/asm-mips/mach-ar71xx/ar71xx.h index f68bfff199..e9a69cd56b 100644 --- a/target/linux/ar71xx/files/include/asm-mips/mach-ar71xx/ar71xx.h +++ b/target/linux/ar71xx/files/include/asm-mips/mach-ar71xx/ar71xx.h @@ -106,13 +106,10 @@ extern enum ar71xx_soc_type ar71xx_soc; /* * PLL block */ -#define PLL_REG_CPU_PLL_CFG 0x00 -#define PLL_REG_SEC_PLL_CFG 0x04 -#define PLL_REG_CPU_CLK_CTRL 0x08 -#define PLL_REG_ETH_INT0_CLK 0x10 -#define PLL_REG_ETH_INT1_CLK 0x14 -#define PLL_REG_ETH_EXT_CLK 0x18 -#define PLL_REG_PCI_CLK 0x1c +#define AR71XX_PLL_REG_CPU_CONFIG 0x00 +#define AR71XX_PLL_REG_SEC_CONFIG 0x04 +#define AR71XX_PLL_REG_ETH0_INT_CLOCK 0x10 +#define AR71XX_PLL_REG_ETH1_INT_CLOCK 0x14 #define AR71XX_PLL_DIV_SHIFT 3 #define AR71XX_PLL_DIV_MASK 0x1f @@ -123,6 +120,14 @@ extern enum ar71xx_soc_type ar71xx_soc; #define AR71XX_AHB_DIV_SHIFT 20 #define AR71XX_AHB_DIV_MASK 0x7 +#define AR71XX_ETH0_PLL_SHIFT 17 +#define AR71XX_ETH1_PLL_SHIFT 19 + +#define AR91XX_PLL_REG_CPU_CONFIG 0x00 +#define AR91XX_PLL_REG_ETH_CONFIG 0x04 +#define AR91XX_PLL_REG_ETH0_INT_CLOCK 0x14 +#define AR91XX_PLL_REG_ETH1_INT_CLOCK 0x18 + #define AR91XX_PLL_DIV_SHIFT 0 #define AR91XX_PLL_DIV_MASK 0x3ff #define AR91XX_DDR_DIV_SHIFT 22 @@ -130,6 +135,9 @@ extern enum ar71xx_soc_type ar71xx_soc; #define AR91XX_AHB_DIV_SHIFT 19 #define AR91XX_AHB_DIV_MASK 0x1 +#define AR91XX_ETH0_PLL_SHIFT 20 +#define AR91XX_ETH1_PLL_SHIFT 22 + extern void __iomem *ar71xx_pll_base; static inline void ar71xx_pll_wr(unsigned reg, u32 val) diff --git a/target/linux/ar71xx/files/include/asm-mips/mach-ar71xx/platform.h b/target/linux/ar71xx/files/include/asm-mips/mach-ar71xx/platform.h index f845c42f30..9d567a6c8d 100644 --- a/target/linux/ar71xx/files/include/asm-mips/mach-ar71xx/platform.h +++ b/target/linux/ar71xx/files/include/asm-mips/mach-ar71xx/platform.h @@ -25,11 +25,13 @@ struct ag71xx_platform_data { int speed; int duplex; u32 reset_bit; - u32 flush_reg; u32 mii_if; u8 mac_addr[ETH_ALEN]; u8 has_gbit:1; + + void (* ddr_flush)(void); + void (* set_pll)(u32 pll); }; struct ag71xx_mdio_platform_data {