cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

ehci-grlib.c (3881B)


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