Message ID | 5f5875eb510e03acd25aa5adbc4f55b370a9762e.1722924540.git.siyanteng@loongson.cn (mailing list archive) |
---|---|
State | Superseded |
Delegated to: | Netdev Maintainers |
Headers | show |
Series | stmmac: Add Loongson platform support | expand |
On Tue, Aug 06, 2024 at 06:59:44PM +0800, Yanteng Si wrote: > The Loongson GMAC driver currently supports the network controllers > installed on the LS2K1000 SoC and LS7A1000 chipset, for which the GMAC > devices are required to be defined in the platform device tree source. > But Loongson machines may have UEFI (implies ACPI) or PMON/UBOOT > (implies FDT) as the system bootloaders. In order to have both system > configurations support let's extend the driver functionality with the > case of having the Loongson GMAC probed on the PCI bus with no device > tree node defined for it. That requires to make the device DT-node > optional, to rely on the IRQ line detected by the PCI core and to > have the MDIO bus ID calculated using the PCIe Domain+BDF numbers. > > In order to have the device probe() and remove() methods less > complicated let's move the DT- and ACPI-specific code to the > respective sub-functions. > > Signed-off-by: Feiyang Chen <chenfeiyang@loongson.cn> > Signed-off-by: Yinggang Gu <guyinggang@loongson.cn> > Acked-by: Huacai Chen <chenhuacai@loongson.cn> > Signed-off-by: Yanteng Si <siyanteng@loongson.cn> > --- > .../ethernet/stmicro/stmmac/dwmac-loongson.c | 163 +++++++++++------- > 1 file changed, 100 insertions(+), 63 deletions(-) > > diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c > index 10b49bea8e3c..6ba4674bc076 100644 > --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c > +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c > @@ -12,11 +12,15 @@ > #define PCI_DEVICE_ID_LOONGSON_GMAC 0x7a03 > > struct stmmac_pci_info { > - int (*setup)(struct plat_stmmacenet_data *plat); > + int (*setup)(struct pci_dev *pdev, struct plat_stmmacenet_data *plat); > }; > > -static void loongson_default_data(struct plat_stmmacenet_data *plat) > +static void loongson_default_data(struct pci_dev *pdev, > + struct plat_stmmacenet_data *plat) > { > + /* Get bus_id, this can be overwritten later */ > + plat->bus_id = pci_dev_id(pdev); > + > plat->clk_csr = 2; /* clk_csr_i = 20-35MHz & MDC = clk_csr_i/16 */ > plat->has_gmac = 1; > plat->force_sf_dma_mode = 1; > @@ -49,9 +53,10 @@ static void loongson_default_data(struct plat_stmmacenet_data *plat) > plat->dma_cfg->pblx8 = true; > } > > -static int loongson_gmac_data(struct plat_stmmacenet_data *plat) > +static int loongson_gmac_data(struct pci_dev *pdev, > + struct plat_stmmacenet_data *plat) > { > - loongson_default_data(plat); > + loongson_default_data(pdev, plat); > > plat->tx_queues_to_use = 1; > plat->rx_queues_to_use = 1; > @@ -65,20 +70,83 @@ static struct stmmac_pci_info loongson_gmac_pci_info = { > .setup = loongson_gmac_data, > }; > > +static int loongson_dwmac_dt_config(struct pci_dev *pdev, > + struct plat_stmmacenet_data *plat, > + struct stmmac_resources *res) > +{ > + struct device_node *np = dev_of_node(&pdev->dev); > + int ret; > + > + plat->mdio_node = of_get_child_by_name(np, "mdio"); > + if (plat->mdio_node) { > + dev_info(&pdev->dev, "Found MDIO subnode\n"); > + plat->mdio_bus_data->needs_reset = true; > + } > + > + ret = of_alias_get_id(np, "ethernet"); > + if (ret >= 0) > + plat->bus_id = ret; > + > + res->irq = of_irq_get_byname(np, "macirq"); > + if (res->irq < 0) { > + dev_err(&pdev->dev, "IRQ macirq not found\n"); > + ret = -ENODEV; > + goto err_put_node; > + } > + > + res->wol_irq = of_irq_get_byname(np, "eth_wake_irq"); > + if (res->wol_irq < 0) { > + dev_info(&pdev->dev, > + "IRQ eth_wake_irq not found, using macirq\n"); > + res->wol_irq = res->irq; > + } > + > + res->lpi_irq = of_irq_get_byname(np, "eth_lpi"); > + if (res->lpi_irq < 0) { > + dev_err(&pdev->dev, "IRQ eth_lpi not found\n"); > + ret = -ENODEV; > + goto err_put_node; > + } > + > + ret = device_get_phy_mode(&pdev->dev); > + if (ret < 0) { > + dev_err(&pdev->dev, "phy_mode not found\n"); > + ret = -ENODEV; > + goto err_put_node; > + } > + > + plat->phy_interface = ret; + + return 0; Arggg. Alas I missed this part in v15.( The rest of changes looks good. Thanks! -Serge(y) > + > +err_put_node: > + of_node_put(plat->mdio_node); > + > + return ret; > +} > + > > ...
在 2024/8/7 3:10, Serge Semin 写道: > On Tue, Aug 06, 2024 at 06:59:44PM +0800, Yanteng Si wrote: >> The Loongson GMAC driver currently supports the network controllers >> installed on the LS2K1000 SoC and LS7A1000 chipset, for which the GMAC >> devices are required to be defined in the platform device tree source. >> But Loongson machines may have UEFI (implies ACPI) or PMON/UBOOT >> (implies FDT) as the system bootloaders. In order to have both system >> configurations support let's extend the driver functionality with the >> case of having the Loongson GMAC probed on the PCI bus with no device >> tree node defined for it. That requires to make the device DT-node >> optional, to rely on the IRQ line detected by the PCI core and to >> have the MDIO bus ID calculated using the PCIe Domain+BDF numbers. >> >> In order to have the device probe() and remove() methods less >> complicated let's move the DT- and ACPI-specific code to the >> respective sub-functions. >> >> Signed-off-by: Feiyang Chen <chenfeiyang@loongson.cn> >> Signed-off-by: Yinggang Gu <guyinggang@loongson.cn> >> Acked-by: Huacai Chen <chenhuacai@loongson.cn> >> Signed-off-by: Yanteng Si <siyanteng@loongson.cn> >> --- >> .../ethernet/stmicro/stmmac/dwmac-loongson.c | 163 +++++++++++------- >> 1 file changed, 100 insertions(+), 63 deletions(-) >> >> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c >> index 10b49bea8e3c..6ba4674bc076 100644 >> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c >> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c >> @@ -12,11 +12,15 @@ >> #define PCI_DEVICE_ID_LOONGSON_GMAC 0x7a03 >> >> struct stmmac_pci_info { >> - int (*setup)(struct plat_stmmacenet_data *plat); >> + int (*setup)(struct pci_dev *pdev, struct plat_stmmacenet_data *plat); >> }; >> >> -static void loongson_default_data(struct plat_stmmacenet_data *plat) >> +static void loongson_default_data(struct pci_dev *pdev, >> + struct plat_stmmacenet_data *plat) >> { >> + /* Get bus_id, this can be overwritten later */ >> + plat->bus_id = pci_dev_id(pdev); >> + >> plat->clk_csr = 2; /* clk_csr_i = 20-35MHz & MDC = clk_csr_i/16 */ >> plat->has_gmac = 1; >> plat->force_sf_dma_mode = 1; >> @@ -49,9 +53,10 @@ static void loongson_default_data(struct plat_stmmacenet_data *plat) >> plat->dma_cfg->pblx8 = true; >> } >> >> -static int loongson_gmac_data(struct plat_stmmacenet_data *plat) >> +static int loongson_gmac_data(struct pci_dev *pdev, >> + struct plat_stmmacenet_data *plat) >> { >> - loongson_default_data(plat); >> + loongson_default_data(pdev, plat); >> >> plat->tx_queues_to_use = 1; >> plat->rx_queues_to_use = 1; >> @@ -65,20 +70,83 @@ static struct stmmac_pci_info loongson_gmac_pci_info = { >> .setup = loongson_gmac_data, >> }; >> >> +static int loongson_dwmac_dt_config(struct pci_dev *pdev, >> + struct plat_stmmacenet_data *plat, >> + struct stmmac_resources *res) >> +{ >> + struct device_node *np = dev_of_node(&pdev->dev); >> + int ret; >> + >> + plat->mdio_node = of_get_child_by_name(np, "mdio"); >> + if (plat->mdio_node) { >> + dev_info(&pdev->dev, "Found MDIO subnode\n"); >> + plat->mdio_bus_data->needs_reset = true; >> + } >> + >> + ret = of_alias_get_id(np, "ethernet"); >> + if (ret >= 0) >> + plat->bus_id = ret; >> + >> + res->irq = of_irq_get_byname(np, "macirq"); >> + if (res->irq < 0) { >> + dev_err(&pdev->dev, "IRQ macirq not found\n"); >> + ret = -ENODEV; >> + goto err_put_node; >> + } >> + >> + res->wol_irq = of_irq_get_byname(np, "eth_wake_irq"); >> + if (res->wol_irq < 0) { >> + dev_info(&pdev->dev, >> + "IRQ eth_wake_irq not found, using macirq\n"); >> + res->wol_irq = res->irq; >> + } >> + >> + res->lpi_irq = of_irq_get_byname(np, "eth_lpi"); >> + if (res->lpi_irq < 0) { >> + dev_err(&pdev->dev, "IRQ eth_lpi not found\n"); >> + ret = -ENODEV; >> + goto err_put_node; >> + } >> + >> + ret = device_get_phy_mode(&pdev->dev); >> + if (ret < 0) { >> + dev_err(&pdev->dev, "phy_mode not found\n"); >> + ret = -ENODEV; >> + goto err_put_node; >> + } >> + >> + plat->phy_interface = ret; > + > + return 0; > > Arggg. Alas I missed this part in v15.( > > The rest of changes looks good. Thanks! OK, Thanks! Thanks, Yanteng > > -Serge(y) > >> + >> +err_put_node: >> + of_node_put(plat->mdio_node); >> + >> + return ret; >> +} >> + >> >> ...
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c index 10b49bea8e3c..6ba4674bc076 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c @@ -12,11 +12,15 @@ #define PCI_DEVICE_ID_LOONGSON_GMAC 0x7a03 struct stmmac_pci_info { - int (*setup)(struct plat_stmmacenet_data *plat); + int (*setup)(struct pci_dev *pdev, struct plat_stmmacenet_data *plat); }; -static void loongson_default_data(struct plat_stmmacenet_data *plat) +static void loongson_default_data(struct pci_dev *pdev, + struct plat_stmmacenet_data *plat) { + /* Get bus_id, this can be overwritten later */ + plat->bus_id = pci_dev_id(pdev); + plat->clk_csr = 2; /* clk_csr_i = 20-35MHz & MDC = clk_csr_i/16 */ plat->has_gmac = 1; plat->force_sf_dma_mode = 1; @@ -49,9 +53,10 @@ static void loongson_default_data(struct plat_stmmacenet_data *plat) plat->dma_cfg->pblx8 = true; } -static int loongson_gmac_data(struct plat_stmmacenet_data *plat) +static int loongson_gmac_data(struct pci_dev *pdev, + struct plat_stmmacenet_data *plat) { - loongson_default_data(plat); + loongson_default_data(pdev, plat); plat->tx_queues_to_use = 1; plat->rx_queues_to_use = 1; @@ -65,20 +70,83 @@ static struct stmmac_pci_info loongson_gmac_pci_info = { .setup = loongson_gmac_data, }; +static int loongson_dwmac_dt_config(struct pci_dev *pdev, + struct plat_stmmacenet_data *plat, + struct stmmac_resources *res) +{ + struct device_node *np = dev_of_node(&pdev->dev); + int ret; + + plat->mdio_node = of_get_child_by_name(np, "mdio"); + if (plat->mdio_node) { + dev_info(&pdev->dev, "Found MDIO subnode\n"); + plat->mdio_bus_data->needs_reset = true; + } + + ret = of_alias_get_id(np, "ethernet"); + if (ret >= 0) + plat->bus_id = ret; + + res->irq = of_irq_get_byname(np, "macirq"); + if (res->irq < 0) { + dev_err(&pdev->dev, "IRQ macirq not found\n"); + ret = -ENODEV; + goto err_put_node; + } + + res->wol_irq = of_irq_get_byname(np, "eth_wake_irq"); + if (res->wol_irq < 0) { + dev_info(&pdev->dev, + "IRQ eth_wake_irq not found, using macirq\n"); + res->wol_irq = res->irq; + } + + res->lpi_irq = of_irq_get_byname(np, "eth_lpi"); + if (res->lpi_irq < 0) { + dev_err(&pdev->dev, "IRQ eth_lpi not found\n"); + ret = -ENODEV; + goto err_put_node; + } + + ret = device_get_phy_mode(&pdev->dev); + if (ret < 0) { + dev_err(&pdev->dev, "phy_mode not found\n"); + ret = -ENODEV; + goto err_put_node; + } + + plat->phy_interface = ret; + +err_put_node: + of_node_put(plat->mdio_node); + + return ret; +} + +static void loongson_dwmac_dt_clear(struct pci_dev *pdev, + struct plat_stmmacenet_data *plat) +{ + of_node_put(plat->mdio_node); +} + +static int loongson_dwmac_acpi_config(struct pci_dev *pdev, + struct plat_stmmacenet_data *plat, + struct stmmac_resources *res) +{ + if (!pdev->irq) + return -EINVAL; + + res->irq = pdev->irq; + + return 0; +} + static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id *id) { struct plat_stmmacenet_data *plat; struct stmmac_pci_info *info; struct stmmac_resources res; - struct device_node *np; - int ret, i, phy_mode; - - np = dev_of_node(&pdev->dev); - - if (!np) { - pr_info("dwmac_loongson_pci: No OF node\n"); - return -ENODEV; - } + int ret, i; plat = devm_kzalloc(&pdev->dev, sizeof(*plat), GFP_KERNEL); if (!plat) @@ -90,25 +158,19 @@ static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id if (!plat->mdio_bus_data) return -ENOMEM; - plat->mdio_node = of_get_child_by_name(np, "mdio"); - if (plat->mdio_node) { - dev_info(&pdev->dev, "Found MDIO subnode\n"); - plat->mdio_bus_data->needs_reset = true; - } - plat->dma_cfg = devm_kzalloc(&pdev->dev, sizeof(*plat->dma_cfg), GFP_KERNEL); - if (!plat->dma_cfg) { - ret = -ENOMEM; - goto err_put_node; - } + if (!plat->dma_cfg) + return -ENOMEM; /* Enable pci device */ ret = pci_enable_device(pdev); if (ret) { dev_err(&pdev->dev, "%s: ERROR: failed to enable device\n", __func__); - goto err_put_node; + return ret; } + pci_set_master(pdev); + /* Get the base address of device */ for (i = 0; i < PCI_STD_NUM_BARS; i++) { if (pci_resource_len(pdev, i) == 0) @@ -119,59 +181,32 @@ static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id break; } - plat->bus_id = of_alias_get_id(np, "ethernet"); - if (plat->bus_id < 0) - plat->bus_id = pci_dev_id(pdev); - - phy_mode = device_get_phy_mode(&pdev->dev); - if (phy_mode < 0) { - dev_err(&pdev->dev, "phy_mode not found\n"); - ret = phy_mode; - goto err_disable_device; - } - - plat->phy_interface = phy_mode; - - pci_set_master(pdev); - memset(&res, 0, sizeof(res)); res.addr = pcim_iomap_table(pdev)[0]; info = (struct stmmac_pci_info *)id->driver_data; - ret = info->setup(plat); + ret = info->setup(pdev, plat); if (ret) goto err_disable_device; - res.irq = of_irq_get_byname(np, "macirq"); - if (res.irq < 0) { - dev_err(&pdev->dev, "IRQ macirq not found\n"); - ret = -ENODEV; - goto err_disable_device; - } - - res.wol_irq = of_irq_get_byname(np, "eth_wake_irq"); - if (res.wol_irq < 0) { - dev_info(&pdev->dev, "IRQ eth_wake_irq not found, using macirq\n"); - res.wol_irq = res.irq; - } - - res.lpi_irq = of_irq_get_byname(np, "eth_lpi"); - if (res.lpi_irq < 0) { - dev_err(&pdev->dev, "IRQ eth_lpi not found\n"); - ret = -ENODEV; + if (dev_of_node(&pdev->dev)) + ret = loongson_dwmac_dt_config(pdev, plat, &res); + else + ret = loongson_dwmac_acpi_config(pdev, plat, &res); + if (ret) goto err_disable_device; - } ret = stmmac_dvr_probe(&pdev->dev, plat, &res); if (ret) - goto err_disable_device; + goto err_plat_clear; - return ret; + return 0; +err_plat_clear: + if (dev_of_node(&pdev->dev)) + loongson_dwmac_dt_clear(pdev, plat); err_disable_device: pci_disable_device(pdev); -err_put_node: - of_node_put(plat->mdio_node); return ret; } @@ -181,9 +216,11 @@ static void loongson_dwmac_remove(struct pci_dev *pdev) struct stmmac_priv *priv = netdev_priv(ndev); int i; - of_node_put(priv->plat->mdio_node); stmmac_dvr_remove(&pdev->dev); + if (dev_of_node(&pdev->dev)) + loongson_dwmac_dt_clear(pdev, priv->plat); + for (i = 0; i < PCI_STD_NUM_BARS; i++) { if (pci_resource_len(pdev, i) == 0) continue;