diff options
author | Lennert Buytenhek <buytenh@wantstofly.org> | 2008-04-23 19:27:02 -0400 |
---|---|---|
committer | Dale Farnsworth <dale@farnsworth.org> | 2008-04-29 00:17:07 -0400 |
commit | fa3959f457109cc7d082b86ea6daae927982815b (patch) | |
tree | 0e1f7aae6f3340d915f61e1489615972c629621d | |
parent | e31a94ed371c70855eb30b77c490d6d85dd4da26 (diff) |
mv643xx_eth: get rid of static variables, allow multiple instances
Move mv643xx_eth's static state (ethernet register block base address
and MII management interface spinlock) into a struct hanging off the
shared platform device. This is necessary to support chips that
contain multiple mv643xx_eth silicon blocks.
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-- | arch/arm/mach-orion5x/common.c | 2 | ||||
-rw-r--r-- | arch/powerpc/platforms/chrp/pegasos_eth.c | 4 | ||||
-rw-r--r-- | arch/powerpc/sysdev/mv64x60_dev.c | 2 | ||||
-rw-r--r-- | arch/ppc/syslib/mv64x60.c | 3 | ||||
-rw-r--r-- | drivers/net/mv643xx_eth.c | 62 | ||||
-rw-r--r-- | include/linux/mv643xx_eth.h | 3 |
6 files changed, 59 insertions, 17 deletions
diff --git a/arch/arm/mach-orion5x/common.c b/arch/arm/mach-orion5x/common.c index 439c7784af02..2bedf71659cb 100644 --- a/arch/arm/mach-orion5x/common.c +++ b/arch/arm/mach-orion5x/common.c | |||
@@ -223,7 +223,9 @@ static struct platform_device orion5x_eth = { | |||
223 | 223 | ||
224 | void __init orion5x_eth_init(struct mv643xx_eth_platform_data *eth_data) | 224 | void __init orion5x_eth_init(struct mv643xx_eth_platform_data *eth_data) |
225 | { | 225 | { |
226 | eth_data->shared = &orion5x_eth_shared; | ||
226 | orion5x_eth.dev.platform_data = eth_data; | 227 | orion5x_eth.dev.platform_data = eth_data; |
228 | |||
227 | platform_device_register(&orion5x_eth_shared); | 229 | platform_device_register(&orion5x_eth_shared); |
228 | platform_device_register(&orion5x_eth); | 230 | platform_device_register(&orion5x_eth); |
229 | } | 231 | } |
diff --git a/arch/powerpc/platforms/chrp/pegasos_eth.c b/arch/powerpc/platforms/chrp/pegasos_eth.c index 5bcc58d9a4dd..130ff72d99dd 100644 --- a/arch/powerpc/platforms/chrp/pegasos_eth.c +++ b/arch/powerpc/platforms/chrp/pegasos_eth.c | |||
@@ -58,7 +58,9 @@ static struct resource mv643xx_eth0_resources[] = { | |||
58 | 58 | ||
59 | 59 | ||
60 | static struct mv643xx_eth_platform_data eth0_pd = { | 60 | static struct mv643xx_eth_platform_data eth0_pd = { |
61 | .shared = &mv643xx_eth_shared_device, | ||
61 | .port_number = 0, | 62 | .port_number = 0, |
63 | |||
62 | .tx_sram_addr = PEGASOS2_SRAM_BASE_ETH0, | 64 | .tx_sram_addr = PEGASOS2_SRAM_BASE_ETH0, |
63 | .tx_sram_size = PEGASOS2_SRAM_TXRING_SIZE, | 65 | .tx_sram_size = PEGASOS2_SRAM_TXRING_SIZE, |
64 | .tx_queue_size = PEGASOS2_SRAM_TXRING_SIZE/16, | 66 | .tx_queue_size = PEGASOS2_SRAM_TXRING_SIZE/16, |
@@ -88,7 +90,9 @@ static struct resource mv643xx_eth1_resources[] = { | |||
88 | }; | 90 | }; |
89 | 91 | ||
90 | static struct mv643xx_eth_platform_data eth1_pd = { | 92 | static struct mv643xx_eth_platform_data eth1_pd = { |
93 | .shared = &mv643xx_eth_shared_device, | ||
91 | .port_number = 1, | 94 | .port_number = 1, |
95 | |||
92 | .tx_sram_addr = PEGASOS2_SRAM_BASE_ETH1, | 96 | .tx_sram_addr = PEGASOS2_SRAM_BASE_ETH1, |
93 | .tx_sram_size = PEGASOS2_SRAM_TXRING_SIZE, | 97 | .tx_sram_size = PEGASOS2_SRAM_TXRING_SIZE, |
94 | .tx_queue_size = PEGASOS2_SRAM_TXRING_SIZE/16, | 98 | .tx_queue_size = PEGASOS2_SRAM_TXRING_SIZE/16, |
diff --git a/arch/powerpc/sysdev/mv64x60_dev.c b/arch/powerpc/sysdev/mv64x60_dev.c index 41af1223e2a0..a132e0de8ca5 100644 --- a/arch/powerpc/sysdev/mv64x60_dev.c +++ b/arch/powerpc/sysdev/mv64x60_dev.c | |||
@@ -239,6 +239,8 @@ static int __init mv64x60_eth_device_setup(struct device_node *np, int id, | |||
239 | 239 | ||
240 | memset(&pdata, 0, sizeof(pdata)); | 240 | memset(&pdata, 0, sizeof(pdata)); |
241 | 241 | ||
242 | pdata.shared = shared_pdev; | ||
243 | |||
242 | prop = of_get_property(np, "reg", NULL); | 244 | prop = of_get_property(np, "reg", NULL); |
243 | if (!prop) | 245 | if (!prop) |
244 | return -ENODEV; | 246 | return -ENODEV; |
diff --git a/arch/ppc/syslib/mv64x60.c b/arch/ppc/syslib/mv64x60.c index 90fe904d3614..418f3053de52 100644 --- a/arch/ppc/syslib/mv64x60.c +++ b/arch/ppc/syslib/mv64x60.c | |||
@@ -341,6 +341,7 @@ static struct resource mv64x60_eth0_resources[] = { | |||
341 | }; | 341 | }; |
342 | 342 | ||
343 | static struct mv643xx_eth_platform_data eth0_pd = { | 343 | static struct mv643xx_eth_platform_data eth0_pd = { |
344 | .shared = &mv64x60_eth_shared_device; | ||
344 | .port_number = 0, | 345 | .port_number = 0, |
345 | }; | 346 | }; |
346 | 347 | ||
@@ -366,6 +367,7 @@ static struct resource mv64x60_eth1_resources[] = { | |||
366 | }; | 367 | }; |
367 | 368 | ||
368 | static struct mv643xx_eth_platform_data eth1_pd = { | 369 | static struct mv643xx_eth_platform_data eth1_pd = { |
370 | .shared = &mv64x60_eth_shared_device; | ||
369 | .port_number = 1, | 371 | .port_number = 1, |
370 | }; | 372 | }; |
371 | 373 | ||
@@ -391,6 +393,7 @@ static struct resource mv64x60_eth2_resources[] = { | |||
391 | }; | 393 | }; |
392 | 394 | ||
393 | static struct mv643xx_eth_platform_data eth2_pd = { | 395 | static struct mv643xx_eth_platform_data eth2_pd = { |
396 | .shared = &mv64x60_eth_shared_device; | ||
394 | .port_number = 2, | 397 | .port_number = 2, |
395 | }; | 398 | }; |
396 | 399 | ||
diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index 381b36e5f64c..eebf0d288e36 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c | |||
@@ -507,7 +507,15 @@ struct mv643xx_mib_counters { | |||
507 | u32 late_collision; | 507 | u32 late_collision; |
508 | }; | 508 | }; |
509 | 509 | ||
510 | struct mv643xx_shared_private { | ||
511 | void __iomem *eth_base; | ||
512 | |||
513 | /* used to protect SMI_REG, which is shared across ports */ | ||
514 | spinlock_t phy_lock; | ||
515 | }; | ||
516 | |||
510 | struct mv643xx_private { | 517 | struct mv643xx_private { |
518 | struct mv643xx_shared_private *shared; | ||
511 | int port_num; /* User Ethernet port number */ | 519 | int port_num; /* User Ethernet port number */ |
512 | 520 | ||
513 | u32 rx_sram_addr; /* Base address of rx sram area */ | 521 | u32 rx_sram_addr; /* Base address of rx sram area */ |
@@ -614,19 +622,14 @@ static const struct ethtool_ops mv643xx_ethtool_ops; | |||
614 | static char mv643xx_driver_name[] = "mv643xx_eth"; | 622 | static char mv643xx_driver_name[] = "mv643xx_eth"; |
615 | static char mv643xx_driver_version[] = "1.0"; | 623 | static char mv643xx_driver_version[] = "1.0"; |
616 | 624 | ||
617 | static void __iomem *mv643xx_eth_base; | ||
618 | |||
619 | /* used to protect SMI_REG, which is shared across ports */ | ||
620 | static DEFINE_SPINLOCK(mv643xx_eth_phy_lock); | ||
621 | |||
622 | static inline u32 rdl(struct mv643xx_private *mp, int offset) | 625 | static inline u32 rdl(struct mv643xx_private *mp, int offset) |
623 | { | 626 | { |
624 | return readl(mv643xx_eth_base + offset); | 627 | return readl(mp->shared->eth_base + offset); |
625 | } | 628 | } |
626 | 629 | ||
627 | static inline void wrl(struct mv643xx_private *mp, int offset, u32 data) | 630 | static inline void wrl(struct mv643xx_private *mp, int offset, u32 data) |
628 | { | 631 | { |
629 | writel(data, mv643xx_eth_base + offset); | 632 | writel(data, mp->shared->eth_base + offset); |
630 | } | 633 | } |
631 | 634 | ||
632 | /* | 635 | /* |
@@ -1827,6 +1830,11 @@ static int mv643xx_eth_probe(struct platform_device *pdev) | |||
1827 | return -ENODEV; | 1830 | return -ENODEV; |
1828 | } | 1831 | } |
1829 | 1832 | ||
1833 | if (pd->shared == NULL) { | ||
1834 | printk(KERN_ERR "No mv643xx_eth_platform_data->shared\n"); | ||
1835 | return -ENODEV; | ||
1836 | } | ||
1837 | |||
1830 | dev = alloc_etherdev(sizeof(struct mv643xx_private)); | 1838 | dev = alloc_etherdev(sizeof(struct mv643xx_private)); |
1831 | if (!dev) | 1839 | if (!dev) |
1832 | return -ENOMEM; | 1840 | return -ENOMEM; |
@@ -1877,6 +1885,7 @@ static int mv643xx_eth_probe(struct platform_device *pdev) | |||
1877 | 1885 | ||
1878 | spin_lock_init(&mp->lock); | 1886 | spin_lock_init(&mp->lock); |
1879 | 1887 | ||
1888 | mp->shared = platform_get_drvdata(pd->shared); | ||
1880 | port_num = mp->port_num = pd->port_number; | 1889 | port_num = mp->port_num = pd->port_number; |
1881 | 1890 | ||
1882 | /* set default config values */ | 1891 | /* set default config values */ |
@@ -1986,27 +1995,46 @@ static int mv643xx_eth_remove(struct platform_device *pdev) | |||
1986 | static int mv643xx_eth_shared_probe(struct platform_device *pdev) | 1995 | static int mv643xx_eth_shared_probe(struct platform_device *pdev) |
1987 | { | 1996 | { |
1988 | static int mv643xx_version_printed = 0; | 1997 | static int mv643xx_version_printed = 0; |
1998 | struct mv643xx_shared_private *msp; | ||
1989 | struct resource *res; | 1999 | struct resource *res; |
2000 | int ret; | ||
1990 | 2001 | ||
1991 | if (!mv643xx_version_printed++) | 2002 | if (!mv643xx_version_printed++) |
1992 | printk(KERN_NOTICE "MV-643xx 10/100/1000 Ethernet Driver\n"); | 2003 | printk(KERN_NOTICE "MV-643xx 10/100/1000 Ethernet Driver\n"); |
1993 | 2004 | ||
2005 | ret = -EINVAL; | ||
1994 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 2006 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
1995 | if (res == NULL) | 2007 | if (res == NULL) |
1996 | return -ENODEV; | 2008 | goto out; |
1997 | 2009 | ||
1998 | mv643xx_eth_base = ioremap(res->start, res->end - res->start + 1); | 2010 | ret = -ENOMEM; |
1999 | if (mv643xx_eth_base == NULL) | 2011 | msp = kmalloc(sizeof(*msp), GFP_KERNEL); |
2000 | return -ENOMEM; | 2012 | if (msp == NULL) |
2013 | goto out; | ||
2014 | memset(msp, 0, sizeof(*msp)); | ||
2015 | |||
2016 | msp->eth_base = ioremap(res->start, res->end - res->start + 1); | ||
2017 | if (msp->eth_base == NULL) | ||
2018 | goto out_free; | ||
2019 | |||
2020 | spin_lock_init(&msp->phy_lock); | ||
2021 | |||
2022 | platform_set_drvdata(pdev, msp); | ||
2001 | 2023 | ||
2002 | return 0; | 2024 | return 0; |
2003 | 2025 | ||
2026 | out_free: | ||
2027 | kfree(msp); | ||
2028 | out: | ||
2029 | return ret; | ||
2004 | } | 2030 | } |
2005 | 2031 | ||
2006 | static int mv643xx_eth_shared_remove(struct platform_device *pdev) | 2032 | static int mv643xx_eth_shared_remove(struct platform_device *pdev) |
2007 | { | 2033 | { |
2008 | iounmap(mv643xx_eth_base); | 2034 | struct mv643xx_shared_private *msp = platform_get_drvdata(pdev); |
2009 | mv643xx_eth_base = NULL; | 2035 | |
2036 | iounmap(msp->eth_base); | ||
2037 | kfree(msp); | ||
2010 | 2038 | ||
2011 | return 0; | 2039 | return 0; |
2012 | } | 2040 | } |
@@ -2911,7 +2939,7 @@ static void eth_port_read_smi_reg(struct mv643xx_private *mp, | |||
2911 | int i; | 2939 | int i; |
2912 | 2940 | ||
2913 | /* the SMI register is a shared resource */ | 2941 | /* the SMI register is a shared resource */ |
2914 | spin_lock_irqsave(&mv643xx_eth_phy_lock, flags); | 2942 | spin_lock_irqsave(&mp->shared->phy_lock, flags); |
2915 | 2943 | ||
2916 | /* wait for the SMI register to become available */ | 2944 | /* wait for the SMI register to become available */ |
2917 | for (i = 0; rdl(mp, SMI_REG) & ETH_SMI_BUSY; i++) { | 2945 | for (i = 0; rdl(mp, SMI_REG) & ETH_SMI_BUSY; i++) { |
@@ -2936,7 +2964,7 @@ static void eth_port_read_smi_reg(struct mv643xx_private *mp, | |||
2936 | 2964 | ||
2937 | *value = rdl(mp, SMI_REG) & 0xffff; | 2965 | *value = rdl(mp, SMI_REG) & 0xffff; |
2938 | out: | 2966 | out: |
2939 | spin_unlock_irqrestore(&mv643xx_eth_phy_lock, flags); | 2967 | spin_unlock_irqrestore(&mp->shared->phy_lock, flags); |
2940 | } | 2968 | } |
2941 | 2969 | ||
2942 | /* | 2970 | /* |
@@ -2969,7 +2997,7 @@ static void eth_port_write_smi_reg(struct mv643xx_private *mp, | |||
2969 | phy_addr = ethernet_phy_get(mp); | 2997 | phy_addr = ethernet_phy_get(mp); |
2970 | 2998 | ||
2971 | /* the SMI register is a shared resource */ | 2999 | /* the SMI register is a shared resource */ |
2972 | spin_lock_irqsave(&mv643xx_eth_phy_lock, flags); | 3000 | spin_lock_irqsave(&mp->shared->phy_lock, flags); |
2973 | 3001 | ||
2974 | /* wait for the SMI register to become available */ | 3002 | /* wait for the SMI register to become available */ |
2975 | for (i = 0; rdl(mp, SMI_REG) & ETH_SMI_BUSY; i++) { | 3003 | for (i = 0; rdl(mp, SMI_REG) & ETH_SMI_BUSY; i++) { |
@@ -2983,7 +3011,7 @@ static void eth_port_write_smi_reg(struct mv643xx_private *mp, | |||
2983 | wrl(mp, SMI_REG, (phy_addr << 16) | (phy_reg << 21) | | 3011 | wrl(mp, SMI_REG, (phy_addr << 16) | (phy_reg << 21) | |
2984 | ETH_SMI_OPCODE_WRITE | (value & 0xffff)); | 3012 | ETH_SMI_OPCODE_WRITE | (value & 0xffff)); |
2985 | out: | 3013 | out: |
2986 | spin_unlock_irqrestore(&mv643xx_eth_phy_lock, flags); | 3014 | spin_unlock_irqrestore(&mp->shared->phy_lock, flags); |
2987 | } | 3015 | } |
2988 | 3016 | ||
2989 | /* | 3017 | /* |
diff --git a/include/linux/mv643xx_eth.h b/include/linux/mv643xx_eth.h index 30e11aa3c1c9..2d59855b61c1 100644 --- a/include/linux/mv643xx_eth.h +++ b/include/linux/mv643xx_eth.h | |||
@@ -1,6 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * MV-643XX ethernet platform device data definition file. | 2 | * MV-643XX ethernet platform device data definition file. |
3 | */ | 3 | */ |
4 | |||
4 | #ifndef __LINUX_MV643XX_ETH_H | 5 | #ifndef __LINUX_MV643XX_ETH_H |
5 | #define __LINUX_MV643XX_ETH_H | 6 | #define __LINUX_MV643XX_ETH_H |
6 | 7 | ||
@@ -13,7 +14,9 @@ | |||
13 | #define MV643XX_ETH_BASE_ADDR_ENABLE_REG 0x2290 | 14 | #define MV643XX_ETH_BASE_ADDR_ENABLE_REG 0x2290 |
14 | 15 | ||
15 | struct mv643xx_eth_platform_data { | 16 | struct mv643xx_eth_platform_data { |
17 | struct platform_device *shared; | ||
16 | int port_number; | 18 | int port_number; |
19 | |||
17 | u16 force_phy_addr; /* force override if phy_addr == 0 */ | 20 | u16 force_phy_addr; /* force override if phy_addr == 0 */ |
18 | u16 phy_addr; | 21 | u16 phy_addr; |
19 | 22 | ||