1 /* 2 * QorIQ 10G MDIO Controller 3 * 4 * Copyright 2012 Freescale Semiconductor, Inc. 5 * 6 * Authors: Andy Fleming <afleming@freescale.com> 7 * Timur Tabi <timur@freescale.com> 8 * 9 * This file is licensed under the terms of the GNU General Public License 10 * version 2. This program is licensed "as is" without any warranty of any 11 * kind, whether express or implied. 12 */ 13 14 #include <linux/kernel.h> 15 #include <linux/slab.h> 16 #include <linux/interrupt.h> 17 #include <linux/module.h> 18 #include <linux/phy.h> 19 #include <linux/mdio.h> 20 #include <linux/of_address.h> 21 #include <linux/of_platform.h> 22 #include <linux/of_mdio.h> 23 24 /* Number of microseconds to wait for a register to respond */ 25 #define TIMEOUT 1000 26 27 struct tgec_mdio_controller { 28 __be32 reserved[12]; 29 __be32 mdio_stat; /* MDIO configuration and status */ 30 __be32 mdio_ctl; /* MDIO control */ 31 __be32 mdio_data; /* MDIO data */ 32 __be32 mdio_addr; /* MDIO address */ 33 } __packed; 34 35 #define MDIO_STAT_ENC BIT(6) 36 #define MDIO_STAT_CLKDIV(x) (((x>>1) & 0xff) << 8) 37 #define MDIO_STAT_BSY BIT(0) 38 #define MDIO_STAT_RD_ER BIT(1) 39 #define MDIO_CTL_DEV_ADDR(x) (x & 0x1f) 40 #define MDIO_CTL_PORT_ADDR(x) ((x & 0x1f) << 5) 41 #define MDIO_CTL_PRE_DIS BIT(10) 42 #define MDIO_CTL_SCAN_EN BIT(11) 43 #define MDIO_CTL_POST_INC BIT(14) 44 #define MDIO_CTL_READ BIT(15) 45 46 #define MDIO_DATA(x) (x & 0xffff) 47 #define MDIO_DATA_BSY BIT(31) 48 49 /* 50 * Wait until the MDIO bus is free 51 */ 52 static int xgmac_wait_until_free(struct device *dev, 53 struct tgec_mdio_controller __iomem *regs) 54 { 55 unsigned int timeout; 56 57 /* Wait till the bus is free */ 58 timeout = TIMEOUT; 59 while ((ioread32be(®s->mdio_stat) & MDIO_STAT_BSY) && timeout) { 60 cpu_relax(); 61 timeout--; 62 } 63 64 if (!timeout) { 65 dev_err(dev, "timeout waiting for bus to be free\n"); 66 return -ETIMEDOUT; 67 } 68 69 return 0; 70 } 71 72 /* 73 * Wait till the MDIO read or write operation is complete 74 */ 75 static int xgmac_wait_until_done(struct device *dev, 76 struct tgec_mdio_controller __iomem *regs) 77 { 78 unsigned int timeout; 79 80 /* Wait till the MDIO write is complete */ 81 timeout = TIMEOUT; 82 while ((ioread32be(®s->mdio_data) & MDIO_DATA_BSY) && timeout) { 83 cpu_relax(); 84 timeout--; 85 } 86 87 if (!timeout) { 88 dev_err(dev, "timeout waiting for operation to complete\n"); 89 return -ETIMEDOUT; 90 } 91 92 return 0; 93 } 94 95 /* 96 * Write value to the PHY for this device to the register at regnum,waiting 97 * until the write is done before it returns. All PHY configuration has to be 98 * done through the TSEC1 MIIM regs. 99 */ 100 static int xgmac_mdio_write(struct mii_bus *bus, int phy_id, int regnum, u16 value) 101 { 102 struct tgec_mdio_controller __iomem *regs = bus->priv; 103 uint16_t dev_addr; 104 u32 mdio_ctl, mdio_stat; 105 int ret; 106 107 mdio_stat = ioread32be(®s->mdio_stat); 108 if (regnum & MII_ADDR_C45) { 109 /* Clause 45 (ie 10G) */ 110 dev_addr = (regnum >> 16) & 0x1f; 111 mdio_stat |= MDIO_STAT_ENC; 112 } else { 113 /* Clause 22 (ie 1G) */ 114 dev_addr = regnum & 0x1f; 115 mdio_stat &= ~MDIO_STAT_ENC; 116 } 117 118 iowrite32be(mdio_stat, ®s->mdio_stat); 119 120 ret = xgmac_wait_until_free(&bus->dev, regs); 121 if (ret) 122 return ret; 123 124 /* Set the port and dev addr */ 125 mdio_ctl = MDIO_CTL_PORT_ADDR(phy_id) | MDIO_CTL_DEV_ADDR(dev_addr); 126 iowrite32be(mdio_ctl, ®s->mdio_ctl); 127 128 /* Set the register address */ 129 if (regnum & MII_ADDR_C45) { 130 iowrite32be(regnum & 0xffff, ®s->mdio_addr); 131 132 ret = xgmac_wait_until_free(&bus->dev, regs); 133 if (ret) 134 return ret; 135 } 136 137 /* Write the value to the register */ 138 iowrite32be(MDIO_DATA(value), ®s->mdio_data); 139 140 ret = xgmac_wait_until_done(&bus->dev, regs); 141 if (ret) 142 return ret; 143 144 return 0; 145 } 146 147 /* 148 * Reads from register regnum in the PHY for device dev, returning the value. 149 * Clears miimcom first. All PHY configuration has to be done through the 150 * TSEC1 MIIM regs. 151 */ 152 static int xgmac_mdio_read(struct mii_bus *bus, int phy_id, int regnum) 153 { 154 struct tgec_mdio_controller __iomem *regs = bus->priv; 155 uint16_t dev_addr; 156 uint32_t mdio_stat; 157 uint32_t mdio_ctl; 158 uint16_t value; 159 int ret; 160 161 mdio_stat = ioread32be(®s->mdio_stat); 162 if (regnum & MII_ADDR_C45) { 163 dev_addr = (regnum >> 16) & 0x1f; 164 mdio_stat |= MDIO_STAT_ENC; 165 } else { 166 dev_addr = regnum & 0x1f; 167 mdio_stat &= ~MDIO_STAT_ENC; 168 } 169 170 iowrite32be(mdio_stat, ®s->mdio_stat); 171 172 ret = xgmac_wait_until_free(&bus->dev, regs); 173 if (ret) 174 return ret; 175 176 /* Set the Port and Device Addrs */ 177 mdio_ctl = MDIO_CTL_PORT_ADDR(phy_id) | MDIO_CTL_DEV_ADDR(dev_addr); 178 iowrite32be(mdio_ctl, ®s->mdio_ctl); 179 180 /* Set the register address */ 181 if (regnum & MII_ADDR_C45) { 182 iowrite32be(regnum & 0xffff, ®s->mdio_addr); 183 184 ret = xgmac_wait_until_free(&bus->dev, regs); 185 if (ret) 186 return ret; 187 } 188 189 /* Initiate the read */ 190 iowrite32be(mdio_ctl | MDIO_CTL_READ, ®s->mdio_ctl); 191 192 ret = xgmac_wait_until_done(&bus->dev, regs); 193 if (ret) 194 return ret; 195 196 /* Return all Fs if nothing was there */ 197 if (ioread32be(®s->mdio_stat) & MDIO_STAT_RD_ER) { 198 dev_err(&bus->dev, 199 "Error while reading PHY%d reg at %d.%hhu\n", 200 phy_id, dev_addr, regnum); 201 return 0xffff; 202 } 203 204 value = ioread32be(®s->mdio_data) & 0xffff; 205 dev_dbg(&bus->dev, "read %04x\n", value); 206 207 return value; 208 } 209 210 static int xgmac_mdio_probe(struct platform_device *pdev) 211 { 212 struct device_node *np = pdev->dev.of_node; 213 struct mii_bus *bus; 214 struct resource res; 215 int ret; 216 217 ret = of_address_to_resource(np, 0, &res); 218 if (ret) { 219 dev_err(&pdev->dev, "could not obtain address\n"); 220 return ret; 221 } 222 223 bus = mdiobus_alloc(); 224 if (!bus) 225 return -ENOMEM; 226 227 bus->name = "Freescale XGMAC MDIO Bus"; 228 bus->read = xgmac_mdio_read; 229 bus->write = xgmac_mdio_write; 230 bus->parent = &pdev->dev; 231 snprintf(bus->id, MII_BUS_ID_SIZE, "%llx", (unsigned long long)res.start); 232 233 /* Set the PHY base address */ 234 bus->priv = of_iomap(np, 0); 235 if (!bus->priv) { 236 ret = -ENOMEM; 237 goto err_ioremap; 238 } 239 240 ret = of_mdiobus_register(bus, np); 241 if (ret) { 242 dev_err(&pdev->dev, "cannot register MDIO bus\n"); 243 goto err_registration; 244 } 245 246 platform_set_drvdata(pdev, bus); 247 248 return 0; 249 250 err_registration: 251 iounmap(bus->priv); 252 253 err_ioremap: 254 mdiobus_free(bus); 255 256 return ret; 257 } 258 259 static int xgmac_mdio_remove(struct platform_device *pdev) 260 { 261 struct mii_bus *bus = platform_get_drvdata(pdev); 262 263 mdiobus_unregister(bus); 264 iounmap(bus->priv); 265 mdiobus_free(bus); 266 267 return 0; 268 } 269 270 static struct of_device_id xgmac_mdio_match[] = { 271 { 272 .compatible = "fsl,fman-xmdio", 273 }, 274 { 275 .compatible = "fsl,fman-memac-mdio", 276 }, 277 {}, 278 }; 279 MODULE_DEVICE_TABLE(of, xgmac_mdio_match); 280 281 static struct platform_driver xgmac_mdio_driver = { 282 .driver = { 283 .name = "fsl-fman_xmdio", 284 .of_match_table = xgmac_mdio_match, 285 }, 286 .probe = xgmac_mdio_probe, 287 .remove = xgmac_mdio_remove, 288 }; 289 290 module_platform_driver(xgmac_mdio_driver); 291 292 MODULE_DESCRIPTION("Freescale QorIQ 10G MDIO Controller"); 293 MODULE_LICENSE("GPL v2"); 294