From mboxrd@z Thu Jan 1 00:00:00 1970 From: Kever Yang Date: Thu, 21 Jan 2021 12:00:05 +0800 Subject: [PATCH v2 1/2] phy: rockchip: Add Rockchip Synopsys PCIe 3.0 PHY In-Reply-To: <20210115100122.7385-2-shawn.lin@rock-chips.com> References: <20210115100122.7385-1-shawn.lin@rock-chips.com> <20210115100122.7385-2-shawn.lin@rock-chips.com> Message-ID: <63c53ecc-2975-013f-59a4-8cebb3c9edbc@rock-chips.com> List-Id: MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit To: u-boot@lists.denx.de On 2021/1/15 ??6:01, Shawn Lin wrote: > Add the Rockchip Synopsys based PCIe 3.0 PHY driver as > part of Generic PHY framework. > > Signed-off-by: Shawn Lin > Reviewed-by: Simon Glass Reviewed-by: Kever Yang Thanks, - Kever > --- > > Changes in v2: > - reoder header file > - add comment > > drivers/phy/rockchip/Kconfig | 6 + > drivers/phy/rockchip/Makefile | 1 + > .../phy/rockchip/phy-rockchip-snps-pcie3.c | 157 ++++++++++++++++++ > 3 files changed, 164 insertions(+) > create mode 100644 drivers/phy/rockchip/phy-rockchip-snps-pcie3.c > > diff --git a/drivers/phy/rockchip/Kconfig b/drivers/phy/rockchip/Kconfig > index 2318e71f35..b794cdaf6a 100644 > --- a/drivers/phy/rockchip/Kconfig > +++ b/drivers/phy/rockchip/Kconfig > @@ -18,6 +18,12 @@ config PHY_ROCKCHIP_PCIE > help > Enable this to support the Rockchip PCIe PHY. > > +config PHY_ROCKCHIP_SNPS_PCIE3 > + bool "Rockchip Snps PCIe3 PHY Driver" > + depends on PHY && ARCH_ROCKCHIP > + help > + Support for Rockchip PCIe3 PHY with Synopsys IP block. > + > config PHY_ROCKCHIP_TYPEC > bool "Rockchip TYPEC PHY Driver" > depends on ARCH_ROCKCHIP > diff --git a/drivers/phy/rockchip/Makefile b/drivers/phy/rockchip/Makefile > index 44049154f9..f6ad3bf59a 100644 > --- a/drivers/phy/rockchip/Makefile > +++ b/drivers/phy/rockchip/Makefile > @@ -5,4 +5,5 @@ > > obj-$(CONFIG_PHY_ROCKCHIP_INNO_USB2) += phy-rockchip-inno-usb2.o > obj-$(CONFIG_PHY_ROCKCHIP_PCIE) += phy-rockchip-pcie.o > +obj-$(CONFIG_PHY_ROCKCHIP_SNPS_PCIE3) += phy-rockchip-snps-pcie3.o > obj-$(CONFIG_PHY_ROCKCHIP_TYPEC) += phy-rockchip-typec.o > diff --git a/drivers/phy/rockchip/phy-rockchip-snps-pcie3.c b/drivers/phy/rockchip/phy-rockchip-snps-pcie3.c > new file mode 100644 > index 0000000000..5ae41fbeee > --- /dev/null > +++ b/drivers/phy/rockchip/phy-rockchip-snps-pcie3.c > @@ -0,0 +1,157 @@ > +// SPDX-License-Identifier: GPL-2.0 > +/* > + * Rockchip PCIE3.0 phy driver > + * > + * Copyright (C) 2021 Rockchip Electronics Co., Ltd. > + */ > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +#define GRF_PCIE30PHY_CON1 0x4 > +#define GRF_PCIE30PHY_CON6 0x18 > +#define GRF_PCIE30PHY_CON9 0x24 > + > +/** > + * struct rockchip_p3phy_priv - RK DW PCIe PHY state > + * > + * @mmio: The base address of PHY internal registers > + * @phy_grf: The regmap for controlling pipe signal > + * @p30phy: The reset signal for PHY > + * @ref_clk_m: The reference clock of M for PHY > + * @ref_clk_n: The reference clock of N for PHY > + * @pclk: The clock for accessing PHY blocks > + */ > +struct rockchip_p3phy_priv { > + void __iomem *mmio; > + struct regmap *phy_grf; > + struct reset_ctl p30phy; > + struct clk ref_clk_m; > + struct clk ref_clk_n; > + struct clk pclk; > +}; > + > +static int rochchip_p3phy_init(struct phy *phy) > +{ > + struct rockchip_p3phy_priv *priv = dev_get_priv(phy->dev); > + int ret; > + > + ret = clk_enable(&priv->ref_clk_m); > + if (ret < 0 && ret != -ENOSYS) > + return ret; > + > + ret = clk_enable(&priv->ref_clk_n); > + if (ret < 0 && ret != -ENOSYS) > + goto err_ref; > + > + ret = clk_enable(&priv->pclk); > + if (ret < 0 && ret != -ENOSYS) > + goto err_pclk; > + > + reset_assert(&priv->p30phy); > + udelay(1); > + > + /* Deassert PCIe PMA output clamp mode */ > + regmap_write(priv->phy_grf, GRF_PCIE30PHY_CON9, > + (0x1 << 15) | (0x1 << 31)); > + > + reset_deassert(&priv->p30phy); > + udelay(1); > + > + return 0; > +err_pclk: > + clk_disable(&priv->ref_clk_n); > +err_ref: > + clk_disable(&priv->ref_clk_m); > + > + return ret; > +} > + > +static int rochchip_p3phy_exit(struct phy *phy) > +{ > + struct rockchip_p3phy_priv *priv = dev_get_priv(phy->dev); > + > + clk_disable(&priv->ref_clk_m); > + clk_disable(&priv->ref_clk_n); > + clk_disable(&priv->pclk); > + reset_assert(&priv->p30phy); > + > + return 0; > +} > + > +static int rockchip_p3phy_probe(struct udevice *dev) > +{ > + struct rockchip_p3phy_priv *priv = dev_get_priv(dev); > + struct udevice *syscon; > + int ret; > + > + priv->mmio = (void __iomem *)dev_read_addr(dev); > + if ((fdt_addr_t)priv->mmio == FDT_ADDR_T_NONE) > + return -EINVAL; > + > + ret = uclass_get_device_by_phandle(UCLASS_SYSCON, dev, > + "rockchip,phy-grf", &syscon); > + if (ret) { > + pr_err("unable to find syscon device for rockchip,phy-grf\n"); > + return ret; > + } > + > + priv->phy_grf = syscon_get_regmap(syscon); > + if (IS_ERR(priv->phy_grf)) { > + dev_err(dev, "failed to find rockchip,phy_grf regmap\n"); > + return PTR_ERR(priv->phy_grf); > + } > + > + ret = reset_get_by_name(dev, "phy", &priv->p30phy); > + if (ret) { > + dev_err(dev, "no phy reset control specified\n"); > + return ret; > + } > + > + ret = clk_get_by_name(dev, "refclk_m", &priv->ref_clk_m); > + if (ret) { > + dev_err(dev, "failed to find ref clock M\n"); > + return PTR_ERR(&priv->ref_clk_m); > + } > + > + ret = clk_get_by_name(dev, "refclk_n", &priv->ref_clk_n); > + if (ret) { > + dev_err(dev, "failed to find ref clock N\n"); > + return PTR_ERR(&priv->ref_clk_n); > + } > + > + ret = clk_get_by_name(dev, "pclk", &priv->pclk); > + if (ret) { > + dev_err(dev, "failed to find pclk\n"); > + return PTR_ERR(&priv->pclk); > + } > + > + return 0; > +} > + > +static struct phy_ops rochchip_p3phy_ops = { > + .init = rochchip_p3phy_init, > + .exit = rochchip_p3phy_exit, > +}; > + > +static const struct udevice_id rockchip_p3phy_of_match[] = { > + { .compatible = "rockchip,rk3568-pcie3-phy" }, > + { }, > +}; > + > +U_BOOT_DRIVER(rockchip_pcie3phy) = { > + .name = "rockchip_pcie3phy", > + .id = UCLASS_PHY, > + .of_match = rockchip_p3phy_of_match, > + .ops = &rochchip_p3phy_ops, > + .probe = rockchip_p3phy_probe, > + .priv_auto = sizeof(struct rockchip_p3phy_priv), > +};