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 989a7241df87526bfef0396567e71ebe53a84ae4 251 lines 6.4 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{ 83 u16 value; 84 85 /* Set the PHY address and the register address we want to read */ 86 gfar_write(&regs->miimadd, (mii_id << 8) | regnum); 87 88 /* Clear miimcom, and then initiate a read */ 89 gfar_write(&regs->miimcom, 0); 90 gfar_write(&regs->miimcom, MII_READ_COMMAND); 91 92 /* Wait for the transaction to finish */ 93 while (gfar_read(&regs->miimind) & (MIIMIND_NOTVALID | MIIMIND_BUSY)) 94 cpu_relax(); 95 96 /* Grab the value of the register from miimstat */ 97 value = gfar_read(&regs->miimstat); 98 99 return value; 100} 101 102/* Write value to the PHY at mii_id at register regnum, 103 * on the bus, waiting until the write is done before returning. 104 * All PHY configuration is done through the TSEC1 MIIM regs */ 105int gfar_mdio_write(struct mii_bus *bus, int mii_id, int regnum, u16 value) 106{ 107 struct gfar_mii __iomem *regs = (void __iomem *)bus->priv; 108 109 /* Write to the local MII regs */ 110 return(gfar_local_mdio_write(regs, mii_id, regnum, value)); 111} 112 113/* Read the bus for PHY at addr mii_id, register regnum, and 114 * return the value. Clears miimcom first. All PHY 115 * configuration has to be done through the TSEC1 MIIM regs */ 116int gfar_mdio_read(struct mii_bus *bus, int mii_id, int regnum) 117{ 118 struct gfar_mii __iomem *regs = (void __iomem *)bus->priv; 119 120 /* Read the local MII regs */ 121 return(gfar_local_mdio_read(regs, mii_id, regnum)); 122} 123 124/* Reset the MIIM registers, and wait for the bus to free */ 125int gfar_mdio_reset(struct mii_bus *bus) 126{ 127 struct gfar_mii __iomem *regs = (void __iomem *)bus->priv; 128 unsigned int timeout = PHY_INIT_TIMEOUT; 129 130 mutex_lock(&bus->mdio_lock); 131 132 /* Reset the management interface */ 133 gfar_write(&regs->miimcfg, MIIMCFG_RESET); 134 135 /* Setup the MII Mgmt clock speed */ 136 gfar_write(&regs->miimcfg, MIIMCFG_INIT_VALUE); 137 138 /* Wait until the bus is free */ 139 while ((gfar_read(&regs->miimind) & MIIMIND_BUSY) && 140 timeout--) 141 cpu_relax(); 142 143 mutex_unlock(&bus->mdio_lock); 144 145 if(timeout <= 0) { 146 printk(KERN_ERR "%s: The MII Bus is stuck!\n", 147 bus->name); 148 return -EBUSY; 149 } 150 151 return 0; 152} 153 154 155int gfar_mdio_probe(struct device *dev) 156{ 157 struct platform_device *pdev = to_platform_device(dev); 158 struct gianfar_mdio_data *pdata; 159 struct gfar_mii __iomem *regs; 160 struct mii_bus *new_bus; 161 struct resource *r; 162 int err = 0; 163 164 if (NULL == dev) 165 return -EINVAL; 166 167 new_bus = kzalloc(sizeof(struct mii_bus), GFP_KERNEL); 168 169 if (NULL == new_bus) 170 return -ENOMEM; 171 172 new_bus->name = "Gianfar MII Bus", 173 new_bus->read = &gfar_mdio_read, 174 new_bus->write = &gfar_mdio_write, 175 new_bus->reset = &gfar_mdio_reset, 176 new_bus->id = pdev->id; 177 178 pdata = (struct gianfar_mdio_data *)pdev->dev.platform_data; 179 180 if (NULL == pdata) { 181 printk(KERN_ERR "gfar mdio %d: Missing platform data!\n", pdev->id); 182 return -ENODEV; 183 } 184 185 r = platform_get_resource(pdev, IORESOURCE_MEM, 0); 186 187 /* Set the PHY base address */ 188 regs = ioremap(r->start, sizeof (struct gfar_mii)); 189 190 if (NULL == regs) { 191 err = -ENOMEM; 192 goto reg_map_fail; 193 } 194 195 new_bus->priv = (void __force *)regs; 196 197 new_bus->irq = pdata->irq; 198 199 new_bus->dev = dev; 200 dev_set_drvdata(dev, new_bus); 201 202 err = mdiobus_register(new_bus); 203 204 if (0 != err) { 205 printk (KERN_ERR "%s: Cannot register as MDIO bus\n", 206 new_bus->name); 207 goto bus_register_fail; 208 } 209 210 return 0; 211 212bus_register_fail: 213 iounmap(regs); 214reg_map_fail: 215 kfree(new_bus); 216 217 return err; 218} 219 220 221int gfar_mdio_remove(struct device *dev) 222{ 223 struct mii_bus *bus = dev_get_drvdata(dev); 224 225 mdiobus_unregister(bus); 226 227 dev_set_drvdata(dev, NULL); 228 229 iounmap((void __iomem *)bus->priv); 230 bus->priv = NULL; 231 kfree(bus); 232 233 return 0; 234} 235 236static struct device_driver gianfar_mdio_driver = { 237 .name = "fsl-gianfar_mdio", 238 .bus = &platform_bus_type, 239 .probe = gfar_mdio_probe, 240 .remove = gfar_mdio_remove, 241}; 242 243int __init gfar_mdio_init(void) 244{ 245 return driver_register(&gianfar_mdio_driver); 246} 247 248void gfar_mdio_exit(void) 249{ 250 driver_unregister(&gianfar_mdio_driver); 251}