diff options
Diffstat (limited to 'drivers/net/stmmac/stmmac_mdio.c')
-rw-r--r-- | drivers/net/stmmac/stmmac_mdio.c | 83 |
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 | |||
195 | bus_register_fail: | 227 | bus_register_fail: |
196 | kfree(irqlist); | 228 | mdiobus_free(new_bus); |
197 | irqlist_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 | } |