aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/mv643xx_eth.c
diff options
context:
space:
mode:
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