1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (C) 2016-2018 Broadcom 4 */ 5 6 #include <linux/delay.h> 7 #include <linux/io.h> 8 #include <linux/module.h> 9 #include <linux/of.h> 10 #include <linux/phy/phy.h> 11 #include <linux/platform_device.h> 12 13 enum bcm_usb_phy_version { 14 BCM_SR_USB_COMBO_PHY, 15 BCM_SR_USB_HS_PHY, 16 }; 17 18 enum bcm_usb_phy_reg { 19 PLL_NDIV_FRAC, 20 PLL_NDIV_INT, 21 PLL_CTRL, 22 PHY_CTRL, 23 PHY_PLL_CTRL, 24 }; 25 26 /* USB PHY registers */ 27 28 static const u8 bcm_usb_combo_phy_ss[] = { 29 [PLL_CTRL] = 0x18, 30 [PHY_CTRL] = 0x14, 31 }; 32 33 static const u8 bcm_usb_combo_phy_hs[] = { 34 [PLL_NDIV_FRAC] = 0x04, 35 [PLL_NDIV_INT] = 0x08, 36 [PLL_CTRL] = 0x0c, 37 [PHY_CTRL] = 0x10, 38 }; 39 40 #define HSPLL_NDIV_INT_VAL 0x13 41 #define HSPLL_NDIV_FRAC_VAL 0x1005 42 43 static const u8 bcm_usb_hs_phy[] = { 44 [PLL_NDIV_FRAC] = 0x0, 45 [PLL_NDIV_INT] = 0x4, 46 [PLL_CTRL] = 0x8, 47 [PHY_CTRL] = 0xc, 48 }; 49 50 enum pll_ctrl_bits { 51 PLL_RESETB, 52 SSPLL_SUSPEND_EN, 53 PLL_SEQ_START, 54 PLL_LOCK, 55 PLL_PDIV, 56 }; 57 58 static const u8 u3pll_ctrl[] = { 59 [PLL_RESETB] = 0, 60 [SSPLL_SUSPEND_EN] = 1, 61 [PLL_SEQ_START] = 2, 62 [PLL_LOCK] = 3, 63 }; 64 65 #define HSPLL_PDIV_MASK 0xF 66 #define HSPLL_PDIV_VAL 0x1 67 68 static const u8 u2pll_ctrl[] = { 69 [PLL_PDIV] = 1, 70 [PLL_RESETB] = 5, 71 [PLL_LOCK] = 6, 72 }; 73 74 enum bcm_usb_phy_ctrl_bits { 75 CORERDY, 76 AFE_LDO_PWRDWNB, 77 AFE_PLL_PWRDWNB, 78 AFE_BG_PWRDWNB, 79 PHY_ISO, 80 PHY_RESETB, 81 PHY_PCTL, 82 }; 83 84 #define PHY_PCTL_MASK 0xffff 85 /* 86 * 0x0806 of PCTL_VAL has below bits set 87 * BIT-8 : refclk divider 1 88 * BIT-3:2: device mode; mode is not effect 89 * BIT-1: soft reset active low 90 */ 91 #define HSPHY_PCTL_VAL 0x0806 92 #define SSPHY_PCTL_VAL 0x0006 93 94 static const u8 u3phy_ctrl[] = { 95 [PHY_RESETB] = 1, 96 [PHY_PCTL] = 2, 97 }; 98 99 static const u8 u2phy_ctrl[] = { 100 [CORERDY] = 0, 101 [AFE_LDO_PWRDWNB] = 1, 102 [AFE_PLL_PWRDWNB] = 2, 103 [AFE_BG_PWRDWNB] = 3, 104 [PHY_ISO] = 4, 105 [PHY_RESETB] = 5, 106 [PHY_PCTL] = 6, 107 }; 108 109 struct bcm_usb_phy_cfg { 110 uint32_t type; 111 uint32_t version; 112 void __iomem *regs; 113 struct phy *phy; 114 const u8 *offset; 115 }; 116 117 #define PLL_LOCK_RETRY_COUNT 1000 118 119 enum bcm_usb_phy_type { 120 USB_HS_PHY, 121 USB_SS_PHY, 122 }; 123 124 #define NUM_BCM_SR_USB_COMBO_PHYS 2 125 126 static inline void bcm_usb_reg32_clrbits(void __iomem *addr, uint32_t clear) 127 { 128 writel(readl(addr) & ~clear, addr); 129 } 130 131 static inline void bcm_usb_reg32_setbits(void __iomem *addr, uint32_t set) 132 { 133 writel(readl(addr) | set, addr); 134 } 135 136 static int bcm_usb_pll_lock_check(void __iomem *addr, u32 bit) 137 { 138 int retry; 139 u32 rd_data; 140 141 retry = PLL_LOCK_RETRY_COUNT; 142 do { 143 rd_data = readl(addr); 144 if (rd_data & bit) 145 return 0; 146 udelay(1); 147 } while (--retry > 0); 148 149 pr_err("%s: FAIL\n", __func__); 150 return -ETIMEDOUT; 151 } 152 153 static int bcm_usb_ss_phy_init(struct bcm_usb_phy_cfg *phy_cfg) 154 { 155 int ret = 0; 156 void __iomem *regs = phy_cfg->regs; 157 const u8 *offset; 158 u32 rd_data; 159 160 offset = phy_cfg->offset; 161 162 /* Set pctl with mode and soft reset */ 163 rd_data = readl(regs + offset[PHY_CTRL]); 164 rd_data &= ~(PHY_PCTL_MASK << u3phy_ctrl[PHY_PCTL]); 165 rd_data |= (SSPHY_PCTL_VAL << u3phy_ctrl[PHY_PCTL]); 166 writel(rd_data, regs + offset[PHY_CTRL]); 167 168 bcm_usb_reg32_clrbits(regs + offset[PLL_CTRL], 169 BIT(u3pll_ctrl[SSPLL_SUSPEND_EN])); 170 bcm_usb_reg32_setbits(regs + offset[PLL_CTRL], 171 BIT(u3pll_ctrl[PLL_SEQ_START])); 172 bcm_usb_reg32_setbits(regs + offset[PLL_CTRL], 173 BIT(u3pll_ctrl[PLL_RESETB])); 174 175 /* Maximum timeout for PLL reset done */ 176 msleep(30); 177 178 ret = bcm_usb_pll_lock_check(regs + offset[PLL_CTRL], 179 BIT(u3pll_ctrl[PLL_LOCK])); 180 181 return ret; 182 } 183 184 static int bcm_usb_hs_phy_init(struct bcm_usb_phy_cfg *phy_cfg) 185 { 186 int ret = 0; 187 void __iomem *regs = phy_cfg->regs; 188 const u8 *offset; 189 u32 rd_data; 190 191 offset = phy_cfg->offset; 192 193 writel(HSPLL_NDIV_INT_VAL, regs + offset[PLL_NDIV_INT]); 194 writel(HSPLL_NDIV_FRAC_VAL, regs + offset[PLL_NDIV_FRAC]); 195 196 rd_data = readl(regs + offset[PLL_CTRL]); 197 rd_data &= ~(HSPLL_PDIV_MASK << u2pll_ctrl[PLL_PDIV]); 198 rd_data |= (HSPLL_PDIV_VAL << u2pll_ctrl[PLL_PDIV]); 199 writel(rd_data, regs + offset[PLL_CTRL]); 200 201 /* Set Core Ready high */ 202 bcm_usb_reg32_setbits(regs + offset[PHY_CTRL], 203 BIT(u2phy_ctrl[CORERDY])); 204 205 /* Maximum timeout for Core Ready done */ 206 msleep(30); 207 208 bcm_usb_reg32_setbits(regs + offset[PLL_CTRL], 209 BIT(u2pll_ctrl[PLL_RESETB])); 210 bcm_usb_reg32_setbits(regs + offset[PHY_CTRL], 211 BIT(u2phy_ctrl[PHY_RESETB])); 212 213 214 rd_data = readl(regs + offset[PHY_CTRL]); 215 rd_data &= ~(PHY_PCTL_MASK << u2phy_ctrl[PHY_PCTL]); 216 rd_data |= (HSPHY_PCTL_VAL << u2phy_ctrl[PHY_PCTL]); 217 writel(rd_data, regs + offset[PHY_CTRL]); 218 219 /* Maximum timeout for PLL reset done */ 220 msleep(30); 221 222 ret = bcm_usb_pll_lock_check(regs + offset[PLL_CTRL], 223 BIT(u2pll_ctrl[PLL_LOCK])); 224 225 return ret; 226 } 227 228 static int bcm_usb_phy_reset(struct phy *phy) 229 { 230 struct bcm_usb_phy_cfg *phy_cfg = phy_get_drvdata(phy); 231 void __iomem *regs = phy_cfg->regs; 232 const u8 *offset; 233 234 offset = phy_cfg->offset; 235 236 if (phy_cfg->type == USB_HS_PHY) { 237 bcm_usb_reg32_clrbits(regs + offset[PHY_CTRL], 238 BIT(u2phy_ctrl[CORERDY])); 239 bcm_usb_reg32_setbits(regs + offset[PHY_CTRL], 240 BIT(u2phy_ctrl[CORERDY])); 241 } 242 243 return 0; 244 } 245 246 static int bcm_usb_phy_init(struct phy *phy) 247 { 248 struct bcm_usb_phy_cfg *phy_cfg = phy_get_drvdata(phy); 249 int ret = -EINVAL; 250 251 if (phy_cfg->type == USB_SS_PHY) 252 ret = bcm_usb_ss_phy_init(phy_cfg); 253 else if (phy_cfg->type == USB_HS_PHY) 254 ret = bcm_usb_hs_phy_init(phy_cfg); 255 256 return ret; 257 } 258 259 static struct phy_ops sr_phy_ops = { 260 .init = bcm_usb_phy_init, 261 .reset = bcm_usb_phy_reset, 262 .owner = THIS_MODULE, 263 }; 264 265 static struct phy *bcm_usb_phy_xlate(struct device *dev, 266 struct of_phandle_args *args) 267 { 268 struct bcm_usb_phy_cfg *phy_cfg; 269 int phy_idx; 270 271 phy_cfg = dev_get_drvdata(dev); 272 if (!phy_cfg) 273 return ERR_PTR(-EINVAL); 274 275 if (phy_cfg->version == BCM_SR_USB_COMBO_PHY) { 276 phy_idx = args->args[0]; 277 278 if (WARN_ON(phy_idx > 1)) 279 return ERR_PTR(-ENODEV); 280 281 return phy_cfg[phy_idx].phy; 282 } else 283 return phy_cfg->phy; 284 } 285 286 static int bcm_usb_phy_create(struct device *dev, struct device_node *node, 287 void __iomem *regs, uint32_t version) 288 { 289 struct bcm_usb_phy_cfg *phy_cfg; 290 int idx; 291 292 if (version == BCM_SR_USB_COMBO_PHY) { 293 phy_cfg = devm_kzalloc(dev, NUM_BCM_SR_USB_COMBO_PHYS * 294 sizeof(struct bcm_usb_phy_cfg), 295 GFP_KERNEL); 296 if (!phy_cfg) 297 return -ENOMEM; 298 299 for (idx = 0; idx < NUM_BCM_SR_USB_COMBO_PHYS; idx++) { 300 phy_cfg[idx].regs = regs; 301 phy_cfg[idx].version = version; 302 if (idx == 0) { 303 phy_cfg[idx].offset = bcm_usb_combo_phy_hs; 304 phy_cfg[idx].type = USB_HS_PHY; 305 } else { 306 phy_cfg[idx].offset = bcm_usb_combo_phy_ss; 307 phy_cfg[idx].type = USB_SS_PHY; 308 } 309 phy_cfg[idx].phy = devm_phy_create(dev, node, 310 &sr_phy_ops); 311 if (IS_ERR(phy_cfg[idx].phy)) 312 return PTR_ERR(phy_cfg[idx].phy); 313 314 phy_set_drvdata(phy_cfg[idx].phy, &phy_cfg[idx]); 315 } 316 } else if (version == BCM_SR_USB_HS_PHY) { 317 phy_cfg = devm_kzalloc(dev, sizeof(struct bcm_usb_phy_cfg), 318 GFP_KERNEL); 319 if (!phy_cfg) 320 return -ENOMEM; 321 322 phy_cfg->regs = regs; 323 phy_cfg->version = version; 324 phy_cfg->offset = bcm_usb_hs_phy; 325 phy_cfg->type = USB_HS_PHY; 326 phy_cfg->phy = devm_phy_create(dev, node, &sr_phy_ops); 327 if (IS_ERR(phy_cfg->phy)) 328 return PTR_ERR(phy_cfg->phy); 329 330 phy_set_drvdata(phy_cfg->phy, phy_cfg); 331 } else 332 return -ENODEV; 333 334 dev_set_drvdata(dev, phy_cfg); 335 336 return 0; 337 } 338 339 static const struct of_device_id bcm_usb_phy_of_match[] = { 340 { 341 .compatible = "brcm,sr-usb-combo-phy", 342 .data = (void *)BCM_SR_USB_COMBO_PHY, 343 }, 344 { 345 .compatible = "brcm,sr-usb-hs-phy", 346 .data = (void *)BCM_SR_USB_HS_PHY, 347 }, 348 { /* sentinel */ }, 349 }; 350 MODULE_DEVICE_TABLE(of, bcm_usb_phy_of_match); 351 352 static int bcm_usb_phy_probe(struct platform_device *pdev) 353 { 354 struct device *dev = &pdev->dev; 355 struct device_node *dn = dev->of_node; 356 const struct of_device_id *of_id; 357 struct resource *res; 358 void __iomem *regs; 359 int ret; 360 enum bcm_usb_phy_version version; 361 struct phy_provider *phy_provider; 362 363 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 364 regs = devm_ioremap_resource(dev, res); 365 if (IS_ERR(regs)) 366 return PTR_ERR(regs); 367 368 of_id = of_match_node(bcm_usb_phy_of_match, dn); 369 if (of_id) 370 version = (enum bcm_usb_phy_version)of_id->data; 371 else 372 return -ENODEV; 373 374 ret = bcm_usb_phy_create(dev, dn, regs, version); 375 if (ret) 376 return ret; 377 378 phy_provider = devm_of_phy_provider_register(dev, bcm_usb_phy_xlate); 379 380 return PTR_ERR_OR_ZERO(phy_provider); 381 } 382 383 static struct platform_driver bcm_usb_phy_driver = { 384 .driver = { 385 .name = "phy-bcm-sr-usb", 386 .of_match_table = bcm_usb_phy_of_match, 387 }, 388 .probe = bcm_usb_phy_probe, 389 }; 390 module_platform_driver(bcm_usb_phy_driver); 391 392 MODULE_AUTHOR("Broadcom"); 393 MODULE_DESCRIPTION("Broadcom stingray USB Phy driver"); 394 MODULE_LICENSE("GPL v2"); 395