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> 1914d5da7dSwilliam.wu #include <linux/iopoll.h> 20925c5749SYifeng Zhao 21925c5749SYifeng Zhao #define BIT_WRITEABLE_SHIFT 16 22925c5749SYifeng Zhao 23925c5749SYifeng Zhao struct rockchip_combphy_priv; 24925c5749SYifeng Zhao 25925c5749SYifeng Zhao struct combphy_reg { 263452d642SJianwei Zheng u32 offset; 27925c5749SYifeng Zhao u16 bitend; 28925c5749SYifeng Zhao u16 bitstart; 29925c5749SYifeng Zhao u16 disable; 30925c5749SYifeng Zhao u16 enable; 31925c5749SYifeng Zhao }; 32925c5749SYifeng Zhao 33925c5749SYifeng Zhao struct rockchip_combphy_grfcfg { 34925c5749SYifeng Zhao struct combphy_reg pcie_mode_set; 35925c5749SYifeng Zhao struct combphy_reg usb_mode_set; 36925c5749SYifeng Zhao struct combphy_reg sgmii_mode_set; 37925c5749SYifeng Zhao struct combphy_reg qsgmii_mode_set; 38925c5749SYifeng Zhao struct combphy_reg pipe_rxterm_set; 39925c5749SYifeng Zhao struct combphy_reg pipe_txelec_set; 40925c5749SYifeng Zhao struct combphy_reg pipe_txcomp_set; 413452d642SJianwei Zheng struct combphy_reg pipe_clk_24m; 42925c5749SYifeng Zhao struct combphy_reg pipe_clk_25m; 43925c5749SYifeng Zhao struct combphy_reg pipe_clk_100m; 44925c5749SYifeng Zhao struct combphy_reg pipe_phymode_sel; 45925c5749SYifeng Zhao struct combphy_reg pipe_rate_sel; 46925c5749SYifeng Zhao struct combphy_reg pipe_rxterm_sel; 47925c5749SYifeng Zhao struct combphy_reg pipe_txelec_sel; 48925c5749SYifeng Zhao struct combphy_reg pipe_txcomp_sel; 49925c5749SYifeng Zhao struct combphy_reg pipe_clk_ext; 50925c5749SYifeng Zhao struct combphy_reg pipe_sel_usb; 51925c5749SYifeng Zhao struct combphy_reg pipe_sel_qsgmii; 52925c5749SYifeng Zhao struct combphy_reg pipe_phy_status; 53925c5749SYifeng Zhao struct combphy_reg con0_for_pcie; 54925c5749SYifeng Zhao struct combphy_reg con1_for_pcie; 55925c5749SYifeng Zhao struct combphy_reg con2_for_pcie; 56925c5749SYifeng Zhao struct combphy_reg con3_for_pcie; 57925c5749SYifeng Zhao struct combphy_reg con0_for_sata; 58925c5749SYifeng Zhao struct combphy_reg con1_for_sata; 59925c5749SYifeng Zhao struct combphy_reg con2_for_sata; 60925c5749SYifeng Zhao struct combphy_reg con3_for_sata; 61925c5749SYifeng Zhao struct combphy_reg pipe_con0_for_sata; 62cf3c44cbSJon Lin struct combphy_reg pipe_con1_for_sata; 63925c5749SYifeng Zhao struct combphy_reg pipe_sgmii_mac_sel; 64925c5749SYifeng Zhao struct combphy_reg pipe_xpcs_phy_ready; 65925c5749SYifeng Zhao struct combphy_reg u3otg0_port_en; 66925c5749SYifeng Zhao struct combphy_reg u3otg1_port_en; 6714d5da7dSwilliam.wu struct combphy_reg u3otg0_pipe_clk_sel; 6886b316b4SFrank Wang struct combphy_reg pipe_phy_grf_reset; 69925c5749SYifeng Zhao }; 70925c5749SYifeng Zhao 71925c5749SYifeng Zhao struct rockchip_combphy_cfg { 72925c5749SYifeng Zhao const struct rockchip_combphy_grfcfg *grfcfg; 73925c5749SYifeng Zhao int (*combphy_cfg)(struct rockchip_combphy_priv *priv); 74925c5749SYifeng Zhao }; 75925c5749SYifeng Zhao 76925c5749SYifeng Zhao struct rockchip_combphy_priv { 77925c5749SYifeng Zhao u32 mode; 78925c5749SYifeng Zhao void __iomem *mmio; 79925c5749SYifeng Zhao struct udevice *dev; 80925c5749SYifeng Zhao struct regmap *pipe_grf; 81925c5749SYifeng Zhao struct regmap *phy_grf; 82925c5749SYifeng Zhao struct phy *phy; 83925c5749SYifeng Zhao struct reset_ctl phy_rst; 84925c5749SYifeng Zhao struct clk ref_clk; 85925c5749SYifeng Zhao const struct rockchip_combphy_cfg *cfg; 86925c5749SYifeng Zhao }; 87925c5749SYifeng Zhao 88925c5749SYifeng Zhao static int param_write(struct regmap *base, 89925c5749SYifeng Zhao const struct combphy_reg *reg, bool en) 90925c5749SYifeng Zhao { 91925c5749SYifeng Zhao u32 val, mask, tmp; 92925c5749SYifeng Zhao 93925c5749SYifeng Zhao tmp = en ? reg->enable : reg->disable; 94925c5749SYifeng Zhao mask = GENMASK(reg->bitend, reg->bitstart); 95925c5749SYifeng Zhao val = (tmp << reg->bitstart) | (mask << BIT_WRITEABLE_SHIFT); 96925c5749SYifeng Zhao 97925c5749SYifeng Zhao return regmap_write(base, reg->offset, val); 98925c5749SYifeng Zhao } 99925c5749SYifeng Zhao 10014d5da7dSwilliam.wu static u32 rockchip_combphy_is_ready(struct rockchip_combphy_priv *priv) 10114d5da7dSwilliam.wu { 10214d5da7dSwilliam.wu const struct rockchip_combphy_grfcfg *cfg = priv->cfg->grfcfg; 10314d5da7dSwilliam.wu u32 mask, val; 10414d5da7dSwilliam.wu 10514d5da7dSwilliam.wu mask = GENMASK(cfg->pipe_phy_status.bitend, 10614d5da7dSwilliam.wu cfg->pipe_phy_status.bitstart); 10714d5da7dSwilliam.wu 10814d5da7dSwilliam.wu regmap_read(priv->phy_grf, cfg->pipe_phy_status.offset, &val); 10914d5da7dSwilliam.wu val = (val & mask) >> cfg->pipe_phy_status.bitstart; 11014d5da7dSwilliam.wu 11114d5da7dSwilliam.wu return val; 11214d5da7dSwilliam.wu } 11314d5da7dSwilliam.wu 114925c5749SYifeng Zhao static int rockchip_combphy_pcie_init(struct rockchip_combphy_priv *priv) 115925c5749SYifeng Zhao { 116925c5749SYifeng Zhao int ret = 0; 117925c5749SYifeng Zhao 118925c5749SYifeng Zhao if (priv->cfg->combphy_cfg) { 119925c5749SYifeng Zhao ret = priv->cfg->combphy_cfg(priv); 120925c5749SYifeng Zhao if (ret) { 121925c5749SYifeng Zhao dev_err(priv->dev, "failed to init phy for pcie\n"); 122925c5749SYifeng Zhao return ret; 123925c5749SYifeng Zhao } 124925c5749SYifeng Zhao } 125925c5749SYifeng Zhao 126925c5749SYifeng Zhao return ret; 127925c5749SYifeng Zhao } 128925c5749SYifeng Zhao 129925c5749SYifeng Zhao static int rockchip_combphy_usb3_init(struct rockchip_combphy_priv *priv) 130925c5749SYifeng Zhao { 131925c5749SYifeng Zhao int ret = 0; 132925c5749SYifeng Zhao 133925c5749SYifeng Zhao if (priv->cfg->combphy_cfg) { 134925c5749SYifeng Zhao ret = priv->cfg->combphy_cfg(priv); 135925c5749SYifeng Zhao if (ret) { 136925c5749SYifeng Zhao dev_err(priv->dev, "failed to init phy for usb3\n"); 137925c5749SYifeng Zhao return ret; 138925c5749SYifeng Zhao } 139925c5749SYifeng Zhao } 140925c5749SYifeng Zhao 141925c5749SYifeng Zhao return ret; 142925c5749SYifeng Zhao } 143925c5749SYifeng Zhao 144925c5749SYifeng Zhao static int rockchip_combphy_sata_init(struct rockchip_combphy_priv *priv) 145925c5749SYifeng Zhao { 146925c5749SYifeng Zhao int ret = 0; 147925c5749SYifeng Zhao 148925c5749SYifeng Zhao if (priv->cfg->combphy_cfg) { 149925c5749SYifeng Zhao ret = priv->cfg->combphy_cfg(priv); 150925c5749SYifeng Zhao if (ret) { 151925c5749SYifeng Zhao dev_err(priv->dev, "failed to init phy for sata\n"); 152925c5749SYifeng Zhao return ret; 153925c5749SYifeng Zhao } 154925c5749SYifeng Zhao } 155925c5749SYifeng Zhao 156925c5749SYifeng Zhao return ret; 157925c5749SYifeng Zhao } 158925c5749SYifeng Zhao 159925c5749SYifeng Zhao static int rockchip_combphy_sgmii_init(struct rockchip_combphy_priv *priv) 160925c5749SYifeng Zhao { 161925c5749SYifeng Zhao int ret = 0; 162925c5749SYifeng Zhao 163925c5749SYifeng Zhao if (priv->cfg->combphy_cfg) { 164925c5749SYifeng Zhao ret = priv->cfg->combphy_cfg(priv); 165925c5749SYifeng Zhao if (ret) { 166925c5749SYifeng Zhao dev_err(priv->dev, "failed to init phy for sgmii\n"); 167925c5749SYifeng Zhao return ret; 168925c5749SYifeng Zhao } 169925c5749SYifeng Zhao } 170925c5749SYifeng Zhao 171925c5749SYifeng Zhao return ret; 172925c5749SYifeng Zhao } 173925c5749SYifeng Zhao 17414d5da7dSwilliam.wu int rockchip_combphy_usb3_uboot_init(void) 17514d5da7dSwilliam.wu { 17614d5da7dSwilliam.wu struct udevice *udev; 17714d5da7dSwilliam.wu struct rockchip_combphy_priv *priv; 17814d5da7dSwilliam.wu const struct rockchip_combphy_grfcfg *cfg; 17914d5da7dSwilliam.wu u32 val; 18014d5da7dSwilliam.wu int ret; 18114d5da7dSwilliam.wu 18214d5da7dSwilliam.wu ret = uclass_get_device_by_driver(UCLASS_PHY, 18314d5da7dSwilliam.wu DM_GET_DRIVER(rockchip_naneng_combphy), 18414d5da7dSwilliam.wu &udev); 18514d5da7dSwilliam.wu if (ret) { 18614d5da7dSwilliam.wu pr_err("%s: get usb3-phy node failed: %d\n", __func__, ret); 18714d5da7dSwilliam.wu return ret; 18814d5da7dSwilliam.wu } 18914d5da7dSwilliam.wu 19014d5da7dSwilliam.wu priv = dev_get_priv(udev); 19114d5da7dSwilliam.wu priv->mode = PHY_TYPE_USB3; 19214d5da7dSwilliam.wu cfg = priv->cfg->grfcfg; 19314d5da7dSwilliam.wu 19414d5da7dSwilliam.wu rockchip_combphy_usb3_init(priv); 19514d5da7dSwilliam.wu reset_deassert(&priv->phy_rst); 19614d5da7dSwilliam.wu 19714d5da7dSwilliam.wu if (cfg->pipe_phy_grf_reset.enable) 19814d5da7dSwilliam.wu param_write(priv->phy_grf, &cfg->pipe_phy_grf_reset, false); 19914d5da7dSwilliam.wu 20014d5da7dSwilliam.wu if (priv->mode == PHY_TYPE_USB3) { 20114d5da7dSwilliam.wu ret = readx_poll_timeout(rockchip_combphy_is_ready, 20214d5da7dSwilliam.wu priv, val, 20314d5da7dSwilliam.wu val == cfg->pipe_phy_status.enable, 20414d5da7dSwilliam.wu 1000); 20514d5da7dSwilliam.wu if (ret) { 20614d5da7dSwilliam.wu dev_err(priv->dev, "wait phy status ready timeout\n"); 20714d5da7dSwilliam.wu param_write(priv->phy_grf, &cfg->usb_mode_set, false); 20814d5da7dSwilliam.wu if (cfg->u3otg0_pipe_clk_sel.disable) 20914d5da7dSwilliam.wu param_write(priv->phy_grf, &cfg->u3otg0_pipe_clk_sel, false); 21014d5da7dSwilliam.wu return ret; 21114d5da7dSwilliam.wu } 21214d5da7dSwilliam.wu } 21314d5da7dSwilliam.wu 21414d5da7dSwilliam.wu /* Select clk_usb3otg0_pipe for source clk */ 21514d5da7dSwilliam.wu if (cfg->u3otg0_pipe_clk_sel.disable) 21614d5da7dSwilliam.wu param_write(priv->phy_grf, &cfg->u3otg0_pipe_clk_sel, true); 21714d5da7dSwilliam.wu 21814d5da7dSwilliam.wu return ret; 21914d5da7dSwilliam.wu } 22014d5da7dSwilliam.wu 221925c5749SYifeng Zhao static int rockchip_combphy_set_mode(struct rockchip_combphy_priv *priv) 222925c5749SYifeng Zhao { 223925c5749SYifeng Zhao switch (priv->mode) { 224925c5749SYifeng Zhao case PHY_TYPE_PCIE: 225925c5749SYifeng Zhao rockchip_combphy_pcie_init(priv); 226925c5749SYifeng Zhao break; 227925c5749SYifeng Zhao case PHY_TYPE_USB3: 228925c5749SYifeng Zhao rockchip_combphy_usb3_init(priv); 229925c5749SYifeng Zhao break; 230925c5749SYifeng Zhao case PHY_TYPE_SATA: 231925c5749SYifeng Zhao rockchip_combphy_sata_init(priv); 232925c5749SYifeng Zhao break; 233925c5749SYifeng Zhao case PHY_TYPE_SGMII: 234925c5749SYifeng Zhao case PHY_TYPE_QSGMII: 235925c5749SYifeng Zhao return rockchip_combphy_sgmii_init(priv); 236925c5749SYifeng Zhao default: 237925c5749SYifeng Zhao dev_err(priv->dev, "incompatible PHY type\n"); 238925c5749SYifeng Zhao return -EINVAL; 239925c5749SYifeng Zhao } 240925c5749SYifeng Zhao 241925c5749SYifeng Zhao return 0; 242925c5749SYifeng Zhao } 243925c5749SYifeng Zhao 244925c5749SYifeng Zhao static int rockchip_combphy_init(struct phy *phy) 245925c5749SYifeng Zhao { 246925c5749SYifeng Zhao struct rockchip_combphy_priv *priv = dev_get_priv(phy->dev); 24786b316b4SFrank Wang const struct rockchip_combphy_grfcfg *cfg = priv->cfg->grfcfg; 248925c5749SYifeng Zhao int ret; 249925c5749SYifeng Zhao 250925c5749SYifeng Zhao ret = clk_enable(&priv->ref_clk); 251925c5749SYifeng Zhao if (ret < 0 && ret != -ENOSYS) 252925c5749SYifeng Zhao return ret; 253925c5749SYifeng Zhao 254925c5749SYifeng Zhao ret = rockchip_combphy_set_mode(priv); 255925c5749SYifeng Zhao if (ret) 256925c5749SYifeng Zhao goto err_clk; 257925c5749SYifeng Zhao 258925c5749SYifeng Zhao reset_deassert(&priv->phy_rst); 259925c5749SYifeng Zhao 26086b316b4SFrank Wang if (cfg->pipe_phy_grf_reset.enable) 26186b316b4SFrank Wang param_write(priv->phy_grf, &cfg->pipe_phy_grf_reset, false); 26286b316b4SFrank Wang 263925c5749SYifeng Zhao return 0; 264925c5749SYifeng Zhao 265925c5749SYifeng Zhao err_clk: 266925c5749SYifeng Zhao clk_disable(&priv->ref_clk); 267925c5749SYifeng Zhao 268925c5749SYifeng Zhao return ret; 269925c5749SYifeng Zhao } 270925c5749SYifeng Zhao 271925c5749SYifeng Zhao static int rockchip_combphy_exit(struct phy *phy) 272925c5749SYifeng Zhao { 273925c5749SYifeng Zhao struct rockchip_combphy_priv *priv = dev_get_priv(phy->dev); 27486b316b4SFrank Wang const struct rockchip_combphy_grfcfg *cfg = priv->cfg->grfcfg; 275925c5749SYifeng Zhao 27686b316b4SFrank Wang if (cfg->pipe_phy_grf_reset.enable) 27786b316b4SFrank Wang param_write(priv->phy_grf, &cfg->pipe_phy_grf_reset, true); 27886b316b4SFrank Wang 279925c5749SYifeng Zhao reset_assert(&priv->phy_rst); 28086b316b4SFrank Wang clk_disable(&priv->ref_clk); 281925c5749SYifeng Zhao 282925c5749SYifeng Zhao return 0; 283925c5749SYifeng Zhao } 284925c5749SYifeng Zhao 285925c5749SYifeng Zhao static int rockchip_combphy_xlate(struct phy *phy, struct ofnode_phandle_args *args) 286925c5749SYifeng Zhao { 287925c5749SYifeng Zhao struct rockchip_combphy_priv *priv = dev_get_priv(phy->dev); 288925c5749SYifeng Zhao 289925c5749SYifeng Zhao if (args->args_count != 1) { 290925c5749SYifeng Zhao pr_err("invalid number of arguments\n"); 291925c5749SYifeng Zhao return -EINVAL; 292925c5749SYifeng Zhao } 293925c5749SYifeng Zhao 294925c5749SYifeng Zhao priv->mode = args->args[0]; 295925c5749SYifeng Zhao 296925c5749SYifeng Zhao return 0; 297925c5749SYifeng Zhao } 298925c5749SYifeng Zhao 299925c5749SYifeng Zhao static const struct phy_ops rochchip_combphy_ops = { 300925c5749SYifeng Zhao .init = rockchip_combphy_init, 301925c5749SYifeng Zhao .exit = rockchip_combphy_exit, 302925c5749SYifeng Zhao .of_xlate = rockchip_combphy_xlate, 303925c5749SYifeng Zhao }; 304925c5749SYifeng Zhao 305925c5749SYifeng Zhao static int rockchip_combphy_parse_dt(struct udevice *dev, 306925c5749SYifeng Zhao struct rockchip_combphy_priv *priv) 307925c5749SYifeng Zhao { 308925c5749SYifeng Zhao struct udevice *syscon; 309925c5749SYifeng Zhao int ret; 3107cc44222SJon Lin u32 vals[4]; 311925c5749SYifeng Zhao 312925c5749SYifeng Zhao ret = uclass_get_device_by_phandle(UCLASS_SYSCON, dev, "rockchip,pipe-grf", &syscon); 313925c5749SYifeng Zhao if (ret) { 314cf3c44cbSJon Lin dev_err(dev, "failed to find peri_ctrl pipe-grf regmap ret= %d\n", ret); 315925c5749SYifeng Zhao return ret; 316925c5749SYifeng Zhao } 317925c5749SYifeng Zhao priv->pipe_grf = syscon_get_regmap(syscon); 318925c5749SYifeng Zhao 319925c5749SYifeng Zhao ret = uclass_get_device_by_phandle(UCLASS_SYSCON, dev, "rockchip,pipe-phy-grf", &syscon); 320925c5749SYifeng Zhao if (ret) { 321925c5749SYifeng Zhao dev_err(dev, "failed to find peri_ctrl pipe-phy-grf regmap\n"); 322925c5749SYifeng Zhao return ret; 323925c5749SYifeng Zhao } 324925c5749SYifeng Zhao priv->phy_grf = syscon_get_regmap(syscon); 325925c5749SYifeng Zhao 326925c5749SYifeng Zhao ret = clk_get_by_index(dev, 0, &priv->ref_clk); 327925c5749SYifeng Zhao if (ret) { 328925c5749SYifeng Zhao dev_err(dev, "failed to find ref clock\n"); 329925c5749SYifeng Zhao return PTR_ERR(&priv->ref_clk); 330925c5749SYifeng Zhao } 331925c5749SYifeng Zhao 332dbf89912SRen Jianing ret = reset_get_by_name(dev, "combphy", &priv->phy_rst); 333925c5749SYifeng Zhao if (ret) { 334925c5749SYifeng Zhao dev_err(dev, "no phy reset control specified\n"); 335925c5749SYifeng Zhao return ret; 336925c5749SYifeng Zhao } 337925c5749SYifeng Zhao 3387cc44222SJon Lin if (!dev_read_u32_array(dev, "rockchip,pcie1ln-sel-bits", 3397cc44222SJon Lin vals, ARRAY_SIZE(vals))) 3407cc44222SJon Lin regmap_write(priv->pipe_grf, vals[0], 3417cc44222SJon Lin (GENMASK(vals[2], vals[1]) << 16) | vals[3]); 3427cc44222SJon Lin 343925c5749SYifeng Zhao return 0; 344925c5749SYifeng Zhao } 345925c5749SYifeng Zhao 346925c5749SYifeng Zhao static int rockchip_combphy_probe(struct udevice *udev) 347925c5749SYifeng Zhao { 348925c5749SYifeng Zhao struct rockchip_combphy_priv *priv = dev_get_priv(udev); 349925c5749SYifeng Zhao const struct rockchip_combphy_cfg *phy_cfg; 350925c5749SYifeng Zhao 351925c5749SYifeng Zhao priv->mmio = (void __iomem *)dev_read_addr(udev); 352925c5749SYifeng Zhao if (IS_ERR(priv->mmio)) 353925c5749SYifeng Zhao return PTR_ERR(priv->mmio); 354925c5749SYifeng Zhao 355925c5749SYifeng Zhao phy_cfg = (const struct rockchip_combphy_cfg *)dev_get_driver_data(udev); 356925c5749SYifeng Zhao if (!phy_cfg) { 357925c5749SYifeng Zhao dev_err(udev, "No OF match data provided\n"); 358925c5749SYifeng Zhao return -EINVAL; 359925c5749SYifeng Zhao } 360925c5749SYifeng Zhao 361925c5749SYifeng Zhao priv->dev = udev; 362925c5749SYifeng Zhao priv->mode = PHY_TYPE_SATA; 363925c5749SYifeng Zhao priv->cfg = phy_cfg; 364925c5749SYifeng Zhao 3655eec6d12SJon Lin return rockchip_combphy_parse_dt(udev, priv); 366925c5749SYifeng Zhao } 367925c5749SYifeng Zhao 3683452d642SJianwei Zheng static int rk3528_combphy_cfg(struct rockchip_combphy_priv *priv) 3693452d642SJianwei Zheng { 3703452d642SJianwei Zheng const struct rockchip_combphy_grfcfg *cfg = priv->cfg->grfcfg; 3713452d642SJianwei Zheng u32 val; 3723452d642SJianwei Zheng 3733452d642SJianwei Zheng switch (priv->mode) { 3743452d642SJianwei Zheng case PHY_TYPE_PCIE: 3753452d642SJianwei Zheng /* Set SSC downward spread spectrum */ 3763452d642SJianwei Zheng val = readl(priv->mmio + 0x18); 3773452d642SJianwei Zheng val &= ~GENMASK(5, 4); 3783452d642SJianwei Zheng val |= 0x01 << 4; 3793452d642SJianwei Zheng writel(val, priv->mmio + 0x18); 3803452d642SJianwei Zheng 3813452d642SJianwei Zheng param_write(priv->phy_grf, &cfg->con0_for_pcie, true); 3823452d642SJianwei Zheng param_write(priv->phy_grf, &cfg->con1_for_pcie, true); 3833452d642SJianwei Zheng param_write(priv->phy_grf, &cfg->con2_for_pcie, true); 3843452d642SJianwei Zheng param_write(priv->phy_grf, &cfg->con3_for_pcie, true); 3853452d642SJianwei Zheng break; 3863452d642SJianwei Zheng case PHY_TYPE_USB3: 3873452d642SJianwei Zheng /* Set SSC downward spread spectrum */ 3883452d642SJianwei Zheng val = readl(priv->mmio + 0x18); 3893452d642SJianwei Zheng val &= ~GENMASK(5, 4); 3903452d642SJianwei Zheng val |= 0x01 << 4; 3913452d642SJianwei Zheng writel(val, priv->mmio + 0x18); 3923452d642SJianwei Zheng 3933452d642SJianwei Zheng /* Enable adaptive CTLE for USB3.0 Rx */ 3943452d642SJianwei Zheng val = readl(priv->mmio + 0x200); 3953452d642SJianwei Zheng val &= ~GENMASK(17, 17); 3963452d642SJianwei Zheng val |= 0x01; 3973452d642SJianwei Zheng writel(val, priv->mmio + 0x200); 3983452d642SJianwei Zheng 399*fc3847fcSWilliam Wu /* Set Rx squelch input filler bandwidth */ 400*fc3847fcSWilliam Wu val = readl(priv->mmio + 0x20c); 401*fc3847fcSWilliam Wu val &= ~GENMASK(2, 0); 402*fc3847fcSWilliam Wu val |= 0x06; 403*fc3847fcSWilliam Wu writel(val, priv->mmio + 0x20c); 404*fc3847fcSWilliam Wu 4053452d642SJianwei Zheng param_write(priv->phy_grf, &cfg->pipe_txcomp_sel, false); 4063452d642SJianwei Zheng param_write(priv->phy_grf, &cfg->pipe_txelec_sel, false); 4073452d642SJianwei Zheng param_write(priv->phy_grf, &cfg->usb_mode_set, true); 4083452d642SJianwei Zheng break; 4093452d642SJianwei Zheng default: 4103452d642SJianwei Zheng dev_err(priv->dev, "incompatible PHY type\n"); 4113452d642SJianwei Zheng return -EINVAL; 4123452d642SJianwei Zheng } 4133452d642SJianwei Zheng 4143452d642SJianwei Zheng param_write(priv->phy_grf, &cfg->pipe_clk_100m, true); 4153452d642SJianwei Zheng if (priv->mode == PHY_TYPE_PCIE) { 4163452d642SJianwei Zheng /* PLL KVCO tuning fine */ 4173452d642SJianwei Zheng val = readl(priv->mmio + 0x18); 4183452d642SJianwei Zheng val &= ~(0x7 << 10); 4193452d642SJianwei Zheng val |= 0x2 << 10; 4203452d642SJianwei Zheng writel(val, priv->mmio + 0x18); 4213452d642SJianwei Zheng 4223452d642SJianwei Zheng /* su_trim[6:4]=111, [10:7]=1001, [2:0]=000 */ 4233452d642SJianwei Zheng val = readl(priv->mmio + 0x108); 4243452d642SJianwei Zheng val &= ~(0x7f7); 4253452d642SJianwei Zheng val |= 0x4f0; 4263452d642SJianwei Zheng writel(val, priv->mmio + 0x108); 4273452d642SJianwei Zheng } 4283452d642SJianwei Zheng 4293452d642SJianwei Zheng return 0; 4303452d642SJianwei Zheng } 4313452d642SJianwei Zheng 4323452d642SJianwei Zheng static const struct rockchip_combphy_grfcfg rk3528_combphy_grfcfgs = { 4333452d642SJianwei Zheng /* pipe-phy-grf */ 4343452d642SJianwei Zheng .pcie_mode_set = { 0x48000, 5, 0, 0x00, 0x11 }, 4353452d642SJianwei Zheng .usb_mode_set = { 0x48000, 5, 0, 0x00, 0x04 }, 4363452d642SJianwei Zheng .pipe_rxterm_set = { 0x48000, 12, 12, 0x00, 0x01 }, 4373452d642SJianwei Zheng .pipe_txelec_set = { 0x48004, 1, 1, 0x00, 0x01 }, 4383452d642SJianwei Zheng .pipe_txcomp_set = { 0x48004, 4, 4, 0x00, 0x01 }, 4393452d642SJianwei Zheng .pipe_clk_24m = { 0x48004, 14, 13, 0x00, 0x00 }, 4403452d642SJianwei Zheng .pipe_clk_100m = { 0x48004, 14, 13, 0x00, 0x02 }, 4413452d642SJianwei Zheng .pipe_rxterm_sel = { 0x48008, 8, 8, 0x00, 0x01 }, 4423452d642SJianwei Zheng .pipe_txelec_sel = { 0x48008, 12, 12, 0x00, 0x01 }, 4433452d642SJianwei Zheng .pipe_txcomp_sel = { 0x48008, 15, 15, 0x00, 0x01 }, 4443452d642SJianwei Zheng .pipe_clk_ext = { 0x4800c, 9, 8, 0x02, 0x01 }, 4453452d642SJianwei Zheng .pipe_phy_status = { 0x48034, 6, 6, 0x01, 0x00 }, 4463452d642SJianwei Zheng .con0_for_pcie = { 0x48000, 15, 0, 0x00, 0x110 }, 4473452d642SJianwei Zheng .con1_for_pcie = { 0x48004, 15, 0, 0x00, 0x00 }, 4483452d642SJianwei Zheng .con2_for_pcie = { 0x48008, 15, 0, 0x00, 0x101 }, 4493452d642SJianwei Zheng .con3_for_pcie = { 0x4800c, 15, 0, 0x00, 0x0200 }, 4503452d642SJianwei Zheng /* pipe-grf */ 45114d5da7dSwilliam.wu .u3otg0_pipe_clk_sel = { 0x40044, 7, 7, 0x01, 0x00 }, 4523452d642SJianwei Zheng .u3otg0_port_en = { 0x40044, 15, 0, 0x0181, 0x1100 }, 4533452d642SJianwei Zheng }; 4543452d642SJianwei Zheng 4553452d642SJianwei Zheng static const struct rockchip_combphy_cfg rk3528_combphy_cfgs = { 4563452d642SJianwei Zheng .grfcfg = &rk3528_combphy_grfcfgs, 4573452d642SJianwei Zheng .combphy_cfg = rk3528_combphy_cfg, 4583452d642SJianwei Zheng }; 4593452d642SJianwei Zheng 460885c5d5dSFrank Wang static int rk3562_combphy_cfg(struct rockchip_combphy_priv *priv) 461885c5d5dSFrank Wang { 462885c5d5dSFrank Wang const struct rockchip_combphy_grfcfg *cfg = priv->cfg->grfcfg; 463885c5d5dSFrank Wang u32 val; 464885c5d5dSFrank Wang 465885c5d5dSFrank Wang switch (priv->mode) { 466885c5d5dSFrank Wang case PHY_TYPE_PCIE: 467885c5d5dSFrank Wang /* Set SSC downward spread spectrum */ 468885c5d5dSFrank Wang val = readl(priv->mmio + (0x1f << 2)); 469885c5d5dSFrank Wang val &= ~GENMASK(5, 4); 470885c5d5dSFrank Wang val |= 0x01 << 4; 471885c5d5dSFrank Wang writel(val, priv->mmio + 0x7c); 472885c5d5dSFrank Wang 473885c5d5dSFrank Wang param_write(priv->phy_grf, &cfg->con0_for_pcie, true); 474885c5d5dSFrank Wang param_write(priv->phy_grf, &cfg->con1_for_pcie, true); 475885c5d5dSFrank Wang param_write(priv->phy_grf, &cfg->con2_for_pcie, true); 476885c5d5dSFrank Wang param_write(priv->phy_grf, &cfg->con3_for_pcie, true); 477885c5d5dSFrank Wang break; 478885c5d5dSFrank Wang case PHY_TYPE_USB3: 479885c5d5dSFrank Wang /* Set SSC downward spread spectrum */ 480885c5d5dSFrank Wang val = readl(priv->mmio + (0x1f << 2)); 481885c5d5dSFrank Wang val &= ~GENMASK(5, 4); 482885c5d5dSFrank Wang val |= 0x01 << 4; 483885c5d5dSFrank Wang writel(val, priv->mmio + 0x7c); 484885c5d5dSFrank Wang 485885c5d5dSFrank Wang /* Enable adaptive CTLE for USB3.0 Rx */ 486885c5d5dSFrank Wang val = readl(priv->mmio + (0x0e << 2)); 487885c5d5dSFrank Wang val &= ~GENMASK(0, 0); 488885c5d5dSFrank Wang val |= 0x01; 489885c5d5dSFrank Wang writel(val, priv->mmio + (0x0e << 2)); 490885c5d5dSFrank Wang 491885c5d5dSFrank Wang /* Set PLL KVCO fine tuning signals */ 492885c5d5dSFrank Wang val = readl(priv->mmio + (0x20 << 2)); 493885c5d5dSFrank Wang val &= ~(0x7 << 2); 494885c5d5dSFrank Wang val |= 0x2 << 2; 495885c5d5dSFrank Wang writel(val, priv->mmio + (0x20 << 2)); 496885c5d5dSFrank Wang 497885c5d5dSFrank Wang /* Set PLL LPF R1 to su_trim[10:7]=1001 */ 498885c5d5dSFrank Wang writel(0x4, priv->mmio + (0xb << 2)); 499885c5d5dSFrank Wang 500885c5d5dSFrank Wang /* Set PLL input clock divider 1/2 */ 501885c5d5dSFrank Wang val = readl(priv->mmio + (0x5 << 2)); 502885c5d5dSFrank Wang val &= ~(0x3 << 6); 503885c5d5dSFrank Wang val |= 0x1 << 6; 504885c5d5dSFrank Wang writel(val, priv->mmio + (0x5 << 2)); 505885c5d5dSFrank Wang 506885c5d5dSFrank Wang /* Set PLL loop divider */ 507885c5d5dSFrank Wang writel(0x32, priv->mmio + (0x11 << 2)); 508885c5d5dSFrank Wang 509885c5d5dSFrank Wang /* Set PLL KVCO to min and set PLL charge pump current to max */ 510885c5d5dSFrank Wang writel(0xf0, priv->mmio + (0xa << 2)); 511885c5d5dSFrank Wang 512*fc3847fcSWilliam Wu /* Set Rx squelch input filler bandwidth */ 513*fc3847fcSWilliam Wu writel(0x0e, priv->mmio + (0x14 << 2)); 514*fc3847fcSWilliam Wu 515885c5d5dSFrank Wang param_write(priv->phy_grf, &cfg->pipe_sel_usb, true); 516885c5d5dSFrank Wang param_write(priv->phy_grf, &cfg->pipe_txcomp_sel, false); 517885c5d5dSFrank Wang param_write(priv->phy_grf, &cfg->pipe_txelec_sel, false); 518885c5d5dSFrank Wang param_write(priv->phy_grf, &cfg->usb_mode_set, true); 519885c5d5dSFrank Wang break; 520885c5d5dSFrank Wang default: 521885c5d5dSFrank Wang pr_err("%s, phy-type %d\n", __func__, priv->mode); 522885c5d5dSFrank Wang return -EINVAL; 523885c5d5dSFrank Wang } 524885c5d5dSFrank Wang 525885c5d5dSFrank Wang clk_set_rate(&priv->ref_clk, 100000000); 526885c5d5dSFrank Wang param_write(priv->phy_grf, &cfg->pipe_clk_100m, true); 527885c5d5dSFrank Wang 528cc9876f4SJon Lin if (priv->mode == PHY_TYPE_PCIE) { 529cc9876f4SJon Lin /* PLL KVCO tuning fine */ 530cc9876f4SJon Lin val = readl(priv->mmio + (0x20 << 2)); 531cc9876f4SJon Lin val &= ~(0x7 << 2); 532cc9876f4SJon Lin val |= 0x2 << 2; 533cc9876f4SJon Lin writel(val, priv->mmio + (0x20 << 2)); 534cc9876f4SJon Lin 535cc9876f4SJon Lin /* Enable controlling random jitter, aka RMJ */ 536cc9876f4SJon Lin writel(0x4, priv->mmio + (0xb << 2)); 537cc9876f4SJon Lin 538cc9876f4SJon Lin val = readl(priv->mmio + (0x5 << 2)); 539cc9876f4SJon Lin val &= ~(0x3 << 6); 540cc9876f4SJon Lin val |= 0x1 << 6; 541cc9876f4SJon Lin writel(val, priv->mmio + (0x5 << 2)); 542cc9876f4SJon Lin 543cc9876f4SJon Lin writel(0x32, priv->mmio + (0x11 << 2)); 544cc9876f4SJon Lin writel(0xf0, priv->mmio + (0xa << 2)); 545cc9876f4SJon Lin } 546cc9876f4SJon Lin 547885c5d5dSFrank Wang if (dev_read_bool(priv->dev, "rockchip,enable-ssc")) { 548885c5d5dSFrank Wang val = readl(priv->mmio + (0x7 << 2)); 549885c5d5dSFrank Wang val |= BIT(4); 550885c5d5dSFrank Wang writel(val, priv->mmio + (0x7 << 2)); 551885c5d5dSFrank Wang } 552885c5d5dSFrank Wang 553885c5d5dSFrank Wang return 0; 554885c5d5dSFrank Wang } 555885c5d5dSFrank Wang 556885c5d5dSFrank Wang static const struct rockchip_combphy_grfcfg rk3562_combphy_grfcfgs = { 557885c5d5dSFrank Wang /* pipe-phy-grf */ 558885c5d5dSFrank Wang .pcie_mode_set = { 0x0000, 5, 0, 0x00, 0x11 }, 559885c5d5dSFrank Wang .usb_mode_set = { 0x0000, 5, 0, 0x00, 0x04 }, 560885c5d5dSFrank Wang .pipe_rxterm_set = { 0x0000, 12, 12, 0x00, 0x01 }, 561885c5d5dSFrank Wang .pipe_txelec_set = { 0x0004, 1, 1, 0x00, 0x01 }, 562885c5d5dSFrank Wang .pipe_txcomp_set = { 0x0004, 4, 4, 0x00, 0x01 }, 563885c5d5dSFrank Wang .pipe_clk_25m = { 0x0004, 14, 13, 0x00, 0x01 }, 564885c5d5dSFrank Wang .pipe_clk_100m = { 0x0004, 14, 13, 0x00, 0x02 }, 565885c5d5dSFrank Wang .pipe_phymode_sel = { 0x0008, 1, 1, 0x00, 0x01 }, 566885c5d5dSFrank Wang .pipe_rate_sel = { 0x0008, 2, 2, 0x00, 0x01 }, 567885c5d5dSFrank Wang .pipe_rxterm_sel = { 0x0008, 8, 8, 0x00, 0x01 }, 568885c5d5dSFrank Wang .pipe_txelec_sel = { 0x0008, 12, 12, 0x00, 0x01 }, 569885c5d5dSFrank Wang .pipe_txcomp_sel = { 0x0008, 15, 15, 0x00, 0x01 }, 570885c5d5dSFrank Wang .pipe_clk_ext = { 0x000c, 9, 8, 0x02, 0x01 }, 571885c5d5dSFrank Wang .pipe_sel_usb = { 0x000c, 14, 13, 0x00, 0x01 }, 572885c5d5dSFrank Wang .pipe_phy_status = { 0x0034, 6, 6, 0x01, 0x00 }, 573885c5d5dSFrank Wang .con0_for_pcie = { 0x0000, 15, 0, 0x00, 0x1000 }, 574885c5d5dSFrank Wang .con1_for_pcie = { 0x0004, 15, 0, 0x00, 0x0000 }, 575885c5d5dSFrank Wang .con2_for_pcie = { 0x0008, 15, 0, 0x00, 0x0101 }, 576885c5d5dSFrank Wang .con3_for_pcie = { 0x000c, 15, 0, 0x00, 0x0200 }, 57786b316b4SFrank Wang .pipe_phy_grf_reset = { 0x0014, 1, 0, 0x3, 0x1 }, 578885c5d5dSFrank Wang /* pipe-grf */ 579885c5d5dSFrank Wang .u3otg0_port_en = { 0x0094, 15, 0, 0x0181, 0x1100 }, 580885c5d5dSFrank Wang }; 581885c5d5dSFrank Wang 582885c5d5dSFrank Wang static const struct rockchip_combphy_cfg rk3562_combphy_cfgs = { 583885c5d5dSFrank Wang .grfcfg = &rk3562_combphy_grfcfgs, 584885c5d5dSFrank Wang .combphy_cfg = rk3562_combphy_cfg, 585885c5d5dSFrank Wang }; 586885c5d5dSFrank Wang 587925c5749SYifeng Zhao static int rk3568_combphy_cfg(struct rockchip_combphy_priv *priv) 588925c5749SYifeng Zhao { 589925c5749SYifeng Zhao const struct rockchip_combphy_grfcfg *cfg = priv->cfg->grfcfg; 590925c5749SYifeng Zhao u32 val; 591925c5749SYifeng Zhao 592925c5749SYifeng Zhao switch (priv->mode) { 593925c5749SYifeng Zhao case PHY_TYPE_PCIE: 594925c5749SYifeng Zhao /* Set SSC downward spread spectrum */ 595925c5749SYifeng Zhao val = readl(priv->mmio + (0x1f << 2)); 596925c5749SYifeng Zhao val &= ~GENMASK(5, 4); 597925c5749SYifeng Zhao val |= 0x01 << 4; 598925c5749SYifeng Zhao writel(val, priv->mmio + 0x7c); 599925c5749SYifeng Zhao 600925c5749SYifeng Zhao param_write(priv->phy_grf, &cfg->con0_for_pcie, true); 601925c5749SYifeng Zhao param_write(priv->phy_grf, &cfg->con1_for_pcie, true); 602925c5749SYifeng Zhao param_write(priv->phy_grf, &cfg->con2_for_pcie, true); 603925c5749SYifeng Zhao param_write(priv->phy_grf, &cfg->con3_for_pcie, true); 604925c5749SYifeng Zhao break; 605925c5749SYifeng Zhao case PHY_TYPE_USB3: 606925c5749SYifeng Zhao /* Set SSC downward spread spectrum */ 607925c5749SYifeng Zhao val = readl(priv->mmio + (0x1f << 2)); 608925c5749SYifeng Zhao val &= ~GENMASK(5, 4); 609925c5749SYifeng Zhao val |= 0x01 << 4; 610925c5749SYifeng Zhao writel(val, priv->mmio + 0x7c); 611925c5749SYifeng Zhao 612925c5749SYifeng Zhao /* Enable adaptive CTLE for USB3.0 Rx */ 613925c5749SYifeng Zhao val = readl(priv->mmio + (0x0e << 2)); 614925c5749SYifeng Zhao val &= ~GENMASK(0, 0); 615925c5749SYifeng Zhao val |= 0x01; 616925c5749SYifeng Zhao writel(val, priv->mmio + (0x0e << 2)); 617925c5749SYifeng Zhao 618a0d03578SWilliam Wu /* Set PLL KVCO fine tuning signals */ 619a0d03578SWilliam Wu val = readl(priv->mmio + (0x20 << 2)); 620a0d03578SWilliam Wu val &= ~(0x7 << 2); 621a0d03578SWilliam Wu val |= 0x2 << 2; 622a0d03578SWilliam Wu writel(val, priv->mmio + (0x20 << 2)); 623a0d03578SWilliam Wu 624a0d03578SWilliam Wu /* Set PLL LPF R1 to su_trim[10:7]=1001 */ 625a0d03578SWilliam Wu writel(0x4, priv->mmio + (0xb << 2)); 626a0d03578SWilliam Wu 627a0d03578SWilliam Wu /* Set PLL input clock divider 1/2 */ 628a0d03578SWilliam Wu val = readl(priv->mmio + (0x5 << 2)); 629a0d03578SWilliam Wu val &= ~(0x3 << 6); 630a0d03578SWilliam Wu val |= 0x1 << 6; 631a0d03578SWilliam Wu writel(val, priv->mmio + (0x5 << 2)); 632a0d03578SWilliam Wu 633a0d03578SWilliam Wu /* Set PLL loop divider */ 634a0d03578SWilliam Wu writel(0x32, priv->mmio + (0x11 << 2)); 635a0d03578SWilliam Wu 636a0d03578SWilliam Wu /* Set PLL KVCO to min and set PLL charge pump current to max */ 637a0d03578SWilliam Wu writel(0xf0, priv->mmio + (0xa << 2)); 638a0d03578SWilliam Wu 639*fc3847fcSWilliam Wu /* Set Rx squelch input filler bandwidth */ 640*fc3847fcSWilliam Wu writel(0x0e, priv->mmio + (0x14 << 2)); 641*fc3847fcSWilliam Wu 642925c5749SYifeng Zhao param_write(priv->phy_grf, &cfg->pipe_sel_usb, true); 643925c5749SYifeng Zhao param_write(priv->phy_grf, &cfg->pipe_txcomp_sel, false); 644925c5749SYifeng Zhao param_write(priv->phy_grf, &cfg->pipe_txelec_sel, false); 645925c5749SYifeng Zhao param_write(priv->phy_grf, &cfg->usb_mode_set, true); 646925c5749SYifeng Zhao break; 647925c5749SYifeng Zhao case PHY_TYPE_SATA: 648925c5749SYifeng Zhao writel(0x41, priv->mmio + 0x38); 649925c5749SYifeng Zhao writel(0x8F, priv->mmio + 0x18); 650925c5749SYifeng Zhao param_write(priv->phy_grf, &cfg->con0_for_sata, true); 651925c5749SYifeng Zhao param_write(priv->phy_grf, &cfg->con1_for_sata, true); 652925c5749SYifeng Zhao param_write(priv->phy_grf, &cfg->con2_for_sata, true); 653925c5749SYifeng Zhao param_write(priv->phy_grf, &cfg->con3_for_sata, true); 654925c5749SYifeng Zhao param_write(priv->pipe_grf, &cfg->pipe_con0_for_sata, true); 655925c5749SYifeng Zhao break; 656925c5749SYifeng Zhao case PHY_TYPE_SGMII: 657925c5749SYifeng Zhao param_write(priv->pipe_grf, &cfg->pipe_xpcs_phy_ready, true); 658925c5749SYifeng Zhao param_write(priv->phy_grf, &cfg->pipe_phymode_sel, true); 659925c5749SYifeng Zhao param_write(priv->phy_grf, &cfg->pipe_sel_qsgmii, true); 660925c5749SYifeng Zhao param_write(priv->phy_grf, &cfg->sgmii_mode_set, true); 661925c5749SYifeng Zhao break; 662925c5749SYifeng Zhao case PHY_TYPE_QSGMII: 663925c5749SYifeng Zhao param_write(priv->pipe_grf, &cfg->pipe_xpcs_phy_ready, true); 664925c5749SYifeng Zhao param_write(priv->phy_grf, &cfg->pipe_phymode_sel, true); 665925c5749SYifeng Zhao param_write(priv->phy_grf, &cfg->pipe_rate_sel, true); 666925c5749SYifeng Zhao param_write(priv->phy_grf, &cfg->pipe_sel_qsgmii, true); 667925c5749SYifeng Zhao param_write(priv->phy_grf, &cfg->qsgmii_mode_set, true); 668925c5749SYifeng Zhao break; 669925c5749SYifeng Zhao default: 670925c5749SYifeng Zhao pr_err("%s, phy-type %d\n", __func__, priv->mode); 671925c5749SYifeng Zhao return -EINVAL; 672925c5749SYifeng Zhao } 673925c5749SYifeng Zhao 674dbf89912SRen Jianing /* The default ref clock is 25Mhz */ 675dbf89912SRen Jianing param_write(priv->phy_grf, &cfg->pipe_clk_25m, true); 676925c5749SYifeng Zhao 677925c5749SYifeng Zhao if (dev_read_bool(priv->dev, "rockchip,enable-ssc")) { 678925c5749SYifeng Zhao val = readl(priv->mmio + (0x7 << 2)); 679925c5749SYifeng Zhao val |= BIT(4); 680925c5749SYifeng Zhao writel(val, priv->mmio + (0x7 << 2)); 681925c5749SYifeng Zhao } 682925c5749SYifeng Zhao 683925c5749SYifeng Zhao return 0; 684925c5749SYifeng Zhao } 685925c5749SYifeng Zhao 686925c5749SYifeng Zhao static const struct rockchip_combphy_grfcfg rk3568_combphy_grfcfgs = { 687925c5749SYifeng Zhao /* pipe-phy-grf */ 688925c5749SYifeng Zhao .pcie_mode_set = { 0x0000, 5, 0, 0x00, 0x11 }, 689925c5749SYifeng Zhao .usb_mode_set = { 0x0000, 5, 0, 0x00, 0x04 }, 690925c5749SYifeng Zhao .sgmii_mode_set = { 0x0000, 5, 0, 0x00, 0x01 }, 691925c5749SYifeng Zhao .qsgmii_mode_set = { 0x0000, 5, 0, 0x00, 0x21 }, 692925c5749SYifeng Zhao .pipe_rxterm_set = { 0x0000, 12, 12, 0x00, 0x01 }, 693925c5749SYifeng Zhao .pipe_txelec_set = { 0x0004, 1, 1, 0x00, 0x01 }, 694925c5749SYifeng Zhao .pipe_txcomp_set = { 0x0004, 4, 4, 0x00, 0x01 }, 695925c5749SYifeng Zhao .pipe_clk_25m = { 0x0004, 14, 13, 0x00, 0x01 }, 696925c5749SYifeng Zhao .pipe_clk_100m = { 0x0004, 14, 13, 0x00, 0x02 }, 697925c5749SYifeng Zhao .pipe_phymode_sel = { 0x0008, 1, 1, 0x00, 0x01 }, 698925c5749SYifeng Zhao .pipe_rate_sel = { 0x0008, 2, 2, 0x00, 0x01 }, 699925c5749SYifeng Zhao .pipe_rxterm_sel = { 0x0008, 8, 8, 0x00, 0x01 }, 700925c5749SYifeng Zhao .pipe_txelec_sel = { 0x0008, 12, 12, 0x00, 0x01 }, 701925c5749SYifeng Zhao .pipe_txcomp_sel = { 0x0008, 15, 15, 0x00, 0x01 }, 702925c5749SYifeng Zhao .pipe_clk_ext = { 0x000c, 9, 8, 0x02, 0x01 }, 703925c5749SYifeng Zhao .pipe_sel_usb = { 0x000c, 14, 13, 0x00, 0x01 }, 704925c5749SYifeng Zhao .pipe_sel_qsgmii = { 0x000c, 15, 13, 0x00, 0x07 }, 705925c5749SYifeng Zhao .pipe_phy_status = { 0x0034, 6, 6, 0x01, 0x00 }, 706925c5749SYifeng Zhao .con0_for_pcie = { 0x0000, 15, 0, 0x00, 0x1000 }, 707925c5749SYifeng Zhao .con1_for_pcie = { 0x0004, 15, 0, 0x00, 0x0000 }, 708925c5749SYifeng Zhao .con2_for_pcie = { 0x0008, 15, 0, 0x00, 0x0101 }, 709925c5749SYifeng Zhao .con3_for_pcie = { 0x000c, 15, 0, 0x00, 0x0200 }, 710925c5749SYifeng Zhao .con0_for_sata = { 0x0000, 15, 0, 0x00, 0x0119 }, 711925c5749SYifeng Zhao .con1_for_sata = { 0x0004, 15, 0, 0x00, 0x0040 }, 712925c5749SYifeng Zhao .con2_for_sata = { 0x0008, 15, 0, 0x00, 0x80c3 }, 713925c5749SYifeng Zhao .con3_for_sata = { 0x000c, 15, 0, 0x00, 0x4407 }, 714925c5749SYifeng Zhao /* pipe-grf */ 715925c5749SYifeng Zhao .pipe_con0_for_sata = { 0x0000, 15, 0, 0x00, 0x2220 }, 716925c5749SYifeng Zhao .pipe_sgmii_mac_sel = { 0x0040, 1, 1, 0x00, 0x01 }, 717925c5749SYifeng Zhao .pipe_xpcs_phy_ready = { 0x0040, 2, 2, 0x00, 0x01 }, 718925c5749SYifeng Zhao .u3otg0_port_en = { 0x0104, 15, 0, 0x0181, 0x1100 }, 719925c5749SYifeng Zhao .u3otg1_port_en = { 0x0144, 15, 0, 0x0181, 0x1100 }, 720925c5749SYifeng Zhao }; 721925c5749SYifeng Zhao 722925c5749SYifeng Zhao static const struct rockchip_combphy_cfg rk3568_combphy_cfgs = { 723925c5749SYifeng Zhao .grfcfg = &rk3568_combphy_grfcfgs, 724925c5749SYifeng Zhao .combphy_cfg = rk3568_combphy_cfg, 725925c5749SYifeng Zhao }; 726925c5749SYifeng Zhao 727cf3c44cbSJon Lin static int rk3588_combphy_cfg(struct rockchip_combphy_priv *priv) 728cf3c44cbSJon Lin { 729cf3c44cbSJon Lin const struct rockchip_combphy_grfcfg *cfg = priv->cfg->grfcfg; 730d8968f57SWilliam Wu u32 val; 731cf3c44cbSJon Lin 732cf3c44cbSJon Lin switch (priv->mode) { 733cf3c44cbSJon Lin case PHY_TYPE_PCIE: 734cf3c44cbSJon Lin param_write(priv->phy_grf, &cfg->con0_for_pcie, true); 735cf3c44cbSJon Lin param_write(priv->phy_grf, &cfg->con1_for_pcie, true); 736cf3c44cbSJon Lin param_write(priv->phy_grf, &cfg->con2_for_pcie, true); 737cf3c44cbSJon Lin param_write(priv->phy_grf, &cfg->con3_for_pcie, true); 738cf3c44cbSJon Lin break; 739cf3c44cbSJon Lin case PHY_TYPE_USB3: 740d8968f57SWilliam Wu /* Set SSC downward spread spectrum */ 741d8968f57SWilliam Wu val = readl(priv->mmio + (0x1f << 2)); 742d8968f57SWilliam Wu val &= ~GENMASK(5, 4); 743d8968f57SWilliam Wu val |= 0x01 << 4; 744d8968f57SWilliam Wu writel(val, priv->mmio + 0x7c); 745d8968f57SWilliam Wu 746d8968f57SWilliam Wu /* Enable adaptive CTLE for USB3.0 Rx */ 747d8968f57SWilliam Wu val = readl(priv->mmio + (0x0e << 2)); 748d8968f57SWilliam Wu val &= ~GENMASK(0, 0); 749d8968f57SWilliam Wu val |= 0x01; 750d8968f57SWilliam Wu writel(val, priv->mmio + (0x0e << 2)); 751d8968f57SWilliam Wu 752d8968f57SWilliam Wu /* Set PLL KVCO fine tuning signals */ 753d8968f57SWilliam Wu val = readl(priv->mmio + (0x20 << 2)); 754d8968f57SWilliam Wu val &= ~(0x7 << 2); 755d8968f57SWilliam Wu val |= 0x2 << 2; 756d8968f57SWilliam Wu writel(val, priv->mmio + (0x20 << 2)); 757d8968f57SWilliam Wu 758d8968f57SWilliam Wu /* Set PLL LPF R1 to su_trim[10:7]=1001 */ 759d8968f57SWilliam Wu writel(0x4, priv->mmio + (0xb << 2)); 760d8968f57SWilliam Wu 761d8968f57SWilliam Wu /* Set PLL input clock divider 1/2 */ 762d8968f57SWilliam Wu val = readl(priv->mmio + (0x5 << 2)); 763d8968f57SWilliam Wu val &= ~(0x3 << 6); 764d8968f57SWilliam Wu val |= 0x1 << 6; 765d8968f57SWilliam Wu writel(val, priv->mmio + (0x5 << 2)); 766d8968f57SWilliam Wu 767d8968f57SWilliam Wu /* Set PLL loop divider */ 768d8968f57SWilliam Wu writel(0x32, priv->mmio + (0x11 << 2)); 769d8968f57SWilliam Wu 770d8968f57SWilliam Wu /* Set PLL KVCO to min and set PLL charge pump current to max */ 771d8968f57SWilliam Wu writel(0xf0, priv->mmio + (0xa << 2)); 772d8968f57SWilliam Wu 77387bfcd06SWilliam Wu /* Set Rx squelch input filler bandwidth */ 77487bfcd06SWilliam Wu writel(0x0d, priv->mmio + (0x14 << 2)); 77587bfcd06SWilliam Wu 776cf3c44cbSJon Lin param_write(priv->phy_grf, &cfg->pipe_txcomp_sel, false); 777cf3c44cbSJon Lin param_write(priv->phy_grf, &cfg->pipe_txelec_sel, false); 778cf3c44cbSJon Lin param_write(priv->phy_grf, &cfg->usb_mode_set, true); 779cf3c44cbSJon Lin break; 780cf3c44cbSJon Lin case PHY_TYPE_SATA: 781418dd88dSYifeng Zhao /* Enable adaptive CTLE for SATA Rx */ 782418dd88dSYifeng Zhao val = readl(priv->mmio + (0x0e << 2)); 783418dd88dSYifeng Zhao val &= ~GENMASK(0, 0); 784418dd88dSYifeng Zhao val |= 0x01; 785418dd88dSYifeng Zhao writel(val, priv->mmio + (0x0e << 2)); 786418dd88dSYifeng Zhao /* Set tx_rterm = 50 ohm and rx_rterm = 43.5 ohm */ 787418dd88dSYifeng Zhao writel(0x8F, priv->mmio + (0x06 << 2)); 788418dd88dSYifeng Zhao 789cf3c44cbSJon Lin param_write(priv->phy_grf, &cfg->con0_for_sata, true); 790cf3c44cbSJon Lin param_write(priv->phy_grf, &cfg->con1_for_sata, true); 791cf3c44cbSJon Lin param_write(priv->phy_grf, &cfg->con2_for_sata, true); 792cf3c44cbSJon Lin param_write(priv->phy_grf, &cfg->con3_for_sata, true); 793cf3c44cbSJon Lin param_write(priv->pipe_grf, &cfg->pipe_con0_for_sata, true); 794cf3c44cbSJon Lin param_write(priv->pipe_grf, &cfg->pipe_con1_for_sata, true); 795cf3c44cbSJon Lin break; 796cf3c44cbSJon Lin case PHY_TYPE_SGMII: 797cf3c44cbSJon Lin case PHY_TYPE_QSGMII: 798cf3c44cbSJon Lin default: 799cf3c44cbSJon Lin dev_err(priv->dev, "incompatible PHY type\n"); 800cf3c44cbSJon Lin return -EINVAL; 801cf3c44cbSJon Lin } 802cf3c44cbSJon Lin 803c72d402cSJon Lin /* 100MHz refclock signal is good */ 804c72d402cSJon Lin clk_set_rate(&priv->ref_clk, 100000000); 805cf3c44cbSJon Lin param_write(priv->phy_grf, &cfg->pipe_clk_100m, true); 806e278c201SKever Yang if (priv->mode == PHY_TYPE_PCIE) { 807e278c201SKever Yang /* PLL KVCO tuning fine */ 808e278c201SKever Yang val = readl(priv->mmio + (0x20 << 2)); 809e278c201SKever Yang val &= ~GENMASK(4, 2); 810e278c201SKever Yang val |= 0x4 << 2; 811e278c201SKever Yang writel(val, priv->mmio + (0x20 << 2)); 812e278c201SKever Yang 813e278c201SKever Yang /* Set up rx_trim: PLL LPF C1 85pf R1 1.25kohm */ 814e278c201SKever Yang val = 0x4c; 815e278c201SKever Yang writel(val, priv->mmio + (0x1b << 2)); 816e278c201SKever Yang 817e278c201SKever Yang /* Set up su_trim: T3 */ 818e278c201SKever Yang val = 0xb0; 819e278c201SKever Yang writel(val, priv->mmio + (0xa << 2)); 820e278c201SKever Yang val = 0x47; 821e278c201SKever Yang writel(val, priv->mmio + (0xb << 2)); 822e278c201SKever Yang val = 0x57; 823e278c201SKever Yang writel(val, priv->mmio + (0xd << 2)); 824e278c201SKever Yang } 825cf3c44cbSJon Lin 826cf3c44cbSJon Lin return 0; 827cf3c44cbSJon Lin } 828cf3c44cbSJon Lin 829cf3c44cbSJon Lin static const struct rockchip_combphy_grfcfg rk3588_combphy_grfcfgs = { 830cf3c44cbSJon Lin /* pipe-phy-grf */ 831cf3c44cbSJon Lin .pcie_mode_set = { 0x0000, 5, 0, 0x00, 0x11 }, 832cf3c44cbSJon Lin .usb_mode_set = { 0x0000, 5, 0, 0x00, 0x04 }, 833cf3c44cbSJon Lin .pipe_rxterm_set = { 0x0000, 12, 12, 0x00, 0x01 }, 834cf3c44cbSJon Lin .pipe_txelec_set = { 0x0004, 1, 1, 0x00, 0x01 }, 835cf3c44cbSJon Lin .pipe_txcomp_set = { 0x0004, 4, 4, 0x00, 0x01 }, 836cf3c44cbSJon Lin .pipe_clk_25m = { 0x0004, 14, 13, 0x00, 0x01 }, 837cf3c44cbSJon Lin .pipe_clk_100m = { 0x0004, 14, 13, 0x00, 0x02 }, 838cf3c44cbSJon Lin .pipe_rxterm_sel = { 0x0008, 8, 8, 0x00, 0x01 }, 839cf3c44cbSJon Lin .pipe_txelec_sel = { 0x0008, 12, 12, 0x00, 0x01 }, 840cf3c44cbSJon Lin .pipe_txcomp_sel = { 0x0008, 15, 15, 0x00, 0x01 }, 841cf3c44cbSJon Lin .pipe_clk_ext = { 0x000c, 9, 8, 0x02, 0x01 }, 842cf3c44cbSJon Lin .pipe_phy_status = { 0x0034, 6, 6, 0x01, 0x00 }, 843cf3c44cbSJon Lin .con0_for_pcie = { 0x0000, 15, 0, 0x00, 0x1000 }, 844cf3c44cbSJon Lin .con1_for_pcie = { 0x0004, 15, 0, 0x00, 0x0000 }, 845cf3c44cbSJon Lin .con2_for_pcie = { 0x0008, 15, 0, 0x00, 0x0101 }, 846cf3c44cbSJon Lin .con3_for_pcie = { 0x000c, 15, 0, 0x00, 0x0200 }, 847cf3c44cbSJon Lin .con0_for_sata = { 0x0000, 15, 0, 0x00, 0x0129 }, 848418dd88dSYifeng Zhao .con1_for_sata = { 0x0004, 15, 0, 0x00, 0x0000 }, 849cf3c44cbSJon Lin .con2_for_sata = { 0x0008, 15, 0, 0x00, 0x80c1 }, 850cf3c44cbSJon Lin .con3_for_sata = { 0x000c, 15, 0, 0x00, 0x0407 }, 851cf3c44cbSJon Lin /* pipe-grf */ 852cf3c44cbSJon Lin .pipe_con0_for_sata = { 0x0000, 11, 5, 0x00, 0x22 }, 853cf3c44cbSJon Lin .pipe_con1_for_sata = { 0x0000, 2, 0, 0x00, 0x2 }, 854cf3c44cbSJon Lin }; 855cf3c44cbSJon Lin 856cf3c44cbSJon Lin static const struct rockchip_combphy_cfg rk3588_combphy_cfgs = { 857cf3c44cbSJon Lin .grfcfg = &rk3588_combphy_grfcfgs, 858cf3c44cbSJon Lin .combphy_cfg = rk3588_combphy_cfg, 859cf3c44cbSJon Lin }; 860cf3c44cbSJon Lin 861925c5749SYifeng Zhao static const struct udevice_id rockchip_combphy_ids[] = { 862925c5749SYifeng Zhao { 8633452d642SJianwei Zheng .compatible = "rockchip,rk3528-naneng-combphy", 8643452d642SJianwei Zheng .data = (ulong)&rk3528_combphy_cfgs 8653452d642SJianwei Zheng }, 8663452d642SJianwei Zheng { 867885c5d5dSFrank Wang .compatible = "rockchip,rk3562-naneng-combphy", 868885c5d5dSFrank Wang .data = (ulong)&rk3562_combphy_cfgs 869885c5d5dSFrank Wang }, 870885c5d5dSFrank Wang { 871925c5749SYifeng Zhao .compatible = "rockchip,rk3568-naneng-combphy", 872925c5749SYifeng Zhao .data = (ulong)&rk3568_combphy_cfgs 873925c5749SYifeng Zhao }, 874cf3c44cbSJon Lin { 875cf3c44cbSJon Lin .compatible = "rockchip,rk3588-naneng-combphy", 876cf3c44cbSJon Lin .data = (ulong)&rk3588_combphy_cfgs 877cf3c44cbSJon Lin }, 878925c5749SYifeng Zhao { } 879925c5749SYifeng Zhao }; 880925c5749SYifeng Zhao 881925c5749SYifeng Zhao U_BOOT_DRIVER(rockchip_naneng_combphy) = { 882925c5749SYifeng Zhao .name = "naneng-combphy", 883925c5749SYifeng Zhao .id = UCLASS_PHY, 884925c5749SYifeng Zhao .of_match = rockchip_combphy_ids, 885925c5749SYifeng Zhao .ops = &rochchip_combphy_ops, 886925c5749SYifeng Zhao .probe = rockchip_combphy_probe, 887925c5749SYifeng Zhao .priv_auto_alloc_size = sizeof(struct rockchip_combphy_priv), 888925c5749SYifeng Zhao }; 889