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 v3.11 249 lines 6.5 kB view raw
1/* 2 * OF helpers for the MDIO (Ethernet PHY) API 3 * 4 * Copyright (c) 2009 Secret Lab Technologies, Ltd. 5 * 6 * This file is released under the GPLv2 7 * 8 * This file provides helper functions for extracting PHY device information 9 * out of the OpenFirmware device tree and using it to populate an mii_bus. 10 */ 11 12#include <linux/kernel.h> 13#include <linux/device.h> 14#include <linux/netdevice.h> 15#include <linux/err.h> 16#include <linux/phy.h> 17#include <linux/of.h> 18#include <linux/of_irq.h> 19#include <linux/of_mdio.h> 20#include <linux/module.h> 21 22MODULE_AUTHOR("Grant Likely <grant.likely@secretlab.ca>"); 23MODULE_LICENSE("GPL"); 24 25/** 26 * of_mdiobus_register - Register mii_bus and create PHYs from the device tree 27 * @mdio: pointer to mii_bus structure 28 * @np: pointer to device_node of MDIO bus. 29 * 30 * This function registers the mii_bus structure and registers a phy_device 31 * for each child node of @np. 32 */ 33int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np) 34{ 35 struct phy_device *phy; 36 struct device_node *child; 37 const __be32 *paddr; 38 u32 addr; 39 bool is_c45, scanphys = false; 40 int rc, i, len; 41 42 /* Mask out all PHYs from auto probing. Instead the PHYs listed in 43 * the device tree are populated after the bus has been registered */ 44 mdio->phy_mask = ~0; 45 46 /* Clear all the IRQ properties */ 47 if (mdio->irq) 48 for (i=0; i<PHY_MAX_ADDR; i++) 49 mdio->irq[i] = PHY_POLL; 50 51 mdio->dev.of_node = np; 52 53 /* Register the MDIO bus */ 54 rc = mdiobus_register(mdio); 55 if (rc) 56 return rc; 57 58 /* Loop over the child nodes and register a phy_device for each one */ 59 for_each_available_child_of_node(np, child) { 60 /* A PHY must have a reg property in the range [0-31] */ 61 paddr = of_get_property(child, "reg", &len); 62 if (!paddr || len < sizeof(*paddr)) { 63 scanphys = true; 64 dev_err(&mdio->dev, "%s has invalid PHY address\n", 65 child->full_name); 66 continue; 67 } 68 69 addr = be32_to_cpup(paddr); 70 if (addr >= 32) { 71 dev_err(&mdio->dev, "%s PHY address %i is too large\n", 72 child->full_name, addr); 73 continue; 74 } 75 76 if (mdio->irq) { 77 mdio->irq[addr] = irq_of_parse_and_map(child, 0); 78 if (!mdio->irq[addr]) 79 mdio->irq[addr] = PHY_POLL; 80 } 81 82 is_c45 = of_device_is_compatible(child, 83 "ethernet-phy-ieee802.3-c45"); 84 phy = get_phy_device(mdio, addr, is_c45); 85 86 if (!phy || IS_ERR(phy)) { 87 dev_err(&mdio->dev, 88 "cannot get PHY at address %i\n", 89 addr); 90 continue; 91 } 92 93 /* Associate the OF node with the device structure so it 94 * can be looked up later */ 95 of_node_get(child); 96 phy->dev.of_node = child; 97 98 /* All data is now stored in the phy struct; register it */ 99 rc = phy_device_register(phy); 100 if (rc) { 101 phy_device_free(phy); 102 of_node_put(child); 103 continue; 104 } 105 106 dev_dbg(&mdio->dev, "registered phy %s at address %i\n", 107 child->name, addr); 108 } 109 110 if (!scanphys) 111 return 0; 112 113 /* auto scan for PHYs with empty reg property */ 114 for_each_available_child_of_node(np, child) { 115 /* Skip PHYs with reg property set */ 116 paddr = of_get_property(child, "reg", &len); 117 if (paddr) 118 continue; 119 120 is_c45 = of_device_is_compatible(child, 121 "ethernet-phy-ieee802.3-c45"); 122 123 for (addr = 0; addr < PHY_MAX_ADDR; addr++) { 124 /* skip already registered PHYs */ 125 if (mdio->phy_map[addr]) 126 continue; 127 128 /* be noisy to encourage people to set reg property */ 129 dev_info(&mdio->dev, "scan phy %s at address %i\n", 130 child->name, addr); 131 132 phy = get_phy_device(mdio, addr, is_c45); 133 if (!phy || IS_ERR(phy)) 134 continue; 135 136 if (mdio->irq) { 137 mdio->irq[addr] = 138 irq_of_parse_and_map(child, 0); 139 if (!mdio->irq[addr]) 140 mdio->irq[addr] = PHY_POLL; 141 } 142 143 /* Associate the OF node with the device structure so it 144 * can be looked up later */ 145 of_node_get(child); 146 phy->dev.of_node = child; 147 148 /* All data is now stored in the phy struct; 149 * register it */ 150 rc = phy_device_register(phy); 151 if (rc) { 152 phy_device_free(phy); 153 of_node_put(child); 154 continue; 155 } 156 157 dev_info(&mdio->dev, "registered phy %s at address %i\n", 158 child->name, addr); 159 break; 160 } 161 } 162 163 return 0; 164} 165EXPORT_SYMBOL(of_mdiobus_register); 166 167/* Helper function for of_phy_find_device */ 168static int of_phy_match(struct device *dev, void *phy_np) 169{ 170 return dev->of_node == phy_np; 171} 172 173/** 174 * of_phy_find_device - Give a PHY node, find the phy_device 175 * @phy_np: Pointer to the phy's device tree node 176 * 177 * Returns a pointer to the phy_device. 178 */ 179struct phy_device *of_phy_find_device(struct device_node *phy_np) 180{ 181 struct device *d; 182 if (!phy_np) 183 return NULL; 184 185 d = bus_find_device(&mdio_bus_type, NULL, phy_np, of_phy_match); 186 return d ? to_phy_device(d) : NULL; 187} 188EXPORT_SYMBOL(of_phy_find_device); 189 190/** 191 * of_phy_connect - Connect to the phy described in the device tree 192 * @dev: pointer to net_device claiming the phy 193 * @phy_np: Pointer to device tree node for the PHY 194 * @hndlr: Link state callback for the network device 195 * @iface: PHY data interface type 196 * 197 * Returns a pointer to the phy_device if successful. NULL otherwise 198 */ 199struct phy_device *of_phy_connect(struct net_device *dev, 200 struct device_node *phy_np, 201 void (*hndlr)(struct net_device *), u32 flags, 202 phy_interface_t iface) 203{ 204 struct phy_device *phy = of_phy_find_device(phy_np); 205 206 if (!phy) 207 return NULL; 208 209 return phy_connect_direct(dev, phy, hndlr, iface) ? NULL : phy; 210} 211EXPORT_SYMBOL(of_phy_connect); 212 213/** 214 * of_phy_connect_fixed_link - Parse fixed-link property and return a dummy phy 215 * @dev: pointer to net_device claiming the phy 216 * @hndlr: Link state callback for the network device 217 * @iface: PHY data interface type 218 * 219 * This function is a temporary stop-gap and will be removed soon. It is 220 * only to support the fs_enet, ucc_geth and gianfar Ethernet drivers. Do 221 * not call this function from new drivers. 222 */ 223struct phy_device *of_phy_connect_fixed_link(struct net_device *dev, 224 void (*hndlr)(struct net_device *), 225 phy_interface_t iface) 226{ 227 struct device_node *net_np; 228 char bus_id[MII_BUS_ID_SIZE + 3]; 229 struct phy_device *phy; 230 const __be32 *phy_id; 231 int sz; 232 233 if (!dev->dev.parent) 234 return NULL; 235 236 net_np = dev->dev.parent->of_node; 237 if (!net_np) 238 return NULL; 239 240 phy_id = of_get_property(net_np, "fixed-link", &sz); 241 if (!phy_id || sz < sizeof(*phy_id)) 242 return NULL; 243 244 sprintf(bus_id, PHY_ID_FMT, "fixed-0", be32_to_cpu(phy_id[0])); 245 246 phy = phy_connect(dev, bus_id, hndlr, iface); 247 return IS_ERR(phy) ? NULL : phy; 248} 249EXPORT_SYMBOL(of_phy_connect_fixed_link);