aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/mv643xx_eth.c
diff options
context:
space:
mode:
authorLennert Buytenhek <buytenh@wantstofly.org>2008-08-25 22:42:59 -0400
committerLennert Buytenhek <buytenh@marvell.com>2008-09-05 00:33:58 -0400
commit45c5d3bc1eae7a1d91b12dbee6443109337ec8c3 (patch)
tree397efc108f01e782abfdced8336c1322a71ffa87 /drivers/net/mv643xx_eth.c
parent2b3ba0e3ea3aa9383d38cf95fabd24ca35483784 (diff)
mv643xx_eth: use the SMI done interrupt to wait for SMI access completion
If the platform code has passed us the IRQ number of the mv643xx_eth top-level error interrupt, use the error interrupt to wait for SMI access completion instead of polling the SMI busy bit, since SMI bus accesses can take up to tens of milliseconds. Signed-off-by: Lennert Buytenhek <buytenh@marvell.com>
Diffstat (limited to 'drivers/net/mv643xx_eth.c')
-rw-r--r--drivers/net/mv643xx_eth.c191
1 files changed, 134 insertions, 57 deletions
diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c
index 2d434017a670..b41860dc5b5e 100644
--- a/drivers/net/mv643xx_eth.c
+++ b/drivers/net/mv643xx_eth.c
@@ -72,6 +72,13 @@ static char mv643xx_eth_driver_version[] = "1.3";
72 */ 72 */
73#define PHY_ADDR 0x0000 73#define PHY_ADDR 0x0000
74#define SMI_REG 0x0004 74#define SMI_REG 0x0004
75#define SMI_BUSY 0x10000000
76#define SMI_READ_VALID 0x08000000
77#define SMI_OPCODE_READ 0x04000000
78#define SMI_OPCODE_WRITE 0x00000000
79#define ERR_INT_CAUSE 0x0080
80#define ERR_INT_SMI_DONE 0x00000010
81#define ERR_INT_MASK 0x0084
75#define WINDOW_BASE(w) (0x0200 + ((w) << 3)) 82#define WINDOW_BASE(w) (0x0200 + ((w) << 3))
76#define WINDOW_SIZE(w) (0x0204 + ((w) << 3)) 83#define WINDOW_SIZE(w) (0x0204 + ((w) << 3))
77#define WINDOW_REMAP_HIGH(w) (0x0280 + ((w) << 2)) 84#define WINDOW_REMAP_HIGH(w) (0x0280 + ((w) << 2))
@@ -254,6 +261,15 @@ struct mv643xx_eth_shared_private {
254 struct mutex phy_lock; 261 struct mutex phy_lock;
255 262
256 /* 263 /*
264 * If we have access to the error interrupt pin (which is
265 * somewhat misnamed as it not only reflects internal errors
266 * but also reflects SMI completion), use that to wait for
267 * SMI access completion instead of polling the SMI busy bit.
268 */
269 int err_interrupt;
270 wait_queue_head_t smi_busy_wait;
271
272 /*
257 * Per-port MBUS window access register value. 273 * Per-port MBUS window access register value.
258 */ 274 */
259 u32 win_protect; 275 u32 win_protect;
@@ -979,68 +995,103 @@ static void txq_set_wrr(struct tx_queue *txq, int weight)
979 995
980 996
981/* mii management interface *************************************************/ 997/* mii management interface *************************************************/
982#define SMI_BUSY 0x10000000 998static irqreturn_t mv643xx_eth_err_irq(int irq, void *dev_id)
983#define SMI_READ_VALID 0x08000000 999{
984#define SMI_OPCODE_READ 0x04000000 1000 struct mv643xx_eth_shared_private *msp = dev_id;
985#define SMI_OPCODE_WRITE 0x00000000
986 1001
987static void smi_reg_read(struct mv643xx_eth_private *mp, unsigned int addr, 1002 if (readl(msp->base + ERR_INT_CAUSE) & ERR_INT_SMI_DONE) {
988 unsigned int reg, unsigned int *value) 1003 writel(~ERR_INT_SMI_DONE, msp->base + ERR_INT_CAUSE);
1004 wake_up(&msp->smi_busy_wait);
1005 return IRQ_HANDLED;
1006 }
1007
1008 return IRQ_NONE;
1009}
1010
1011static int smi_is_done(struct mv643xx_eth_shared_private *msp)
989{ 1012{
990 void __iomem *smi_reg = mp->shared_smi->base + SMI_REG; 1013 return !(readl(msp->base + SMI_REG) & SMI_BUSY);
991 int i; 1014}
992 1015
993 /* the SMI register is a shared resource */ 1016static int smi_wait_ready(struct mv643xx_eth_shared_private *msp)
994 mutex_lock(&mp->shared_smi->phy_lock); 1017{
1018 if (msp->err_interrupt == NO_IRQ) {
1019 int i;
995 1020
996 /* wait for the SMI register to become available */ 1021 for (i = 0; !smi_is_done(msp); i++) {
997 for (i = 0; readl(smi_reg) & SMI_BUSY; i++) { 1022 if (i == 10)
998 if (i == 1000) { 1023 return -ETIMEDOUT;
999 printk("%s: PHY busy timeout\n", mp->dev->name); 1024 msleep(10);
1000 goto out;
1001 } 1025 }
1002 udelay(10); 1026
1027 return 0;
1028 }
1029
1030 if (!wait_event_timeout(msp->smi_busy_wait, smi_is_done(msp),
1031 msecs_to_jiffies(100)))
1032 return -ETIMEDOUT;
1033
1034 return 0;
1035}
1036
1037static int smi_reg_read(struct mv643xx_eth_private *mp,
1038 unsigned int addr, unsigned int reg)
1039{
1040 struct mv643xx_eth_shared_private *msp = mp->shared_smi;
1041 void __iomem *smi_reg = msp->base + SMI_REG;
1042 int ret;
1043
1044 mutex_lock(&msp->phy_lock);
1045
1046 if (smi_wait_ready(msp)) {
1047 printk("%s: SMI bus busy timeout\n", mp->dev->name);
1048 ret = -ETIMEDOUT;
1049 goto out;
1003 } 1050 }
1004 1051
1005 writel(SMI_OPCODE_READ | (reg << 21) | (addr << 16), smi_reg); 1052 writel(SMI_OPCODE_READ | (reg << 21) | (addr << 16), smi_reg);
1006 1053
1007 /* now wait for the data to be valid */ 1054 if (smi_wait_ready(msp)) {
1008 for (i = 0; !(readl(smi_reg) & SMI_READ_VALID); i++) { 1055 printk("%s: SMI bus busy timeout\n", mp->dev->name);
1009 if (i == 1000) { 1056 ret = -ETIMEDOUT;
1010 printk("%s: PHY read timeout\n", mp->dev->name); 1057 goto out;
1011 goto out;
1012 }
1013 udelay(10);
1014 } 1058 }
1015 1059
1016 *value = readl(smi_reg) & 0xffff; 1060 ret = readl(smi_reg);
1061 if (!(ret & SMI_READ_VALID)) {
1062 printk("%s: SMI bus read not valid\n", mp->dev->name);
1063 ret = -ENODEV;
1064 goto out;
1065 }
1066
1067 ret &= 0xffff;
1068
1017out: 1069out:
1018 mutex_unlock(&mp->shared_smi->phy_lock); 1070 mutex_unlock(&msp->phy_lock);
1071
1072 return ret;
1019} 1073}
1020 1074
1021static void smi_reg_write(struct mv643xx_eth_private *mp, 1075static int smi_reg_write(struct mv643xx_eth_private *mp, unsigned int addr,
1022 unsigned int addr, 1076 unsigned int reg, unsigned int value)
1023 unsigned int reg, unsigned int value)
1024{ 1077{
1025 void __iomem *smi_reg = mp->shared_smi->base + SMI_REG; 1078 struct mv643xx_eth_shared_private *msp = mp->shared_smi;
1026 int i; 1079 void __iomem *smi_reg = msp->base + SMI_REG;
1027 1080
1028 /* the SMI register is a shared resource */ 1081 mutex_lock(&msp->phy_lock);
1029 mutex_lock(&mp->shared_smi->phy_lock);
1030 1082
1031 /* wait for the SMI register to become available */ 1083 if (smi_wait_ready(msp)) {
1032 for (i = 0; readl(smi_reg) & SMI_BUSY; i++) { 1084 printk("%s: SMI bus busy timeout\n", mp->dev->name);
1033 if (i == 1000) { 1085 mutex_unlock(&msp->phy_lock);
1034 printk("%s: PHY busy timeout\n", mp->dev->name); 1086 return -ETIMEDOUT;
1035 goto out;
1036 }
1037 udelay(10);
1038 } 1087 }
1039 1088
1040 writel(SMI_OPCODE_WRITE | (reg << 21) | 1089 writel(SMI_OPCODE_WRITE | (reg << 21) |
1041 (addr << 16) | (value & 0xffff), smi_reg); 1090 (addr << 16) | (value & 0xffff), smi_reg);
1042out: 1091
1043 mutex_unlock(&mp->shared_smi->phy_lock); 1092 mutex_unlock(&msp->phy_lock);
1093
1094 return 0;
1044} 1095}
1045 1096
1046 1097
@@ -1877,16 +1928,19 @@ static irqreturn_t mv643xx_eth_irq(int irq, void *dev_id)
1877 1928
1878static void phy_reset(struct mv643xx_eth_private *mp) 1929static void phy_reset(struct mv643xx_eth_private *mp)
1879{ 1930{
1880 unsigned int data; 1931 int data;
1932
1933 data = smi_reg_read(mp, mp->phy_addr, MII_BMCR);
1934 if (data < 0)
1935 return;
1881 1936
1882 smi_reg_read(mp, mp->phy_addr, MII_BMCR, &data);
1883 data |= BMCR_RESET; 1937 data |= BMCR_RESET;
1884 smi_reg_write(mp, mp->phy_addr, MII_BMCR, data); 1938 if (smi_reg_write(mp, mp->phy_addr, MII_BMCR, data) < 0)
1939 return;
1885 1940
1886 do { 1941 do {
1887 udelay(1); 1942 data = smi_reg_read(mp, mp->phy_addr, MII_BMCR);
1888 smi_reg_read(mp, mp->phy_addr, MII_BMCR, &data); 1943 } while (data >= 0 && data & BMCR_RESET);
1889 } while (data & BMCR_RESET);
1890} 1944}
1891 1945
1892static void port_start(struct mv643xx_eth_private *mp) 1946static void port_start(struct mv643xx_eth_private *mp)
@@ -2214,11 +2268,7 @@ static void mv643xx_eth_netpoll(struct net_device *dev)
2214static int mv643xx_eth_mdio_read(struct net_device *dev, int addr, int reg) 2268static int mv643xx_eth_mdio_read(struct net_device *dev, int addr, int reg)
2215{ 2269{
2216 struct mv643xx_eth_private *mp = netdev_priv(dev); 2270 struct mv643xx_eth_private *mp = netdev_priv(dev);
2217 int val; 2271 return smi_reg_read(mp, addr, reg);
2218
2219 smi_reg_read(mp, addr, reg, &val);
2220
2221 return val;
2222} 2272}
2223 2273
2224static void mv643xx_eth_mdio_write(struct net_device *dev, int addr, int reg, int val) 2274static void mv643xx_eth_mdio_write(struct net_device *dev, int addr, int reg, int val)
@@ -2317,6 +2367,24 @@ static int mv643xx_eth_shared_probe(struct platform_device *pdev)
2317 2367
2318 mutex_init(&msp->phy_lock); 2368 mutex_init(&msp->phy_lock);
2319 2369
2370 msp->err_interrupt = NO_IRQ;
2371 init_waitqueue_head(&msp->smi_busy_wait);
2372
2373 /*
2374 * Check whether the error interrupt is hooked up.
2375 */
2376 res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
2377 if (res != NULL) {
2378 int err;
2379
2380 err = request_irq(res->start, mv643xx_eth_err_irq,
2381 IRQF_SHARED, "mv643xx_eth", msp);
2382 if (!err) {
2383 writel(ERR_INT_SMI_DONE, msp->base + ERR_INT_MASK);
2384 msp->err_interrupt = res->start;
2385 }
2386 }
2387
2320 /* 2388 /*
2321 * (Re-)program MBUS remapping windows if we are asked to. 2389 * (Re-)program MBUS remapping windows if we are asked to.
2322 */ 2390 */
@@ -2343,6 +2411,8 @@ static int mv643xx_eth_shared_remove(struct platform_device *pdev)
2343{ 2411{
2344 struct mv643xx_eth_shared_private *msp = platform_get_drvdata(pdev); 2412 struct mv643xx_eth_shared_private *msp = platform_get_drvdata(pdev);
2345 2413
2414 if (msp->err_interrupt != NO_IRQ)
2415 free_irq(msp->err_interrupt, msp);
2346 iounmap(msp->base); 2416 iounmap(msp->base);
2347 kfree(msp); 2417 kfree(msp);
2348 2418
@@ -2431,13 +2501,20 @@ static void set_params(struct mv643xx_eth_private *mp,
2431 2501
2432static int phy_detect(struct mv643xx_eth_private *mp) 2502static int phy_detect(struct mv643xx_eth_private *mp)
2433{ 2503{
2434 unsigned int data; 2504 int data;
2435 unsigned int data2; 2505 int data2;
2506
2507 data = smi_reg_read(mp, mp->phy_addr, MII_BMCR);
2508 if (data < 0)
2509 return -ENODEV;
2510
2511 if (smi_reg_write(mp, mp->phy_addr, MII_BMCR, data ^ BMCR_ANENABLE) < 0)
2512 return -ENODEV;
2436 2513
2437 smi_reg_read(mp, mp->phy_addr, MII_BMCR, &data); 2514 data2 = smi_reg_read(mp, mp->phy_addr, MII_BMCR);
2438 smi_reg_write(mp, mp->phy_addr, MII_BMCR, data ^ BMCR_ANENABLE); 2515 if (data2 < 0)
2516 return -ENODEV;
2439 2517
2440 smi_reg_read(mp, mp->phy_addr, MII_BMCR, &data2);
2441 if (((data ^ data2) & BMCR_ANENABLE) == 0) 2518 if (((data ^ data2) & BMCR_ANENABLE) == 0)
2442 return -ENODEV; 2519 return -ENODEV;
2443 2520