diff --git a/board/gdsys/a38x/ihs_phys.c b/board/gdsys/a38x/ihs_phys.c index 690a29690b9..0c68087912a 100644 --- a/board/gdsys/a38x/ihs_phys.c +++ b/board/gdsys/a38x/ihs_phys.c @@ -102,102 +102,6 @@ uint calculate_octo_phy_mask(void) return octo_phy_mask; } -int register_miiphy_bus(uint k, struct mii_dev **bus) -{ - int retval; - struct mii_dev *mdiodev = mdio_alloc(); - char *name = bb_miiphy_buses[k].name; - - if (!mdiodev) - return -ENOMEM; - strlcpy(mdiodev->name, name, MDIO_NAME_LEN); - mdiodev->read = bb_miiphy_read; - mdiodev->write = bb_miiphy_write; - - retval = mdio_register(mdiodev); - if (retval < 0) - return retval; - *bus = miiphy_get_dev_by_name(name); - - return 0; -} - -struct porttype *get_porttype(uint octo_phy_mask, uint k) -{ - uint octo_index = k * 4; - - if (!k) { - if (octo_phy_mask & 0x01) - return &porttypes[PORTTYPE_MAIN_CAT]; - else if (!(octo_phy_mask & 0x03)) - return &porttypes[PORTTYPE_16C_16F]; - } else { - if (octo_phy_mask & (1 << octo_index)) - return &porttypes[PORTTYPE_TOP_CAT]; - } - - return NULL; -} - -int init_single_phy(struct porttype *porttype, struct mii_dev *bus, - uint bus_idx, uint m, uint phy_idx) -{ - struct phy_device *phydev; - - phydev = phy_find_by_mask(bus, BIT(m * 8 + phy_idx)); - printf(" %u", bus_idx * 32 + m * 8 + phy_idx); - - if (!phydev) - puts("!"); - else - ihs_phy_config(phydev, porttype->phy_invert_in_pol, - porttype->phy_invert_out_pol); - - return 0; -} - -int init_octo_phys(uint octo_phy_mask) -{ - uint bus_idx; - - /* there are up to four octo-phys on each mdio bus */ - for (bus_idx = 0; bus_idx < bb_miiphy_buses_num; ++bus_idx) { - uint m; - uint octo_index = bus_idx * 4; - struct mii_dev *bus = NULL; - struct porttype *porttype = NULL; - int ret; - - porttype = get_porttype(octo_phy_mask, bus_idx); - - if (!porttype) - continue; - - for (m = 0; m < 4; ++m) { - uint phy_idx; - - /** - * Register a bus device if there is at least one phy - * on the current bus - */ - if (!m && octo_phy_mask & (0xf << octo_index)) { - ret = register_miiphy_bus(bus_idx, &bus); - if (ret) - return ret; - } - - if (!(octo_phy_mask & BIT(octo_index + m))) - continue; - - for (phy_idx = 0; phy_idx < 8; ++phy_idx) - init_single_phy(porttype, bus, bus_idx, m, - phy_idx); - } - } - - return 0; -} - /* * MII GPIO bitbang implementation * MDC MDIO bus @@ -315,40 +219,109 @@ static int mii_delay(struct bb_miiphy_bus *bus) return 0; } -struct bb_miiphy_bus bb_miiphy_buses[] = { - { - .name = "ihs0", - .init = mii_mdio_init, - .mdio_active = mii_mdio_active, - .mdio_tristate = mii_mdio_tristate, - .set_mdio = mii_set_mdio, - .get_mdio = mii_get_mdio, - .set_mdc = mii_set_mdc, - .delay = mii_delay, - .priv = &gpio_mii_set[0], - }, - { - .name = "ihs1", - .init = mii_mdio_init, - .mdio_active = mii_mdio_active, - .mdio_tristate = mii_mdio_tristate, - .set_mdio = mii_set_mdio, - .get_mdio = mii_get_mdio, - .set_mdc = mii_set_mdc, - .delay = mii_delay, - .priv = &gpio_mii_set[1], - }, - { - .name = "ihs2", - .init = mii_mdio_init, - .mdio_active = mii_mdio_active, - .mdio_tristate = mii_mdio_tristate, - .set_mdio = mii_set_mdio, - .get_mdio = mii_get_mdio, - .set_mdc = mii_set_mdc, - .delay = mii_delay, - .priv = &gpio_mii_set[2], - }, -}; +int register_miiphy_bus(uint k, struct mii_dev **bus) +{ + struct bb_miiphy_bus *bb_miiphy = bb_miiphy_alloc(); + struct mii_dev *mdiodev; + int retval; -int bb_miiphy_buses_num = ARRAY_SIZE(bb_miiphy_buses); + if (!bb_miiphy) + return -ENOMEM; + + mdiodev = &bb_miiphy->mii; + snprintf(mdiodev->name, MDIO_NAME_LEN, "ihs%d", k); + mdiodev->read = bb_miiphy_read; + mdiodev->write = bb_miiphy_write; + + /* Copy the bus accessors and private data */ + bb_miiphy->mdio_active = mii_mdio_active; + bb_miiphy->mdio_tristate = mii_mdio_tristate; + bb_miiphy->set_mdio = mii_set_mdio; + bb_miiphy->get_mdio = mii_get_mdio; + bb_miiphy->set_mdc = mii_set_mdc; + bb_miiphy->delay = mii_delay; + bb_miiphy->priv = &gpio_mii_set[k]; + + retval = mdio_register(mdiodev); + if (retval < 0) + return retval; + *bus = &bb_miiphy->mii; + + return mii_mdio_init(bb_miiphy); +} + +struct porttype *get_porttype(uint octo_phy_mask, uint k) +{ + uint octo_index = k * 4; + + if (!k) { + if (octo_phy_mask & 0x01) + return &porttypes[PORTTYPE_MAIN_CAT]; + else if (!(octo_phy_mask & 0x03)) + return &porttypes[PORTTYPE_16C_16F]; + } else { + if (octo_phy_mask & (1 << octo_index)) + return &porttypes[PORTTYPE_TOP_CAT]; + } + + return NULL; +} + +int init_single_phy(struct porttype *porttype, struct mii_dev *bus, + uint bus_idx, uint m, uint phy_idx) +{ + struct phy_device *phydev; + + phydev = phy_find_by_mask(bus, BIT(m * 8 + phy_idx)); + printf(" %u", bus_idx * 32 + m * 8 + phy_idx); + + if (!phydev) + puts("!"); + else + ihs_phy_config(phydev, porttype->phy_invert_in_pol, + porttype->phy_invert_out_pol); + + return 0; +} + +int init_octo_phys(uint octo_phy_mask) +{ + uint bus_idx; + + /* there are up to four octo-phys on each mdio bus */ + for (bus_idx = 0; bus_idx < ARRAY_SIZE(gpio_mii_set); ++bus_idx) { + uint m; + uint octo_index = bus_idx * 4; + struct mii_dev *bus = NULL; + struct porttype *porttype = NULL; + int ret; + + porttype = get_porttype(octo_phy_mask, bus_idx); + + if (!porttype) + continue; + + for (m = 0; m < 4; ++m) { + uint phy_idx; + + /** + * Register a bus device if there is at least one phy + * on the current bus + */ + if (!m && octo_phy_mask & (0xf << octo_index)) { + ret = register_miiphy_bus(bus_idx, &bus); + if (ret) + return ret; + } + + if (!(octo_phy_mask & BIT(octo_index + m))) + continue; + + for (phy_idx = 0; phy_idx < 8; ++phy_idx) + init_single_phy(porttype, bus, bus_idx, m, + phy_idx); + } + } + + return 0; +} diff --git a/common/board_r.c b/common/board_r.c index 179259b00de..db0c5cb8032 100644 --- a/common/board_r.c +++ b/common/board_r.c @@ -749,9 +749,6 @@ static init_fnc_t init_sequence_r[] = { #ifdef CONFIG_BOARD_LATE_INIT board_late_init, #endif -#ifdef CONFIG_BITBANGMII - bb_miiphy_init, -#endif #ifdef CONFIG_PCI_ENDPOINT pci_ep_init, #endif diff --git a/common/miiphyutil.c b/common/miiphyutil.c index 9b8744e5d8b..2a034d3a77c 100644 --- a/common/miiphyutil.c +++ b/common/miiphyutil.c @@ -65,6 +65,14 @@ void miiphy_init(void) current_mii = NULL; } +void mdio_init(struct mii_dev *bus) +{ + memset(bus, 0, sizeof(*bus)); + + /* initialize mii_dev struct fields */ + INIT_LIST_HEAD(&bus->link); +} + struct mii_dev *mdio_alloc(void) { struct mii_dev *bus; @@ -73,10 +81,7 @@ struct mii_dev *mdio_alloc(void) if (!bus) return bus; - memset(bus, 0, sizeof(*bus)); - - /* initalize mii_dev struct fields */ - INIT_LIST_HEAD(&bus->link); + mdio_init(bus); return bus; } diff --git a/drivers/net/designware.c b/drivers/net/designware.c index 2ab03015ffa..5a6e89c0575 100644 --- a/drivers/net/designware.c +++ b/drivers/net/designware.c @@ -226,6 +226,124 @@ static int dw_dm_mdio_init(const char *name, void *priv) } #endif +#if IS_ENABLED(CONFIG_BITBANGMII) && IS_ENABLED(CONFIG_DM_GPIO) +static int dw_eth_bb_mdio_active(struct bb_miiphy_bus *bus) +{ + struct dw_eth_dev *priv = bus->priv; + struct gpio_desc *desc = &priv->mdio_gpio; + + desc->flags = 0; + dm_gpio_set_dir_flags(&priv->mdio_gpio, GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE); + + return 0; +} + +static int dw_eth_bb_mdio_tristate(struct bb_miiphy_bus *bus) +{ + struct dw_eth_dev *priv = bus->priv; + struct gpio_desc *desc = &priv->mdio_gpio; + + desc->flags = 0; + dm_gpio_set_dir_flags(&priv->mdio_gpio, GPIOD_IS_IN); + + return 0; +} + +static int dw_eth_bb_set_mdio(struct bb_miiphy_bus *bus, int v) +{ + struct dw_eth_dev *priv = bus->priv; + + if (v) + dm_gpio_set_value(&priv->mdio_gpio, 1); + else + dm_gpio_set_value(&priv->mdio_gpio, 0); + + return 0; +} + +static int dw_eth_bb_get_mdio(struct bb_miiphy_bus *bus, int *v) +{ + struct dw_eth_dev *priv = bus->priv; + + *v = dm_gpio_get_value(&priv->mdio_gpio); + + return 0; +} + +static int dw_eth_bb_set_mdc(struct bb_miiphy_bus *bus, int v) +{ + struct dw_eth_dev *priv = bus->priv; + + if (v) + dm_gpio_set_value(&priv->mdc_gpio, 1); + else + dm_gpio_set_value(&priv->mdc_gpio, 0); + + return 0; +} + +static int dw_eth_bb_delay(struct bb_miiphy_bus *bus) +{ + struct dw_eth_dev *priv = bus->priv; + + udelay(priv->bb_delay); + return 0; +} + +static int dw_bb_mdio_init(const char *name, struct udevice *dev) +{ + struct dw_eth_dev *dwpriv = dev_get_priv(dev); + struct bb_miiphy_bus *bb_miiphy = bb_miiphy_alloc(); + struct mii_dev *bus; + int ret; + + if (!bb_miiphy) { + printf("Failed to allocate MDIO bus\n"); + return -ENOMEM; + } + + bus = &bb_miiphy->mii; + + debug("\n%s: use bitbang mii..\n", dev->name); + ret = gpio_request_by_name(dev, "snps,mdc-gpio", 0, + &dwpriv->mdc_gpio, + GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE); + if (ret) { + debug("no mdc-gpio\n"); + return ret; + } + ret = gpio_request_by_name(dev, "snps,mdio-gpio", 0, + &dwpriv->mdio_gpio, + GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE); + if (ret) { + debug("no mdio-gpio\n"); + return ret; + } + dwpriv->bb_delay = dev_read_u32_default(dev, "snps,bitbang-delay", 1); + + dwpriv->bus = bus; + dwpriv->dev = dev; + + snprintf(bus->name, sizeof(bus->name), "%s", name); + bus->read = bb_miiphy_read; + bus->write = bb_miiphy_write; +#if CONFIG_IS_ENABLED(DM_GPIO) + bus->reset = dw_mdio_reset; +#endif + bus->priv = dwpriv; + + /* Copy the bus accessors and private data */ + bb_miiphy->mdio_active = dw_eth_bb_mdio_active; + bb_miiphy->mdio_tristate = dw_eth_bb_mdio_tristate; + bb_miiphy->set_mdio = dw_eth_bb_set_mdio; + bb_miiphy->get_mdio = dw_eth_bb_get_mdio; + bb_miiphy->set_mdc = dw_eth_bb_set_mdc; + bb_miiphy->delay = dw_eth_bb_delay; + + return mdio_register(bus); +} +#endif + static void tx_descs_init(struct dw_eth_dev *priv) { struct eth_dma_regs *dma_p = priv->dma_regs_p; @@ -722,6 +840,7 @@ int designware_eth_probe(struct udevice *dev) { struct eth_pdata *pdata = dev_get_plat(dev); struct dw_eth_dev *priv = dev_get_priv(dev); + bool __maybe_unused bbmiiphy = false; phys_addr_t iobase = pdata->iobase; void *ioaddr; int ret, err; @@ -812,51 +931,30 @@ int designware_eth_probe(struct udevice *dev) priv->interface = pdata->phy_interface; priv->max_speed = pdata->max_speed; -#if IS_ENABLED(CONFIG_DM_MDIO) - ret = dw_dm_mdio_init(dev->name, dev); -#else - ret = dw_mdio_init(dev->name, dev); -#endif - if (ret) { - err = ret; - goto mdio_err; - } - priv->bus = miiphy_get_dev_by_name(dev->name); - priv->dev = dev; - #if IS_ENABLED(CONFIG_BITBANGMII) && IS_ENABLED(CONFIG_DM_GPIO) - if (dev_read_bool(dev, "snps,bitbang-mii")) { - int bus_idx; - - debug("\n%s: use bitbang mii..\n", dev->name); - ret = gpio_request_by_name(dev, "snps,mdc-gpio", 0, - &priv->mdc_gpio, GPIOD_IS_OUT - | GPIOD_IS_OUT_ACTIVE); + bbmiiphy = dev_read_bool(dev, "snps,bitbang-mii"); + if (bbmiiphy) { + ret = dw_bb_mdio_init(dev->name, dev); if (ret) { - debug("no mdc-gpio\n"); - return ret; + err = ret; + goto mdio_err; } - ret = gpio_request_by_name(dev, "snps,mdio-gpio", 0, - &priv->mdio_gpio, GPIOD_IS_OUT - | GPIOD_IS_OUT_ACTIVE); - if (ret) { - debug("no mdio-gpio\n"); - return ret; - } - priv->bb_delay = dev_read_u32_default(dev, "snps,bitbang-delay", 1); - - for (bus_idx = 0; bus_idx < bb_miiphy_buses_num; bus_idx++) { - if (!bb_miiphy_buses[bus_idx].priv) { - bb_miiphy_buses[bus_idx].priv = priv; - strlcpy(bb_miiphy_buses[bus_idx].name, priv->bus->name, - MDIO_NAME_LEN); - priv->bus->read = bb_miiphy_read; - priv->bus->write = bb_miiphy_write; - break; - } - } - } + } else #endif + { +#if IS_ENABLED(CONFIG_DM_MDIO) + ret = dw_dm_mdio_init(dev->name, dev); +#else + ret = dw_mdio_init(dev->name, dev); +#endif + if (ret) { + err = ret; + goto mdio_err; + } + priv->bus = miiphy_get_dev_by_name(dev->name); + priv->dev = dev; + } + ret = dw_phy_init(priv, dev); debug("%s, ret=%d\n", __func__, ret); if (!ret) @@ -865,7 +963,12 @@ int designware_eth_probe(struct udevice *dev) /* continue here for cleanup if no PHY found */ err = ret; mdio_unregister(priv->bus); - mdio_free(priv->bus); +#if IS_ENABLED(CONFIG_BITBANGMII) && IS_ENABLED(CONFIG_DM_GPIO) + if (bbmiiphy) + bb_miiphy_free(container_of(priv->bus, struct bb_miiphy_bus, mii)); + else +#endif + mdio_free(priv->bus); mdio_err: #ifdef CONFIG_CLK @@ -967,83 +1070,3 @@ static struct pci_device_id supported[] = { }; U_BOOT_PCI_DEVICE(eth_designware, supported); - -#if IS_ENABLED(CONFIG_BITBANGMII) && IS_ENABLED(CONFIG_DM_GPIO) -static int dw_eth_bb_mdio_active(struct bb_miiphy_bus *bus) -{ - struct dw_eth_dev *priv = bus->priv; - struct gpio_desc *desc = &priv->mdio_gpio; - - desc->flags = 0; - dm_gpio_set_dir_flags(&priv->mdio_gpio, GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE); - - return 0; -} - -static int dw_eth_bb_mdio_tristate(struct bb_miiphy_bus *bus) -{ - struct dw_eth_dev *priv = bus->priv; - struct gpio_desc *desc = &priv->mdio_gpio; - - desc->flags = 0; - dm_gpio_set_dir_flags(&priv->mdio_gpio, GPIOD_IS_IN); - - return 0; -} - -static int dw_eth_bb_set_mdio(struct bb_miiphy_bus *bus, int v) -{ - struct dw_eth_dev *priv = bus->priv; - - if (v) - dm_gpio_set_value(&priv->mdio_gpio, 1); - else - dm_gpio_set_value(&priv->mdio_gpio, 0); - - return 0; -} - -static int dw_eth_bb_get_mdio(struct bb_miiphy_bus *bus, int *v) -{ - struct dw_eth_dev *priv = bus->priv; - - *v = dm_gpio_get_value(&priv->mdio_gpio); - - return 0; -} - -static int dw_eth_bb_set_mdc(struct bb_miiphy_bus *bus, int v) -{ - struct dw_eth_dev *priv = bus->priv; - - if (v) - dm_gpio_set_value(&priv->mdc_gpio, 1); - else - dm_gpio_set_value(&priv->mdc_gpio, 0); - - return 0; -} - -static int dw_eth_bb_delay(struct bb_miiphy_bus *bus) -{ - struct dw_eth_dev *priv = bus->priv; - - udelay(priv->bb_delay); - return 0; -} - -struct bb_miiphy_bus bb_miiphy_buses[] = { - { - .name = BB_MII_DEVNAME, - .mdio_active = dw_eth_bb_mdio_active, - .mdio_tristate = dw_eth_bb_mdio_tristate, - .set_mdio = dw_eth_bb_set_mdio, - .get_mdio = dw_eth_bb_get_mdio, - .set_mdc = dw_eth_bb_set_mdc, - .delay = dw_eth_bb_delay, - .priv = NULL, - } -}; - -int bb_miiphy_buses_num = ARRAY_SIZE(bb_miiphy_buses); -#endif diff --git a/drivers/net/phy/miiphybb.c b/drivers/net/phy/miiphybb.c index 9f5f9b12c9f..553af2c1032 100644 --- a/drivers/net/phy/miiphybb.c +++ b/drivers/net/phy/miiphybb.c @@ -14,31 +14,31 @@ #include #include +#include #include #include -int bb_miiphy_init(void) +static inline struct bb_miiphy_bus *bb_miiphy_getbus(struct mii_dev *miidev) { - int i; - - for (i = 0; i < bb_miiphy_buses_num; i++) - if (bb_miiphy_buses[i].init != NULL) - bb_miiphy_buses[i].init(&bb_miiphy_buses[i]); - - return 0; + return container_of(miidev, struct bb_miiphy_bus, mii); } -static inline struct bb_miiphy_bus *bb_miiphy_getbus(const char *devname) +struct bb_miiphy_bus *bb_miiphy_alloc(void) { - int i; + struct bb_miiphy_bus *bus; - /* Search the correct bus */ - for (i = 0; i < bb_miiphy_buses_num; i++) { - if (!strcmp(bb_miiphy_buses[i].name, devname)) { - return &bb_miiphy_buses[i]; - } - } - return NULL; + bus = malloc(sizeof(*bus)); + if (!bus) + return bus; + + mdio_init(&bus->mii); + + return bus; +} + +void bb_miiphy_free(struct bb_miiphy_bus *bus) +{ + free(bus); } /***************************************************************************** @@ -133,7 +133,7 @@ int bb_miiphy_read(struct mii_dev *miidev, int addr, int devad, int reg) int j; /* counter */ struct bb_miiphy_bus *bus; - bus = bb_miiphy_getbus(miidev->name); + bus = bb_miiphy_getbus(miidev); if (bus == NULL) { return -1; } @@ -201,7 +201,7 @@ int bb_miiphy_write(struct mii_dev *miidev, int addr, int devad, int reg, struct bb_miiphy_bus *bus; int j; /* counter */ - bus = bb_miiphy_getbus(miidev->name); + bus = bb_miiphy_getbus(miidev); if (bus == NULL) { /* Bus not found! */ return -1; diff --git a/drivers/net/ravb.c b/drivers/net/ravb.c index 7286ad19598..cb727ae9bc1 100644 --- a/drivers/net/ravb.c +++ b/drivers/net/ravb.c @@ -490,81 +490,7 @@ static void ravb_stop(struct udevice *dev) ravb_reset(dev); } -static int ravb_probe(struct udevice *dev) -{ - struct eth_pdata *pdata = dev_get_plat(dev); - struct ravb_priv *eth = dev_get_priv(dev); - struct mii_dev *mdiodev; - void __iomem *iobase; - int ret; - - iobase = map_physmem(pdata->iobase, 0x1000, MAP_NOCACHE); - eth->iobase = iobase; - - ret = clk_get_bulk(dev, ð->clks); - if (ret < 0) - goto err_mdio_alloc; - - mdiodev = mdio_alloc(); - if (!mdiodev) { - ret = -ENOMEM; - goto err_mdio_alloc; - } - - mdiodev->read = bb_miiphy_read; - mdiodev->write = bb_miiphy_write; - bb_miiphy_buses[0].priv = eth; - snprintf(mdiodev->name, sizeof(mdiodev->name), dev->name); - - ret = mdio_register(mdiodev); - if (ret < 0) - goto err_mdio_register; - - eth->bus = miiphy_get_dev_by_name(dev->name); - - /* Bring up PHY */ - ret = clk_enable_bulk(ð->clks); - if (ret) - goto err_mdio_register; - - ret = ravb_reset(dev); - if (ret) - goto err_mdio_reset; - - ret = ravb_phy_config(dev); - if (ret) - goto err_mdio_reset; - - return 0; - -err_mdio_reset: - clk_release_bulk(ð->clks); -err_mdio_register: - mdio_free(mdiodev); -err_mdio_alloc: - unmap_physmem(eth->iobase, MAP_NOCACHE); - return ret; -} - -static int ravb_remove(struct udevice *dev) -{ - struct ravb_priv *eth = dev_get_priv(dev); - - clk_release_bulk(ð->clks); - - free(eth->phydev); - mdio_unregister(eth->bus); - mdio_free(eth->bus); - unmap_physmem(eth->iobase, MAP_NOCACHE); - - return 0; -} - -static int ravb_bb_init(struct bb_miiphy_bus *bus) -{ - return 0; -} - +/* Bitbang MDIO access */ static int ravb_bb_mdio_active(struct bb_miiphy_bus *bus) { struct ravb_priv *eth = bus->priv; @@ -623,19 +549,86 @@ static int ravb_bb_delay(struct bb_miiphy_bus *bus) return 0; } -struct bb_miiphy_bus bb_miiphy_buses[] = { - { - .name = "ravb", - .init = ravb_bb_init, - .mdio_active = ravb_bb_mdio_active, - .mdio_tristate = ravb_bb_mdio_tristate, - .set_mdio = ravb_bb_set_mdio, - .get_mdio = ravb_bb_get_mdio, - .set_mdc = ravb_bb_set_mdc, - .delay = ravb_bb_delay, - }, -}; -int bb_miiphy_buses_num = ARRAY_SIZE(bb_miiphy_buses); +static int ravb_probe(struct udevice *dev) +{ + struct eth_pdata *pdata = dev_get_plat(dev); + struct ravb_priv *eth = dev_get_priv(dev); + struct bb_miiphy_bus *bb_miiphy; + struct mii_dev *mdiodev; + void __iomem *iobase; + int ret; + + iobase = map_physmem(pdata->iobase, 0x1000, MAP_NOCACHE); + eth->iobase = iobase; + + ret = clk_get_bulk(dev, ð->clks); + if (ret < 0) + goto err_mdio_alloc; + + bb_miiphy = bb_miiphy_alloc(); + if (!bb_miiphy) { + ret = -ENOMEM; + goto err_mdio_alloc; + } + + mdiodev = &bb_miiphy->mii; + + mdiodev->read = bb_miiphy_read; + mdiodev->write = bb_miiphy_write; + snprintf(mdiodev->name, sizeof(mdiodev->name), dev->name); + + /* Copy the bus accessors and private data */ + bb_miiphy->mdio_active = ravb_bb_mdio_active; + bb_miiphy->mdio_tristate = ravb_bb_mdio_tristate; + bb_miiphy->set_mdio = ravb_bb_set_mdio; + bb_miiphy->get_mdio = ravb_bb_get_mdio; + bb_miiphy->set_mdc = ravb_bb_set_mdc; + bb_miiphy->delay = ravb_bb_delay; + bb_miiphy->priv = eth; + + ret = mdio_register(mdiodev); + if (ret < 0) + goto err_mdio_register; + + eth->bus = &bb_miiphy->mii; + + /* Bring up PHY */ + ret = clk_enable_bulk(ð->clks); + if (ret) + goto err_mdio_register; + + ret = ravb_reset(dev); + if (ret) + goto err_mdio_reset; + + ret = ravb_phy_config(dev); + if (ret) + goto err_mdio_reset; + + return 0; + +err_mdio_reset: + clk_release_bulk(ð->clks); +err_mdio_register: + bb_miiphy_free(bb_miiphy); +err_mdio_alloc: + unmap_physmem(eth->iobase, MAP_NOCACHE); + return ret; +} + +static int ravb_remove(struct udevice *dev) +{ + struct ravb_priv *eth = dev_get_priv(dev); + + clk_release_bulk(ð->clks); + + free(eth->phydev); + mdio_unregister(eth->bus); + mdio_free(eth->bus); + unmap_physmem(eth->iobase, MAP_NOCACHE); + + return 0; +} static const struct eth_ops ravb_ops = { .start = ravb_start, @@ -658,8 +651,6 @@ int ravb_of_to_plat(struct udevice *dev) pdata->max_speed = dev_read_u32_default(dev, "max-speed", 1000); - sprintf(bb_miiphy_buses[0].name, dev->name); - return 0; } diff --git a/drivers/net/sh_eth.c b/drivers/net/sh_eth.c index f1ce994cfd5..83e48609224 100644 --- a/drivers/net/sh_eth.c +++ b/drivers/net/sh_eth.c @@ -643,145 +643,7 @@ static void sh_ether_stop(struct udevice *dev) sh_eth_stop(&priv->shdev); } -static int sh_ether_probe(struct udevice *udev) -{ - struct eth_pdata *pdata = dev_get_plat(udev); - struct sh_ether_priv *priv = dev_get_priv(udev); - struct sh_eth_dev *eth = &priv->shdev; - struct mii_dev *mdiodev; - int ret; - - priv->iobase = pdata->iobase; - -#if CONFIG_IS_ENABLED(CLK) - ret = clk_get_by_index(udev, 0, &priv->clk); - if (ret < 0) - return ret; -#endif - mdiodev = mdio_alloc(); - if (!mdiodev) { - ret = -ENOMEM; - return ret; - } - - mdiodev->read = bb_miiphy_read; - mdiodev->write = bb_miiphy_write; - bb_miiphy_buses[0].priv = eth; - snprintf(mdiodev->name, sizeof(mdiodev->name), udev->name); - - ret = mdio_register(mdiodev); - if (ret < 0) - goto err_mdio_register; - - priv->bus = miiphy_get_dev_by_name(udev->name); - - eth->port = CFG_SH_ETHER_USE_PORT; - eth->port_info[eth->port].phy_addr = CFG_SH_ETHER_PHY_ADDR; - eth->port_info[eth->port].iobase = - (void __iomem *)(uintptr_t)(BASE_IO_ADDR + 0x800 * eth->port); - -#if CONFIG_IS_ENABLED(CLK) - ret = clk_enable(&priv->clk); - if (ret) - goto err_mdio_register; -#endif - - ret = sh_eth_init_common(eth, pdata->enetaddr); - if (ret) - goto err_phy_config; - - ret = sh_eth_phy_config(udev); - if (ret) { - printf(SHETHER_NAME ": phy config timeout\n"); - goto err_phy_config; - } - - return 0; - -err_phy_config: -#if CONFIG_IS_ENABLED(CLK) - clk_disable(&priv->clk); -#endif -err_mdio_register: - mdio_free(mdiodev); - return ret; -} - -static int sh_ether_remove(struct udevice *udev) -{ - struct sh_ether_priv *priv = dev_get_priv(udev); - struct sh_eth_dev *eth = &priv->shdev; - struct sh_eth_info *port_info = ð->port_info[eth->port]; - -#if CONFIG_IS_ENABLED(CLK) - clk_disable(&priv->clk); -#endif - free(port_info->phydev); - mdio_unregister(priv->bus); - mdio_free(priv->bus); - - return 0; -} - -static const struct eth_ops sh_ether_ops = { - .start = sh_ether_start, - .send = sh_ether_send, - .recv = sh_ether_recv, - .free_pkt = sh_ether_free_pkt, - .stop = sh_ether_stop, - .write_hwaddr = sh_ether_write_hwaddr, -}; - -int sh_ether_of_to_plat(struct udevice *dev) -{ - struct eth_pdata *pdata = dev_get_plat(dev); - const fdt32_t *cell; - - pdata->iobase = dev_read_addr(dev); - - pdata->phy_interface = dev_read_phy_mode(dev); - if (pdata->phy_interface == PHY_INTERFACE_MODE_NA) - return -EINVAL; - - pdata->max_speed = 1000; - cell = fdt_getprop(gd->fdt_blob, dev_of_offset(dev), "max-speed", NULL); - if (cell) - pdata->max_speed = fdt32_to_cpu(*cell); - - sprintf(bb_miiphy_buses[0].name, dev->name); - - return 0; -} - -static const struct udevice_id sh_ether_ids[] = { - { .compatible = "renesas,ether-r7s72100" }, - { .compatible = "renesas,ether-r8a7790" }, - { .compatible = "renesas,ether-r8a7791" }, - { .compatible = "renesas,ether-r8a7793" }, - { .compatible = "renesas,ether-r8a7794" }, - { .compatible = "renesas,gether-r8a77980" }, - { } -}; - -U_BOOT_DRIVER(eth_sh_ether) = { - .name = "sh_ether", - .id = UCLASS_ETH, - .of_match = sh_ether_ids, - .of_to_plat = sh_ether_of_to_plat, - .probe = sh_ether_probe, - .remove = sh_ether_remove, - .ops = &sh_ether_ops, - .priv_auto = sizeof(struct sh_ether_priv), - .plat_auto = sizeof(struct eth_pdata), - .flags = DM_FLAG_ALLOC_PRIV_DMA, -}; - /******* for bb_miiphy *******/ -static int sh_eth_bb_init(struct bb_miiphy_bus *bus) -{ - return 0; -} - static int sh_eth_bb_mdio_active(struct bb_miiphy_bus *bus) { struct sh_eth_dev *eth = bus->priv; @@ -849,17 +711,144 @@ static int sh_eth_bb_delay(struct bb_miiphy_bus *bus) return 0; } -struct bb_miiphy_bus bb_miiphy_buses[] = { - { - .name = "sh_eth", - .init = sh_eth_bb_init, - .mdio_active = sh_eth_bb_mdio_active, - .mdio_tristate = sh_eth_bb_mdio_tristate, - .set_mdio = sh_eth_bb_set_mdio, - .get_mdio = sh_eth_bb_get_mdio, - .set_mdc = sh_eth_bb_set_mdc, - .delay = sh_eth_bb_delay, +static int sh_ether_probe(struct udevice *udev) +{ + struct eth_pdata *pdata = dev_get_plat(udev); + struct sh_ether_priv *priv = dev_get_priv(udev); + struct sh_eth_dev *eth = &priv->shdev; + struct bb_miiphy_bus *bb_miiphy; + struct mii_dev *mdiodev; + int ret; + + priv->iobase = pdata->iobase; + +#if CONFIG_IS_ENABLED(CLK) + ret = clk_get_by_index(udev, 0, &priv->clk); + if (ret < 0) + return ret; +#endif + bb_miiphy = bb_miiphy_alloc(); + if (!bb_miiphy) { + ret = -ENOMEM; + return ret; } + + mdiodev = &bb_miiphy->mii; + + mdiodev->read = bb_miiphy_read; + mdiodev->write = bb_miiphy_write; + snprintf(mdiodev->name, sizeof(mdiodev->name), udev->name); + + /* Copy the bus accessors and private data */ + bb_miiphy->mdio_active = sh_eth_bb_mdio_active; + bb_miiphy->mdio_tristate = sh_eth_bb_mdio_tristate; + bb_miiphy->set_mdio = sh_eth_bb_set_mdio; + bb_miiphy->get_mdio = sh_eth_bb_get_mdio; + bb_miiphy->set_mdc = sh_eth_bb_set_mdc; + bb_miiphy->delay = sh_eth_bb_delay; + bb_miiphy->priv = eth; + + ret = mdio_register(mdiodev); + if (ret < 0) + goto err_mdio_register; + + priv->bus = &bb_miiphy->mii; + + eth->port = CFG_SH_ETHER_USE_PORT; + eth->port_info[eth->port].phy_addr = CFG_SH_ETHER_PHY_ADDR; + eth->port_info[eth->port].iobase = + (void __iomem *)(uintptr_t)(BASE_IO_ADDR + 0x800 * eth->port); + +#if CONFIG_IS_ENABLED(CLK) + ret = clk_enable(&priv->clk); + if (ret) + goto err_mdio_register; +#endif + + ret = sh_eth_init_common(eth, pdata->enetaddr); + if (ret) + goto err_phy_config; + + ret = sh_eth_phy_config(udev); + if (ret) { + printf(SHETHER_NAME ": phy config timeout\n"); + goto err_phy_config; + } + + return 0; + +err_phy_config: +#if CONFIG_IS_ENABLED(CLK) + clk_disable(&priv->clk); +#endif +err_mdio_register: + bb_miiphy_free(bb_miiphy); + return ret; +} + +static int sh_ether_remove(struct udevice *udev) +{ + struct sh_ether_priv *priv = dev_get_priv(udev); + struct sh_eth_dev *eth = &priv->shdev; + struct sh_eth_info *port_info = ð->port_info[eth->port]; + +#if CONFIG_IS_ENABLED(CLK) + clk_disable(&priv->clk); +#endif + free(port_info->phydev); + mdio_unregister(priv->bus); + mdio_free(priv->bus); + + return 0; +} + +static const struct eth_ops sh_ether_ops = { + .start = sh_ether_start, + .send = sh_ether_send, + .recv = sh_ether_recv, + .free_pkt = sh_ether_free_pkt, + .stop = sh_ether_stop, + .write_hwaddr = sh_ether_write_hwaddr, }; -int bb_miiphy_buses_num = ARRAY_SIZE(bb_miiphy_buses); +int sh_ether_of_to_plat(struct udevice *dev) +{ + struct eth_pdata *pdata = dev_get_plat(dev); + const fdt32_t *cell; + + pdata->iobase = dev_read_addr(dev); + + pdata->phy_interface = dev_read_phy_mode(dev); + if (pdata->phy_interface == PHY_INTERFACE_MODE_NA) + return -EINVAL; + + pdata->max_speed = 1000; + cell = fdt_getprop(gd->fdt_blob, dev_of_offset(dev), "max-speed", NULL); + if (cell) + pdata->max_speed = fdt32_to_cpu(*cell); + + return 0; +} + +static const struct udevice_id sh_ether_ids[] = { + { .compatible = "renesas,ether-r7s72100" }, + { .compatible = "renesas,ether-r8a7790" }, + { .compatible = "renesas,ether-r8a7791" }, + { .compatible = "renesas,ether-r8a7793" }, + { .compatible = "renesas,ether-r8a7794" }, + { .compatible = "renesas,gether-r8a77980" }, + { } +}; + +U_BOOT_DRIVER(eth_sh_ether) = { + .name = "sh_ether", + .id = UCLASS_ETH, + .of_match = sh_ether_ids, + .of_to_plat = sh_ether_of_to_plat, + .probe = sh_ether_probe, + .remove = sh_ether_remove, + .ops = &sh_ether_ops, + .priv_auto = sizeof(struct sh_ether_priv), + .plat_auto = sizeof(struct eth_pdata), + .flags = DM_FLAG_ALLOC_PRIV_DMA, +}; diff --git a/include/miiphy.h b/include/miiphy.h index 1e6c7041fdc..b879fd16ae3 100644 --- a/include/miiphy.h +++ b/include/miiphy.h @@ -44,6 +44,7 @@ struct phy_device *mdio_phydev_for_ethname(const char *devname); void miiphy_listdev(void); +void mdio_init(struct mii_dev *bus); struct mii_dev *mdio_alloc(void); void mdio_free(struct mii_dev *bus); int mdio_register(struct mii_dev *bus); @@ -64,8 +65,6 @@ void mdio_list_devices(void); #define BB_MII_DEVNAME "bb_miiphy" struct bb_miiphy_bus { - char name[MDIO_NAME_LEN]; - int (*init)(struct bb_miiphy_bus *bus); int (*mdio_active)(struct bb_miiphy_bus *bus); int (*mdio_tristate)(struct bb_miiphy_bus *bus); int (*set_mdio)(struct bb_miiphy_bus *bus, int v); @@ -73,19 +72,11 @@ struct bb_miiphy_bus { int (*set_mdc)(struct bb_miiphy_bus *bus, int v); int (*delay)(struct bb_miiphy_bus *bus); void *priv; + struct mii_dev mii; }; -extern struct bb_miiphy_bus bb_miiphy_buses[]; -extern int bb_miiphy_buses_num; - -/** - * bb_miiphy_init() - Initialize bit-banged MII bus driver - * - * It is called during the generic post-relocation init sequence. - * - * Return: 0 if OK - */ -int bb_miiphy_init(void); +struct bb_miiphy_bus *bb_miiphy_alloc(void); +void bb_miiphy_free(struct bb_miiphy_bus *bus); int bb_miiphy_read(struct mii_dev *miidev, int addr, int devad, int reg); int bb_miiphy_write(struct mii_dev *miidev, int addr, int devad, int reg,