Commit 36bcfe7d74782c07f601edc4831f6b1ef40e9e43
Committed by
David S. Miller
1 parent
f3240e2811
Exists in
master
and in
6 other branches
stmmac: unify MAC and PHY configuration parameters (V2)
Prior to this change, most PHY configuration parameters were passed into the STMMAC device as a separate PHY device. As well as being unusual, this made it difficult to make changes to the MAC/PHY relationship. This patch moves all the PHY parameters into the MAC configuration structure, mainly as a separate structure. This allows us to completely ignore the MDIO bus attached to a stmmac if desired, and not create the PHY bus. It also allows the stmmac driver to use a different PHY from the one it is connected to, for example a fixed PHY or bit banging PHY. Also derive the stmmac/PHY connection type (MII/RMII etc) from the mode can be passed into <platf>_configure_ethernet. STLinux kernel at git://git.stlinux.com/stm/linux-sh4-2.6.32.y.git provides several examples how to use this new infrastructure (that actually is easier to maintain and clearer). Signed-off-by: Stuart Menefy <stuart.menefy@st.com> Signed-off-by: Giuseppe Cavallaro <peppe.cavallaro@st.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Showing 4 changed files with 77 additions and 131 deletions Side-by-side Diff
drivers/net/stmmac/stmmac.h
... | ... | @@ -56,14 +56,9 @@ |
56 | 56 | struct stmmac_extra_stats xstats; |
57 | 57 | struct napi_struct napi; |
58 | 58 | |
59 | - phy_interface_t phy_interface; | |
60 | - int phy_addr; | |
61 | - int phy_mask; | |
62 | - int (*phy_reset) (void *priv); | |
63 | 59 | int rx_coe; |
64 | 60 | int no_csum_insertion; |
65 | 61 | |
66 | - int phy_irq; | |
67 | 62 | struct phy_device *phydev; |
68 | 63 | int oldlink; |
69 | 64 | int speed; |
... | ... | @@ -71,6 +66,7 @@ |
71 | 66 | unsigned int flow_ctrl; |
72 | 67 | unsigned int pause; |
73 | 68 | struct mii_bus *mii; |
69 | + int mii_irq[PHY_MAX_ADDR]; | |
74 | 70 | |
75 | 71 | u32 msg_enable; |
76 | 72 | spinlock_t lock; |
drivers/net/stmmac/stmmac_main.c
... | ... | @@ -49,7 +49,6 @@ |
49 | 49 | #include "stmmac.h" |
50 | 50 | |
51 | 51 | #define STMMAC_RESOURCE_NAME "stmmaceth" |
52 | -#define PHY_RESOURCE_NAME "stmmacphy" | |
53 | 52 | |
54 | 53 | #undef STMMAC_DEBUG |
55 | 54 | /*#define STMMAC_DEBUG*/ |
56 | 55 | |
57 | 56 | |
... | ... | @@ -305,18 +304,13 @@ |
305 | 304 | priv->speed = 0; |
306 | 305 | priv->oldduplex = -1; |
307 | 306 | |
308 | - if (priv->phy_addr == -1) { | |
309 | - /* We don't have a PHY, so do nothing */ | |
310 | - return 0; | |
311 | - } | |
312 | - | |
313 | 307 | snprintf(bus_id, MII_BUS_ID_SIZE, "%x", priv->plat->bus_id); |
314 | 308 | snprintf(phy_id, MII_BUS_ID_SIZE + 3, PHY_ID_FMT, bus_id, |
315 | - priv->phy_addr); | |
309 | + priv->plat->phy_addr); | |
316 | 310 | pr_debug("stmmac_init_phy: trying to attach to %s\n", phy_id); |
317 | 311 | |
318 | 312 | phydev = phy_connect(dev, phy_id, &stmmac_adjust_link, 0, |
319 | - priv->phy_interface); | |
313 | + priv->plat->interface); | |
320 | 314 | |
321 | 315 | if (IS_ERR(phydev)) { |
322 | 316 | pr_err("%s: Could not attach to PHY\n", dev->name); |
... | ... | @@ -335,7 +329,7 @@ |
335 | 329 | return -ENODEV; |
336 | 330 | } |
337 | 331 | pr_debug("stmmac_init_phy: %s: attached to PHY (UID 0x%x)" |
338 | - " Link = %d\n", dev->name, phydev->phy_id, phydev->link); | |
332 | + " Link = %d\n", dev->name, phydev->phy_id, phydev->link); | |
339 | 333 | |
340 | 334 | priv->phydev = phydev; |
341 | 335 | |
342 | 336 | |
... | ... | @@ -1528,72 +1522,7 @@ |
1528 | 1522 | return 0; |
1529 | 1523 | } |
1530 | 1524 | |
1531 | -static int stmmacphy_dvr_probe(struct platform_device *pdev) | |
1532 | -{ | |
1533 | - struct plat_stmmacphy_data *plat_dat = pdev->dev.platform_data; | |
1534 | - | |
1535 | - pr_debug("stmmacphy_dvr_probe: added phy for bus %d\n", | |
1536 | - plat_dat->bus_id); | |
1537 | - | |
1538 | - return 0; | |
1539 | -} | |
1540 | - | |
1541 | -static int stmmacphy_dvr_remove(struct platform_device *pdev) | |
1542 | -{ | |
1543 | - return 0; | |
1544 | -} | |
1545 | - | |
1546 | -static struct platform_driver stmmacphy_driver = { | |
1547 | - .driver = { | |
1548 | - .name = PHY_RESOURCE_NAME, | |
1549 | - }, | |
1550 | - .probe = stmmacphy_dvr_probe, | |
1551 | - .remove = stmmacphy_dvr_remove, | |
1552 | -}; | |
1553 | - | |
1554 | 1525 | /** |
1555 | - * stmmac_associate_phy | |
1556 | - * @dev: pointer to device structure | |
1557 | - * @data: points to the private structure. | |
1558 | - * Description: Scans through all the PHYs we have registered and checks if | |
1559 | - * any are associated with our MAC. If so, then just fill in | |
1560 | - * the blanks in our local context structure | |
1561 | - */ | |
1562 | -static int stmmac_associate_phy(struct device *dev, void *data) | |
1563 | -{ | |
1564 | - struct stmmac_priv *priv = (struct stmmac_priv *)data; | |
1565 | - struct plat_stmmacphy_data *plat_dat = dev->platform_data; | |
1566 | - | |
1567 | - DBG(probe, DEBUG, "%s: checking phy for bus %d\n", __func__, | |
1568 | - plat_dat->bus_id); | |
1569 | - | |
1570 | - /* Check that this phy is for the MAC being initialised */ | |
1571 | - if (priv->plat->bus_id != plat_dat->bus_id) | |
1572 | - return 0; | |
1573 | - | |
1574 | - /* OK, this PHY is connected to the MAC. | |
1575 | - Go ahead and get the parameters */ | |
1576 | - DBG(probe, DEBUG, "%s: OK. Found PHY config\n", __func__); | |
1577 | - priv->phy_irq = | |
1578 | - platform_get_irq_byname(to_platform_device(dev), "phyirq"); | |
1579 | - DBG(probe, DEBUG, "%s: PHY irq on bus %d is %d\n", __func__, | |
1580 | - plat_dat->bus_id, priv->phy_irq); | |
1581 | - | |
1582 | - /* Override with kernel parameters if supplied XXX CRS XXX | |
1583 | - * this needs to have multiple instances */ | |
1584 | - if ((phyaddr >= 0) && (phyaddr <= 31)) | |
1585 | - plat_dat->phy_addr = phyaddr; | |
1586 | - | |
1587 | - priv->phy_addr = plat_dat->phy_addr; | |
1588 | - priv->phy_mask = plat_dat->phy_mask; | |
1589 | - priv->phy_interface = plat_dat->interface; | |
1590 | - priv->phy_reset = plat_dat->phy_reset; | |
1591 | - | |
1592 | - DBG(probe, DEBUG, "%s: exiting\n", __func__); | |
1593 | - return 1; /* forces exit of driver_for_each_device() */ | |
1594 | -} | |
1595 | - | |
1596 | -/** | |
1597 | 1526 | * stmmac_dvr_probe |
1598 | 1527 | * @pdev: platform device pointer |
1599 | 1528 | * Description: the driver is initialized through platform_device. |
... | ... | @@ -1683,14 +1612,10 @@ |
1683 | 1612 | if (ret < 0) |
1684 | 1613 | goto out_plat_exit; |
1685 | 1614 | |
1686 | - /* associate a PHY - it is provided by another platform bus */ | |
1687 | - if (!driver_for_each_device | |
1688 | - (&(stmmacphy_driver.driver), NULL, (void *)priv, | |
1689 | - stmmac_associate_phy)) { | |
1690 | - pr_err("No PHY device is associated with this MAC!\n"); | |
1691 | - ret = -ENODEV; | |
1692 | - goto out_unregister; | |
1693 | - } | |
1615 | + /* Override with kernel parameters if supplied XXX CRS XXX | |
1616 | + * this needs to have multiple instances */ | |
1617 | + if ((phyaddr >= 0) && (phyaddr <= 31)) | |
1618 | + priv->plat->phy_addr = phyaddr; | |
1694 | 1619 | |
1695 | 1620 | pr_info("\t%s - (dev. name: %s - id: %d, IRQ #%d\n" |
1696 | 1621 | "\tIO base addr: 0x%p)\n", ndev->name, pdev->name, |
... | ... | @@ -1890,11 +1815,6 @@ |
1890 | 1815 | { |
1891 | 1816 | int ret; |
1892 | 1817 | |
1893 | - if (platform_driver_register(&stmmacphy_driver)) { | |
1894 | - pr_err("No PHY devices registered!\n"); | |
1895 | - return -ENODEV; | |
1896 | - } | |
1897 | - | |
1898 | 1818 | ret = platform_driver_register(&stmmac_driver); |
1899 | 1819 | return ret; |
1900 | 1820 | } |
... | ... | @@ -1905,7 +1825,6 @@ |
1905 | 1825 | */ |
1906 | 1826 | static void __exit stmmac_cleanup_module(void) |
1907 | 1827 | { |
1908 | - platform_driver_unregister(&stmmacphy_driver); | |
1909 | 1828 | platform_driver_unregister(&stmmac_driver); |
1910 | 1829 | } |
1911 | 1830 |
drivers/net/stmmac/stmmac_mdio.c
... | ... | @@ -113,9 +113,9 @@ |
113 | 113 | struct stmmac_priv *priv = netdev_priv(ndev); |
114 | 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 | 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 | 121 | /* This is a workaround for problems with the STE101P PHY. |
122 | 122 | |
123 | 123 | |
124 | 124 | |
125 | 125 | |
126 | 126 | |
... | ... | @@ -138,30 +138,29 @@ |
138 | 138 | struct mii_bus *new_bus; |
139 | 139 | int *irqlist; |
140 | 140 | struct stmmac_priv *priv = netdev_priv(ndev); |
141 | + struct stmmac_mdio_bus_data *mdio_bus_data = priv->plat->mdio_bus_data; | |
141 | 142 | int addr, found; |
142 | 143 | |
144 | + if (!mdio_bus_data) | |
145 | + return 0; | |
146 | + | |
143 | 147 | new_bus = mdiobus_alloc(); |
144 | 148 | if (new_bus == NULL) |
145 | 149 | return -ENOMEM; |
146 | 150 | |
147 | - irqlist = kzalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL); | |
148 | - if (irqlist == NULL) { | |
149 | - err = -ENOMEM; | |
150 | - goto irqlist_alloc_fail; | |
151 | - } | |
151 | + if (mdio_bus_data->irqs) | |
152 | + irqlist = mdio_bus_data->irqs; | |
153 | + else | |
154 | + irqlist = priv->mii_irq; | |
152 | 155 | |
153 | - /* Assign IRQ to phy at address phy_addr */ | |
154 | - if (priv->phy_addr != -1) | |
155 | - irqlist[priv->phy_addr] = priv->phy_irq; | |
156 | - | |
157 | 156 | new_bus->name = "STMMAC MII Bus"; |
158 | 157 | new_bus->read = &stmmac_mdio_read; |
159 | 158 | new_bus->write = &stmmac_mdio_write; |
160 | 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 | 161 | new_bus->priv = ndev; |
163 | 162 | new_bus->irq = irqlist; |
164 | - new_bus->phy_mask = priv->phy_mask; | |
163 | + new_bus->phy_mask = mdio_bus_data->phy_mask; | |
165 | 164 | new_bus->parent = priv->device; |
166 | 165 | err = mdiobus_register(new_bus); |
167 | 166 | if (err != 0) { |
168 | 167 | |
169 | 168 | |
... | ... | @@ -172,18 +171,50 @@ |
172 | 171 | priv->mii = new_bus; |
173 | 172 | |
174 | 173 | found = 0; |
175 | - for (addr = 0; addr < 32; addr++) { | |
174 | + for (addr = 0; addr < PHY_MAX_ADDR; addr++) { | |
176 | 175 | struct phy_device *phydev = new_bus->phy_map[addr]; |
177 | 176 | if (phydev) { |
178 | - if (priv->phy_addr == -1) { | |
179 | - priv->phy_addr = addr; | |
180 | - phydev->irq = priv->phy_irq; | |
181 | - irqlist[addr] = priv->phy_irq; | |
177 | + int act = 0; | |
178 | + char irq_num[4]; | |
179 | + char *irq_str; | |
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", | |
184 | - ndev->name, phydev->phy_id, addr, | |
185 | - phydev->irq, dev_name(&phydev->dev), | |
186 | - (addr == priv->phy_addr) ? " active" : ""); | |
190 | + | |
191 | + /* | |
192 | + * If we're going to bind the MAC to this PHY bus, | |
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 | 218 | found = 1; |
188 | 219 | } |
189 | 220 | } |
190 | 221 | |
... | ... | @@ -192,10 +223,9 @@ |
192 | 223 | pr_warning("%s: No PHY found\n", ndev->name); |
193 | 224 | |
194 | 225 | return 0; |
226 | + | |
195 | 227 | bus_register_fail: |
196 | - kfree(irqlist); | |
197 | -irqlist_alloc_fail: | |
198 | - kfree(new_bus); | |
228 | + mdiobus_free(new_bus); | |
199 | 229 | return err; |
200 | 230 | } |
201 | 231 | |
... | ... | @@ -210,7 +240,8 @@ |
210 | 240 | |
211 | 241 | mdiobus_unregister(priv->mii); |
212 | 242 | priv->mii->priv = NULL; |
213 | - kfree(priv->mii); | |
243 | + mdiobus_free(priv->mii); | |
244 | + priv->mii = NULL; | |
214 | 245 | |
215 | 246 | return 0; |
216 | 247 | } |
include/linux/stmmac.h
... | ... | @@ -28,11 +28,21 @@ |
28 | 28 | |
29 | 29 | #include <linux/platform_device.h> |
30 | 30 | |
31 | -/* platform data for platform device structure's platform_data field */ | |
31 | +/* Platfrom data for platform device structure's platform_data field */ | |
32 | 32 | |
33 | -/* Private data for the STM on-board ethernet driver */ | |
33 | +struct stmmac_mdio_bus_data { | |
34 | + int bus_id; | |
35 | + int (*phy_reset)(void *priv); | |
36 | + unsigned int phy_mask; | |
37 | + int *irqs; | |
38 | + int probed_phy_irq; | |
39 | +}; | |
40 | + | |
34 | 41 | struct plat_stmmacenet_data { |
35 | 42 | int bus_id; |
43 | + int phy_addr; | |
44 | + int interface; | |
45 | + struct stmmac_mdio_bus_data *mdio_bus_data; | |
36 | 46 | int pbl; |
37 | 47 | int clk_csr; |
38 | 48 | int has_gmac; |
... | ... | @@ -47,15 +57,6 @@ |
47 | 57 | void (*exit)(struct platform_device *pdev); |
48 | 58 | void *custom_cfg; |
49 | 59 | void *bsp_priv; |
50 | -}; | |
51 | - | |
52 | -struct plat_stmmacphy_data { | |
53 | - int bus_id; | |
54 | - int phy_addr; | |
55 | - unsigned int phy_mask; | |
56 | - int interface; | |
57 | - int (*phy_reset)(void *priv); | |
58 | - void *priv; | |
59 | 60 | }; |
60 | 61 | #endif |