2 * Combined Ethernet driver for Motorola MPC8xx and MPC82xx.
4 * Copyright (c) 2003 Intracom S.A.
5 * by Pantelis Antoniou <panto@intracom.gr>
7 * 2005 (c) MontaVista Software, Inc.
8 * Vitaly Bordug <vbordug@ru.mvista.com>
10 * This file is licensed under the terms of the GNU General Public License
11 * version 2. This program is licensed "as is" without any warranty of any
12 * kind, whether express or implied.
15 #include <linux/module.h>
16 #include <linux/ioport.h>
17 #include <linux/slab.h>
18 #include <linux/init.h>
19 #include <linux/interrupt.h>
20 #include <linux/netdevice.h>
21 #include <linux/etherdevice.h>
22 #include <linux/mii.h>
23 #include <linux/platform_device.h>
24 #include <linux/mdio-bitbang.h>
25 #include <linux/of_mdio.h>
26 #include <linux/of_platform.h>
31 struct mdiobb_ctrl ctrl
;
38 static inline void bb_set(u32 __iomem
*p
, u32 m
)
40 out_be32(p
, in_be32(p
) | m
);
43 static inline void bb_clr(u32 __iomem
*p
, u32 m
)
45 out_be32(p
, in_be32(p
) & ~m
);
48 static inline int bb_read(u32 __iomem
*p
, u32 m
)
50 return (in_be32(p
) & m
) != 0;
53 static inline void mdio_dir(struct mdiobb_ctrl
*ctrl
, int dir
)
55 struct bb_info
*bitbang
= container_of(ctrl
, struct bb_info
, ctrl
);
58 bb_set(bitbang
->dir
, bitbang
->mdio_msk
);
60 bb_clr(bitbang
->dir
, bitbang
->mdio_msk
);
62 /* Read back to flush the write. */
63 in_be32(bitbang
->dir
);
66 static inline int mdio_read(struct mdiobb_ctrl
*ctrl
)
68 struct bb_info
*bitbang
= container_of(ctrl
, struct bb_info
, ctrl
);
69 return bb_read(bitbang
->dat
, bitbang
->mdio_msk
);
72 static inline void mdio(struct mdiobb_ctrl
*ctrl
, int what
)
74 struct bb_info
*bitbang
= container_of(ctrl
, struct bb_info
, ctrl
);
77 bb_set(bitbang
->dat
, bitbang
->mdio_msk
);
79 bb_clr(bitbang
->dat
, bitbang
->mdio_msk
);
81 /* Read back to flush the write. */
82 in_be32(bitbang
->dat
);
85 static inline void mdc(struct mdiobb_ctrl
*ctrl
, int what
)
87 struct bb_info
*bitbang
= container_of(ctrl
, struct bb_info
, ctrl
);
90 bb_set(bitbang
->dat
, bitbang
->mdc_msk
);
92 bb_clr(bitbang
->dat
, bitbang
->mdc_msk
);
94 /* Read back to flush the write. */
95 in_be32(bitbang
->dat
);
98 static struct mdiobb_ops bb_ops
= {
101 .set_mdio_dir
= mdio_dir
,
102 .set_mdio_data
= mdio
,
103 .get_mdio_data
= mdio_read
,
106 static int __devinit
fs_mii_bitbang_init(struct mii_bus
*bus
,
107 struct device_node
*np
)
111 int mdio_pin
, mdc_pin
, len
;
112 struct bb_info
*bitbang
= bus
->priv
;
114 int ret
= of_address_to_resource(np
, 0, &res
);
118 if (res
.end
- res
.start
< 13)
121 /* This should really encode the pin number as well, but all
122 * we get is an int, and the odds of multiple bitbang mdio buses
123 * is low enough that it's not worth going too crazy.
125 snprintf(bus
->id
, MII_BUS_ID_SIZE
, "%x", res
.start
);
127 data
= of_get_property(np
, "fsl,mdio-pin", &len
);
128 if (!data
|| len
!= 4)
132 data
= of_get_property(np
, "fsl,mdc-pin", &len
);
133 if (!data
|| len
!= 4)
137 bitbang
->dir
= ioremap(res
.start
, res
.end
- res
.start
+ 1);
141 bitbang
->dat
= bitbang
->dir
+ 4;
142 bitbang
->mdio_msk
= 1 << (31 - mdio_pin
);
143 bitbang
->mdc_msk
= 1 << (31 - mdc_pin
);
148 static int __devinit
fs_enet_mdio_probe(struct platform_device
*ofdev
,
149 const struct of_device_id
*match
)
151 struct mii_bus
*new_bus
;
152 struct bb_info
*bitbang
;
155 bitbang
= kzalloc(sizeof(struct bb_info
), GFP_KERNEL
);
159 bitbang
->ctrl
.ops
= &bb_ops
;
161 new_bus
= alloc_mdio_bitbang(&bitbang
->ctrl
);
165 new_bus
->name
= "CPM2 Bitbanged MII",
167 ret
= fs_mii_bitbang_init(new_bus
, ofdev
->dev
.of_node
);
171 new_bus
->phy_mask
= ~0;
172 new_bus
->irq
= kmalloc(sizeof(int) * PHY_MAX_ADDR
, GFP_KERNEL
);
176 new_bus
->parent
= &ofdev
->dev
;
177 dev_set_drvdata(&ofdev
->dev
, new_bus
);
179 ret
= of_mdiobus_register(new_bus
, ofdev
->dev
.of_node
);
186 dev_set_drvdata(&ofdev
->dev
, NULL
);
189 iounmap(bitbang
->dir
);
191 free_mdio_bitbang(new_bus
);
198 static int fs_enet_mdio_remove(struct platform_device
*ofdev
)
200 struct mii_bus
*bus
= dev_get_drvdata(&ofdev
->dev
);
201 struct bb_info
*bitbang
= bus
->priv
;
203 mdiobus_unregister(bus
);
204 dev_set_drvdata(&ofdev
->dev
, NULL
);
206 free_mdio_bitbang(bus
);
207 iounmap(bitbang
->dir
);
213 static struct of_device_id fs_enet_mdio_bb_match
[] = {
215 .compatible
= "fsl,cpm2-mdio-bitbang",
219 MODULE_DEVICE_TABLE(of
, fs_enet_mdio_bb_match
);
221 static struct of_platform_driver fs_enet_bb_mdio_driver
= {
223 .name
= "fsl-bb-mdio",
224 .owner
= THIS_MODULE
,
225 .of_match_table
= fs_enet_mdio_bb_match
,
227 .probe
= fs_enet_mdio_probe
,
228 .remove
= fs_enet_mdio_remove
,
231 static int fs_enet_mdio_bb_init(void)
233 return of_register_platform_driver(&fs_enet_bb_mdio_driver
);
236 static void fs_enet_mdio_bb_exit(void)
238 of_unregister_platform_driver(&fs_enet_bb_mdio_driver
);
241 module_init(fs_enet_mdio_bb_init
);
242 module_exit(fs_enet_mdio_bb_exit
);