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/kernel.h>
17 #include <linux/string.h>
18 #include <linux/errno.h>
19 #include <linux/unistd.h>
20 #include <linux/slab.h>
21 #include <linux/interrupt.h>
22 #include <linux/init.h>
23 #include <linux/delay.h>
24 #include <linux/netdevice.h>
25 #include <linux/etherdevice.h>
26 #include <linux/skbuff.h>
27 #include <linux/spinlock.h>
29 #include <linux/module.h>
30 #include <linux/mii.h>
31 #include <linux/ethtool.h>
32 #include <linux/phy.h>
33 #include <linux/phy_fixed.h>
37 #include <asm/uaccess.h>
39 /* we need to track the allocated pointers in order to free them on exit */
40 static struct fixed_info
*fixed_phy_ptrs
[CONFIG_FIXED_MII_AMNT
*MAX_PHY_AMNT
];
42 /*-----------------------------------------------------------------------------
43 * If something weird is required to be done with link/speed,
44 * network driver is able to assign a function to implement this.
45 * May be useful for PHY's that need to be software-driven.
46 *-----------------------------------------------------------------------------*/
47 int fixed_mdio_set_link_update(struct phy_device
*phydev
,
48 int (*link_update
) (struct net_device
*,
49 struct fixed_phy_status
*))
51 struct fixed_info
*fixed
;
53 if (link_update
== NULL
)
58 fixed
= phydev
->bus
->priv
;
59 fixed
->link_update
= link_update
;
66 EXPORT_SYMBOL(fixed_mdio_set_link_update
);
68 struct fixed_info
*fixed_mdio_get_phydev (int phydev_ind
)
70 if (phydev_ind
>= MAX_PHY_AMNT
)
72 return fixed_phy_ptrs
[phydev_ind
];
75 EXPORT_SYMBOL(fixed_mdio_get_phydev
);
77 /*-----------------------------------------------------------------------------
78 * This is used for updating internal mii regs from the status
79 *-----------------------------------------------------------------------------*/
80 #if defined(CONFIG_FIXED_MII_100_FDX) || defined(CONFIG_FIXED_MII_10_FDX) || defined(CONFIG_FIXED_MII_1000_FDX)
81 static int fixed_mdio_update_regs(struct fixed_info
*fixed
)
83 u16
*regs
= fixed
->regs
;
88 printk(KERN_ERR
"%s: regs not set up", __FUNCTION__
);
92 if (fixed
->phy_status
.link
)
95 if (fixed
->phy_status
.duplex
) {
96 bmcr
|= BMCR_FULLDPLX
;
98 switch (fixed
->phy_status
.speed
) {
100 bmsr
|= BMSR_100FULL
;
101 bmcr
|= BMCR_SPEED100
;
109 switch (fixed
->phy_status
.speed
) {
111 bmsr
|= BMSR_100HALF
;
112 bmcr
|= BMCR_SPEED100
;
116 bmsr
|= BMSR_100HALF
;
121 regs
[MII_BMCR
] = bmcr
;
122 regs
[MII_BMSR
] = bmsr
| 0x800; /*we are always capable of 10 hdx */
127 static int fixed_mii_read(struct mii_bus
*bus
, int phy_id
, int location
)
129 struct fixed_info
*fixed
= bus
->priv
;
131 /* if user has registered link update callback, use it */
133 if (fixed
->phydev
->attached_dev
) {
134 if (fixed
->link_update
) {
135 fixed
->link_update(fixed
->phydev
->attached_dev
,
137 fixed_mdio_update_regs(fixed
);
141 if ((unsigned int)location
>= fixed
->regs_num
)
143 return fixed
->regs
[location
];
146 static int fixed_mii_write(struct mii_bus
*bus
, int phy_id
, int location
,
149 /* do nothing for now */
153 static int fixed_mii_reset(struct mii_bus
*bus
)
155 /*nothing here - no way/need to reset it */
160 static int fixed_config_aneg(struct phy_device
*phydev
)
162 /* :TODO:03/13/2006 09:45:37 PM::
163 The full autoneg funcionality can be emulated,
164 but no need to have anything here for now
169 /*-----------------------------------------------------------------------------
170 * the manual bind will do the magic - with phy_id_mask == 0
171 * match will never return true...
172 *-----------------------------------------------------------------------------*/
173 static struct phy_driver fixed_mdio_driver
= {
175 #ifdef CONFIG_FIXED_MII_1000_FDX
176 .features
= PHY_GBIT_FEATURES
,
178 .features
= PHY_BASIC_FEATURES
,
180 .config_aneg
= fixed_config_aneg
,
181 .read_status
= genphy_read_status
,
182 .driver
= { .owner
= THIS_MODULE
, },
185 static void fixed_mdio_release(struct device
*dev
)
187 struct phy_device
*phydev
= container_of(dev
, struct phy_device
, dev
);
188 struct mii_bus
*bus
= phydev
->bus
;
189 struct fixed_info
*fixed
= bus
->priv
;
198 /*-----------------------------------------------------------------------------
199 * This func is used to create all the necessary stuff, bind
200 * the fixed phy driver and register all it on the mdio_bus_type.
201 * speed is either 10 or 100 or 1000, duplex is boolean.
202 * number is used to create multiple fixed PHYs, so that several devices can
203 * utilize them simultaneously.
205 * The device on mdio bus will look like [bus_id]:[phy_id],
207 * phy_id = speed+duplex.
208 *-----------------------------------------------------------------------------*/
209 #if defined(CONFIG_FIXED_MII_100_FDX) || defined(CONFIG_FIXED_MII_10_FDX) || defined(CONFIG_FIXED_MII_1000_FDX)
210 struct fixed_info
*fixed_mdio_register_device(
211 int bus_id
, int speed
, int duplex
, u8 phy_id
)
213 struct mii_bus
*new_bus
;
214 struct fixed_info
*fixed
;
215 struct phy_device
*phydev
;
218 struct device
*dev
= kzalloc(sizeof(struct device
), GFP_KERNEL
);
223 new_bus
= kzalloc(sizeof(struct mii_bus
), GFP_KERNEL
);
228 fixed
= kzalloc(sizeof(struct fixed_info
), GFP_KERNEL
);
231 goto err_fixed_alloc
;
233 fixed
->regs
= kzalloc(MII_REGS_NUM
* sizeof(int), GFP_KERNEL
);
234 if (NULL
== fixed
->regs
)
235 goto err_fixed_regs_alloc
;
237 fixed
->regs_num
= MII_REGS_NUM
;
238 fixed
->phy_status
.speed
= speed
;
239 fixed
->phy_status
.duplex
= duplex
;
240 fixed
->phy_status
.link
= 1;
242 new_bus
->name
= "Fixed MII Bus";
243 new_bus
->read
= &fixed_mii_read
;
244 new_bus
->write
= &fixed_mii_write
;
245 new_bus
->reset
= &fixed_mii_reset
;
246 /*set up workspace */
247 fixed_mdio_update_regs(fixed
);
248 new_bus
->priv
= fixed
;
251 dev_set_drvdata(dev
, new_bus
);
253 /* create phy_device and register it on the mdio bus */
254 phydev
= phy_device_create(new_bus
, 0, 0);
256 goto err_phy_dev_create
;
259 * Put the phydev pointer into the fixed pack so that bus read/write
260 * code could be able to access for instance attached netdev. Well it
261 * doesn't have to do so, only in case of utilizing user-specified
265 fixed
->phydev
= phydev
;
266 phydev
->speed
= speed
;
267 phydev
->duplex
= duplex
;
269 phydev
->irq
= PHY_IGNORE_INTERRUPT
;
270 phydev
->dev
.bus
= &mdio_bus_type
;
272 snprintf(phydev
->dev
.bus_id
, BUS_ID_SIZE
,
273 PHY_ID_FMT
, bus_id
, phy_id
);
275 phydev
->bus
= new_bus
;
277 phydev
->dev
.driver
= &fixed_mdio_driver
.driver
;
278 phydev
->dev
.release
= fixed_mdio_release
;
279 err
= phydev
->dev
.driver
->probe(&phydev
->dev
);
281 printk(KERN_ERR
"Phy %s: problems with fixed driver\n",
285 err
= device_register(&phydev
->dev
);
287 printk(KERN_ERR
"Phy %s failed to register\n",
291 //phydev->state = PHY_RUNNING; /* make phy go up quick, but in 10Mbit/HDX
298 err_fixed_regs_alloc
:
311 MODULE_DESCRIPTION("Fixed PHY device & driver for PAL");
312 MODULE_AUTHOR("Vitaly Bordug");
313 MODULE_LICENSE("GPL");
315 static int __init
fixed_init(void)
319 /* register on the bus... Not expected to be matched
320 * with anything there...
323 phy_driver_register(&fixed_mdio_driver
);
325 /* We will create several mdio devices here, and will bound the upper
328 * Then the external software can lookup the phy bus by searching
329 * for 0:101, to be connected to the virtual 100M Fdx phy.
331 * In case several virtual PHYs required, the bus_id will be in form
332 * [num]:[duplex]+[speed], which make it able even to define
333 * driver-specific link control callback, if for instance PHY is
334 * completely SW-driven.
336 for (i
=1; i
<= CONFIG_FIXED_MII_AMNT
; i
++) {
337 #ifdef CONFIG_FIXED_MII_1000_FDX
338 fixed_phy_ptrs
[cnt
++] = fixed_mdio_register_device(0, 1000, 1, i
);
340 #ifdef CONFIG_FIXED_MII_100_FDX
341 fixed_phy_ptrs
[cnt
++] = fixed_mdio_register_device(1, 100, 1, i
);
343 #ifdef CONFIG_FIXED_MII_10_FDX
344 fixed_phy_ptrs
[cnt
++] = fixed_mdio_register_device(2, 10, 1, i
);
351 static void __exit
fixed_exit(void)
355 phy_driver_unregister(&fixed_mdio_driver
);
356 for (i
=0; i
< MAX_PHY_AMNT
; i
++)
357 if ( fixed_phy_ptrs
[i
] )
358 device_unregister(&fixed_phy_ptrs
[i
]->phydev
->dev
);
361 module_init(fixed_init
);
362 module_exit(fixed_exit
);