1925c5749SYifeng Zhao // SPDX-License-Identifier: GPL-2.0 2925c5749SYifeng Zhao /* 3925c5749SYifeng Zhao * Rockchip USB3.0/PCIe Gen2/SATA/SGMII combphy driver 4925c5749SYifeng Zhao * 5925c5749SYifeng Zhao * Copyright (C) 2021 Rockchip Electronics Co., Ltd. 6925c5749SYifeng Zhao */ 7925c5749SYifeng Zhao 8925c5749SYifeng Zhao #include <common.h> 9925c5749SYifeng Zhao #include <clk.h> 10925c5749SYifeng Zhao #include <dm.h> 11925c5749SYifeng Zhao #include <dm/lists.h> 12925c5749SYifeng Zhao #include <dt-bindings/phy/phy.h> 13925c5749SYifeng Zhao #include <generic-phy.h> 14925c5749SYifeng Zhao #include <syscon.h> 15925c5749SYifeng Zhao #include <asm/io.h> 16925c5749SYifeng Zhao #include <asm/arch/clock.h> 17925c5749SYifeng Zhao #include <regmap.h> 18925c5749SYifeng Zhao #include <reset-uclass.h> 19925c5749SYifeng Zhao 20925c5749SYifeng Zhao #define BIT_WRITEABLE_SHIFT 16 21925c5749SYifeng Zhao 22925c5749SYifeng Zhao struct rockchip_combphy_priv; 23925c5749SYifeng Zhao 24925c5749SYifeng Zhao struct combphy_reg { 25925c5749SYifeng Zhao u16 offset; 26925c5749SYifeng Zhao u16 bitend; 27925c5749SYifeng Zhao u16 bitstart; 28925c5749SYifeng Zhao u16 disable; 29925c5749SYifeng Zhao u16 enable; 30925c5749SYifeng Zhao }; 31925c5749SYifeng Zhao 32925c5749SYifeng Zhao struct rockchip_combphy_grfcfg { 33925c5749SYifeng Zhao struct combphy_reg pcie_mode_set; 34925c5749SYifeng Zhao struct combphy_reg usb_mode_set; 35925c5749SYifeng Zhao struct combphy_reg sgmii_mode_set; 36925c5749SYifeng Zhao struct combphy_reg qsgmii_mode_set; 37925c5749SYifeng Zhao struct combphy_reg pipe_rxterm_set; 38925c5749SYifeng Zhao struct combphy_reg pipe_txelec_set; 39925c5749SYifeng Zhao struct combphy_reg pipe_txcomp_set; 40925c5749SYifeng Zhao struct combphy_reg pipe_clk_25m; 41925c5749SYifeng Zhao struct combphy_reg pipe_clk_100m; 42925c5749SYifeng Zhao struct combphy_reg pipe_phymode_sel; 43925c5749SYifeng Zhao struct combphy_reg pipe_rate_sel; 44925c5749SYifeng Zhao struct combphy_reg pipe_rxterm_sel; 45925c5749SYifeng Zhao struct combphy_reg pipe_txelec_sel; 46925c5749SYifeng Zhao struct combphy_reg pipe_txcomp_sel; 47925c5749SYifeng Zhao struct combphy_reg pipe_clk_ext; 48925c5749SYifeng Zhao struct combphy_reg pipe_sel_usb; 49925c5749SYifeng Zhao struct combphy_reg pipe_sel_qsgmii; 50925c5749SYifeng Zhao struct combphy_reg pipe_phy_status; 51925c5749SYifeng Zhao struct combphy_reg con0_for_pcie; 52925c5749SYifeng Zhao struct combphy_reg con1_for_pcie; 53925c5749SYifeng Zhao struct combphy_reg con2_for_pcie; 54925c5749SYifeng Zhao struct combphy_reg con3_for_pcie; 55925c5749SYifeng Zhao struct combphy_reg con0_for_sata; 56925c5749SYifeng Zhao struct combphy_reg con1_for_sata; 57925c5749SYifeng Zhao struct combphy_reg con2_for_sata; 58925c5749SYifeng Zhao struct combphy_reg con3_for_sata; 59925c5749SYifeng Zhao struct combphy_reg pipe_con0_for_sata; 60cf3c44cbSJon Lin struct combphy_reg pipe_con1_for_sata; 61925c5749SYifeng Zhao struct combphy_reg pipe_sgmii_mac_sel; 62925c5749SYifeng Zhao struct combphy_reg pipe_xpcs_phy_ready; 63925c5749SYifeng Zhao struct combphy_reg u3otg0_port_en; 64925c5749SYifeng Zhao struct combphy_reg u3otg1_port_en; 65925c5749SYifeng Zhao }; 66925c5749SYifeng Zhao 67925c5749SYifeng Zhao struct rockchip_combphy_cfg { 68925c5749SYifeng Zhao const struct rockchip_combphy_grfcfg *grfcfg; 69925c5749SYifeng Zhao int (*combphy_cfg)(struct rockchip_combphy_priv *priv); 70925c5749SYifeng Zhao }; 71925c5749SYifeng Zhao 72925c5749SYifeng Zhao struct rockchip_combphy_priv { 73925c5749SYifeng Zhao u32 mode; 74925c5749SYifeng Zhao void __iomem *mmio; 75925c5749SYifeng Zhao struct udevice *dev; 76925c5749SYifeng Zhao struct regmap *pipe_grf; 77925c5749SYifeng Zhao struct regmap *phy_grf; 78925c5749SYifeng Zhao struct phy *phy; 79925c5749SYifeng Zhao struct reset_ctl phy_rst; 80925c5749SYifeng Zhao struct clk ref_clk; 81925c5749SYifeng Zhao const struct rockchip_combphy_cfg *cfg; 82925c5749SYifeng Zhao }; 83925c5749SYifeng Zhao 84925c5749SYifeng Zhao static int param_write(struct regmap *base, 85925c5749SYifeng Zhao const struct combphy_reg *reg, bool en) 86925c5749SYifeng Zhao { 87925c5749SYifeng Zhao u32 val, mask, tmp; 88925c5749SYifeng Zhao 89925c5749SYifeng Zhao tmp = en ? reg->enable : reg->disable; 90925c5749SYifeng Zhao mask = GENMASK(reg->bitend, reg->bitstart); 91925c5749SYifeng Zhao val = (tmp << reg->bitstart) | (mask << BIT_WRITEABLE_SHIFT); 92925c5749SYifeng Zhao 93925c5749SYifeng Zhao return regmap_write(base, reg->offset, val); 94925c5749SYifeng Zhao } 95925c5749SYifeng Zhao 96925c5749SYifeng Zhao static int rockchip_combphy_pcie_init(struct rockchip_combphy_priv *priv) 97925c5749SYifeng Zhao { 98925c5749SYifeng Zhao int ret = 0; 99925c5749SYifeng Zhao 100925c5749SYifeng Zhao if (priv->cfg->combphy_cfg) { 101925c5749SYifeng Zhao ret = priv->cfg->combphy_cfg(priv); 102925c5749SYifeng Zhao if (ret) { 103925c5749SYifeng Zhao dev_err(priv->dev, "failed to init phy for pcie\n"); 104925c5749SYifeng Zhao return ret; 105925c5749SYifeng Zhao } 106925c5749SYifeng Zhao } 107925c5749SYifeng Zhao 108925c5749SYifeng Zhao return ret; 109925c5749SYifeng Zhao } 110925c5749SYifeng Zhao 111925c5749SYifeng Zhao static int rockchip_combphy_usb3_init(struct rockchip_combphy_priv *priv) 112925c5749SYifeng Zhao { 113925c5749SYifeng Zhao int ret = 0; 114925c5749SYifeng Zhao 115925c5749SYifeng Zhao if (priv->cfg->combphy_cfg) { 116925c5749SYifeng Zhao ret = priv->cfg->combphy_cfg(priv); 117925c5749SYifeng Zhao if (ret) { 118925c5749SYifeng Zhao dev_err(priv->dev, "failed to init phy for usb3\n"); 119925c5749SYifeng Zhao return ret; 120925c5749SYifeng Zhao } 121925c5749SYifeng Zhao } 122925c5749SYifeng Zhao 123925c5749SYifeng Zhao return ret; 124925c5749SYifeng Zhao } 125925c5749SYifeng Zhao 126925c5749SYifeng Zhao static int rockchip_combphy_sata_init(struct rockchip_combphy_priv *priv) 127925c5749SYifeng Zhao { 128925c5749SYifeng Zhao int ret = 0; 129925c5749SYifeng Zhao 130925c5749SYifeng Zhao if (priv->cfg->combphy_cfg) { 131925c5749SYifeng Zhao ret = priv->cfg->combphy_cfg(priv); 132925c5749SYifeng Zhao if (ret) { 133925c5749SYifeng Zhao dev_err(priv->dev, "failed to init phy for sata\n"); 134925c5749SYifeng Zhao return ret; 135925c5749SYifeng Zhao } 136925c5749SYifeng Zhao } 137925c5749SYifeng Zhao 138925c5749SYifeng Zhao return ret; 139925c5749SYifeng Zhao } 140925c5749SYifeng Zhao 141925c5749SYifeng Zhao static int rockchip_combphy_sgmii_init(struct rockchip_combphy_priv *priv) 142925c5749SYifeng Zhao { 143925c5749SYifeng Zhao int ret = 0; 144925c5749SYifeng Zhao 145925c5749SYifeng Zhao if (priv->cfg->combphy_cfg) { 146925c5749SYifeng Zhao ret = priv->cfg->combphy_cfg(priv); 147925c5749SYifeng Zhao if (ret) { 148925c5749SYifeng Zhao dev_err(priv->dev, "failed to init phy for sgmii\n"); 149925c5749SYifeng Zhao return ret; 150925c5749SYifeng Zhao } 151925c5749SYifeng Zhao } 152925c5749SYifeng Zhao 153925c5749SYifeng Zhao return ret; 154925c5749SYifeng Zhao } 155925c5749SYifeng Zhao 156925c5749SYifeng Zhao static int rockchip_combphy_set_mode(struct rockchip_combphy_priv *priv) 157925c5749SYifeng Zhao { 158925c5749SYifeng Zhao switch (priv->mode) { 159925c5749SYifeng Zhao case PHY_TYPE_PCIE: 160925c5749SYifeng Zhao rockchip_combphy_pcie_init(priv); 161925c5749SYifeng Zhao break; 162925c5749SYifeng Zhao case PHY_TYPE_USB3: 163925c5749SYifeng Zhao rockchip_combphy_usb3_init(priv); 164925c5749SYifeng Zhao break; 165925c5749SYifeng Zhao case PHY_TYPE_SATA: 166925c5749SYifeng Zhao rockchip_combphy_sata_init(priv); 167925c5749SYifeng Zhao break; 168925c5749SYifeng Zhao case PHY_TYPE_SGMII: 169925c5749SYifeng Zhao case PHY_TYPE_QSGMII: 170925c5749SYifeng Zhao return rockchip_combphy_sgmii_init(priv); 171925c5749SYifeng Zhao default: 172925c5749SYifeng Zhao dev_err(priv->dev, "incompatible PHY type\n"); 173925c5749SYifeng Zhao return -EINVAL; 174925c5749SYifeng Zhao } 175925c5749SYifeng Zhao 176925c5749SYifeng Zhao return 0; 177925c5749SYifeng Zhao } 178925c5749SYifeng Zhao 179925c5749SYifeng Zhao static int rockchip_combphy_init(struct phy *phy) 180925c5749SYifeng Zhao { 181925c5749SYifeng Zhao struct rockchip_combphy_priv *priv = dev_get_priv(phy->dev); 182925c5749SYifeng Zhao int ret; 183925c5749SYifeng Zhao 184925c5749SYifeng Zhao ret = clk_enable(&priv->ref_clk); 185925c5749SYifeng Zhao if (ret < 0 && ret != -ENOSYS) 186925c5749SYifeng Zhao return ret; 187925c5749SYifeng Zhao 188925c5749SYifeng Zhao ret = rockchip_combphy_set_mode(priv); 189925c5749SYifeng Zhao if (ret) 190925c5749SYifeng Zhao goto err_clk; 191925c5749SYifeng Zhao 192925c5749SYifeng Zhao reset_deassert(&priv->phy_rst); 193925c5749SYifeng Zhao 194925c5749SYifeng Zhao return 0; 195925c5749SYifeng Zhao 196925c5749SYifeng Zhao err_clk: 197925c5749SYifeng Zhao clk_disable(&priv->ref_clk); 198925c5749SYifeng Zhao 199925c5749SYifeng Zhao return ret; 200925c5749SYifeng Zhao } 201925c5749SYifeng Zhao 202925c5749SYifeng Zhao static int rockchip_combphy_exit(struct phy *phy) 203925c5749SYifeng Zhao { 204925c5749SYifeng Zhao struct rockchip_combphy_priv *priv = dev_get_priv(phy->dev); 205925c5749SYifeng Zhao 206925c5749SYifeng Zhao clk_disable(&priv->ref_clk); 207925c5749SYifeng Zhao reset_assert(&priv->phy_rst); 208925c5749SYifeng Zhao 209925c5749SYifeng Zhao return 0; 210925c5749SYifeng Zhao } 211925c5749SYifeng Zhao 212925c5749SYifeng Zhao static int rockchip_combphy_xlate(struct phy *phy, struct ofnode_phandle_args *args) 213925c5749SYifeng Zhao { 214925c5749SYifeng Zhao struct rockchip_combphy_priv *priv = dev_get_priv(phy->dev); 215925c5749SYifeng Zhao 216925c5749SYifeng Zhao if (args->args_count != 1) { 217925c5749SYifeng Zhao pr_err("invalid number of arguments\n"); 218925c5749SYifeng Zhao return -EINVAL; 219925c5749SYifeng Zhao } 220925c5749SYifeng Zhao 221925c5749SYifeng Zhao priv->mode = args->args[0]; 222925c5749SYifeng Zhao 223925c5749SYifeng Zhao return 0; 224925c5749SYifeng Zhao } 225925c5749SYifeng Zhao 226925c5749SYifeng Zhao static const struct phy_ops rochchip_combphy_ops = { 227925c5749SYifeng Zhao .init = rockchip_combphy_init, 228925c5749SYifeng Zhao .exit = rockchip_combphy_exit, 229925c5749SYifeng Zhao .of_xlate = rockchip_combphy_xlate, 230925c5749SYifeng Zhao }; 231925c5749SYifeng Zhao 232925c5749SYifeng Zhao static int rockchip_combphy_parse_dt(struct udevice *dev, 233925c5749SYifeng Zhao struct rockchip_combphy_priv *priv) 234925c5749SYifeng Zhao { 235925c5749SYifeng Zhao struct udevice *syscon; 236925c5749SYifeng Zhao int ret; 2377cc44222SJon Lin u32 vals[4]; 238925c5749SYifeng Zhao 239925c5749SYifeng Zhao ret = uclass_get_device_by_phandle(UCLASS_SYSCON, dev, "rockchip,pipe-grf", &syscon); 240925c5749SYifeng Zhao if (ret) { 241cf3c44cbSJon Lin dev_err(dev, "failed to find peri_ctrl pipe-grf regmap ret= %d\n", ret); 242925c5749SYifeng Zhao return ret; 243925c5749SYifeng Zhao } 244925c5749SYifeng Zhao priv->pipe_grf = syscon_get_regmap(syscon); 245925c5749SYifeng Zhao 246925c5749SYifeng Zhao ret = uclass_get_device_by_phandle(UCLASS_SYSCON, dev, "rockchip,pipe-phy-grf", &syscon); 247925c5749SYifeng Zhao if (ret) { 248925c5749SYifeng Zhao dev_err(dev, "failed to find peri_ctrl pipe-phy-grf regmap\n"); 249925c5749SYifeng Zhao return ret; 250925c5749SYifeng Zhao } 251925c5749SYifeng Zhao priv->phy_grf = syscon_get_regmap(syscon); 252925c5749SYifeng Zhao 253925c5749SYifeng Zhao ret = clk_get_by_index(dev, 0, &priv->ref_clk); 254925c5749SYifeng Zhao if (ret) { 255925c5749SYifeng Zhao dev_err(dev, "failed to find ref clock\n"); 256925c5749SYifeng Zhao return PTR_ERR(&priv->ref_clk); 257925c5749SYifeng Zhao } 258925c5749SYifeng Zhao 259dbf89912SRen Jianing ret = reset_get_by_name(dev, "combphy", &priv->phy_rst); 260925c5749SYifeng Zhao if (ret) { 261925c5749SYifeng Zhao dev_err(dev, "no phy reset control specified\n"); 262925c5749SYifeng Zhao return ret; 263925c5749SYifeng Zhao } 264925c5749SYifeng Zhao 2657cc44222SJon Lin if (!dev_read_u32_array(dev, "rockchip,pcie1ln-sel-bits", 2667cc44222SJon Lin vals, ARRAY_SIZE(vals))) 2677cc44222SJon Lin regmap_write(priv->pipe_grf, vals[0], 2687cc44222SJon Lin (GENMASK(vals[2], vals[1]) << 16) | vals[3]); 2697cc44222SJon Lin 270925c5749SYifeng Zhao return 0; 271925c5749SYifeng Zhao } 272925c5749SYifeng Zhao 273925c5749SYifeng Zhao static int rockchip_combphy_probe(struct udevice *udev) 274925c5749SYifeng Zhao { 275925c5749SYifeng Zhao struct rockchip_combphy_priv *priv = dev_get_priv(udev); 276925c5749SYifeng Zhao const struct rockchip_combphy_cfg *phy_cfg; 277925c5749SYifeng Zhao 278925c5749SYifeng Zhao priv->mmio = (void __iomem *)dev_read_addr(udev); 279925c5749SYifeng Zhao if (IS_ERR(priv->mmio)) 280925c5749SYifeng Zhao return PTR_ERR(priv->mmio); 281925c5749SYifeng Zhao 282925c5749SYifeng Zhao phy_cfg = (const struct rockchip_combphy_cfg *)dev_get_driver_data(udev); 283925c5749SYifeng Zhao if (!phy_cfg) { 284925c5749SYifeng Zhao dev_err(udev, "No OF match data provided\n"); 285925c5749SYifeng Zhao return -EINVAL; 286925c5749SYifeng Zhao } 287925c5749SYifeng Zhao 288925c5749SYifeng Zhao priv->dev = udev; 289925c5749SYifeng Zhao priv->mode = PHY_TYPE_SATA; 290925c5749SYifeng Zhao priv->cfg = phy_cfg; 291925c5749SYifeng Zhao 292*5eec6d12SJon Lin return rockchip_combphy_parse_dt(udev, priv); 293925c5749SYifeng Zhao } 294925c5749SYifeng Zhao 295925c5749SYifeng Zhao static int rk3568_combphy_cfg(struct rockchip_combphy_priv *priv) 296925c5749SYifeng Zhao { 297925c5749SYifeng Zhao const struct rockchip_combphy_grfcfg *cfg = priv->cfg->grfcfg; 298925c5749SYifeng Zhao u32 val; 299925c5749SYifeng Zhao 300925c5749SYifeng Zhao switch (priv->mode) { 301925c5749SYifeng Zhao case PHY_TYPE_PCIE: 302925c5749SYifeng Zhao /* Set SSC downward spread spectrum */ 303925c5749SYifeng Zhao val = readl(priv->mmio + (0x1f << 2)); 304925c5749SYifeng Zhao val &= ~GENMASK(5, 4); 305925c5749SYifeng Zhao val |= 0x01 << 4; 306925c5749SYifeng Zhao writel(val, priv->mmio + 0x7c); 307925c5749SYifeng Zhao 308925c5749SYifeng Zhao param_write(priv->phy_grf, &cfg->con0_for_pcie, true); 309925c5749SYifeng Zhao param_write(priv->phy_grf, &cfg->con1_for_pcie, true); 310925c5749SYifeng Zhao param_write(priv->phy_grf, &cfg->con2_for_pcie, true); 311925c5749SYifeng Zhao param_write(priv->phy_grf, &cfg->con3_for_pcie, true); 312925c5749SYifeng Zhao break; 313925c5749SYifeng Zhao case PHY_TYPE_USB3: 314925c5749SYifeng Zhao /* Set SSC downward spread spectrum */ 315925c5749SYifeng Zhao val = readl(priv->mmio + (0x1f << 2)); 316925c5749SYifeng Zhao val &= ~GENMASK(5, 4); 317925c5749SYifeng Zhao val |= 0x01 << 4; 318925c5749SYifeng Zhao writel(val, priv->mmio + 0x7c); 319925c5749SYifeng Zhao 320925c5749SYifeng Zhao /* Enable adaptive CTLE for USB3.0 Rx */ 321925c5749SYifeng Zhao val = readl(priv->mmio + (0x0e << 2)); 322925c5749SYifeng Zhao val &= ~GENMASK(0, 0); 323925c5749SYifeng Zhao val |= 0x01; 324925c5749SYifeng Zhao writel(val, priv->mmio + (0x0e << 2)); 325925c5749SYifeng Zhao 326a0d03578SWilliam Wu /* Set PLL KVCO fine tuning signals */ 327a0d03578SWilliam Wu val = readl(priv->mmio + (0x20 << 2)); 328a0d03578SWilliam Wu val &= ~(0x7 << 2); 329a0d03578SWilliam Wu val |= 0x2 << 2; 330a0d03578SWilliam Wu writel(val, priv->mmio + (0x20 << 2)); 331a0d03578SWilliam Wu 332a0d03578SWilliam Wu /* Set PLL LPF R1 to su_trim[10:7]=1001 */ 333a0d03578SWilliam Wu writel(0x4, priv->mmio + (0xb << 2)); 334a0d03578SWilliam Wu 335a0d03578SWilliam Wu /* Set PLL input clock divider 1/2 */ 336a0d03578SWilliam Wu val = readl(priv->mmio + (0x5 << 2)); 337a0d03578SWilliam Wu val &= ~(0x3 << 6); 338a0d03578SWilliam Wu val |= 0x1 << 6; 339a0d03578SWilliam Wu writel(val, priv->mmio + (0x5 << 2)); 340a0d03578SWilliam Wu 341a0d03578SWilliam Wu /* Set PLL loop divider */ 342a0d03578SWilliam Wu writel(0x32, priv->mmio + (0x11 << 2)); 343a0d03578SWilliam Wu 344a0d03578SWilliam Wu /* Set PLL KVCO to min and set PLL charge pump current to max */ 345a0d03578SWilliam Wu writel(0xf0, priv->mmio + (0xa << 2)); 346a0d03578SWilliam Wu 347925c5749SYifeng Zhao param_write(priv->phy_grf, &cfg->pipe_sel_usb, true); 348925c5749SYifeng Zhao param_write(priv->phy_grf, &cfg->pipe_txcomp_sel, false); 349925c5749SYifeng Zhao param_write(priv->phy_grf, &cfg->pipe_txelec_sel, false); 350925c5749SYifeng Zhao param_write(priv->phy_grf, &cfg->usb_mode_set, true); 351925c5749SYifeng Zhao break; 352925c5749SYifeng Zhao case PHY_TYPE_SATA: 353925c5749SYifeng Zhao writel(0x41, priv->mmio + 0x38); 354925c5749SYifeng Zhao writel(0x8F, priv->mmio + 0x18); 355925c5749SYifeng Zhao param_write(priv->phy_grf, &cfg->con0_for_sata, true); 356925c5749SYifeng Zhao param_write(priv->phy_grf, &cfg->con1_for_sata, true); 357925c5749SYifeng Zhao param_write(priv->phy_grf, &cfg->con2_for_sata, true); 358925c5749SYifeng Zhao param_write(priv->phy_grf, &cfg->con3_for_sata, true); 359925c5749SYifeng Zhao param_write(priv->pipe_grf, &cfg->pipe_con0_for_sata, true); 360925c5749SYifeng Zhao break; 361925c5749SYifeng Zhao case PHY_TYPE_SGMII: 362925c5749SYifeng Zhao param_write(priv->pipe_grf, &cfg->pipe_xpcs_phy_ready, true); 363925c5749SYifeng Zhao param_write(priv->phy_grf, &cfg->pipe_phymode_sel, true); 364925c5749SYifeng Zhao param_write(priv->phy_grf, &cfg->pipe_sel_qsgmii, true); 365925c5749SYifeng Zhao param_write(priv->phy_grf, &cfg->sgmii_mode_set, true); 366925c5749SYifeng Zhao break; 367925c5749SYifeng Zhao case PHY_TYPE_QSGMII: 368925c5749SYifeng Zhao param_write(priv->pipe_grf, &cfg->pipe_xpcs_phy_ready, true); 369925c5749SYifeng Zhao param_write(priv->phy_grf, &cfg->pipe_phymode_sel, true); 370925c5749SYifeng Zhao param_write(priv->phy_grf, &cfg->pipe_rate_sel, true); 371925c5749SYifeng Zhao param_write(priv->phy_grf, &cfg->pipe_sel_qsgmii, true); 372925c5749SYifeng Zhao param_write(priv->phy_grf, &cfg->qsgmii_mode_set, true); 373925c5749SYifeng Zhao break; 374925c5749SYifeng Zhao default: 375925c5749SYifeng Zhao pr_err("%s, phy-type %d\n", __func__, priv->mode); 376925c5749SYifeng Zhao return -EINVAL; 377925c5749SYifeng Zhao } 378925c5749SYifeng Zhao 379dbf89912SRen Jianing /* The default ref clock is 25Mhz */ 380dbf89912SRen Jianing param_write(priv->phy_grf, &cfg->pipe_clk_25m, true); 381925c5749SYifeng Zhao 382925c5749SYifeng Zhao if (dev_read_bool(priv->dev, "rockchip,enable-ssc")) { 383925c5749SYifeng Zhao val = readl(priv->mmio + (0x7 << 2)); 384925c5749SYifeng Zhao val |= BIT(4); 385925c5749SYifeng Zhao writel(val, priv->mmio + (0x7 << 2)); 386925c5749SYifeng Zhao } 387925c5749SYifeng Zhao 388925c5749SYifeng Zhao return 0; 389925c5749SYifeng Zhao } 390925c5749SYifeng Zhao 391925c5749SYifeng Zhao static const struct rockchip_combphy_grfcfg rk3568_combphy_grfcfgs = { 392925c5749SYifeng Zhao /* pipe-phy-grf */ 393925c5749SYifeng Zhao .pcie_mode_set = { 0x0000, 5, 0, 0x00, 0x11 }, 394925c5749SYifeng Zhao .usb_mode_set = { 0x0000, 5, 0, 0x00, 0x04 }, 395925c5749SYifeng Zhao .sgmii_mode_set = { 0x0000, 5, 0, 0x00, 0x01 }, 396925c5749SYifeng Zhao .qsgmii_mode_set = { 0x0000, 5, 0, 0x00, 0x21 }, 397925c5749SYifeng Zhao .pipe_rxterm_set = { 0x0000, 12, 12, 0x00, 0x01 }, 398925c5749SYifeng Zhao .pipe_txelec_set = { 0x0004, 1, 1, 0x00, 0x01 }, 399925c5749SYifeng Zhao .pipe_txcomp_set = { 0x0004, 4, 4, 0x00, 0x01 }, 400925c5749SYifeng Zhao .pipe_clk_25m = { 0x0004, 14, 13, 0x00, 0x01 }, 401925c5749SYifeng Zhao .pipe_clk_100m = { 0x0004, 14, 13, 0x00, 0x02 }, 402925c5749SYifeng Zhao .pipe_phymode_sel = { 0x0008, 1, 1, 0x00, 0x01 }, 403925c5749SYifeng Zhao .pipe_rate_sel = { 0x0008, 2, 2, 0x00, 0x01 }, 404925c5749SYifeng Zhao .pipe_rxterm_sel = { 0x0008, 8, 8, 0x00, 0x01 }, 405925c5749SYifeng Zhao .pipe_txelec_sel = { 0x0008, 12, 12, 0x00, 0x01 }, 406925c5749SYifeng Zhao .pipe_txcomp_sel = { 0x0008, 15, 15, 0x00, 0x01 }, 407925c5749SYifeng Zhao .pipe_clk_ext = { 0x000c, 9, 8, 0x02, 0x01 }, 408925c5749SYifeng Zhao .pipe_sel_usb = { 0x000c, 14, 13, 0x00, 0x01 }, 409925c5749SYifeng Zhao .pipe_sel_qsgmii = { 0x000c, 15, 13, 0x00, 0x07 }, 410925c5749SYifeng Zhao .pipe_phy_status = { 0x0034, 6, 6, 0x01, 0x00 }, 411925c5749SYifeng Zhao .con0_for_pcie = { 0x0000, 15, 0, 0x00, 0x1000 }, 412925c5749SYifeng Zhao .con1_for_pcie = { 0x0004, 15, 0, 0x00, 0x0000 }, 413925c5749SYifeng Zhao .con2_for_pcie = { 0x0008, 15, 0, 0x00, 0x0101 }, 414925c5749SYifeng Zhao .con3_for_pcie = { 0x000c, 15, 0, 0x00, 0x0200 }, 415925c5749SYifeng Zhao .con0_for_sata = { 0x0000, 15, 0, 0x00, 0x0119 }, 416925c5749SYifeng Zhao .con1_for_sata = { 0x0004, 15, 0, 0x00, 0x0040 }, 417925c5749SYifeng Zhao .con2_for_sata = { 0x0008, 15, 0, 0x00, 0x80c3 }, 418925c5749SYifeng Zhao .con3_for_sata = { 0x000c, 15, 0, 0x00, 0x4407 }, 419925c5749SYifeng Zhao /* pipe-grf */ 420925c5749SYifeng Zhao .pipe_con0_for_sata = { 0x0000, 15, 0, 0x00, 0x2220 }, 421925c5749SYifeng Zhao .pipe_sgmii_mac_sel = { 0x0040, 1, 1, 0x00, 0x01 }, 422925c5749SYifeng Zhao .pipe_xpcs_phy_ready = { 0x0040, 2, 2, 0x00, 0x01 }, 423925c5749SYifeng Zhao .u3otg0_port_en = { 0x0104, 15, 0, 0x0181, 0x1100 }, 424925c5749SYifeng Zhao .u3otg1_port_en = { 0x0144, 15, 0, 0x0181, 0x1100 }, 425925c5749SYifeng Zhao }; 426925c5749SYifeng Zhao 427925c5749SYifeng Zhao static const struct rockchip_combphy_cfg rk3568_combphy_cfgs = { 428925c5749SYifeng Zhao .grfcfg = &rk3568_combphy_grfcfgs, 429925c5749SYifeng Zhao .combphy_cfg = rk3568_combphy_cfg, 430925c5749SYifeng Zhao }; 431925c5749SYifeng Zhao 432cf3c44cbSJon Lin static int rk3588_combphy_cfg(struct rockchip_combphy_priv *priv) 433cf3c44cbSJon Lin { 434cf3c44cbSJon Lin const struct rockchip_combphy_grfcfg *cfg = priv->cfg->grfcfg; 435d8968f57SWilliam Wu u32 val; 436cf3c44cbSJon Lin 437cf3c44cbSJon Lin switch (priv->mode) { 438cf3c44cbSJon Lin case PHY_TYPE_PCIE: 439cf3c44cbSJon Lin param_write(priv->phy_grf, &cfg->con0_for_pcie, true); 440cf3c44cbSJon Lin param_write(priv->phy_grf, &cfg->con1_for_pcie, true); 441cf3c44cbSJon Lin param_write(priv->phy_grf, &cfg->con2_for_pcie, true); 442cf3c44cbSJon Lin param_write(priv->phy_grf, &cfg->con3_for_pcie, true); 443cf3c44cbSJon Lin break; 444cf3c44cbSJon Lin case PHY_TYPE_USB3: 445d8968f57SWilliam Wu /* Set SSC downward spread spectrum */ 446d8968f57SWilliam Wu val = readl(priv->mmio + (0x1f << 2)); 447d8968f57SWilliam Wu val &= ~GENMASK(5, 4); 448d8968f57SWilliam Wu val |= 0x01 << 4; 449d8968f57SWilliam Wu writel(val, priv->mmio + 0x7c); 450d8968f57SWilliam Wu 451d8968f57SWilliam Wu /* Enable adaptive CTLE for USB3.0 Rx */ 452d8968f57SWilliam Wu val = readl(priv->mmio + (0x0e << 2)); 453d8968f57SWilliam Wu val &= ~GENMASK(0, 0); 454d8968f57SWilliam Wu val |= 0x01; 455d8968f57SWilliam Wu writel(val, priv->mmio + (0x0e << 2)); 456d8968f57SWilliam Wu 457d8968f57SWilliam Wu /* Set PLL KVCO fine tuning signals */ 458d8968f57SWilliam Wu val = readl(priv->mmio + (0x20 << 2)); 459d8968f57SWilliam Wu val &= ~(0x7 << 2); 460d8968f57SWilliam Wu val |= 0x2 << 2; 461d8968f57SWilliam Wu writel(val, priv->mmio + (0x20 << 2)); 462d8968f57SWilliam Wu 463d8968f57SWilliam Wu /* Set PLL LPF R1 to su_trim[10:7]=1001 */ 464d8968f57SWilliam Wu writel(0x4, priv->mmio + (0xb << 2)); 465d8968f57SWilliam Wu 466d8968f57SWilliam Wu /* Set PLL input clock divider 1/2 */ 467d8968f57SWilliam Wu val = readl(priv->mmio + (0x5 << 2)); 468d8968f57SWilliam Wu val &= ~(0x3 << 6); 469d8968f57SWilliam Wu val |= 0x1 << 6; 470d8968f57SWilliam Wu writel(val, priv->mmio + (0x5 << 2)); 471d8968f57SWilliam Wu 472d8968f57SWilliam Wu /* Set PLL loop divider */ 473d8968f57SWilliam Wu writel(0x32, priv->mmio + (0x11 << 2)); 474d8968f57SWilliam Wu 475d8968f57SWilliam Wu /* Set PLL KVCO to min and set PLL charge pump current to max */ 476d8968f57SWilliam Wu writel(0xf0, priv->mmio + (0xa << 2)); 477d8968f57SWilliam Wu 478cf3c44cbSJon Lin param_write(priv->phy_grf, &cfg->pipe_txcomp_sel, false); 479cf3c44cbSJon Lin param_write(priv->phy_grf, &cfg->pipe_txelec_sel, false); 480cf3c44cbSJon Lin param_write(priv->phy_grf, &cfg->usb_mode_set, true); 481cf3c44cbSJon Lin break; 482cf3c44cbSJon Lin case PHY_TYPE_SATA: 483cf3c44cbSJon Lin param_write(priv->phy_grf, &cfg->con0_for_sata, true); 484cf3c44cbSJon Lin param_write(priv->phy_grf, &cfg->con1_for_sata, true); 485cf3c44cbSJon Lin param_write(priv->phy_grf, &cfg->con2_for_sata, true); 486cf3c44cbSJon Lin param_write(priv->phy_grf, &cfg->con3_for_sata, true); 487cf3c44cbSJon Lin param_write(priv->pipe_grf, &cfg->pipe_con0_for_sata, true); 488cf3c44cbSJon Lin param_write(priv->pipe_grf, &cfg->pipe_con1_for_sata, true); 489cf3c44cbSJon Lin break; 490cf3c44cbSJon Lin case PHY_TYPE_SGMII: 491cf3c44cbSJon Lin case PHY_TYPE_QSGMII: 492cf3c44cbSJon Lin default: 493cf3c44cbSJon Lin dev_err(priv->dev, "incompatible PHY type\n"); 494cf3c44cbSJon Lin return -EINVAL; 495cf3c44cbSJon Lin } 496cf3c44cbSJon Lin 497c72d402cSJon Lin /* 100MHz refclock signal is good */ 498c72d402cSJon Lin clk_set_rate(&priv->ref_clk, 100000000); 499cf3c44cbSJon Lin param_write(priv->phy_grf, &cfg->pipe_clk_100m, true); 500e278c201SKever Yang if (priv->mode == PHY_TYPE_PCIE) { 501e278c201SKever Yang /* PLL KVCO tuning fine */ 502e278c201SKever Yang val = readl(priv->mmio + (0x20 << 2)); 503e278c201SKever Yang val &= ~GENMASK(4, 2); 504e278c201SKever Yang val |= 0x4 << 2; 505e278c201SKever Yang writel(val, priv->mmio + (0x20 << 2)); 506e278c201SKever Yang 507e278c201SKever Yang /* Set up rx_trim: PLL LPF C1 85pf R1 1.25kohm */ 508e278c201SKever Yang val = 0x4c; 509e278c201SKever Yang writel(val, priv->mmio + (0x1b << 2)); 510e278c201SKever Yang 511e278c201SKever Yang /* Set up su_trim: T3 */ 512e278c201SKever Yang val = 0xb0; 513e278c201SKever Yang writel(val, priv->mmio + (0xa << 2)); 514e278c201SKever Yang val = 0x47; 515e278c201SKever Yang writel(val, priv->mmio + (0xb << 2)); 516e278c201SKever Yang val = 0x57; 517e278c201SKever Yang writel(val, priv->mmio + (0xd << 2)); 518e278c201SKever Yang } 519cf3c44cbSJon Lin 520cf3c44cbSJon Lin return 0; 521cf3c44cbSJon Lin } 522cf3c44cbSJon Lin 523cf3c44cbSJon Lin static const struct rockchip_combphy_grfcfg rk3588_combphy_grfcfgs = { 524cf3c44cbSJon Lin /* pipe-phy-grf */ 525cf3c44cbSJon Lin .pcie_mode_set = { 0x0000, 5, 0, 0x00, 0x11 }, 526cf3c44cbSJon Lin .usb_mode_set = { 0x0000, 5, 0, 0x00, 0x04 }, 527cf3c44cbSJon Lin .pipe_rxterm_set = { 0x0000, 12, 12, 0x00, 0x01 }, 528cf3c44cbSJon Lin .pipe_txelec_set = { 0x0004, 1, 1, 0x00, 0x01 }, 529cf3c44cbSJon Lin .pipe_txcomp_set = { 0x0004, 4, 4, 0x00, 0x01 }, 530cf3c44cbSJon Lin .pipe_clk_25m = { 0x0004, 14, 13, 0x00, 0x01 }, 531cf3c44cbSJon Lin .pipe_clk_100m = { 0x0004, 14, 13, 0x00, 0x02 }, 532cf3c44cbSJon Lin .pipe_rxterm_sel = { 0x0008, 8, 8, 0x00, 0x01 }, 533cf3c44cbSJon Lin .pipe_txelec_sel = { 0x0008, 12, 12, 0x00, 0x01 }, 534cf3c44cbSJon Lin .pipe_txcomp_sel = { 0x0008, 15, 15, 0x00, 0x01 }, 535cf3c44cbSJon Lin .pipe_clk_ext = { 0x000c, 9, 8, 0x02, 0x01 }, 536cf3c44cbSJon Lin .pipe_phy_status = { 0x0034, 6, 6, 0x01, 0x00 }, 537cf3c44cbSJon Lin .con0_for_pcie = { 0x0000, 15, 0, 0x00, 0x1000 }, 538cf3c44cbSJon Lin .con1_for_pcie = { 0x0004, 15, 0, 0x00, 0x0000 }, 539cf3c44cbSJon Lin .con2_for_pcie = { 0x0008, 15, 0, 0x00, 0x0101 }, 540cf3c44cbSJon Lin .con3_for_pcie = { 0x000c, 15, 0, 0x00, 0x0200 }, 541cf3c44cbSJon Lin .con0_for_sata = { 0x0000, 15, 0, 0x00, 0x0129 }, 542cf3c44cbSJon Lin .con1_for_sata = { 0x0004, 15, 0, 0x00, 0x0040 }, 543cf3c44cbSJon Lin .con2_for_sata = { 0x0008, 15, 0, 0x00, 0x80c1 }, 544cf3c44cbSJon Lin .con3_for_sata = { 0x000c, 15, 0, 0x00, 0x0407 }, 545cf3c44cbSJon Lin /* pipe-grf */ 546cf3c44cbSJon Lin .pipe_con0_for_sata = { 0x0000, 11, 5, 0x00, 0x22 }, 547cf3c44cbSJon Lin .pipe_con1_for_sata = { 0x0000, 2, 0, 0x00, 0x2 }, 548cf3c44cbSJon Lin }; 549cf3c44cbSJon Lin 550cf3c44cbSJon Lin static const struct rockchip_combphy_cfg rk3588_combphy_cfgs = { 551cf3c44cbSJon Lin .grfcfg = &rk3588_combphy_grfcfgs, 552cf3c44cbSJon Lin .combphy_cfg = rk3588_combphy_cfg, 553cf3c44cbSJon Lin }; 554cf3c44cbSJon Lin 555925c5749SYifeng Zhao static const struct udevice_id rockchip_combphy_ids[] = { 556925c5749SYifeng Zhao { 557925c5749SYifeng Zhao .compatible = "rockchip,rk3568-naneng-combphy", 558925c5749SYifeng Zhao .data = (ulong)&rk3568_combphy_cfgs 559925c5749SYifeng Zhao }, 560cf3c44cbSJon Lin { 561cf3c44cbSJon Lin .compatible = "rockchip,rk3588-naneng-combphy", 562cf3c44cbSJon Lin .data = (ulong)&rk3588_combphy_cfgs 563cf3c44cbSJon Lin }, 564925c5749SYifeng Zhao { } 565925c5749SYifeng Zhao }; 566925c5749SYifeng Zhao 567925c5749SYifeng Zhao U_BOOT_DRIVER(rockchip_naneng_combphy) = { 568925c5749SYifeng Zhao .name = "naneng-combphy", 569925c5749SYifeng Zhao .id = UCLASS_PHY, 570925c5749SYifeng Zhao .of_match = rockchip_combphy_ids, 571925c5749SYifeng Zhao .ops = &rochchip_combphy_ops, 572925c5749SYifeng Zhao .probe = rockchip_combphy_probe, 573925c5749SYifeng Zhao .priv_auto_alloc_size = sizeof(struct rockchip_combphy_priv), 574925c5749SYifeng Zhao }; 575