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.

usb: exynos: add workaround for the USB device bindings conflict

Commit 69bec7259853 ("USB: core: let USB device know device node") added
support for attaching devicetree node for USB devices. Those nodes are
children of their USB host controller. However Exynos EHCI and OHCI
driver bindings already define child-nodes for each physical root hub
port and assigns respective PHY controller and parameters to them. Those
bindings predates support for USB device tree nodes.

To mitigate the side-effects of the conflict between those bindings,
lets reset Exynos host controller of_node pointer before registering it
to USB subsystem. This fixes the issue raised by the commit 01fdf179f4b0
("usb: core: skip interfaces disabled in devicetree"), which incorrectly
disabled some devices on Exynos based boards.

Reported-by: Markus Reichl <m.reichl@fivetechno.de>
Suggested-by: Måns Rullgård <mans@mansr.com>
Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
Acked-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Marek Szyprowski and committed by
Greg Kroah-Hartman
01d40714 3a38e874

+22
+11
drivers/usb/host/ehci-exynos.c
··· 39 39 40 40 struct exynos_ehci_hcd { 41 41 struct clk *clk; 42 + struct device_node *of_node; 42 43 struct phy *phy[PHY_NUMBER]; 43 44 }; 44 45 ··· 204 203 ehci = hcd_to_ehci(hcd); 205 204 ehci->caps = hcd->regs; 206 205 206 + /* 207 + * Workaround: reset of_node pointer to avoid conflict between Exynos 208 + * EHCI port subnodes and generic USB device bindings 209 + */ 210 + exynos_ehci->of_node = pdev->dev.of_node; 211 + pdev->dev.of_node = NULL; 212 + 207 213 /* DMA burst Enable */ 208 214 writel(EHCI_INSNREG00_ENABLE_DMA_BURST, EHCI_INSNREG00(hcd->regs)); 209 215 ··· 227 219 228 220 fail_add_hcd: 229 221 exynos_ehci_phy_disable(&pdev->dev); 222 + pdev->dev.of_node = exynos_ehci->of_node; 230 223 fail_io: 231 224 clk_disable_unprepare(exynos_ehci->clk); 232 225 fail_clk: ··· 239 230 { 240 231 struct usb_hcd *hcd = platform_get_drvdata(pdev); 241 232 struct exynos_ehci_hcd *exynos_ehci = to_exynos_ehci(hcd); 233 + 234 + pdev->dev.of_node = exynos_ehci->of_node; 242 235 243 236 usb_remove_hcd(hcd); 244 237
+11
drivers/usb/host/ohci-exynos.c
··· 30 30 31 31 struct exynos_ohci_hcd { 32 32 struct clk *clk; 33 + struct device_node *of_node; 33 34 struct phy *phy[PHY_NUMBER]; 34 35 }; 35 36 ··· 171 170 goto fail_io; 172 171 } 173 172 173 + /* 174 + * Workaround: reset of_node pointer to avoid conflict between Exynos 175 + * OHCI port subnodes and generic USB device bindings 176 + */ 177 + exynos_ohci->of_node = pdev->dev.of_node; 178 + pdev->dev.of_node = NULL; 179 + 174 180 err = usb_add_hcd(hcd, irq, IRQF_SHARED); 175 181 if (err) { 176 182 dev_err(&pdev->dev, "Failed to add USB HCD\n"); ··· 188 180 189 181 fail_add_hcd: 190 182 exynos_ohci_phy_disable(&pdev->dev); 183 + pdev->dev.of_node = exynos_ohci->of_node; 191 184 fail_io: 192 185 clk_disable_unprepare(exynos_ohci->clk); 193 186 fail_clk: ··· 200 191 { 201 192 struct usb_hcd *hcd = platform_get_drvdata(pdev); 202 193 struct exynos_ohci_hcd *exynos_ohci = to_exynos_ohci(hcd); 194 + 195 + pdev->dev.of_node = exynos_ohci->of_node; 203 196 204 197 usb_remove_hcd(hcd); 205 198