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