From patchwork Tue Aug 6 10:59:44 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yanteng Si X-Patchwork-Id: 13754658 X-Patchwork-Delegate: kuba@kernel.org Received: from mail.loongson.cn (mail.loongson.cn [114.242.206.163]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 0EB1F1C2317 for ; Tue, 6 Aug 2024 10:59:55 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=114.242.206.163 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1722941998; cv=none; b=S0E/vMicSVPH4LAoq1OYSaFvs5m/XSMLCKzKLrvpxkWyWqHtLZ0nTfOYOq4xwZcu8DLoendgPU7rE2p4velsEhA5aR5FqRNfhJpcoUpGu1ygPQRQRIumEMvToCh3YRyTExhe+51Gb6at6R26uFxPPbUuv37QKlduHU+01T819Lg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1722941998; c=relaxed/simple; bh=bf4G/uKimEbL1QrctvinZM+jfLBBaxODrQhU7CLx8Kk=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=sjXcRoTkaddmjkW6Mw+BnWI8lKUoSVgod4S7eSzYdmNoH83c7cjP0EBgmKr1lYfjkioCxQ7GQ0qaDVBoILqDEuAjcOSpaim102EDjI41IWWD3ux74oDlVfaB6yCCIYXEI8jMcnMqcSDu9P0UBncBBA90obZyQ4fgyMen4loZu28= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=loongson.cn; spf=pass smtp.mailfrom=loongson.cn; arc=none smtp.client-ip=114.242.206.163 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=loongson.cn Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=loongson.cn Received: from loongson.cn (unknown [223.64.68.71]) by gateway (Coremail) with SMTP id _____8CxuOkqArJmQLAIAA--.29160S3; Tue, 06 Aug 2024 18:59:54 +0800 (CST) Received: from localhost.localdomain (unknown [223.64.68.71]) by front1 (Coremail) with SMTP id qMiowMAxVOAlArJmWfgFAA--.31237S5; Tue, 06 Aug 2024 18:59:53 +0800 (CST) From: Yanteng Si To: andrew@lunn.ch, hkallweit1@gmail.com, peppe.cavallaro@st.com, alexandre.torgue@foss.st.com, joabreu@synopsys.com, fancer.lancer@gmail.com, diasyzhang@tencent.com Cc: Yanteng Si , Jose.Abreu@synopsys.com, chenhuacai@kernel.org, linux@armlinux.org.uk, guyinggang@loongson.cn, netdev@vger.kernel.org, chris.chenfeiyang@gmail.com, si.yanteng@linux.dev, Huacai Chen Subject: [PATCH net-next v16 11/14] net: stmmac: dwmac-loongson: Add DT-less GMAC PCI-device support Date: Tue, 6 Aug 2024 18:59:44 +0800 Message-Id: <5f5875eb510e03acd25aa5adbc4f55b370a9762e.1722924540.git.siyanteng@loongson.cn> X-Mailer: git-send-email 2.31.4 In-Reply-To: References: Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-CM-TRANSID: qMiowMAxVOAlArJmWfgFAA--.31237S5 X-CM-SenderInfo: pvl1t0pwhqwqxorr0wxvrqhubq/ X-Coremail-Antispam: 1Uk129KBj93XoWxuFWkZr4UtFW7CrWrAw45XFc_yoW3AF17p3 yfCasIgrZ3KryIgan5ZrWUZF1YyrWjvay8KF42y3s3Ca90yr1aqF10qFWjyFWfAFZ5Cw13 Xr4UtF48uF4DGFbCm3ZEXasCq-sJn29KB7ZKAUJUUUUD529EdanIXcx71UUUUU7KY7ZEXa sCq-sGcSsGvfJ3Ic02F40EFcxC0VAKzVAqx4xG6I80ebIjqfuFe4nvWSU5nxnvy29KBjDU 0xBIdaVrnRJUUUmIb4IE77IF4wAFF20E14v26r1j6r4UM7CY07I20VC2zVCF04k26cxKx2 IYs7xG6rWj6s0DM7CIcVAFz4kK6r1Y6r17M28lY4IEw2IIxxk0rwA2F7IY1VAKz4vEj48v e4kI8wA2z4x0Y4vE2Ix0cI8IcVAFwI0_tr0E3s1l84ACjcxK6xIIjxv20xvEc7CjxVAFwI 0_Gr1j6F4UJwA2z4x0Y4vEx4A2jsIE14v26r4UJVWxJr1l84ACjcxK6I8E87Iv6xkF7I0E 14v26r4UJVWxJr1ln4kS14v26r126r1DM2AIxVAIcxkEcVAq07x20xvEncxIr21l57IF6x kI12xvs2x26I8E6xACxx1l5I8CrVACY4xI64kE6c02F40Ex7xfMcIj6xIIjxv20xvE14v2 6Fy26r45twAv7VC2z280aVAFwI0_Gr1j6F4UJwAm72CE4IkC6x0Yz7v_Jr0_Gr1lF7xvr2 IYc2Ij64vIr41lF7xvrVCFI7AF6II2Y40_Zr0_Gr1UMxkF7I0En4kS14v26r1q6r43MxAI w28IcxkI7VAKI48JMxC20s026xCaFVCjc4AY6r1j6r4UMxCIbckI1I0E14v26r126r1DMI 8I3I0E5I8CrVAFwI0_Jr0_Jr4lx2IqxVCjr7xvwVAFwI0_JrI_JrWlx4CE17CEb7AF67AK xVW8ZVWrXwCIc40Y0x0EwIxGrwCI42IY6xIIjxv20xvE14v26w1j6s0DMIIF0xvE2Ix0cI 8IcVCY1x0267AKxVW8Jr0_Cr1UMIIF0xvE42xK8VAvwI8IcIk0rVWUJVWUCwCI42IY6I8E 87Iv67AKxVW8Jr0_Cr1UMIIF0xvEx4A2jsIEc7CjxVAFwI0_Gr1j6F4UJbIYCTnIWIevJa 73UjIFyTuYvjxUgc_-DUUUU X-Patchwork-Delegate: kuba@kernel.org 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 Signed-off-by: Yinggang Gu Acked-by: Huacai Chen Signed-off-by: Yanteng Si --- .../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; + +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;