^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Driver for Aeroflex Gaisler GRLIB GRUSBHC EHCI host controller
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * GRUSBHC is typically found on LEON/GRLIB SoCs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * (c) Jan Andersson <jan@gaisler.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Based on ehci-ppc-of.c which is:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * (c) Valentine Barshak <vbarshak@ru.mvista.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * and in turn based on "ehci-ppc-soc.c" by Stefan Roese <sr@denx.de>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * and "ohci-ppc-of.c" by Sylvain Munaut <tnt@246tNt.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/err.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/signal.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/of_irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/of_address.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/of_platform.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #define GRUSBHC_HCIVERSION 0x0100 /* Known value of cap. reg. HCIVERSION */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) static const struct hc_driver ehci_grlib_hc_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) .description = hcd_name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) .product_desc = "GRLIB GRUSBHC EHCI",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) .hcd_priv_size = sizeof(struct ehci_hcd),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) * generic hardware linkage
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) .irq = ehci_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) .flags = HCD_MEMORY | HCD_DMA | HCD_USB2 | HCD_BH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) * basic lifecycle operations
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) .reset = ehci_setup,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) .start = ehci_run,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) .stop = ehci_stop,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) .shutdown = ehci_shutdown,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) * managing i/o requests and associated device resources
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) .urb_enqueue = ehci_urb_enqueue,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) .urb_dequeue = ehci_urb_dequeue,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) .endpoint_disable = ehci_endpoint_disable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) .endpoint_reset = ehci_endpoint_reset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) * scheduling support
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) .get_frame_number = ehci_get_frame,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) * root hub support
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) .hub_status_data = ehci_hub_status_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) .hub_control = ehci_hub_control,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) #ifdef CONFIG_PM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) .bus_suspend = ehci_bus_suspend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) .bus_resume = ehci_bus_resume,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) .relinquish_port = ehci_relinquish_port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) .port_handed_over = ehci_port_handed_over,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) };
^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) static int ehci_hcd_grlib_probe(struct platform_device *op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) struct device_node *dn = op->dev.of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) struct usb_hcd *hcd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) struct ehci_hcd *ehci = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) struct resource res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) u32 hc_capbase;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) int irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) int rv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) if (usb_disabled())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) dev_dbg(&op->dev, "initializing GRUSBHC EHCI USB Controller\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) rv = of_address_to_resource(dn, 0, &res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) if (rv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) return rv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) /* usb_create_hcd requires dma_mask != NULL */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) op->dev.dma_mask = &op->dev.coherent_dma_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) hcd = usb_create_hcd(&ehci_grlib_hc_driver, &op->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) "GRUSBHC EHCI USB");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) if (!hcd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) hcd->rsrc_start = res.start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) hcd->rsrc_len = resource_size(&res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) irq = irq_of_parse_and_map(dn, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) if (irq == NO_IRQ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) dev_err(&op->dev, "%s: irq_of_parse_and_map failed\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) __FILE__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) rv = -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) goto err_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) hcd->regs = devm_ioremap_resource(&op->dev, &res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) if (IS_ERR(hcd->regs)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) rv = PTR_ERR(hcd->regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) goto err_ioremap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) ehci = hcd_to_ehci(hcd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) ehci->caps = hcd->regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) /* determine endianness of this implementation */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) hc_capbase = ehci_readl(ehci, &ehci->caps->hc_capbase);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) if (HC_VERSION(ehci, hc_capbase) != GRUSBHC_HCIVERSION) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) ehci->big_endian_mmio = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) ehci->big_endian_desc = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) ehci->big_endian_capbase = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) rv = usb_add_hcd(hcd, irq, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) if (rv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) goto err_ioremap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) device_wakeup_enable(hcd->self.controller);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) err_ioremap:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) irq_dispose_mapping(irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) err_irq:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) usb_put_hcd(hcd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) return rv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) static int ehci_hcd_grlib_remove(struct platform_device *op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) struct usb_hcd *hcd = platform_get_drvdata(op);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) dev_dbg(&op->dev, "stopping GRLIB GRUSBHC EHCI USB Controller\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) usb_remove_hcd(hcd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) irq_dispose_mapping(hcd->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) usb_put_hcd(hcd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) static const struct of_device_id ehci_hcd_grlib_of_match[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) .name = "GAISLER_EHCI",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) .name = "01_026",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) {},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) MODULE_DEVICE_TABLE(of, ehci_hcd_grlib_of_match);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) static struct platform_driver ehci_grlib_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) .probe = ehci_hcd_grlib_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) .remove = ehci_hcd_grlib_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) .shutdown = usb_hcd_platform_shutdown,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) .name = "grlib-ehci",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) .of_match_table = ehci_hcd_grlib_of_match,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) };