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> 129863b7ebSFrank Wang #include <dm/uclass-internal.h> 13925c5749SYifeng Zhao #include <dt-bindings/phy/phy.h> 14925c5749SYifeng Zhao #include <generic-phy.h> 15925c5749SYifeng Zhao #include <syscon.h> 16925c5749SYifeng Zhao #include <asm/io.h> 17925c5749SYifeng Zhao #include <asm/arch/clock.h> 18925c5749SYifeng Zhao #include <regmap.h> 19925c5749SYifeng Zhao #include <reset-uclass.h> 2014d5da7dSwilliam.wu #include <linux/iopoll.h> 21925c5749SYifeng Zhao 22925c5749SYifeng Zhao #define BIT_WRITEABLE_SHIFT 16 23925c5749SYifeng Zhao 24925c5749SYifeng Zhao struct rockchip_combphy_priv; 25925c5749SYifeng Zhao 26925c5749SYifeng Zhao struct combphy_reg { 273452d642SJianwei Zheng u32 offset; 28925c5749SYifeng Zhao u16 bitend; 29925c5749SYifeng Zhao u16 bitstart; 30925c5749SYifeng Zhao u16 disable; 31925c5749SYifeng Zhao u16 enable; 32925c5749SYifeng Zhao }; 33925c5749SYifeng Zhao 34925c5749SYifeng Zhao struct rockchip_combphy_grfcfg { 35925c5749SYifeng Zhao struct combphy_reg pcie_mode_set; 36925c5749SYifeng Zhao struct combphy_reg usb_mode_set; 37925c5749SYifeng Zhao struct combphy_reg sgmii_mode_set; 38925c5749SYifeng Zhao struct combphy_reg qsgmii_mode_set; 39925c5749SYifeng Zhao struct combphy_reg pipe_rxterm_set; 40925c5749SYifeng Zhao struct combphy_reg pipe_txelec_set; 41925c5749SYifeng Zhao struct combphy_reg pipe_txcomp_set; 423452d642SJianwei Zheng struct combphy_reg pipe_clk_24m; 43925c5749SYifeng Zhao struct combphy_reg pipe_clk_25m; 44925c5749SYifeng Zhao struct combphy_reg pipe_clk_100m; 45925c5749SYifeng Zhao struct combphy_reg pipe_phymode_sel; 46925c5749SYifeng Zhao struct combphy_reg pipe_rate_sel; 47925c5749SYifeng Zhao struct combphy_reg pipe_rxterm_sel; 48925c5749SYifeng Zhao struct combphy_reg pipe_txelec_sel; 49925c5749SYifeng Zhao struct combphy_reg pipe_txcomp_sel; 50925c5749SYifeng Zhao struct combphy_reg pipe_clk_ext; 51925c5749SYifeng Zhao struct combphy_reg pipe_sel_usb; 52925c5749SYifeng Zhao struct combphy_reg pipe_sel_qsgmii; 53925c5749SYifeng Zhao struct combphy_reg pipe_phy_status; 54925c5749SYifeng Zhao struct combphy_reg con0_for_pcie; 55925c5749SYifeng Zhao struct combphy_reg con1_for_pcie; 56925c5749SYifeng Zhao struct combphy_reg con2_for_pcie; 57925c5749SYifeng Zhao struct combphy_reg con3_for_pcie; 58925c5749SYifeng Zhao struct combphy_reg con0_for_sata; 59925c5749SYifeng Zhao struct combphy_reg con1_for_sata; 60925c5749SYifeng Zhao struct combphy_reg con2_for_sata; 61925c5749SYifeng Zhao struct combphy_reg con3_for_sata; 62925c5749SYifeng Zhao struct combphy_reg pipe_con0_for_sata; 63cf3c44cbSJon Lin struct combphy_reg pipe_con1_for_sata; 64925c5749SYifeng Zhao struct combphy_reg pipe_sgmii_mac_sel; 65925c5749SYifeng Zhao struct combphy_reg pipe_xpcs_phy_ready; 66925c5749SYifeng Zhao struct combphy_reg u3otg0_port_en; 67925c5749SYifeng Zhao struct combphy_reg u3otg1_port_en; 6814d5da7dSwilliam.wu struct combphy_reg u3otg0_pipe_clk_sel; 6986b316b4SFrank Wang struct combphy_reg pipe_phy_grf_reset; 70925c5749SYifeng Zhao }; 71925c5749SYifeng Zhao 72925c5749SYifeng Zhao struct rockchip_combphy_cfg { 73925c5749SYifeng Zhao const struct rockchip_combphy_grfcfg *grfcfg; 74fb632bccSShawn Lin bool force_det_out; /* Tx detect Rx errata */ 75925c5749SYifeng Zhao int (*combphy_cfg)(struct rockchip_combphy_priv *priv); 76925c5749SYifeng Zhao }; 77925c5749SYifeng Zhao 78925c5749SYifeng Zhao struct rockchip_combphy_priv { 79925c5749SYifeng Zhao u32 mode; 80925c5749SYifeng Zhao void __iomem *mmio; 81925c5749SYifeng Zhao struct udevice *dev; 82925c5749SYifeng Zhao struct regmap *pipe_grf; 83925c5749SYifeng Zhao struct regmap *phy_grf; 84925c5749SYifeng Zhao struct phy *phy; 85925c5749SYifeng Zhao struct reset_ctl phy_rst; 86925c5749SYifeng Zhao struct clk ref_clk; 87925c5749SYifeng Zhao const struct rockchip_combphy_cfg *cfg; 88925c5749SYifeng Zhao }; 89925c5749SYifeng Zhao 90925c5749SYifeng Zhao static int param_write(struct regmap *base, 91925c5749SYifeng Zhao const struct combphy_reg *reg, bool en) 92925c5749SYifeng Zhao { 93925c5749SYifeng Zhao u32 val, mask, tmp; 94925c5749SYifeng Zhao 95925c5749SYifeng Zhao tmp = en ? reg->enable : reg->disable; 96925c5749SYifeng Zhao mask = GENMASK(reg->bitend, reg->bitstart); 97925c5749SYifeng Zhao val = (tmp << reg->bitstart) | (mask << BIT_WRITEABLE_SHIFT); 98925c5749SYifeng Zhao 99925c5749SYifeng Zhao return regmap_write(base, reg->offset, val); 100925c5749SYifeng Zhao } 101925c5749SYifeng Zhao 10214d5da7dSwilliam.wu static u32 rockchip_combphy_is_ready(struct rockchip_combphy_priv *priv) 10314d5da7dSwilliam.wu { 10414d5da7dSwilliam.wu const struct rockchip_combphy_grfcfg *cfg = priv->cfg->grfcfg; 10514d5da7dSwilliam.wu u32 mask, val; 10614d5da7dSwilliam.wu 10714d5da7dSwilliam.wu mask = GENMASK(cfg->pipe_phy_status.bitend, 10814d5da7dSwilliam.wu cfg->pipe_phy_status.bitstart); 10914d5da7dSwilliam.wu 11014d5da7dSwilliam.wu regmap_read(priv->phy_grf, cfg->pipe_phy_status.offset, &val); 11114d5da7dSwilliam.wu val = (val & mask) >> cfg->pipe_phy_status.bitstart; 11214d5da7dSwilliam.wu 11314d5da7dSwilliam.wu return val; 11414d5da7dSwilliam.wu } 11514d5da7dSwilliam.wu 116925c5749SYifeng Zhao static int rockchip_combphy_pcie_init(struct rockchip_combphy_priv *priv) 117925c5749SYifeng Zhao { 118925c5749SYifeng Zhao int ret = 0; 119fb632bccSShawn Lin u32 val; 120925c5749SYifeng Zhao 121925c5749SYifeng Zhao if (priv->cfg->combphy_cfg) { 122925c5749SYifeng Zhao ret = priv->cfg->combphy_cfg(priv); 123925c5749SYifeng Zhao if (ret) { 124925c5749SYifeng Zhao dev_err(priv->dev, "failed to init phy for pcie\n"); 125925c5749SYifeng Zhao return ret; 126925c5749SYifeng Zhao } 127925c5749SYifeng Zhao } 128925c5749SYifeng Zhao 129fb632bccSShawn Lin if (priv->cfg->force_det_out) { 130fb632bccSShawn Lin val = readl(priv->mmio + (0x19 << 2)); 131fb632bccSShawn Lin val |= BIT(5); 132fb632bccSShawn Lin writel(val, priv->mmio + (0x19 << 2)); 133fb632bccSShawn Lin } 134fb632bccSShawn Lin 135925c5749SYifeng Zhao return ret; 136925c5749SYifeng Zhao } 137925c5749SYifeng Zhao 138925c5749SYifeng Zhao static int rockchip_combphy_usb3_init(struct rockchip_combphy_priv *priv) 139925c5749SYifeng Zhao { 140ac8e4a89SWilliam Wu const struct rockchip_combphy_grfcfg *cfg = priv->cfg->grfcfg; 141925c5749SYifeng Zhao int ret = 0; 142925c5749SYifeng Zhao 143ac8e4a89SWilliam Wu if (dev_read_bool(priv->dev, "rockchip,dis-u3otg0-port")) { 144ac8e4a89SWilliam Wu ret = param_write(priv->pipe_grf, &cfg->u3otg0_port_en, false); 145ac8e4a89SWilliam Wu return ret; 146ac8e4a89SWilliam Wu } else if (dev_read_bool(priv->dev, "rockchip,dis-u3otg1-port")) { 147ac8e4a89SWilliam Wu param_write(priv->pipe_grf, &cfg->u3otg1_port_en, false); 148ac8e4a89SWilliam Wu #ifdef CONFIG_ROCKCHIP_RK3576 149ac8e4a89SWilliam Wu param_write(priv->phy_grf, &cfg->usb_mode_set, true); 150ac8e4a89SWilliam Wu #endif 151ac8e4a89SWilliam Wu return ret; 152ac8e4a89SWilliam Wu } 153ac8e4a89SWilliam Wu 154925c5749SYifeng Zhao if (priv->cfg->combphy_cfg) { 155925c5749SYifeng Zhao ret = priv->cfg->combphy_cfg(priv); 156925c5749SYifeng Zhao if (ret) { 157925c5749SYifeng Zhao dev_err(priv->dev, "failed to init phy for usb3\n"); 158925c5749SYifeng Zhao return ret; 159925c5749SYifeng Zhao } 160925c5749SYifeng Zhao } 161925c5749SYifeng Zhao 162925c5749SYifeng Zhao return ret; 163925c5749SYifeng Zhao } 164925c5749SYifeng Zhao 165925c5749SYifeng Zhao static int rockchip_combphy_sata_init(struct rockchip_combphy_priv *priv) 166925c5749SYifeng Zhao { 167925c5749SYifeng Zhao int ret = 0; 168925c5749SYifeng Zhao 169925c5749SYifeng Zhao if (priv->cfg->combphy_cfg) { 170925c5749SYifeng Zhao ret = priv->cfg->combphy_cfg(priv); 171925c5749SYifeng Zhao if (ret) { 172925c5749SYifeng Zhao dev_err(priv->dev, "failed to init phy for sata\n"); 173925c5749SYifeng Zhao return ret; 174925c5749SYifeng Zhao } 175925c5749SYifeng Zhao } 176925c5749SYifeng Zhao 177925c5749SYifeng Zhao return ret; 178925c5749SYifeng Zhao } 179925c5749SYifeng Zhao 180925c5749SYifeng Zhao static int rockchip_combphy_sgmii_init(struct rockchip_combphy_priv *priv) 181925c5749SYifeng Zhao { 182925c5749SYifeng Zhao int ret = 0; 183925c5749SYifeng Zhao 184925c5749SYifeng Zhao if (priv->cfg->combphy_cfg) { 185925c5749SYifeng Zhao ret = priv->cfg->combphy_cfg(priv); 186925c5749SYifeng Zhao if (ret) { 187925c5749SYifeng Zhao dev_err(priv->dev, "failed to init phy for sgmii\n"); 188925c5749SYifeng Zhao return ret; 189925c5749SYifeng Zhao } 190925c5749SYifeng Zhao } 191925c5749SYifeng Zhao 192925c5749SYifeng Zhao return ret; 193925c5749SYifeng Zhao } 194925c5749SYifeng Zhao 1959863b7ebSFrank Wang int rockchip_combphy_usb3_uboot_init(fdt_addr_t phy_addr) 19614d5da7dSwilliam.wu { 1979863b7ebSFrank Wang struct udevice *udev = NULL; 1989863b7ebSFrank Wang struct udevice *dev; 1999863b7ebSFrank Wang struct uclass *uc; 2009863b7ebSFrank Wang const struct driver *find_drv; 20114d5da7dSwilliam.wu struct rockchip_combphy_priv *priv; 20214d5da7dSwilliam.wu const struct rockchip_combphy_grfcfg *cfg; 20314d5da7dSwilliam.wu u32 val; 2049863b7ebSFrank Wang int ret = 0; 20514d5da7dSwilliam.wu 2069863b7ebSFrank Wang ret = uclass_get(UCLASS_PHY, &uc); 2079863b7ebSFrank Wang if (ret) 2089863b7ebSFrank Wang return ret; 2099863b7ebSFrank Wang 2109863b7ebSFrank Wang find_drv = DM_GET_DRIVER(rockchip_naneng_combphy); 2119863b7ebSFrank Wang list_for_each_entry(dev, &uc->dev_head, uclass_node) { 2129863b7ebSFrank Wang if (dev->driver == find_drv && dev_read_addr(dev) == phy_addr) { 2139863b7ebSFrank Wang ret = uclass_get_device_tail(dev, 0, &udev); 2149863b7ebSFrank Wang break; 2159863b7ebSFrank Wang } 2169863b7ebSFrank Wang } 2179863b7ebSFrank Wang 2189863b7ebSFrank Wang if (!udev || ret) { 2199863b7ebSFrank Wang ret = ret ? ret : -ENODEV; 22014d5da7dSwilliam.wu pr_err("%s: get usb3-phy node failed: %d\n", __func__, ret); 22114d5da7dSwilliam.wu return ret; 22214d5da7dSwilliam.wu } 22314d5da7dSwilliam.wu 22414d5da7dSwilliam.wu priv = dev_get_priv(udev); 22514d5da7dSwilliam.wu priv->mode = PHY_TYPE_USB3; 22614d5da7dSwilliam.wu cfg = priv->cfg->grfcfg; 22714d5da7dSwilliam.wu 22814d5da7dSwilliam.wu rockchip_combphy_usb3_init(priv); 22914d5da7dSwilliam.wu reset_deassert(&priv->phy_rst); 23014d5da7dSwilliam.wu 23114d5da7dSwilliam.wu if (cfg->pipe_phy_grf_reset.enable) 23214d5da7dSwilliam.wu param_write(priv->phy_grf, &cfg->pipe_phy_grf_reset, false); 23314d5da7dSwilliam.wu 23414d5da7dSwilliam.wu if (priv->mode == PHY_TYPE_USB3) { 23514d5da7dSwilliam.wu ret = readx_poll_timeout(rockchip_combphy_is_ready, 23614d5da7dSwilliam.wu priv, val, 23714d5da7dSwilliam.wu val == cfg->pipe_phy_status.enable, 23814d5da7dSwilliam.wu 1000); 23914d5da7dSwilliam.wu if (ret) { 24014d5da7dSwilliam.wu dev_err(priv->dev, "wait phy status ready timeout\n"); 24114d5da7dSwilliam.wu param_write(priv->phy_grf, &cfg->usb_mode_set, false); 24214d5da7dSwilliam.wu if (cfg->u3otg0_pipe_clk_sel.disable) 24314d5da7dSwilliam.wu param_write(priv->phy_grf, &cfg->u3otg0_pipe_clk_sel, false); 24414d5da7dSwilliam.wu return ret; 24514d5da7dSwilliam.wu } 24614d5da7dSwilliam.wu } 24714d5da7dSwilliam.wu 24814d5da7dSwilliam.wu /* Select clk_usb3otg0_pipe for source clk */ 24914d5da7dSwilliam.wu if (cfg->u3otg0_pipe_clk_sel.disable) 25014d5da7dSwilliam.wu param_write(priv->phy_grf, &cfg->u3otg0_pipe_clk_sel, true); 25114d5da7dSwilliam.wu 25214d5da7dSwilliam.wu return ret; 25314d5da7dSwilliam.wu } 25414d5da7dSwilliam.wu 255925c5749SYifeng Zhao static int rockchip_combphy_set_mode(struct rockchip_combphy_priv *priv) 256925c5749SYifeng Zhao { 257925c5749SYifeng Zhao switch (priv->mode) { 258925c5749SYifeng Zhao case PHY_TYPE_PCIE: 259925c5749SYifeng Zhao rockchip_combphy_pcie_init(priv); 260925c5749SYifeng Zhao break; 261925c5749SYifeng Zhao case PHY_TYPE_USB3: 262925c5749SYifeng Zhao rockchip_combphy_usb3_init(priv); 263925c5749SYifeng Zhao break; 264925c5749SYifeng Zhao case PHY_TYPE_SATA: 265925c5749SYifeng Zhao rockchip_combphy_sata_init(priv); 266925c5749SYifeng Zhao break; 267925c5749SYifeng Zhao case PHY_TYPE_SGMII: 268925c5749SYifeng Zhao case PHY_TYPE_QSGMII: 269925c5749SYifeng Zhao return rockchip_combphy_sgmii_init(priv); 270925c5749SYifeng Zhao default: 271925c5749SYifeng Zhao dev_err(priv->dev, "incompatible PHY type\n"); 272925c5749SYifeng Zhao return -EINVAL; 273925c5749SYifeng Zhao } 274925c5749SYifeng Zhao 275925c5749SYifeng Zhao return 0; 276925c5749SYifeng Zhao } 277925c5749SYifeng Zhao 278925c5749SYifeng Zhao static int rockchip_combphy_init(struct phy *phy) 279925c5749SYifeng Zhao { 280925c5749SYifeng Zhao struct rockchip_combphy_priv *priv = dev_get_priv(phy->dev); 28186b316b4SFrank Wang const struct rockchip_combphy_grfcfg *cfg = priv->cfg->grfcfg; 282925c5749SYifeng Zhao int ret; 283925c5749SYifeng Zhao 284925c5749SYifeng Zhao ret = clk_enable(&priv->ref_clk); 285925c5749SYifeng Zhao if (ret < 0 && ret != -ENOSYS) 286925c5749SYifeng Zhao return ret; 287925c5749SYifeng Zhao 288925c5749SYifeng Zhao ret = rockchip_combphy_set_mode(priv); 289925c5749SYifeng Zhao if (ret) 290925c5749SYifeng Zhao goto err_clk; 291925c5749SYifeng Zhao 292925c5749SYifeng Zhao reset_deassert(&priv->phy_rst); 293925c5749SYifeng Zhao 29486b316b4SFrank Wang if (cfg->pipe_phy_grf_reset.enable) 29586b316b4SFrank Wang param_write(priv->phy_grf, &cfg->pipe_phy_grf_reset, false); 29686b316b4SFrank Wang 297925c5749SYifeng Zhao return 0; 298925c5749SYifeng Zhao 299925c5749SYifeng Zhao err_clk: 300925c5749SYifeng Zhao clk_disable(&priv->ref_clk); 301925c5749SYifeng Zhao 302925c5749SYifeng Zhao return ret; 303925c5749SYifeng Zhao } 304925c5749SYifeng Zhao 305925c5749SYifeng Zhao static int rockchip_combphy_exit(struct phy *phy) 306925c5749SYifeng Zhao { 307925c5749SYifeng Zhao struct rockchip_combphy_priv *priv = dev_get_priv(phy->dev); 30886b316b4SFrank Wang const struct rockchip_combphy_grfcfg *cfg = priv->cfg->grfcfg; 309925c5749SYifeng Zhao 31086b316b4SFrank Wang if (cfg->pipe_phy_grf_reset.enable) 31186b316b4SFrank Wang param_write(priv->phy_grf, &cfg->pipe_phy_grf_reset, true); 31286b316b4SFrank Wang 313925c5749SYifeng Zhao reset_assert(&priv->phy_rst); 31486b316b4SFrank Wang clk_disable(&priv->ref_clk); 315925c5749SYifeng Zhao 316925c5749SYifeng Zhao return 0; 317925c5749SYifeng Zhao } 318925c5749SYifeng Zhao 319925c5749SYifeng Zhao static int rockchip_combphy_xlate(struct phy *phy, struct ofnode_phandle_args *args) 320925c5749SYifeng Zhao { 321925c5749SYifeng Zhao struct rockchip_combphy_priv *priv = dev_get_priv(phy->dev); 322925c5749SYifeng Zhao 323925c5749SYifeng Zhao if (args->args_count != 1) { 324925c5749SYifeng Zhao pr_err("invalid number of arguments\n"); 325925c5749SYifeng Zhao return -EINVAL; 326925c5749SYifeng Zhao } 327925c5749SYifeng Zhao 328925c5749SYifeng Zhao priv->mode = args->args[0]; 329925c5749SYifeng Zhao 330925c5749SYifeng Zhao return 0; 331925c5749SYifeng Zhao } 332925c5749SYifeng Zhao 333925c5749SYifeng Zhao static const struct phy_ops rochchip_combphy_ops = { 334925c5749SYifeng Zhao .init = rockchip_combphy_init, 335925c5749SYifeng Zhao .exit = rockchip_combphy_exit, 336925c5749SYifeng Zhao .of_xlate = rockchip_combphy_xlate, 337925c5749SYifeng Zhao }; 338925c5749SYifeng Zhao 339925c5749SYifeng Zhao static int rockchip_combphy_parse_dt(struct udevice *dev, 340925c5749SYifeng Zhao struct rockchip_combphy_priv *priv) 341925c5749SYifeng Zhao { 342925c5749SYifeng Zhao struct udevice *syscon; 343925c5749SYifeng Zhao int ret; 3447cc44222SJon Lin u32 vals[4]; 345925c5749SYifeng Zhao 346925c5749SYifeng Zhao ret = uclass_get_device_by_phandle(UCLASS_SYSCON, dev, "rockchip,pipe-grf", &syscon); 347925c5749SYifeng Zhao if (ret) { 348cf3c44cbSJon Lin dev_err(dev, "failed to find peri_ctrl pipe-grf regmap ret= %d\n", ret); 349925c5749SYifeng Zhao return ret; 350925c5749SYifeng Zhao } 351925c5749SYifeng Zhao priv->pipe_grf = syscon_get_regmap(syscon); 352925c5749SYifeng Zhao 353925c5749SYifeng Zhao ret = uclass_get_device_by_phandle(UCLASS_SYSCON, dev, "rockchip,pipe-phy-grf", &syscon); 354925c5749SYifeng Zhao if (ret) { 355925c5749SYifeng Zhao dev_err(dev, "failed to find peri_ctrl pipe-phy-grf regmap\n"); 356925c5749SYifeng Zhao return ret; 357925c5749SYifeng Zhao } 358925c5749SYifeng Zhao priv->phy_grf = syscon_get_regmap(syscon); 359925c5749SYifeng Zhao 360925c5749SYifeng Zhao ret = clk_get_by_index(dev, 0, &priv->ref_clk); 361925c5749SYifeng Zhao if (ret) { 362925c5749SYifeng Zhao dev_err(dev, "failed to find ref clock\n"); 363925c5749SYifeng Zhao return PTR_ERR(&priv->ref_clk); 364925c5749SYifeng Zhao } 365925c5749SYifeng Zhao 366dbf89912SRen Jianing ret = reset_get_by_name(dev, "combphy", &priv->phy_rst); 367925c5749SYifeng Zhao if (ret) { 368925c5749SYifeng Zhao dev_err(dev, "no phy reset control specified\n"); 369925c5749SYifeng Zhao return ret; 370925c5749SYifeng Zhao } 371925c5749SYifeng Zhao 3727cc44222SJon Lin if (!dev_read_u32_array(dev, "rockchip,pcie1ln-sel-bits", 3737cc44222SJon Lin vals, ARRAY_SIZE(vals))) 3747cc44222SJon Lin regmap_write(priv->pipe_grf, vals[0], 3757cc44222SJon Lin (GENMASK(vals[2], vals[1]) << 16) | vals[3]); 3767cc44222SJon Lin 377925c5749SYifeng Zhao return 0; 378925c5749SYifeng Zhao } 379925c5749SYifeng Zhao 380925c5749SYifeng Zhao static int rockchip_combphy_probe(struct udevice *udev) 381925c5749SYifeng Zhao { 382925c5749SYifeng Zhao struct rockchip_combphy_priv *priv = dev_get_priv(udev); 383925c5749SYifeng Zhao const struct rockchip_combphy_cfg *phy_cfg; 384925c5749SYifeng Zhao 385925c5749SYifeng Zhao priv->mmio = (void __iomem *)dev_read_addr(udev); 386925c5749SYifeng Zhao if (IS_ERR(priv->mmio)) 387925c5749SYifeng Zhao return PTR_ERR(priv->mmio); 388925c5749SYifeng Zhao 389925c5749SYifeng Zhao phy_cfg = (const struct rockchip_combphy_cfg *)dev_get_driver_data(udev); 390925c5749SYifeng Zhao if (!phy_cfg) { 391925c5749SYifeng Zhao dev_err(udev, "No OF match data provided\n"); 392925c5749SYifeng Zhao return -EINVAL; 393925c5749SYifeng Zhao } 394925c5749SYifeng Zhao 395925c5749SYifeng Zhao priv->dev = udev; 396925c5749SYifeng Zhao priv->mode = PHY_TYPE_SATA; 397925c5749SYifeng Zhao priv->cfg = phy_cfg; 398925c5749SYifeng Zhao 3995eec6d12SJon Lin return rockchip_combphy_parse_dt(udev, priv); 400925c5749SYifeng Zhao } 401925c5749SYifeng Zhao 402fc22f2adSWilliam Wu #ifdef CONFIG_ROCKCHIP_RK3528 4033452d642SJianwei Zheng static int rk3528_combphy_cfg(struct rockchip_combphy_priv *priv) 4043452d642SJianwei Zheng { 4053452d642SJianwei Zheng const struct rockchip_combphy_grfcfg *cfg = priv->cfg->grfcfg; 4063452d642SJianwei Zheng u32 val; 4073452d642SJianwei Zheng 4083452d642SJianwei Zheng switch (priv->mode) { 4093452d642SJianwei Zheng case PHY_TYPE_PCIE: 4103452d642SJianwei Zheng /* Set SSC downward spread spectrum */ 4113452d642SJianwei Zheng val = readl(priv->mmio + 0x18); 4123452d642SJianwei Zheng val &= ~GENMASK(5, 4); 4133452d642SJianwei Zheng val |= 0x01 << 4; 4143452d642SJianwei Zheng writel(val, priv->mmio + 0x18); 4153452d642SJianwei Zheng 4163452d642SJianwei Zheng param_write(priv->phy_grf, &cfg->con0_for_pcie, true); 4173452d642SJianwei Zheng param_write(priv->phy_grf, &cfg->con1_for_pcie, true); 4183452d642SJianwei Zheng param_write(priv->phy_grf, &cfg->con2_for_pcie, true); 4193452d642SJianwei Zheng param_write(priv->phy_grf, &cfg->con3_for_pcie, true); 4203452d642SJianwei Zheng break; 4213452d642SJianwei Zheng case PHY_TYPE_USB3: 4223452d642SJianwei Zheng /* Set SSC downward spread spectrum */ 4233452d642SJianwei Zheng val = readl(priv->mmio + 0x18); 4243452d642SJianwei Zheng val &= ~GENMASK(5, 4); 4253452d642SJianwei Zheng val |= 0x01 << 4; 4263452d642SJianwei Zheng writel(val, priv->mmio + 0x18); 4273452d642SJianwei Zheng 4283452d642SJianwei Zheng /* Enable adaptive CTLE for USB3.0 Rx */ 4293452d642SJianwei Zheng val = readl(priv->mmio + 0x200); 4303452d642SJianwei Zheng val &= ~GENMASK(17, 17); 4313452d642SJianwei Zheng val |= 0x01; 4323452d642SJianwei Zheng writel(val, priv->mmio + 0x200); 4333452d642SJianwei Zheng 434fc3847fcSWilliam Wu /* Set Rx squelch input filler bandwidth */ 435fc3847fcSWilliam Wu val = readl(priv->mmio + 0x20c); 436fc3847fcSWilliam Wu val &= ~GENMASK(2, 0); 437fc3847fcSWilliam Wu val |= 0x06; 438fc3847fcSWilliam Wu writel(val, priv->mmio + 0x20c); 439fc3847fcSWilliam Wu 4403452d642SJianwei Zheng param_write(priv->phy_grf, &cfg->pipe_txcomp_sel, false); 4413452d642SJianwei Zheng param_write(priv->phy_grf, &cfg->pipe_txelec_sel, false); 4423452d642SJianwei Zheng param_write(priv->phy_grf, &cfg->usb_mode_set, true); 4433452d642SJianwei Zheng break; 4443452d642SJianwei Zheng default: 4453452d642SJianwei Zheng dev_err(priv->dev, "incompatible PHY type\n"); 4463452d642SJianwei Zheng return -EINVAL; 4473452d642SJianwei Zheng } 4483452d642SJianwei Zheng 4493452d642SJianwei Zheng param_write(priv->phy_grf, &cfg->pipe_clk_100m, true); 4503452d642SJianwei Zheng if (priv->mode == PHY_TYPE_PCIE) { 4513452d642SJianwei Zheng /* PLL KVCO tuning fine */ 4523452d642SJianwei Zheng val = readl(priv->mmio + 0x18); 4533452d642SJianwei Zheng val &= ~(0x7 << 10); 4543452d642SJianwei Zheng val |= 0x2 << 10; 4553452d642SJianwei Zheng writel(val, priv->mmio + 0x18); 4563452d642SJianwei Zheng 4573452d642SJianwei Zheng /* su_trim[6:4]=111, [10:7]=1001, [2:0]=000 */ 4583452d642SJianwei Zheng val = readl(priv->mmio + 0x108); 4593452d642SJianwei Zheng val &= ~(0x7f7); 4603452d642SJianwei Zheng val |= 0x4f0; 4613452d642SJianwei Zheng writel(val, priv->mmio + 0x108); 4623452d642SJianwei Zheng } 4633452d642SJianwei Zheng 4643452d642SJianwei Zheng return 0; 4653452d642SJianwei Zheng } 4663452d642SJianwei Zheng 4673452d642SJianwei Zheng static const struct rockchip_combphy_grfcfg rk3528_combphy_grfcfgs = { 4683452d642SJianwei Zheng /* pipe-phy-grf */ 4693452d642SJianwei Zheng .pcie_mode_set = { 0x48000, 5, 0, 0x00, 0x11 }, 4703452d642SJianwei Zheng .usb_mode_set = { 0x48000, 5, 0, 0x00, 0x04 }, 4713452d642SJianwei Zheng .pipe_rxterm_set = { 0x48000, 12, 12, 0x00, 0x01 }, 4723452d642SJianwei Zheng .pipe_txelec_set = { 0x48004, 1, 1, 0x00, 0x01 }, 4733452d642SJianwei Zheng .pipe_txcomp_set = { 0x48004, 4, 4, 0x00, 0x01 }, 4743452d642SJianwei Zheng .pipe_clk_24m = { 0x48004, 14, 13, 0x00, 0x00 }, 4753452d642SJianwei Zheng .pipe_clk_100m = { 0x48004, 14, 13, 0x00, 0x02 }, 4763452d642SJianwei Zheng .pipe_rxterm_sel = { 0x48008, 8, 8, 0x00, 0x01 }, 4773452d642SJianwei Zheng .pipe_txelec_sel = { 0x48008, 12, 12, 0x00, 0x01 }, 4783452d642SJianwei Zheng .pipe_txcomp_sel = { 0x48008, 15, 15, 0x00, 0x01 }, 4793452d642SJianwei Zheng .pipe_clk_ext = { 0x4800c, 9, 8, 0x02, 0x01 }, 4803452d642SJianwei Zheng .pipe_phy_status = { 0x48034, 6, 6, 0x01, 0x00 }, 4813452d642SJianwei Zheng .con0_for_pcie = { 0x48000, 15, 0, 0x00, 0x110 }, 4823452d642SJianwei Zheng .con1_for_pcie = { 0x48004, 15, 0, 0x00, 0x00 }, 4833452d642SJianwei Zheng .con2_for_pcie = { 0x48008, 15, 0, 0x00, 0x101 }, 4843452d642SJianwei Zheng .con3_for_pcie = { 0x4800c, 15, 0, 0x00, 0x0200 }, 4853452d642SJianwei Zheng /* pipe-grf */ 48614d5da7dSwilliam.wu .u3otg0_pipe_clk_sel = { 0x40044, 7, 7, 0x01, 0x00 }, 4873452d642SJianwei Zheng .u3otg0_port_en = { 0x40044, 15, 0, 0x0181, 0x1100 }, 4883452d642SJianwei Zheng }; 4893452d642SJianwei Zheng 4903452d642SJianwei Zheng static const struct rockchip_combphy_cfg rk3528_combphy_cfgs = { 4913452d642SJianwei Zheng .grfcfg = &rk3528_combphy_grfcfgs, 4923452d642SJianwei Zheng .combphy_cfg = rk3528_combphy_cfg, 4933452d642SJianwei Zheng }; 494fc22f2adSWilliam Wu #endif 4953452d642SJianwei Zheng 496fc22f2adSWilliam Wu #ifdef CONFIG_ROCKCHIP_RK3562 497885c5d5dSFrank Wang static int rk3562_combphy_cfg(struct rockchip_combphy_priv *priv) 498885c5d5dSFrank Wang { 499885c5d5dSFrank Wang const struct rockchip_combphy_grfcfg *cfg = priv->cfg->grfcfg; 500885c5d5dSFrank Wang u32 val; 501885c5d5dSFrank Wang 502885c5d5dSFrank Wang switch (priv->mode) { 503885c5d5dSFrank Wang case PHY_TYPE_PCIE: 504885c5d5dSFrank Wang /* Set SSC downward spread spectrum */ 505885c5d5dSFrank Wang val = readl(priv->mmio + (0x1f << 2)); 506885c5d5dSFrank Wang val &= ~GENMASK(5, 4); 507885c5d5dSFrank Wang val |= 0x01 << 4; 508885c5d5dSFrank Wang writel(val, priv->mmio + 0x7c); 509885c5d5dSFrank Wang 510885c5d5dSFrank Wang param_write(priv->phy_grf, &cfg->con0_for_pcie, true); 511885c5d5dSFrank Wang param_write(priv->phy_grf, &cfg->con1_for_pcie, true); 512885c5d5dSFrank Wang param_write(priv->phy_grf, &cfg->con2_for_pcie, true); 513885c5d5dSFrank Wang param_write(priv->phy_grf, &cfg->con3_for_pcie, true); 514885c5d5dSFrank Wang break; 515885c5d5dSFrank Wang case PHY_TYPE_USB3: 516885c5d5dSFrank Wang /* Set SSC downward spread spectrum */ 517885c5d5dSFrank Wang val = readl(priv->mmio + (0x1f << 2)); 518885c5d5dSFrank Wang val &= ~GENMASK(5, 4); 519885c5d5dSFrank Wang val |= 0x01 << 4; 520885c5d5dSFrank Wang writel(val, priv->mmio + 0x7c); 521885c5d5dSFrank Wang 522885c5d5dSFrank Wang /* Enable adaptive CTLE for USB3.0 Rx */ 523885c5d5dSFrank Wang val = readl(priv->mmio + (0x0e << 2)); 524885c5d5dSFrank Wang val &= ~GENMASK(0, 0); 525885c5d5dSFrank Wang val |= 0x01; 526885c5d5dSFrank Wang writel(val, priv->mmio + (0x0e << 2)); 527885c5d5dSFrank Wang 528885c5d5dSFrank Wang /* Set PLL KVCO fine tuning signals */ 529885c5d5dSFrank Wang val = readl(priv->mmio + (0x20 << 2)); 530885c5d5dSFrank Wang val &= ~(0x7 << 2); 531885c5d5dSFrank Wang val |= 0x2 << 2; 532885c5d5dSFrank Wang writel(val, priv->mmio + (0x20 << 2)); 533885c5d5dSFrank Wang 534885c5d5dSFrank Wang /* Set PLL LPF R1 to su_trim[10:7]=1001 */ 535885c5d5dSFrank Wang writel(0x4, priv->mmio + (0xb << 2)); 536885c5d5dSFrank Wang 537885c5d5dSFrank Wang /* Set PLL input clock divider 1/2 */ 538885c5d5dSFrank Wang val = readl(priv->mmio + (0x5 << 2)); 539885c5d5dSFrank Wang val &= ~(0x3 << 6); 540885c5d5dSFrank Wang val |= 0x1 << 6; 541885c5d5dSFrank Wang writel(val, priv->mmio + (0x5 << 2)); 542885c5d5dSFrank Wang 543885c5d5dSFrank Wang /* Set PLL loop divider */ 544885c5d5dSFrank Wang writel(0x32, priv->mmio + (0x11 << 2)); 545885c5d5dSFrank Wang 546885c5d5dSFrank Wang /* Set PLL KVCO to min and set PLL charge pump current to max */ 547885c5d5dSFrank Wang writel(0xf0, priv->mmio + (0xa << 2)); 548885c5d5dSFrank Wang 549fc3847fcSWilliam Wu /* Set Rx squelch input filler bandwidth */ 550fc3847fcSWilliam Wu writel(0x0e, priv->mmio + (0x14 << 2)); 551fc3847fcSWilliam Wu 552885c5d5dSFrank Wang param_write(priv->phy_grf, &cfg->pipe_sel_usb, true); 553885c5d5dSFrank Wang param_write(priv->phy_grf, &cfg->pipe_txcomp_sel, false); 554885c5d5dSFrank Wang param_write(priv->phy_grf, &cfg->pipe_txelec_sel, false); 555885c5d5dSFrank Wang param_write(priv->phy_grf, &cfg->usb_mode_set, true); 556885c5d5dSFrank Wang break; 557885c5d5dSFrank Wang default: 558885c5d5dSFrank Wang pr_err("%s, phy-type %d\n", __func__, priv->mode); 559885c5d5dSFrank Wang return -EINVAL; 560885c5d5dSFrank Wang } 561885c5d5dSFrank Wang 562885c5d5dSFrank Wang clk_set_rate(&priv->ref_clk, 100000000); 563885c5d5dSFrank Wang param_write(priv->phy_grf, &cfg->pipe_clk_100m, true); 564885c5d5dSFrank Wang 565cc9876f4SJon Lin if (priv->mode == PHY_TYPE_PCIE) { 566cc9876f4SJon Lin /* PLL KVCO tuning fine */ 567cc9876f4SJon Lin val = readl(priv->mmio + (0x20 << 2)); 568cc9876f4SJon Lin val &= ~(0x7 << 2); 569cc9876f4SJon Lin val |= 0x2 << 2; 570cc9876f4SJon Lin writel(val, priv->mmio + (0x20 << 2)); 571cc9876f4SJon Lin 572cc9876f4SJon Lin /* Enable controlling random jitter, aka RMJ */ 573cc9876f4SJon Lin writel(0x4, priv->mmio + (0xb << 2)); 574cc9876f4SJon Lin 575cc9876f4SJon Lin val = readl(priv->mmio + (0x5 << 2)); 576cc9876f4SJon Lin val &= ~(0x3 << 6); 577cc9876f4SJon Lin val |= 0x1 << 6; 578cc9876f4SJon Lin writel(val, priv->mmio + (0x5 << 2)); 579cc9876f4SJon Lin 580cc9876f4SJon Lin writel(0x32, priv->mmio + (0x11 << 2)); 581cc9876f4SJon Lin writel(0xf0, priv->mmio + (0xa << 2)); 582cc9876f4SJon Lin } 583cc9876f4SJon Lin 5849bd901abSJon Lin if (dev_read_bool(priv->dev, "rockchip,ext-refclk")) { 5859bd901abSJon Lin param_write(priv->phy_grf, &cfg->pipe_clk_ext, true); 5869bd901abSJon Lin if (priv->mode == PHY_TYPE_PCIE) { 5879bd901abSJon Lin val = readl(priv->mmio + (0xc << 2)); 5889bd901abSJon Lin val |= 0x3 << 4 | 0x1 << 7; 5899bd901abSJon Lin writel(val, priv->mmio + (0xc << 2)); 5909bd901abSJon Lin 5919bd901abSJon Lin val = readl(priv->mmio + (0xd << 2)); 5929bd901abSJon Lin val |= 0x1; 5939bd901abSJon Lin writel(val, priv->mmio + (0xd << 2)); 5949bd901abSJon Lin } 5959bd901abSJon Lin } 5969bd901abSJon Lin 597885c5d5dSFrank Wang if (dev_read_bool(priv->dev, "rockchip,enable-ssc")) { 598885c5d5dSFrank Wang val = readl(priv->mmio + (0x7 << 2)); 599885c5d5dSFrank Wang val |= BIT(4); 600885c5d5dSFrank Wang writel(val, priv->mmio + (0x7 << 2)); 601885c5d5dSFrank Wang } 602885c5d5dSFrank Wang 603885c5d5dSFrank Wang return 0; 604885c5d5dSFrank Wang } 605885c5d5dSFrank Wang 606885c5d5dSFrank Wang static const struct rockchip_combphy_grfcfg rk3562_combphy_grfcfgs = { 607885c5d5dSFrank Wang /* pipe-phy-grf */ 608885c5d5dSFrank Wang .pcie_mode_set = { 0x0000, 5, 0, 0x00, 0x11 }, 609885c5d5dSFrank Wang .usb_mode_set = { 0x0000, 5, 0, 0x00, 0x04 }, 610885c5d5dSFrank Wang .pipe_rxterm_set = { 0x0000, 12, 12, 0x00, 0x01 }, 611885c5d5dSFrank Wang .pipe_txelec_set = { 0x0004, 1, 1, 0x00, 0x01 }, 612885c5d5dSFrank Wang .pipe_txcomp_set = { 0x0004, 4, 4, 0x00, 0x01 }, 613885c5d5dSFrank Wang .pipe_clk_25m = { 0x0004, 14, 13, 0x00, 0x01 }, 614885c5d5dSFrank Wang .pipe_clk_100m = { 0x0004, 14, 13, 0x00, 0x02 }, 615885c5d5dSFrank Wang .pipe_phymode_sel = { 0x0008, 1, 1, 0x00, 0x01 }, 616885c5d5dSFrank Wang .pipe_rate_sel = { 0x0008, 2, 2, 0x00, 0x01 }, 617885c5d5dSFrank Wang .pipe_rxterm_sel = { 0x0008, 8, 8, 0x00, 0x01 }, 618885c5d5dSFrank Wang .pipe_txelec_sel = { 0x0008, 12, 12, 0x00, 0x01 }, 619885c5d5dSFrank Wang .pipe_txcomp_sel = { 0x0008, 15, 15, 0x00, 0x01 }, 620885c5d5dSFrank Wang .pipe_clk_ext = { 0x000c, 9, 8, 0x02, 0x01 }, 621885c5d5dSFrank Wang .pipe_sel_usb = { 0x000c, 14, 13, 0x00, 0x01 }, 622885c5d5dSFrank Wang .pipe_phy_status = { 0x0034, 6, 6, 0x01, 0x00 }, 623885c5d5dSFrank Wang .con0_for_pcie = { 0x0000, 15, 0, 0x00, 0x1000 }, 624885c5d5dSFrank Wang .con1_for_pcie = { 0x0004, 15, 0, 0x00, 0x0000 }, 625885c5d5dSFrank Wang .con2_for_pcie = { 0x0008, 15, 0, 0x00, 0x0101 }, 626885c5d5dSFrank Wang .con3_for_pcie = { 0x000c, 15, 0, 0x00, 0x0200 }, 62786b316b4SFrank Wang .pipe_phy_grf_reset = { 0x0014, 1, 0, 0x3, 0x1 }, 628885c5d5dSFrank Wang /* pipe-grf */ 629885c5d5dSFrank Wang .u3otg0_port_en = { 0x0094, 15, 0, 0x0181, 0x1100 }, 630885c5d5dSFrank Wang }; 631885c5d5dSFrank Wang 632885c5d5dSFrank Wang static const struct rockchip_combphy_cfg rk3562_combphy_cfgs = { 633885c5d5dSFrank Wang .grfcfg = &rk3562_combphy_grfcfgs, 634885c5d5dSFrank Wang .combphy_cfg = rk3562_combphy_cfg, 635fb632bccSShawn Lin .force_det_out = true, 636885c5d5dSFrank Wang }; 637fc22f2adSWilliam Wu #endif 638885c5d5dSFrank Wang 639fc22f2adSWilliam Wu #ifdef CONFIG_ROCKCHIP_RK3568 640925c5749SYifeng Zhao static int rk3568_combphy_cfg(struct rockchip_combphy_priv *priv) 641925c5749SYifeng Zhao { 642925c5749SYifeng Zhao const struct rockchip_combphy_grfcfg *cfg = priv->cfg->grfcfg; 643925c5749SYifeng Zhao u32 val; 644925c5749SYifeng Zhao 645925c5749SYifeng Zhao switch (priv->mode) { 646925c5749SYifeng Zhao case PHY_TYPE_PCIE: 647925c5749SYifeng Zhao /* Set SSC downward spread spectrum */ 648925c5749SYifeng Zhao val = readl(priv->mmio + (0x1f << 2)); 649925c5749SYifeng Zhao val &= ~GENMASK(5, 4); 650925c5749SYifeng Zhao val |= 0x01 << 4; 651925c5749SYifeng Zhao writel(val, priv->mmio + 0x7c); 652925c5749SYifeng Zhao 653925c5749SYifeng Zhao param_write(priv->phy_grf, &cfg->con0_for_pcie, true); 654925c5749SYifeng Zhao param_write(priv->phy_grf, &cfg->con1_for_pcie, true); 655925c5749SYifeng Zhao param_write(priv->phy_grf, &cfg->con2_for_pcie, true); 656925c5749SYifeng Zhao param_write(priv->phy_grf, &cfg->con3_for_pcie, true); 657925c5749SYifeng Zhao break; 658925c5749SYifeng Zhao case PHY_TYPE_USB3: 659925c5749SYifeng Zhao /* Set SSC downward spread spectrum */ 660925c5749SYifeng Zhao val = readl(priv->mmio + (0x1f << 2)); 661925c5749SYifeng Zhao val &= ~GENMASK(5, 4); 662925c5749SYifeng Zhao val |= 0x01 << 4; 663925c5749SYifeng Zhao writel(val, priv->mmio + 0x7c); 664925c5749SYifeng Zhao 665925c5749SYifeng Zhao /* Enable adaptive CTLE for USB3.0 Rx */ 666925c5749SYifeng Zhao val = readl(priv->mmio + (0x0e << 2)); 667925c5749SYifeng Zhao val &= ~GENMASK(0, 0); 668925c5749SYifeng Zhao val |= 0x01; 669925c5749SYifeng Zhao writel(val, priv->mmio + (0x0e << 2)); 670925c5749SYifeng Zhao 671a0d03578SWilliam Wu /* Set PLL KVCO fine tuning signals */ 672a0d03578SWilliam Wu val = readl(priv->mmio + (0x20 << 2)); 673a0d03578SWilliam Wu val &= ~(0x7 << 2); 674a0d03578SWilliam Wu val |= 0x2 << 2; 675a0d03578SWilliam Wu writel(val, priv->mmio + (0x20 << 2)); 676a0d03578SWilliam Wu 677a0d03578SWilliam Wu /* Set PLL LPF R1 to su_trim[10:7]=1001 */ 678a0d03578SWilliam Wu writel(0x4, priv->mmio + (0xb << 2)); 679a0d03578SWilliam Wu 680a0d03578SWilliam Wu /* Set PLL input clock divider 1/2 */ 681a0d03578SWilliam Wu val = readl(priv->mmio + (0x5 << 2)); 682a0d03578SWilliam Wu val &= ~(0x3 << 6); 683a0d03578SWilliam Wu val |= 0x1 << 6; 684a0d03578SWilliam Wu writel(val, priv->mmio + (0x5 << 2)); 685a0d03578SWilliam Wu 686a0d03578SWilliam Wu /* Set PLL loop divider */ 687a0d03578SWilliam Wu writel(0x32, priv->mmio + (0x11 << 2)); 688a0d03578SWilliam Wu 689a0d03578SWilliam Wu /* Set PLL KVCO to min and set PLL charge pump current to max */ 690a0d03578SWilliam Wu writel(0xf0, priv->mmio + (0xa << 2)); 691a0d03578SWilliam Wu 692fc3847fcSWilliam Wu /* Set Rx squelch input filler bandwidth */ 693fc3847fcSWilliam Wu writel(0x0e, priv->mmio + (0x14 << 2)); 694fc3847fcSWilliam Wu 695925c5749SYifeng Zhao param_write(priv->phy_grf, &cfg->pipe_sel_usb, true); 696925c5749SYifeng Zhao param_write(priv->phy_grf, &cfg->pipe_txcomp_sel, false); 697925c5749SYifeng Zhao param_write(priv->phy_grf, &cfg->pipe_txelec_sel, false); 698925c5749SYifeng Zhao param_write(priv->phy_grf, &cfg->usb_mode_set, true); 699925c5749SYifeng Zhao break; 700925c5749SYifeng Zhao case PHY_TYPE_SATA: 701925c5749SYifeng Zhao writel(0x41, priv->mmio + 0x38); 702925c5749SYifeng Zhao writel(0x8F, priv->mmio + 0x18); 703925c5749SYifeng Zhao param_write(priv->phy_grf, &cfg->con0_for_sata, true); 704925c5749SYifeng Zhao param_write(priv->phy_grf, &cfg->con1_for_sata, true); 705925c5749SYifeng Zhao param_write(priv->phy_grf, &cfg->con2_for_sata, true); 706925c5749SYifeng Zhao param_write(priv->phy_grf, &cfg->con3_for_sata, true); 707925c5749SYifeng Zhao param_write(priv->pipe_grf, &cfg->pipe_con0_for_sata, true); 708925c5749SYifeng Zhao break; 709925c5749SYifeng Zhao case PHY_TYPE_SGMII: 710925c5749SYifeng Zhao param_write(priv->pipe_grf, &cfg->pipe_xpcs_phy_ready, true); 711925c5749SYifeng Zhao param_write(priv->phy_grf, &cfg->pipe_phymode_sel, true); 712925c5749SYifeng Zhao param_write(priv->phy_grf, &cfg->pipe_sel_qsgmii, true); 713925c5749SYifeng Zhao param_write(priv->phy_grf, &cfg->sgmii_mode_set, true); 714925c5749SYifeng Zhao break; 715925c5749SYifeng Zhao case PHY_TYPE_QSGMII: 716925c5749SYifeng Zhao param_write(priv->pipe_grf, &cfg->pipe_xpcs_phy_ready, true); 717925c5749SYifeng Zhao param_write(priv->phy_grf, &cfg->pipe_phymode_sel, true); 718925c5749SYifeng Zhao param_write(priv->phy_grf, &cfg->pipe_rate_sel, true); 719925c5749SYifeng Zhao param_write(priv->phy_grf, &cfg->pipe_sel_qsgmii, true); 720925c5749SYifeng Zhao param_write(priv->phy_grf, &cfg->qsgmii_mode_set, true); 721925c5749SYifeng Zhao break; 722925c5749SYifeng Zhao default: 723925c5749SYifeng Zhao pr_err("%s, phy-type %d\n", __func__, priv->mode); 724925c5749SYifeng Zhao return -EINVAL; 725925c5749SYifeng Zhao } 726925c5749SYifeng Zhao 727dbf89912SRen Jianing /* The default ref clock is 25Mhz */ 728dbf89912SRen Jianing param_write(priv->phy_grf, &cfg->pipe_clk_25m, true); 729925c5749SYifeng Zhao 730925c5749SYifeng Zhao if (dev_read_bool(priv->dev, "rockchip,enable-ssc")) { 731925c5749SYifeng Zhao val = readl(priv->mmio + (0x7 << 2)); 732925c5749SYifeng Zhao val |= BIT(4); 733925c5749SYifeng Zhao writel(val, priv->mmio + (0x7 << 2)); 734925c5749SYifeng Zhao } 735925c5749SYifeng Zhao 736925c5749SYifeng Zhao return 0; 737925c5749SYifeng Zhao } 738925c5749SYifeng Zhao 739925c5749SYifeng Zhao static const struct rockchip_combphy_grfcfg rk3568_combphy_grfcfgs = { 740925c5749SYifeng Zhao /* pipe-phy-grf */ 741925c5749SYifeng Zhao .pcie_mode_set = { 0x0000, 5, 0, 0x00, 0x11 }, 742925c5749SYifeng Zhao .usb_mode_set = { 0x0000, 5, 0, 0x00, 0x04 }, 743925c5749SYifeng Zhao .sgmii_mode_set = { 0x0000, 5, 0, 0x00, 0x01 }, 744925c5749SYifeng Zhao .qsgmii_mode_set = { 0x0000, 5, 0, 0x00, 0x21 }, 745925c5749SYifeng Zhao .pipe_rxterm_set = { 0x0000, 12, 12, 0x00, 0x01 }, 746925c5749SYifeng Zhao .pipe_txelec_set = { 0x0004, 1, 1, 0x00, 0x01 }, 747925c5749SYifeng Zhao .pipe_txcomp_set = { 0x0004, 4, 4, 0x00, 0x01 }, 748925c5749SYifeng Zhao .pipe_clk_25m = { 0x0004, 14, 13, 0x00, 0x01 }, 749925c5749SYifeng Zhao .pipe_clk_100m = { 0x0004, 14, 13, 0x00, 0x02 }, 750925c5749SYifeng Zhao .pipe_phymode_sel = { 0x0008, 1, 1, 0x00, 0x01 }, 751925c5749SYifeng Zhao .pipe_rate_sel = { 0x0008, 2, 2, 0x00, 0x01 }, 752925c5749SYifeng Zhao .pipe_rxterm_sel = { 0x0008, 8, 8, 0x00, 0x01 }, 753925c5749SYifeng Zhao .pipe_txelec_sel = { 0x0008, 12, 12, 0x00, 0x01 }, 754925c5749SYifeng Zhao .pipe_txcomp_sel = { 0x0008, 15, 15, 0x00, 0x01 }, 755925c5749SYifeng Zhao .pipe_clk_ext = { 0x000c, 9, 8, 0x02, 0x01 }, 756925c5749SYifeng Zhao .pipe_sel_usb = { 0x000c, 14, 13, 0x00, 0x01 }, 757925c5749SYifeng Zhao .pipe_sel_qsgmii = { 0x000c, 15, 13, 0x00, 0x07 }, 758925c5749SYifeng Zhao .pipe_phy_status = { 0x0034, 6, 6, 0x01, 0x00 }, 759925c5749SYifeng Zhao .con0_for_pcie = { 0x0000, 15, 0, 0x00, 0x1000 }, 760925c5749SYifeng Zhao .con1_for_pcie = { 0x0004, 15, 0, 0x00, 0x0000 }, 761925c5749SYifeng Zhao .con2_for_pcie = { 0x0008, 15, 0, 0x00, 0x0101 }, 762925c5749SYifeng Zhao .con3_for_pcie = { 0x000c, 15, 0, 0x00, 0x0200 }, 763925c5749SYifeng Zhao .con0_for_sata = { 0x0000, 15, 0, 0x00, 0x0119 }, 764925c5749SYifeng Zhao .con1_for_sata = { 0x0004, 15, 0, 0x00, 0x0040 }, 765925c5749SYifeng Zhao .con2_for_sata = { 0x0008, 15, 0, 0x00, 0x80c3 }, 766925c5749SYifeng Zhao .con3_for_sata = { 0x000c, 15, 0, 0x00, 0x4407 }, 767925c5749SYifeng Zhao /* pipe-grf */ 768925c5749SYifeng Zhao .pipe_con0_for_sata = { 0x0000, 15, 0, 0x00, 0x2220 }, 769925c5749SYifeng Zhao .pipe_sgmii_mac_sel = { 0x0040, 1, 1, 0x00, 0x01 }, 770925c5749SYifeng Zhao .pipe_xpcs_phy_ready = { 0x0040, 2, 2, 0x00, 0x01 }, 771925c5749SYifeng Zhao .u3otg0_port_en = { 0x0104, 15, 0, 0x0181, 0x1100 }, 772925c5749SYifeng Zhao .u3otg1_port_en = { 0x0144, 15, 0, 0x0181, 0x1100 }, 773925c5749SYifeng Zhao }; 774925c5749SYifeng Zhao 775925c5749SYifeng Zhao static const struct rockchip_combphy_cfg rk3568_combphy_cfgs = { 776925c5749SYifeng Zhao .grfcfg = &rk3568_combphy_grfcfgs, 777925c5749SYifeng Zhao .combphy_cfg = rk3568_combphy_cfg, 778fb632bccSShawn Lin .force_det_out = true, 779925c5749SYifeng Zhao }; 780fc22f2adSWilliam Wu #endif 781925c5749SYifeng Zhao 782fc22f2adSWilliam Wu #ifdef CONFIG_ROCKCHIP_RK3588 783cf3c44cbSJon Lin static int rk3588_combphy_cfg(struct rockchip_combphy_priv *priv) 784cf3c44cbSJon Lin { 785cf3c44cbSJon Lin const struct rockchip_combphy_grfcfg *cfg = priv->cfg->grfcfg; 786d8968f57SWilliam Wu u32 val; 787cf3c44cbSJon Lin 788cf3c44cbSJon Lin switch (priv->mode) { 789cf3c44cbSJon Lin case PHY_TYPE_PCIE: 790cf3c44cbSJon Lin param_write(priv->phy_grf, &cfg->con0_for_pcie, true); 791cf3c44cbSJon Lin param_write(priv->phy_grf, &cfg->con1_for_pcie, true); 792cf3c44cbSJon Lin param_write(priv->phy_grf, &cfg->con2_for_pcie, true); 793cf3c44cbSJon Lin param_write(priv->phy_grf, &cfg->con3_for_pcie, true); 794cf3c44cbSJon Lin break; 795cf3c44cbSJon Lin case PHY_TYPE_USB3: 796d8968f57SWilliam Wu /* Set SSC downward spread spectrum */ 797d8968f57SWilliam Wu val = readl(priv->mmio + (0x1f << 2)); 798d8968f57SWilliam Wu val &= ~GENMASK(5, 4); 799d8968f57SWilliam Wu val |= 0x01 << 4; 800d8968f57SWilliam Wu writel(val, priv->mmio + 0x7c); 801d8968f57SWilliam Wu 802d8968f57SWilliam Wu /* Enable adaptive CTLE for USB3.0 Rx */ 803d8968f57SWilliam Wu val = readl(priv->mmio + (0x0e << 2)); 804d8968f57SWilliam Wu val &= ~GENMASK(0, 0); 805d8968f57SWilliam Wu val |= 0x01; 806d8968f57SWilliam Wu writel(val, priv->mmio + (0x0e << 2)); 807d8968f57SWilliam Wu 808d8968f57SWilliam Wu /* Set PLL KVCO fine tuning signals */ 809d8968f57SWilliam Wu val = readl(priv->mmio + (0x20 << 2)); 810d8968f57SWilliam Wu val &= ~(0x7 << 2); 811d8968f57SWilliam Wu val |= 0x2 << 2; 812d8968f57SWilliam Wu writel(val, priv->mmio + (0x20 << 2)); 813d8968f57SWilliam Wu 814d8968f57SWilliam Wu /* Set PLL LPF R1 to su_trim[10:7]=1001 */ 815d8968f57SWilliam Wu writel(0x4, priv->mmio + (0xb << 2)); 816d8968f57SWilliam Wu 817d8968f57SWilliam Wu /* Set PLL input clock divider 1/2 */ 818d8968f57SWilliam Wu val = readl(priv->mmio + (0x5 << 2)); 819d8968f57SWilliam Wu val &= ~(0x3 << 6); 820d8968f57SWilliam Wu val |= 0x1 << 6; 821d8968f57SWilliam Wu writel(val, priv->mmio + (0x5 << 2)); 822d8968f57SWilliam Wu 823d8968f57SWilliam Wu /* Set PLL loop divider */ 824d8968f57SWilliam Wu writel(0x32, priv->mmio + (0x11 << 2)); 825d8968f57SWilliam Wu 826d8968f57SWilliam Wu /* Set PLL KVCO to min and set PLL charge pump current to max */ 827d8968f57SWilliam Wu writel(0xf0, priv->mmio + (0xa << 2)); 828d8968f57SWilliam Wu 82987bfcd06SWilliam Wu /* Set Rx squelch input filler bandwidth */ 83087bfcd06SWilliam Wu writel(0x0d, priv->mmio + (0x14 << 2)); 83187bfcd06SWilliam Wu 832cf3c44cbSJon Lin param_write(priv->phy_grf, &cfg->pipe_txcomp_sel, false); 833cf3c44cbSJon Lin param_write(priv->phy_grf, &cfg->pipe_txelec_sel, false); 834cf3c44cbSJon Lin param_write(priv->phy_grf, &cfg->usb_mode_set, true); 835cf3c44cbSJon Lin break; 836cf3c44cbSJon Lin case PHY_TYPE_SATA: 837418dd88dSYifeng Zhao /* Enable adaptive CTLE for SATA Rx */ 838418dd88dSYifeng Zhao val = readl(priv->mmio + (0x0e << 2)); 839418dd88dSYifeng Zhao val &= ~GENMASK(0, 0); 840418dd88dSYifeng Zhao val |= 0x01; 841418dd88dSYifeng Zhao writel(val, priv->mmio + (0x0e << 2)); 842418dd88dSYifeng Zhao /* Set tx_rterm = 50 ohm and rx_rterm = 43.5 ohm */ 843418dd88dSYifeng Zhao writel(0x8F, priv->mmio + (0x06 << 2)); 844418dd88dSYifeng Zhao 845cf3c44cbSJon Lin param_write(priv->phy_grf, &cfg->con0_for_sata, true); 846cf3c44cbSJon Lin param_write(priv->phy_grf, &cfg->con1_for_sata, true); 847cf3c44cbSJon Lin param_write(priv->phy_grf, &cfg->con2_for_sata, true); 848cf3c44cbSJon Lin param_write(priv->phy_grf, &cfg->con3_for_sata, true); 849cf3c44cbSJon Lin param_write(priv->pipe_grf, &cfg->pipe_con0_for_sata, true); 850cf3c44cbSJon Lin param_write(priv->pipe_grf, &cfg->pipe_con1_for_sata, true); 851cf3c44cbSJon Lin break; 852cf3c44cbSJon Lin case PHY_TYPE_SGMII: 853cf3c44cbSJon Lin case PHY_TYPE_QSGMII: 854cf3c44cbSJon Lin default: 855cf3c44cbSJon Lin dev_err(priv->dev, "incompatible PHY type\n"); 856cf3c44cbSJon Lin return -EINVAL; 857cf3c44cbSJon Lin } 858cf3c44cbSJon Lin 859c72d402cSJon Lin /* 100MHz refclock signal is good */ 860c72d402cSJon Lin clk_set_rate(&priv->ref_clk, 100000000); 861cf3c44cbSJon Lin param_write(priv->phy_grf, &cfg->pipe_clk_100m, true); 862e278c201SKever Yang if (priv->mode == PHY_TYPE_PCIE) { 863e278c201SKever Yang /* PLL KVCO tuning fine */ 864e278c201SKever Yang val = readl(priv->mmio + (0x20 << 2)); 865e278c201SKever Yang val &= ~GENMASK(4, 2); 866e278c201SKever Yang val |= 0x4 << 2; 867e278c201SKever Yang writel(val, priv->mmio + (0x20 << 2)); 868e278c201SKever Yang 869e278c201SKever Yang /* Set up rx_trim: PLL LPF C1 85pf R1 1.25kohm */ 870e278c201SKever Yang val = 0x4c; 871e278c201SKever Yang writel(val, priv->mmio + (0x1b << 2)); 872e278c201SKever Yang 873e278c201SKever Yang /* Set up su_trim: T3 */ 874e278c201SKever Yang val = 0xb0; 875e278c201SKever Yang writel(val, priv->mmio + (0xa << 2)); 876e278c201SKever Yang val = 0x47; 877e278c201SKever Yang writel(val, priv->mmio + (0xb << 2)); 878e278c201SKever Yang val = 0x57; 879e278c201SKever Yang writel(val, priv->mmio + (0xd << 2)); 880e278c201SKever Yang } 881cf3c44cbSJon Lin 882cf3c44cbSJon Lin return 0; 883cf3c44cbSJon Lin } 884cf3c44cbSJon Lin 885cf3c44cbSJon Lin static const struct rockchip_combphy_grfcfg rk3588_combphy_grfcfgs = { 886cf3c44cbSJon Lin /* pipe-phy-grf */ 887cf3c44cbSJon Lin .pcie_mode_set = { 0x0000, 5, 0, 0x00, 0x11 }, 888cf3c44cbSJon Lin .usb_mode_set = { 0x0000, 5, 0, 0x00, 0x04 }, 889cf3c44cbSJon Lin .pipe_rxterm_set = { 0x0000, 12, 12, 0x00, 0x01 }, 890cf3c44cbSJon Lin .pipe_txelec_set = { 0x0004, 1, 1, 0x00, 0x01 }, 891cf3c44cbSJon Lin .pipe_txcomp_set = { 0x0004, 4, 4, 0x00, 0x01 }, 892cf3c44cbSJon Lin .pipe_clk_25m = { 0x0004, 14, 13, 0x00, 0x01 }, 893cf3c44cbSJon Lin .pipe_clk_100m = { 0x0004, 14, 13, 0x00, 0x02 }, 894cf3c44cbSJon Lin .pipe_rxterm_sel = { 0x0008, 8, 8, 0x00, 0x01 }, 895cf3c44cbSJon Lin .pipe_txelec_sel = { 0x0008, 12, 12, 0x00, 0x01 }, 896cf3c44cbSJon Lin .pipe_txcomp_sel = { 0x0008, 15, 15, 0x00, 0x01 }, 897cf3c44cbSJon Lin .pipe_clk_ext = { 0x000c, 9, 8, 0x02, 0x01 }, 898cf3c44cbSJon Lin .pipe_phy_status = { 0x0034, 6, 6, 0x01, 0x00 }, 899cf3c44cbSJon Lin .con0_for_pcie = { 0x0000, 15, 0, 0x00, 0x1000 }, 900cf3c44cbSJon Lin .con1_for_pcie = { 0x0004, 15, 0, 0x00, 0x0000 }, 901cf3c44cbSJon Lin .con2_for_pcie = { 0x0008, 15, 0, 0x00, 0x0101 }, 902cf3c44cbSJon Lin .con3_for_pcie = { 0x000c, 15, 0, 0x00, 0x0200 }, 903cf3c44cbSJon Lin .con0_for_sata = { 0x0000, 15, 0, 0x00, 0x0129 }, 904418dd88dSYifeng Zhao .con1_for_sata = { 0x0004, 15, 0, 0x00, 0x0000 }, 905cf3c44cbSJon Lin .con2_for_sata = { 0x0008, 15, 0, 0x00, 0x80c1 }, 906cf3c44cbSJon Lin .con3_for_sata = { 0x000c, 15, 0, 0x00, 0x0407 }, 907cf3c44cbSJon Lin /* pipe-grf */ 908cf3c44cbSJon Lin .pipe_con0_for_sata = { 0x0000, 11, 5, 0x00, 0x22 }, 909cf3c44cbSJon Lin .pipe_con1_for_sata = { 0x0000, 2, 0, 0x00, 0x2 }, 910cf3c44cbSJon Lin }; 911cf3c44cbSJon Lin 912cf3c44cbSJon Lin static const struct rockchip_combphy_cfg rk3588_combphy_cfgs = { 913cf3c44cbSJon Lin .grfcfg = &rk3588_combphy_grfcfgs, 914cf3c44cbSJon Lin .combphy_cfg = rk3588_combphy_cfg, 915fb632bccSShawn Lin .force_det_out = true, 916cf3c44cbSJon Lin }; 917fc22f2adSWilliam Wu #endif 918cf3c44cbSJon Lin 9193f21b61aSJon Lin 9203f21b61aSJon Lin #ifdef CONFIG_ROCKCHIP_RK3576 9213f21b61aSJon Lin static int rk3576_combphy_cfg(struct rockchip_combphy_priv *priv) 9223f21b61aSJon Lin { 9233f21b61aSJon Lin const struct rockchip_combphy_grfcfg *cfg = priv->cfg->grfcfg; 9243f21b61aSJon Lin u32 val; 9253f21b61aSJon Lin 9263f21b61aSJon Lin switch (priv->mode) { 9273f21b61aSJon Lin case PHY_TYPE_PCIE: 9283f21b61aSJon Lin param_write(priv->phy_grf, &cfg->con0_for_pcie, true); 9293f21b61aSJon Lin param_write(priv->phy_grf, &cfg->con1_for_pcie, true); 9303f21b61aSJon Lin param_write(priv->phy_grf, &cfg->con2_for_pcie, true); 9313f21b61aSJon Lin param_write(priv->phy_grf, &cfg->con3_for_pcie, true); 9323f21b61aSJon Lin break; 9333f21b61aSJon Lin case PHY_TYPE_USB3: 9343f21b61aSJon Lin /* Set SSC downward spread spectrum */ 9353f21b61aSJon Lin val = readl(priv->mmio + (0x1f << 2)); 9363f21b61aSJon Lin val &= ~GENMASK(5, 4); 9373f21b61aSJon Lin val |= 0x01 << 4; 9383f21b61aSJon Lin writel(val, priv->mmio + 0x7c); 9393f21b61aSJon Lin 9403f21b61aSJon Lin /* Enable adaptive CTLE for USB3.0 Rx */ 9413f21b61aSJon Lin val = readl(priv->mmio + (0x0e << 2)); 9423f21b61aSJon Lin val &= ~GENMASK(0, 0); 9433f21b61aSJon Lin val |= 0x01; 9443f21b61aSJon Lin writel(val, priv->mmio + (0x0e << 2)); 9453f21b61aSJon Lin 9463f21b61aSJon Lin /* Set PLL KVCO fine tuning signals */ 9473f21b61aSJon Lin val = readl(priv->mmio + (0x20 << 2)); 9483f21b61aSJon Lin val &= ~(0x7 << 2); 9493f21b61aSJon Lin val |= 0x2 << 2; 9503f21b61aSJon Lin writel(val, priv->mmio + (0x20 << 2)); 9513f21b61aSJon Lin 9523f21b61aSJon Lin /* Set PLL LPF R1 to su_trim[10:7]=1001 */ 9533f21b61aSJon Lin writel(0x4, priv->mmio + (0xb << 2)); 9543f21b61aSJon Lin 9553f21b61aSJon Lin /* Set PLL input clock divider 1/2 */ 9563f21b61aSJon Lin val = readl(priv->mmio + (0x5 << 2)); 9573f21b61aSJon Lin val &= ~(0x3 << 6); 9583f21b61aSJon Lin val |= 0x1 << 6; 9593f21b61aSJon Lin writel(val, priv->mmio + (0x5 << 2)); 9603f21b61aSJon Lin 9613f21b61aSJon Lin /* Set PLL loop divider */ 9623f21b61aSJon Lin writel(0x32, priv->mmio + (0x11 << 2)); 9633f21b61aSJon Lin 9643f21b61aSJon Lin /* Set PLL KVCO to min and set PLL charge pump current to max */ 9653f21b61aSJon Lin writel(0xf0, priv->mmio + (0xa << 2)); 9663f21b61aSJon Lin 9673f21b61aSJon Lin /* Set Rx squelch input filler bandwidth */ 9683f21b61aSJon Lin writel(0x0d, priv->mmio + (0x14 << 2)); 9693f21b61aSJon Lin 9703f21b61aSJon Lin param_write(priv->phy_grf, &cfg->pipe_txcomp_sel, false); 9713f21b61aSJon Lin param_write(priv->phy_grf, &cfg->pipe_txelec_sel, false); 9723f21b61aSJon Lin param_write(priv->phy_grf, &cfg->usb_mode_set, true); 9733f21b61aSJon Lin break; 9743f21b61aSJon Lin case PHY_TYPE_SATA: 9753f21b61aSJon Lin /* Enable adaptive CTLE for SATA Rx */ 9763f21b61aSJon Lin val = readl(priv->mmio + (0x0e << 2)); 9773f21b61aSJon Lin val &= ~GENMASK(0, 0); 9783f21b61aSJon Lin val |= 0x01; 9793f21b61aSJon Lin writel(val, priv->mmio + (0x0e << 2)); 9803f21b61aSJon Lin /* Set tx_rterm = 50 ohm and rx_rterm = 43.5 ohm */ 9813f21b61aSJon Lin writel(0x8F, priv->mmio + (0x06 << 2)); 9823f21b61aSJon Lin 9833f21b61aSJon Lin param_write(priv->phy_grf, &cfg->con0_for_sata, true); 9843f21b61aSJon Lin param_write(priv->phy_grf, &cfg->con1_for_sata, true); 9853f21b61aSJon Lin param_write(priv->phy_grf, &cfg->con2_for_sata, true); 9863f21b61aSJon Lin param_write(priv->phy_grf, &cfg->con3_for_sata, true); 9873f21b61aSJon Lin param_write(priv->pipe_grf, &cfg->pipe_con0_for_sata, true); 9883f21b61aSJon Lin param_write(priv->pipe_grf, &cfg->pipe_con1_for_sata, true); 9893f21b61aSJon Lin break; 9903f21b61aSJon Lin case PHY_TYPE_SGMII: 9913f21b61aSJon Lin case PHY_TYPE_QSGMII: 9923f21b61aSJon Lin default: 9933f21b61aSJon Lin dev_err(priv->dev, "incompatible PHY type\n"); 9943f21b61aSJon Lin return -EINVAL; 9953f21b61aSJon Lin } 9963f21b61aSJon Lin 9973f21b61aSJon Lin /* 100MHz refclock signal is good */ 9983f21b61aSJon Lin clk_set_rate(&priv->ref_clk, 100000000); 9993f21b61aSJon Lin param_write(priv->phy_grf, &cfg->pipe_clk_100m, true); 10003f21b61aSJon Lin if (priv->mode == PHY_TYPE_PCIE) { 10013f21b61aSJon Lin /* gate_tx_pck_sel length select work for L1SS */ 10023f21b61aSJon Lin writel(0xc0, priv->mmio + 0x74); 10033f21b61aSJon Lin 10043f21b61aSJon Lin /* PLL KVCO tuning fine */ 10053f21b61aSJon Lin val = readl(priv->mmio + (0x20 << 2)); 10063f21b61aSJon Lin val &= ~(0x7 << 2); 10073f21b61aSJon Lin val |= 0x2 << 2; 10083f21b61aSJon Lin writel(val, priv->mmio + (0x20 << 2)); 10093f21b61aSJon Lin 10103f21b61aSJon Lin /* Set up rx_trim: PLL LPF C1 85pf R1 1.25kohm */ 10113f21b61aSJon Lin writel(0x4c, priv->mmio + (0x1b << 2)); 10123f21b61aSJon Lin 10133f21b61aSJon Lin /* Set up su_trim: T3_P1 650mv */ 10143f21b61aSJon Lin writel(0x90, priv->mmio + (0xa << 2)); 10153f21b61aSJon Lin writel(0x43, priv->mmio + (0xb << 2)); 10163f21b61aSJon Lin writel(0x88, priv->mmio + (0xc << 2)); 10173f21b61aSJon Lin writel(0x56, priv->mmio + (0xd << 2)); 10183f21b61aSJon Lin } 10193f21b61aSJon Lin 10203f21b61aSJon Lin return 0; 10213f21b61aSJon Lin } 10223f21b61aSJon Lin 10233f21b61aSJon Lin static const struct rockchip_combphy_grfcfg rk3576_combphy_grfcfgs = { 10243f21b61aSJon Lin /* pipe-phy-grf */ 10253f21b61aSJon Lin .pcie_mode_set = { 0x0000, 5, 0, 0x00, 0x11 }, 10263f21b61aSJon Lin .usb_mode_set = { 0x0000, 5, 0, 0x00, 0x04 }, 10273f21b61aSJon Lin .pipe_rxterm_set = { 0x0000, 12, 12, 0x00, 0x01 }, 10283f21b61aSJon Lin .pipe_txelec_set = { 0x0004, 1, 1, 0x00, 0x01 }, 10293f21b61aSJon Lin .pipe_txcomp_set = { 0x0004, 4, 4, 0x00, 0x01 }, 10303f21b61aSJon Lin .pipe_clk_24m = { 0x0004, 14, 13, 0x00, 0x00 }, 10313f21b61aSJon Lin .pipe_clk_25m = { 0x0004, 14, 13, 0x00, 0x01 }, 10323f21b61aSJon Lin .pipe_clk_100m = { 0x0004, 14, 13, 0x00, 0x02 }, 10333f21b61aSJon Lin .pipe_phymode_sel = { 0x0008, 1, 1, 0x00, 0x01 }, 10343f21b61aSJon Lin .pipe_rate_sel = { 0x0008, 2, 2, 0x00, 0x01 }, 10353f21b61aSJon Lin .pipe_rxterm_sel = { 0x0008, 8, 8, 0x00, 0x01 }, 10363f21b61aSJon Lin .pipe_txelec_sel = { 0x0008, 12, 12, 0x00, 0x01 }, 10373f21b61aSJon Lin .pipe_txcomp_sel = { 0x0008, 15, 15, 0x00, 0x01 }, 10383f21b61aSJon Lin .pipe_clk_ext = { 0x000c, 9, 8, 0x02, 0x01 }, 10393f21b61aSJon Lin .pipe_phy_status = { 0x0034, 6, 6, 0x01, 0x00 }, 10403f21b61aSJon Lin .con0_for_pcie = { 0x0000, 15, 0, 0x00, 0x1000 }, 10413f21b61aSJon Lin .con1_for_pcie = { 0x0004, 15, 0, 0x00, 0x0000 }, 10423f21b61aSJon Lin .con2_for_pcie = { 0x0008, 15, 0, 0x00, 0x0101 }, 10433f21b61aSJon Lin .con3_for_pcie = { 0x000c, 15, 0, 0x00, 0x0200 }, 10443f21b61aSJon Lin .con0_for_sata = { 0x0000, 15, 0, 0x00, 0x0129 }, 10453f21b61aSJon Lin .con1_for_sata = { 0x0004, 15, 0, 0x00, 0x0000 }, 10463f21b61aSJon Lin .con2_for_sata = { 0x0008, 15, 0, 0x00, 0x80c1 }, 10473f21b61aSJon Lin .con3_for_sata = { 0x000c, 15, 0, 0x00, 0x0407 }, 10483f21b61aSJon Lin .pipe_phy_grf_reset = { 0x0014, 1, 0, 0x3, 0x1 }, 10493f21b61aSJon Lin /* php-grf */ 10503f21b61aSJon Lin .pipe_con0_for_sata = { 0x001C, 2, 0, 0x00, 0x2 }, 10513f21b61aSJon Lin .pipe_con1_for_sata = { 0x0020, 2, 0, 0x00, 0x2 }, 10523f21b61aSJon Lin .u3otg1_port_en = { 0x0038, 15, 0, 0x0181, 0x1100 }, 10533f21b61aSJon Lin }; 10543f21b61aSJon Lin 10553f21b61aSJon Lin static const struct rockchip_combphy_cfg rk3576_combphy_cfgs = { 10563f21b61aSJon Lin .grfcfg = &rk3576_combphy_grfcfgs, 10573f21b61aSJon Lin .combphy_cfg = rk3576_combphy_cfg, 10583f21b61aSJon Lin }; 10593f21b61aSJon Lin #endif 10603f21b61aSJon Lin 1061*eed45787SFrank Wang #ifdef CONFIG_ROCKCHIP_RV1126B 1062*eed45787SFrank Wang static int rv1126b_combphy_cfg(struct rockchip_combphy_priv *priv) 1063*eed45787SFrank Wang { 1064*eed45787SFrank Wang const struct rockchip_combphy_grfcfg *cfg = priv->cfg->grfcfg; 1065*eed45787SFrank Wang u32 val; 1066*eed45787SFrank Wang 1067*eed45787SFrank Wang switch (priv->mode) { 1068*eed45787SFrank Wang case PHY_TYPE_USB3: 1069*eed45787SFrank Wang /* Set SSC downward spread spectrum */ 1070*eed45787SFrank Wang val = readl(priv->mmio + (0x1f << 2)); 1071*eed45787SFrank Wang val &= ~GENMASK(5, 4); 1072*eed45787SFrank Wang val |= 0x01 << 4; 1073*eed45787SFrank Wang writel(val, priv->mmio + 0x7c); 1074*eed45787SFrank Wang 1075*eed45787SFrank Wang /* Enable adaptive CTLE for USB3.0 Rx */ 1076*eed45787SFrank Wang val = readl(priv->mmio + (0x0e << 2)); 1077*eed45787SFrank Wang val &= ~GENMASK(0, 0); 1078*eed45787SFrank Wang val |= 0x01; 1079*eed45787SFrank Wang writel(val, priv->mmio + (0x0e << 2)); 1080*eed45787SFrank Wang 1081*eed45787SFrank Wang /* Set PLL KVCO fine tuning signals */ 1082*eed45787SFrank Wang val = readl(priv->mmio + (0x20 << 2)); 1083*eed45787SFrank Wang val &= ~(0x7 << 2); 1084*eed45787SFrank Wang val |= 0x2 << 2; 1085*eed45787SFrank Wang writel(val, priv->mmio + (0x20 << 2)); 1086*eed45787SFrank Wang 1087*eed45787SFrank Wang /* Set PLL LPF R1 to su_trim[10:7]=1001 */ 1088*eed45787SFrank Wang writel(0x4, priv->mmio + (0x0b << 2)); 1089*eed45787SFrank Wang 1090*eed45787SFrank Wang /* Set PLL input clock divider 1/2 */ 1091*eed45787SFrank Wang val = readl(priv->mmio + (0x5 << 2)); 1092*eed45787SFrank Wang val &= ~(0x3 << 6); 1093*eed45787SFrank Wang val |= 0x1 << 6; 1094*eed45787SFrank Wang writel(val, priv->mmio + (0x5 << 2)); 1095*eed45787SFrank Wang 1096*eed45787SFrank Wang /* Set PLL loop divider */ 1097*eed45787SFrank Wang writel(0x32, priv->mmio + (0x11 << 2)); 1098*eed45787SFrank Wang 1099*eed45787SFrank Wang /* Set PLL KVCO to min and set PLL charge pump current to max */ 1100*eed45787SFrank Wang writel(0xf0, priv->mmio + (0x0a << 2)); 1101*eed45787SFrank Wang 1102*eed45787SFrank Wang /* Set Rx squelch input filler bandwidth */ 1103*eed45787SFrank Wang writel(0x0e, priv->mmio + (0x14 << 2)); 1104*eed45787SFrank Wang 1105*eed45787SFrank Wang param_write(priv->phy_grf, &cfg->pipe_sel_usb, true); 1106*eed45787SFrank Wang param_write(priv->phy_grf, &cfg->pipe_txcomp_sel, false); 1107*eed45787SFrank Wang param_write(priv->phy_grf, &cfg->pipe_txelec_sel, false); 1108*eed45787SFrank Wang param_write(priv->phy_grf, &cfg->usb_mode_set, true); 1109*eed45787SFrank Wang break; 1110*eed45787SFrank Wang default: 1111*eed45787SFrank Wang dev_err(priv->dev, "incompatible PHY type\n"); 1112*eed45787SFrank Wang return -EINVAL; 1113*eed45787SFrank Wang } 1114*eed45787SFrank Wang 1115*eed45787SFrank Wang clk_set_rate(&priv->ref_clk, 100000000); 1116*eed45787SFrank Wang param_write(priv->phy_grf, &cfg->pipe_clk_100m, true); 1117*eed45787SFrank Wang 1118*eed45787SFrank Wang return 0; 1119*eed45787SFrank Wang } 1120*eed45787SFrank Wang 1121*eed45787SFrank Wang static const struct rockchip_combphy_grfcfg rv1126b_combphy_grfcfgs = { 1122*eed45787SFrank Wang /* pipe-phy-grf */ 1123*eed45787SFrank Wang .usb_mode_set = { 0x18000, 5, 0, 0x00, 0x04 }, 1124*eed45787SFrank Wang .pipe_rxterm_set = { 0x18000, 12, 12, 0x00, 0x01 }, 1125*eed45787SFrank Wang .pipe_txelec_set = { 0x18004, 1, 1, 0x00, 0x01 }, 1126*eed45787SFrank Wang .pipe_txcomp_set = { 0x18004, 4, 4, 0x00, 0x01 }, 1127*eed45787SFrank Wang .pipe_clk_25m = { 0x18004, 14, 13, 0x00, 0x01 }, 1128*eed45787SFrank Wang .pipe_clk_100m = { 0x18004, 14, 13, 0x00, 0x02 }, 1129*eed45787SFrank Wang .pipe_phymode_sel = { 0x18008, 1, 1, 0x00, 0x01 }, 1130*eed45787SFrank Wang .pipe_rate_sel = { 0x18008, 2, 2, 0x00, 0x01 }, 1131*eed45787SFrank Wang .pipe_rxterm_sel = { 0x18008, 8, 8, 0x00, 0x01 }, 1132*eed45787SFrank Wang .pipe_txelec_sel = { 0x18008, 12, 12, 0x00, 0x01 }, 1133*eed45787SFrank Wang .pipe_txcomp_sel = { 0x18008, 15, 15, 0x00, 0x01 }, 1134*eed45787SFrank Wang .pipe_clk_ext = { 0x1800c, 9, 8, 0x02, 0x01 }, 1135*eed45787SFrank Wang .pipe_sel_usb = { 0x1800c, 14, 13, 0x00, 0x01 }, 1136*eed45787SFrank Wang .pipe_phy_status = { 0x18034, 6, 6, 0x01, 0x00 }, 1137*eed45787SFrank Wang /* peri-grf */ 1138*eed45787SFrank Wang .u3otg0_port_en = { 0x1003c, 15, 0, 0x0189, 0x1100 }, 1139*eed45787SFrank Wang }; 1140*eed45787SFrank Wang 1141*eed45787SFrank Wang static const struct rockchip_combphy_cfg rv1126b_combphy_cfgs = { 1142*eed45787SFrank Wang .grfcfg = &rv1126b_combphy_grfcfgs, 1143*eed45787SFrank Wang .combphy_cfg = rv1126b_combphy_cfg, 1144*eed45787SFrank Wang .force_det_out = true, 1145*eed45787SFrank Wang }; 1146*eed45787SFrank Wang #endif 1147*eed45787SFrank Wang 1148925c5749SYifeng Zhao static const struct udevice_id rockchip_combphy_ids[] = { 1149fc22f2adSWilliam Wu #ifdef CONFIG_ROCKCHIP_RK3528 1150925c5749SYifeng Zhao { 11513452d642SJianwei Zheng .compatible = "rockchip,rk3528-naneng-combphy", 11523452d642SJianwei Zheng .data = (ulong)&rk3528_combphy_cfgs 11533452d642SJianwei Zheng }, 1154fc22f2adSWilliam Wu #endif 1155fc22f2adSWilliam Wu #ifdef CONFIG_ROCKCHIP_RK3562 11563452d642SJianwei Zheng { 1157885c5d5dSFrank Wang .compatible = "rockchip,rk3562-naneng-combphy", 1158885c5d5dSFrank Wang .data = (ulong)&rk3562_combphy_cfgs 1159885c5d5dSFrank Wang }, 1160fc22f2adSWilliam Wu #endif 1161fc22f2adSWilliam Wu #ifdef CONFIG_ROCKCHIP_RK3568 1162885c5d5dSFrank Wang { 1163925c5749SYifeng Zhao .compatible = "rockchip,rk3568-naneng-combphy", 1164925c5749SYifeng Zhao .data = (ulong)&rk3568_combphy_cfgs 1165925c5749SYifeng Zhao }, 1166fc22f2adSWilliam Wu #endif 1167fc22f2adSWilliam Wu #ifdef CONFIG_ROCKCHIP_RK3588 1168cf3c44cbSJon Lin { 1169cf3c44cbSJon Lin .compatible = "rockchip,rk3588-naneng-combphy", 1170cf3c44cbSJon Lin .data = (ulong)&rk3588_combphy_cfgs 1171cf3c44cbSJon Lin }, 1172fc22f2adSWilliam Wu #endif 11733f21b61aSJon Lin #ifdef CONFIG_ROCKCHIP_RK3576 11743f21b61aSJon Lin { 11753f21b61aSJon Lin .compatible = "rockchip,rk3576-naneng-combphy", 11763f21b61aSJon Lin .data = (ulong)&rk3576_combphy_cfgs 11773f21b61aSJon Lin }, 11783f21b61aSJon Lin #endif 1179*eed45787SFrank Wang #ifdef CONFIG_ROCKCHIP_RV1126B 1180*eed45787SFrank Wang { 1181*eed45787SFrank Wang .compatible = "rockchip,rv1126b-usb3-phy", 1182*eed45787SFrank Wang .data = (ulong)&rv1126b_combphy_cfgs 1183*eed45787SFrank Wang }, 1184*eed45787SFrank Wang #endif 1185925c5749SYifeng Zhao { } 1186925c5749SYifeng Zhao }; 1187925c5749SYifeng Zhao 1188925c5749SYifeng Zhao U_BOOT_DRIVER(rockchip_naneng_combphy) = { 1189925c5749SYifeng Zhao .name = "naneng-combphy", 1190925c5749SYifeng Zhao .id = UCLASS_PHY, 1191925c5749SYifeng Zhao .of_match = rockchip_combphy_ids, 1192925c5749SYifeng Zhao .ops = &rochchip_combphy_ops, 1193925c5749SYifeng Zhao .probe = rockchip_combphy_probe, 1194925c5749SYifeng Zhao .priv_auto_alloc_size = sizeof(struct rockchip_combphy_priv), 1195925c5749SYifeng Zhao }; 1196