1 /* 2 * Combined Ethernet driver for Motorola MPC8xx and MPC82xx. 3 * 4 * Copyright (c) 2003 Intracom S.A. 5 * by Pantelis Antoniou <panto@intracom.gr> 6 * 7 * 2005 (c) MontaVista Software, Inc. 8 * Vitaly Bordug <vbordug@ru.mvista.com> 9 * 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. 13 */ 14 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_address.h> 26 #include <linux/of_mdio.h> 27 #include <linux/of_platform.h> 28 29 #include "fs_enet.h" 30 31 struct bb_info { 32 struct mdiobb_ctrl ctrl; 33 __be32 __iomem *dir; 34 __be32 __iomem *dat; 35 u32 mdio_msk; 36 u32 mdc_msk; 37 }; 38 39 /* FIXME: If any other users of GPIO crop up, then these will have to 40 * have some sort of global synchronization to avoid races with other 41 * pins on the same port. The ideal solution would probably be to 42 * bind the ports to a GPIO driver, and have this be a client of it. 43 */ 44 static inline void bb_set(u32 __iomem *p, u32 m) 45 { 46 out_be32(p, in_be32(p) | m); 47 } 48 49 static inline void bb_clr(u32 __iomem *p, u32 m) 50 { 51 out_be32(p, in_be32(p) & ~m); 52 } 53 54 static inline int bb_read(u32 __iomem *p, u32 m) 55 { 56 return (in_be32(p) & m) != 0; 57 } 58 59 static inline void mdio_dir(struct mdiobb_ctrl *ctrl, int dir) 60 { 61 struct bb_info *bitbang = container_of(ctrl, struct bb_info, ctrl); 62 63 if (dir) 64 bb_set(bitbang->dir, bitbang->mdio_msk); 65 else 66 bb_clr(bitbang->dir, bitbang->mdio_msk); 67 68 /* Read back to flush the write. */ 69 in_be32(bitbang->dir); 70 } 71 72 static inline int mdio_read(struct mdiobb_ctrl *ctrl) 73 { 74 struct bb_info *bitbang = container_of(ctrl, struct bb_info, ctrl); 75 return bb_read(bitbang->dat, bitbang->mdio_msk); 76 } 77 78 static inline void mdio(struct mdiobb_ctrl *ctrl, int what) 79 { 80 struct bb_info *bitbang = container_of(ctrl, struct bb_info, ctrl); 81 82 if (what) 83 bb_set(bitbang->dat, bitbang->mdio_msk); 84 else 85 bb_clr(bitbang->dat, bitbang->mdio_msk); 86 87 /* Read back to flush the write. */ 88 in_be32(bitbang->dat); 89 } 90 91 static inline void mdc(struct mdiobb_ctrl *ctrl, int what) 92 { 93 struct bb_info *bitbang = container_of(ctrl, struct bb_info, ctrl); 94 95 if (what) 96 bb_set(bitbang->dat, bitbang->mdc_msk); 97 else 98 bb_clr(bitbang->dat, bitbang->mdc_msk); 99 100 /* Read back to flush the write. */ 101 in_be32(bitbang->dat); 102 } 103 104 static struct mdiobb_ops bb_ops = { 105 .owner = THIS_MODULE, 106 .set_mdc = mdc, 107 .set_mdio_dir = mdio_dir, 108 .set_mdio_data = mdio, 109 .get_mdio_data = mdio_read, 110 }; 111 112 static int fs_mii_bitbang_init(struct mii_bus *bus, struct device_node *np) 113 { 114 struct resource res; 115 const u32 *data; 116 int mdio_pin, mdc_pin, len; 117 struct bb_info *bitbang = bus->priv; 118 119 int ret = of_address_to_resource(np, 0, &res); 120 if (ret) 121 return ret; 122 123 if (resource_size(&res) <= 13) 124 return -ENODEV; 125 126 /* This should really encode the pin number as well, but all 127 * we get is an int, and the odds of multiple bitbang mdio buses 128 * is low enough that it's not worth going too crazy. 129 */ 130 snprintf(bus->id, MII_BUS_ID_SIZE, "%x", res.start); 131 132 data = of_get_property(np, "fsl,mdio-pin", &len); 133 if (!data || len != 4) 134 return -ENODEV; 135 mdio_pin = *data; 136 137 data = of_get_property(np, "fsl,mdc-pin", &len); 138 if (!data || len != 4) 139 return -ENODEV; 140 mdc_pin = *data; 141 142 bitbang->dir = ioremap(res.start, resource_size(&res)); 143 if (!bitbang->dir) 144 return -ENOMEM; 145 146 bitbang->dat = bitbang->dir + 4; 147 bitbang->mdio_msk = 1 << (31 - mdio_pin); 148 bitbang->mdc_msk = 1 << (31 - mdc_pin); 149 150 return 0; 151 } 152 153 static int fs_enet_mdio_probe(struct platform_device *ofdev) 154 { 155 struct mii_bus *new_bus; 156 struct bb_info *bitbang; 157 int ret = -ENOMEM; 158 159 bitbang = kzalloc(sizeof(struct bb_info), GFP_KERNEL); 160 if (!bitbang) 161 goto out; 162 163 bitbang->ctrl.ops = &bb_ops; 164 165 new_bus = alloc_mdio_bitbang(&bitbang->ctrl); 166 if (!new_bus) 167 goto out_free_priv; 168 169 new_bus->name = "CPM2 Bitbanged MII", 170 171 ret = fs_mii_bitbang_init(new_bus, ofdev->dev.of_node); 172 if (ret) 173 goto out_free_bus; 174 175 new_bus->phy_mask = ~0; 176 new_bus->irq = kmalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL); 177 if (!new_bus->irq) { 178 ret = -ENOMEM; 179 goto out_unmap_regs; 180 } 181 182 new_bus->parent = &ofdev->dev; 183 platform_set_drvdata(ofdev, new_bus); 184 185 ret = of_mdiobus_register(new_bus, ofdev->dev.of_node); 186 if (ret) 187 goto out_free_irqs; 188 189 return 0; 190 191 out_free_irqs: 192 kfree(new_bus->irq); 193 out_unmap_regs: 194 iounmap(bitbang->dir); 195 out_free_bus: 196 free_mdio_bitbang(new_bus); 197 out_free_priv: 198 kfree(bitbang); 199 out: 200 return ret; 201 } 202 203 static int fs_enet_mdio_remove(struct platform_device *ofdev) 204 { 205 struct mii_bus *bus = platform_get_drvdata(ofdev); 206 struct bb_info *bitbang = bus->priv; 207 208 mdiobus_unregister(bus); 209 kfree(bus->irq); 210 free_mdio_bitbang(bus); 211 iounmap(bitbang->dir); 212 kfree(bitbang); 213 214 return 0; 215 } 216 217 static struct of_device_id fs_enet_mdio_bb_match[] = { 218 { 219 .compatible = "fsl,cpm2-mdio-bitbang", 220 }, 221 {}, 222 }; 223 MODULE_DEVICE_TABLE(of, fs_enet_mdio_bb_match); 224 225 static struct platform_driver fs_enet_bb_mdio_driver = { 226 .driver = { 227 .name = "fsl-bb-mdio", 228 .owner = THIS_MODULE, 229 .of_match_table = fs_enet_mdio_bb_match, 230 }, 231 .probe = fs_enet_mdio_probe, 232 .remove = fs_enet_mdio_remove, 233 }; 234 235 module_platform_driver(fs_enet_bb_mdio_driver); 236