From patchwork Thu Apr 30 21:45:23 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jagan Teki X-Patchwork-Id: 1141 Return-Path: X-Original-To: linux-amarula@patchwork.amarulasolutions.com Delivered-To: linux-amarula@patchwork.amarulasolutions.com Received: from mail-pg1-f197.google.com (mail-pg1-f197.google.com [209.85.215.197]) by ganimede.amarulasolutions.com (Postfix) with ESMTPS id ADC003F077 for ; Thu, 30 Apr 2020 23:45:56 +0200 (CEST) Received: by mail-pg1-f197.google.com with SMTP id u15sf6679166pgg.14 for ; Thu, 30 Apr 2020 14:45:56 -0700 (PDT) ARC-Seal: i=2; a=rsa-sha256; t=1588283155; cv=pass; d=google.com; s=arc-20160816; b=XrAh6TCsTnRsJmYRhAyp6K8WeOwGF6fN6/FaOrzes11vST/PyrRR6nkb1/hykbsb8P 48SGpEZeYybjKkj0QydvshSiAfD3VxrPj8LjfsvW9Zmg3zg8LkXu1dAB71AkVMSKvcXl YMG/dsXW1h5LqZHdKkn/un7Tr5CDxwd3MbOOe8lwxtelHIL5qN+rocvuaNnwCR032sqF W73WUCqvKfSihWBCWhDaac6W7Mj0SLTsh310f+kbua5hDK3ShQcBl346YhBJ3nC4uh49 y24GOq1qFVPOqRlIdyeEDplbYYcmm17jdZ3vC8tz6LMo4GjFcycI40JYMAiGx7fkvUeK FaCg== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-unsubscribe:list-archive:list-help:list-post:list-id :mailing-list:precedence:references:in-reply-to:message-id:date :subject:cc:to:from:mime-version:dkim-signature; bh=U5Q6b/VnnwfruCaCbQsBPzrlR5c/x3r7UO0II97xenk=; b=YbTKmFxHnK3P3cs62fBwbMdwLEmhoJiqVEahxLaZpIwDWqW82zA7V6nvyB4d8uJqXY AEiQPOge88GIrg3ol1SRYY0PKmOlg9btJjcDF0recQTC801uq29160ZMs7OpROTJHRRw wOZaaDyhgNa+LInmgJ8+pQFAcm7Hceokdr/3x2igBp059utAW6aIdLs19FlZ8JdJZe+R 4X2kg3378Ur3U2g41+/0d91nGGfRjpuev67EKAMcsZG5lAUAYsm8on6iWfA+Ra4sB7VC cxqrugul9kXy+C7qMzuq9oErGG3BR3IUApW+LtMez0lrivbmAJ8o+PV5ZGeYnnSejuPz Tq4w== ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@amarulasolutions.com header.s=google header.b=IEibsAiA; spf=pass (google.com: domain of jagan@amarulasolutions.com designates 209.85.220.65 as permitted sender) smtp.mailfrom=jagan@amarulasolutions.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amarulasolutions.com; s=google; h=mime-version:from:to:cc:subject:date:message-id:in-reply-to :references:x-original-sender:x-original-authentication-results :precedence:mailing-list:list-id:list-post:list-help:list-archive :list-unsubscribe; bh=U5Q6b/VnnwfruCaCbQsBPzrlR5c/x3r7UO0II97xenk=; b=LvYWj7mx0hPuNULTyk+kQTDWl/8gZl4iGX3GIRZJRSlo91KSewk5NHIg24OUo2uBcx djD44uJwyPrGmDzkAXhaQ01AzrKILQEVCDPK9pKM78gRjl6riZGGtE7rw8Y8AnBxiKw9 nc6BcQbZe63BwqWD+wC8fHs1H+If4qOYenHAU= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:from:to:cc:subject:date:message-id :in-reply-to:references:x-original-sender :x-original-authentication-results:precedence:mailing-list:list-id :x-spam-checked-in-group:list-post:list-help:list-archive :list-unsubscribe; bh=U5Q6b/VnnwfruCaCbQsBPzrlR5c/x3r7UO0II97xenk=; b=nwwHj9I6lHn9Da4J/B6dEz4VjHH3gLbotN1VuHJUOAP4VMK1b/tYQrShtKAuIJcDor v6WoSaQ/Q82/RTO0xP/tHeMBUXFpQobZCkfdEgW+gvIysvjkIJ1SIj1YqXdMIhSiFq3i ulAZnaru8k0ReCvHUqhLWB9VgoMA6HnuB2TFYISUGimNw4MkqoSHtZymmZ0+xWjNe+fS tyH73S/5VyedzbHfTB6k2H9Kdxaak+7HReVVDSKK0E//ig6MN/fWD25eoNpUAd7BaiwK HLoo7TF4hIYfXgKuDxySveWIF4hlSDXDOnI0X914UT318yKmjsEfGkgF7IHUwLfLwPxz qowA== X-Gm-Message-State: AGi0PuYp2IeRz1LZagVKurrKnSjwDkx9viXyCeRMW8YFQrHha0dZvoDa H1fSDFUo7qOA9ZN5lHRgoRA/XivV X-Google-Smtp-Source: APiQypIa3l9Q5nY5ni5CkplEINwJH1GgtkgNdYyZ949yeklKthKlpMk5PpWzegvlKVKVIX2l6Pc3uw== X-Received: by 2002:a63:2214:: with SMTP id i20mr1046970pgi.307.1588283154706; Thu, 30 Apr 2020 14:45:54 -0700 (PDT) MIME-Version: 1.0 X-BeenThere: linux-amarula@amarulasolutions.com Received: by 2002:a17:90a:8a98:: with SMTP id x24ls3913398pjn.0.gmail; Thu, 30 Apr 2020 14:45:54 -0700 (PDT) X-Received: by 2002:a17:90a:2281:: with SMTP id s1mr1032218pjc.68.1588283154210; Thu, 30 Apr 2020 14:45:54 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1588283154; cv=none; d=google.com; s=arc-20160816; b=R3BWHEK6+ubw70Nx0rNRcJsuQOoKyTKmu/Xgm+hJdBHqGykuUGNuvNabUECKlB17BE mt+gZuvg00X9r2g9Dp9fardz7u+6GS8YAYIMsgpK4hnwo97pY5jnKaluNb6UAyCBo37E G0IsQIflwnnI1Qi3N+Lv4C3Fbv9wTyshiO65kYRDfR5GDVMdWCillFJWRKY4u286oG/7 oAE+w7hX8ZxNcfcU6C7p8CtCOBQx5qzASndz6gq00um+L3w62mdnAZl7ga0aqfSK8bTo U3YI5bKD0VGFATFkHIF7/8GiORKvIyyy6nPm3AInTgTNygbhOnmeMnscHkBzAbNLgNiR zBjg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=L+A6rotdTZxuFABPL+Mc8AuyhvfS/Z9BRk0edgcGHN8=; b=EumHu5yuFi7rfsVEQCgKecLmqEixdYlSmFYMoKMpYgm7s+zO4woRGahweUFYhSor9y kV3A7pB6/kuNJU2zA/I0ZhrOYVwuW6u+7+pi1my4QmReyavdPtbO71XY6hAURWiXPc1O vEDjdgnWQBpQ4Uliy9hKFUbd9d3aHFMy6pEkwnFaH6VqdVWbcWTg51uLu9k16IKRN7NB Vx8ufLCEaTBnJfbXjTKP5K6SUGGFlOJ7k6meIJjt9CpEouMuIMFEwbWRu7Tojmkcy1Cp tHMFFI9ZgkmUUhdr3ufdyE4jSEAtn70aHNCqpQcHzpYBiZp6qKVq0FgZgsOvfMkPLX0S SrVA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@amarulasolutions.com header.s=google header.b=IEibsAiA; spf=pass (google.com: domain of jagan@amarulasolutions.com designates 209.85.220.65 as permitted sender) smtp.mailfrom=jagan@amarulasolutions.com Received: from mail-sor-f65.google.com (mail-sor-f65.google.com. [209.85.220.65]) by mx.google.com with SMTPS id u3sor1129969pjy.8.2020.04.30.14.45.53 for (Google Transport Security); Thu, 30 Apr 2020 14:45:53 -0700 (PDT) Received-SPF: pass (google.com: domain of jagan@amarulasolutions.com designates 209.85.220.65 as permitted sender) client-ip=209.85.220.65; X-Received: by 2002:a17:90a:2004:: with SMTP id n4mr1003560pjc.190.1588283153100; Thu, 30 Apr 2020 14:45:53 -0700 (PDT) Received: from localhost.localdomain ([2405:201:c809:c7d5:a9f2:11c6:8c6c:2861]) by smtp.gmail.com with ESMTPSA id p64sm615243pjp.7.2020.04.30.14.45.48 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 30 Apr 2020 14:45:52 -0700 (PDT) From: Jagan Teki To: Kever Yang , Simon Glass , Philipp Tomsich , Tom Rini , Frank Wang , William Wu , Shawn Lin , Heiko Stuebner , Patrice Chotard Cc: u-boot@lists.denx.de, linux-rockchip@lists.infradead.org, linux-amarula@amarulasolutions.com, Jagan Teki Subject: [RFC 1/7] phy: Add Rockchip PCIe PHY driver Date: Fri, 1 May 2020 03:15:23 +0530 Message-Id: <20200430214529.18887-2-jagan@amarulasolutions.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200430214529.18887-1-jagan@amarulasolutions.com> References: <20200430214529.18887-1-jagan@amarulasolutions.com> X-Original-Sender: jagan@amarulasolutions.com X-Original-Authentication-Results: mx.google.com; dkim=pass header.i=@amarulasolutions.com header.s=google header.b=IEibsAiA; spf=pass (google.com: domain of jagan@amarulasolutions.com designates 209.85.220.65 as permitted sender) smtp.mailfrom=jagan@amarulasolutions.com Content-Type: text/plain; charset="UTF-8" Precedence: list Mailing-list: list linux-amarula@amarulasolutions.com; contact linux-amarula+owners@amarulasolutions.com List-ID: X-Spam-Checked-In-Group: linux-amarula@amarulasolutions.com X-Google-Group-Id: 476853432473 List-Post: , List-Help: , List-Archive: List-Unsubscribe: , Add the Rockchip PCIe PHY driver as part of Generic PHY framework. Signed-off-by: Jagan Teki --- drivers/Kconfig | 2 + drivers/Makefile | 1 + drivers/phy/rockchip/Kconfig | 9 + drivers/phy/rockchip/Makefile | 6 + drivers/phy/rockchip/phy-rockchip-pcie.c | 271 +++++++++++++++++++++++ 5 files changed, 289 insertions(+) create mode 100644 drivers/phy/rockchip/Kconfig create mode 100644 drivers/phy/rockchip/Makefile create mode 100644 drivers/phy/rockchip/phy-rockchip-pcie.c diff --git a/drivers/Kconfig b/drivers/Kconfig index e34a22708c..2fe23f953c 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -76,6 +76,8 @@ source "drivers/phy/allwinner/Kconfig" source "drivers/phy/marvell/Kconfig" +source "drivers/phy/rockchip/Kconfig" + source "drivers/pinctrl/Kconfig" source "drivers/power/Kconfig" diff --git a/drivers/Makefile b/drivers/Makefile index 4208750428..94e8c5da17 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -91,6 +91,7 @@ obj-y += dfu/ obj-$(CONFIG_PCH) += pch/ obj-y += phy/allwinner/ obj-y += phy/marvell/ +obj-y += phy/rockchip/ obj-y += rtc/ obj-y += scsi/ obj-y += sound/ diff --git a/drivers/phy/rockchip/Kconfig b/drivers/phy/rockchip/Kconfig new file mode 100644 index 0000000000..477c68920b --- /dev/null +++ b/drivers/phy/rockchip/Kconfig @@ -0,0 +1,9 @@ +# +# Phy drivers for Rockchip platforms +# +config PHY_ROCKCHIP_PCIE + bool "Rockchip PCIe PHY Driver" + depends on ARCH_ROCKCHIP + select PHY + help + Enable this to support the Rockchip PCIe PHY. diff --git a/drivers/phy/rockchip/Makefile b/drivers/phy/rockchip/Makefile new file mode 100644 index 0000000000..4d19ccdfd0 --- /dev/null +++ b/drivers/phy/rockchip/Makefile @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# Copyright (C) 2020 Amarula Solutions(India) +# + +obj-$(CONFIG_PHY_ROCKCHIP_PCIE) += phy-rockchip-pcie.o diff --git a/drivers/phy/rockchip/phy-rockchip-pcie.c b/drivers/phy/rockchip/phy-rockchip-pcie.c new file mode 100644 index 0000000000..83928cffe0 --- /dev/null +++ b/drivers/phy/rockchip/phy-rockchip-pcie.c @@ -0,0 +1,271 @@ +// SPDX-License-Identifier: (GPL-2.0-only) +/* + * Rockchip PCIe PHY driver + * + * Copyright (C) 2020 Amarula Solutions(India) + * Copyright (C) 2016 Shawn Lin + * Copyright (C) 2016 ROCKCHIP, Inc. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +/* + * The higher 16-bit of this register is used for write protection + * only if BIT(x + 16) set to 1 the BIT(x) can be written. + */ +#define HIWORD_UPDATE(val, mask, shift) \ + ((val) << (shift) | (mask) << ((shift) + 16)) + +#define PHY_MAX_LANE_NUM 4 +#define PHY_CFG_DATA_SHIFT 7 +#define PHY_CFG_ADDR_SHIFT 1 +#define PHY_CFG_DATA_MASK 0xf +#define PHY_CFG_ADDR_MASK 0x3f +#define PHY_CFG_RD_MASK 0x3ff +#define PHY_CFG_WR_ENABLE 1 +#define PHY_CFG_WR_DISABLE 1 +#define PHY_CFG_WR_SHIFT 0 +#define PHY_CFG_WR_MASK 1 +#define PHY_CFG_PLL_LOCK 0x10 +#define PHY_CFG_CLK_TEST 0x10 +#define PHY_CFG_CLK_SCC 0x12 +#define PHY_CFG_SEPE_RATE BIT(3) +#define PHY_CFG_PLL_100M BIT(3) +#define PHY_PLL_LOCKED BIT(9) +#define PHY_PLL_OUTPUT BIT(10) +#define PHY_LANE_RX_DET_SHIFT 11 +#define PHY_LANE_RX_DET_TH 0x1 +#define PHY_LANE_IDLE_OFF 0x1 +#define PHY_LANE_IDLE_MASK 0x1 +#define PHY_LANE_IDLE_A_SHIFT 3 +#define PHY_LANE_IDLE_B_SHIFT 4 +#define PHY_LANE_IDLE_C_SHIFT 5 +#define PHY_LANE_IDLE_D_SHIFT 6 + +struct rockchip_pcie_phy_data { + unsigned int pcie_conf; + unsigned int pcie_status; + unsigned int pcie_laneoff; +}; + +struct rockchip_pcie_phy { + void *reg_base; + struct clk refclk; + struct reset_ctl phy_rst; + const struct rockchip_pcie_phy_data *data; +}; + +static void phy_wr_cfg(struct rockchip_pcie_phy *priv, u32 addr, u32 data) +{ + u32 reg; + + reg = HIWORD_UPDATE(data, PHY_CFG_DATA_MASK, PHY_CFG_DATA_SHIFT); + reg |= HIWORD_UPDATE(addr, PHY_CFG_ADDR_MASK, PHY_CFG_ADDR_SHIFT); + writel(reg, priv->reg_base + priv->data->pcie_conf); + + udelay(1); + + reg = HIWORD_UPDATE(PHY_CFG_WR_ENABLE, + PHY_CFG_WR_MASK, + PHY_CFG_WR_SHIFT); + writel(reg, priv->reg_base + priv->data->pcie_conf); + + udelay(1); + + reg = HIWORD_UPDATE(PHY_CFG_WR_DISABLE, + PHY_CFG_WR_MASK, + PHY_CFG_WR_SHIFT); + writel(reg, priv->reg_base + priv->data->pcie_conf); +} + +static int rockchip_pcie_phy_power_on(struct phy *phy) +{ + struct rockchip_pcie_phy *priv = dev_get_priv(phy->dev); + int ret = 0; + u32 reg, status; + + ret = reset_deassert(&priv->phy_rst); + if (ret) { + dev_err(dev, "failed to assert phy reset\n"); + return ret; + } + + reg = HIWORD_UPDATE(PHY_CFG_PLL_LOCK, + PHY_CFG_ADDR_MASK, + PHY_CFG_ADDR_SHIFT); + writel(reg, priv->reg_base + priv->data->pcie_conf); + + reg = HIWORD_UPDATE(!PHY_LANE_IDLE_OFF, + PHY_LANE_IDLE_MASK, + PHY_LANE_IDLE_A_SHIFT); + writel(reg, priv->reg_base + priv->data->pcie_laneoff); + + ret = -EINVAL; + ret = readl_poll_sleep_timeout(priv->reg_base + priv->data->pcie_status, + status, + status & PHY_PLL_LOCKED, + 20 * 1000, + 50); + if (ret) { + dev_err(&priv->dev, "pll lock timeout!\n"); + goto err_pll_lock; + } + + phy_wr_cfg(priv, PHY_CFG_CLK_TEST, PHY_CFG_SEPE_RATE); + phy_wr_cfg(priv, PHY_CFG_CLK_SCC, PHY_CFG_PLL_100M); + + ret = -ETIMEDOUT; + ret = readl_poll_sleep_timeout(priv->reg_base + priv->data->pcie_status, + status, + !(status & PHY_PLL_OUTPUT), + 20 * 1000, + 50); + if (ret) { + dev_err(&priv->dev, "pll output enable timeout!\n"); + goto err_pll_lock; + } + + reg = HIWORD_UPDATE(PHY_CFG_PLL_LOCK, + PHY_CFG_ADDR_MASK, + PHY_CFG_ADDR_SHIFT); + writel(reg, priv->reg_base + priv->data->pcie_conf); + + ret = -EINVAL; + ret = readl_poll_sleep_timeout(priv->reg_base + priv->data->pcie_status, + status, + status & PHY_PLL_LOCKED, + 20 * 1000, + 50); + if (ret) { + dev_err(&priv->dev, "pll relock timeout!\n"); + goto err_pll_lock; + } + + return 0; + +err_pll_lock: + reset_assert(&priv->phy_rst); + return ret; +} + +static int rockchip_pcie_phy_power_off(struct phy *phy) +{ + struct rockchip_pcie_phy *priv = dev_get_priv(phy->dev); + int ret; + u32 reg; + + reg = HIWORD_UPDATE(PHY_LANE_IDLE_OFF, + PHY_LANE_IDLE_MASK, + PHY_LANE_IDLE_A_SHIFT); + writel(reg, priv->reg_base + priv->data->pcie_laneoff); + + ret = reset_assert(&priv->phy_rst); + if (ret) { + dev_err(dev, "failed to assert phy reset\n"); + return ret; + } + + return 0; +} + +static int rockchip_pcie_phy_init(struct phy *phy) +{ + struct rockchip_pcie_phy *priv = dev_get_priv(phy->dev); + int ret; + + ret = clk_enable(&priv->refclk); + if (ret) { + dev_err(dev, "failed to enable refclk clock\n"); + return ret; + } + + ret = reset_assert(&priv->phy_rst); + if (ret) { + dev_err(dev, "failed to assert phy reset\n"); + goto err_reset; + } + + return 0; + +err_reset: + clk_disable(&priv->refclk); + return ret; +} + +static int rockchip_pcie_phy_exit(struct phy *phy) +{ + struct rockchip_pcie_phy *priv = dev_get_priv(phy->dev); + + clk_disable(&priv->refclk); + + return 0; +} + +static struct phy_ops rockchip_pcie_phy_ops = { + .init = rockchip_pcie_phy_init, + .power_on = rockchip_pcie_phy_power_on, + .power_off = rockchip_pcie_phy_power_off, + .exit = rockchip_pcie_phy_exit, +}; + +static int rockchip_pcie_phy_probe(struct udevice *dev) +{ + struct rockchip_pcie_phy *priv = dev_get_priv(dev); + int ret; + + priv->data = (const struct rockchip_pcie_phy_data *) + dev_get_driver_data(dev); + if (!priv->data) + return -EINVAL; + + priv->reg_base = syscon_get_first_range(ROCKCHIP_SYSCON_GRF); + + ret = clk_get_by_name(dev, "refclk", &priv->refclk); + if (ret) { + dev_err(dev, "failed to get refclk clock phandle\n"); + return ret; + } + + ret = reset_get_by_name(dev, "phy", &priv->phy_rst); + if (ret) { + dev_err(dev, "failed to get phy reset phandle\n"); + return ret; + } + + return 0; +} + +static const struct rockchip_pcie_phy_data rk3399_pcie_data = { + .pcie_conf = 0xe220, + .pcie_status = 0xe2a4, + .pcie_laneoff = 0xe214, +}; + +static const struct udevice_id rockchip_pcie_phy_ids[] = { + { + .compatible = "rockchip,rk3399-pcie-phy", + .data = (ulong)&rk3399_pcie_data, + }, + { /* sentile */ } +}; + +U_BOOT_DRIVER(rockchip_pcie_phy) = { + .name = "rockchip_pcie_phy", + .id = UCLASS_PHY, + .of_match = rockchip_pcie_phy_ids, + .ops = &rockchip_pcie_phy_ops, + .probe = rockchip_pcie_phy_probe, + .priv_auto_alloc_size = sizeof(struct rockchip_pcie_phy), +};