Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at 0bc77ecbe4f69ff8ead1d2abfe84ca9ba2a7bca4 301 lines 7.9 kB view raw
1/* 2 * drivers/net/gianfar_mii.c 3 * 4 * Gianfar Ethernet Driver -- MIIM bus implementation 5 * Provides Bus interface for MIIM regs 6 * 7 * Author: Andy Fleming 8 * Maintainer: Kumar Gala 9 * 10 * Copyright (c) 2002-2004 Freescale Semiconductor, Inc. 11 * 12 * This program is free software; you can redistribute it and/or modify it 13 * under the terms of the GNU General Public License as published by the 14 * Free Software Foundation; either version 2 of the License, or (at your 15 * option) any later version. 16 * 17 */ 18 19#include <linux/kernel.h> 20#include <linux/string.h> 21#include <linux/errno.h> 22#include <linux/unistd.h> 23#include <linux/slab.h> 24#include <linux/interrupt.h> 25#include <linux/init.h> 26#include <linux/delay.h> 27#include <linux/netdevice.h> 28#include <linux/etherdevice.h> 29#include <linux/skbuff.h> 30#include <linux/spinlock.h> 31#include <linux/mm.h> 32#include <linux/module.h> 33#include <linux/platform_device.h> 34#include <linux/crc32.h> 35#include <linux/mii.h> 36#include <linux/phy.h> 37 38#include <asm/io.h> 39#include <asm/irq.h> 40#include <asm/uaccess.h> 41 42#include "gianfar.h" 43#include "gianfar_mii.h" 44 45/* 46 * Write value to the PHY at mii_id at register regnum, 47 * on the bus attached to the local interface, which may be different from the 48 * generic mdio bus (tied to a single interface), waiting until the write is 49 * done before returning. This is helpful in programming interfaces like 50 * the TBI which control interfaces like onchip SERDES and are always tied to 51 * the local mdio pins, which may not be the same as system mdio bus, used for 52 * controlling the external PHYs, for example. 53 */ 54int gfar_local_mdio_write(struct gfar_mii __iomem *regs, int mii_id, 55 int regnum, u16 value) 56{ 57 /* Set the PHY address and the register address we want to write */ 58 gfar_write(&regs->miimadd, (mii_id << 8) | regnum); 59 60 /* Write out the value we want */ 61 gfar_write(&regs->miimcon, value); 62 63 /* Wait for the transaction to finish */ 64 while (gfar_read(&regs->miimind) & MIIMIND_BUSY) 65 cpu_relax(); 66 67 return 0; 68} 69 70/* 71 * Read the bus for PHY at addr mii_id, register regnum, and 72 * return the value. Clears miimcom first. All PHY operation 73 * done on the bus attached to the local interface, 74 * which may be different from the generic mdio bus 75 * This is helpful in programming interfaces like 76 * the TBI which, inturn, control interfaces like onchip SERDES 77 * and are always tied to the local mdio pins, which may not be the 78 * same as system mdio bus, used for controlling the external PHYs, for eg. 79 */ 80int gfar_local_mdio_read(struct gfar_mii __iomem *regs, int mii_id, int regnum) 81{ 82 u16 value; 83 84 /* Set the PHY address and the register address we want to read */ 85 gfar_write(&regs->miimadd, (mii_id << 8) | regnum); 86 87 /* Clear miimcom, and then initiate a read */ 88 gfar_write(&regs->miimcom, 0); 89 gfar_write(&regs->miimcom, MII_READ_COMMAND); 90 91 /* Wait for the transaction to finish */ 92 while (gfar_read(&regs->miimind) & (MIIMIND_NOTVALID | MIIMIND_BUSY)) 93 cpu_relax(); 94 95 /* Grab the value of the register from miimstat */ 96 value = gfar_read(&regs->miimstat); 97 98 return value; 99} 100 101/* Write value to the PHY at mii_id at register regnum, 102 * on the bus, waiting until the write is done before returning. 103 * All PHY configuration is done through the TSEC1 MIIM regs */ 104int gfar_mdio_write(struct mii_bus *bus, int mii_id, int regnum, u16 value) 105{ 106 struct gfar_mii __iomem *regs = (void __iomem *)bus->priv; 107 108 /* Write to the local MII regs */ 109 return(gfar_local_mdio_write(regs, mii_id, regnum, value)); 110} 111 112/* Read the bus for PHY at addr mii_id, register regnum, and 113 * return the value. Clears miimcom first. All PHY 114 * configuration has to be done through the TSEC1 MIIM regs */ 115int gfar_mdio_read(struct mii_bus *bus, int mii_id, int regnum) 116{ 117 struct gfar_mii __iomem *regs = (void __iomem *)bus->priv; 118 119 /* Read the local MII regs */ 120 return(gfar_local_mdio_read(regs, mii_id, regnum)); 121} 122 123/* Reset the MIIM registers, and wait for the bus to free */ 124static int gfar_mdio_reset(struct mii_bus *bus) 125{ 126 struct gfar_mii __iomem *regs = (void __iomem *)bus->priv; 127 unsigned int timeout = PHY_INIT_TIMEOUT; 128 129 mutex_lock(&bus->mdio_lock); 130 131 /* Reset the management interface */ 132 gfar_write(&regs->miimcfg, MIIMCFG_RESET); 133 134 /* Setup the MII Mgmt clock speed */ 135 gfar_write(&regs->miimcfg, MIIMCFG_INIT_VALUE); 136 137 /* Wait until the bus is free */ 138 while ((gfar_read(&regs->miimind) & MIIMIND_BUSY) && 139 --timeout) 140 cpu_relax(); 141 142 mutex_unlock(&bus->mdio_lock); 143 144 if(timeout == 0) { 145 printk(KERN_ERR "%s: The MII Bus is stuck!\n", 146 bus->name); 147 return -EBUSY; 148 } 149 150 return 0; 151} 152 153 154static int gfar_mdio_probe(struct device *dev) 155{ 156 struct platform_device *pdev = to_platform_device(dev); 157 struct gianfar_mdio_data *pdata; 158 struct gfar_mii __iomem *regs; 159 struct gfar __iomem *enet_regs; 160 struct mii_bus *new_bus; 161 struct resource *r; 162 int i, err = 0; 163 164 if (NULL == dev) 165 return -EINVAL; 166 167 new_bus = mdiobus_alloc(); 168 if (NULL == new_bus) 169 return -ENOMEM; 170 171 new_bus->name = "Gianfar MII Bus", 172 new_bus->read = &gfar_mdio_read, 173 new_bus->write = &gfar_mdio_write, 174 new_bus->reset = &gfar_mdio_reset, 175 snprintf(new_bus->id, MII_BUS_ID_SIZE, "%x", pdev->id); 176 177 pdata = (struct gianfar_mdio_data *)pdev->dev.platform_data; 178 179 if (NULL == pdata) { 180 printk(KERN_ERR "gfar mdio %d: Missing platform data!\n", pdev->id); 181 return -ENODEV; 182 } 183 184 r = platform_get_resource(pdev, IORESOURCE_MEM, 0); 185 186 /* Set the PHY base address */ 187 regs = ioremap(r->start, sizeof (struct gfar_mii)); 188 189 if (NULL == regs) { 190 err = -ENOMEM; 191 goto reg_map_fail; 192 } 193 194 new_bus->priv = (void __force *)regs; 195 196 new_bus->irq = pdata->irq; 197 198 new_bus->parent = dev; 199 dev_set_drvdata(dev, new_bus); 200 201 /* 202 * This is mildly evil, but so is our hardware for doing this. 203 * Also, we have to cast back to struct gfar_mii because of 204 * definition weirdness done in gianfar.h. 205 */ 206 enet_regs = (struct gfar __iomem *) 207 ((char *)regs - offsetof(struct gfar, gfar_mii_regs)); 208 209 /* Scan the bus, looking for an empty spot for TBIPA */ 210 gfar_write(&enet_regs->tbipa, 0); 211 for (i = PHY_MAX_ADDR; i > 0; i--) { 212 u32 phy_id; 213 214 err = get_phy_id(new_bus, i, &phy_id); 215 if (err) 216 goto bus_register_fail; 217 218 if (phy_id == 0xffffffff) 219 break; 220 } 221 222 /* The bus is full. We don't support using 31 PHYs, sorry */ 223 if (i == 0) { 224 err = -EBUSY; 225 226 goto bus_register_fail; 227 } 228 229 gfar_write(&enet_regs->tbipa, i); 230 231 err = mdiobus_register(new_bus); 232 233 if (0 != err) { 234 printk (KERN_ERR "%s: Cannot register as MDIO bus\n", 235 new_bus->name); 236 goto bus_register_fail; 237 } 238 239 return 0; 240 241bus_register_fail: 242 iounmap(regs); 243reg_map_fail: 244 mdiobus_free(new_bus); 245 246 return err; 247} 248 249 250static int gfar_mdio_remove(struct device *dev) 251{ 252 struct mii_bus *bus = dev_get_drvdata(dev); 253 254 mdiobus_unregister(bus); 255 256 dev_set_drvdata(dev, NULL); 257 258 iounmap((void __iomem *)bus->priv); 259 bus->priv = NULL; 260 mdiobus_free(bus); 261 262 return 0; 263} 264 265static struct device_driver gianfar_mdio_driver = { 266 .name = "fsl-gianfar_mdio", 267 .bus = &platform_bus_type, 268 .probe = gfar_mdio_probe, 269 .remove = gfar_mdio_remove, 270}; 271 272static int match_mdio_bus(struct device *dev, void *data) 273{ 274 const struct gfar_private *priv = data; 275 const struct platform_device *pdev = to_platform_device(dev); 276 277 return !strcmp(pdev->name, gianfar_mdio_driver.name) && 278 pdev->id == priv->einfo->mdio_bus; 279} 280 281/* Given a gfar_priv structure, find the mii_bus controlled by this device (not 282 * necessarily the same as the bus the gfar's PHY is on), if one exists. 283 * Normally only the first gianfar controls a mii_bus. */ 284struct mii_bus *gfar_get_miibus(const struct gfar_private *priv) 285{ 286 /*const*/ struct device *d; 287 288 d = bus_find_device(gianfar_mdio_driver.bus, NULL, (void *)priv, 289 match_mdio_bus); 290 return d ? dev_get_drvdata(d) : NULL; 291} 292 293int __init gfar_mdio_init(void) 294{ 295 return driver_register(&gianfar_mdio_driver); 296} 297 298void gfar_mdio_exit(void) 299{ 300 driver_unregister(&gianfar_mdio_driver); 301}