1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * BCM6328 USBH PHY Controller Driver 4 * 5 * Copyright (C) 2020 Álvaro Fernández Rojas <noltari@gmail.com> 6 * Copyright (C) 2015 Simon Arlott 7 * 8 * Derived from bcm963xx_4.12L.06B_consumer/kernel/linux/arch/mips/bcm963xx/setup.c: 9 * Copyright (C) 2002 Broadcom Corporation 10 * 11 * Derived from OpenWrt patches: 12 * Copyright (C) 2013 Jonas Gorski <jonas.gorski@gmail.com> 13 * Copyright (C) 2013 Florian Fainelli <f.fainelli@gmail.com> 14 * Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr> 15 */ 16 17 #include <linux/clk.h> 18 #include <linux/io.h> 19 #include <linux/module.h> 20 #include <linux/phy/phy.h> 21 #include <linux/platform_device.h> 22 #include <linux/reset.h> 23 24 /* USBH control register offsets */ 25 enum usbh_regs { 26 USBH_BRT_CONTROL1 = 0, 27 USBH_BRT_CONTROL2, 28 USBH_BRT_STATUS1, 29 USBH_BRT_STATUS2, 30 USBH_UTMI_CONTROL1, 31 #define USBH_UC1_DEV_MODE_SEL BIT(0) 32 USBH_TEST_PORT_CONTROL, 33 USBH_PLL_CONTROL1, 34 #define USBH_PLLC_REFCLKSEL_SHIFT 0 35 #define USBH_PLLC_REFCLKSEL_MASK (0x3 << USBH_PLLC_REFCLKSEL_SHIFT) 36 #define USBH_PLLC_CLKSEL_SHIFT 2 37 #define USBH_PLLC_CLKSEL_MASK (0x3 << USBH_PLLC_CLKSEL_MASK) 38 #define USBH_PLLC_XTAL_PWRDWNB BIT(4) 39 #define USBH_PLLC_PLL_PWRDWNB BIT(5) 40 #define USBH_PLLC_PLL_CALEN BIT(6) 41 #define USBH_PLLC_PHYPLL_BYP BIT(7) 42 #define USBH_PLLC_PLL_RESET BIT(8) 43 #define USBH_PLLC_PLL_IDDQ_PWRDN BIT(9) 44 #define USBH_PLLC_PLL_PWRDN_DELAY BIT(10) 45 #define USBH_6318_PLLC_PLL_SUSPEND_EN BIT(27) 46 #define USBH_6318_PLLC_PHYPLL_BYP BIT(29) 47 #define USBH_6318_PLLC_PLL_RESET BIT(30) 48 #define USBH_6318_PLLC_PLL_IDDQ_PWRDN BIT(31) 49 USBH_SWAP_CONTROL, 50 #define USBH_SC_OHCI_DATA_SWAP BIT(0) 51 #define USBH_SC_OHCI_ENDIAN_SWAP BIT(1) 52 #define USBH_SC_OHCI_LOGICAL_ADDR_EN BIT(2) 53 #define USBH_SC_EHCI_DATA_SWAP BIT(3) 54 #define USBH_SC_EHCI_ENDIAN_SWAP BIT(4) 55 #define USBH_SC_EHCI_LOGICAL_ADDR_EN BIT(5) 56 #define USBH_SC_USB_DEVICE_SEL BIT(6) 57 USBH_GENERIC_CONTROL, 58 #define USBH_GC_PLL_SUSPEND_EN BIT(1) 59 USBH_FRAME_ADJUST_VALUE, 60 USBH_SETUP, 61 #define USBH_S_IOC BIT(4) 62 #define USBH_S_IPP BIT(5) 63 USBH_MDIO, 64 USBH_MDIO32, 65 USBH_USB_SIM_CONTROL, 66 #define USBH_USC_LADDR_SEL BIT(5) 67 68 __USBH_ENUM_SIZE 69 }; 70 71 struct bcm63xx_usbh_phy_variant { 72 /* Registers */ 73 long regs[__USBH_ENUM_SIZE]; 74 75 /* PLLC bits to set/clear for power on */ 76 u32 power_pllc_clr; 77 u32 power_pllc_set; 78 79 /* Setup bits to set/clear for power on */ 80 u32 setup_clr; 81 u32 setup_set; 82 83 /* Swap Control bits to set */ 84 u32 swapctl_dev_set; 85 86 /* Test Port Control value to set if non-zero */ 87 u32 tpc_val; 88 89 /* USB Sim Control bits to set */ 90 u32 usc_set; 91 92 /* UTMI Control 1 bits to set */ 93 u32 utmictl1_dev_set; 94 }; 95 96 struct bcm63xx_usbh_phy { 97 void __iomem *base; 98 struct clk *usbh_clk; 99 struct clk *usb_ref_clk; 100 struct reset_control *reset; 101 const struct bcm63xx_usbh_phy_variant *variant; 102 bool device_mode; 103 }; 104 105 static const struct bcm63xx_usbh_phy_variant usbh_bcm6318 = { 106 .regs = { 107 [USBH_BRT_CONTROL1] = -1, 108 [USBH_BRT_CONTROL2] = -1, 109 [USBH_BRT_STATUS1] = -1, 110 [USBH_BRT_STATUS2] = -1, 111 [USBH_UTMI_CONTROL1] = 0x2c, 112 [USBH_TEST_PORT_CONTROL] = 0x1c, 113 [USBH_PLL_CONTROL1] = 0x04, 114 [USBH_SWAP_CONTROL] = 0x0c, 115 [USBH_GENERIC_CONTROL] = -1, 116 [USBH_FRAME_ADJUST_VALUE] = 0x08, 117 [USBH_SETUP] = 0x00, 118 [USBH_MDIO] = 0x14, 119 [USBH_MDIO32] = 0x18, 120 [USBH_USB_SIM_CONTROL] = 0x20, 121 }, 122 .power_pllc_clr = USBH_6318_PLLC_PLL_IDDQ_PWRDN, 123 .power_pllc_set = USBH_6318_PLLC_PLL_SUSPEND_EN, 124 .setup_set = USBH_S_IOC, 125 .swapctl_dev_set = USBH_SC_USB_DEVICE_SEL, 126 .usc_set = USBH_USC_LADDR_SEL, 127 .utmictl1_dev_set = USBH_UC1_DEV_MODE_SEL, 128 }; 129 130 static const struct bcm63xx_usbh_phy_variant usbh_bcm6328 = { 131 .regs = { 132 [USBH_BRT_CONTROL1] = 0x00, 133 [USBH_BRT_CONTROL2] = 0x04, 134 [USBH_BRT_STATUS1] = 0x08, 135 [USBH_BRT_STATUS2] = 0x0c, 136 [USBH_UTMI_CONTROL1] = 0x10, 137 [USBH_TEST_PORT_CONTROL] = 0x14, 138 [USBH_PLL_CONTROL1] = 0x18, 139 [USBH_SWAP_CONTROL] = 0x1c, 140 [USBH_GENERIC_CONTROL] = 0x20, 141 [USBH_FRAME_ADJUST_VALUE] = 0x24, 142 [USBH_SETUP] = 0x28, 143 [USBH_MDIO] = 0x2c, 144 [USBH_MDIO32] = 0x30, 145 [USBH_USB_SIM_CONTROL] = 0x34, 146 }, 147 .setup_set = USBH_S_IOC, 148 .swapctl_dev_set = USBH_SC_USB_DEVICE_SEL, 149 .utmictl1_dev_set = USBH_UC1_DEV_MODE_SEL, 150 }; 151 152 static const struct bcm63xx_usbh_phy_variant usbh_bcm6358 = { 153 .regs = { 154 [USBH_BRT_CONTROL1] = -1, 155 [USBH_BRT_CONTROL2] = -1, 156 [USBH_BRT_STATUS1] = -1, 157 [USBH_BRT_STATUS2] = -1, 158 [USBH_UTMI_CONTROL1] = -1, 159 [USBH_TEST_PORT_CONTROL] = 0x24, 160 [USBH_PLL_CONTROL1] = -1, 161 [USBH_SWAP_CONTROL] = 0x00, 162 [USBH_GENERIC_CONTROL] = -1, 163 [USBH_FRAME_ADJUST_VALUE] = -1, 164 [USBH_SETUP] = -1, 165 [USBH_MDIO] = -1, 166 [USBH_MDIO32] = -1, 167 [USBH_USB_SIM_CONTROL] = -1, 168 }, 169 /* 170 * The magic value comes for the original vendor BSP 171 * and is needed for USB to work. Datasheet does not 172 * help, so the magic value is used as-is. 173 */ 174 .tpc_val = 0x1c0020, 175 }; 176 177 static const struct bcm63xx_usbh_phy_variant usbh_bcm6368 = { 178 .regs = { 179 [USBH_BRT_CONTROL1] = 0x00, 180 [USBH_BRT_CONTROL2] = 0x04, 181 [USBH_BRT_STATUS1] = 0x08, 182 [USBH_BRT_STATUS2] = 0x0c, 183 [USBH_UTMI_CONTROL1] = 0x10, 184 [USBH_TEST_PORT_CONTROL] = 0x14, 185 [USBH_PLL_CONTROL1] = 0x18, 186 [USBH_SWAP_CONTROL] = 0x1c, 187 [USBH_GENERIC_CONTROL] = -1, 188 [USBH_FRAME_ADJUST_VALUE] = 0x24, 189 [USBH_SETUP] = 0x28, 190 [USBH_MDIO] = 0x2c, 191 [USBH_MDIO32] = 0x30, 192 [USBH_USB_SIM_CONTROL] = 0x34, 193 }, 194 .power_pllc_clr = USBH_PLLC_PLL_IDDQ_PWRDN | USBH_PLLC_PLL_PWRDN_DELAY, 195 .setup_set = USBH_S_IOC, 196 .swapctl_dev_set = USBH_SC_USB_DEVICE_SEL, 197 .utmictl1_dev_set = USBH_UC1_DEV_MODE_SEL, 198 }; 199 200 static const struct bcm63xx_usbh_phy_variant usbh_bcm63268 = { 201 .regs = { 202 [USBH_BRT_CONTROL1] = 0x00, 203 [USBH_BRT_CONTROL2] = 0x04, 204 [USBH_BRT_STATUS1] = 0x08, 205 [USBH_BRT_STATUS2] = 0x0c, 206 [USBH_UTMI_CONTROL1] = 0x10, 207 [USBH_TEST_PORT_CONTROL] = 0x14, 208 [USBH_PLL_CONTROL1] = 0x18, 209 [USBH_SWAP_CONTROL] = 0x1c, 210 [USBH_GENERIC_CONTROL] = 0x20, 211 [USBH_FRAME_ADJUST_VALUE] = 0x24, 212 [USBH_SETUP] = 0x28, 213 [USBH_MDIO] = 0x2c, 214 [USBH_MDIO32] = 0x30, 215 [USBH_USB_SIM_CONTROL] = 0x34, 216 }, 217 .power_pllc_clr = USBH_PLLC_PLL_IDDQ_PWRDN | USBH_PLLC_PLL_PWRDN_DELAY, 218 .setup_clr = USBH_S_IPP, 219 .setup_set = USBH_S_IOC, 220 .swapctl_dev_set = USBH_SC_USB_DEVICE_SEL, 221 .utmictl1_dev_set = USBH_UC1_DEV_MODE_SEL, 222 }; 223 224 static inline bool usbh_has_reg(struct bcm63xx_usbh_phy *usbh, int reg) 225 { 226 return (usbh->variant->regs[reg] >= 0); 227 } 228 229 static inline u32 usbh_readl(struct bcm63xx_usbh_phy *usbh, int reg) 230 { 231 return __raw_readl(usbh->base + usbh->variant->regs[reg]); 232 } 233 234 static inline void usbh_writel(struct bcm63xx_usbh_phy *usbh, int reg, 235 u32 value) 236 { 237 __raw_writel(value, usbh->base + usbh->variant->regs[reg]); 238 } 239 240 static int bcm63xx_usbh_phy_init(struct phy *phy) 241 { 242 struct bcm63xx_usbh_phy *usbh = phy_get_drvdata(phy); 243 int ret; 244 245 ret = clk_prepare_enable(usbh->usbh_clk); 246 if (ret) { 247 dev_err(&phy->dev, "unable to enable usbh clock: %d\n", ret); 248 return ret; 249 } 250 251 ret = clk_prepare_enable(usbh->usb_ref_clk); 252 if (ret) { 253 dev_err(&phy->dev, "unable to enable usb_ref clock: %d\n", ret); 254 clk_disable_unprepare(usbh->usbh_clk); 255 return ret; 256 } 257 258 ret = reset_control_reset(usbh->reset); 259 if (ret) { 260 dev_err(&phy->dev, "unable to reset device: %d\n", ret); 261 clk_disable_unprepare(usbh->usb_ref_clk); 262 clk_disable_unprepare(usbh->usbh_clk); 263 return ret; 264 } 265 266 /* Configure to work in native CPU endian */ 267 if (usbh_has_reg(usbh, USBH_SWAP_CONTROL)) { 268 u32 val = usbh_readl(usbh, USBH_SWAP_CONTROL); 269 270 val |= USBH_SC_EHCI_DATA_SWAP; 271 val &= ~USBH_SC_EHCI_ENDIAN_SWAP; 272 273 val |= USBH_SC_OHCI_DATA_SWAP; 274 val &= ~USBH_SC_OHCI_ENDIAN_SWAP; 275 276 if (usbh->device_mode && usbh->variant->swapctl_dev_set) 277 val |= usbh->variant->swapctl_dev_set; 278 279 usbh_writel(usbh, USBH_SWAP_CONTROL, val); 280 } 281 282 if (usbh_has_reg(usbh, USBH_SETUP)) { 283 u32 val = usbh_readl(usbh, USBH_SETUP); 284 285 val |= usbh->variant->setup_set; 286 val &= ~usbh->variant->setup_clr; 287 288 usbh_writel(usbh, USBH_SETUP, val); 289 } 290 291 if (usbh_has_reg(usbh, USBH_USB_SIM_CONTROL)) { 292 u32 val = usbh_readl(usbh, USBH_USB_SIM_CONTROL); 293 294 val |= usbh->variant->usc_set; 295 296 usbh_writel(usbh, USBH_USB_SIM_CONTROL, val); 297 } 298 299 if (usbh->variant->tpc_val && 300 usbh_has_reg(usbh, USBH_TEST_PORT_CONTROL)) 301 usbh_writel(usbh, USBH_TEST_PORT_CONTROL, 302 usbh->variant->tpc_val); 303 304 if (usbh->device_mode && 305 usbh_has_reg(usbh, USBH_UTMI_CONTROL1) && 306 usbh->variant->utmictl1_dev_set) { 307 u32 val = usbh_readl(usbh, USBH_UTMI_CONTROL1); 308 309 val |= usbh->variant->utmictl1_dev_set; 310 311 usbh_writel(usbh, USBH_UTMI_CONTROL1, val); 312 } 313 314 return 0; 315 } 316 317 static int bcm63xx_usbh_phy_power_on(struct phy *phy) 318 { 319 struct bcm63xx_usbh_phy *usbh = phy_get_drvdata(phy); 320 321 if (usbh_has_reg(usbh, USBH_PLL_CONTROL1)) { 322 u32 val = usbh_readl(usbh, USBH_PLL_CONTROL1); 323 324 val |= usbh->variant->power_pllc_set; 325 val &= ~usbh->variant->power_pllc_clr; 326 327 usbh_writel(usbh, USBH_PLL_CONTROL1, val); 328 } 329 330 return 0; 331 } 332 333 static int bcm63xx_usbh_phy_power_off(struct phy *phy) 334 { 335 struct bcm63xx_usbh_phy *usbh = phy_get_drvdata(phy); 336 337 if (usbh_has_reg(usbh, USBH_PLL_CONTROL1)) { 338 u32 val = usbh_readl(usbh, USBH_PLL_CONTROL1); 339 340 val &= ~usbh->variant->power_pllc_set; 341 val |= usbh->variant->power_pllc_clr; 342 343 usbh_writel(usbh, USBH_PLL_CONTROL1, val); 344 } 345 346 return 0; 347 } 348 349 static int bcm63xx_usbh_phy_exit(struct phy *phy) 350 { 351 struct bcm63xx_usbh_phy *usbh = phy_get_drvdata(phy); 352 353 clk_disable_unprepare(usbh->usbh_clk); 354 clk_disable_unprepare(usbh->usb_ref_clk); 355 356 return 0; 357 } 358 359 static const struct phy_ops bcm63xx_usbh_phy_ops = { 360 .exit = bcm63xx_usbh_phy_exit, 361 .init = bcm63xx_usbh_phy_init, 362 .power_off = bcm63xx_usbh_phy_power_off, 363 .power_on = bcm63xx_usbh_phy_power_on, 364 .owner = THIS_MODULE, 365 }; 366 367 static struct phy *bcm63xx_usbh_phy_xlate(struct device *dev, 368 struct of_phandle_args *args) 369 { 370 struct bcm63xx_usbh_phy *usbh = dev_get_drvdata(dev); 371 372 usbh->device_mode = !!args->args[0]; 373 374 return of_phy_simple_xlate(dev, args); 375 } 376 377 static int __init bcm63xx_usbh_phy_probe(struct platform_device *pdev) 378 { 379 struct device *dev = &pdev->dev; 380 struct bcm63xx_usbh_phy *usbh; 381 const struct bcm63xx_usbh_phy_variant *variant; 382 struct phy *phy; 383 struct phy_provider *phy_provider; 384 385 usbh = devm_kzalloc(dev, sizeof(*usbh), GFP_KERNEL); 386 if (!usbh) 387 return -ENOMEM; 388 389 variant = device_get_match_data(dev); 390 if (!variant) 391 return -EINVAL; 392 usbh->variant = variant; 393 394 usbh->base = devm_platform_ioremap_resource(pdev, 0); 395 if (IS_ERR(usbh->base)) 396 return PTR_ERR(usbh->base); 397 398 usbh->reset = devm_reset_control_get_exclusive(dev, NULL); 399 if (IS_ERR(usbh->reset)) { 400 if (PTR_ERR(usbh->reset) != -EPROBE_DEFER) 401 dev_err(dev, "failed to get reset\n"); 402 return PTR_ERR(usbh->reset); 403 } 404 405 usbh->usbh_clk = devm_clk_get_optional(dev, "usbh"); 406 if (IS_ERR(usbh->usbh_clk)) 407 return PTR_ERR(usbh->usbh_clk); 408 409 usbh->usb_ref_clk = devm_clk_get_optional(dev, "usb_ref"); 410 if (IS_ERR(usbh->usb_ref_clk)) 411 return PTR_ERR(usbh->usb_ref_clk); 412 413 phy = devm_phy_create(dev, NULL, &bcm63xx_usbh_phy_ops); 414 if (IS_ERR(phy)) { 415 dev_err(dev, "failed to create PHY\n"); 416 return PTR_ERR(phy); 417 } 418 419 platform_set_drvdata(pdev, usbh); 420 phy_set_drvdata(phy, usbh); 421 422 phy_provider = devm_of_phy_provider_register(dev, 423 bcm63xx_usbh_phy_xlate); 424 if (IS_ERR(phy_provider)) { 425 dev_err(dev, "failed to register PHY provider\n"); 426 return PTR_ERR(phy_provider); 427 } 428 429 dev_dbg(dev, "Registered BCM63xx USB PHY driver\n"); 430 431 return 0; 432 } 433 434 static const struct of_device_id bcm63xx_usbh_phy_ids[] __initconst = { 435 { .compatible = "brcm,bcm6318-usbh-phy", .data = &usbh_bcm6318 }, 436 { .compatible = "brcm,bcm6328-usbh-phy", .data = &usbh_bcm6328 }, 437 { .compatible = "brcm,bcm6358-usbh-phy", .data = &usbh_bcm6358 }, 438 { .compatible = "brcm,bcm6362-usbh-phy", .data = &usbh_bcm6368 }, 439 { .compatible = "brcm,bcm6368-usbh-phy", .data = &usbh_bcm6368 }, 440 { .compatible = "brcm,bcm63268-usbh-phy", .data = &usbh_bcm63268 }, 441 { /* sentinel */ } 442 }; 443 MODULE_DEVICE_TABLE(of, bcm63xx_usbh_phy_ids); 444 445 static struct platform_driver bcm63xx_usbh_phy_driver __refdata = { 446 .driver = { 447 .name = "bcm63xx-usbh-phy", 448 .of_match_table = bcm63xx_usbh_phy_ids, 449 }, 450 .probe = bcm63xx_usbh_phy_probe, 451 }; 452 module_platform_driver(bcm63xx_usbh_phy_driver); 453 454 MODULE_DESCRIPTION("BCM63xx USBH PHY driver"); 455 MODULE_AUTHOR("Álvaro Fernández Rojas <noltari@gmail.com>"); 456 MODULE_AUTHOR("Simon Arlott"); 457 MODULE_LICENSE("GPL"); 458