From patchwork Mon Apr 1 13:12:39 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Miquel Raynal X-Patchwork-Id: 1072763 X-Patchwork-Delegate: lorenzo.pieralisi@arm.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-pci-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=bootlin.com Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 44Xt7J1tmwz9sPM for ; Tue, 2 Apr 2019 00:13:00 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726542AbfDANM7 (ORCPT ); Mon, 1 Apr 2019 09:12:59 -0400 Received: from relay10.mail.gandi.net ([217.70.178.230]:57531 "EHLO relay10.mail.gandi.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726852AbfDANM6 (ORCPT ); Mon, 1 Apr 2019 09:12:58 -0400 Received: from localhost.localdomain (aaubervilliers-681-1-91-136.w90-88.abo.wanadoo.fr [90.88.32.136]) (Authenticated sender: miquel.raynal@bootlin.com) by relay10.mail.gandi.net (Postfix) with ESMTPSA id 6F8E724000E; Mon, 1 Apr 2019 13:12:55 +0000 (UTC) From: Miquel Raynal To: Thomas Petazzoni , Lorenzo Pieralisi , Bjorn Helgaas Cc: linux-pci@vger.kernel.org, linux-arm-kernel@lists.infradead.org, Miquel Raynal Subject: [PATCH] PCI: armada8k: Add PHYs support Date: Mon, 1 Apr 2019 15:12:39 +0200 Message-Id: <20190401131239.17008-1-miquel.raynal@bootlin.com> X-Mailer: git-send-email 2.19.1 MIME-Version: 1.0 Sender: linux-pci-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pci@vger.kernel.org Bring PHY support for the Armada8k driver. The Armada8k IP only supports x1, x2 or x4 link widths. Iterate over the DT 'phys' entries and configure them one by one. Use phy_set_mode_ext() to make use of the submode parameter (initially introduced for Ethernet modes). For PCI configuration, let the submode be the width (1, 2, 4, etc) so that the PHY driver knows how many lanes are bundled. Do not error out in case of error for compatibility reasons. Signed-off-by: Miquel Raynal Reviewed-by: Thomas Petazzoni --- drivers/pci/controller/dwc/pcie-armada8k.c | 82 +++++++++++++++++++++- 1 file changed, 81 insertions(+), 1 deletion(-) diff --git a/drivers/pci/controller/dwc/pcie-armada8k.c b/drivers/pci/controller/dwc/pcie-armada8k.c index 0c389a30ef5d..e567a7cfa3d7 100644 --- a/drivers/pci/controller/dwc/pcie-armada8k.c +++ b/drivers/pci/controller/dwc/pcie-armada8k.c @@ -25,10 +25,14 @@ #include "pcie-designware.h" +#define ARMADA8K_PCIE_MAX_LANES PCIE_LNK_X4 + struct armada8k_pcie { struct dw_pcie *pci; struct clk *clk; struct clk *clk_reg; + struct phy *phy[ARMADA8K_PCIE_MAX_LANES]; + unsigned int phy_count; }; #define PCIE_VENDOR_REGS_OFFSET 0x8000 @@ -67,6 +71,76 @@ struct armada8k_pcie { #define to_armada8k_pcie(x) dev_get_drvdata((x)->dev) +static void armada8k_pcie_disable_phys(struct armada8k_pcie *pcie) +{ + int i; + + for (i = 0; i < ARMADA8K_PCIE_MAX_LANES; i++) { + phy_power_off(pcie->phy[i]); + phy_exit(pcie->phy[i]); + } +} + +static int armada8k_pcie_enable_phys(struct armada8k_pcie *pcie) +{ + int ret; + int i; + + for (i = 0; i < ARMADA8K_PCIE_MAX_LANES; i++) { + ret = phy_init(pcie->phy[i]); + if (ret) + return ret; + + ret = phy_set_mode_ext(pcie->phy[i], PHY_MODE_PCIE, + pcie->phy_count); + if (ret) { + phy_exit(pcie->phy[i]); + return ret; + } + + ret = phy_power_on(pcie->phy[i]); + if (ret) { + phy_exit(pcie->phy[i]); + return ret; + } + } + + return 0; +} + +static int armada8k_pcie_setup_phys(struct armada8k_pcie *pcie) +{ + struct dw_pcie *pci = pcie->pci; + struct device *dev = pci->dev; + struct device_node *node = dev->of_node; + int ret = 0; + int i; + + for (i = 0; i < ARMADA8K_PCIE_MAX_LANES; i++) { + pcie->phy[i] = devm_of_phy_get_by_index(dev, node, i); + if (IS_ERR(pcie->phy[i]) && + (PTR_ERR(pcie->phy[i]) == -EPROBE_DEFER)) + return PTR_ERR(pcie->phy[i]); + + if (IS_ERR(pcie->phy[i])) { + pcie->phy[i] = NULL; + continue; + } + + pcie->phy_count++; + } + + /* Old bindings miss the PHY handle, so just warn if there is no PHY */ + if (!pcie->phy_count) + dev_warn(dev, "No available PHY\n"); + + ret = armada8k_pcie_enable_phys(pcie); + if (ret) + dev_err(dev, "Failed to initialize PHY(s) (%d)\n", ret); + + return ret; +} + static int armada8k_pcie_link_up(struct dw_pcie *pci) { u32 reg; @@ -249,14 +323,20 @@ static int armada8k_pcie_probe(struct platform_device *pdev) goto fail_clkreg; } + ret = armada8k_pcie_setup_phys(pcie); + if (ret) + goto fail_clkreg; + platform_set_drvdata(pdev, pcie); ret = armada8k_add_pcie_port(pcie, pdev); if (ret) - goto fail_clkreg; + goto disable_phy; return 0; +disable_phy: + armada8k_pcie_disable_phys(pcie); fail_clkreg: clk_disable_unprepare(pcie->clk_reg); fail: