From c9ae01d3c868020747b32424188f12542a69efc2 Mon Sep 17 00:00:00 2001
From: Gabor Juhos <juhosg@openwrt.org>
Date: Wed, 26 Nov 2008 20:00:41 +0000
Subject: ag71xx: introduce SoC specific fuctions for DDR flush and PLL setup

SVN-Revision: 13369
---
 .../linux/ar71xx/files/arch/mips/ar71xx/platform.c | 102 ++++++++++++++++++++-
 target/linux/ar71xx/files/arch/mips/ar71xx/setup.c |   4 +-
 .../linux/ar71xx/files/drivers/net/ag71xx/ag71xx.h |   4 +-
 .../ar71xx/files/drivers/net/ag71xx/ag71xx_main.c  |   8 +-
 .../ar71xx/files/drivers/net/ag71xx/ag71xx_phy.c   |  43 +--------
 .../files/include/asm-mips/mach-ar71xx/ar71xx.h    |  22 +++--
 .../files/include/asm-mips/mach-ar71xx/platform.h  |   4 +-
 7 files changed, 126 insertions(+), 61 deletions(-)

(limited to 'target/linux/ar71xx/files')

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 {
-- 
cgit v1.2.3