Received: by 2002:a25:ad19:0:0:0:0:0 with SMTP id y25csp10895379ybi; Thu, 25 Jul 2019 06:42:37 -0700 (PDT) X-Google-Smtp-Source: APXvYqz8e626RAALQaug660HliPnQbw1kFwFW2BYuB2hVr+s6bFTbb8rIM+ipeqJKL6HOZnYt3A/ X-Received: by 2002:a65:504c:: with SMTP id k12mr87622081pgo.252.1564062156830; Thu, 25 Jul 2019 06:42:36 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1564062156; cv=none; d=google.com; s=arc-20160816; b=HhYBkx/V2D3R8leVktuLLyRsPO0Wo17QQhCiVIJXHt57QekSIR/azmasF1YlobDPWo 0HHcpd+eVdBsEbqs59P6d63eYDA85hkVfu5faNJtg7HDqHZHZbfGSRHcSxnCYckhK/Ry 1aPaDuVj7wa1CPOIoIF4lqm9ih2HQL57235yehfSTXlSEuFS7Qi6bKlp4+mbw2YRKqUS a+y3UTfFx0slRbjD6ExkmOC/4anz0+KgPk2Ej4VaiF9yc8sbrczZR97hf2GeK2Lf7cZz mUfQ0kEURkQJT1yHd8/KdyWG7w+k+CMCQgIqikhIvu9lHoHaLAyCHhGfKEeGzi0YLOBg ixZA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from; bh=KS8X5F0fjvXxejP12gsHYfexLJyhADoqtKGHQYRDW5k=; b=TuI7RXBZMwPmKwXCR40VSVto33qoUgJTQChsF+QOwokw1n18ApCLEMJPDI1BBRXErC C0YIPxOM3o3VezOp0GE+oSkK0F7+RgdMmyAAMzxkTSmZ0rsM0C6MrztPMUlP3b6h3VYj 61v1xCGarnGf/3gxEdz3q4hdMuk8Yh06fZKFjSEsiGtMZ/8T1l021Ov2sBuWh3TORLx4 DJOrZLx+TzLa+hkKWJd3DQmhmpMCvVswW4IewdD3Fn50nZscdVDzHmZaaexUXxEAAYCm haQj9rwpPE0Tpdw2jwNWKugJLg2smKyo2Vx8y6KLZk3EOQv3LwuSLFUk5PncuTxvSMSE QBng== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=nxp.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id r17si17487016pgj.259.2019.07.25.06.42.21; Thu, 25 Jul 2019 06:42:36 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=nxp.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2404081AbfGYLTe (ORCPT + 99 others); Thu, 25 Jul 2019 07:19:34 -0400 Received: from inva020.nxp.com ([92.121.34.13]:52934 "EHLO inva020.nxp.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2391541AbfGYLTc (ORCPT ); Thu, 25 Jul 2019 07:19:32 -0400 Received: from inva020.nxp.com (localhost [127.0.0.1]) by inva020.eu-rdc02.nxp.com (Postfix) with ESMTP id E5ECB1A06A7; Thu, 25 Jul 2019 13:19:29 +0200 (CEST) Received: from inva024.eu-rdc02.nxp.com (inva024.eu-rdc02.nxp.com [134.27.226.22]) by inva020.eu-rdc02.nxp.com (Postfix) with ESMTP id D89851A0147; Thu, 25 Jul 2019 13:19:29 +0200 (CEST) Received: from fsr-ub1664-016.ea.freescale.net (fsr-ub1664-016.ea.freescale.net [10.171.71.216]) by inva024.eu-rdc02.nxp.com (Postfix) with ESMTP id 737F0205E8; Thu, 25 Jul 2019 13:19:29 +0200 (CEST) From: Claudiu Manoil To: "David S . Miller" Cc: andrew@lunn.ch, Rob Herring , Li Yang , alexandru.marginean@nxp.com, netdev@vger.kernel.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org Subject: [PATCH net-next v2 2/4] enetc: Add mdio bus driver for the PCIe MDIO endpoint Date: Thu, 25 Jul 2019 14:19:26 +0300 Message-Id: <1564053568-20522-3-git-send-email-claudiu.manoil@nxp.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1564053568-20522-1-git-send-email-claudiu.manoil@nxp.com> References: <1564053568-20522-1-git-send-email-claudiu.manoil@nxp.com> X-Virus-Scanned: ClamAV using ClamSMTP Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org ENETC ports can manage the MDIO bus via local register interface. However there's also a centralized way to manage the MDIO bus, via the MDIO PCIe endpoint device integrated by the same root complex that also integrates the ENETC ports (eth controllers). Depending on board design and use case, centralized access to MDIO may be better than using local ENETC port registers. For instance, on the LS1028A QDS board where MDIO muxing is requiered. Also, the LS1028A on-chip switch doesn't have a local MDIO register interface. The current patch registers the above PCIe enpoint as a separate MDIO bus and provides a driver for it by re-using the code used for local MDIO access. It also allows the ENETC port PHYs to be managed by this driver if the local "mdio" node is missing from the ENETC port node. Signed-off-by: Claudiu Manoil --- v1 - fixed mdio bus allocation - requested only BAR0 region, as it's the only one used by the driver v2 - reworked accessors as per Andrew Lunn's request .../net/ethernet/freescale/enetc/enetc_mdio.c | 98 +++++++++++++++++++ .../net/ethernet/freescale/enetc/enetc_pf.c | 5 +- 2 files changed, 102 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/freescale/enetc/enetc_mdio.c b/drivers/net/ethernet/freescale/enetc/enetc_mdio.c index 05094601ece8..56ad94a3504c 100644 --- a/drivers/net/ethernet/freescale/enetc/enetc_mdio.c +++ b/drivers/net/ethernet/freescale/enetc/enetc_mdio.c @@ -195,3 +195,101 @@ void enetc_mdio_remove(struct enetc_pf *pf) if (pf->mdio) mdiobus_unregister(pf->mdio); } + +#define ENETC_MDIO_DEV_ID 0xee01 +#define ENETC_MDIO_DEV_NAME "FSL PCIe IE Central MDIO" +#define ENETC_MDIO_BUS_NAME ENETC_MDIO_DEV_NAME " Bus" +#define ENETC_MDIO_DRV_NAME ENETC_MDIO_DEV_NAME " driver" +#define ENETC_MDIO_DRV_ID "fsl_enetc_mdio" + +static int enetc_pci_mdio_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) +{ + struct enetc_mdio_priv *mdio_priv; + struct device *dev = &pdev->dev; + struct enetc_hw *hw; + struct mii_bus *bus; + int err; + + hw = devm_kzalloc(dev, sizeof(*hw), GFP_KERNEL); + if (!hw) + return -ENOMEM; + + bus = devm_mdiobus_alloc_size(dev, sizeof(*mdio_priv)); + if (!bus) + return -ENOMEM; + + bus->name = ENETC_MDIO_BUS_NAME; + bus->read = enetc_mdio_read; + bus->write = enetc_mdio_write; + bus->parent = dev; + mdio_priv = bus->priv; + mdio_priv->hw = hw; + snprintf(bus->id, MII_BUS_ID_SIZE, "%s", dev_name(dev)); + + pcie_flr(pdev); + err = pci_enable_device_mem(pdev); + if (err) { + dev_err(dev, "device enable failed\n"); + return err; + } + + err = pci_request_region(pdev, 0, ENETC_MDIO_DRV_ID); + if (err) { + dev_err(dev, "pci_request_region failed\n"); + goto err_pci_mem_reg; + } + + hw->port = pci_iomap(pdev, 0, 0); + if (!bus->priv) { + err = -ENXIO; + dev_err(dev, "iomap failed\n"); + goto err_ioremap; + } + + err = of_mdiobus_register(bus, dev->of_node); + if (err) + goto err_mdiobus_reg; + + pci_set_drvdata(pdev, bus); + + return 0; + +err_mdiobus_reg: + iounmap(mdio_priv->hw->port); +err_ioremap: + pci_release_mem_regions(pdev); +err_pci_mem_reg: + pci_disable_device(pdev); + + return err; +} + +static void enetc_pci_mdio_remove(struct pci_dev *pdev) +{ + struct mii_bus *bus = pci_get_drvdata(pdev); + struct enetc_mdio_priv *mdio_priv; + + mdiobus_unregister(bus); + mdio_priv = bus->priv; + iounmap(mdio_priv->hw->port); + pci_release_mem_regions(pdev); + pci_disable_device(pdev); +} + +static const struct pci_device_id enetc_pci_mdio_id_table[] = { + { PCI_DEVICE(PCI_VENDOR_ID_FREESCALE, ENETC_MDIO_DEV_ID) }, + { 0, } /* End of table. */ +}; +MODULE_DEVICE_TABLE(pci, enetc_mdio_id_table); + +static struct pci_driver enetc_pci_mdio_driver = { + .name = ENETC_MDIO_DRV_ID, + .id_table = enetc_pci_mdio_id_table, + .probe = enetc_pci_mdio_probe, + .remove = enetc_pci_mdio_remove, +}; +module_pci_driver(enetc_pci_mdio_driver); + +MODULE_DESCRIPTION(ENETC_MDIO_DRV_NAME); +MODULE_LICENSE("Dual BSD/GPL"); diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.c b/drivers/net/ethernet/freescale/enetc/enetc_pf.c index 258b3cb38a6f..7d6513ff8507 100644 --- a/drivers/net/ethernet/freescale/enetc/enetc_pf.c +++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.c @@ -750,6 +750,7 @@ static int enetc_of_get_phy(struct enetc_ndev_priv *priv) { struct enetc_pf *pf = enetc_si_priv(priv->si); struct device_node *np = priv->dev->of_node; + struct device_node *mdio_np; int err; if (!np) { @@ -773,7 +774,9 @@ static int enetc_of_get_phy(struct enetc_ndev_priv *priv) priv->phy_node = of_node_get(np); } - if (!of_phy_is_fixed_link(np)) { + mdio_np = of_get_child_by_name(np, "mdio"); + if (mdio_np) { + of_node_put(mdio_np); err = enetc_mdio_probe(pf); if (err) { of_node_put(priv->phy_node); -- 2.17.1