bcma-hcd.c (12540B)
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * Broadcom specific Advanced Microcontroller Bus 4 * Broadcom USB-core driver (BCMA bus glue) 5 * 6 * Copyright 2011-2015 Hauke Mehrtens <hauke@hauke-m.de> 7 * Copyright 2015 Felix Fietkau <nbd@openwrt.org> 8 * 9 * Based on ssb-ohci driver 10 * Copyright 2007 Michael Buesch <m@bues.ch> 11 * 12 * Derived from the OHCI-PCI driver 13 * Copyright 1999 Roman Weissgaerber 14 * Copyright 2000-2002 David Brownell 15 * Copyright 1999 Linus Torvalds 16 * Copyright 1999 Gregory P. Smith 17 * 18 * Derived from the USBcore related parts of Broadcom-SB 19 * Copyright 2005-2011 Broadcom Corporation 20 */ 21#include <linux/bcma/bcma.h> 22#include <linux/delay.h> 23#include <linux/gpio/consumer.h> 24#include <linux/platform_device.h> 25#include <linux/module.h> 26#include <linux/slab.h> 27#include <linux/of.h> 28#include <linux/of_gpio.h> 29#include <linux/of_platform.h> 30#include <linux/usb/ehci_pdriver.h> 31#include <linux/usb/ohci_pdriver.h> 32 33MODULE_AUTHOR("Hauke Mehrtens"); 34MODULE_DESCRIPTION("Common USB driver for BCMA Bus"); 35MODULE_LICENSE("GPL"); 36 37/* See BCMA_CLKCTLST_EXTRESREQ and BCMA_CLKCTLST_EXTRESST */ 38#define USB_BCMA_CLKCTLST_USB_CLK_REQ 0x00000100 39 40struct bcma_hcd_device { 41 struct bcma_device *core; 42 struct platform_device *ehci_dev; 43 struct platform_device *ohci_dev; 44 struct gpio_desc *gpio_desc; 45}; 46 47/* Wait for bitmask in a register to get set or cleared. 48 * timeout is in units of ten-microseconds. 49 */ 50static int bcma_wait_bits(struct bcma_device *dev, u16 reg, u32 bitmask, 51 int timeout) 52{ 53 int i; 54 u32 val; 55 56 for (i = 0; i < timeout; i++) { 57 val = bcma_read32(dev, reg); 58 if ((val & bitmask) == bitmask) 59 return 0; 60 udelay(10); 61 } 62 63 return -ETIMEDOUT; 64} 65 66static void bcma_hcd_4716wa(struct bcma_device *dev) 67{ 68#ifdef CONFIG_BCMA_DRIVER_MIPS 69 /* Work around for 4716 failures. */ 70 if (dev->bus->chipinfo.id == 0x4716) { 71 u32 tmp; 72 73 tmp = bcma_cpu_clock(&dev->bus->drv_mips); 74 if (tmp >= 480000000) 75 tmp = 0x1846b; /* set CDR to 0x11(fast) */ 76 else if (tmp == 453000000) 77 tmp = 0x1046b; /* set CDR to 0x10(slow) */ 78 else 79 tmp = 0; 80 81 /* Change Shim mdio control reg to fix host not acking at 82 * high frequencies 83 */ 84 if (tmp) { 85 bcma_write32(dev, 0x524, 0x1); /* write sel to enable */ 86 udelay(500); 87 88 bcma_write32(dev, 0x524, tmp); 89 udelay(500); 90 bcma_write32(dev, 0x524, 0x4ab); 91 udelay(500); 92 bcma_read32(dev, 0x528); 93 bcma_write32(dev, 0x528, 0x80000000); 94 } 95 } 96#endif /* CONFIG_BCMA_DRIVER_MIPS */ 97} 98 99/* based on arch/mips/brcm-boards/bcm947xx/pcibios.c */ 100static void bcma_hcd_init_chip_mips(struct bcma_device *dev) 101{ 102 u32 tmp; 103 104 /* 105 * USB 2.0 special considerations: 106 * 107 * 1. Since the core supports both OHCI and EHCI functions, it must 108 * only be reset once. 109 * 110 * 2. In addition to the standard SI reset sequence, the Host Control 111 * Register must be programmed to bring the USB core and various 112 * phy components out of reset. 113 */ 114 if (!bcma_core_is_enabled(dev)) { 115 bcma_core_enable(dev, 0); 116 mdelay(10); 117 if (dev->id.rev >= 5) { 118 /* Enable Misc PLL */ 119 tmp = bcma_read32(dev, 0x1e0); 120 tmp |= 0x100; 121 bcma_write32(dev, 0x1e0, tmp); 122 if (bcma_wait_bits(dev, 0x1e0, 1 << 24, 100)) 123 printk(KERN_EMERG "Failed to enable misc PPL!\n"); 124 125 /* Take out of resets */ 126 bcma_write32(dev, 0x200, 0x4ff); 127 udelay(25); 128 bcma_write32(dev, 0x200, 0x6ff); 129 udelay(25); 130 131 /* Make sure digital and AFE are locked in USB PHY */ 132 bcma_write32(dev, 0x524, 0x6b); 133 udelay(50); 134 tmp = bcma_read32(dev, 0x524); 135 udelay(50); 136 bcma_write32(dev, 0x524, 0xab); 137 udelay(50); 138 tmp = bcma_read32(dev, 0x524); 139 udelay(50); 140 bcma_write32(dev, 0x524, 0x2b); 141 udelay(50); 142 tmp = bcma_read32(dev, 0x524); 143 udelay(50); 144 bcma_write32(dev, 0x524, 0x10ab); 145 udelay(50); 146 tmp = bcma_read32(dev, 0x524); 147 148 if (bcma_wait_bits(dev, 0x528, 0xc000, 10000)) { 149 tmp = bcma_read32(dev, 0x528); 150 printk(KERN_EMERG 151 "USB20H mdio_rddata 0x%08x\n", tmp); 152 } 153 bcma_write32(dev, 0x528, 0x80000000); 154 tmp = bcma_read32(dev, 0x314); 155 udelay(265); 156 bcma_write32(dev, 0x200, 0x7ff); 157 udelay(10); 158 159 /* Take USB and HSIC out of non-driving modes */ 160 bcma_write32(dev, 0x510, 0); 161 } else { 162 bcma_write32(dev, 0x200, 0x7ff); 163 164 udelay(1); 165 } 166 167 bcma_hcd_4716wa(dev); 168 } 169} 170 171/* 172 * bcma_hcd_usb20_old_arm_init - Initialize old USB 2.0 controller on ARM 173 * 174 * Old USB 2.0 core is identified as BCMA_CORE_USB20_HOST and was introduced 175 * long before Northstar devices. It seems some cheaper chipsets like BCM53573 176 * still use it. 177 * Initialization of this old core differs between MIPS and ARM. 178 */ 179static int bcma_hcd_usb20_old_arm_init(struct bcma_hcd_device *usb_dev) 180{ 181 struct bcma_device *core = usb_dev->core; 182 struct device *dev = &core->dev; 183 struct bcma_device *pmu_core; 184 185 usleep_range(10000, 20000); 186 if (core->id.rev < 5) 187 return 0; 188 189 pmu_core = bcma_find_core(core->bus, BCMA_CORE_PMU); 190 if (!pmu_core) { 191 dev_err(dev, "Could not find PMU core\n"); 192 return -ENOENT; 193 } 194 195 /* Take USB core out of reset */ 196 bcma_awrite32(core, BCMA_IOCTL, BCMA_IOCTL_CLK | BCMA_IOCTL_FGC); 197 usleep_range(100, 200); 198 bcma_awrite32(core, BCMA_RESET_CTL, BCMA_RESET_CTL_RESET); 199 usleep_range(100, 200); 200 bcma_awrite32(core, BCMA_RESET_CTL, 0); 201 usleep_range(100, 200); 202 bcma_awrite32(core, BCMA_IOCTL, BCMA_IOCTL_CLK); 203 usleep_range(100, 200); 204 205 /* Enable Misc PLL */ 206 bcma_write32(core, BCMA_CLKCTLST, BCMA_CLKCTLST_FORCEHT | 207 BCMA_CLKCTLST_HQCLKREQ | 208 USB_BCMA_CLKCTLST_USB_CLK_REQ); 209 usleep_range(100, 200); 210 211 bcma_write32(core, 0x510, 0xc7f85000); 212 bcma_write32(core, 0x510, 0xc7f85003); 213 usleep_range(300, 600); 214 215 /* Program USB PHY PLL parameters */ 216 bcma_write32(pmu_core, BCMA_CC_PMU_PLLCTL_ADDR, 0x6); 217 bcma_write32(pmu_core, BCMA_CC_PMU_PLLCTL_DATA, 0x005360c1); 218 usleep_range(100, 200); 219 bcma_write32(pmu_core, BCMA_CC_PMU_PLLCTL_ADDR, 0x7); 220 bcma_write32(pmu_core, BCMA_CC_PMU_PLLCTL_DATA, 0x0); 221 usleep_range(100, 200); 222 bcma_set32(pmu_core, BCMA_CC_PMU_CTL, BCMA_CC_PMU_CTL_PLL_UPD); 223 usleep_range(100, 200); 224 225 bcma_write32(core, 0x510, 0x7f8d007); 226 udelay(1000); 227 228 /* Take controller out of reset */ 229 bcma_write32(core, 0x200, 0x4ff); 230 usleep_range(25, 50); 231 bcma_write32(core, 0x200, 0x6ff); 232 usleep_range(25, 50); 233 bcma_write32(core, 0x200, 0x7ff); 234 usleep_range(25, 50); 235 236 of_platform_default_populate(dev->of_node, NULL, dev); 237 238 return 0; 239} 240 241static void bcma_hcd_usb20_ns_init_hc(struct bcma_device *dev) 242{ 243 u32 val; 244 245 /* Set packet buffer OUT threshold */ 246 val = bcma_read32(dev, 0x94); 247 val &= 0xffff; 248 val |= 0x80 << 16; 249 bcma_write32(dev, 0x94, val); 250 251 /* Enable break memory transfer */ 252 val = bcma_read32(dev, 0x9c); 253 val |= 1; 254 bcma_write32(dev, 0x9c, val); 255 256 /* 257 * Broadcom initializes PHY and then waits to ensure HC is ready to be 258 * configured. In our case the order is reversed. We just initialized 259 * controller and we let HCD initialize PHY, so let's wait (sleep) now. 260 */ 261 usleep_range(1000, 2000); 262} 263 264/* 265 * bcma_hcd_usb20_ns_init - Initialize Northstar USB 2.0 controller 266 */ 267static int bcma_hcd_usb20_ns_init(struct bcma_hcd_device *bcma_hcd) 268{ 269 struct bcma_device *core = bcma_hcd->core; 270 struct bcma_chipinfo *ci = &core->bus->chipinfo; 271 struct device *dev = &core->dev; 272 273 bcma_core_enable(core, 0); 274 275 if (ci->id == BCMA_CHIP_ID_BCM4707 || 276 ci->id == BCMA_CHIP_ID_BCM53018) 277 bcma_hcd_usb20_ns_init_hc(core); 278 279 of_platform_default_populate(dev->of_node, NULL, dev); 280 281 return 0; 282} 283 284static void bcma_hci_platform_power_gpio(struct bcma_device *dev, bool val) 285{ 286 struct bcma_hcd_device *usb_dev = bcma_get_drvdata(dev); 287 288 if (IS_ERR_OR_NULL(usb_dev->gpio_desc)) 289 return; 290 291 gpiod_set_value(usb_dev->gpio_desc, val); 292} 293 294static const struct usb_ehci_pdata ehci_pdata = { 295}; 296 297static const struct usb_ohci_pdata ohci_pdata = { 298}; 299 300static struct platform_device *bcma_hcd_create_pdev(struct bcma_device *dev, 301 const char *name, u32 addr, 302 const void *data, 303 size_t size) 304{ 305 struct platform_device *hci_dev; 306 struct resource hci_res[2]; 307 int ret; 308 309 memset(hci_res, 0, sizeof(hci_res)); 310 311 hci_res[0].start = addr; 312 hci_res[0].end = hci_res[0].start + 0x1000 - 1; 313 hci_res[0].flags = IORESOURCE_MEM; 314 315 hci_res[1].start = dev->irq; 316 hci_res[1].flags = IORESOURCE_IRQ; 317 318 hci_dev = platform_device_alloc(name, 0); 319 if (!hci_dev) 320 return ERR_PTR(-ENOMEM); 321 322 hci_dev->dev.parent = &dev->dev; 323 hci_dev->dev.dma_mask = &hci_dev->dev.coherent_dma_mask; 324 325 ret = platform_device_add_resources(hci_dev, hci_res, 326 ARRAY_SIZE(hci_res)); 327 if (ret) 328 goto err_alloc; 329 if (data) 330 ret = platform_device_add_data(hci_dev, data, size); 331 if (ret) 332 goto err_alloc; 333 ret = platform_device_add(hci_dev); 334 if (ret) 335 goto err_alloc; 336 337 return hci_dev; 338 339err_alloc: 340 platform_device_put(hci_dev); 341 return ERR_PTR(ret); 342} 343 344static int bcma_hcd_usb20_init(struct bcma_hcd_device *usb_dev) 345{ 346 struct bcma_device *dev = usb_dev->core; 347 struct bcma_chipinfo *chipinfo = &dev->bus->chipinfo; 348 u32 ohci_addr; 349 int err; 350 351 if (dma_set_mask_and_coherent(dev->dma_dev, DMA_BIT_MASK(32))) 352 return -EOPNOTSUPP; 353 354 bcma_hcd_init_chip_mips(dev); 355 356 /* In AI chips EHCI is addrspace 0, OHCI is 1 */ 357 ohci_addr = dev->addr_s[0]; 358 if ((chipinfo->id == BCMA_CHIP_ID_BCM5357 || 359 chipinfo->id == BCMA_CHIP_ID_BCM4749) 360 && chipinfo->rev == 0) 361 ohci_addr = 0x18009000; 362 363 usb_dev->ohci_dev = bcma_hcd_create_pdev(dev, "ohci-platform", 364 ohci_addr, &ohci_pdata, 365 sizeof(ohci_pdata)); 366 if (IS_ERR(usb_dev->ohci_dev)) 367 return PTR_ERR(usb_dev->ohci_dev); 368 369 usb_dev->ehci_dev = bcma_hcd_create_pdev(dev, "ehci-platform", 370 dev->addr, &ehci_pdata, 371 sizeof(ehci_pdata)); 372 if (IS_ERR(usb_dev->ehci_dev)) { 373 err = PTR_ERR(usb_dev->ehci_dev); 374 goto err_unregister_ohci_dev; 375 } 376 377 return 0; 378 379err_unregister_ohci_dev: 380 platform_device_unregister(usb_dev->ohci_dev); 381 return err; 382} 383 384static int bcma_hcd_usb30_init(struct bcma_hcd_device *bcma_hcd) 385{ 386 struct bcma_device *core = bcma_hcd->core; 387 struct device *dev = &core->dev; 388 389 bcma_core_enable(core, 0); 390 391 of_platform_default_populate(dev->of_node, NULL, dev); 392 393 return 0; 394} 395 396static int bcma_hcd_probe(struct bcma_device *core) 397{ 398 int err; 399 struct bcma_hcd_device *usb_dev; 400 401 /* TODO: Probably need checks here; is the core connected? */ 402 403 usb_dev = devm_kzalloc(&core->dev, sizeof(struct bcma_hcd_device), 404 GFP_KERNEL); 405 if (!usb_dev) 406 return -ENOMEM; 407 usb_dev->core = core; 408 409 if (core->dev.of_node) 410 usb_dev->gpio_desc = devm_gpiod_get(&core->dev, "vcc", 411 GPIOD_OUT_HIGH); 412 413 switch (core->id.id) { 414 case BCMA_CORE_USB20_HOST: 415 if (IS_ENABLED(CONFIG_ARM)) 416 err = bcma_hcd_usb20_old_arm_init(usb_dev); 417 else if (IS_ENABLED(CONFIG_MIPS)) 418 err = bcma_hcd_usb20_init(usb_dev); 419 else 420 err = -ENOTSUPP; 421 break; 422 case BCMA_CORE_NS_USB20: 423 err = bcma_hcd_usb20_ns_init(usb_dev); 424 break; 425 case BCMA_CORE_NS_USB30: 426 err = bcma_hcd_usb30_init(usb_dev); 427 break; 428 default: 429 return -ENODEV; 430 } 431 if (err) 432 return err; 433 434 bcma_set_drvdata(core, usb_dev); 435 return 0; 436} 437 438static void bcma_hcd_remove(struct bcma_device *dev) 439{ 440 struct bcma_hcd_device *usb_dev = bcma_get_drvdata(dev); 441 struct platform_device *ohci_dev = usb_dev->ohci_dev; 442 struct platform_device *ehci_dev = usb_dev->ehci_dev; 443 444 if (ohci_dev) 445 platform_device_unregister(ohci_dev); 446 if (ehci_dev) 447 platform_device_unregister(ehci_dev); 448 449 bcma_core_disable(dev, 0); 450} 451 452static void bcma_hcd_shutdown(struct bcma_device *dev) 453{ 454 bcma_hci_platform_power_gpio(dev, false); 455 bcma_core_disable(dev, 0); 456} 457 458#ifdef CONFIG_PM 459 460static int bcma_hcd_suspend(struct bcma_device *dev) 461{ 462 bcma_hci_platform_power_gpio(dev, false); 463 bcma_core_disable(dev, 0); 464 465 return 0; 466} 467 468static int bcma_hcd_resume(struct bcma_device *dev) 469{ 470 bcma_hci_platform_power_gpio(dev, true); 471 bcma_core_enable(dev, 0); 472 473 return 0; 474} 475 476#else /* !CONFIG_PM */ 477#define bcma_hcd_suspend NULL 478#define bcma_hcd_resume NULL 479#endif /* CONFIG_PM */ 480 481static const struct bcma_device_id bcma_hcd_table[] = { 482 BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_USB20_HOST, BCMA_ANY_REV, BCMA_ANY_CLASS), 483 BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_NS_USB20, BCMA_ANY_REV, BCMA_ANY_CLASS), 484 BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_NS_USB30, BCMA_ANY_REV, BCMA_ANY_CLASS), 485 {}, 486}; 487MODULE_DEVICE_TABLE(bcma, bcma_hcd_table); 488 489static struct bcma_driver bcma_hcd_driver = { 490 .name = KBUILD_MODNAME, 491 .id_table = bcma_hcd_table, 492 .probe = bcma_hcd_probe, 493 .remove = bcma_hcd_remove, 494 .shutdown = bcma_hcd_shutdown, 495 .suspend = bcma_hcd_suspend, 496 .resume = bcma_hcd_resume, 497}; 498module_bcma_driver(bcma_hcd_driver);