1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Salvo PHY is a 28nm PHY, it is a legacy PHY, and only 4 * for USB3 and USB2. 5 * 6 * Copyright (c) 2019-2020 NXP 7 */ 8 9 #include <linux/bitfield.h> 10 #include <linux/clk.h> 11 #include <linux/io.h> 12 #include <linux/module.h> 13 #include <linux/phy/phy.h> 14 #include <linux/platform_device.h> 15 #include <linux/delay.h> 16 #include <linux/of.h> 17 #include <linux/of_platform.h> 18 19 #define USB3_PHY_OFFSET 0x0 20 #define USB2_PHY_OFFSET 0x38000 21 /* USB3 PHY register definition */ 22 #define PHY_PMA_CMN_CTRL1 0xC800 23 #define TB_ADDR_CMN_DIAG_HSCLK_SEL 0x01e0 24 #define TB_ADDR_CMN_PLL0_VCOCAL_INIT_TMR 0x0084 25 #define TB_ADDR_CMN_PLL0_VCOCAL_ITER_TMR 0x0085 26 #define TB_ADDR_CMN_PLL0_INTDIV 0x0094 27 #define TB_ADDR_CMN_PLL0_FRACDIV 0x0095 28 #define TB_ADDR_CMN_PLL0_HIGH_THR 0x0096 29 #define TB_ADDR_CMN_PLL0_SS_CTRL1 0x0098 30 #define TB_ADDR_CMN_PLL0_SS_CTRL2 0x0099 31 #define TB_ADDR_CMN_PLL0_DSM_DIAG 0x0097 32 #define TB_ADDR_CMN_DIAG_PLL0_OVRD 0x01c2 33 #define TB_ADDR_CMN_DIAG_PLL0_FBH_OVRD 0x01c0 34 #define TB_ADDR_CMN_DIAG_PLL0_FBL_OVRD 0x01c1 35 #define TB_ADDR_CMN_DIAG_PLL0_V2I_TUNE 0x01C5 36 #define TB_ADDR_CMN_DIAG_PLL0_CP_TUNE 0x01C6 37 #define TB_ADDR_CMN_DIAG_PLL0_LF_PROG 0x01C7 38 #define TB_ADDR_CMN_DIAG_PLL0_TEST_MODE 0x01c4 39 #define TB_ADDR_CMN_PSM_CLK_CTRL 0x0061 40 #define TB_ADDR_XCVR_DIAG_RX_LANE_CAL_RST_TMR 0x40ea 41 #define TB_ADDR_XCVR_PSM_RCTRL 0x4001 42 #define TB_ADDR_TX_PSC_A0 0x4100 43 #define TB_ADDR_TX_PSC_A1 0x4101 44 #define TB_ADDR_TX_PSC_A2 0x4102 45 #define TB_ADDR_TX_PSC_A3 0x4103 46 #define TB_ADDR_TX_DIAG_ECTRL_OVRD 0x41f5 47 #define TB_ADDR_TX_PSC_CAL 0x4106 48 #define TB_ADDR_TX_PSC_RDY 0x4107 49 #define TB_ADDR_RX_PSC_A0 0x8000 50 #define TB_ADDR_RX_PSC_A1 0x8001 51 #define TB_ADDR_RX_PSC_A2 0x8002 52 #define TB_ADDR_RX_PSC_A3 0x8003 53 #define TB_ADDR_RX_PSC_CAL 0x8006 54 #define TB_ADDR_RX_PSC_RDY 0x8007 55 #define TB_ADDR_TX_TXCC_MGNLS_MULT_000 0x4058 56 #define TB_ADDR_TX_DIAG_BGREF_PREDRV_DELAY 0x41e7 57 #define TB_ADDR_RX_SLC_CU_ITER_TMR 0x80e3 58 #define TB_ADDR_RX_SIGDET_HL_FILT_TMR 0x8090 59 #define TB_ADDR_RX_SAMP_DAC_CTRL 0x8058 60 #define TB_ADDR_RX_DIAG_SIGDET_TUNE 0x81dc 61 #define TB_ADDR_RX_DIAG_LFPSDET_TUNE2 0x81df 62 #define TB_ADDR_RX_DIAG_BS_TM 0x81f5 63 #define TB_ADDR_RX_DIAG_DFE_CTRL1 0x81d3 64 #define TB_ADDR_RX_DIAG_ILL_IQE_TRIM4 0x81c7 65 #define TB_ADDR_RX_DIAG_ILL_E_TRIM0 0x81c2 66 #define TB_ADDR_RX_DIAG_ILL_IQ_TRIM0 0x81c1 67 #define TB_ADDR_RX_DIAG_ILL_IQE_TRIM6 0x81c9 68 #define TB_ADDR_RX_DIAG_RXFE_TM3 0x81f8 69 #define TB_ADDR_RX_DIAG_RXFE_TM4 0x81f9 70 #define TB_ADDR_RX_DIAG_LFPSDET_TUNE 0x81dd 71 #define TB_ADDR_RX_DIAG_DFE_CTRL3 0x81d5 72 #define TB_ADDR_RX_DIAG_SC2C_DELAY 0x81e1 73 #define TB_ADDR_RX_REE_VGA_GAIN_NODFE 0x81bf 74 #define TB_ADDR_XCVR_PSM_CAL_TMR 0x4002 75 #define TB_ADDR_XCVR_PSM_A0BYP_TMR 0x4004 76 #define TB_ADDR_XCVR_PSM_A0IN_TMR 0x4003 77 #define TB_ADDR_XCVR_PSM_A1IN_TMR 0x4005 78 #define TB_ADDR_XCVR_PSM_A2IN_TMR 0x4006 79 #define TB_ADDR_XCVR_PSM_A3IN_TMR 0x4007 80 #define TB_ADDR_XCVR_PSM_A4IN_TMR 0x4008 81 #define TB_ADDR_XCVR_PSM_A5IN_TMR 0x4009 82 #define TB_ADDR_XCVR_PSM_A0OUT_TMR 0x400a 83 #define TB_ADDR_XCVR_PSM_A1OUT_TMR 0x400b 84 #define TB_ADDR_XCVR_PSM_A2OUT_TMR 0x400c 85 #define TB_ADDR_XCVR_PSM_A3OUT_TMR 0x400d 86 #define TB_ADDR_XCVR_PSM_A4OUT_TMR 0x400e 87 #define TB_ADDR_XCVR_PSM_A5OUT_TMR 0x400f 88 #define TB_ADDR_TX_RCVDET_EN_TMR 0x4122 89 #define TB_ADDR_TX_RCVDET_ST_TMR 0x4123 90 #define TB_ADDR_XCVR_DIAG_LANE_FCM_EN_MGN_TMR 0x40f2 91 #define TB_ADDR_TX_RCVDETSC_CTRL 0x4124 92 93 /* USB2 PHY register definition */ 94 #define UTMI_REG15 0xaf 95 #define UTMI_AFE_RX_REG0 0x0d 96 #define UTMI_AFE_RX_REG5 0x12 97 #define UTMI_AFE_BC_REG4 0x29 98 99 /* Align UTMI_AFE_RX_REG0 bit[7:6] define */ 100 enum usb2_disconn_threshold { 101 USB2_DISCONN_THRESHOLD_575 = 0x0, 102 USB2_DISCONN_THRESHOLD_610 = 0x1, 103 USB2_DISCONN_THRESHOLD_645 = 0x3, 104 }; 105 106 #define RX_USB2_DISCONN_MASK GENMASK(7, 6) 107 108 /* TB_ADDR_TX_RCVDETSC_CTRL */ 109 #define RXDET_IN_P3_32KHZ BIT(0) 110 /* 111 * UTMI_REG15 112 * 113 * Gate how many us for the txvalid signal until analog 114 * HS/FS transmitters have powered up 115 */ 116 #define TXVALID_GATE_THRESHOLD_HS_MASK (BIT(4) | BIT(5)) 117 /* 0us, txvalid is ready just after HS/FS transmitters have powered up */ 118 #define TXVALID_GATE_THRESHOLD_HS_0US (BIT(4) | BIT(5)) 119 120 #define SET_B_SESSION_VALID (BIT(6) | BIT(5)) 121 #define CLR_B_SESSION_VALID (BIT(6)) 122 123 struct cdns_reg_pairs { 124 u16 val; 125 u32 off; 126 }; 127 128 struct cdns_salvo_data { 129 u8 reg_offset_shift; 130 const struct cdns_reg_pairs *init_sequence_val; 131 u8 init_sequence_length; 132 }; 133 134 struct cdns_salvo_phy { 135 struct phy *phy; 136 struct clk *clk; 137 void __iomem *base; 138 struct cdns_salvo_data *data; 139 enum usb2_disconn_threshold usb2_disconn; 140 }; 141 142 static const struct of_device_id cdns_salvo_phy_of_match[]; 143 static const struct cdns_salvo_data cdns_nxp_salvo_data; 144 145 static bool cdns_is_nxp_phy(struct cdns_salvo_phy *salvo_phy) 146 { 147 return salvo_phy->data == &cdns_nxp_salvo_data; 148 } 149 150 static u16 cdns_salvo_read(struct cdns_salvo_phy *salvo_phy, u32 offset, u32 reg) 151 { 152 return (u16)readl(salvo_phy->base + offset + 153 reg * (1 << salvo_phy->data->reg_offset_shift)); 154 } 155 156 static void cdns_salvo_write(struct cdns_salvo_phy *salvo_phy, u32 offset, 157 u32 reg, u16 val) 158 { 159 writel(val, salvo_phy->base + offset + 160 reg * (1 << salvo_phy->data->reg_offset_shift)); 161 } 162 163 /* 164 * Below bringup sequence pair are from Cadence PHY's User Guide 165 * and NXP platform tuning results. 166 */ 167 static const struct cdns_reg_pairs cdns_nxp_sequence_pair[] = { 168 {0x0830, PHY_PMA_CMN_CTRL1}, 169 {0x0010, TB_ADDR_CMN_DIAG_HSCLK_SEL}, 170 {0x00f0, TB_ADDR_CMN_PLL0_VCOCAL_INIT_TMR}, 171 {0x0018, TB_ADDR_CMN_PLL0_VCOCAL_ITER_TMR}, 172 {0x00d0, TB_ADDR_CMN_PLL0_INTDIV}, 173 {0x4aaa, TB_ADDR_CMN_PLL0_FRACDIV}, 174 {0x0034, TB_ADDR_CMN_PLL0_HIGH_THR}, 175 {0x01ee, TB_ADDR_CMN_PLL0_SS_CTRL1}, 176 {0x7f03, TB_ADDR_CMN_PLL0_SS_CTRL2}, 177 {0x0020, TB_ADDR_CMN_PLL0_DSM_DIAG}, 178 {0x0000, TB_ADDR_CMN_DIAG_PLL0_OVRD}, 179 {0x0000, TB_ADDR_CMN_DIAG_PLL0_FBH_OVRD}, 180 {0x0000, TB_ADDR_CMN_DIAG_PLL0_FBL_OVRD}, 181 {0x0007, TB_ADDR_CMN_DIAG_PLL0_V2I_TUNE}, 182 {0x0027, TB_ADDR_CMN_DIAG_PLL0_CP_TUNE}, 183 {0x0008, TB_ADDR_CMN_DIAG_PLL0_LF_PROG}, 184 {0x0022, TB_ADDR_CMN_DIAG_PLL0_TEST_MODE}, 185 {0x000a, TB_ADDR_CMN_PSM_CLK_CTRL}, 186 {0x0139, TB_ADDR_XCVR_DIAG_RX_LANE_CAL_RST_TMR}, 187 {0xbefc, TB_ADDR_XCVR_PSM_RCTRL}, 188 189 {0x7799, TB_ADDR_TX_PSC_A0}, 190 {0x7798, TB_ADDR_TX_PSC_A1}, 191 {0x509b, TB_ADDR_TX_PSC_A2}, 192 {0x0003, TB_ADDR_TX_DIAG_ECTRL_OVRD}, 193 {0x509b, TB_ADDR_TX_PSC_A3}, 194 {0x2090, TB_ADDR_TX_PSC_CAL}, 195 {0x2090, TB_ADDR_TX_PSC_RDY}, 196 197 {0xA6FD, TB_ADDR_RX_PSC_A0}, 198 {0xA6FD, TB_ADDR_RX_PSC_A1}, 199 {0xA410, TB_ADDR_RX_PSC_A2}, 200 {0x2410, TB_ADDR_RX_PSC_A3}, 201 202 {0x23FF, TB_ADDR_RX_PSC_CAL}, 203 {0x2010, TB_ADDR_RX_PSC_RDY}, 204 205 {0x0020, TB_ADDR_TX_TXCC_MGNLS_MULT_000}, 206 {0x00ff, TB_ADDR_TX_DIAG_BGREF_PREDRV_DELAY}, 207 {0x0002, TB_ADDR_RX_SLC_CU_ITER_TMR}, 208 {0x0013, TB_ADDR_RX_SIGDET_HL_FILT_TMR}, 209 {0x0000, TB_ADDR_RX_SAMP_DAC_CTRL}, 210 {0x1004, TB_ADDR_RX_DIAG_SIGDET_TUNE}, 211 {0x4041, TB_ADDR_RX_DIAG_LFPSDET_TUNE2}, 212 {0x0480, TB_ADDR_RX_DIAG_BS_TM}, 213 {0x8006, TB_ADDR_RX_DIAG_DFE_CTRL1}, 214 {0x003f, TB_ADDR_RX_DIAG_ILL_IQE_TRIM4}, 215 {0x543f, TB_ADDR_RX_DIAG_ILL_E_TRIM0}, 216 {0x543f, TB_ADDR_RX_DIAG_ILL_IQ_TRIM0}, 217 {0x0000, TB_ADDR_RX_DIAG_ILL_IQE_TRIM6}, 218 {0x8000, TB_ADDR_RX_DIAG_RXFE_TM3}, 219 {0x0003, TB_ADDR_RX_DIAG_RXFE_TM4}, 220 {0x2408, TB_ADDR_RX_DIAG_LFPSDET_TUNE}, 221 {0x05ca, TB_ADDR_RX_DIAG_DFE_CTRL3}, 222 {0x0258, TB_ADDR_RX_DIAG_SC2C_DELAY}, 223 {0x1fff, TB_ADDR_RX_REE_VGA_GAIN_NODFE}, 224 225 {0x02c6, TB_ADDR_XCVR_PSM_CAL_TMR}, 226 {0x0002, TB_ADDR_XCVR_PSM_A0BYP_TMR}, 227 {0x02c6, TB_ADDR_XCVR_PSM_A0IN_TMR}, 228 {0x0010, TB_ADDR_XCVR_PSM_A1IN_TMR}, 229 {0x0010, TB_ADDR_XCVR_PSM_A2IN_TMR}, 230 {0x0010, TB_ADDR_XCVR_PSM_A3IN_TMR}, 231 {0x0010, TB_ADDR_XCVR_PSM_A4IN_TMR}, 232 {0x0010, TB_ADDR_XCVR_PSM_A5IN_TMR}, 233 234 {0x0002, TB_ADDR_XCVR_PSM_A0OUT_TMR}, 235 {0x0002, TB_ADDR_XCVR_PSM_A1OUT_TMR}, 236 {0x0002, TB_ADDR_XCVR_PSM_A2OUT_TMR}, 237 {0x0002, TB_ADDR_XCVR_PSM_A3OUT_TMR}, 238 {0x0002, TB_ADDR_XCVR_PSM_A4OUT_TMR}, 239 {0x0002, TB_ADDR_XCVR_PSM_A5OUT_TMR}, 240 /* Change rx detect parameter */ 241 {0x0960, TB_ADDR_TX_RCVDET_EN_TMR}, 242 {0x01e0, TB_ADDR_TX_RCVDET_ST_TMR}, 243 {0x0090, TB_ADDR_XCVR_DIAG_LANE_FCM_EN_MGN_TMR}, 244 }; 245 246 static int cdns_salvo_phy_init(struct phy *phy) 247 { 248 struct cdns_salvo_phy *salvo_phy = phy_get_drvdata(phy); 249 struct cdns_salvo_data *data = salvo_phy->data; 250 int ret, i; 251 u16 value; 252 253 ret = clk_prepare_enable(salvo_phy->clk); 254 if (ret) 255 return ret; 256 257 for (i = 0; i < data->init_sequence_length; i++) { 258 const struct cdns_reg_pairs *reg_pair = data->init_sequence_val + i; 259 260 cdns_salvo_write(salvo_phy, USB3_PHY_OFFSET, reg_pair->off, reg_pair->val); 261 } 262 263 /* RXDET_IN_P3_32KHZ, Receiver detect slow clock enable */ 264 value = cdns_salvo_read(salvo_phy, USB3_PHY_OFFSET, TB_ADDR_TX_RCVDETSC_CTRL); 265 value |= RXDET_IN_P3_32KHZ; 266 cdns_salvo_write(salvo_phy, USB3_PHY_OFFSET, TB_ADDR_TX_RCVDETSC_CTRL, 267 RXDET_IN_P3_32KHZ); 268 269 value = cdns_salvo_read(salvo_phy, USB2_PHY_OFFSET, UTMI_REG15); 270 value &= ~TXVALID_GATE_THRESHOLD_HS_MASK; 271 cdns_salvo_write(salvo_phy, USB2_PHY_OFFSET, UTMI_REG15, 272 value | TXVALID_GATE_THRESHOLD_HS_0US); 273 274 cdns_salvo_write(salvo_phy, USB2_PHY_OFFSET, UTMI_AFE_RX_REG5, 0x5); 275 276 value = cdns_salvo_read(salvo_phy, USB2_PHY_OFFSET, UTMI_AFE_RX_REG0); 277 value &= ~RX_USB2_DISCONN_MASK; 278 value = FIELD_PREP(RX_USB2_DISCONN_MASK, salvo_phy->usb2_disconn); 279 cdns_salvo_write(salvo_phy, USB2_PHY_OFFSET, UTMI_AFE_RX_REG0, value); 280 281 udelay(10); 282 283 clk_disable_unprepare(salvo_phy->clk); 284 285 return ret; 286 } 287 288 static int cdns_salvo_phy_power_on(struct phy *phy) 289 { 290 struct cdns_salvo_phy *salvo_phy = phy_get_drvdata(phy); 291 292 return clk_prepare_enable(salvo_phy->clk); 293 } 294 295 static int cdns_salvo_phy_power_off(struct phy *phy) 296 { 297 struct cdns_salvo_phy *salvo_phy = phy_get_drvdata(phy); 298 299 clk_disable_unprepare(salvo_phy->clk); 300 301 return 0; 302 } 303 304 static int cdns_salvo_set_mode(struct phy *phy, enum phy_mode mode, int submode) 305 { 306 struct cdns_salvo_phy *salvo_phy = phy_get_drvdata(phy); 307 308 if (!cdns_is_nxp_phy(salvo_phy)) 309 return 0; 310 311 if (mode == PHY_MODE_USB_DEVICE) 312 cdns_salvo_write(salvo_phy, USB2_PHY_OFFSET, UTMI_AFE_BC_REG4, 313 SET_B_SESSION_VALID); 314 else 315 cdns_salvo_write(salvo_phy, USB2_PHY_OFFSET, UTMI_AFE_BC_REG4, 316 CLR_B_SESSION_VALID); 317 318 return 0; 319 } 320 321 static const struct phy_ops cdns_salvo_phy_ops = { 322 .init = cdns_salvo_phy_init, 323 .power_on = cdns_salvo_phy_power_on, 324 .power_off = cdns_salvo_phy_power_off, 325 .owner = THIS_MODULE, 326 .set_mode = cdns_salvo_set_mode, 327 }; 328 329 static int cdns_salvo_phy_probe(struct platform_device *pdev) 330 { 331 struct phy_provider *phy_provider; 332 struct device *dev = &pdev->dev; 333 struct cdns_salvo_phy *salvo_phy; 334 struct cdns_salvo_data *data; 335 u32 val; 336 337 data = (struct cdns_salvo_data *)of_device_get_match_data(dev); 338 salvo_phy = devm_kzalloc(dev, sizeof(*salvo_phy), GFP_KERNEL); 339 if (!salvo_phy) 340 return -ENOMEM; 341 342 salvo_phy->data = data; 343 salvo_phy->clk = devm_clk_get_optional(dev, "salvo_phy_clk"); 344 if (IS_ERR(salvo_phy->clk)) 345 return PTR_ERR(salvo_phy->clk); 346 347 if (of_property_read_u32(dev->of_node, "cdns,usb2-disconnect-threshold-microvolt", &val)) 348 val = 575; 349 350 if (val < 610) 351 salvo_phy->usb2_disconn = USB2_DISCONN_THRESHOLD_575; 352 else if (val < 645) 353 salvo_phy->usb2_disconn = USB2_DISCONN_THRESHOLD_610; 354 else 355 salvo_phy->usb2_disconn = USB2_DISCONN_THRESHOLD_645; 356 357 salvo_phy->base = devm_platform_ioremap_resource(pdev, 0); 358 if (IS_ERR(salvo_phy->base)) 359 return PTR_ERR(salvo_phy->base); 360 361 salvo_phy->phy = devm_phy_create(dev, NULL, &cdns_salvo_phy_ops); 362 if (IS_ERR(salvo_phy->phy)) 363 return PTR_ERR(salvo_phy->phy); 364 365 phy_set_drvdata(salvo_phy->phy, salvo_phy); 366 367 phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); 368 return PTR_ERR_OR_ZERO(phy_provider); 369 } 370 371 static const struct cdns_salvo_data cdns_nxp_salvo_data = { 372 2, 373 cdns_nxp_sequence_pair, 374 ARRAY_SIZE(cdns_nxp_sequence_pair), 375 }; 376 377 static const struct of_device_id cdns_salvo_phy_of_match[] = { 378 { 379 .compatible = "nxp,salvo-phy", 380 .data = &cdns_nxp_salvo_data, 381 }, 382 {} 383 }; 384 MODULE_DEVICE_TABLE(of, cdns_salvo_phy_of_match); 385 386 static struct platform_driver cdns_salvo_phy_driver = { 387 .probe = cdns_salvo_phy_probe, 388 .driver = { 389 .name = "cdns-salvo-phy", 390 .of_match_table = cdns_salvo_phy_of_match, 391 } 392 }; 393 module_platform_driver(cdns_salvo_phy_driver); 394 395 MODULE_AUTHOR("Peter Chen <peter.chen@nxp.com>"); 396 MODULE_LICENSE("GPL v2"); 397 MODULE_DESCRIPTION("Cadence SALVO PHY Driver"); 398