Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

IXP4xx: Add PHYLIB support to Ethernet driver.

Signed-off-by: Krzysztof Hałasa <khc@pm.waw.pl>

+100 -104
+1 -1
drivers/net/arm/Kconfig
··· 59 59 config IXP4XX_ETH 60 60 tristate "Intel IXP4xx Ethernet support" 61 61 depends on ARM && ARCH_IXP4XX && IXP4XX_NPE && IXP4XX_QMGR 62 - select MII 62 + select PHYLIB 63 63 help 64 64 Say Y here if you want to use built-in Ethernet ports 65 65 on IXP4xx processor.
+99 -103
drivers/net/arm/ixp4xx_eth.c
··· 30 30 #include <linux/etherdevice.h> 31 31 #include <linux/io.h> 32 32 #include <linux/kernel.h> 33 - #include <linux/mii.h> 33 + #include <linux/phy.h> 34 34 #include <linux/platform_device.h> 35 35 #include <mach/npe.h> 36 36 #include <mach/qmgr.h> ··· 59 59 #define NAPI_WEIGHT 16 60 60 #define MDIO_INTERVAL (3 * HZ) 61 61 #define MAX_MDIO_RETRIES 100 /* microseconds, typically 30 cycles */ 62 - #define MAX_MII_RESET_RETRIES 100 /* mdio_read() cycles, typically 4 */ 63 62 #define MAX_CLOSE_WAIT 1000 /* microseconds, typically 2-3 cycles */ 64 63 65 64 #define NPE_ID(port_id) ((port_id) >> 4) ··· 163 164 struct npe *npe; 164 165 struct net_device *netdev; 165 166 struct napi_struct napi; 166 - struct mii_if_info mii; 167 - struct delayed_work mdio_thread; 167 + struct phy_device *phydev; 168 168 struct eth_plat_info *plat; 169 169 buffer_t *rx_buff_tab[RX_DESCS], *tx_buff_tab[TX_DESCS]; 170 170 struct desc *desc_tab; /* coherent */ 171 171 u32 desc_tab_phys; 172 172 int id; /* logical port ID */ 173 - u16 mii_bmcr; 173 + int speed, duplex; 174 174 }; 175 175 176 176 /* NPE message structure */ ··· 240 242 241 243 static spinlock_t mdio_lock; 242 244 static struct eth_regs __iomem *mdio_regs; /* mdio command and status only */ 245 + struct mii_bus *mdio_bus; 243 246 static int ports_open; 244 247 static struct port *npe_port_tab[MAX_NPES]; 245 248 static struct dma_pool *dma_pool; 246 249 247 250 248 - static u16 mdio_cmd(struct net_device *dev, int phy_id, int location, 249 - int write, u16 cmd) 251 + static int ixp4xx_mdio_cmd(struct mii_bus *bus, int phy_id, int location, 252 + int write, u16 cmd) 250 253 { 251 254 int cycles = 0; 252 255 253 256 if (__raw_readl(&mdio_regs->mdio_command[3]) & 0x80) { 254 - printk(KERN_ERR "%s: MII not ready to transmit\n", dev->name); 255 - return 0; 257 + printk(KERN_ERR "%s: MII not ready to transmit\n", bus->name); 258 + return -1; 256 259 } 257 260 258 261 if (write) { ··· 272 273 } 273 274 274 275 if (cycles == MAX_MDIO_RETRIES) { 275 - printk(KERN_ERR "%s: MII write failed\n", dev->name); 276 - return 0; 276 + printk(KERN_ERR "%s #%i: MII write failed\n", bus->name, 277 + phy_id); 278 + return -1; 277 279 } 278 280 279 281 #if DEBUG_MDIO 280 - printk(KERN_DEBUG "%s: mdio_cmd() took %i cycles\n", dev->name, 281 - cycles); 282 + printk(KERN_DEBUG "%s #%i: mdio_%s() took %i cycles\n", bus->name, 283 + phy_id, write ? "write" : "read", cycles); 282 284 #endif 283 285 284 286 if (write) 285 287 return 0; 286 288 287 289 if (__raw_readl(&mdio_regs->mdio_status[3]) & 0x80) { 288 - printk(KERN_ERR "%s: MII read failed\n", dev->name); 289 - return 0; 290 + #if DEBUG_MDIO 291 + printk(KERN_DEBUG "%s #%i: MII read failed\n", bus->name, 292 + phy_id); 293 + #endif 294 + return 0xFFFF; /* don't return error */ 290 295 } 291 296 292 297 return (__raw_readl(&mdio_regs->mdio_status[0]) & 0xFF) | 293 - (__raw_readl(&mdio_regs->mdio_status[1]) << 8); 298 + ((__raw_readl(&mdio_regs->mdio_status[1]) & 0xFF) << 8); 294 299 } 295 300 296 - static int mdio_read(struct net_device *dev, int phy_id, int location) 301 + static int ixp4xx_mdio_read(struct mii_bus *bus, int phy_id, int location) 297 302 { 298 303 unsigned long flags; 299 - u16 val; 304 + int ret; 300 305 301 306 spin_lock_irqsave(&mdio_lock, flags); 302 - val = mdio_cmd(dev, phy_id, location, 0, 0); 307 + ret = ixp4xx_mdio_cmd(bus, phy_id, location, 0, 0); 303 308 spin_unlock_irqrestore(&mdio_lock, flags); 304 - return val; 309 + #if DEBUG_MDIO 310 + printk(KERN_DEBUG "%s #%i: MII read [%i] -> 0x%X\n", bus->name, 311 + phy_id, location, ret); 312 + #endif 313 + return ret; 305 314 } 306 315 307 - static void mdio_write(struct net_device *dev, int phy_id, int location, 308 - int val) 316 + static int ixp4xx_mdio_write(struct mii_bus *bus, int phy_id, int location, 317 + u16 val) 309 318 { 310 319 unsigned long flags; 320 + int ret; 311 321 312 322 spin_lock_irqsave(&mdio_lock, flags); 313 - mdio_cmd(dev, phy_id, location, 1, val); 323 + ret = ixp4xx_mdio_cmd(bus, phy_id, location, 1, val); 314 324 spin_unlock_irqrestore(&mdio_lock, flags); 325 + #if DEBUG_MDIO 326 + printk(KERN_DEBUG "%s #%i: MII read [%i] <- 0x%X, err = %i\n", 327 + bus->name, phy_id, location, val, ret); 328 + #endif 329 + return ret; 315 330 } 316 331 317 - static void phy_reset(struct net_device *dev, int phy_id) 332 + static int ixp4xx_mdio_register(void) 333 + { 334 + int err; 335 + 336 + if (!(mdio_bus = mdiobus_alloc())) 337 + return -ENOMEM; 338 + 339 + /* All MII PHY accesses use NPE-B Ethernet registers */ 340 + spin_lock_init(&mdio_lock); 341 + mdio_regs = (struct eth_regs __iomem *)IXP4XX_EthB_BASE_VIRT; 342 + __raw_writel(DEFAULT_CORE_CNTRL, &mdio_regs->core_control); 343 + 344 + mdio_bus->name = "IXP4xx MII Bus"; 345 + mdio_bus->read = &ixp4xx_mdio_read; 346 + mdio_bus->write = &ixp4xx_mdio_write; 347 + strcpy(mdio_bus->id, "0"); 348 + 349 + if ((err = mdiobus_register(mdio_bus))) 350 + mdiobus_free(mdio_bus); 351 + return err; 352 + } 353 + 354 + static void ixp4xx_mdio_remove(void) 355 + { 356 + mdiobus_unregister(mdio_bus); 357 + mdiobus_free(mdio_bus); 358 + } 359 + 360 + 361 + static void ixp4xx_adjust_link(struct net_device *dev) 318 362 { 319 363 struct port *port = netdev_priv(dev); 320 - int cycles = 0; 364 + struct phy_device *phydev = port->phydev; 321 365 322 - mdio_write(dev, phy_id, MII_BMCR, port->mii_bmcr | BMCR_RESET); 323 - 324 - while (cycles < MAX_MII_RESET_RETRIES) { 325 - if (!(mdio_read(dev, phy_id, MII_BMCR) & BMCR_RESET)) { 326 - #if DEBUG_MDIO 327 - printk(KERN_DEBUG "%s: phy_reset() took %i cycles\n", 328 - dev->name, cycles); 329 - #endif 330 - return; 366 + if (!phydev->link) { 367 + if (port->speed) { 368 + port->speed = 0; 369 + printk(KERN_INFO "%s: link down\n", dev->name); 331 370 } 332 - udelay(1); 333 - cycles++; 371 + return; 334 372 } 335 373 336 - printk(KERN_ERR "%s: MII reset failed\n", dev->name); 337 - } 374 + if (port->speed == phydev->speed && port->duplex == phydev->duplex) 375 + return; 338 376 339 - static void eth_set_duplex(struct port *port) 340 - { 341 - if (port->mii.full_duplex) 377 + port->speed = phydev->speed; 378 + port->duplex = phydev->duplex; 379 + 380 + if (port->duplex) 342 381 __raw_writel(DEFAULT_TX_CNTRL0 & ~TX_CNTRL0_HALFDUPLEX, 343 382 &port->regs->tx_control[0]); 344 383 else 345 384 __raw_writel(DEFAULT_TX_CNTRL0 | TX_CNTRL0_HALFDUPLEX, 346 385 &port->regs->tx_control[0]); 347 - } 348 386 349 - 350 - static void phy_check_media(struct port *port, int init) 351 - { 352 - if (mii_check_media(&port->mii, 1, init)) 353 - eth_set_duplex(port); 354 - if (port->mii.force_media) { /* mii_check_media() doesn't work */ 355 - struct net_device *dev = port->netdev; 356 - int cur_link = mii_link_ok(&port->mii); 357 - int prev_link = netif_carrier_ok(dev); 358 - 359 - if (!prev_link && cur_link) { 360 - printk(KERN_INFO "%s: link up\n", dev->name); 361 - netif_carrier_on(dev); 362 - } else if (prev_link && !cur_link) { 363 - printk(KERN_INFO "%s: link down\n", dev->name); 364 - netif_carrier_off(dev); 365 - } 366 - } 367 - } 368 - 369 - 370 - static void mdio_thread(struct work_struct *work) 371 - { 372 - struct port *port = container_of(work, struct port, mdio_thread.work); 373 - 374 - phy_check_media(port, 0); 375 - schedule_delayed_work(&port->mdio_thread, MDIO_INTERVAL); 387 + printk(KERN_INFO "%s: link up, speed %u Mb/s, %s duplex\n", 388 + dev->name, port->speed, port->duplex ? "full" : "half"); 376 389 } 377 390 378 391 ··· 788 777 789 778 static int eth_ioctl(struct net_device *dev, struct ifreq *req, int cmd) 790 779 { 791 - struct port *port = netdev_priv(dev); 792 - unsigned int duplex_chg; 793 - int err; 794 - 795 780 if (!netif_running(dev)) 796 781 return -EINVAL; 797 - err = generic_mii_ioctl(&port->mii, if_mii(req), cmd, &duplex_chg); 798 - if (duplex_chg) 799 - eth_set_duplex(port); 800 - return err; 782 + return -EINVAL; 801 783 } 802 784 803 785 ··· 942 938 } 943 939 } 944 940 945 - mdio_write(dev, port->plat->phy, MII_BMCR, port->mii_bmcr); 946 - 947 941 memset(&msg, 0, sizeof(msg)); 948 942 msg.cmd = NPE_VLAN_SETRXQOSENTRY; 949 943 msg.eth_id = port->id; ··· 979 977 return err; 980 978 } 981 979 980 + port->speed = 0; /* force "link up" message */ 981 + phy_start(port->phydev); 982 + 982 983 for (i = 0; i < ETH_ALEN; i++) 983 984 __raw_writel(dev->dev_addr[i], &port->regs->hw_addr[i]); 984 985 __raw_writel(0x08, &port->regs->random_seed); ··· 1009 1004 __raw_writel(DEFAULT_RX_CNTRL0, &port->regs->rx_control[0]); 1010 1005 1011 1006 napi_enable(&port->napi); 1012 - phy_check_media(port, 1); 1013 1007 eth_set_mcast_list(dev); 1014 1008 netif_start_queue(dev); 1015 - schedule_delayed_work(&port->mdio_thread, MDIO_INTERVAL); 1016 1009 1017 1010 qmgr_set_irq(port->plat->rxq, QUEUE_IRQ_SRC_NOT_EMPTY, 1018 1011 eth_rx_irq, dev); ··· 1101 1098 printk(KERN_CRIT "%s: unable to disable loopback\n", 1102 1099 dev->name); 1103 1100 1104 - port->mii_bmcr = mdio_read(dev, port->plat->phy, MII_BMCR) & 1105 - ~(BMCR_RESET | BMCR_PDOWN); /* may have been altered */ 1106 - mdio_write(dev, port->plat->phy, MII_BMCR, 1107 - port->mii_bmcr | BMCR_PDOWN); 1101 + phy_stop(port->phydev); 1108 1102 1109 1103 if (!ports_open) 1110 1104 qmgr_disable_irq(TXDONE_QUEUE); 1111 - cancel_rearming_delayed_work(&port->mdio_thread); 1112 1105 destroy_queues(port); 1113 1106 release_queues(port); 1114 1107 return 0; ··· 1116 1117 struct net_device *dev; 1117 1118 struct eth_plat_info *plat = pdev->dev.platform_data; 1118 1119 u32 regs_phys; 1120 + char phy_id[BUS_ID_SIZE]; 1119 1121 int err; 1120 1122 1121 1123 if (!(dev = alloc_etherdev(sizeof(struct port)))) ··· 1182 1182 __raw_writel(DEFAULT_CORE_CNTRL, &port->regs->core_control); 1183 1183 udelay(50); 1184 1184 1185 - port->mii.dev = dev; 1186 - port->mii.mdio_read = mdio_read; 1187 - port->mii.mdio_write = mdio_write; 1188 - port->mii.phy_id = plat->phy; 1189 - port->mii.phy_id_mask = 0x1F; 1190 - port->mii.reg_num_mask = 0x1F; 1185 + snprintf(phy_id, BUS_ID_SIZE, PHY_ID_FMT, "0", plat->phy); 1186 + port->phydev = phy_connect(dev, phy_id, &ixp4xx_adjust_link, 0, 1187 + PHY_INTERFACE_MODE_MII); 1188 + if (IS_ERR(port->phydev)) { 1189 + printk(KERN_ERR "%s: Could not attach to PHY\n", dev->name); 1190 + return PTR_ERR(port->phydev); 1191 + } 1192 + 1193 + port->phydev->irq = PHY_POLL; 1191 1194 1192 1195 printk(KERN_INFO "%s: MII PHY %i on %s\n", dev->name, plat->phy, 1193 1196 npe_name(port->npe)); 1194 1197 1195 - phy_reset(dev, plat->phy); 1196 - port->mii_bmcr = mdio_read(dev, plat->phy, MII_BMCR) & 1197 - ~(BMCR_RESET | BMCR_PDOWN); 1198 - mdio_write(dev, plat->phy, MII_BMCR, port->mii_bmcr | BMCR_PDOWN); 1199 - 1200 - INIT_DELAYED_WORK(&port->mdio_thread, mdio_thread); 1201 1198 return 0; 1202 1199 1203 1200 err_unreg: ··· 1228 1231 1229 1232 static int __init eth_init_module(void) 1230 1233 { 1234 + int err; 1231 1235 if (!(ixp4xx_read_feature_bits() & IXP4XX_FEATURE_NPEB_ETH0)) 1232 1236 return -ENOSYS; 1233 1237 1234 - /* All MII PHY accesses use NPE-B Ethernet registers */ 1235 - spin_lock_init(&mdio_lock); 1236 - mdio_regs = (struct eth_regs __iomem *)IXP4XX_EthB_BASE_VIRT; 1237 - __raw_writel(DEFAULT_CORE_CNTRL, &mdio_regs->core_control); 1238 - 1238 + if ((err = ixp4xx_mdio_register())) 1239 + return err; 1239 1240 return platform_driver_register(&ixp4xx_eth_driver); 1240 1241 } 1241 1242 1242 1243 static void __exit eth_cleanup_module(void) 1243 1244 { 1244 1245 platform_driver_unregister(&ixp4xx_eth_driver); 1246 + ixp4xx_mdio_remove(); 1245 1247 } 1246 1248 1247 1249 MODULE_AUTHOR("Krzysztof Halasa");