aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/stmmac/stmmac_mdio.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/stmmac/stmmac_mdio.c')
-rw-r--r--drivers/net/stmmac/stmmac_mdio.c83
1 files changed, 57 insertions, 26 deletions
diff --git a/drivers/net/stmmac/stmmac_mdio.c b/drivers/net/stmmac/stmmac_mdio.c
index 29a6bb6b8058..9c3b9d5c3411 100644
--- a/drivers/net/stmmac/stmmac_mdio.c
+++ b/drivers/net/stmmac/stmmac_mdio.c
@@ -113,9 +113,9 @@ static int stmmac_mdio_reset(struct mii_bus *bus)
113 struct stmmac_priv *priv = netdev_priv(ndev); 113 struct stmmac_priv *priv = netdev_priv(ndev);
114 unsigned int mii_address = priv->hw->mii.addr; 114 unsigned int mii_address = priv->hw->mii.addr;
115 115
116 if (priv->phy_reset) { 116 if (priv->plat->mdio_bus_data->phy_reset) {
117 pr_debug("stmmac_mdio_reset: calling phy_reset\n"); 117 pr_debug("stmmac_mdio_reset: calling phy_reset\n");
118 priv->phy_reset(priv->plat->bsp_priv); 118 priv->plat->mdio_bus_data->phy_reset(priv->plat->bsp_priv);
119 } 119 }
120 120
121 /* This is a workaround for problems with the STE101P PHY. 121 /* This is a workaround for problems with the STE101P PHY.
@@ -138,30 +138,29 @@ int stmmac_mdio_register(struct net_device *ndev)
138 struct mii_bus *new_bus; 138 struct mii_bus *new_bus;
139 int *irqlist; 139 int *irqlist;
140 struct stmmac_priv *priv = netdev_priv(ndev); 140 struct stmmac_priv *priv = netdev_priv(ndev);
141 struct stmmac_mdio_bus_data *mdio_bus_data = priv->plat->mdio_bus_data;
141 int addr, found; 142 int addr, found;
142 143
144 if (!mdio_bus_data)
145 return 0;
146
143 new_bus = mdiobus_alloc(); 147 new_bus = mdiobus_alloc();
144 if (new_bus == NULL) 148 if (new_bus == NULL)
145 return -ENOMEM; 149 return -ENOMEM;
146 150
147 irqlist = kzalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL); 151 if (mdio_bus_data->irqs)
148 if (irqlist == NULL) { 152 irqlist = mdio_bus_data->irqs;
149 err = -ENOMEM; 153 else
150 goto irqlist_alloc_fail; 154 irqlist = priv->mii_irq;
151 }
152
153 /* Assign IRQ to phy at address phy_addr */
154 if (priv->phy_addr != -1)
155 irqlist[priv->phy_addr] = priv->phy_irq;
156 155
157 new_bus->name = "STMMAC MII Bus"; 156 new_bus->name = "STMMAC MII Bus";
158 new_bus->read = &stmmac_mdio_read; 157 new_bus->read = &stmmac_mdio_read;
159 new_bus->write = &stmmac_mdio_write; 158 new_bus->write = &stmmac_mdio_write;
160 new_bus->reset = &stmmac_mdio_reset; 159 new_bus->reset = &stmmac_mdio_reset;
161 snprintf(new_bus->id, MII_BUS_ID_SIZE, "%x", priv->plat->bus_id); 160 snprintf(new_bus->id, MII_BUS_ID_SIZE, "%x", mdio_bus_data->bus_id);
162 new_bus->priv = ndev; 161 new_bus->priv = ndev;
163 new_bus->irq = irqlist; 162 new_bus->irq = irqlist;
164 new_bus->phy_mask = priv->phy_mask; 163 new_bus->phy_mask = mdio_bus_data->phy_mask;
165 new_bus->parent = priv->device; 164 new_bus->parent = priv->device;
166 err = mdiobus_register(new_bus); 165 err = mdiobus_register(new_bus);
167 if (err != 0) { 166 if (err != 0) {
@@ -172,18 +171,50 @@ int stmmac_mdio_register(struct net_device *ndev)
172 priv->mii = new_bus; 171 priv->mii = new_bus;
173 172
174 found = 0; 173 found = 0;
175 for (addr = 0; addr < 32; addr++) { 174 for (addr = 0; addr < PHY_MAX_ADDR; addr++) {
176 struct phy_device *phydev = new_bus->phy_map[addr]; 175 struct phy_device *phydev = new_bus->phy_map[addr];
177 if (phydev) { 176 if (phydev) {
178 if (priv->phy_addr == -1) { 177 int act = 0;
179 priv->phy_addr = addr; 178 char irq_num[4];
180 phydev->irq = priv->phy_irq; 179 char *irq_str;
181 irqlist[addr] = priv->phy_irq; 180
181 /*
182 * If an IRQ was provided to be assigned after
183 * the bus probe, do it here.
184 */
185 if ((mdio_bus_data->irqs == NULL) &&
186 (mdio_bus_data->probed_phy_irq > 0)) {
187 irqlist[addr] = mdio_bus_data->probed_phy_irq;
188 phydev->irq = mdio_bus_data->probed_phy_irq;
182 } 189 }
183 pr_info("%s: PHY ID %08x at %d IRQ %d (%s)%s\n", 190
184 ndev->name, phydev->phy_id, addr, 191 /*
185 phydev->irq, dev_name(&phydev->dev), 192 * If we're going to bind the MAC to this PHY bus,
186 (addr == priv->phy_addr) ? " active" : ""); 193 * and no PHY number was provided to the MAC,
194 * use the one probed here.
195 */
196 if ((priv->plat->bus_id == mdio_bus_data->bus_id) &&
197 (priv->plat->phy_addr == -1))
198 priv->plat->phy_addr = addr;
199
200 act = (priv->plat->bus_id == mdio_bus_data->bus_id) &&
201 (priv->plat->phy_addr == addr);
202 switch (phydev->irq) {
203 case PHY_POLL:
204 irq_str = "POLL";
205 break;
206 case PHY_IGNORE_INTERRUPT:
207 irq_str = "IGNORE";
208 break;
209 default:
210 sprintf(irq_num, "%d", phydev->irq);
211 irq_str = irq_num;
212 break;
213 }
214 pr_info("%s: PHY ID %08x at %d IRQ %s (%s)%s\n",
215 ndev->name, phydev->phy_id, addr,
216 irq_str, dev_name(&phydev->dev),
217 act ? " active" : "");
187 found = 1; 218 found = 1;
188 } 219 }
189 } 220 }
@@ -192,10 +223,9 @@ int stmmac_mdio_register(struct net_device *ndev)
192 pr_warning("%s: No PHY found\n", ndev->name); 223 pr_warning("%s: No PHY found\n", ndev->name);
193 224
194 return 0; 225 return 0;
226
195bus_register_fail: 227bus_register_fail:
196 kfree(irqlist); 228 mdiobus_free(new_bus);
197irqlist_alloc_fail:
198 kfree(new_bus);
199 return err; 229 return err;
200} 230}
201 231
@@ -210,7 +240,8 @@ int stmmac_mdio_unregister(struct net_device *ndev)
210 240
211 mdiobus_unregister(priv->mii); 241 mdiobus_unregister(priv->mii);
212 priv->mii->priv = NULL; 242 priv->mii->priv = NULL;
213 kfree(priv->mii); 243 mdiobus_free(priv->mii);
244 priv->mii = NULL;
214 245
215 return 0; 246 return 0;
216} 247}