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