brintos

brintos / linux-shallow public Read only

0
0
Text · 21.8 KiB · 0ac9634 Raw
846 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * PCIe phy driver for Kirin 9704 *5 * Copyright (C) 2017 HiSilicon Electronics Co., Ltd.6 *		https://www.huawei.com7 * Copyright (C) 2021 Huawei Technologies Co., Ltd.8 *		https://www.huawei.com9 *10 * Authors:11 *	Mauro Carvalho Chehab <mchehab+huawei@kernel.org>12 *	Manivannan Sadhasivam <mani@kernel.org>13 *14 * Based on:15 *	https://lore.kernel.org/lkml/4c9d6581478aa966698758c0420933f5defab4dd.1612335031.git.mchehab+huawei@kernel.org/16 */17 18#include <linux/bitfield.h>19#include <linux/clk.h>20#include <linux/gpio.h>21#include <linux/kernel.h>22#include <linux/mfd/syscon.h>23#include <linux/module.h>24#include <linux/of_gpio.h>25#include <linux/phy/phy.h>26#include <linux/platform_device.h>27#include <linux/regmap.h>28 29#define AXI_CLK_FREQ				20750000030#define REF_CLK_FREQ				10000000031 32/* PCIe CTRL registers */33#define SOC_PCIECTRL_CTRL7_ADDR			0x01c34#define SOC_PCIECTRL_CTRL12_ADDR		0x03035#define SOC_PCIECTRL_CTRL20_ADDR		0x05036#define SOC_PCIECTRL_CTRL21_ADDR		0x05437 38#define PCIE_OUTPUT_PULL_BITS			GENMASK(3, 0)39#define SOC_PCIECTRL_CTRL20_2P_MEM_CTRL		0x0260555040#define SOC_PCIECTRL_CTRL21_DEFAULT		0x2000007041#define PCIE_PULL_UP_SYS_AUX_PWR_DET		BIT(10)42#define PCIE_OUTPUT_PULL_DOWN			BIT(1)43 44/* PCIe PHY registers */45#define SOC_PCIEPHY_CTRL0_ADDR			0x00046#define SOC_PCIEPHY_CTRL1_ADDR			0x00447#define SOC_PCIEPHY_CTRL38_ADDR			0x009848#define SOC_PCIEPHY_STATE0_ADDR			0x40049 50#define RAWLANEN_DIG_PCS_XF_TX_OVRD_IN_1	0xc00451#define SUP_DIG_LVL_OVRD_IN			0x003c52#define LANEN_DIG_ASIC_TX_OVRD_IN_1		0x400853#define LANEN_DIG_ASIC_TX_OVRD_IN_2		0x400c54 55#define PCIEPHY_RESET_BIT			BIT(17)56#define PCIEPHY_PIPE_LINE0_RESET_BIT		BIT(19)57#define PCIE_TXDETECT_RX_FAIL			BIT(2)58#define PCIE_CLK_SOURCE				BIT(8)59#define PCIE_IS_CLOCK_STABLE			BIT(19)60#define PCIE_PULL_DOWN_PHY_TEST_POWERDOWN	BIT(22)61#define PCIE_DEASSERT_CONTROLLER_PERST		BIT(2)62 63#define EYEPARAM_NOCFG				0xffffffff64#define EYE_PARM0_MASK				GENMASK(8, 6)65#define EYE_PARM1_MASK				GENMASK(11, 8)66#define EYE_PARM2_MASK				GENMASK(5, 0)67#define EYE_PARM3_MASK				GENMASK(12, 7)68#define EYE_PARM4_MASK				GENMASK(14, 9)69#define EYE_PARM0_EN				BIT(9)70#define EYE_PARM1_EN				BIT(12)71#define EYE_PARM2_EN				BIT(6)72#define EYE_PARM3_EN				BIT(13)73#define EYE_PARM4_EN				BIT(15)74 75/* hi3670 pciephy register */76#define APB_PHY_START_ADDR			0x4000077#define SOC_PCIEPHY_MMC1PLL_CTRL1		0xc0478#define SOC_PCIEPHY_MMC1PLL_CTRL16		0xC4079#define SOC_PCIEPHY_MMC1PLL_CTRL17		0xC4480#define SOC_PCIEPHY_MMC1PLL_CTRL20		0xC5081#define SOC_PCIEPHY_MMC1PLL_CTRL21		0xC5482#define SOC_PCIEPHY_MMC1PLL_STAT0		0xE0083 84#define CRGPERIPH_PEREN12			0x47085#define CRGPERIPH_PERDIS12			0x47486#define CRGPERIPH_PCIECTRL0			0x80087 88#define PCIE_FNPLL_FBDIV_MASK			GENMASK(27, 16)89#define PCIE_FNPLL_FRACDIV_MASK			GENMASK(23, 0)90#define PCIE_FNPLL_POSTDIV1_MASK		GENMASK(10, 8)91#define PCIE_FNPLL_POSTDIV2_MASK		GENMASK(14, 12)92#define PCIE_FNPLL_PLL_MODE_MASK		BIT(25)93 94#define PCIE_FNPLL_DLL_EN			BIT(27)95#define PCIE_FNPLL_FBDIV			0xd096#define PCIE_FNPLL_FRACDIV			0x55555597#define PCIE_FNPLL_POSTDIV1			0x598#define PCIE_FNPLL_POSTDIV2			0x499#define PCIE_FNPLL_PLL_MODE			0x0100 101#define PCIE_PHY_MMC1PLL			0x20102#define PCIE_PHY_CHOOSE_FNPLL			BIT(27)103#define PCIE_PHY_MMC1PLL_DISABLE		BIT(0)104#define PCIE_PHY_PCIEPL_BP			BIT(16)105 106/* define ie,oe cfg */107#define IO_OE_HARD_GT_MODE			BIT(1)108#define IO_IE_EN_HARD_BYPASS			BIT(27)109#define IO_OE_EN_HARD_BYPASS			BIT(11)110#define IO_HARD_CTRL_DEBOUNCE_BYPASS		BIT(10)111#define IO_OE_GT_MODE				BIT(8)112#define DEBOUNCE_WAITCFG_IN			GENMASK(23, 20)113#define DEBOUNCE_WAITCFG_OUT			GENMASK(16, 13)114 115#define IO_HP_DEBOUNCE_GT			(BIT(12) | BIT(15))116#define IO_PHYREF_SOFT_GT_MODE			BIT(14)117#define IO_REF_SOFT_GT_MODE			BIT(13)118#define IO_REF_HARD_GT_MODE			BIT(0)119 120/* noc power domain */121#define NOC_POWER_IDLEREQ_1			0x38c122#define NOC_POWER_IDLE_1			0x394123#define NOC_PW_MASK				0x10000124#define NOC_PW_SET_BIT				0x1125 126#define NUM_EYEPARAM				5127 128/* info located in sysctrl */129#define SCTRL_PCIE_CMOS_OFFSET			0x60130#define SCTRL_PCIE_CMOS_BIT			0x10131#define SCTRL_PCIE_ISO_OFFSET			0x44132#define SCTRL_PCIE_ISO_BIT			0x30133#define SCTRL_PCIE_HPCLK_OFFSET			0x190134#define SCTRL_PCIE_HPCLK_BIT			0x184000135#define SCTRL_PCIE_OE_OFFSET			0x14a136#define PCIE_DEBOUNCE_PARAM			0xf0f400137#define PCIE_OE_BYPASS				GENMASK(29, 28)138 139/* peri_crg ctrl */140#define CRGCTRL_PCIE_ASSERT_OFFSET		0x88141#define CRGCTRL_PCIE_ASSERT_BIT			0x8c000000142 143#define FNPLL_HAS_LOCKED			BIT(4)144 145/* Time for delay */146#define TIME_CMOS_MIN		100147#define TIME_CMOS_MAX		105148#define PIPE_CLK_STABLE_TIME	100149#define PLL_CTRL_WAIT_TIME	200150#define NOC_POWER_TIME		100151 152struct hi3670_pcie_phy {153	struct device	*dev;154	void __iomem	*base;155	struct regmap	*apb;156	struct regmap	*crgctrl;157	struct regmap	*sysctrl;158	struct regmap	*pmctrl;159	struct clk	*apb_sys_clk;160	struct clk	*apb_phy_clk;161	struct clk	*phy_ref_clk;162	struct clk	*aclk;163	struct clk	*aux_clk;164	u32		eye_param[NUM_EYEPARAM];165};166 167/* Registers in PCIePHY */168static inline void hi3670_apb_phy_writel(struct hi3670_pcie_phy *phy, u32 val,169					 u32 reg)170{171	writel(val, phy->base + APB_PHY_START_ADDR + reg);172}173 174static inline u32 hi3670_apb_phy_readl(struct hi3670_pcie_phy *phy, u32 reg)175{176	return readl(phy->base + APB_PHY_START_ADDR + reg);177}178 179static inline void hi3670_apb_phy_updatel(struct hi3670_pcie_phy *phy,180					  u32 val, u32 mask, u32 reg)181{182	u32 regval;183 184	regval = hi3670_apb_phy_readl(phy, reg);185	regval &= ~mask;186	regval |= val;187	hi3670_apb_phy_writel(phy, regval, reg);188}189 190static inline void kirin_apb_natural_phy_writel(struct hi3670_pcie_phy *phy,191						u32 val, u32 reg)192{193	writel(val, phy->base + reg);194}195 196static inline u32 kirin_apb_natural_phy_readl(struct hi3670_pcie_phy *phy,197					      u32 reg)198{199	return readl(phy->base + reg);200}201 202static void hi3670_pcie_phy_oe_enable(struct hi3670_pcie_phy *phy, bool enable)203{204	u32 val;205 206	regmap_read(phy->sysctrl, SCTRL_PCIE_OE_OFFSET, &val);207	val |= PCIE_DEBOUNCE_PARAM;208	if (enable)209		val &= ~PCIE_OE_BYPASS;210	else211		val |= PCIE_OE_BYPASS;212	regmap_write(phy->sysctrl, SCTRL_PCIE_OE_OFFSET, val);213}214 215static void hi3670_pcie_get_eyeparam(struct hi3670_pcie_phy *phy)216{217	struct device *dev = phy->dev;218	struct device_node *np;219	int ret, i;220 221	np = dev->of_node;222 223	ret = of_property_read_u32_array(np, "hisilicon,eye-diagram-param",224					 phy->eye_param, NUM_EYEPARAM);225	if (!ret)226		return;227 228	/* There's no optional eye_param property. Set array to default */229	for (i = 0; i < NUM_EYEPARAM; i++)230		phy->eye_param[i] = EYEPARAM_NOCFG;231}232 233static void hi3670_pcie_set_eyeparam(struct hi3670_pcie_phy *phy)234{235	u32 val;236 237	val = kirin_apb_natural_phy_readl(phy, RAWLANEN_DIG_PCS_XF_TX_OVRD_IN_1);238 239	if (phy->eye_param[1] != EYEPARAM_NOCFG) {240		val &= ~EYE_PARM1_MASK;241		val |= FIELD_PREP(EYE_PARM1_MASK, phy->eye_param[1]);242		val |= EYE_PARM1_EN;243	}244	kirin_apb_natural_phy_writel(phy, val,245				     RAWLANEN_DIG_PCS_XF_TX_OVRD_IN_1);246 247	val = kirin_apb_natural_phy_readl(phy, LANEN_DIG_ASIC_TX_OVRD_IN_2);248	val &= ~(EYE_PARM2_MASK | EYE_PARM3_MASK);249	if (phy->eye_param[2] != EYEPARAM_NOCFG) {250		val |= FIELD_PREP(EYE_PARM2_MASK, phy->eye_param[2]);251		val |= EYE_PARM2_EN;252	}253 254	if (phy->eye_param[3] != EYEPARAM_NOCFG) {255		val |= FIELD_PREP(EYE_PARM3_MASK, phy->eye_param[3]);256		val |= EYE_PARM3_EN;257	}258 259	kirin_apb_natural_phy_writel(phy, val, LANEN_DIG_ASIC_TX_OVRD_IN_2);260 261	val = kirin_apb_natural_phy_readl(phy, SUP_DIG_LVL_OVRD_IN);262	if (phy->eye_param[0] != EYEPARAM_NOCFG) {263		val &= ~EYE_PARM0_MASK;264		val |= FIELD_PREP(EYE_PARM0_MASK, phy->eye_param[0]);265		val |= EYE_PARM0_EN;266	}267	kirin_apb_natural_phy_writel(phy, val, SUP_DIG_LVL_OVRD_IN);268 269	val = kirin_apb_natural_phy_readl(phy, LANEN_DIG_ASIC_TX_OVRD_IN_1);270	if (phy->eye_param[4] != EYEPARAM_NOCFG) {271		val &= ~EYE_PARM4_MASK;272		val |= FIELD_PREP(EYE_PARM4_MASK, phy->eye_param[4]);273		val |= EYE_PARM4_EN;274	}275	kirin_apb_natural_phy_writel(phy, val, LANEN_DIG_ASIC_TX_OVRD_IN_1);276}277 278static void hi3670_pcie_natural_cfg(struct hi3670_pcie_phy *phy)279{280	u32 val;281 282	/* change 2p mem_ctrl */283	regmap_write(phy->apb, SOC_PCIECTRL_CTRL20_ADDR,284		     SOC_PCIECTRL_CTRL20_2P_MEM_CTRL);285 286	regmap_read(phy->apb, SOC_PCIECTRL_CTRL7_ADDR, &val);287	val |= PCIE_PULL_UP_SYS_AUX_PWR_DET;288	regmap_write(phy->apb, SOC_PCIECTRL_CTRL7_ADDR, val);289 290	/* output, pull down */291	regmap_read(phy->apb, SOC_PCIECTRL_CTRL12_ADDR, &val);292	val &= ~PCIE_OUTPUT_PULL_BITS;293	val |= PCIE_OUTPUT_PULL_DOWN;294	regmap_write(phy->apb, SOC_PCIECTRL_CTRL12_ADDR, val);295 296	/* Handle phy_reset and lane0_reset to HW */297	hi3670_apb_phy_updatel(phy, PCIEPHY_RESET_BIT,298			       PCIEPHY_PIPE_LINE0_RESET_BIT | PCIEPHY_RESET_BIT,299			       SOC_PCIEPHY_CTRL1_ADDR);300 301	/* fix chip bug: TxDetectRx fail */302	hi3670_apb_phy_updatel(phy, PCIE_TXDETECT_RX_FAIL, PCIE_TXDETECT_RX_FAIL,303			       SOC_PCIEPHY_CTRL38_ADDR);304}305 306static void hi3670_pcie_pll_init(struct hi3670_pcie_phy *phy)307{308	hi3670_apb_phy_updatel(phy, PCIE_PHY_CHOOSE_FNPLL, PCIE_PHY_CHOOSE_FNPLL,309			       SOC_PCIEPHY_MMC1PLL_CTRL1);310 311	hi3670_apb_phy_updatel(phy,312			       FIELD_PREP(PCIE_FNPLL_FBDIV_MASK, PCIE_FNPLL_FBDIV),313			       PCIE_FNPLL_FBDIV_MASK,314			       SOC_PCIEPHY_MMC1PLL_CTRL16);315 316	hi3670_apb_phy_updatel(phy,317			       FIELD_PREP(PCIE_FNPLL_FRACDIV_MASK, PCIE_FNPLL_FRACDIV),318			       PCIE_FNPLL_FRACDIV_MASK, SOC_PCIEPHY_MMC1PLL_CTRL17);319 320	hi3670_apb_phy_updatel(phy,321			       PCIE_FNPLL_DLL_EN |322			       FIELD_PREP(PCIE_FNPLL_POSTDIV1_MASK, PCIE_FNPLL_POSTDIV1) |323			       FIELD_PREP(PCIE_FNPLL_POSTDIV2_MASK, PCIE_FNPLL_POSTDIV2) |324			       FIELD_PREP(PCIE_FNPLL_PLL_MODE_MASK, PCIE_FNPLL_PLL_MODE),325			       PCIE_FNPLL_POSTDIV1_MASK |326			       PCIE_FNPLL_POSTDIV2_MASK |327			       PCIE_FNPLL_PLL_MODE_MASK | PCIE_FNPLL_DLL_EN,328			       SOC_PCIEPHY_MMC1PLL_CTRL20);329 330	hi3670_apb_phy_writel(phy, PCIE_PHY_MMC1PLL,331			      SOC_PCIEPHY_MMC1PLL_CTRL21);332}333 334static int hi3670_pcie_pll_ctrl(struct hi3670_pcie_phy *phy, bool enable)335{336	struct device *dev = phy->dev;337	u32 val;338	int time = PLL_CTRL_WAIT_TIME;339 340	if (enable) {341		/* pd = 0 */342		hi3670_apb_phy_updatel(phy, 0, PCIE_PHY_MMC1PLL_DISABLE,343				       SOC_PCIEPHY_MMC1PLL_CTRL16);344 345		/* choose FNPLL */346		val = hi3670_apb_phy_readl(phy, SOC_PCIEPHY_MMC1PLL_STAT0);347		while (!(val & FNPLL_HAS_LOCKED)) {348			if (!time) {349				dev_err(dev, "wait for pll_lock timeout\n");350				return -EINVAL;351			}352			time--;353			udelay(1);354			val = hi3670_apb_phy_readl(phy, SOC_PCIEPHY_MMC1PLL_STAT0);355		}356 357		hi3670_apb_phy_updatel(phy, 0, PCIE_PHY_PCIEPL_BP,358				       SOC_PCIEPHY_MMC1PLL_CTRL20);359 360	} else {361		hi3670_apb_phy_updatel(phy,362				       PCIE_PHY_MMC1PLL_DISABLE,363				       PCIE_PHY_MMC1PLL_DISABLE,364				       SOC_PCIEPHY_MMC1PLL_CTRL16);365 366		hi3670_apb_phy_updatel(phy, PCIE_PHY_PCIEPL_BP,367				       PCIE_PHY_PCIEPL_BP,368				       SOC_PCIEPHY_MMC1PLL_CTRL20);369	}370 371	return 0;372}373 374static void hi3670_pcie_hp_debounce_gt(struct hi3670_pcie_phy *phy, bool open)375{376	if (open)377		/* gt_clk_pcie_hp/gt_clk_pcie_debounce open */378		regmap_write(phy->crgctrl, CRGPERIPH_PEREN12,379			     IO_HP_DEBOUNCE_GT);380	else381		/* gt_clk_pcie_hp/gt_clk_pcie_debounce close */382		regmap_write(phy->crgctrl, CRGPERIPH_PERDIS12,383			     IO_HP_DEBOUNCE_GT);384}385 386static void hi3670_pcie_phyref_gt(struct hi3670_pcie_phy *phy, bool open)387{388	unsigned int val;389 390	regmap_read(phy->crgctrl, CRGPERIPH_PCIECTRL0, &val);391 392	if (open)393		val &= ~IO_OE_HARD_GT_MODE; /* enable hard gt mode */394	else395		val |= IO_OE_HARD_GT_MODE; /* disable hard gt mode */396 397	regmap_write(phy->crgctrl, CRGPERIPH_PCIECTRL0, val);398 399	/* disable soft gt mode */400	regmap_write(phy->crgctrl, CRGPERIPH_PERDIS12, IO_PHYREF_SOFT_GT_MODE);401}402 403static void hi3670_pcie_oe_ctrl(struct hi3670_pcie_phy *phy, bool en_flag)404{405	unsigned int val;406 407	regmap_read(phy->crgctrl, CRGPERIPH_PCIECTRL0, &val);408 409	/* set ie cfg */410	val |= IO_IE_EN_HARD_BYPASS;411 412	/* set oe cfg */413	val &= ~IO_HARD_CTRL_DEBOUNCE_BYPASS;414 415	/* set phy_debounce in&out time */416	val |= (DEBOUNCE_WAITCFG_IN | DEBOUNCE_WAITCFG_OUT);417 418	/* select oe_gt_mode */419	val |= IO_OE_GT_MODE;420 421	if (en_flag)422		val &= ~IO_OE_EN_HARD_BYPASS;423	else424		val |= IO_OE_EN_HARD_BYPASS;425 426	regmap_write(phy->crgctrl, CRGPERIPH_PCIECTRL0, val);427}428 429static void hi3670_pcie_ioref_gt(struct hi3670_pcie_phy *phy, bool open)430{431	unsigned int val;432 433	if (open) {434		regmap_write(phy->apb, SOC_PCIECTRL_CTRL21_ADDR,435			     SOC_PCIECTRL_CTRL21_DEFAULT);436 437		hi3670_pcie_oe_ctrl(phy, true);438 439		/* en hard gt mode */440		regmap_read(phy->crgctrl, CRGPERIPH_PCIECTRL0, &val);441		val &= ~IO_REF_HARD_GT_MODE;442		regmap_write(phy->crgctrl, CRGPERIPH_PCIECTRL0, val);443 444		/* disable soft gt mode */445		regmap_write(phy->crgctrl, CRGPERIPH_PERDIS12,446			     IO_REF_SOFT_GT_MODE);447 448	} else {449		/* disable hard gt mode */450		regmap_read(phy->crgctrl, CRGPERIPH_PCIECTRL0, &val);451		val |= IO_REF_HARD_GT_MODE;452		regmap_write(phy->crgctrl, CRGPERIPH_PCIECTRL0, val);453 454		/* disable soft gt mode */455		regmap_write(phy->crgctrl, CRGPERIPH_PERDIS12,456			     IO_REF_SOFT_GT_MODE);457 458		hi3670_pcie_oe_ctrl(phy, false);459	}460}461 462static int hi3670_pcie_allclk_ctrl(struct hi3670_pcie_phy *phy, bool clk_on)463{464	struct device *dev = phy->dev;465	int ret = 0;466 467	if (!clk_on)468		goto close_clocks;469 470	/* choose 100MHz clk src: Bit[8]==1 pad, Bit[8]==0 pll */471	hi3670_apb_phy_updatel(phy, 0, PCIE_CLK_SOURCE,472			       SOC_PCIEPHY_CTRL1_ADDR);473 474	hi3670_pcie_pll_init(phy);475 476	ret = hi3670_pcie_pll_ctrl(phy, true);477	if (ret) {478		dev_err(dev, "Failed to enable pll\n");479		return -EINVAL;480	}481	hi3670_pcie_hp_debounce_gt(phy, true);482	hi3670_pcie_phyref_gt(phy, true);483	hi3670_pcie_ioref_gt(phy, true);484 485	ret = clk_set_rate(phy->aclk, AXI_CLK_FREQ);486	if (ret) {487		dev_err(dev, "Failed to set rate\n");488		goto close_clocks;489	}490 491	return 0;492 493close_clocks:494	hi3670_pcie_ioref_gt(phy, false);495	hi3670_pcie_phyref_gt(phy, false);496	hi3670_pcie_hp_debounce_gt(phy, false);497 498	hi3670_pcie_pll_ctrl(phy, false);499 500	return ret;501}502 503static bool is_pipe_clk_stable(struct hi3670_pcie_phy *phy)504{505	struct device *dev = phy->dev;506	u32 val;507	u32 time = PIPE_CLK_STABLE_TIME;508	u32 pipe_clk_stable = PCIE_IS_CLOCK_STABLE;509 510	val = hi3670_apb_phy_readl(phy, SOC_PCIEPHY_STATE0_ADDR);511	while (val & pipe_clk_stable) {512		mdelay(1);513		if (!time) {514			dev_err(dev, "PIPE clk is not stable\n");515			return false;516		}517		time--;518		val = hi3670_apb_phy_readl(phy, SOC_PCIEPHY_STATE0_ADDR);519	}520 521	return true;522}523 524static int hi3670_pcie_noc_power(struct hi3670_pcie_phy *phy, bool enable)525{526	struct device *dev = phy->dev;527	u32 time = NOC_POWER_TIME;528	unsigned int val = NOC_PW_MASK;529	int rst;530 531	if (enable)532		val = NOC_PW_MASK | NOC_PW_SET_BIT;533	else534		val = NOC_PW_MASK;535	rst = enable ? 1 : 0;536 537	regmap_write(phy->pmctrl, NOC_POWER_IDLEREQ_1, val);538 539	time = NOC_POWER_TIME;540	regmap_read(phy->pmctrl, NOC_POWER_IDLE_1, &val);541	while ((val & NOC_PW_SET_BIT) != rst) {542		udelay(10);543		if (!time) {544			dev_err(dev, "Failed to reverse noc power-status\n");545			return -EINVAL;546		}547		time--;548		regmap_read(phy->pmctrl, NOC_POWER_IDLE_1, &val);549	}550 551	return 0;552}553 554static int hi3670_pcie_get_resources_from_pcie(struct hi3670_pcie_phy *phy)555{556	struct device_node *pcie_port;557	struct device *dev = phy->dev;558	struct device *pcie_dev;559 560	pcie_port = of_get_child_by_name(dev->parent->of_node, "pcie");561	if (!pcie_port) {562		dev_err(dev, "no pcie node found in %s\n",563			dev->parent->of_node->full_name);564		return -ENODEV;565	}566 567	pcie_dev = bus_find_device_by_of_node(&platform_bus_type, pcie_port);568	if (!pcie_dev) {569		dev_err(dev, "Didn't find pcie device\n");570		return -ENODEV;571	}572 573	/*574	 * We might just use NULL instead of the APB name, as the575	 * pcie-kirin currently registers directly just one regmap (although576	 * the DWC driver register other regmaps).577	 *578	 * Yet, it sounds safer to warrant that it will be accessing the579	 * right regmap. So, let's use the named version.580	 */581	phy->apb = dev_get_regmap(pcie_dev, "kirin_pcie_apb");582	if (!phy->apb) {583		dev_err(dev, "Failed to get APB regmap\n");584		return -ENODEV;585	}586 587	return 0;588}589 590static int kirin_pcie_clk_ctrl(struct hi3670_pcie_phy *phy, bool enable)591{592	int ret = 0;593 594	if (!enable)595		goto close_clk;596 597	ret = clk_set_rate(phy->phy_ref_clk, REF_CLK_FREQ);598	if (ret)599		return ret;600 601	ret = clk_prepare_enable(phy->phy_ref_clk);602	if (ret)603		return ret;604 605	ret = clk_prepare_enable(phy->apb_sys_clk);606	if (ret)607		goto apb_sys_fail;608 609	ret = clk_prepare_enable(phy->apb_phy_clk);610	if (ret)611		goto apb_phy_fail;612 613	ret = clk_prepare_enable(phy->aclk);614	if (ret)615		goto aclk_fail;616 617	ret = clk_prepare_enable(phy->aux_clk);618	if (ret)619		goto aux_clk_fail;620 621	return 0;622 623close_clk:624	clk_disable_unprepare(phy->aux_clk);625aux_clk_fail:626	clk_disable_unprepare(phy->aclk);627aclk_fail:628	clk_disable_unprepare(phy->apb_phy_clk);629apb_phy_fail:630	clk_disable_unprepare(phy->apb_sys_clk);631apb_sys_fail:632	clk_disable_unprepare(phy->phy_ref_clk);633 634	return ret;635}636 637static int hi3670_pcie_phy_init(struct phy *generic_phy)638{639	struct hi3670_pcie_phy *phy = phy_get_drvdata(generic_phy);640	int ret;641 642	/*643	 * The code under hi3670_pcie_get_resources_from_pcie() need to644	 * access the reset-gpios and the APB registers, both from the645	 * pcie-kirin driver.646	 *647	 * The APB is obtained via the pcie driver's regmap648	 * Such kind of resource can only be obtained during the PCIe649	 * power_on sequence, as the code inside pcie-kirin needs to650	 * be already probed, as it needs to register the APB regmap.651	 */652 653	ret = hi3670_pcie_get_resources_from_pcie(phy);654	if (ret)655		return ret;656 657	return 0;658}659 660static int hi3670_pcie_phy_power_on(struct phy *generic_phy)661{662	struct hi3670_pcie_phy *phy = phy_get_drvdata(generic_phy);663	int val, ret;664 665	/* Power supply for Host */666	regmap_write(phy->sysctrl, SCTRL_PCIE_CMOS_OFFSET, SCTRL_PCIE_CMOS_BIT);667	usleep_range(TIME_CMOS_MIN, TIME_CMOS_MAX);668 669	hi3670_pcie_phy_oe_enable(phy, true);670 671	ret = kirin_pcie_clk_ctrl(phy, true);672	if (ret)673		return ret;674 675	/* ISO disable, PCIeCtrl, PHY assert and clk gate clear */676	regmap_write(phy->sysctrl, SCTRL_PCIE_ISO_OFFSET, SCTRL_PCIE_ISO_BIT);677	regmap_write(phy->crgctrl, CRGCTRL_PCIE_ASSERT_OFFSET,678		     CRGCTRL_PCIE_ASSERT_BIT);679	regmap_write(phy->sysctrl, SCTRL_PCIE_HPCLK_OFFSET,680		     SCTRL_PCIE_HPCLK_BIT);681 682	hi3670_pcie_natural_cfg(phy);683 684	ret = hi3670_pcie_allclk_ctrl(phy, true);685	if (ret)686		goto disable_clks;687 688	/* pull down phy_test_powerdown signal */689	hi3670_apb_phy_updatel(phy, 0, PCIE_PULL_DOWN_PHY_TEST_POWERDOWN,690			       SOC_PCIEPHY_CTRL0_ADDR);691 692	/* deassert controller perst_n */693	regmap_read(phy->apb, SOC_PCIECTRL_CTRL12_ADDR, &val);694	val |= PCIE_DEASSERT_CONTROLLER_PERST;695	regmap_write(phy->apb, SOC_PCIECTRL_CTRL12_ADDR, val);696	udelay(10);697 698	ret = is_pipe_clk_stable(phy);699	if (!ret)700		goto disable_clks;701 702	hi3670_pcie_set_eyeparam(phy);703 704	ret = hi3670_pcie_noc_power(phy, false);705	if (ret)706		goto disable_clks;707 708	return 0;709 710disable_clks:711	kirin_pcie_clk_ctrl(phy, false);712	return ret;713}714 715static int hi3670_pcie_phy_power_off(struct phy *generic_phy)716{717	struct hi3670_pcie_phy *phy = phy_get_drvdata(generic_phy);718 719	hi3670_pcie_phy_oe_enable(phy, false);720 721	hi3670_pcie_allclk_ctrl(phy, false);722 723	/* Drop power supply for Host */724	regmap_write(phy->sysctrl, SCTRL_PCIE_CMOS_OFFSET, 0);725 726	/*727	 * FIXME: The enabled clocks should be disabled here by calling728	 * kirin_pcie_clk_ctrl(phy, false);729	 * However, some clocks used at Kirin 970 should be marked as730	 * CLK_IS_CRITICAL at clk-hi3670 driver, as powering such clocks off731	 * cause an Asynchronous SError interrupt, which produces panic().732	 * While clk-hi3670 is not fixed, we cannot risk disabling clocks here.733	 */734 735	return 0;736}737 738static const struct phy_ops hi3670_phy_ops = {739	.init		= hi3670_pcie_phy_init,740	.power_on	= hi3670_pcie_phy_power_on,741	.power_off	= hi3670_pcie_phy_power_off,742	.owner		= THIS_MODULE,743};744 745static int hi3670_pcie_phy_get_resources(struct hi3670_pcie_phy *phy,746					 struct platform_device *pdev)747{748	struct device *dev = &pdev->dev;749 750	/* syscon */751	phy->crgctrl = syscon_regmap_lookup_by_compatible("hisilicon,hi3670-crgctrl");752	if (IS_ERR(phy->crgctrl))753		return PTR_ERR(phy->crgctrl);754 755	phy->sysctrl = syscon_regmap_lookup_by_compatible("hisilicon,hi3670-sctrl");756	if (IS_ERR(phy->sysctrl))757		return PTR_ERR(phy->sysctrl);758 759	phy->pmctrl = syscon_regmap_lookup_by_compatible("hisilicon,hi3670-pmctrl");760	if (IS_ERR(phy->pmctrl))761		return PTR_ERR(phy->pmctrl);762 763	/* clocks */764	phy->phy_ref_clk = devm_clk_get(dev, "phy_ref");765	if (IS_ERR(phy->phy_ref_clk))766		return PTR_ERR(phy->phy_ref_clk);767 768	phy->aux_clk = devm_clk_get(dev, "aux");769	if (IS_ERR(phy->aux_clk))770		return PTR_ERR(phy->aux_clk);771 772	phy->apb_phy_clk = devm_clk_get(dev, "apb_phy");773	if (IS_ERR(phy->apb_phy_clk))774		return PTR_ERR(phy->apb_phy_clk);775 776	phy->apb_sys_clk = devm_clk_get(dev, "apb_sys");777	if (IS_ERR(phy->apb_sys_clk))778		return PTR_ERR(phy->apb_sys_clk);779 780	phy->aclk = devm_clk_get(dev, "aclk");781	if (IS_ERR(phy->aclk))782		return PTR_ERR(phy->aclk);783 784	/* registers */785	phy->base = devm_platform_ioremap_resource(pdev, 0);786	if (IS_ERR(phy->base))787		return PTR_ERR(phy->base);788 789	hi3670_pcie_get_eyeparam(phy);790 791	return 0;792}793 794static int hi3670_pcie_phy_probe(struct platform_device *pdev)795{796	struct phy_provider *phy_provider;797	struct device *dev = &pdev->dev;798	struct hi3670_pcie_phy *phy;799	struct phy *generic_phy;800	int ret;801 802	phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL);803	if (!phy)804		return -ENOMEM;805 806	phy->dev = dev;807 808	ret = hi3670_pcie_phy_get_resources(phy, pdev);809	if (ret)810		return ret;811 812	generic_phy = devm_phy_create(dev, dev->of_node, &hi3670_phy_ops);813	if (IS_ERR(generic_phy)) {814		dev_err(dev, "failed to create PHY\n");815		return PTR_ERR(generic_phy);816	}817 818	phy_set_drvdata(generic_phy, phy);819	phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);820 821	return PTR_ERR_OR_ZERO(phy_provider);822}823 824static const struct of_device_id hi3670_pcie_phy_match[] = {825	{826		.compatible = "hisilicon,hi970-pcie-phy",827	},828	{},829};830 831static struct platform_driver hi3670_pcie_phy_driver = {832	.probe	= hi3670_pcie_phy_probe,833	.driver = {834		.of_match_table	= hi3670_pcie_phy_match,835		.name		= "hi3670_pcie_phy",836		.suppress_bind_attrs = true,837	}838};839builtin_platform_driver(hi3670_pcie_phy_driver);840 841MODULE_DEVICE_TABLE(of, hi3670_pcie_phy_match);842MODULE_DESCRIPTION("PCIe phy driver for Kirin 970");843MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@kernel.org>");844MODULE_AUTHOR("Manivannan Sadhasivam <mani@kernel.org>");845MODULE_LICENSE("GPL v2");846