2 * drivers/net/phy/fixed.c
4 * Driver for fixed PHYs, when transceiver is able to operate in one fixed mode.
6 * Author: Vitaly Bordug
8 * Copyright (c) 2006 MontaVista Software, Inc.
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by the
12 * Free Software Foundation; either version 2 of the License, or (at your
13 * option) any later version.
16 #include <linux/config.h>
17 #include <linux/kernel.h>
18 #include <linux/sched.h>
19 #include <linux/string.h>
20 #include <linux/errno.h>
21 #include <linux/unistd.h>
22 #include <linux/slab.h>
23 #include <linux/interrupt.h>
24 #include <linux/init.h>
25 #include <linux/delay.h>
26 #include <linux/netdevice.h>
27 #include <linux/etherdevice.h>
28 #include <linux/skbuff.h>
29 #include <linux/spinlock.h>
31 #include <linux/module.h>
32 #include <linux/mii.h>
33 #include <linux/ethtool.h>
34 #include <linux/phy.h>
38 #include <asm/uaccess.h>
40 #define MII_REGS_NUM 7
43 The idea is to emulate normal phy behavior by responding with
44 pre-defined values to mii BMCR read, so that read_status hook could
45 take all the needed info.
48 struct fixed_phy_status {
54 /*-----------------------------------------------------------------------------
55 * Private information hoder for mii_bus
56 *-----------------------------------------------------------------------------*/
60 struct fixed_phy_status phy_status;
61 struct phy_device *phydev; /* pointer to the container */
63 int(*link_update)(struct net_device*, struct fixed_phy_status*);
67 /*-----------------------------------------------------------------------------
68 * If something weird is required to be done with link/speed,
69 * network driver is able to assign a function to implement this.
70 * May be useful for PHY's that need to be software-driven.
71 *-----------------------------------------------------------------------------*/
72 int fixed_mdio_set_link_update(struct phy_device* phydev,
73 int(*link_update)(struct net_device*, struct fixed_phy_status*))
75 struct fixed_info *fixed;
77 if(link_update == NULL)
82 fixed = phydev->bus->priv;
83 fixed->link_update = link_update;
89 EXPORT_SYMBOL(fixed_mdio_set_link_update);
91 /*-----------------------------------------------------------------------------
92 * This is used for updating internal mii regs from the status
93 *-----------------------------------------------------------------------------*/
94 static int fixed_mdio_update_regs(struct fixed_info *fixed)
96 u16 *regs = fixed->regs;
101 printk(KERN_ERR "%s: regs not set up", __FUNCTION__);
105 if(fixed->phy_status.link)
106 bmsr |= BMSR_LSTATUS;
108 if(fixed->phy_status.duplex) {
109 bmcr |= BMCR_FULLDPLX;
111 switch ( fixed->phy_status.speed ) {
113 bmsr |= BMSR_100FULL;
114 bmcr |= BMCR_SPEED100;
122 switch ( fixed->phy_status.speed ) {
124 bmsr |= BMSR_100HALF;
125 bmcr |= BMCR_SPEED100;
129 bmsr |= BMSR_100HALF;
134 regs[MII_BMCR] = bmcr;
135 regs[MII_BMSR] = bmsr | 0x800; /*we are always capable of 10 hdx*/
140 static int fixed_mii_read(struct mii_bus *bus, int phy_id, int location)
142 struct fixed_info *fixed = bus->priv;
144 /* if user has registered link update callback, use it */
146 if(fixed->phydev->attached_dev) {
147 if(fixed->link_update) {
148 fixed->link_update(fixed->phydev->attached_dev,
150 fixed_mdio_update_regs(fixed);
154 if ((unsigned int)location >= fixed->regs_num)
156 return fixed->regs[location];
159 static int fixed_mii_write(struct mii_bus *bus, int phy_id, int location, u16 val)
161 /* do nothing for now*/
165 static int fixed_mii_reset(struct mii_bus *bus)
167 /*nothing here - no way/need to reset it*/
171 static int fixed_config_aneg(struct phy_device *phydev)
173 /* :TODO:03/13/2006 09:45:37 PM::
174 The full autoneg funcionality can be emulated,
175 but no need to have anything here for now
180 /*-----------------------------------------------------------------------------
181 * the manual bind will do the magic - with phy_id_mask == 0
182 * match will never return true...
183 *-----------------------------------------------------------------------------*/
184 static struct phy_driver fixed_mdio_driver = {
186 .features = PHY_BASIC_FEATURES,
187 .config_aneg = fixed_config_aneg,
188 .read_status = genphy_read_status,
189 .driver = { .owner = THIS_MODULE,},
192 /*-----------------------------------------------------------------------------
193 * This func is used to create all the necessary stuff, bind
194 * the fixed phy driver and register all it on the mdio_bus_type.
195 * speed is either 10 or 100, duplex is boolean.
196 * number is used to create multiple fixed PHYs, so that several devices can
197 * utilize them simultaneously.
198 *-----------------------------------------------------------------------------*/
199 static int fixed_mdio_register_device(int number, int speed, int duplex)
201 struct mii_bus *new_bus;
202 struct fixed_info *fixed;
203 struct phy_device *phydev;
206 struct device* dev = kzalloc(sizeof(struct device), GFP_KERNEL);
211 new_bus = kzalloc(sizeof(struct mii_bus), GFP_KERNEL);
213 if (NULL == new_bus) {
217 fixed = kzalloc(sizeof(struct fixed_info), GFP_KERNEL);
225 fixed->regs = kzalloc(MII_REGS_NUM*sizeof(int), GFP_KERNEL);
226 fixed->regs_num = MII_REGS_NUM;
227 fixed->phy_status.speed = speed;
228 fixed->phy_status.duplex = duplex;
229 fixed->phy_status.link = 1;
231 new_bus->name = "Fixed MII Bus",
232 new_bus->read = &fixed_mii_read,
233 new_bus->write = &fixed_mii_write,
234 new_bus->reset = &fixed_mii_reset,
237 fixed_mdio_update_regs(fixed);
238 new_bus->priv = fixed;
241 dev_set_drvdata(dev, new_bus);
243 /* create phy_device and register it on the mdio bus */
244 phydev = phy_device_create(new_bus, 0, 0);
247 Put the phydev pointer into the fixed pack so that bus read/write code could
248 be able to access for instance attached netdev. Well it doesn't have to do
249 so, only in case of utilizing user-specified link-update...
251 fixed->phydev = phydev;
255 goto device_create_fail;
259 phydev->dev.bus = &mdio_bus_type;
262 snprintf(phydev->dev.bus_id, BUS_ID_SIZE,
263 "fixed_%d@%d:%d", number, speed, duplex);
265 snprintf(phydev->dev.bus_id, BUS_ID_SIZE,
266 "fixed@%d:%d", speed, duplex);
267 phydev->bus = new_bus;
269 err = device_register(&phydev->dev);
271 printk(KERN_ERR "Phy %s failed to register\n",
273 goto bus_register_fail;
277 the mdio bus has phy_id match... In order not to do it
278 artificially, we are binding the driver here by hand;
279 it will be the same for all the fixed phys anyway.
281 down_write(&phydev->dev.bus->subsys.rwsem);
283 phydev->dev.driver = &fixed_mdio_driver.driver;
285 err = phydev->dev.driver->probe(&phydev->dev);
287 printk(KERN_ERR "Phy %s: problems with fixed driver\n",phydev->dev.bus_id);
288 up_write(&phydev->dev.bus->subsys.rwsem);
292 device_bind_driver(&phydev->dev);
293 up_write(&phydev->dev.bus->subsys.rwsem);
298 device_unregister(&phydev->dev);
310 MODULE_DESCRIPTION("Fixed PHY device & driver for PAL");
311 MODULE_AUTHOR("Vitaly Bordug");
312 MODULE_LICENSE("GPL");
314 static int __init fixed_init(void)
319 /* register on the bus... Not expected to be matched with anything there... */
320 phy_driver_register(&fixed_mdio_driver);
322 /* So let the fun begin...
323 We will create several mdio devices here, and will bound the upper
326 Then the external software can lookup the phy bus by searching
327 fixed@speed:duplex, e.g. fixed@100:1, to be connected to the
328 virtual 100M Fdx phy.
330 In case several virtual PHYs required, the bus_id will be in form
331 fixed_<num>@<speed>:<duplex>, which make it able even to define
332 driver-specific link control callback, if for instance PHY is completely
337 #ifdef CONFIG_FIXED_MII_DUPLEX
341 #ifdef CONFIG_FIXED_MII_100_FDX
342 fixed_mdio_register_device(0, 100, 1);
345 #ifdef CONFIX_FIXED_MII_10_FDX
346 fixed_mdio_register_device(0, 10, 1);
351 static void __exit fixed_exit(void)
353 phy_driver_unregister(&fixed_mdio_driver);
354 /* :WARNING:02/18/2006 04:32:40 AM:: Cleanup all the created stuff */
357 module_init(fixed_init);
358 module_exit(fixed_exit);