^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-1.0+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * EHCI HCD (Host Controller Driver) for USB.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Bus Glue for PPC On-Chip EHCI driver on the of_platform bus
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Tested on AMCC PPC 440EPx
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Valentine Barshak <vbarshak@ru.mvista.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * Based on "ehci-ppc-soc.c" by Stefan Roese <sr@denx.de>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * and "ohci-ppc-of.c" by Sylvain Munaut <tnt@246tNt.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * This file is licenced under the GPL.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/err.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/signal.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/of_address.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/of_irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/of_platform.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) static const struct hc_driver ehci_ppc_of_hc_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) .description = hcd_name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) .product_desc = "OF EHCI",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) .hcd_priv_size = sizeof(struct ehci_hcd),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) * generic hardware linkage
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) .irq = ehci_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) .flags = HCD_MEMORY | HCD_DMA | HCD_USB2 | HCD_BH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) * basic lifecycle operations
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) .reset = ehci_setup,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) .start = ehci_run,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) .stop = ehci_stop,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) .shutdown = ehci_shutdown,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) * managing i/o requests and associated device resources
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) .urb_enqueue = ehci_urb_enqueue,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) .urb_dequeue = ehci_urb_dequeue,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) .endpoint_disable = ehci_endpoint_disable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) .endpoint_reset = ehci_endpoint_reset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) * scheduling support
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) .get_frame_number = ehci_get_frame,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) * root hub support
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) .hub_status_data = ehci_hub_status_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) .hub_control = ehci_hub_control,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) #ifdef CONFIG_PM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) .bus_suspend = ehci_bus_suspend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) .bus_resume = ehci_bus_resume,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) .relinquish_port = ehci_relinquish_port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) .port_handed_over = ehci_port_handed_over,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) * 440EPx Errata USBH_3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) * Fix: Enable Break Memory Transfer (BMT) in INSNREG3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) #define PPC440EPX_EHCI0_INSREG_BMT (0x1 << 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) ppc44x_enable_bmt(struct device_node *dn)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) __iomem u32 *insreg_virt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) insreg_virt = of_iomap(dn, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) if (!insreg_virt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) out_be32(insreg_virt + 3, PPC440EPX_EHCI0_INSREG_BMT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) iounmap(insreg_virt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) static int ehci_hcd_ppc_of_probe(struct platform_device *op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) struct device_node *dn = op->dev.of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) struct usb_hcd *hcd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) struct ehci_hcd *ehci = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) struct resource res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) int irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) int rv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) struct device_node *np;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) if (usb_disabled())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) dev_dbg(&op->dev, "initializing PPC-OF USB Controller\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) rv = of_address_to_resource(dn, 0, &res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) if (rv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) return rv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) hcd = usb_create_hcd(&ehci_ppc_of_hc_driver, &op->dev, "PPC-OF USB");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) if (!hcd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) hcd->rsrc_start = res.start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) hcd->rsrc_len = resource_size(&res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) irq = irq_of_parse_and_map(dn, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) if (irq == NO_IRQ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) dev_err(&op->dev, "%s: irq_of_parse_and_map failed\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) __FILE__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) rv = -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) goto err_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) hcd->regs = devm_ioremap_resource(&op->dev, &res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) if (IS_ERR(hcd->regs)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) rv = PTR_ERR(hcd->regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) goto err_ioremap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) ehci = hcd_to_ehci(hcd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) np = of_find_compatible_node(NULL, NULL, "ibm,usb-ohci-440epx");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) if (np != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) /* claim we really affected by usb23 erratum */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) if (!of_address_to_resource(np, 0, &res))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) ehci->ohci_hcctrl_reg =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) devm_ioremap(&op->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) res.start + OHCI_HCCTRL_OFFSET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) OHCI_HCCTRL_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) pr_debug("%s: no ohci offset in fdt\n", __FILE__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) if (!ehci->ohci_hcctrl_reg) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) pr_debug("%s: ioremap for ohci hcctrl failed\n", __FILE__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) ehci->has_amcc_usb23 = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) if (of_get_property(dn, "big-endian", NULL)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) ehci->big_endian_mmio = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) ehci->big_endian_desc = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) if (of_get_property(dn, "big-endian-regs", NULL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) ehci->big_endian_mmio = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) if (of_get_property(dn, "big-endian-desc", NULL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) ehci->big_endian_desc = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) ehci->caps = hcd->regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) if (of_device_is_compatible(dn, "ibm,usb-ehci-440epx")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) rv = ppc44x_enable_bmt(dn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) ehci_dbg(ehci, "Break Memory Transfer (BMT) is %senabled!\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) rv ? "NOT ": "");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) rv = usb_add_hcd(hcd, irq, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) if (rv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) goto err_ioremap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) device_wakeup_enable(hcd->self.controller);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) err_ioremap:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) irq_dispose_mapping(irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) err_irq:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) usb_put_hcd(hcd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) return rv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) static int ehci_hcd_ppc_of_remove(struct platform_device *op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) struct usb_hcd *hcd = platform_get_drvdata(op);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) struct ehci_hcd *ehci = hcd_to_ehci(hcd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) struct device_node *np;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) struct resource res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) dev_dbg(&op->dev, "stopping PPC-OF USB Controller\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) usb_remove_hcd(hcd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) irq_dispose_mapping(hcd->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) /* use request_mem_region to test if the ohci driver is loaded. if so
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) * ensure the ohci core is operational.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) if (ehci->has_amcc_usb23) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) np = of_find_compatible_node(NULL, NULL, "ibm,usb-ohci-440epx");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) if (np != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) if (!of_address_to_resource(np, 0, &res))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) if (!request_mem_region(res.start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 0x4, hcd_name))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) set_ohci_hcfs(ehci, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) release_mem_region(res.start, 0x4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) pr_debug("%s: no ohci offset in fdt\n", __FILE__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) of_node_put(np);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) usb_put_hcd(hcd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) static const struct of_device_id ehci_hcd_ppc_of_match[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) .compatible = "usb-ehci",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) {},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) MODULE_DEVICE_TABLE(of, ehci_hcd_ppc_of_match);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) static struct platform_driver ehci_hcd_ppc_of_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) .probe = ehci_hcd_ppc_of_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) .remove = ehci_hcd_ppc_of_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) .shutdown = usb_hcd_platform_shutdown,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) .name = "ppc-of-ehci",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) .of_match_table = ehci_hcd_ppc_of_match,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) };