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

usb: dwc3: core: split host address space

This fix prevents a problem with dwc3 and host mode where
we were requesting the entire memory region in dwc3/core.c,
thus preventing xhci-plat from ever ioremapping its own address space.

Signed-off-by: Ido Shayevitz <idos@codeaurora.org>
Signed-off-by: Felipe Balbi <balbi@ti.com>

authored by

Ido Shayevitz and committed by
Felipe Balbi
51249dca ab5e59db

+45 -34
+17 -12
drivers/usb/dwc3/core.c
··· 410 410 struct device *dev = &pdev->dev; 411 411 412 412 int ret = -ENOMEM; 413 - int irq; 414 413 415 414 void __iomem *regs; 416 415 void *mem; ··· 424 425 dwc = PTR_ALIGN(mem, DWC3_ALIGN_MASK + 1); 425 426 dwc->mem = mem; 426 427 427 - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 428 + res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); 428 429 if (!res) { 429 - dev_err(dev, "missing resource\n"); 430 + dev_err(dev, "missing IRQ\n"); 430 431 return -ENODEV; 431 432 } 433 + dwc->xhci_resources[1] = *res; 432 434 433 - dwc->res = res; 435 + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 436 + if (!res) { 437 + dev_err(dev, "missing memory resource\n"); 438 + return -ENODEV; 439 + } 440 + dwc->xhci_resources[0] = *res; 441 + dwc->xhci_resources[0].end = dwc->xhci_resources[0].start + 442 + DWC3_XHCI_REGS_END; 434 443 435 - res = devm_request_mem_region(dev, res->start, resource_size(res), 444 + /* 445 + * Request memory region but exclude xHCI regs, 446 + * since it will be requested by the xhci-plat driver. 447 + */ 448 + res = devm_request_mem_region(dev, res->start + DWC3_GLOBALS_REGS_START, 449 + resource_size(res) - DWC3_GLOBALS_REGS_START, 436 450 dev_name(dev)); 437 451 if (!res) { 438 452 dev_err(dev, "can't request mem region\n"); ··· 458 446 return -ENOMEM; 459 447 } 460 448 461 - irq = platform_get_irq(pdev, 0); 462 - if (irq < 0) { 463 - dev_err(dev, "missing IRQ\n"); 464 - return -ENODEV; 465 - } 466 - 467 449 spin_lock_init(&dwc->lock); 468 450 platform_set_drvdata(pdev, dwc); 469 451 470 452 dwc->regs = regs; 471 453 dwc->regs_size = resource_size(res); 472 454 dwc->dev = dev; 473 - dwc->irq = irq; 474 455 475 456 if (!strncmp("super", maximum_speed, 5)) 476 457 dwc->maximum_speed = DWC3_DCFG_SUPERSPEED;
+12 -3
drivers/usb/dwc3/core.h
··· 52 52 53 53 /* Global constants */ 54 54 #define DWC3_ENDPOINTS_NUM 32 55 + #define DWC3_XHCI_RESOURCES_NUM 2 55 56 56 57 #define DWC3_EVENT_BUFFERS_SIZE PAGE_SIZE 57 58 #define DWC3_EVENT_TYPE_MASK 0xfe ··· 75 74 #define DWC3_GEVNTCOUNT_MASK 0xfffc 76 75 #define DWC3_GSNPSID_MASK 0xffff0000 77 76 #define DWC3_GSNPSREV_MASK 0xffff 77 + 78 + /* DWC3 registers memory space boundries */ 79 + #define DWC3_XHCI_REGS_START 0x0 80 + #define DWC3_XHCI_REGS_END 0x7fff 81 + #define DWC3_GLOBALS_REGS_START 0xc100 82 + #define DWC3_GLOBALS_REGS_END 0xc6ff 83 + #define DWC3_DEVICE_REGS_START 0xc700 84 + #define DWC3_DEVICE_REGS_END 0xcbff 85 + #define DWC3_OTG_REGS_START 0xcc00 86 + #define DWC3_OTG_REGS_END 0xccff 78 87 79 88 /* Global Registers */ 80 89 #define DWC3_GSBUSCFG0 0xc100 ··· 594 583 struct device *dev; 595 584 596 585 struct platform_device *xhci; 597 - struct resource *res; 586 + struct resource xhci_resources[DWC3_XHCI_RESOURCES_NUM]; 598 587 599 588 struct dwc3_event_buffer **ev_buffs; 600 589 struct dwc3_ep *eps[DWC3_ENDPOINTS_NUM]; ··· 604 593 605 594 void __iomem *regs; 606 595 size_t regs_size; 607 - 608 - int irq; 609 596 610 597 u32 num_event_buffers; 611 598 u32 u1u2;
+2 -17
drivers/usb/dwc3/host.c
··· 39 39 40 40 #include "core.h" 41 41 42 - static struct resource generic_resources[] = { 43 - { 44 - .flags = IORESOURCE_IRQ, 45 - }, 46 - { 47 - .flags = IORESOURCE_MEM, 48 - }, 49 - }; 50 - 51 42 int dwc3_host_init(struct dwc3 *dwc) 52 43 { 53 44 struct platform_device *xhci; ··· 59 68 60 69 dwc->xhci = xhci; 61 70 62 - /* setup resources */ 63 - generic_resources[0].start = dwc->irq; 64 - 65 - generic_resources[1].start = dwc->res->start; 66 - generic_resources[1].end = dwc->res->start + 0x7fff; 67 - 68 - ret = platform_device_add_resources(xhci, generic_resources, 69 - ARRAY_SIZE(generic_resources)); 71 + ret = platform_device_add_resources(xhci, dwc->xhci_resources, 72 + DWC3_XHCI_RESOURCES_NUM); 70 73 if (ret) { 71 74 dev_err(dwc->dev, "couldn't add resources to xHCI device\n"); 72 75 goto err1;
+14 -2
drivers/usb/dwc3/io.h
··· 41 41 42 42 #include <linux/io.h> 43 43 44 + #include "core.h" 45 + 44 46 static inline u32 dwc3_readl(void __iomem *base, u32 offset) 45 47 { 46 - return readl(base + offset); 48 + /* 49 + * We requested the mem region starting from the Globals address 50 + * space, see dwc3_probe in core.c. 51 + * However, the offsets are given starting from xHCI address space. 52 + */ 53 + return readl(base + (offset - DWC3_GLOBALS_REGS_START)); 47 54 } 48 55 49 56 static inline void dwc3_writel(void __iomem *base, u32 offset, u32 value) 50 57 { 51 - writel(value, base + offset); 58 + /* 59 + * We requested the mem region starting from the Globals address 60 + * space, see dwc3_probe in core.c. 61 + * However, the offsets are given starting from xHCI address space. 62 + */ 63 + writel(value, base + (offset - DWC3_GLOBALS_REGS_START)); 52 64 } 53 65 54 66 #endif /* __DRIVERS_USB_DWC3_IO_H */