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

phylib: add the ICPlus IP175C PHY driver

The ICPlus IP175C sports a 100Mbit/s 4-port switch in addition
to a dedicated 100Mbit/s WAN port.

Signed-off-by: Michael Barkowski <michael.barkowski@freescale.com>
Signed-off-by: Kim Phillips <kim.phillips@freescale.com>
Signed-off-by: Jeff Garzik <jeff@garzik.org>

authored by

Michael Barkowski and committed by
Jeff Garzik
0cefeeba 146bd683

+140
+5
drivers/net/phy/Kconfig
··· 55 55 ---help--- 56 56 Currently supports the BCM5411, BCM5421 and BCM5461 PHYs. 57 57 58 + config ICPLUS_PHY 59 + tristate "Drivers for ICPlus PHYs" 60 + ---help--- 61 + Currently supports the IP175C PHY. 62 + 58 63 config FIXED_PHY 59 64 tristate "Drivers for PHY emulation on fixed speed/link" 60 65 ---help---
+1
drivers/net/phy/Makefile
··· 11 11 obj-$(CONFIG_SMSC_PHY) += smsc.o 12 12 obj-$(CONFIG_VITESSE_PHY) += vitesse.o 13 13 obj-$(CONFIG_BROADCOM_PHY) += broadcom.o 14 + obj-$(CONFIG_ICPLUS_PHY) += icplus.o 14 15 obj-$(CONFIG_FIXED_PHY) += fixed.o
+134
drivers/net/phy/icplus.c
··· 1 + /* 2 + * Driver for ICPlus PHYs 3 + * 4 + * Copyright (c) 2007 Freescale Semiconductor, Inc. 5 + * 6 + * This program is free software; you can redistribute it and/or modify it 7 + * under the terms of the GNU General Public License as published by the 8 + * Free Software Foundation; either version 2 of the License, or (at your 9 + * option) any later version. 10 + * 11 + */ 12 + #include <linux/kernel.h> 13 + #include <linux/string.h> 14 + #include <linux/errno.h> 15 + #include <linux/unistd.h> 16 + #include <linux/slab.h> 17 + #include <linux/interrupt.h> 18 + #include <linux/init.h> 19 + #include <linux/delay.h> 20 + #include <linux/netdevice.h> 21 + #include <linux/etherdevice.h> 22 + #include <linux/skbuff.h> 23 + #include <linux/spinlock.h> 24 + #include <linux/mm.h> 25 + #include <linux/module.h> 26 + #include <linux/mii.h> 27 + #include <linux/ethtool.h> 28 + #include <linux/phy.h> 29 + 30 + #include <asm/io.h> 31 + #include <asm/irq.h> 32 + #include <asm/uaccess.h> 33 + 34 + MODULE_DESCRIPTION("ICPlus IP175C PHY driver"); 35 + MODULE_AUTHOR("Michael Barkowski"); 36 + MODULE_LICENSE("GPL"); 37 + 38 + static int ip175c_config_init(struct phy_device *phydev) 39 + { 40 + int err, i; 41 + static int full_reset_performed = 0; 42 + 43 + if (full_reset_performed == 0) { 44 + 45 + /* master reset */ 46 + err = phydev->bus->write(phydev->bus, 30, 0, 0x175c); 47 + if (err < 0) 48 + return err; 49 + 50 + /* ensure no bus delays overlap reset period */ 51 + err = phydev->bus->read(phydev->bus, 30, 0); 52 + 53 + /* data sheet specifies reset period is 2 msec */ 54 + mdelay(2); 55 + 56 + /* enable IP175C mode */ 57 + err = phydev->bus->write(phydev->bus, 29, 31, 0x175c); 58 + if (err < 0) 59 + return err; 60 + 61 + /* Set MII0 speed and duplex (in PHY mode) */ 62 + err = phydev->bus->write(phydev->bus, 29, 22, 0x420); 63 + if (err < 0) 64 + return err; 65 + 66 + /* reset switch ports */ 67 + for (i = 0; i < 5; i++) { 68 + err = phydev->bus->write(phydev->bus, i, 69 + MII_BMCR, BMCR_RESET); 70 + if (err < 0) 71 + return err; 72 + } 73 + 74 + for (i = 0; i < 5; i++) 75 + err = phydev->bus->read(phydev->bus, i, MII_BMCR); 76 + 77 + mdelay(2); 78 + 79 + full_reset_performed = 1; 80 + } 81 + 82 + if (phydev->addr != 4) { 83 + phydev->state = PHY_RUNNING; 84 + phydev->speed = SPEED_100; 85 + phydev->duplex = DUPLEX_FULL; 86 + phydev->link = 1; 87 + netif_carrier_on(phydev->attached_dev); 88 + } 89 + 90 + return 0; 91 + } 92 + 93 + static int ip175c_read_status(struct phy_device *phydev) 94 + { 95 + if (phydev->addr == 4) /* WAN port */ 96 + genphy_read_status(phydev); 97 + else 98 + /* Don't need to read status for switch ports */ 99 + phydev->irq = PHY_IGNORE_INTERRUPT; 100 + 101 + return 0; 102 + } 103 + 104 + static int ip175c_config_aneg(struct phy_device *phydev) 105 + { 106 + if (phydev->addr == 4) /* WAN port */ 107 + genphy_config_aneg(phydev); 108 + 109 + return 0; 110 + } 111 + 112 + static struct phy_driver ip175c_driver = { 113 + .phy_id = 0x02430d80, 114 + .name = "ICPlus IP175C", 115 + .phy_id_mask = 0x0ffffff0, 116 + .features = PHY_BASIC_FEATURES, 117 + .config_init = &ip175c_config_init, 118 + .config_aneg = &ip175c_config_aneg, 119 + .read_status = &ip175c_read_status, 120 + .driver = { .owner = THIS_MODULE,}, 121 + }; 122 + 123 + static int __init ip175c_init(void) 124 + { 125 + return phy_driver_register(&ip175c_driver); 126 + } 127 + 128 + static void __exit ip175c_exit(void) 129 + { 130 + phy_driver_unregister(&ip175c_driver); 131 + } 132 + 133 + module_init(ip175c_init); 134 + module_exit(ip175c_exit);