From patchwork Mon Dec 23 21:45:27 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Remi Pommarel X-Patchwork-Id: 11308777 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 91745109A for ; Mon, 23 Dec 2019 21:38:22 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 70484206CB for ; Mon, 23 Dec 2019 21:38:22 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="qxHG2h1O" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 70484206CB Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=triplefau.lt Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-amlogic-bounces+patchwork-linux-amlogic=patchwork.kernel.org@lists.infradead.org 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:Cc:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version: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=YqDqlPi+2dvEC3/F2Xqs0eXlCtN7CRLRf+PL0ApdoNQ=; b=qxHG2h1OO3rYob hDfe/Z/HK1l+6CD/Cm0BZ7QhpaZF0bqBAqa3wLqNprpj3zgjOCeWcmg+vxSB1AoTmfULTSJiMc9TN H92iaRy4yK3+i93Vv2uFTuQ7pXRQAXFaLqEnMcMwtBsxS/BkC7XyQMkPOFgvtiuiSEK1TJHq9VjWf cogtnvl7/ZqAutugMBv2b9/Z6UXdI1oDz2HO7KlBDht5BFsmj3JYqF/xuoZOIOP1xr9cGH9woKT6m xAUBmKiAfAADVAsGa39hGh3nLowG8rPQr9Qr7/crh+l/LtpVFLPtycOKvPy3FvovYOJhESvm8GVYe Kguq38n1bVGXM+5LZQTA==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1ijVPB-0006oc-V1; Mon, 23 Dec 2019 21:38:21 +0000 Received: from relay10.mail.gandi.net ([217.70.178.230]) by bombadil.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1ijVP6-0006l1-NM for linux-amlogic@lists.infradead.org; Mon, 23 Dec 2019 21:38:18 +0000 Received: from localhost (unknown [88.190.179.123]) (Authenticated sender: repk@triplefau.lt) by relay10.mail.gandi.net (Postfix) with ESMTPSA id 90219240007; Mon, 23 Dec 2019 21:38:03 +0000 (UTC) From: Remi Pommarel To: Kishon Vijay Abraham I , Yue Wang , Lorenzo Pieralisi , Andrew Murray , Kevin Hilman , Martin Blumenstingl , Neil Armstrong Subject: [PATCH v2 1/3] phy: amlogic: Add Amlogic AXG MIPI/PCIE PHY Driver Date: Mon, 23 Dec 2019 22:45:27 +0100 Message-Id: <20191223214529.20377-2-repk@triplefau.lt> X-Mailer: git-send-email 2.24.0 In-Reply-To: <20191223214529.20377-1-repk@triplefau.lt> References: <20191223214529.20377-1-repk@triplefau.lt> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20191223_133817_031472_9C1AF118 X-CRM114-Status: GOOD ( 14.52 ) X-Spam-Score: -0.7 (/) X-Spam-Report: SpamAssassin version 3.4.2 on bombadil.infradead.org summary: Content analysis details: (-0.7 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.7 RCVD_IN_DNSWL_LOW RBL: Sender listed at https://www.dnswl.org/, low trust [217.70.178.230 listed in list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record X-BeenThere: linux-amlogic@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: linux-pci@vger.kernel.org, linux-amlogic@lists.infradead.org, Remi Pommarel , linux-kernel@vger.kernel.org, Jerome Brunet Sender: "linux-amlogic" Errors-To: linux-amlogic-bounces+patchwork-linux-amlogic=patchwork.kernel.org@lists.infradead.org This adds support for the MIPI PHY also needed for PCIE found in the Amlogic AXG SoC Family. MIPI or PCIE selection is done by the #phy-cells, making the mode static and exclusive. For now only PCIE fonctionality is supported. This PHY will be used to replace the mipi_enable clock gating logic which was mistakenly added in the clock subsystem. This also activate a non documented band gap bit in those registers that allows reliable PCIE clock signal generation on AXG platforms. Signed-off-by: Remi Pommarel --- drivers/phy/amlogic/Kconfig | 11 ++ drivers/phy/amlogic/Makefile | 1 + drivers/phy/amlogic/phy-meson-axg-mipi-pcie.c | 176 ++++++++++++++++++ 3 files changed, 188 insertions(+) create mode 100644 drivers/phy/amlogic/phy-meson-axg-mipi-pcie.c diff --git a/drivers/phy/amlogic/Kconfig b/drivers/phy/amlogic/Kconfig index af774ac2b934..1eeb75d018e3 100644 --- a/drivers/phy/amlogic/Kconfig +++ b/drivers/phy/amlogic/Kconfig @@ -59,3 +59,14 @@ config PHY_MESON_G12A_USB3_PCIE Enable this to support the Meson USB3 + PCIE Combo PHY found in Meson G12A SoCs. If unsure, say N. + +config PHY_MESON_AXG_MIPI_PCIE + tristate "Meson AXG MIPI + PCIE PHY driver" + default ARCH_MESON + depends on OF && (ARCH_MESON || COMPILE_TEST) + select GENERIC_PHY + select MFD_SYSCON + help + Enable this to support the Meson MIPI + PCIE PHY found + in Meson AXG SoCs. + If unsure, say N. diff --git a/drivers/phy/amlogic/Makefile b/drivers/phy/amlogic/Makefile index 11d1c42ac2be..2167330a0ae8 100644 --- a/drivers/phy/amlogic/Makefile +++ b/drivers/phy/amlogic/Makefile @@ -4,3 +4,4 @@ obj-$(CONFIG_PHY_MESON_GXL_USB2) += phy-meson-gxl-usb2.o obj-$(CONFIG_PHY_MESON_G12A_USB2) += phy-meson-g12a-usb2.o obj-$(CONFIG_PHY_MESON_GXL_USB3) += phy-meson-gxl-usb3.o obj-$(CONFIG_PHY_MESON_G12A_USB3_PCIE) += phy-meson-g12a-usb3-pcie.o +obj-$(CONFIG_PHY_MESON_AXG_MIPI_PCIE) += phy-meson-axg-mipi-pcie.o diff --git a/drivers/phy/amlogic/phy-meson-axg-mipi-pcie.c b/drivers/phy/amlogic/phy-meson-axg-mipi-pcie.c new file mode 100644 index 000000000000..006aa8cdfc47 --- /dev/null +++ b/drivers/phy/amlogic/phy-meson-axg-mipi-pcie.c @@ -0,0 +1,176 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Amlogic AXG MIPI + PCIE PHY driver + * + * Copyright (C) 2019 Remi Pommarel + */ +#include +#include +#include +#include +#include +#include + +#define HHI_MIPI_CNTL0 0x00 +#define HHI_MIPI_CNTL0_COMMON_BLOCK GENMASK(31, 28) +#define HHI_MIPI_CNTL0_ENABLE BIT(29) +#define HHI_MIPI_CNTL0_BANDGAP BIT(26) +#define HHI_MIPI_CNTL0_DECODE_TO_RTERM GENMASK(15, 12) +#define HHI_MIPI_CNTL0_OUTPUT_EN BIT(3) + +#define HHI_MIPI_CNTL1 0x01 +#define HHI_MIPI_CNTL1_CH0_CML_PDR_EN BIT(12) +#define HHI_MIPI_CNTL1_LP_ABILITY GENMASK(5, 4) +#define HHI_MIPI_CNTL1_LP_RESISTER BIT(3) +#define HHI_MIPI_CNTL1_INPUT_SETTING BIT(2) +#define HHI_MIPI_CNTL1_INPUT_SEL BIT(1) +#define HHI_MIPI_CNTL1_PRBS7_EN BIT(0) + +#define HHI_MIPI_CNTL2 0x02 +#define HHI_MIPI_CNTL2_CH_PU GENMASK(31, 25) +#define HHI_MIPI_CNTL2_CH_CTL GENMASK(24, 19) +#define HHI_MIPI_CNTL2_CH0_DIGDR_EN BIT(18) +#define HHI_MIPI_CNTL2_CH_DIGDR_EN BIT(17) +#define HHI_MIPI_CNTL2_LPULPS_EN BIT(16) +#define HHI_MIPI_CNTL2_CH_EN(n) BIT(15 - (n)) +#define HHI_MIPI_CNTL2_CH0_LP_CTL GENMASK(10, 1) + +struct phy_axg_mipi_pcie_priv { + struct phy *phy; + unsigned int mode; + struct regmap *regmap; +}; + +static const struct regmap_config phy_axg_mipi_pcie_regmap_conf = { + .reg_bits = 8, + .val_bits = 32, + .reg_stride = 4, + .max_register = HHI_MIPI_CNTL2, +}; + +static int phy_axg_mipi_pcie_power_on(struct phy *phy) +{ + struct phy_axg_mipi_pcie_priv *priv = phy_get_drvdata(phy); + + /* MIPI not supported yet */ + if (priv->mode != PHY_TYPE_PCIE) + return 0; + + regmap_update_bits(priv->regmap, HHI_MIPI_CNTL0, + HHI_MIPI_CNTL0_BANDGAP, HHI_MIPI_CNTL0_BANDGAP); + + regmap_update_bits(priv->regmap, HHI_MIPI_CNTL0, + HHI_MIPI_CNTL0_ENABLE, HHI_MIPI_CNTL0_ENABLE); + return 0; +} + +static int phy_axg_mipi_pcie_power_off(struct phy *phy) +{ + struct phy_axg_mipi_pcie_priv *priv = phy_get_drvdata(phy); + + /* MIPI not supported yet */ + if (priv->mode != PHY_TYPE_PCIE) + return 0; + + regmap_update_bits(priv->regmap, HHI_MIPI_CNTL0, + HHI_MIPI_CNTL0_BANDGAP, 0); + regmap_update_bits(priv->regmap, HHI_MIPI_CNTL0, + HHI_MIPI_CNTL0_ENABLE, 0); + return 0; +} + +static int phy_axg_mipi_pcie_init(struct phy *phy) +{ + return 0; +} + +static int phy_axg_mipi_pcie_exit(struct phy *phy) +{ + return 0; +} + +static const struct phy_ops phy_axg_mipi_pcie_ops = { + .init = phy_axg_mipi_pcie_init, + .exit = phy_axg_mipi_pcie_exit, + .power_on = phy_axg_mipi_pcie_power_on, + .power_off = phy_axg_mipi_pcie_power_off, + .owner = THIS_MODULE, +}; + +static struct phy *phy_axg_mipi_pcie_xlate(struct device *dev, + struct of_phandle_args *args) +{ + struct phy_axg_mipi_pcie_priv *priv = dev_get_drvdata(dev); + unsigned int mode; + + if (args->args_count != 1) { + dev_err(dev, "invalid number of arguments\n"); + return ERR_PTR(-EINVAL); + } + + mode = args->args[0]; + + /* MIPI mode is not supported yet */ + if (mode != PHY_TYPE_PCIE) { + dev_err(dev, "invalid phy mode select argument\n"); + return ERR_PTR(-EINVAL); + } + + priv->mode = mode; + return priv->phy; +} + +static int phy_axg_mipi_pcie_probe(struct platform_device *pdev) +{ + struct phy_provider *pphy; + struct device *dev = &pdev->dev; + struct phy_axg_mipi_pcie_priv *priv; + struct device_node *np = dev->of_node; + int ret; + + priv = devm_kmalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + /* Get the hhi system controller node */ + priv->regmap = syscon_node_to_regmap(of_get_parent(dev->of_node)); + if (IS_ERR(priv->regmap)) { + dev_err(dev, "failed to get HHI regmap\n"); + return PTR_ERR(priv->regmap); + } + + priv->phy = devm_phy_create(dev, np, &phy_axg_mipi_pcie_ops); + if (IS_ERR(priv->phy)) { + ret = PTR_ERR(priv->phy); + if (ret != -EPROBE_DEFER) + dev_err(dev, "failed to create PHY\n"); + return ret; + } + + phy_set_drvdata(priv->phy, priv); + dev_set_drvdata(dev, priv); + pphy = devm_of_phy_provider_register(dev, phy_axg_mipi_pcie_xlate); + + return PTR_ERR_OR_ZERO(pphy); +} + +static const struct of_device_id phy_axg_mipi_pcie_of_match[] = { + { + .compatible = "amlogic,axg-mipi-pcie-phy", + }, + { }, +}; +MODULE_DEVICE_TABLE(of, phy_axg_mipi_pcie_of_match); + +static struct platform_driver phy_axg_mipi_pcie_driver = { + .probe = phy_axg_mipi_pcie_probe, + .driver = { + .name = "phy-axg-mipi-pcie", + .of_match_table = phy_axg_mipi_pcie_of_match, + }, +}; +module_platform_driver(phy_axg_mipi_pcie_driver); + +MODULE_AUTHOR("Remi Pommarel "); +MODULE_DESCRIPTION("Amlogic AXG MIPI + PCIE PHY driver"); +MODULE_LICENSE("GPL v2"); From patchwork Mon Dec 23 21:45:28 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Remi Pommarel X-Patchwork-Id: 11308781 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 8098A138D for ; Mon, 23 Dec 2019 21:38:27 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 5F45E206CB for ; Mon, 23 Dec 2019 21:38:27 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="Qmcv1l9T" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 5F45E206CB Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=triplefau.lt Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-amlogic-bounces+patchwork-linux-amlogic=patchwork.kernel.org@lists.infradead.org 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:Cc:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version: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=EvnbI575sm4A9ne8D6uk77kv391igm76ePKaq+y+3xE=; b=Qmcv1l9T9e2nPa uZn3ixN7sOYAY3gQ+v5DDQnN/+Sox+6bVWPF0Qk/4cMs/puiM6AVU2/QAjwVakgeOqt18GRZ5WgYK SO9CE7LwgFh0Rwf2X8bozzYlsfsuBZIc1my+/K9xSVR1goUQwGe6wApaH5luwSwhOPQ0/jsy/+Hs3 36D40YvTg+xGJiKjezOuZ+dZWwze85o2aeQQgds0XvxdhSzwxmiBerNUtIuOj3md1/DHDwyWKMf6J 9ls3PX1NMK0wnTOAvn7zqhp5m+u9AyHNjOQzWGfjX8/qGOO3r/eyk76yAYmvdeVM3OzQLtS+mvlOJ RRdgFNXruGY+p4/SXlpQ==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1ijVPG-0006ty-V2; Mon, 23 Dec 2019 21:38:26 +0000 Received: from relay7-d.mail.gandi.net ([217.70.183.200]) by bombadil.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1ijVPC-0006nC-IG for linux-amlogic@lists.infradead.org; Mon, 23 Dec 2019 21:38:24 +0000 X-Originating-IP: 88.190.179.123 Received: from localhost (unknown [88.190.179.123]) (Authenticated sender: repk@triplefau.lt) by relay7-d.mail.gandi.net (Postfix) with ESMTPSA id AA18A20004; Mon, 23 Dec 2019 21:38:10 +0000 (UTC) From: Remi Pommarel To: Kishon Vijay Abraham I , Yue Wang , Lorenzo Pieralisi , Andrew Murray , Kevin Hilman , Martin Blumenstingl , Neil Armstrong Subject: [PATCH v2 2/3] phy: amlogic: Add Amlogic AXG PCIE PHY Driver Date: Mon, 23 Dec 2019 22:45:28 +0100 Message-Id: <20191223214529.20377-3-repk@triplefau.lt> X-Mailer: git-send-email 2.24.0 In-Reply-To: <20191223214529.20377-1-repk@triplefau.lt> References: <20191223214529.20377-1-repk@triplefau.lt> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20191223_133822_885818_0C3E5D23 X-CRM114-Status: GOOD ( 14.46 ) X-Spam-Score: -0.7 (/) X-Spam-Report: SpamAssassin version 3.4.2 on bombadil.infradead.org summary: Content analysis details: (-0.7 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.7 RCVD_IN_DNSWL_LOW RBL: Sender listed at https://www.dnswl.org/, low trust [217.70.183.200 listed in list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record -0.0 RCVD_IN_MSPIKE_H2 RBL: Average reputation (+2) [217.70.183.200 listed in wl.mailspike.net] 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record X-BeenThere: linux-amlogic@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: linux-pci@vger.kernel.org, linux-amlogic@lists.infradead.org, Remi Pommarel , linux-kernel@vger.kernel.org, Jerome Brunet Sender: "linux-amlogic" Errors-To: linux-amlogic-bounces+patchwork-linux-amlogic=patchwork.kernel.org@lists.infradead.org This adds support for the PCI PHY found in the Amlogic AXG SoC Family. This will allow to mutualize code in pci-meson.c between AXG and G12A SoC. Signed-off-by: Remi Pommarel --- drivers/phy/amlogic/Kconfig | 11 ++ drivers/phy/amlogic/Makefile | 1 + drivers/phy/amlogic/phy-meson-axg-pcie.c | 163 +++++++++++++++++++++++ 3 files changed, 175 insertions(+) create mode 100644 drivers/phy/amlogic/phy-meson-axg-pcie.c diff --git a/drivers/phy/amlogic/Kconfig b/drivers/phy/amlogic/Kconfig index 1eeb75d018e3..2a3935169ef4 100644 --- a/drivers/phy/amlogic/Kconfig +++ b/drivers/phy/amlogic/Kconfig @@ -60,6 +60,17 @@ config PHY_MESON_G12A_USB3_PCIE in Meson G12A SoCs. If unsure, say N. +config PHY_MESON_AXG_PCIE + tristate "Meson AXG PCIE PHY driver" + default ARCH_MESON + depends on OF && (ARCH_MESON || COMPILE_TEST) + select GENERIC_PHY + select REGMAP_MMIO + help + Enable this to support the Meson MIPI + PCIE PHY found + in Meson AXG SoCs. + If unsure, say N. + config PHY_MESON_AXG_MIPI_PCIE tristate "Meson AXG MIPI + PCIE PHY driver" default ARCH_MESON diff --git a/drivers/phy/amlogic/Makefile b/drivers/phy/amlogic/Makefile index 2167330a0ae8..5fd3a6dca0a5 100644 --- a/drivers/phy/amlogic/Makefile +++ b/drivers/phy/amlogic/Makefile @@ -4,4 +4,5 @@ obj-$(CONFIG_PHY_MESON_GXL_USB2) += phy-meson-gxl-usb2.o obj-$(CONFIG_PHY_MESON_G12A_USB2) += phy-meson-g12a-usb2.o obj-$(CONFIG_PHY_MESON_GXL_USB3) += phy-meson-gxl-usb3.o obj-$(CONFIG_PHY_MESON_G12A_USB3_PCIE) += phy-meson-g12a-usb3-pcie.o +obj-$(CONFIG_PHY_MESON_AXG_PCIE) += phy-meson-axg-pcie.o obj-$(CONFIG_PHY_MESON_AXG_MIPI_PCIE) += phy-meson-axg-mipi-pcie.o diff --git a/drivers/phy/amlogic/phy-meson-axg-pcie.c b/drivers/phy/amlogic/phy-meson-axg-pcie.c new file mode 100644 index 000000000000..559c42c1524d --- /dev/null +++ b/drivers/phy/amlogic/phy-meson-axg-pcie.c @@ -0,0 +1,163 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Amlogic AXG PCIE PHY driver + * + * Copyright (C) 2019 Remi Pommarel + */ +#include +#include +#include +#include +#include +#include +#include + +#define MESON_PCIE_REG0 0x00 +#define MESON_PCIE_COMMON_CLK BIT(4) +#define MESON_PCIE_PORT_SEL GENMASK(3, 2) +#define MESON_PCIE_CLK BIT(1) +#define MESON_PCIE_POWERDOWN BIT(0) + +#define MESON_PCIE_TWO_X1 FIELD_PREP(MESON_PCIE_PORT_SEL, 0x3) +#define MESON_PCIE_COMMON_REF_CLK FIELD_PREP(MESON_PCIE_COMMON_CLK, 0x1) +#define MESON_PCIE_PHY_INIT (MESON_PCIE_TWO_X1 | \ + MESON_PCIE_COMMON_REF_CLK) +#define MESON_PCIE_RESET_DELAY 500 + +struct phy_axg_pcie_priv { + struct phy *phy; + struct regmap *regmap; + struct reset_control *reset; +}; + +static const struct regmap_config phy_axg_pcie_regmap_conf = { + .reg_bits = 8, + .val_bits = 32, + .reg_stride = 4, + .max_register = MESON_PCIE_REG0, +}; + +static int phy_axg_pcie_power_on(struct phy *phy) +{ + struct phy_axg_pcie_priv *priv = phy_get_drvdata(phy); + + regmap_update_bits(priv->regmap, MESON_PCIE_REG0, + MESON_PCIE_POWERDOWN, 0); + return 0; +} + +static int phy_axg_pcie_power_off(struct phy *phy) +{ + struct phy_axg_pcie_priv *priv = phy_get_drvdata(phy); + + regmap_update_bits(priv->regmap, MESON_PCIE_REG0, + MESON_PCIE_POWERDOWN, 1); + return 0; +} + +static int phy_axg_pcie_init(struct phy *phy) +{ + struct phy_axg_pcie_priv *priv = phy_get_drvdata(phy); + + regmap_write(priv->regmap, MESON_PCIE_REG0, MESON_PCIE_PHY_INIT); + return reset_control_reset(priv->reset); +} + +static int phy_axg_pcie_exit(struct phy *phy) +{ + struct phy_axg_pcie_priv *priv = phy_get_drvdata(phy); + + return reset_control_reset(priv->reset); +} + +static int phy_axg_pcie_reset(struct phy *phy) +{ + struct phy_axg_pcie_priv *priv = phy_get_drvdata(phy); + int ret = 0; + + ret = reset_control_assert(priv->reset); + if (ret != 0) + goto out; + udelay(MESON_PCIE_RESET_DELAY); + + ret = reset_control_deassert(priv->reset); + if (ret != 0) + goto out; + udelay(MESON_PCIE_RESET_DELAY); + +out: + return ret; +} + +static const struct phy_ops phy_axg_pcie_ops = { + .init = phy_axg_pcie_init, + .exit = phy_axg_pcie_exit, + .power_on = phy_axg_pcie_power_on, + .power_off = phy_axg_pcie_power_off, + .reset = phy_axg_pcie_reset, + .owner = THIS_MODULE, +}; + +static int phy_axg_pcie_probe(struct platform_device *pdev) +{ + struct phy_provider *pphy; + struct device *dev = &pdev->dev; + struct phy_axg_pcie_priv *priv; + struct device_node *np = dev->of_node; + struct resource *res; + void __iomem *base; + int ret; + + priv = devm_kmalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->phy = devm_phy_create(dev, np, &phy_axg_pcie_ops); + if (IS_ERR(priv->phy)) { + ret = PTR_ERR(priv->phy); + if (ret != -EPROBE_DEFER) + dev_err(dev, "failed to create PHY\n"); + return ret; + } + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + base = devm_ioremap_resource(dev, res); + if (IS_ERR(base)) + return PTR_ERR(base); + + priv->regmap = devm_regmap_init_mmio(dev, base, + &phy_axg_pcie_regmap_conf); + if (IS_ERR(priv->regmap)) + return PTR_ERR(priv->regmap); + + priv->reset = devm_reset_control_array_get(dev, false, false); + if (IS_ERR(priv->reset)) + return PTR_ERR(priv->reset); + + phy_set_drvdata(priv->phy, priv); + dev_set_drvdata(dev, priv); + pphy = devm_of_phy_provider_register(dev, of_phy_simple_xlate); + + return PTR_ERR_OR_ZERO(pphy); +} + +static const struct of_device_id phy_axg_pcie_of_match[] = { + { + .compatible = "amlogic,axg-pcie-phy", + }, + { }, +}; +MODULE_DEVICE_TABLE(of, phy_axg_pcie_of_match); + +static struct platform_driver phy_axg_pcie_driver = { + .probe = phy_axg_pcie_probe, + .driver = { + .name = "phy-axg-pcie", + .of_match_table = phy_axg_pcie_of_match, + }, +}; +module_platform_driver(phy_axg_pcie_driver); + +MODULE_AUTHOR("Remi Pommarel "); +MODULE_DESCRIPTION("Amlogic AXG PCIE PHY driver"); +MODULE_LICENSE("GPL v2"); From patchwork Mon Dec 23 21:45:29 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Remi Pommarel X-Patchwork-Id: 11308779 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 02AC4138D for ; Mon, 23 Dec 2019 21:38:24 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id D1AAC206CB for ; Mon, 23 Dec 2019 21:38:23 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="GJNXGqNi" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org D1AAC206CB Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=triplefau.lt Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-amlogic-bounces+patchwork-linux-amlogic=patchwork.kernel.org@lists.infradead.org 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:Cc:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version: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=wwzomCvXUHlGgU0pEZ7i/Ogf4d0C8chNQjVEh/9Kvgg=; b=GJNXGqNiGLaRdQ pIsXZPRW4WUeYJJmQPD84lNCGdlaTFeLMf3z93dV5gMQMt5WpatwW7638dSXIW5D3bHGFwVR4XH5B xwIwosA/A9HcMyL4Nun3ng7GI7G5NQ8OJzx5x9TInFQuvDYH6fhmUZtjbejpw0jQU0zCSFCESp8aw 5nK6jPvSOzv8062E8KdmeBArcT8HwDHaCrNzTLtfbo1rTQWsYwdEAtE7549iIRq1W4gNxUKrw9CzY yRnanr2Ubi+4scQV5LfzJM+GmLJsHLqA1pczVJeRYcr/uiGmWKEcQSulgs1EPndNMjxvZOiKGLT6b ZK/Ro8PVKZpZ7ZY0N3IA==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1ijVPD-0006pz-3D; Mon, 23 Dec 2019 21:38:23 +0000 Received: from relay10.mail.gandi.net ([217.70.178.230]) by bombadil.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1ijVP7-0006lw-Ge for linux-amlogic@lists.infradead.org; Mon, 23 Dec 2019 21:38:19 +0000 Received: from localhost (unknown [88.190.179.123]) (Authenticated sender: repk@triplefau.lt) by relay10.mail.gandi.net (Postfix) with ESMTPSA id 82C37240006; Mon, 23 Dec 2019 21:38:14 +0000 (UTC) From: Remi Pommarel To: Kishon Vijay Abraham I , Yue Wang , Lorenzo Pieralisi , Andrew Murray , Kevin Hilman , Martin Blumenstingl , Neil Armstrong Subject: [PATCH v2 3/3] PCI: amlogic: Use AXG PCIE and shared MIPI/PCIE PHYs Date: Mon, 23 Dec 2019 22:45:29 +0100 Message-Id: <20191223214529.20377-4-repk@triplefau.lt> X-Mailer: git-send-email 2.24.0 In-Reply-To: <20191223214529.20377-1-repk@triplefau.lt> References: <20191223214529.20377-1-repk@triplefau.lt> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20191223_133817_818785_51743CE9 X-CRM114-Status: GOOD ( 13.65 ) X-Spam-Score: -0.7 (/) X-Spam-Report: SpamAssassin version 3.4.2 on bombadil.infradead.org summary: Content analysis details: (-0.7 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.7 RCVD_IN_DNSWL_LOW RBL: Sender listed at https://www.dnswl.org/, low trust [217.70.178.230 listed in list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record X-BeenThere: linux-amlogic@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: linux-pci@vger.kernel.org, linux-amlogic@lists.infradead.org, Remi Pommarel , linux-kernel@vger.kernel.org, Jerome Brunet Sender: "linux-amlogic" Errors-To: linux-amlogic-bounces+patchwork-linux-amlogic=patchwork.kernel.org@lists.infradead.org Now that PCIE PHY has been introduced for AXG, the whole has_shared_phy logic can be mutualized between AXG and G12A platforms. This also makes use of the optional MIPI/PCIE shared fonctionality PHY found on AXG platforms, which need to be used in order to have reliable PCIE communications. Signed-off-by: Remi Pommarel --- drivers/pci/controller/dwc/pci-meson.c | 140 ++++++++----------------- 1 file changed, 46 insertions(+), 94 deletions(-) diff --git a/drivers/pci/controller/dwc/pci-meson.c b/drivers/pci/controller/dwc/pci-meson.c index 3772b02a5c55..3d12155c32f6 100644 --- a/drivers/pci/controller/dwc/pci-meson.c +++ b/drivers/pci/controller/dwc/pci-meson.c @@ -66,7 +66,6 @@ #define PORT_CLK_RATE 100000000UL #define MAX_PAYLOAD_SIZE 256 #define MAX_READ_REQ_SIZE 256 -#define MESON_PCIE_PHY_POWERUP 0x1c #define PCIE_RESET_DELAY 500 #define PCIE_SHARED_RESET 1 #define PCIE_NORMAL_RESET 0 @@ -81,26 +80,19 @@ enum pcie_data_rate { struct meson_pcie_mem_res { void __iomem *elbi_base; void __iomem *cfg_base; - void __iomem *phy_base; }; struct meson_pcie_clk_res { struct clk *clk; - struct clk *mipi_gate; struct clk *port_clk; struct clk *general_clk; }; struct meson_pcie_rc_reset { - struct reset_control *phy; struct reset_control *port; struct reset_control *apb; }; -struct meson_pcie_param { - bool has_shared_phy; -}; - struct meson_pcie { struct dw_pcie pci; struct meson_pcie_mem_res mem_res; @@ -108,7 +100,7 @@ struct meson_pcie { struct meson_pcie_rc_reset mrst; struct gpio_desc *reset_gpio; struct phy *phy; - const struct meson_pcie_param *param; + struct phy *shared_phy; }; static struct reset_control *meson_pcie_get_reset(struct meson_pcie *mp, @@ -130,13 +122,6 @@ static int meson_pcie_get_resets(struct meson_pcie *mp) { struct meson_pcie_rc_reset *mrst = &mp->mrst; - if (!mp->param->has_shared_phy) { - mrst->phy = meson_pcie_get_reset(mp, "phy", PCIE_SHARED_RESET); - if (IS_ERR(mrst->phy)) - return PTR_ERR(mrst->phy); - reset_control_deassert(mrst->phy); - } - mrst->port = meson_pcie_get_reset(mp, "port", PCIE_NORMAL_RESET); if (IS_ERR(mrst->port)) return PTR_ERR(mrst->port); @@ -162,22 +147,6 @@ static void __iomem *meson_pcie_get_mem(struct platform_device *pdev, return devm_ioremap_resource(dev, res); } -static void __iomem *meson_pcie_get_mem_shared(struct platform_device *pdev, - struct meson_pcie *mp, - const char *id) -{ - struct device *dev = mp->pci.dev; - struct resource *res; - - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, id); - if (!res) { - dev_err(dev, "No REG resource %s\n", id); - return ERR_PTR(-ENXIO); - } - - return devm_ioremap(dev, res->start, resource_size(res)); -} - static int meson_pcie_get_mems(struct platform_device *pdev, struct meson_pcie *mp) { @@ -189,14 +158,6 @@ static int meson_pcie_get_mems(struct platform_device *pdev, if (IS_ERR(mp->mem_res.cfg_base)) return PTR_ERR(mp->mem_res.cfg_base); - /* Meson AXG SoC has two PCI controllers use same phy register */ - if (!mp->param->has_shared_phy) { - mp->mem_res.phy_base = - meson_pcie_get_mem_shared(pdev, mp, "phy"); - if (IS_ERR(mp->mem_res.phy_base)) - return PTR_ERR(mp->mem_res.phy_base); - } - return 0; } @@ -204,20 +165,40 @@ static int meson_pcie_power_on(struct meson_pcie *mp) { int ret = 0; - if (mp->param->has_shared_phy) { - ret = phy_init(mp->phy); - if (ret) - return ret; + ret = phy_init(mp->phy); + if (ret) + goto err; - ret = phy_power_on(mp->phy); - if (ret) { - phy_exit(mp->phy); - return ret; - } - } else - writel(MESON_PCIE_PHY_POWERUP, mp->mem_res.phy_base); + ret = phy_init(mp->shared_phy); + if (ret) + goto exit; + + ret = phy_power_on(mp->phy); + if (ret) + goto shared_exit; + + ret = phy_power_on(mp->shared_phy); + if (ret) + goto power_off; return 0; + +power_off: + phy_power_off(mp->phy); +shared_exit: + phy_exit(mp->shared_phy); +exit: + phy_exit(mp->phy); +err: + return ret; +} + +static void meson_pcie_power_off(struct meson_pcie *mp) +{ + phy_power_off(mp->shared_phy); + phy_power_off(mp->phy); + phy_exit(mp->shared_phy); + phy_exit(mp->phy); } static int meson_pcie_reset(struct meson_pcie *mp) @@ -225,16 +206,13 @@ static int meson_pcie_reset(struct meson_pcie *mp) struct meson_pcie_rc_reset *mrst = &mp->mrst; int ret = 0; - if (mp->param->has_shared_phy) { - ret = phy_reset(mp->phy); - if (ret) - return ret; - } else { - reset_control_assert(mrst->phy); - udelay(PCIE_RESET_DELAY); - reset_control_deassert(mrst->phy); - udelay(PCIE_RESET_DELAY); - } + ret = phy_reset(mp->phy); + if (ret) + return ret; + + ret = phy_reset(mp->shared_phy); + if (ret) + return ret; reset_control_assert(mrst->port); reset_control_assert(mrst->apb); @@ -286,12 +264,6 @@ static int meson_pcie_probe_clocks(struct meson_pcie *mp) if (IS_ERR(res->port_clk)) return PTR_ERR(res->port_clk); - if (!mp->param->has_shared_phy) { - res->mipi_gate = meson_pcie_probe_clock(dev, "mipi", 0); - if (IS_ERR(res->mipi_gate)) - return PTR_ERR(res->mipi_gate); - } - res->general_clk = meson_pcie_probe_clock(dev, "general", 0); if (IS_ERR(res->general_clk)) return PTR_ERR(res->general_clk); @@ -562,7 +534,6 @@ static const struct dw_pcie_ops dw_pcie_ops = { static int meson_pcie_probe(struct platform_device *pdev) { - const struct meson_pcie_param *match_data; struct device *dev = &pdev->dev; struct dw_pcie *pci; struct meson_pcie *mp; @@ -576,18 +547,13 @@ static int meson_pcie_probe(struct platform_device *pdev) pci->dev = dev; pci->ops = &dw_pcie_ops; - match_data = of_device_get_match_data(dev); - if (!match_data) { - dev_err(dev, "failed to get match data\n"); - return -ENODEV; - } - mp->param = match_data; + mp->phy = devm_phy_get(dev, "pcie"); + if (IS_ERR(mp->phy)) + return PTR_ERR(mp->phy); - if (mp->param->has_shared_phy) { - mp->phy = devm_phy_get(dev, "pcie"); - if (IS_ERR(mp->phy)) - return PTR_ERR(mp->phy); - } + mp->shared_phy = devm_phy_optional_get(dev, "shared"); + if (IS_ERR(mp->phy)) + return PTR_ERR(mp->phy); mp->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW); if (IS_ERR(mp->reset_gpio)) { @@ -636,30 +602,16 @@ static int meson_pcie_probe(struct platform_device *pdev) return 0; err_phy: - if (mp->param->has_shared_phy) { - phy_power_off(mp->phy); - phy_exit(mp->phy); - } - + meson_pcie_power_off(mp); return ret; } -static struct meson_pcie_param meson_pcie_axg_param = { - .has_shared_phy = false, -}; - -static struct meson_pcie_param meson_pcie_g12a_param = { - .has_shared_phy = true, -}; - static const struct of_device_id meson_pcie_of_match[] = { { .compatible = "amlogic,axg-pcie", - .data = &meson_pcie_axg_param, }, { .compatible = "amlogic,g12a-pcie", - .data = &meson_pcie_g12a_param, }, {}, };