Message ID | ae660c8872297b562ee4e62cd852ba96f307e079.1712917541.git.siyanteng@loongson.cn (mailing list archive) |
---|---|
State | Superseded |
Delegated to: | Netdev Maintainers |
Headers | show |
Series | stmmac: Add Loongson platform support | expand |
On Fri, Apr 12, 2024 at 07:28:50PM +0800, Yanteng Si wrote: > Current dwmac-loongson only support LS2K in the "probed with PCI and > configured with DT" manner. Add LS7A support on which the devices are > fully PCI (non-DT). > > Others: > LS2K is a SoC and LS7A is a bridge chip. In the current driving state, > they are both gmac and phy_interface is RGMII. > > Signed-off-by: Feiyang Chen <chenfeiyang@loongson.cn> > Signed-off-by: Yinggang Gu <guyinggang@loongson.cn> > Signed-off-by: Yanteng Si <siyanteng@loongson.cn> > --- > .../ethernet/stmicro/stmmac/dwmac-loongson.c | 103 +++++++++++------- > 1 file changed, 64 insertions(+), 39 deletions(-) > > diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c > index ad19b4087974..69078eb1f923 100644 > --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c > +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c > @@ -9,9 +9,19 @@ > #include <linux/of_irq.h> > #include "stmmac.h" > > +#define PCI_DEVICE_ID_LOONGSON_GMAC 0x7a03 > + > +struct stmmac_pci_info { > + int (*setup)(struct pci_dev *pdev, 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 overloaded later */ > + plat->bus_id = (pci_domain_nr(pdev->bus) << 16) | > + PCI_DEVID(pdev->bus->number, pdev->devfn); > + > plat->clk_csr = 2; /* clk_csr_i = 20-35MHz & MDC = clk_csr_i/16 */ > plat->has_gmac = 1; > plat->force_sf_dma_mode = 1; > @@ -40,6 +50,7 @@ static int loongson_gmac_data(struct pci_dev *pdev, > > /* Default to phy auto-detection */ > plat->phy_addr = -1; > + plat->phy_interface = PHY_INTERFACE_MODE_RGMII_ID; > > plat->dma_cfg->pbl = 32; > plat->dma_cfg->pblx8 = true; > @@ -54,19 +65,17 @@ static int loongson_gmac_data(struct pci_dev *pdev, > return 0; > } > > +static struct stmmac_pci_info loongson_gmac_pci_info = { > + .setup = loongson_gmac_data, > +}; > + > static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id *id) > { > struct plat_stmmacenet_data *plat; > + int ret, i, bus_id, phy_mode; > + 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; > - } Hm, I see you dropping this snippet and never getting it back in this patch. Thus after the patch is applied np will be left uninitialized, which will completely break the driver. Please make sure it's fixed. This problem has been introduced at the v9 stage, which I didn't have time to review. There were no problem like that in v8. -Serge(y) > > plat = devm_kzalloc(&pdev->dev, sizeof(*plat), GFP_KERNEL); > if (!plat) > @@ -78,12 +87,6 @@ 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; > @@ -107,10 +110,6 @@ 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"); > @@ -123,30 +122,56 @@ static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id > > pci_set_master(pdev); > > - loongson_gmac_data(pdev, plat); > - pci_enable_msi(pdev); > - memset(&res, 0, sizeof(res)); > - res.addr = pcim_iomap_table(pdev)[0]; > - > - 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_msi; > - } > + info = (struct stmmac_pci_info *)id->driver_data; > + ret = info->setup(pdev, plat); > + if (ret) > + 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; > + if (np) { > + 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; > + } > + > + bus_id = of_alias_get_id(np, "ethernet"); > + if (bus_id >= 0) > + plat->bus_id = bus_id; > + > + 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; > + > + 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_msi; > + } > + > + 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_disable_msi; > + } > + } else { > + res.irq = pdev->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_disable_msi; > - } > + pci_enable_msi(pdev); > + memset(&res, 0, sizeof(res)); > + res.addr = pcim_iomap_table(pdev)[0]; > > ret = stmmac_dvr_probe(&pdev->dev, plat, &res); > if (ret) > -- > 2.31.4 >
在 2024/4/18 21:08, Serge Semin 写道: >> - np = dev_of_node(&pdev->dev); >> - >> - if (!np) { >> - pr_info("dwmac_loongson_pci: No OF node\n"); >> - return -ENODEV; >> - } > Hm, I see you dropping this snippet and never getting it back in this > patch. Thus after the patch is applied np will be left uninitialized, > which will completely break the driver. Please make sure it's fixed. > > This problem has been introduced at the v9 stage, which I didn't have > time to review. There were no problem like that in v8. Okay, I will restore it. Thanks, Yanteng
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c index ad19b4087974..69078eb1f923 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c @@ -9,9 +9,19 @@ #include <linux/of_irq.h> #include "stmmac.h" +#define PCI_DEVICE_ID_LOONGSON_GMAC 0x7a03 + +struct stmmac_pci_info { + int (*setup)(struct pci_dev *pdev, 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 overloaded later */ + plat->bus_id = (pci_domain_nr(pdev->bus) << 16) | + PCI_DEVID(pdev->bus->number, pdev->devfn); + plat->clk_csr = 2; /* clk_csr_i = 20-35MHz & MDC = clk_csr_i/16 */ plat->has_gmac = 1; plat->force_sf_dma_mode = 1; @@ -40,6 +50,7 @@ static int loongson_gmac_data(struct pci_dev *pdev, /* Default to phy auto-detection */ plat->phy_addr = -1; + plat->phy_interface = PHY_INTERFACE_MODE_RGMII_ID; plat->dma_cfg->pbl = 32; plat->dma_cfg->pblx8 = true; @@ -54,19 +65,17 @@ static int loongson_gmac_data(struct pci_dev *pdev, return 0; } +static struct stmmac_pci_info loongson_gmac_pci_info = { + .setup = loongson_gmac_data, +}; + static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id *id) { struct plat_stmmacenet_data *plat; + int ret, i, bus_id, phy_mode; + 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; - } plat = devm_kzalloc(&pdev->dev, sizeof(*plat), GFP_KERNEL); if (!plat) @@ -78,12 +87,6 @@ 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; @@ -107,10 +110,6 @@ 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"); @@ -123,30 +122,56 @@ static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id pci_set_master(pdev); - loongson_gmac_data(pdev, plat); - pci_enable_msi(pdev); - memset(&res, 0, sizeof(res)); - res.addr = pcim_iomap_table(pdev)[0]; - - 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_msi; - } + info = (struct stmmac_pci_info *)id->driver_data; + ret = info->setup(pdev, plat); + if (ret) + 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; + if (np) { + 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; + } + + bus_id = of_alias_get_id(np, "ethernet"); + if (bus_id >= 0) + plat->bus_id = bus_id; + + 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; + + 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_msi; + } + + 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_disable_msi; + } + } else { + res.irq = pdev->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_disable_msi; - } + pci_enable_msi(pdev); + memset(&res, 0, sizeof(res)); + res.addr = pcim_iomap_table(pdev)[0]; ret = stmmac_dvr_probe(&pdev->dev, plat, &res); if (ret)