1*7160820dSYifeng Zhao // SPDX-License-Identifier: GPL-2.0 2*7160820dSYifeng Zhao /* 3*7160820dSYifeng Zhao * Rockchip PIPE USB3.0 PCIE SATA Combo Phy driver 4*7160820dSYifeng Zhao * 5*7160820dSYifeng Zhao * Copyright (C) 2021 Rockchip Electronics Co., Ltd. 6*7160820dSYifeng Zhao */ 7*7160820dSYifeng Zhao 8*7160820dSYifeng Zhao #include <dt-bindings/phy/phy.h> 9*7160820dSYifeng Zhao #include <linux/clk.h> 10*7160820dSYifeng Zhao #include <linux/mfd/syscon.h> 11*7160820dSYifeng Zhao #include <linux/of_device.h> 12*7160820dSYifeng Zhao #include <linux/phy/phy.h> 13*7160820dSYifeng Zhao #include <linux/regmap.h> 14*7160820dSYifeng Zhao #include <linux/reset.h> 15*7160820dSYifeng Zhao #include <linux/units.h> 16*7160820dSYifeng Zhao 17*7160820dSYifeng Zhao #define BIT_WRITEABLE_SHIFT 16 18*7160820dSYifeng Zhao #define REF_CLOCK_24MHz (24 * HZ_PER_MHZ) 19*7160820dSYifeng Zhao #define REF_CLOCK_25MHz (25 * HZ_PER_MHZ) 20*7160820dSYifeng Zhao #define REF_CLOCK_100MHz (100 * HZ_PER_MHZ) 21*7160820dSYifeng Zhao 22*7160820dSYifeng Zhao /* COMBO PHY REG */ 23*7160820dSYifeng Zhao #define PHYREG6 0x14 24*7160820dSYifeng Zhao #define PHYREG6_PLL_DIV_MASK GENMASK(7, 6) 25*7160820dSYifeng Zhao #define PHYREG6_PLL_DIV_SHIFT 6 26*7160820dSYifeng Zhao #define PHYREG6_PLL_DIV_2 1 27*7160820dSYifeng Zhao 28*7160820dSYifeng Zhao #define PHYREG7 0x18 29*7160820dSYifeng Zhao #define PHYREG7_TX_RTERM_MASK GENMASK(7, 4) 30*7160820dSYifeng Zhao #define PHYREG7_TX_RTERM_SHIFT 4 31*7160820dSYifeng Zhao #define PHYREG7_TX_RTERM_50OHM 8 32*7160820dSYifeng Zhao #define PHYREG7_RX_RTERM_MASK GENMASK(3, 0) 33*7160820dSYifeng Zhao #define PHYREG7_RX_RTERM_SHIFT 0 34*7160820dSYifeng Zhao #define PHYREG7_RX_RTERM_44OHM 15 35*7160820dSYifeng Zhao 36*7160820dSYifeng Zhao #define PHYREG8 0x1C 37*7160820dSYifeng Zhao #define PHYREG8_SSC_EN BIT(4) 38*7160820dSYifeng Zhao 39*7160820dSYifeng Zhao #define PHYREG11 0x28 40*7160820dSYifeng Zhao #define PHYREG11_SU_TRIM_0_7 0xF0 41*7160820dSYifeng Zhao 42*7160820dSYifeng Zhao #define PHYREG12 0x2C 43*7160820dSYifeng Zhao #define PHYREG12_PLL_LPF_ADJ_VALUE 4 44*7160820dSYifeng Zhao 45*7160820dSYifeng Zhao #define PHYREG13 0x30 46*7160820dSYifeng Zhao #define PHYREG13_RESISTER_MASK GENMASK(5, 4) 47*7160820dSYifeng Zhao #define PHYREG13_RESISTER_SHIFT 0x4 48*7160820dSYifeng Zhao #define PHYREG13_RESISTER_HIGH_Z 3 49*7160820dSYifeng Zhao #define PHYREG13_CKRCV_AMP0 BIT(7) 50*7160820dSYifeng Zhao 51*7160820dSYifeng Zhao #define PHYREG14 0x34 52*7160820dSYifeng Zhao #define PHYREG14_CKRCV_AMP1 BIT(0) 53*7160820dSYifeng Zhao 54*7160820dSYifeng Zhao #define PHYREG15 0x38 55*7160820dSYifeng Zhao #define PHYREG15_CTLE_EN BIT(0) 56*7160820dSYifeng Zhao #define PHYREG15_SSC_CNT_MASK GENMASK(7, 6) 57*7160820dSYifeng Zhao #define PHYREG15_SSC_CNT_SHIFT 6 58*7160820dSYifeng Zhao #define PHYREG15_SSC_CNT_VALUE 1 59*7160820dSYifeng Zhao 60*7160820dSYifeng Zhao #define PHYREG16 0x3C 61*7160820dSYifeng Zhao #define PHYREG16_SSC_CNT_VALUE 0x5f 62*7160820dSYifeng Zhao 63*7160820dSYifeng Zhao #define PHYREG18 0x44 64*7160820dSYifeng Zhao #define PHYREG18_PLL_LOOP 0x32 65*7160820dSYifeng Zhao 66*7160820dSYifeng Zhao #define PHYREG32 0x7C 67*7160820dSYifeng Zhao #define PHYREG32_SSC_MASK GENMASK(7, 4) 68*7160820dSYifeng Zhao #define PHYREG32_SSC_DIR_SHIFT 4 69*7160820dSYifeng Zhao #define PHYREG32_SSC_UPWARD 0 70*7160820dSYifeng Zhao #define PHYREG32_SSC_DOWNWARD 1 71*7160820dSYifeng Zhao #define PHYREG32_SSC_OFFSET_SHIFT 6 72*7160820dSYifeng Zhao #define PHYREG32_SSC_OFFSET_500PPM 1 73*7160820dSYifeng Zhao 74*7160820dSYifeng Zhao #define PHYREG33 0x80 75*7160820dSYifeng Zhao #define PHYREG33_PLL_KVCO_MASK GENMASK(4, 2) 76*7160820dSYifeng Zhao #define PHYREG33_PLL_KVCO_SHIFT 2 77*7160820dSYifeng Zhao #define PHYREG33_PLL_KVCO_VALUE 2 78*7160820dSYifeng Zhao 79*7160820dSYifeng Zhao struct rockchip_combphy_priv; 80*7160820dSYifeng Zhao 81*7160820dSYifeng Zhao struct combphy_reg { 82*7160820dSYifeng Zhao u16 offset; 83*7160820dSYifeng Zhao u16 bitend; 84*7160820dSYifeng Zhao u16 bitstart; 85*7160820dSYifeng Zhao u16 disable; 86*7160820dSYifeng Zhao u16 enable; 87*7160820dSYifeng Zhao }; 88*7160820dSYifeng Zhao 89*7160820dSYifeng Zhao struct rockchip_combphy_grfcfg { 90*7160820dSYifeng Zhao struct combphy_reg pcie_mode_set; 91*7160820dSYifeng Zhao struct combphy_reg usb_mode_set; 92*7160820dSYifeng Zhao struct combphy_reg sgmii_mode_set; 93*7160820dSYifeng Zhao struct combphy_reg qsgmii_mode_set; 94*7160820dSYifeng Zhao struct combphy_reg pipe_rxterm_set; 95*7160820dSYifeng Zhao struct combphy_reg pipe_txelec_set; 96*7160820dSYifeng Zhao struct combphy_reg pipe_txcomp_set; 97*7160820dSYifeng Zhao struct combphy_reg pipe_clk_25m; 98*7160820dSYifeng Zhao struct combphy_reg pipe_clk_100m; 99*7160820dSYifeng Zhao struct combphy_reg pipe_phymode_sel; 100*7160820dSYifeng Zhao struct combphy_reg pipe_rate_sel; 101*7160820dSYifeng Zhao struct combphy_reg pipe_rxterm_sel; 102*7160820dSYifeng Zhao struct combphy_reg pipe_txelec_sel; 103*7160820dSYifeng Zhao struct combphy_reg pipe_txcomp_sel; 104*7160820dSYifeng Zhao struct combphy_reg pipe_clk_ext; 105*7160820dSYifeng Zhao struct combphy_reg pipe_sel_usb; 106*7160820dSYifeng Zhao struct combphy_reg pipe_sel_qsgmii; 107*7160820dSYifeng Zhao struct combphy_reg pipe_phy_status; 108*7160820dSYifeng Zhao struct combphy_reg con0_for_pcie; 109*7160820dSYifeng Zhao struct combphy_reg con1_for_pcie; 110*7160820dSYifeng Zhao struct combphy_reg con2_for_pcie; 111*7160820dSYifeng Zhao struct combphy_reg con3_for_pcie; 112*7160820dSYifeng Zhao struct combphy_reg con0_for_sata; 113*7160820dSYifeng Zhao struct combphy_reg con1_for_sata; 114*7160820dSYifeng Zhao struct combphy_reg con2_for_sata; 115*7160820dSYifeng Zhao struct combphy_reg con3_for_sata; 116*7160820dSYifeng Zhao struct combphy_reg pipe_con0_for_sata; 117*7160820dSYifeng Zhao struct combphy_reg pipe_xpcs_phy_ready; 118*7160820dSYifeng Zhao }; 119*7160820dSYifeng Zhao 120*7160820dSYifeng Zhao struct rockchip_combphy_cfg { 121*7160820dSYifeng Zhao const struct rockchip_combphy_grfcfg *grfcfg; 122*7160820dSYifeng Zhao int (*combphy_cfg)(struct rockchip_combphy_priv *priv); 123*7160820dSYifeng Zhao }; 124*7160820dSYifeng Zhao 125*7160820dSYifeng Zhao struct rockchip_combphy_priv { 126*7160820dSYifeng Zhao u8 type; 127*7160820dSYifeng Zhao void __iomem *mmio; 128*7160820dSYifeng Zhao int num_clks; 129*7160820dSYifeng Zhao struct clk_bulk_data *clks; 130*7160820dSYifeng Zhao struct device *dev; 131*7160820dSYifeng Zhao struct regmap *pipe_grf; 132*7160820dSYifeng Zhao struct regmap *phy_grf; 133*7160820dSYifeng Zhao struct phy *phy; 134*7160820dSYifeng Zhao struct reset_control *phy_rst; 135*7160820dSYifeng Zhao const struct rockchip_combphy_cfg *cfg; 136*7160820dSYifeng Zhao bool enable_ssc; 137*7160820dSYifeng Zhao bool ext_refclk; 138*7160820dSYifeng Zhao struct clk *refclk; 139*7160820dSYifeng Zhao }; 140*7160820dSYifeng Zhao 141*7160820dSYifeng Zhao static void rockchip_combphy_updatel(struct rockchip_combphy_priv *priv, 142*7160820dSYifeng Zhao int mask, int val, int reg) 143*7160820dSYifeng Zhao { 144*7160820dSYifeng Zhao unsigned int temp; 145*7160820dSYifeng Zhao 146*7160820dSYifeng Zhao temp = readl(priv->mmio + reg); 147*7160820dSYifeng Zhao temp = (temp & ~(mask)) | val; 148*7160820dSYifeng Zhao writel(temp, priv->mmio + reg); 149*7160820dSYifeng Zhao } 150*7160820dSYifeng Zhao 151*7160820dSYifeng Zhao static int rockchip_combphy_param_write(struct regmap *base, 152*7160820dSYifeng Zhao const struct combphy_reg *reg, bool en) 153*7160820dSYifeng Zhao { 154*7160820dSYifeng Zhao u32 val, mask, tmp; 155*7160820dSYifeng Zhao 156*7160820dSYifeng Zhao tmp = en ? reg->enable : reg->disable; 157*7160820dSYifeng Zhao mask = GENMASK(reg->bitend, reg->bitstart); 158*7160820dSYifeng Zhao val = (tmp << reg->bitstart) | (mask << BIT_WRITEABLE_SHIFT); 159*7160820dSYifeng Zhao 160*7160820dSYifeng Zhao return regmap_write(base, reg->offset, val); 161*7160820dSYifeng Zhao } 162*7160820dSYifeng Zhao 163*7160820dSYifeng Zhao static u32 rockchip_combphy_is_ready(struct rockchip_combphy_priv *priv) 164*7160820dSYifeng Zhao { 165*7160820dSYifeng Zhao const struct rockchip_combphy_grfcfg *cfg = priv->cfg->grfcfg; 166*7160820dSYifeng Zhao u32 mask, val; 167*7160820dSYifeng Zhao 168*7160820dSYifeng Zhao mask = GENMASK(cfg->pipe_phy_status.bitend, 169*7160820dSYifeng Zhao cfg->pipe_phy_status.bitstart); 170*7160820dSYifeng Zhao 171*7160820dSYifeng Zhao regmap_read(priv->phy_grf, cfg->pipe_phy_status.offset, &val); 172*7160820dSYifeng Zhao val = (val & mask) >> cfg->pipe_phy_status.bitstart; 173*7160820dSYifeng Zhao 174*7160820dSYifeng Zhao return val; 175*7160820dSYifeng Zhao } 176*7160820dSYifeng Zhao 177*7160820dSYifeng Zhao static int rockchip_combphy_init(struct phy *phy) 178*7160820dSYifeng Zhao { 179*7160820dSYifeng Zhao struct rockchip_combphy_priv *priv = phy_get_drvdata(phy); 180*7160820dSYifeng Zhao const struct rockchip_combphy_grfcfg *cfg = priv->cfg->grfcfg; 181*7160820dSYifeng Zhao u32 val; 182*7160820dSYifeng Zhao int ret; 183*7160820dSYifeng Zhao 184*7160820dSYifeng Zhao ret = clk_bulk_prepare_enable(priv->num_clks, priv->clks); 185*7160820dSYifeng Zhao if (ret) { 186*7160820dSYifeng Zhao dev_err(priv->dev, "failed to enable clks\n"); 187*7160820dSYifeng Zhao return ret; 188*7160820dSYifeng Zhao } 189*7160820dSYifeng Zhao 190*7160820dSYifeng Zhao switch (priv->type) { 191*7160820dSYifeng Zhao case PHY_TYPE_PCIE: 192*7160820dSYifeng Zhao case PHY_TYPE_USB3: 193*7160820dSYifeng Zhao case PHY_TYPE_SATA: 194*7160820dSYifeng Zhao case PHY_TYPE_SGMII: 195*7160820dSYifeng Zhao case PHY_TYPE_QSGMII: 196*7160820dSYifeng Zhao if (priv->cfg->combphy_cfg) 197*7160820dSYifeng Zhao ret = priv->cfg->combphy_cfg(priv); 198*7160820dSYifeng Zhao break; 199*7160820dSYifeng Zhao default: 200*7160820dSYifeng Zhao dev_err(priv->dev, "incompatible PHY type\n"); 201*7160820dSYifeng Zhao ret = -EINVAL; 202*7160820dSYifeng Zhao break; 203*7160820dSYifeng Zhao } 204*7160820dSYifeng Zhao 205*7160820dSYifeng Zhao if (ret) { 206*7160820dSYifeng Zhao dev_err(priv->dev, "failed to init phy for phy type %x\n", priv->type); 207*7160820dSYifeng Zhao goto err_clk; 208*7160820dSYifeng Zhao } 209*7160820dSYifeng Zhao 210*7160820dSYifeng Zhao ret = reset_control_deassert(priv->phy_rst); 211*7160820dSYifeng Zhao if (ret) 212*7160820dSYifeng Zhao goto err_clk; 213*7160820dSYifeng Zhao 214*7160820dSYifeng Zhao if (priv->type == PHY_TYPE_USB3) { 215*7160820dSYifeng Zhao ret = readx_poll_timeout_atomic(rockchip_combphy_is_ready, 216*7160820dSYifeng Zhao priv, val, 217*7160820dSYifeng Zhao val == cfg->pipe_phy_status.enable, 218*7160820dSYifeng Zhao 10, 1000); 219*7160820dSYifeng Zhao if (ret) 220*7160820dSYifeng Zhao dev_warn(priv->dev, "wait phy status ready timeout\n"); 221*7160820dSYifeng Zhao } 222*7160820dSYifeng Zhao 223*7160820dSYifeng Zhao return 0; 224*7160820dSYifeng Zhao 225*7160820dSYifeng Zhao err_clk: 226*7160820dSYifeng Zhao clk_bulk_disable_unprepare(priv->num_clks, priv->clks); 227*7160820dSYifeng Zhao 228*7160820dSYifeng Zhao return ret; 229*7160820dSYifeng Zhao } 230*7160820dSYifeng Zhao 231*7160820dSYifeng Zhao static int rockchip_combphy_exit(struct phy *phy) 232*7160820dSYifeng Zhao { 233*7160820dSYifeng Zhao struct rockchip_combphy_priv *priv = phy_get_drvdata(phy); 234*7160820dSYifeng Zhao 235*7160820dSYifeng Zhao clk_bulk_disable_unprepare(priv->num_clks, priv->clks); 236*7160820dSYifeng Zhao reset_control_assert(priv->phy_rst); 237*7160820dSYifeng Zhao 238*7160820dSYifeng Zhao return 0; 239*7160820dSYifeng Zhao } 240*7160820dSYifeng Zhao 241*7160820dSYifeng Zhao static const struct phy_ops rochchip_combphy_ops = { 242*7160820dSYifeng Zhao .init = rockchip_combphy_init, 243*7160820dSYifeng Zhao .exit = rockchip_combphy_exit, 244*7160820dSYifeng Zhao .owner = THIS_MODULE, 245*7160820dSYifeng Zhao }; 246*7160820dSYifeng Zhao 247*7160820dSYifeng Zhao static struct phy *rockchip_combphy_xlate(struct device *dev, struct of_phandle_args *args) 248*7160820dSYifeng Zhao { 249*7160820dSYifeng Zhao struct rockchip_combphy_priv *priv = dev_get_drvdata(dev); 250*7160820dSYifeng Zhao 251*7160820dSYifeng Zhao if (args->args_count != 1) { 252*7160820dSYifeng Zhao dev_err(dev, "invalid number of arguments\n"); 253*7160820dSYifeng Zhao return ERR_PTR(-EINVAL); 254*7160820dSYifeng Zhao } 255*7160820dSYifeng Zhao 256*7160820dSYifeng Zhao if (priv->type != PHY_NONE && priv->type != args->args[0]) 257*7160820dSYifeng Zhao dev_warn(dev, "phy type select %d overwriting type %d\n", 258*7160820dSYifeng Zhao args->args[0], priv->type); 259*7160820dSYifeng Zhao 260*7160820dSYifeng Zhao priv->type = args->args[0]; 261*7160820dSYifeng Zhao 262*7160820dSYifeng Zhao return priv->phy; 263*7160820dSYifeng Zhao } 264*7160820dSYifeng Zhao 265*7160820dSYifeng Zhao static int rockchip_combphy_parse_dt(struct device *dev, struct rockchip_combphy_priv *priv) 266*7160820dSYifeng Zhao { 267*7160820dSYifeng Zhao int i; 268*7160820dSYifeng Zhao 269*7160820dSYifeng Zhao priv->num_clks = devm_clk_bulk_get_all(dev, &priv->clks); 270*7160820dSYifeng Zhao if (priv->num_clks < 1) 271*7160820dSYifeng Zhao return -EINVAL; 272*7160820dSYifeng Zhao 273*7160820dSYifeng Zhao priv->refclk = NULL; 274*7160820dSYifeng Zhao for (i = 0; i < priv->num_clks; i++) { 275*7160820dSYifeng Zhao if (!strncmp(priv->clks[i].id, "ref", 3)) { 276*7160820dSYifeng Zhao priv->refclk = priv->clks[i].clk; 277*7160820dSYifeng Zhao break; 278*7160820dSYifeng Zhao } 279*7160820dSYifeng Zhao } 280*7160820dSYifeng Zhao 281*7160820dSYifeng Zhao if (!priv->refclk) { 282*7160820dSYifeng Zhao dev_err(dev, "no refclk found\n"); 283*7160820dSYifeng Zhao return -EINVAL; 284*7160820dSYifeng Zhao } 285*7160820dSYifeng Zhao 286*7160820dSYifeng Zhao priv->pipe_grf = syscon_regmap_lookup_by_phandle(dev->of_node, "rockchip,pipe-grf"); 287*7160820dSYifeng Zhao if (IS_ERR(priv->pipe_grf)) { 288*7160820dSYifeng Zhao dev_err(dev, "failed to find peri_ctrl pipe-grf regmap\n"); 289*7160820dSYifeng Zhao return PTR_ERR(priv->pipe_grf); 290*7160820dSYifeng Zhao } 291*7160820dSYifeng Zhao 292*7160820dSYifeng Zhao priv->phy_grf = syscon_regmap_lookup_by_phandle(dev->of_node, "rockchip,pipe-phy-grf"); 293*7160820dSYifeng Zhao if (IS_ERR(priv->phy_grf)) { 294*7160820dSYifeng Zhao dev_err(dev, "failed to find peri_ctrl pipe-phy-grf regmap\n"); 295*7160820dSYifeng Zhao return PTR_ERR(priv->phy_grf); 296*7160820dSYifeng Zhao } 297*7160820dSYifeng Zhao 298*7160820dSYifeng Zhao priv->enable_ssc = device_property_present(dev, "rockchip,enable-ssc"); 299*7160820dSYifeng Zhao 300*7160820dSYifeng Zhao priv->ext_refclk = device_property_present(dev, "rockchip,ext-refclk"); 301*7160820dSYifeng Zhao 302*7160820dSYifeng Zhao priv->phy_rst = devm_reset_control_array_get_exclusive(dev); 303*7160820dSYifeng Zhao if (IS_ERR(priv->phy_rst)) 304*7160820dSYifeng Zhao return dev_err_probe(dev, PTR_ERR(priv->phy_rst), "failed to get phy reset\n"); 305*7160820dSYifeng Zhao 306*7160820dSYifeng Zhao return 0; 307*7160820dSYifeng Zhao } 308*7160820dSYifeng Zhao 309*7160820dSYifeng Zhao static int rockchip_combphy_probe(struct platform_device *pdev) 310*7160820dSYifeng Zhao { 311*7160820dSYifeng Zhao struct phy_provider *phy_provider; 312*7160820dSYifeng Zhao struct device *dev = &pdev->dev; 313*7160820dSYifeng Zhao struct rockchip_combphy_priv *priv; 314*7160820dSYifeng Zhao const struct rockchip_combphy_cfg *phy_cfg; 315*7160820dSYifeng Zhao struct resource *res; 316*7160820dSYifeng Zhao int ret; 317*7160820dSYifeng Zhao 318*7160820dSYifeng Zhao phy_cfg = of_device_get_match_data(dev); 319*7160820dSYifeng Zhao if (!phy_cfg) { 320*7160820dSYifeng Zhao dev_err(dev, "no OF match data provided\n"); 321*7160820dSYifeng Zhao return -EINVAL; 322*7160820dSYifeng Zhao } 323*7160820dSYifeng Zhao 324*7160820dSYifeng Zhao priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 325*7160820dSYifeng Zhao if (!priv) 326*7160820dSYifeng Zhao return -ENOMEM; 327*7160820dSYifeng Zhao 328*7160820dSYifeng Zhao priv->mmio = devm_platform_get_and_ioremap_resource(pdev, 0, &res); 329*7160820dSYifeng Zhao if (IS_ERR(priv->mmio)) { 330*7160820dSYifeng Zhao ret = PTR_ERR(priv->mmio); 331*7160820dSYifeng Zhao return ret; 332*7160820dSYifeng Zhao } 333*7160820dSYifeng Zhao 334*7160820dSYifeng Zhao priv->dev = dev; 335*7160820dSYifeng Zhao priv->type = PHY_NONE; 336*7160820dSYifeng Zhao priv->cfg = phy_cfg; 337*7160820dSYifeng Zhao 338*7160820dSYifeng Zhao ret = rockchip_combphy_parse_dt(dev, priv); 339*7160820dSYifeng Zhao if (ret) 340*7160820dSYifeng Zhao return ret; 341*7160820dSYifeng Zhao 342*7160820dSYifeng Zhao ret = reset_control_assert(priv->phy_rst); 343*7160820dSYifeng Zhao if (ret) { 344*7160820dSYifeng Zhao dev_err(dev, "failed to reset phy\n"); 345*7160820dSYifeng Zhao return ret; 346*7160820dSYifeng Zhao } 347*7160820dSYifeng Zhao 348*7160820dSYifeng Zhao priv->phy = devm_phy_create(dev, NULL, &rochchip_combphy_ops); 349*7160820dSYifeng Zhao if (IS_ERR(priv->phy)) { 350*7160820dSYifeng Zhao dev_err(dev, "failed to create combphy\n"); 351*7160820dSYifeng Zhao return PTR_ERR(priv->phy); 352*7160820dSYifeng Zhao } 353*7160820dSYifeng Zhao 354*7160820dSYifeng Zhao dev_set_drvdata(dev, priv); 355*7160820dSYifeng Zhao phy_set_drvdata(priv->phy, priv); 356*7160820dSYifeng Zhao 357*7160820dSYifeng Zhao phy_provider = devm_of_phy_provider_register(dev, rockchip_combphy_xlate); 358*7160820dSYifeng Zhao 359*7160820dSYifeng Zhao return PTR_ERR_OR_ZERO(phy_provider); 360*7160820dSYifeng Zhao } 361*7160820dSYifeng Zhao 362*7160820dSYifeng Zhao static int rk3568_combphy_cfg(struct rockchip_combphy_priv *priv) 363*7160820dSYifeng Zhao { 364*7160820dSYifeng Zhao const struct rockchip_combphy_grfcfg *cfg = priv->cfg->grfcfg; 365*7160820dSYifeng Zhao unsigned long rate; 366*7160820dSYifeng Zhao u32 val; 367*7160820dSYifeng Zhao 368*7160820dSYifeng Zhao switch (priv->type) { 369*7160820dSYifeng Zhao case PHY_TYPE_PCIE: 370*7160820dSYifeng Zhao /* Set SSC downward spread spectrum. */ 371*7160820dSYifeng Zhao rockchip_combphy_updatel(priv, PHYREG32_SSC_MASK, 372*7160820dSYifeng Zhao PHYREG32_SSC_DOWNWARD << PHYREG32_SSC_DIR_SHIFT, 373*7160820dSYifeng Zhao PHYREG32); 374*7160820dSYifeng Zhao 375*7160820dSYifeng Zhao rockchip_combphy_param_write(priv->phy_grf, &cfg->con0_for_pcie, true); 376*7160820dSYifeng Zhao rockchip_combphy_param_write(priv->phy_grf, &cfg->con1_for_pcie, true); 377*7160820dSYifeng Zhao rockchip_combphy_param_write(priv->phy_grf, &cfg->con2_for_pcie, true); 378*7160820dSYifeng Zhao rockchip_combphy_param_write(priv->phy_grf, &cfg->con3_for_pcie, true); 379*7160820dSYifeng Zhao break; 380*7160820dSYifeng Zhao 381*7160820dSYifeng Zhao case PHY_TYPE_USB3: 382*7160820dSYifeng Zhao /* Set SSC downward spread spectrum. */ 383*7160820dSYifeng Zhao rockchip_combphy_updatel(priv, PHYREG32_SSC_MASK, 384*7160820dSYifeng Zhao PHYREG32_SSC_DOWNWARD << PHYREG32_SSC_DIR_SHIFT, 385*7160820dSYifeng Zhao PHYREG32); 386*7160820dSYifeng Zhao 387*7160820dSYifeng Zhao /* Enable adaptive CTLE for USB3.0 Rx. */ 388*7160820dSYifeng Zhao val = readl(priv->mmio + PHYREG15); 389*7160820dSYifeng Zhao val |= PHYREG15_CTLE_EN; 390*7160820dSYifeng Zhao writel(val, priv->mmio + PHYREG15); 391*7160820dSYifeng Zhao 392*7160820dSYifeng Zhao /* Set PLL KVCO fine tuning signals. */ 393*7160820dSYifeng Zhao rockchip_combphy_updatel(priv, PHYREG33_PLL_KVCO_MASK, 394*7160820dSYifeng Zhao PHYREG33_PLL_KVCO_VALUE << PHYREG33_PLL_KVCO_SHIFT, 395*7160820dSYifeng Zhao PHYREG33); 396*7160820dSYifeng Zhao 397*7160820dSYifeng Zhao /* Enable controlling random jitter. */ 398*7160820dSYifeng Zhao writel(PHYREG12_PLL_LPF_ADJ_VALUE, priv->mmio + PHYREG12); 399*7160820dSYifeng Zhao 400*7160820dSYifeng Zhao /* Set PLL input clock divider 1/2. */ 401*7160820dSYifeng Zhao rockchip_combphy_updatel(priv, PHYREG6_PLL_DIV_MASK, 402*7160820dSYifeng Zhao PHYREG6_PLL_DIV_2 << PHYREG6_PLL_DIV_SHIFT, 403*7160820dSYifeng Zhao PHYREG6); 404*7160820dSYifeng Zhao 405*7160820dSYifeng Zhao writel(PHYREG18_PLL_LOOP, priv->mmio + PHYREG18); 406*7160820dSYifeng Zhao writel(PHYREG11_SU_TRIM_0_7, priv->mmio + PHYREG11); 407*7160820dSYifeng Zhao 408*7160820dSYifeng Zhao rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_sel_usb, true); 409*7160820dSYifeng Zhao rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_txcomp_sel, false); 410*7160820dSYifeng Zhao rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_txelec_sel, false); 411*7160820dSYifeng Zhao rockchip_combphy_param_write(priv->phy_grf, &cfg->usb_mode_set, true); 412*7160820dSYifeng Zhao break; 413*7160820dSYifeng Zhao 414*7160820dSYifeng Zhao case PHY_TYPE_SATA: 415*7160820dSYifeng Zhao /* Enable adaptive CTLE for SATA Rx. */ 416*7160820dSYifeng Zhao val = readl(priv->mmio + PHYREG15); 417*7160820dSYifeng Zhao val |= PHYREG15_CTLE_EN; 418*7160820dSYifeng Zhao writel(val, priv->mmio + PHYREG15); 419*7160820dSYifeng Zhao /* 420*7160820dSYifeng Zhao * Set tx_rterm=50ohm and rx_rterm=44ohm for SATA. 421*7160820dSYifeng Zhao * 0: 60ohm, 8: 50ohm 15: 44ohm (by step abort 1ohm) 422*7160820dSYifeng Zhao */ 423*7160820dSYifeng Zhao val = PHYREG7_TX_RTERM_50OHM << PHYREG7_TX_RTERM_SHIFT; 424*7160820dSYifeng Zhao val |= PHYREG7_RX_RTERM_44OHM << PHYREG7_RX_RTERM_SHIFT; 425*7160820dSYifeng Zhao writel(val, priv->mmio + PHYREG7); 426*7160820dSYifeng Zhao 427*7160820dSYifeng Zhao rockchip_combphy_param_write(priv->phy_grf, &cfg->con0_for_sata, true); 428*7160820dSYifeng Zhao rockchip_combphy_param_write(priv->phy_grf, &cfg->con1_for_sata, true); 429*7160820dSYifeng Zhao rockchip_combphy_param_write(priv->phy_grf, &cfg->con2_for_sata, true); 430*7160820dSYifeng Zhao rockchip_combphy_param_write(priv->phy_grf, &cfg->con3_for_sata, true); 431*7160820dSYifeng Zhao rockchip_combphy_param_write(priv->pipe_grf, &cfg->pipe_con0_for_sata, true); 432*7160820dSYifeng Zhao break; 433*7160820dSYifeng Zhao 434*7160820dSYifeng Zhao case PHY_TYPE_SGMII: 435*7160820dSYifeng Zhao rockchip_combphy_param_write(priv->pipe_grf, &cfg->pipe_xpcs_phy_ready, true); 436*7160820dSYifeng Zhao rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_phymode_sel, true); 437*7160820dSYifeng Zhao rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_sel_qsgmii, true); 438*7160820dSYifeng Zhao rockchip_combphy_param_write(priv->phy_grf, &cfg->sgmii_mode_set, true); 439*7160820dSYifeng Zhao break; 440*7160820dSYifeng Zhao 441*7160820dSYifeng Zhao case PHY_TYPE_QSGMII: 442*7160820dSYifeng Zhao rockchip_combphy_param_write(priv->pipe_grf, &cfg->pipe_xpcs_phy_ready, true); 443*7160820dSYifeng Zhao rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_phymode_sel, true); 444*7160820dSYifeng Zhao rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_rate_sel, true); 445*7160820dSYifeng Zhao rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_sel_qsgmii, true); 446*7160820dSYifeng Zhao rockchip_combphy_param_write(priv->phy_grf, &cfg->qsgmii_mode_set, true); 447*7160820dSYifeng Zhao break; 448*7160820dSYifeng Zhao 449*7160820dSYifeng Zhao default: 450*7160820dSYifeng Zhao dev_err(priv->dev, "incompatible PHY type\n"); 451*7160820dSYifeng Zhao return -EINVAL; 452*7160820dSYifeng Zhao } 453*7160820dSYifeng Zhao 454*7160820dSYifeng Zhao rate = clk_get_rate(priv->refclk); 455*7160820dSYifeng Zhao 456*7160820dSYifeng Zhao switch (rate) { 457*7160820dSYifeng Zhao case REF_CLOCK_24MHz: 458*7160820dSYifeng Zhao if (priv->type == PHY_TYPE_USB3 || priv->type == PHY_TYPE_SATA) { 459*7160820dSYifeng Zhao /* Set ssc_cnt[9:0]=0101111101 & 31.5KHz. */ 460*7160820dSYifeng Zhao val = PHYREG15_SSC_CNT_VALUE << PHYREG15_SSC_CNT_SHIFT; 461*7160820dSYifeng Zhao rockchip_combphy_updatel(priv, PHYREG15_SSC_CNT_MASK, 462*7160820dSYifeng Zhao val, PHYREG15); 463*7160820dSYifeng Zhao 464*7160820dSYifeng Zhao writel(PHYREG16_SSC_CNT_VALUE, priv->mmio + PHYREG16); 465*7160820dSYifeng Zhao } 466*7160820dSYifeng Zhao break; 467*7160820dSYifeng Zhao 468*7160820dSYifeng Zhao case REF_CLOCK_25MHz: 469*7160820dSYifeng Zhao rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_clk_25m, true); 470*7160820dSYifeng Zhao break; 471*7160820dSYifeng Zhao 472*7160820dSYifeng Zhao case REF_CLOCK_100MHz: 473*7160820dSYifeng Zhao rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_clk_100m, true); 474*7160820dSYifeng Zhao if (priv->type == PHY_TYPE_PCIE) { 475*7160820dSYifeng Zhao /* PLL KVCO fine tuning. */ 476*7160820dSYifeng Zhao val = PHYREG33_PLL_KVCO_VALUE << PHYREG33_PLL_KVCO_SHIFT; 477*7160820dSYifeng Zhao rockchip_combphy_updatel(priv, PHYREG33_PLL_KVCO_MASK, 478*7160820dSYifeng Zhao val, PHYREG33); 479*7160820dSYifeng Zhao 480*7160820dSYifeng Zhao /* Enable controlling random jitter. */ 481*7160820dSYifeng Zhao writel(PHYREG12_PLL_LPF_ADJ_VALUE, priv->mmio + PHYREG12); 482*7160820dSYifeng Zhao 483*7160820dSYifeng Zhao val = PHYREG6_PLL_DIV_2 << PHYREG6_PLL_DIV_SHIFT; 484*7160820dSYifeng Zhao rockchip_combphy_updatel(priv, PHYREG6_PLL_DIV_MASK, 485*7160820dSYifeng Zhao val, PHYREG6); 486*7160820dSYifeng Zhao 487*7160820dSYifeng Zhao writel(PHYREG18_PLL_LOOP, priv->mmio + PHYREG18); 488*7160820dSYifeng Zhao writel(PHYREG11_SU_TRIM_0_7, priv->mmio + PHYREG11); 489*7160820dSYifeng Zhao } else if (priv->type == PHY_TYPE_SATA) { 490*7160820dSYifeng Zhao /* downward spread spectrum +500ppm */ 491*7160820dSYifeng Zhao val = PHYREG32_SSC_DOWNWARD << PHYREG32_SSC_DIR_SHIFT; 492*7160820dSYifeng Zhao val |= PHYREG32_SSC_OFFSET_500PPM << PHYREG32_SSC_OFFSET_SHIFT; 493*7160820dSYifeng Zhao rockchip_combphy_updatel(priv, PHYREG32_SSC_MASK, val, PHYREG32); 494*7160820dSYifeng Zhao } 495*7160820dSYifeng Zhao break; 496*7160820dSYifeng Zhao 497*7160820dSYifeng Zhao default: 498*7160820dSYifeng Zhao dev_err(priv->dev, "unsupported rate: %lu\n", rate); 499*7160820dSYifeng Zhao return -EINVAL; 500*7160820dSYifeng Zhao } 501*7160820dSYifeng Zhao 502*7160820dSYifeng Zhao if (priv->ext_refclk) { 503*7160820dSYifeng Zhao rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_clk_ext, true); 504*7160820dSYifeng Zhao if (priv->type == PHY_TYPE_PCIE && rate == REF_CLOCK_100MHz) { 505*7160820dSYifeng Zhao val = PHYREG13_RESISTER_HIGH_Z << PHYREG13_RESISTER_SHIFT; 506*7160820dSYifeng Zhao val |= PHYREG13_CKRCV_AMP0; 507*7160820dSYifeng Zhao rockchip_combphy_updatel(priv, PHYREG13_RESISTER_MASK, val, PHYREG13); 508*7160820dSYifeng Zhao 509*7160820dSYifeng Zhao val = readl(priv->mmio + PHYREG14); 510*7160820dSYifeng Zhao val |= PHYREG14_CKRCV_AMP1; 511*7160820dSYifeng Zhao writel(val, priv->mmio + PHYREG14); 512*7160820dSYifeng Zhao } 513*7160820dSYifeng Zhao } 514*7160820dSYifeng Zhao 515*7160820dSYifeng Zhao if (priv->enable_ssc) { 516*7160820dSYifeng Zhao val = readl(priv->mmio + PHYREG8); 517*7160820dSYifeng Zhao val |= PHYREG8_SSC_EN; 518*7160820dSYifeng Zhao writel(val, priv->mmio + PHYREG8); 519*7160820dSYifeng Zhao } 520*7160820dSYifeng Zhao 521*7160820dSYifeng Zhao return 0; 522*7160820dSYifeng Zhao } 523*7160820dSYifeng Zhao 524*7160820dSYifeng Zhao static const struct rockchip_combphy_grfcfg rk3568_combphy_grfcfgs = { 525*7160820dSYifeng Zhao /* pipe-phy-grf */ 526*7160820dSYifeng Zhao .pcie_mode_set = { 0x0000, 5, 0, 0x00, 0x11 }, 527*7160820dSYifeng Zhao .usb_mode_set = { 0x0000, 5, 0, 0x00, 0x04 }, 528*7160820dSYifeng Zhao .sgmii_mode_set = { 0x0000, 5, 0, 0x00, 0x01 }, 529*7160820dSYifeng Zhao .qsgmii_mode_set = { 0x0000, 5, 0, 0x00, 0x21 }, 530*7160820dSYifeng Zhao .pipe_rxterm_set = { 0x0000, 12, 12, 0x00, 0x01 }, 531*7160820dSYifeng Zhao .pipe_txelec_set = { 0x0004, 1, 1, 0x00, 0x01 }, 532*7160820dSYifeng Zhao .pipe_txcomp_set = { 0x0004, 4, 4, 0x00, 0x01 }, 533*7160820dSYifeng Zhao .pipe_clk_25m = { 0x0004, 14, 13, 0x00, 0x01 }, 534*7160820dSYifeng Zhao .pipe_clk_100m = { 0x0004, 14, 13, 0x00, 0x02 }, 535*7160820dSYifeng Zhao .pipe_phymode_sel = { 0x0008, 1, 1, 0x00, 0x01 }, 536*7160820dSYifeng Zhao .pipe_rate_sel = { 0x0008, 2, 2, 0x00, 0x01 }, 537*7160820dSYifeng Zhao .pipe_rxterm_sel = { 0x0008, 8, 8, 0x00, 0x01 }, 538*7160820dSYifeng Zhao .pipe_txelec_sel = { 0x0008, 12, 12, 0x00, 0x01 }, 539*7160820dSYifeng Zhao .pipe_txcomp_sel = { 0x0008, 15, 15, 0x00, 0x01 }, 540*7160820dSYifeng Zhao .pipe_clk_ext = { 0x000c, 9, 8, 0x02, 0x01 }, 541*7160820dSYifeng Zhao .pipe_sel_usb = { 0x000c, 14, 13, 0x00, 0x01 }, 542*7160820dSYifeng Zhao .pipe_sel_qsgmii = { 0x000c, 15, 13, 0x00, 0x07 }, 543*7160820dSYifeng Zhao .pipe_phy_status = { 0x0034, 6, 6, 0x01, 0x00 }, 544*7160820dSYifeng Zhao .con0_for_pcie = { 0x0000, 15, 0, 0x00, 0x1000 }, 545*7160820dSYifeng Zhao .con1_for_pcie = { 0x0004, 15, 0, 0x00, 0x0000 }, 546*7160820dSYifeng Zhao .con2_for_pcie = { 0x0008, 15, 0, 0x00, 0x0101 }, 547*7160820dSYifeng Zhao .con3_for_pcie = { 0x000c, 15, 0, 0x00, 0x0200 }, 548*7160820dSYifeng Zhao .con0_for_sata = { 0x0000, 15, 0, 0x00, 0x0119 }, 549*7160820dSYifeng Zhao .con1_for_sata = { 0x0004, 15, 0, 0x00, 0x0040 }, 550*7160820dSYifeng Zhao .con2_for_sata = { 0x0008, 15, 0, 0x00, 0x80c3 }, 551*7160820dSYifeng Zhao .con3_for_sata = { 0x000c, 15, 0, 0x00, 0x4407 }, 552*7160820dSYifeng Zhao /* pipe-grf */ 553*7160820dSYifeng Zhao .pipe_con0_for_sata = { 0x0000, 15, 0, 0x00, 0x2220 }, 554*7160820dSYifeng Zhao .pipe_xpcs_phy_ready = { 0x0040, 2, 2, 0x00, 0x01 }, 555*7160820dSYifeng Zhao }; 556*7160820dSYifeng Zhao 557*7160820dSYifeng Zhao static const struct rockchip_combphy_cfg rk3568_combphy_cfgs = { 558*7160820dSYifeng Zhao .grfcfg = &rk3568_combphy_grfcfgs, 559*7160820dSYifeng Zhao .combphy_cfg = rk3568_combphy_cfg, 560*7160820dSYifeng Zhao }; 561*7160820dSYifeng Zhao 562*7160820dSYifeng Zhao static const struct of_device_id rockchip_combphy_of_match[] = { 563*7160820dSYifeng Zhao { 564*7160820dSYifeng Zhao .compatible = "rockchip,rk3568-naneng-combphy", 565*7160820dSYifeng Zhao .data = &rk3568_combphy_cfgs, 566*7160820dSYifeng Zhao }, 567*7160820dSYifeng Zhao { }, 568*7160820dSYifeng Zhao }; 569*7160820dSYifeng Zhao MODULE_DEVICE_TABLE(of, rockchip_combphy_of_match); 570*7160820dSYifeng Zhao 571*7160820dSYifeng Zhao static struct platform_driver rockchip_combphy_driver = { 572*7160820dSYifeng Zhao .probe = rockchip_combphy_probe, 573*7160820dSYifeng Zhao .driver = { 574*7160820dSYifeng Zhao .name = "rockchip-naneng-combphy", 575*7160820dSYifeng Zhao .of_match_table = rockchip_combphy_of_match, 576*7160820dSYifeng Zhao }, 577*7160820dSYifeng Zhao }; 578*7160820dSYifeng Zhao module_platform_driver(rockchip_combphy_driver); 579*7160820dSYifeng Zhao 580*7160820dSYifeng Zhao MODULE_DESCRIPTION("Rockchip NANENG COMBPHY driver"); 581*7160820dSYifeng Zhao MODULE_LICENSE("GPL v2"); 582