From patchwork Fri Jul 14 03:52:42 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Shawn Lin X-Patchwork-Id: 9839855 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 0008C60212 for ; Fri, 14 Jul 2017 03:53:28 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id EFF1128783 for ; Fri, 14 Jul 2017 03:53:28 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id E492D28789; Fri, 14 Jul 2017 03:53:28 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-1.9 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID autolearn=unavailable version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [65.50.211.133]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 7497928783 for ; Fri, 14 Jul 2017 03:53:28 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:Cc:List-Subscribe: List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id:References: In-Reply-To:Message-Id:Date:Subject:To:From:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=GVhsvIFmPdv6gs907XLWfvg2L+eY4s9YlZI7v+Lhtsg=; b=RJBaPOABUlbv6w6WXAsKTtjlOY u6WdXD8WZ3kx/gwU+5ZdrURQa/YMFL8hf0nz/HCsiUdWGWVMJcgVragepVthZQPostaZ0C6jggd7b ypRPCxPzEk6Xyb1QMkOiU6GaWP7c9Ivuowq33Vo/ErXWx+JmrJ7CjKBb26jMAAeRBmOCat4If9D5r 5If5vo6xXS9drSX/JVHp2W+sFfmuI/HcDNP8xPdP37DCfoeOVumRl46iqcR+JPF2QRWDysoUajrY0 UP/ZNdc6iwplVxI5LE5JQ8w3mI9+QtVcyqDHOdiyY/fd5Tos3hpDoe6hILLF9uBQ1keBOtYcfvdJE cwkZHi0Q==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.87 #1 (Red Hat Linux)) id 1dVrfT-0003Z0-L7; Fri, 14 Jul 2017 03:53:27 +0000 Received: from lucky1.263xmail.com ([211.157.147.130]) by bombadil.infradead.org with esmtps (Exim 4.87 #1 (Red Hat Linux)) id 1dVrfP-0003Nf-Ug for linux-rockchip@lists.infradead.org; Fri, 14 Jul 2017 03:53:26 +0000 Received: from shawn.lin?rock-chips.com (unknown [192.168.167.205]) by lucky1.263xmail.com (Postfix) with ESMTP id 5C1591EF0AB; Fri, 14 Jul 2017 11:52:58 +0800 (CST) X-263anti-spam: KSV:0; X-MAIL-GRAY: 1 X-MAIL-DELIVERY: 0 X-KSVirus-check: 0 X-ABS-CHECKED: 4 Received: from localhost.localdomain (localhost [127.0.0.1]) by smtp.263.net (Postfix) with ESMTPA id 57A6B38A; Fri, 14 Jul 2017 11:52:57 +0800 (CST) X-RL-SENDER: shawn.lin@rock-chips.com X-FST-TO: bhelgaas@google.com X-SENDER-IP: 58.22.7.114 X-LOGIN-NAME: shawn.lin@rock-chips.com X-UNIQUE-TAG: X-ATTACHMENT-NUM: 0 X-SENDER: lintao@rock-chips.com X-DNS-TYPE: 0 Received: from localhost.localdomain (unknown [58.22.7.114]) by smtp.263.net (Postfix) whith ESMTP id 10780VTHXGJ; Fri, 14 Jul 2017 11:52:58 +0800 (CST) From: Shawn Lin To: Bjorn Helgaas , Rob Herring , Kishon Vijay Abraham I Subject: [RFC PATCH 2/6] PCI: rockchip: introduce per-lanes PHYs support Date: Fri, 14 Jul 2017 11:52:42 +0800 Message-Id: <1500004366-241633-1-git-send-email-shawn.lin@rock-chips.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1500004101-240296-1-git-send-email-shawn.lin@rock-chips.com> References: <1500004101-240296-1-git-send-email-shawn.lin@rock-chips.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20170713_205324_554245_700AF597 X-CRM114-Status: GOOD ( 14.65 ) X-BeenThere: linux-rockchip@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: Upstream kernel work for Rockchip platforms List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: devicetree@vger.kernel.org, Brian Norris , Heiko Stuebner , linux-pci@vger.kernel.org, Shawn Lin , Jeffy Chen , linux-rockchip@lists.infradead.org MIME-Version: 1.0 Sender: "Linux-rockchip" Errors-To: linux-rockchip-bounces+patchwork-linux-rockchip=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP We distinguish the legacy PHY with the newer per-lane PHYs by adding legacy_phy flag and consolidate all the phy operations into a single function to simply the code. Note that the legacy phy is still the first option to be searched in order not to break the backward compatibility of DT blob, althoug we use devm_phy_optional_get instead which seams to violate the original statement of pcie-rockchip's DT document. Signed-off-by: Shawn Lin --- drivers/pci/host/pcie-rockchip.c | 138 +++++++++++++++++++++++++++++++-------- 1 file changed, 112 insertions(+), 26 deletions(-) diff --git a/drivers/pci/host/pcie-rockchip.c b/drivers/pci/host/pcie-rockchip.c index 6632a51..a3dc7bd 100644 --- a/drivers/pci/host/pcie-rockchip.c +++ b/drivers/pci/host/pcie-rockchip.c @@ -47,6 +47,7 @@ #define HIWORD_UPDATE_BIT(val) HIWORD_UPDATE(val, val) #define ENCODE_LANES(x) ((((x) >> 1) & 3) << 4) +#define MAX_LANE_NUM 4 #define PCIE_CLIENT_BASE 0x0 #define PCIE_CLIENT_CONFIG (PCIE_CLIENT_BASE + 0x00) @@ -210,7 +211,9 @@ struct rockchip_pcie { void __iomem *reg_base; /* DT axi-base */ void __iomem *apb_base; /* DT apb-base */ + bool legacy_phy; struct phy *phy; + struct phy **phys; struct reset_control *core_rst; struct reset_control *mgmt_rst; struct reset_control *mgmt_sticky_rst; @@ -242,6 +245,15 @@ struct rockchip_pcie { phys_addr_t mem_bus_addr; }; +enum phy_ops_type { + PHY_INIT, + PHY_PWR_ON, + PHY_PWR_OFF, + PHY_EXIT, +}; + +const char *ops_name[] = {"init", "power on", "power off", "exit"}; + static u32 rockchip_pcie_read(struct rockchip_pcie *rockchip, u32 reg) { return readl(rockchip->apb_base + reg); @@ -507,6 +519,98 @@ static void rockchip_pcie_set_power_limit(struct rockchip_pcie *rockchip) rockchip_pcie_write(rockchip, status, PCIE_RC_CONFIG_DCR); } +static int rockchip_pcie_get_phys(struct rockchip_pcie *rockchip) +{ + struct device *dev = rockchip->dev; + struct phy *phy; + char *name; + u32 i; + + rockchip->phy = devm_phy_optional_get(dev, "pcie-phy"); + if (IS_ERR(rockchip->phy)) { + if (PTR_ERR(rockchip->phy) != -EPROBE_DEFER) + dev_err(dev, "missing phy\n"); + return PTR_ERR(rockchip->phy); + } else if (!rockchip->phy) { + rockchip->legacy_phy = false; + } else { + rockchip->legacy_phy = true; + return 0; + } + + /* per-lane PHYs */ + rockchip->phys = devm_kcalloc(dev, sizeof(phy), MAX_LANE_NUM, + GFP_KERNEL); + if (!rockchip->phys) + return -ENOMEM; + + for (i = 0; i < MAX_LANE_NUM; i++) { + name = kasprintf(GFP_KERNEL, "%s-%u", "pcie-phy", i); + if (!name) + return -ENOMEM; + + phy = devm_of_phy_get(rockchip->dev, + rockchip->dev->of_node, name); + kfree(name); + + if (IS_ERR(phy) && PTR_ERR(phy) == -ENODEV) { + phy = NULL; + } else if (IS_ERR(phy)) { + dev_err(dev, "failed to get per-lane PHY#%u: %ld\n", i, + PTR_ERR(phy)); + return PTR_ERR(phy); + } + + rockchip->phys[i] = phy; + } + + return 0; +} + +static int rockchip_pcie_manipulate_phys(struct rockchip_pcie *rockchip, + enum phy_ops_type type) +{ + int i, phy_num, err; + struct device *dev = rockchip->dev; + struct phy *phy; + + phy_num = rockchip->legacy_phy ? 1 : MAX_LANE_NUM; + + for (i = 0; i < phy_num; i++) { + phy = rockchip->legacy_phy ? rockchip->phy : + rockchip->phys[i]; + switch (type) { + case PHY_INIT: + err = phy_init(phy); + break; + case PHY_PWR_ON: + err = phy_power_on(phy); + break; + case PHY_PWR_OFF: + err = phy_power_off(phy); + break; + case PHY_EXIT: + err = phy_exit(phy); + break; + default: + dev_err(dev, "unsupported phy_ops_type\n"); + return -EOPNOTSUPP; + } + + if (err < 0) { + if (rockchip->legacy_phy) + dev_err(dev, "fail to %s legacy PHY, err %d\n", + ops_name[type], err); + else + dev_err(dev, "fail to %s per-lane PHY#%u, err %d\n", + ops_name[type], i, err); + return err; + } + } + + return 0; +} + /** * rockchip_pcie_init_port - Initialize hardware * @rockchip: PCIe port information @@ -537,11 +641,9 @@ static int rockchip_pcie_init_port(struct rockchip_pcie *rockchip) return err; } - err = phy_init(rockchip->phy); - if (err < 0) { - dev_err(dev, "fail to init phy, err %d\n", err); + err = rockchip_pcie_manipulate_phys(rockchip, PHY_INIT); + if (err < 0) return err; - } err = reset_control_assert(rockchip->core_rst); if (err) { @@ -602,11 +704,9 @@ static int rockchip_pcie_init_port(struct rockchip_pcie *rockchip) PCIE_CLIENT_MODE_RC, PCIE_CLIENT_CONFIG); - err = phy_power_on(rockchip->phy); - if (err) { - dev_err(dev, "fail to power on phy, err %d\n", err); + err = rockchip_pcie_manipulate_phys(rockchip, PHY_PWR_ON); + if (err) return err; - } /* * Please don't reorder the deassert sequence of the following @@ -853,20 +953,6 @@ static void rockchip_pcie_legacy_int_handler(struct irq_desc *desc) chained_irq_exit(chip, desc); } -static int rockchip_pcie_get_phys(struct rockchip_pcie *rockchip) -{ - struct device *dev = rockchip->dev; - - rockchip->phy = devm_phy_get(dev, "pcie-phy"); - if (IS_ERR(rockchip->phy)) { - if (PTR_ERR(rockchip->phy) != -EPROBE_DEFER) - dev_err(dev, "missing phy\n"); - return PTR_ERR(rockchip->phy); - } - - return 0; -} - /** * rockchip_pcie_parse_dt - Parse Device Tree * @rockchip: PCIe port information @@ -1295,8 +1381,8 @@ static int __maybe_unused rockchip_pcie_suspend_noirq(struct device *dev) return ret; } - phy_power_off(rockchip->phy); - phy_exit(rockchip->phy); + rockchip_pcie_manipulate_phys(rockchip, PHY_PWR_OFF); + rockchip_pcie_manipulate_phys(rockchip, PHY_EXIT); clk_disable_unprepare(rockchip->clk_pcie_pm); clk_disable_unprepare(rockchip->hclk_pcie); @@ -1538,8 +1624,8 @@ static int rockchip_pcie_remove(struct platform_device *pdev) pci_unmap_iospace(rockchip->io); irq_domain_remove(rockchip->irq_domain); - phy_power_off(rockchip->phy); - phy_exit(rockchip->phy); + rockchip_pcie_manipulate_phys(rockchip, PHY_PWR_OFF); + rockchip_pcie_manipulate_phys(rockchip, PHY_EXIT); clk_disable_unprepare(rockchip->clk_pcie_pm); clk_disable_unprepare(rockchip->hclk_pcie);