Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v4.5-rc3 424 lines 10 kB view raw
1/* 2 * Broadcom specific Advanced Microcontroller Bus 3 * Broadcom USB-core driver (BCMA bus glue) 4 * 5 * Copyright 2011-2015 Hauke Mehrtens <hauke@hauke-m.de> 6 * Copyright 2015 Felix Fietkau <nbd@openwrt.org> 7 * 8 * Based on ssb-ohci driver 9 * Copyright 2007 Michael Buesch <m@bues.ch> 10 * 11 * Derived from the OHCI-PCI driver 12 * Copyright 1999 Roman Weissgaerber 13 * Copyright 2000-2002 David Brownell 14 * Copyright 1999 Linus Torvalds 15 * Copyright 1999 Gregory P. Smith 16 * 17 * Derived from the USBcore related parts of Broadcom-SB 18 * Copyright 2005-2011 Broadcom Corporation 19 * 20 * Licensed under the GNU/GPL. See COPYING for details. 21 */ 22#include <linux/bcma/bcma.h> 23#include <linux/delay.h> 24#include <linux/gpio/consumer.h> 25#include <linux/platform_device.h> 26#include <linux/module.h> 27#include <linux/slab.h> 28#include <linux/of.h> 29#include <linux/of_gpio.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 37struct bcma_hcd_device { 38 struct platform_device *ehci_dev; 39 struct platform_device *ohci_dev; 40 struct gpio_desc *gpio_desc; 41}; 42 43/* Wait for bitmask in a register to get set or cleared. 44 * timeout is in units of ten-microseconds. 45 */ 46static int bcma_wait_bits(struct bcma_device *dev, u16 reg, u32 bitmask, 47 int timeout) 48{ 49 int i; 50 u32 val; 51 52 for (i = 0; i < timeout; i++) { 53 val = bcma_read32(dev, reg); 54 if ((val & bitmask) == bitmask) 55 return 0; 56 udelay(10); 57 } 58 59 return -ETIMEDOUT; 60} 61 62static void bcma_hcd_4716wa(struct bcma_device *dev) 63{ 64#ifdef CONFIG_BCMA_DRIVER_MIPS 65 /* Work around for 4716 failures. */ 66 if (dev->bus->chipinfo.id == 0x4716) { 67 u32 tmp; 68 69 tmp = bcma_cpu_clock(&dev->bus->drv_mips); 70 if (tmp >= 480000000) 71 tmp = 0x1846b; /* set CDR to 0x11(fast) */ 72 else if (tmp == 453000000) 73 tmp = 0x1046b; /* set CDR to 0x10(slow) */ 74 else 75 tmp = 0; 76 77 /* Change Shim mdio control reg to fix host not acking at 78 * high frequencies 79 */ 80 if (tmp) { 81 bcma_write32(dev, 0x524, 0x1); /* write sel to enable */ 82 udelay(500); 83 84 bcma_write32(dev, 0x524, tmp); 85 udelay(500); 86 bcma_write32(dev, 0x524, 0x4ab); 87 udelay(500); 88 bcma_read32(dev, 0x528); 89 bcma_write32(dev, 0x528, 0x80000000); 90 } 91 } 92#endif /* CONFIG_BCMA_DRIVER_MIPS */ 93} 94 95/* based on arch/mips/brcm-boards/bcm947xx/pcibios.c */ 96static void bcma_hcd_init_chip_mips(struct bcma_device *dev) 97{ 98 u32 tmp; 99 100 /* 101 * USB 2.0 special considerations: 102 * 103 * 1. Since the core supports both OHCI and EHCI functions, it must 104 * only be reset once. 105 * 106 * 2. In addition to the standard SI reset sequence, the Host Control 107 * Register must be programmed to bring the USB core and various 108 * phy components out of reset. 109 */ 110 if (!bcma_core_is_enabled(dev)) { 111 bcma_core_enable(dev, 0); 112 mdelay(10); 113 if (dev->id.rev >= 5) { 114 /* Enable Misc PLL */ 115 tmp = bcma_read32(dev, 0x1e0); 116 tmp |= 0x100; 117 bcma_write32(dev, 0x1e0, tmp); 118 if (bcma_wait_bits(dev, 0x1e0, 1 << 24, 100)) 119 printk(KERN_EMERG "Failed to enable misc PPL!\n"); 120 121 /* Take out of resets */ 122 bcma_write32(dev, 0x200, 0x4ff); 123 udelay(25); 124 bcma_write32(dev, 0x200, 0x6ff); 125 udelay(25); 126 127 /* Make sure digital and AFE are locked in USB PHY */ 128 bcma_write32(dev, 0x524, 0x6b); 129 udelay(50); 130 tmp = bcma_read32(dev, 0x524); 131 udelay(50); 132 bcma_write32(dev, 0x524, 0xab); 133 udelay(50); 134 tmp = bcma_read32(dev, 0x524); 135 udelay(50); 136 bcma_write32(dev, 0x524, 0x2b); 137 udelay(50); 138 tmp = bcma_read32(dev, 0x524); 139 udelay(50); 140 bcma_write32(dev, 0x524, 0x10ab); 141 udelay(50); 142 tmp = bcma_read32(dev, 0x524); 143 144 if (bcma_wait_bits(dev, 0x528, 0xc000, 10000)) { 145 tmp = bcma_read32(dev, 0x528); 146 printk(KERN_EMERG 147 "USB20H mdio_rddata 0x%08x\n", tmp); 148 } 149 bcma_write32(dev, 0x528, 0x80000000); 150 tmp = bcma_read32(dev, 0x314); 151 udelay(265); 152 bcma_write32(dev, 0x200, 0x7ff); 153 udelay(10); 154 155 /* Take USB and HSIC out of non-driving modes */ 156 bcma_write32(dev, 0x510, 0); 157 } else { 158 bcma_write32(dev, 0x200, 0x7ff); 159 160 udelay(1); 161 } 162 163 bcma_hcd_4716wa(dev); 164 } 165} 166 167static void bcma_hcd_init_chip_arm_phy(struct bcma_device *dev) 168{ 169 struct bcma_device *arm_core; 170 void __iomem *dmu; 171 172 arm_core = bcma_find_core(dev->bus, BCMA_CORE_ARMCA9); 173 if (!arm_core) { 174 dev_err(&dev->dev, "can not find ARM Cortex A9 ihost core\n"); 175 return; 176 } 177 178 dmu = ioremap_nocache(arm_core->addr_s[0], 0x1000); 179 if (!dmu) { 180 dev_err(&dev->dev, "can not map ARM Cortex A9 ihost core\n"); 181 return; 182 } 183 184 /* Unlock DMU PLL settings */ 185 iowrite32(0x0000ea68, dmu + 0x180); 186 187 /* Write USB 2.0 PLL control setting */ 188 iowrite32(0x00dd10c3, dmu + 0x164); 189 190 /* Lock DMU PLL settings */ 191 iowrite32(0x00000000, dmu + 0x180); 192 193 iounmap(dmu); 194} 195 196static void bcma_hcd_init_chip_arm_hc(struct bcma_device *dev) 197{ 198 u32 val; 199 200 /* 201 * Delay after PHY initialized to ensure HC is ready to be configured 202 */ 203 usleep_range(1000, 2000); 204 205 /* Set packet buffer OUT threshold */ 206 val = bcma_read32(dev, 0x94); 207 val &= 0xffff; 208 val |= 0x80 << 16; 209 bcma_write32(dev, 0x94, val); 210 211 /* Enable break memory transfer */ 212 val = bcma_read32(dev, 0x9c); 213 val |= 1; 214 bcma_write32(dev, 0x9c, val); 215} 216 217static void bcma_hcd_init_chip_arm(struct bcma_device *dev) 218{ 219 bcma_core_enable(dev, 0); 220 221 if (dev->bus->chipinfo.id == BCMA_CHIP_ID_BCM4707 || 222 dev->bus->chipinfo.id == BCMA_CHIP_ID_BCM53018) { 223 if (dev->bus->chipinfo.pkg == BCMA_PKG_ID_BCM4707 || 224 dev->bus->chipinfo.pkg == BCMA_PKG_ID_BCM4708) 225 bcma_hcd_init_chip_arm_phy(dev); 226 227 bcma_hcd_init_chip_arm_hc(dev); 228 } 229} 230 231static void bcma_hci_platform_power_gpio(struct bcma_device *dev, bool val) 232{ 233 struct bcma_hcd_device *usb_dev = bcma_get_drvdata(dev); 234 235 if (IS_ERR_OR_NULL(usb_dev->gpio_desc)) 236 return; 237 238 gpiod_set_value(usb_dev->gpio_desc, val); 239} 240 241static const struct usb_ehci_pdata ehci_pdata = { 242}; 243 244static const struct usb_ohci_pdata ohci_pdata = { 245}; 246 247static struct platform_device *bcma_hcd_create_pdev(struct bcma_device *dev, bool ohci, u32 addr) 248{ 249 struct platform_device *hci_dev; 250 struct resource hci_res[2]; 251 int ret; 252 253 memset(hci_res, 0, sizeof(hci_res)); 254 255 hci_res[0].start = addr; 256 hci_res[0].end = hci_res[0].start + 0x1000 - 1; 257 hci_res[0].flags = IORESOURCE_MEM; 258 259 hci_res[1].start = dev->irq; 260 hci_res[1].flags = IORESOURCE_IRQ; 261 262 hci_dev = platform_device_alloc(ohci ? "ohci-platform" : 263 "ehci-platform" , 0); 264 if (!hci_dev) 265 return ERR_PTR(-ENOMEM); 266 267 hci_dev->dev.parent = &dev->dev; 268 hci_dev->dev.dma_mask = &hci_dev->dev.coherent_dma_mask; 269 270 ret = platform_device_add_resources(hci_dev, hci_res, 271 ARRAY_SIZE(hci_res)); 272 if (ret) 273 goto err_alloc; 274 if (ohci) 275 ret = platform_device_add_data(hci_dev, &ohci_pdata, 276 sizeof(ohci_pdata)); 277 else 278 ret = platform_device_add_data(hci_dev, &ehci_pdata, 279 sizeof(ehci_pdata)); 280 if (ret) 281 goto err_alloc; 282 ret = platform_device_add(hci_dev); 283 if (ret) 284 goto err_alloc; 285 286 return hci_dev; 287 288err_alloc: 289 platform_device_put(hci_dev); 290 return ERR_PTR(ret); 291} 292 293static int bcma_hcd_probe(struct bcma_device *dev) 294{ 295 int err; 296 u32 ohci_addr; 297 struct bcma_hcd_device *usb_dev; 298 struct bcma_chipinfo *chipinfo; 299 300 chipinfo = &dev->bus->chipinfo; 301 302 /* TODO: Probably need checks here; is the core connected? */ 303 304 if (dma_set_mask_and_coherent(dev->dma_dev, DMA_BIT_MASK(32))) 305 return -EOPNOTSUPP; 306 307 usb_dev = devm_kzalloc(&dev->dev, sizeof(struct bcma_hcd_device), 308 GFP_KERNEL); 309 if (!usb_dev) 310 return -ENOMEM; 311 312 if (dev->dev.of_node) 313 usb_dev->gpio_desc = devm_get_gpiod_from_child(&dev->dev, "vcc", 314 &dev->dev.of_node->fwnode); 315 if (!IS_ERR_OR_NULL(usb_dev->gpio_desc)) 316 gpiod_direction_output(usb_dev->gpio_desc, 1); 317 318 switch (dev->id.id) { 319 case BCMA_CORE_NS_USB20: 320 bcma_hcd_init_chip_arm(dev); 321 break; 322 case BCMA_CORE_USB20_HOST: 323 bcma_hcd_init_chip_mips(dev); 324 break; 325 default: 326 return -ENODEV; 327 } 328 329 /* In AI chips EHCI is addrspace 0, OHCI is 1 */ 330 ohci_addr = dev->addr_s[0]; 331 if ((chipinfo->id == BCMA_CHIP_ID_BCM5357 || 332 chipinfo->id == BCMA_CHIP_ID_BCM4749) 333 && chipinfo->rev == 0) 334 ohci_addr = 0x18009000; 335 336 usb_dev->ohci_dev = bcma_hcd_create_pdev(dev, true, ohci_addr); 337 if (IS_ERR(usb_dev->ohci_dev)) 338 return PTR_ERR(usb_dev->ohci_dev); 339 340 usb_dev->ehci_dev = bcma_hcd_create_pdev(dev, false, dev->addr); 341 if (IS_ERR(usb_dev->ehci_dev)) { 342 err = PTR_ERR(usb_dev->ehci_dev); 343 goto err_unregister_ohci_dev; 344 } 345 346 bcma_set_drvdata(dev, usb_dev); 347 return 0; 348 349err_unregister_ohci_dev: 350 platform_device_unregister(usb_dev->ohci_dev); 351 return err; 352} 353 354static void bcma_hcd_remove(struct bcma_device *dev) 355{ 356 struct bcma_hcd_device *usb_dev = bcma_get_drvdata(dev); 357 struct platform_device *ohci_dev = usb_dev->ohci_dev; 358 struct platform_device *ehci_dev = usb_dev->ehci_dev; 359 360 if (ohci_dev) 361 platform_device_unregister(ohci_dev); 362 if (ehci_dev) 363 platform_device_unregister(ehci_dev); 364 365 bcma_core_disable(dev, 0); 366} 367 368static void bcma_hcd_shutdown(struct bcma_device *dev) 369{ 370 bcma_hci_platform_power_gpio(dev, false); 371 bcma_core_disable(dev, 0); 372} 373 374#ifdef CONFIG_PM 375 376static int bcma_hcd_suspend(struct bcma_device *dev) 377{ 378 bcma_hci_platform_power_gpio(dev, false); 379 bcma_core_disable(dev, 0); 380 381 return 0; 382} 383 384static int bcma_hcd_resume(struct bcma_device *dev) 385{ 386 bcma_hci_platform_power_gpio(dev, true); 387 bcma_core_enable(dev, 0); 388 389 return 0; 390} 391 392#else /* !CONFIG_PM */ 393#define bcma_hcd_suspend NULL 394#define bcma_hcd_resume NULL 395#endif /* CONFIG_PM */ 396 397static const struct bcma_device_id bcma_hcd_table[] = { 398 BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_USB20_HOST, BCMA_ANY_REV, BCMA_ANY_CLASS), 399 BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_NS_USB20, BCMA_ANY_REV, BCMA_ANY_CLASS), 400 {}, 401}; 402MODULE_DEVICE_TABLE(bcma, bcma_hcd_table); 403 404static struct bcma_driver bcma_hcd_driver = { 405 .name = KBUILD_MODNAME, 406 .id_table = bcma_hcd_table, 407 .probe = bcma_hcd_probe, 408 .remove = bcma_hcd_remove, 409 .shutdown = bcma_hcd_shutdown, 410 .suspend = bcma_hcd_suspend, 411 .resume = bcma_hcd_resume, 412}; 413 414static int __init bcma_hcd_init(void) 415{ 416 return bcma_driver_register(&bcma_hcd_driver); 417} 418module_init(bcma_hcd_init); 419 420static void __exit bcma_hcd_exit(void) 421{ 422 bcma_driver_unregister(&bcma_hcd_driver); 423} 424module_exit(bcma_hcd_exit);