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 v2.6.24 278 lines 7.0 kB view raw
1/* 2 * drivers/net/ucc_geth_mii.c 3 * 4 * QE UCC Gigabit Ethernet Driver -- MII Management Bus Implementation 5 * Provides Bus interface for MII Management regs in the UCC register space 6 * 7 * Copyright (C) 2007 Freescale Semiconductor, Inc. 8 * 9 * Authors: Li Yang <leoli@freescale.com> 10 * Kim Phillips <kim.phillips@freescale.com> 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/sched.h> 21#include <linux/string.h> 22#include <linux/errno.h> 23#include <linux/unistd.h> 24#include <linux/slab.h> 25#include <linux/interrupt.h> 26#include <linux/init.h> 27#include <linux/delay.h> 28#include <linux/netdevice.h> 29#include <linux/etherdevice.h> 30#include <linux/skbuff.h> 31#include <linux/spinlock.h> 32#include <linux/mm.h> 33#include <linux/module.h> 34#include <linux/platform_device.h> 35#include <linux/crc32.h> 36#include <linux/mii.h> 37#include <linux/phy.h> 38#include <linux/fsl_devices.h> 39 40#include <asm/of_platform.h> 41#include <asm/io.h> 42#include <asm/irq.h> 43#include <asm/uaccess.h> 44#include <asm/ucc.h> 45 46#include "ucc_geth_mii.h" 47#include "ucc_geth.h" 48 49#define DEBUG 50#ifdef DEBUG 51#define vdbg(format, arg...) printk(KERN_DEBUG , format "\n" , ## arg) 52#else 53#define vdbg(format, arg...) do {} while(0) 54#endif 55 56#define MII_DRV_DESC "QE UCC Ethernet Controller MII Bus" 57#define MII_DRV_NAME "fsl-uec_mdio" 58 59/* Write value to the PHY for this device to the register at regnum, */ 60/* waiting until the write is done before it returns. All PHY */ 61/* configuration has to be done through the master UEC MIIM regs */ 62int uec_mdio_write(struct mii_bus *bus, int mii_id, int regnum, u16 value) 63{ 64 struct ucc_mii_mng __iomem *regs = (void __iomem *)bus->priv; 65 66 /* Setting up the MII Mangement Address Register */ 67 out_be32(&regs->miimadd, 68 (mii_id << MIIMADD_PHY_ADDRESS_SHIFT) | regnum); 69 70 /* Setting up the MII Mangement Control Register with the value */ 71 out_be32(&regs->miimcon, value); 72 73 /* Wait till MII management write is complete */ 74 while ((in_be32(&regs->miimind)) & MIIMIND_BUSY) 75 cpu_relax(); 76 77 return 0; 78} 79 80/* Reads from register regnum in the PHY for device dev, */ 81/* returning the value. Clears miimcom first. All PHY */ 82/* configuration has to be done through the TSEC1 MIIM regs */ 83int uec_mdio_read(struct mii_bus *bus, int mii_id, int regnum) 84{ 85 struct ucc_mii_mng __iomem *regs = (void __iomem *)bus->priv; 86 u16 value; 87 88 /* Setting up the MII Mangement Address Register */ 89 out_be32(&regs->miimadd, 90 (mii_id << MIIMADD_PHY_ADDRESS_SHIFT) | regnum); 91 92 /* Clear miimcom, perform an MII management read cycle */ 93 out_be32(&regs->miimcom, 0); 94 out_be32(&regs->miimcom, MIIMCOM_READ_CYCLE); 95 96 /* Wait till MII management write is complete */ 97 while ((in_be32(&regs->miimind)) & (MIIMIND_BUSY | MIIMIND_NOT_VALID)) 98 cpu_relax(); 99 100 /* Read MII management status */ 101 value = in_be32(&regs->miimstat); 102 103 return value; 104} 105 106/* Reset the MIIM registers, and wait for the bus to free */ 107int uec_mdio_reset(struct mii_bus *bus) 108{ 109 struct ucc_mii_mng __iomem *regs = (void __iomem *)bus->priv; 110 unsigned int timeout = PHY_INIT_TIMEOUT; 111 112 spin_lock_bh(&bus->mdio_lock); 113 114 /* Reset the management interface */ 115 out_be32(&regs->miimcfg, MIIMCFG_RESET_MANAGEMENT); 116 117 /* Setup the MII Mgmt clock speed */ 118 out_be32(&regs->miimcfg, MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_112); 119 120 /* Wait until the bus is free */ 121 while ((in_be32(&regs->miimind) & MIIMIND_BUSY) && timeout--) 122 cpu_relax(); 123 124 spin_unlock_bh(&bus->mdio_lock); 125 126 if (timeout <= 0) { 127 printk(KERN_ERR "%s: The MII Bus is stuck!\n", bus->name); 128 return -EBUSY; 129 } 130 131 return 0; 132} 133 134static int uec_mdio_probe(struct of_device *ofdev, const struct of_device_id *match) 135{ 136 struct device *device = &ofdev->dev; 137 struct device_node *np = ofdev->node, *tempnp = NULL; 138 struct device_node *child = NULL; 139 struct ucc_mii_mng __iomem *regs; 140 struct mii_bus *new_bus; 141 struct resource res; 142 int k, err = 0; 143 144 new_bus = kzalloc(sizeof(struct mii_bus), GFP_KERNEL); 145 146 if (NULL == new_bus) 147 return -ENOMEM; 148 149 new_bus->name = "UCC Ethernet Controller MII Bus"; 150 new_bus->read = &uec_mdio_read; 151 new_bus->write = &uec_mdio_write; 152 new_bus->reset = &uec_mdio_reset; 153 154 memset(&res, 0, sizeof(res)); 155 156 err = of_address_to_resource(np, 0, &res); 157 if (err) 158 goto reg_map_fail; 159 160 new_bus->id = res.start; 161 162 new_bus->irq = kmalloc(32 * sizeof(int), GFP_KERNEL); 163 164 if (NULL == new_bus->irq) { 165 err = -ENOMEM; 166 goto reg_map_fail; 167 } 168 169 for (k = 0; k < 32; k++) 170 new_bus->irq[k] = PHY_POLL; 171 172 while ((child = of_get_next_child(np, child)) != NULL) { 173 int irq = irq_of_parse_and_map(child, 0); 174 if (irq != NO_IRQ) { 175 const u32 *id = of_get_property(child, "reg", NULL); 176 new_bus->irq[*id] = irq; 177 } 178 } 179 180 /* Set the base address */ 181 regs = ioremap(res.start, sizeof(struct ucc_mii_mng)); 182 183 if (NULL == regs) { 184 err = -ENOMEM; 185 goto ioremap_fail; 186 } 187 188 new_bus->priv = (void __force *)regs; 189 190 new_bus->dev = device; 191 dev_set_drvdata(device, new_bus); 192 193 /* Read MII management master from device tree */ 194 while ((tempnp = of_find_compatible_node(tempnp, "network", "ucc_geth")) 195 != NULL) { 196 struct resource tempres; 197 198 err = of_address_to_resource(tempnp, 0, &tempres); 199 if (err) 200 goto bus_register_fail; 201 202 /* if our mdio regs fall within this UCC regs range */ 203 if ((res.start >= tempres.start) && 204 (res.end <= tempres.end)) { 205 /* set this UCC to be the MII master */ 206 const u32 *id = of_get_property(tempnp, "device-id", NULL); 207 if (id == NULL) 208 goto bus_register_fail; 209 210 ucc_set_qe_mux_mii_mng(*id - 1); 211 212 /* assign the TBI an address which won't 213 * conflict with the PHYs */ 214 out_be32(&regs->utbipar, UTBIPAR_INIT_TBIPA); 215 break; 216 } 217 } 218 219 err = mdiobus_register(new_bus); 220 if (0 != err) { 221 printk(KERN_ERR "%s: Cannot register as MDIO bus\n", 222 new_bus->name); 223 goto bus_register_fail; 224 } 225 226 return 0; 227 228bus_register_fail: 229 iounmap(regs); 230ioremap_fail: 231 kfree(new_bus->irq); 232reg_map_fail: 233 kfree(new_bus); 234 235 return err; 236} 237 238int uec_mdio_remove(struct of_device *ofdev) 239{ 240 struct device *device = &ofdev->dev; 241 struct mii_bus *bus = dev_get_drvdata(device); 242 243 mdiobus_unregister(bus); 244 245 dev_set_drvdata(device, NULL); 246 247 iounmap((void __iomem *)bus->priv); 248 bus->priv = NULL; 249 kfree(bus); 250 251 return 0; 252} 253 254static struct of_device_id uec_mdio_match[] = { 255 { 256 .type = "mdio", 257 .compatible = "ucc_geth_phy", 258 }, 259 {}, 260}; 261 262static struct of_platform_driver uec_mdio_driver = { 263 .name = MII_DRV_NAME, 264 .probe = uec_mdio_probe, 265 .remove = uec_mdio_remove, 266 .match_table = uec_mdio_match, 267}; 268 269int __init uec_mdio_init(void) 270{ 271 return of_register_platform_driver(&uec_mdio_driver); 272} 273 274/* called from __init ucc_geth_init, therefore can not be __exit */ 275void uec_mdio_exit(void) 276{ 277 of_unregister_platform_driver(&uec_mdio_driver); 278}