1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Rockchip USB3.0/PCIe Gen2/SATA/SGMII combphy driver 4 * 5 * Copyright (C) 2021 Rockchip Electronics Co., Ltd. 6 */ 7 8 #include <common.h> 9 #include <clk.h> 10 #include <dm.h> 11 #include <dm/lists.h> 12 #include <dt-bindings/phy/phy.h> 13 #include <generic-phy.h> 14 #include <syscon.h> 15 #include <asm/io.h> 16 #include <asm/arch/clock.h> 17 #include <regmap.h> 18 #include <reset-uclass.h> 19 20 #define BIT_WRITEABLE_SHIFT 16 21 22 struct rockchip_combphy_priv; 23 24 struct combphy_reg { 25 u16 offset; 26 u16 bitend; 27 u16 bitstart; 28 u16 disable; 29 u16 enable; 30 }; 31 32 struct rockchip_combphy_grfcfg { 33 struct combphy_reg pcie_mode_set; 34 struct combphy_reg usb_mode_set; 35 struct combphy_reg sgmii_mode_set; 36 struct combphy_reg qsgmii_mode_set; 37 struct combphy_reg pipe_rxterm_set; 38 struct combphy_reg pipe_txelec_set; 39 struct combphy_reg pipe_txcomp_set; 40 struct combphy_reg pipe_clk_25m; 41 struct combphy_reg pipe_clk_100m; 42 struct combphy_reg pipe_phymode_sel; 43 struct combphy_reg pipe_rate_sel; 44 struct combphy_reg pipe_rxterm_sel; 45 struct combphy_reg pipe_txelec_sel; 46 struct combphy_reg pipe_txcomp_sel; 47 struct combphy_reg pipe_clk_ext; 48 struct combphy_reg pipe_sel_usb; 49 struct combphy_reg pipe_sel_qsgmii; 50 struct combphy_reg pipe_phy_status; 51 struct combphy_reg con0_for_pcie; 52 struct combphy_reg con1_for_pcie; 53 struct combphy_reg con2_for_pcie; 54 struct combphy_reg con3_for_pcie; 55 struct combphy_reg con0_for_sata; 56 struct combphy_reg con1_for_sata; 57 struct combphy_reg con2_for_sata; 58 struct combphy_reg con3_for_sata; 59 struct combphy_reg pipe_con0_for_sata; 60 struct combphy_reg pipe_sgmii_mac_sel; 61 struct combphy_reg pipe_xpcs_phy_ready; 62 struct combphy_reg u3otg0_port_en; 63 struct combphy_reg u3otg1_port_en; 64 }; 65 66 struct rockchip_combphy_cfg { 67 const struct rockchip_combphy_grfcfg *grfcfg; 68 int (*combphy_cfg)(struct rockchip_combphy_priv *priv); 69 }; 70 71 struct rockchip_combphy_priv { 72 u32 mode; 73 void __iomem *mmio; 74 struct udevice *dev; 75 struct regmap *pipe_grf; 76 struct regmap *phy_grf; 77 struct phy *phy; 78 struct reset_ctl phy_rst; 79 struct clk ref_clk; 80 const struct rockchip_combphy_cfg *cfg; 81 }; 82 83 static int param_write(struct regmap *base, 84 const struct combphy_reg *reg, bool en) 85 { 86 u32 val, mask, tmp; 87 88 tmp = en ? reg->enable : reg->disable; 89 mask = GENMASK(reg->bitend, reg->bitstart); 90 val = (tmp << reg->bitstart) | (mask << BIT_WRITEABLE_SHIFT); 91 92 return regmap_write(base, reg->offset, val); 93 } 94 95 static int rockchip_combphy_pcie_init(struct rockchip_combphy_priv *priv) 96 { 97 int ret = 0; 98 99 if (priv->cfg->combphy_cfg) { 100 ret = priv->cfg->combphy_cfg(priv); 101 if (ret) { 102 dev_err(priv->dev, "failed to init phy for pcie\n"); 103 return ret; 104 } 105 } 106 107 return ret; 108 } 109 110 static int rockchip_combphy_usb3_init(struct rockchip_combphy_priv *priv) 111 { 112 int ret = 0; 113 114 if (priv->cfg->combphy_cfg) { 115 ret = priv->cfg->combphy_cfg(priv); 116 if (ret) { 117 dev_err(priv->dev, "failed to init phy for usb3\n"); 118 return ret; 119 } 120 } 121 122 return ret; 123 } 124 125 static int rockchip_combphy_sata_init(struct rockchip_combphy_priv *priv) 126 { 127 int ret = 0; 128 129 if (priv->cfg->combphy_cfg) { 130 ret = priv->cfg->combphy_cfg(priv); 131 if (ret) { 132 dev_err(priv->dev, "failed to init phy for sata\n"); 133 return ret; 134 } 135 } 136 137 return ret; 138 } 139 140 static int rockchip_combphy_sgmii_init(struct rockchip_combphy_priv *priv) 141 { 142 int ret = 0; 143 144 if (priv->cfg->combphy_cfg) { 145 ret = priv->cfg->combphy_cfg(priv); 146 if (ret) { 147 dev_err(priv->dev, "failed to init phy for sgmii\n"); 148 return ret; 149 } 150 } 151 152 return ret; 153 } 154 155 static int rockchip_combphy_set_mode(struct rockchip_combphy_priv *priv) 156 { 157 switch (priv->mode) { 158 case PHY_TYPE_PCIE: 159 rockchip_combphy_pcie_init(priv); 160 break; 161 case PHY_TYPE_USB3: 162 rockchip_combphy_usb3_init(priv); 163 break; 164 case PHY_TYPE_SATA: 165 rockchip_combphy_sata_init(priv); 166 break; 167 case PHY_TYPE_SGMII: 168 case PHY_TYPE_QSGMII: 169 return rockchip_combphy_sgmii_init(priv); 170 default: 171 dev_err(priv->dev, "incompatible PHY type\n"); 172 return -EINVAL; 173 } 174 175 return 0; 176 } 177 178 static int rockchip_combphy_init(struct phy *phy) 179 { 180 struct rockchip_combphy_priv *priv = dev_get_priv(phy->dev); 181 int ret; 182 183 ret = clk_enable(&priv->ref_clk); 184 if (ret < 0 && ret != -ENOSYS) 185 return ret; 186 187 ret = rockchip_combphy_set_mode(priv); 188 if (ret) 189 goto err_clk; 190 191 reset_deassert(&priv->phy_rst); 192 193 return 0; 194 195 err_clk: 196 clk_disable(&priv->ref_clk); 197 198 return ret; 199 } 200 201 static int rockchip_combphy_exit(struct phy *phy) 202 { 203 struct rockchip_combphy_priv *priv = dev_get_priv(phy->dev); 204 205 clk_disable(&priv->ref_clk); 206 reset_assert(&priv->phy_rst); 207 208 return 0; 209 } 210 211 static int rockchip_combphy_xlate(struct phy *phy, struct ofnode_phandle_args *args) 212 { 213 struct rockchip_combphy_priv *priv = dev_get_priv(phy->dev); 214 215 if (args->args_count != 1) { 216 pr_err("invalid number of arguments\n"); 217 return -EINVAL; 218 } 219 220 priv->mode = args->args[0]; 221 222 return 0; 223 } 224 225 static const struct phy_ops rochchip_combphy_ops = { 226 .init = rockchip_combphy_init, 227 .exit = rockchip_combphy_exit, 228 .of_xlate = rockchip_combphy_xlate, 229 }; 230 231 static int rockchip_combphy_parse_dt(struct udevice *dev, 232 struct rockchip_combphy_priv *priv) 233 { 234 struct udevice *syscon; 235 int ret; 236 237 ret = uclass_get_device_by_phandle(UCLASS_SYSCON, dev, "rockchip,pipe-grf", &syscon); 238 if (ret) { 239 dev_err(dev, "failed to find peri_ctrl pipe-grf regmap"); 240 return ret; 241 } 242 priv->pipe_grf = syscon_get_regmap(syscon); 243 244 ret = uclass_get_device_by_phandle(UCLASS_SYSCON, dev, "rockchip,pipe-phy-grf", &syscon); 245 if (ret) { 246 dev_err(dev, "failed to find peri_ctrl pipe-phy-grf regmap\n"); 247 return ret; 248 } 249 priv->phy_grf = syscon_get_regmap(syscon); 250 251 ret = clk_get_by_index(dev, 0, &priv->ref_clk); 252 if (ret) { 253 dev_err(dev, "failed to find ref clock\n"); 254 return PTR_ERR(&priv->ref_clk); 255 } 256 257 ret = reset_get_by_name(dev, "combphy", &priv->phy_rst); 258 if (ret) { 259 dev_err(dev, "no phy reset control specified\n"); 260 return ret; 261 } 262 263 return 0; 264 } 265 266 static int rockchip_combphy_probe(struct udevice *udev) 267 { 268 struct rockchip_combphy_priv *priv = dev_get_priv(udev); 269 const struct rockchip_combphy_cfg *phy_cfg; 270 int ret; 271 272 priv->mmio = (void __iomem *)dev_read_addr(udev); 273 if (IS_ERR(priv->mmio)) 274 return PTR_ERR(priv->mmio); 275 276 phy_cfg = (const struct rockchip_combphy_cfg *)dev_get_driver_data(udev); 277 if (!phy_cfg) { 278 dev_err(udev, "No OF match data provided\n"); 279 return -EINVAL; 280 } 281 282 priv->dev = udev; 283 priv->mode = PHY_TYPE_SATA; 284 priv->cfg = phy_cfg; 285 286 ret = rockchip_combphy_parse_dt(udev, priv); 287 if (ret) 288 return ret; 289 290 ret = rockchip_combphy_set_mode(priv); 291 292 return ret; 293 } 294 295 static int rk3568_combphy_cfg(struct rockchip_combphy_priv *priv) 296 { 297 const struct rockchip_combphy_grfcfg *cfg = priv->cfg->grfcfg; 298 u32 val; 299 300 switch (priv->mode) { 301 case PHY_TYPE_PCIE: 302 /* Set SSC downward spread spectrum */ 303 val = readl(priv->mmio + (0x1f << 2)); 304 val &= ~GENMASK(5, 4); 305 val |= 0x01 << 4; 306 writel(val, priv->mmio + 0x7c); 307 308 param_write(priv->phy_grf, &cfg->con0_for_pcie, true); 309 param_write(priv->phy_grf, &cfg->con1_for_pcie, true); 310 param_write(priv->phy_grf, &cfg->con2_for_pcie, true); 311 param_write(priv->phy_grf, &cfg->con3_for_pcie, true); 312 break; 313 case PHY_TYPE_USB3: 314 /* Set SSC downward spread spectrum */ 315 val = readl(priv->mmio + (0x1f << 2)); 316 val &= ~GENMASK(5, 4); 317 val |= 0x01 << 4; 318 writel(val, priv->mmio + 0x7c); 319 320 /* Enable adaptive CTLE for USB3.0 Rx */ 321 val = readl(priv->mmio + (0x0e << 2)); 322 val &= ~GENMASK(0, 0); 323 val |= 0x01; 324 writel(val, priv->mmio + (0x0e << 2)); 325 326 param_write(priv->phy_grf, &cfg->pipe_sel_usb, true); 327 param_write(priv->phy_grf, &cfg->pipe_txcomp_sel, false); 328 param_write(priv->phy_grf, &cfg->pipe_txelec_sel, false); 329 param_write(priv->phy_grf, &cfg->usb_mode_set, true); 330 break; 331 case PHY_TYPE_SATA: 332 writel(0x41, priv->mmio + 0x38); 333 writel(0x8F, priv->mmio + 0x18); 334 param_write(priv->phy_grf, &cfg->con0_for_sata, true); 335 param_write(priv->phy_grf, &cfg->con1_for_sata, true); 336 param_write(priv->phy_grf, &cfg->con2_for_sata, true); 337 param_write(priv->phy_grf, &cfg->con3_for_sata, true); 338 param_write(priv->pipe_grf, &cfg->pipe_con0_for_sata, true); 339 break; 340 case PHY_TYPE_SGMII: 341 param_write(priv->pipe_grf, &cfg->pipe_xpcs_phy_ready, true); 342 param_write(priv->phy_grf, &cfg->pipe_phymode_sel, true); 343 param_write(priv->phy_grf, &cfg->pipe_sel_qsgmii, true); 344 param_write(priv->phy_grf, &cfg->sgmii_mode_set, true); 345 break; 346 case PHY_TYPE_QSGMII: 347 param_write(priv->pipe_grf, &cfg->pipe_xpcs_phy_ready, true); 348 param_write(priv->phy_grf, &cfg->pipe_phymode_sel, true); 349 param_write(priv->phy_grf, &cfg->pipe_rate_sel, true); 350 param_write(priv->phy_grf, &cfg->pipe_sel_qsgmii, true); 351 param_write(priv->phy_grf, &cfg->qsgmii_mode_set, true); 352 break; 353 default: 354 pr_err("%s, phy-type %d\n", __func__, priv->mode); 355 return -EINVAL; 356 } 357 358 /* The default ref clock is 25Mhz */ 359 param_write(priv->phy_grf, &cfg->pipe_clk_25m, true); 360 361 if (dev_read_bool(priv->dev, "rockchip,enable-ssc")) { 362 val = readl(priv->mmio + (0x7 << 2)); 363 val |= BIT(4); 364 writel(val, priv->mmio + (0x7 << 2)); 365 } 366 367 return 0; 368 } 369 370 static const struct rockchip_combphy_grfcfg rk3568_combphy_grfcfgs = { 371 /* pipe-phy-grf */ 372 .pcie_mode_set = { 0x0000, 5, 0, 0x00, 0x11 }, 373 .usb_mode_set = { 0x0000, 5, 0, 0x00, 0x04 }, 374 .sgmii_mode_set = { 0x0000, 5, 0, 0x00, 0x01 }, 375 .qsgmii_mode_set = { 0x0000, 5, 0, 0x00, 0x21 }, 376 .pipe_rxterm_set = { 0x0000, 12, 12, 0x00, 0x01 }, 377 .pipe_txelec_set = { 0x0004, 1, 1, 0x00, 0x01 }, 378 .pipe_txcomp_set = { 0x0004, 4, 4, 0x00, 0x01 }, 379 .pipe_clk_25m = { 0x0004, 14, 13, 0x00, 0x01 }, 380 .pipe_clk_100m = { 0x0004, 14, 13, 0x00, 0x02 }, 381 .pipe_phymode_sel = { 0x0008, 1, 1, 0x00, 0x01 }, 382 .pipe_rate_sel = { 0x0008, 2, 2, 0x00, 0x01 }, 383 .pipe_rxterm_sel = { 0x0008, 8, 8, 0x00, 0x01 }, 384 .pipe_txelec_sel = { 0x0008, 12, 12, 0x00, 0x01 }, 385 .pipe_txcomp_sel = { 0x0008, 15, 15, 0x00, 0x01 }, 386 .pipe_clk_ext = { 0x000c, 9, 8, 0x02, 0x01 }, 387 .pipe_sel_usb = { 0x000c, 14, 13, 0x00, 0x01 }, 388 .pipe_sel_qsgmii = { 0x000c, 15, 13, 0x00, 0x07 }, 389 .pipe_phy_status = { 0x0034, 6, 6, 0x01, 0x00 }, 390 .con0_for_pcie = { 0x0000, 15, 0, 0x00, 0x1000 }, 391 .con1_for_pcie = { 0x0004, 15, 0, 0x00, 0x0000 }, 392 .con2_for_pcie = { 0x0008, 15, 0, 0x00, 0x0101 }, 393 .con3_for_pcie = { 0x000c, 15, 0, 0x00, 0x0200 }, 394 .con0_for_sata = { 0x0000, 15, 0, 0x00, 0x0119 }, 395 .con1_for_sata = { 0x0004, 15, 0, 0x00, 0x0040 }, 396 .con2_for_sata = { 0x0008, 15, 0, 0x00, 0x80c3 }, 397 .con3_for_sata = { 0x000c, 15, 0, 0x00, 0x4407 }, 398 /* pipe-grf */ 399 .pipe_con0_for_sata = { 0x0000, 15, 0, 0x00, 0x2220 }, 400 .pipe_sgmii_mac_sel = { 0x0040, 1, 1, 0x00, 0x01 }, 401 .pipe_xpcs_phy_ready = { 0x0040, 2, 2, 0x00, 0x01 }, 402 .u3otg0_port_en = { 0x0104, 15, 0, 0x0181, 0x1100 }, 403 .u3otg1_port_en = { 0x0144, 15, 0, 0x0181, 0x1100 }, 404 }; 405 406 static const struct rockchip_combphy_cfg rk3568_combphy_cfgs = { 407 .grfcfg = &rk3568_combphy_grfcfgs, 408 .combphy_cfg = rk3568_combphy_cfg, 409 }; 410 411 static const struct udevice_id rockchip_combphy_ids[] = { 412 { 413 .compatible = "rockchip,rk3568-naneng-combphy", 414 .data = (ulong)&rk3568_combphy_cfgs 415 }, 416 { } 417 }; 418 419 U_BOOT_DRIVER(rockchip_naneng_combphy) = { 420 .name = "naneng-combphy", 421 .id = UCLASS_PHY, 422 .of_match = rockchip_combphy_ids, 423 .ops = &rochchip_combphy_ops, 424 .probe = rockchip_combphy_probe, 425 .priv_auto_alloc_size = sizeof(struct rockchip_combphy_priv), 426 }; 427