aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLennert Buytenhek <buytenh@wantstofly.org>2008-04-23 19:29:59 -0400
committerDale Farnsworth <dale@farnsworth.org>2008-04-29 00:17:07 -0400
commitce4e2e4558903ef92edf1ab4e09b0b338a09fd61 (patch)
treedbfd7901022f9761214469749d19b07ba1d441b1
parent240e4419e0cfcba737883b637ec2bdcc071ea03d (diff)
mv643xx_eth: inter-mv643xx SMI port sharing
There exist chips with up to four mv643xx_eth silicon blocks but only one external SMI (MII management) interface -- the SMI logic of the first block is shared by all the blocks. Handle this by allowing a per-port override of which mv643xx_eth_shared's SMI registers (and spinlock) to use. Signed-off-by: Lennert Buytenhek <buytenh@marvell.com> Acked-by: Nicolas Pitre <nico@marvell.com> Signed-off-by: Dale Farnsworth <dale@farnsworth.org>
-rw-r--r--drivers/net/mv643xx_eth.c38
-rw-r--r--include/linux/mv643xx_eth.h2
2 files changed, 24 insertions, 16 deletions
diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c
index 8bd41e4e88a9..b7915cdcc6a5 100644
--- a/drivers/net/mv643xx_eth.c
+++ b/drivers/net/mv643xx_eth.c
@@ -527,6 +527,8 @@ struct mv643xx_private {
527 struct mv643xx_shared_private *shared; 527 struct mv643xx_shared_private *shared;
528 int port_num; /* User Ethernet port number */ 528 int port_num; /* User Ethernet port number */
529 529
530 struct mv643xx_shared_private *shared_smi;
531
530 u32 rx_sram_addr; /* Base address of rx sram area */ 532 u32 rx_sram_addr; /* Base address of rx sram area */
531 u32 rx_sram_size; /* Size of rx sram area */ 533 u32 rx_sram_size; /* Size of rx sram area */
532 u32 tx_sram_addr; /* Base address of tx sram area */ 534 u32 tx_sram_addr; /* Base address of tx sram area */
@@ -1898,6 +1900,10 @@ static int mv643xx_eth_probe(struct platform_device *pdev)
1898 if (mp->shared->win_protect) 1900 if (mp->shared->win_protect)
1899 wrl(mp, WINDOW_PROTECT(port_num), mp->shared->win_protect); 1901 wrl(mp, WINDOW_PROTECT(port_num), mp->shared->win_protect);
1900 1902
1903 mp->shared_smi = mp->shared;
1904 if (pd->shared_smi != NULL)
1905 mp->shared_smi = platform_get_drvdata(pd->shared_smi);
1906
1901 /* set default config values */ 1907 /* set default config values */
1902 eth_port_uc_addr_get(mp, dev->dev_addr); 1908 eth_port_uc_addr_get(mp, dev->dev_addr);
1903 mp->rx_ring_size = PORT_DEFAULT_RECEIVE_QUEUE_SIZE; 1909 mp->rx_ring_size = PORT_DEFAULT_RECEIVE_QUEUE_SIZE;
@@ -2986,15 +2992,16 @@ static void eth_port_reset(struct mv643xx_private *mp)
2986static void eth_port_read_smi_reg(struct mv643xx_private *mp, 2992static void eth_port_read_smi_reg(struct mv643xx_private *mp,
2987 unsigned int phy_reg, unsigned int *value) 2993 unsigned int phy_reg, unsigned int *value)
2988{ 2994{
2995 void __iomem *smi_reg = mp->shared_smi->eth_base + SMI_REG;
2989 int phy_addr = ethernet_phy_get(mp); 2996 int phy_addr = ethernet_phy_get(mp);
2990 unsigned long flags; 2997 unsigned long flags;
2991 int i; 2998 int i;
2992 2999
2993 /* the SMI register is a shared resource */ 3000 /* the SMI register is a shared resource */
2994 spin_lock_irqsave(&mp->shared->phy_lock, flags); 3001 spin_lock_irqsave(&mp->shared_smi->phy_lock, flags);
2995 3002
2996 /* wait for the SMI register to become available */ 3003 /* wait for the SMI register to become available */
2997 for (i = 0; rdl(mp, SMI_REG) & ETH_SMI_BUSY; i++) { 3004 for (i = 0; readl(smi_reg) & ETH_SMI_BUSY; i++) {
2998 if (i == PHY_WAIT_ITERATIONS) { 3005 if (i == PHY_WAIT_ITERATIONS) {
2999 printk("%s: PHY busy timeout\n", mp->dev->name); 3006 printk("%s: PHY busy timeout\n", mp->dev->name);
3000 goto out; 3007 goto out;
@@ -3002,11 +3009,11 @@ static void eth_port_read_smi_reg(struct mv643xx_private *mp,
3002 udelay(PHY_WAIT_MICRO_SECONDS); 3009 udelay(PHY_WAIT_MICRO_SECONDS);
3003 } 3010 }
3004 3011
3005 wrl(mp, SMI_REG, 3012 writel((phy_addr << 16) | (phy_reg << 21) | ETH_SMI_OPCODE_READ,
3006 (phy_addr << 16) | (phy_reg << 21) | ETH_SMI_OPCODE_READ); 3013 smi_reg);
3007 3014
3008 /* now wait for the data to be valid */ 3015 /* now wait for the data to be valid */
3009 for (i = 0; !(rdl(mp, SMI_REG) & ETH_SMI_READ_VALID); i++) { 3016 for (i = 0; !(readl(smi_reg) & ETH_SMI_READ_VALID); i++) {
3010 if (i == PHY_WAIT_ITERATIONS) { 3017 if (i == PHY_WAIT_ITERATIONS) {
3011 printk("%s: PHY read timeout\n", mp->dev->name); 3018 printk("%s: PHY read timeout\n", mp->dev->name);
3012 goto out; 3019 goto out;
@@ -3014,9 +3021,9 @@ static void eth_port_read_smi_reg(struct mv643xx_private *mp,
3014 udelay(PHY_WAIT_MICRO_SECONDS); 3021 udelay(PHY_WAIT_MICRO_SECONDS);
3015 } 3022 }
3016 3023
3017 *value = rdl(mp, SMI_REG) & 0xffff; 3024 *value = readl(smi_reg) & 0xffff;
3018out: 3025out:
3019 spin_unlock_irqrestore(&mp->shared->phy_lock, flags); 3026 spin_unlock_irqrestore(&mp->shared_smi->phy_lock, flags);
3020} 3027}
3021 3028
3022/* 3029/*
@@ -3042,17 +3049,16 @@ out:
3042static void eth_port_write_smi_reg(struct mv643xx_private *mp, 3049static void eth_port_write_smi_reg(struct mv643xx_private *mp,
3043 unsigned int phy_reg, unsigned int value) 3050 unsigned int phy_reg, unsigned int value)
3044{ 3051{
3045 int phy_addr; 3052 void __iomem *smi_reg = mp->shared_smi->eth_base + SMI_REG;
3046 int i; 3053 int phy_addr = ethernet_phy_get(mp);
3047 unsigned long flags; 3054 unsigned long flags;
3048 3055 int i;
3049 phy_addr = ethernet_phy_get(mp);
3050 3056
3051 /* the SMI register is a shared resource */ 3057 /* the SMI register is a shared resource */
3052 spin_lock_irqsave(&mp->shared->phy_lock, flags); 3058 spin_lock_irqsave(&mp->shared_smi->phy_lock, flags);
3053 3059
3054 /* wait for the SMI register to become available */ 3060 /* wait for the SMI register to become available */
3055 for (i = 0; rdl(mp, SMI_REG) & ETH_SMI_BUSY; i++) { 3061 for (i = 0; readl(smi_reg) & ETH_SMI_BUSY; i++) {
3056 if (i == PHY_WAIT_ITERATIONS) { 3062 if (i == PHY_WAIT_ITERATIONS) {
3057 printk("%s: PHY busy timeout\n", mp->dev->name); 3063 printk("%s: PHY busy timeout\n", mp->dev->name);
3058 goto out; 3064 goto out;
@@ -3060,10 +3066,10 @@ static void eth_port_write_smi_reg(struct mv643xx_private *mp,
3060 udelay(PHY_WAIT_MICRO_SECONDS); 3066 udelay(PHY_WAIT_MICRO_SECONDS);
3061 } 3067 }
3062 3068
3063 wrl(mp, SMI_REG, (phy_addr << 16) | (phy_reg << 21) | 3069 writel((phy_addr << 16) | (phy_reg << 21) |
3064 ETH_SMI_OPCODE_WRITE | (value & 0xffff)); 3070 ETH_SMI_OPCODE_WRITE | (value & 0xffff), smi_reg);
3065out: 3071out:
3066 spin_unlock_irqrestore(&mp->shared->phy_lock, flags); 3072 spin_unlock_irqrestore(&mp->shared_smi->phy_lock, flags);
3067} 3073}
3068 3074
3069/* 3075/*
diff --git a/include/linux/mv643xx_eth.h b/include/linux/mv643xx_eth.h
index 66dc9571922a..a15cdd4a8e58 100644
--- a/include/linux/mv643xx_eth.h
+++ b/include/linux/mv643xx_eth.h
@@ -24,6 +24,8 @@ struct mv643xx_eth_platform_data {
24 struct platform_device *shared; 24 struct platform_device *shared;
25 int port_number; 25 int port_number;
26 26
27 struct platform_device *shared_smi;
28
27 u16 force_phy_addr; /* force override if phy_addr == 0 */ 29 u16 force_phy_addr; /* force override if phy_addr == 0 */
28 u16 phy_addr; 30 u16 phy_addr;
29 31