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

host.c (3118B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * host.c - DesignWare USB3 DRD Controller Host Glue
      4 *
      5 * Copyright (C) 2011 Texas Instruments Incorporated - https://www.ti.com
      6 *
      7 * Authors: Felipe Balbi <balbi@ti.com>,
      8 */
      9
     10#include <linux/irq.h>
     11#include <linux/of.h>
     12#include <linux/platform_device.h>
     13
     14#include "core.h"
     15
     16static void dwc3_host_fill_xhci_irq_res(struct dwc3 *dwc,
     17					int irq, char *name)
     18{
     19	struct platform_device *pdev = to_platform_device(dwc->dev);
     20	struct device_node *np = dev_of_node(&pdev->dev);
     21
     22	dwc->xhci_resources[1].start = irq;
     23	dwc->xhci_resources[1].end = irq;
     24	dwc->xhci_resources[1].flags = IORESOURCE_IRQ | irq_get_trigger_type(irq);
     25	if (!name && np)
     26		dwc->xhci_resources[1].name = of_node_full_name(pdev->dev.of_node);
     27	else
     28		dwc->xhci_resources[1].name = name;
     29}
     30
     31static int dwc3_host_get_irq(struct dwc3 *dwc)
     32{
     33	struct platform_device	*dwc3_pdev = to_platform_device(dwc->dev);
     34	int irq;
     35
     36	irq = platform_get_irq_byname_optional(dwc3_pdev, "host");
     37	if (irq > 0) {
     38		dwc3_host_fill_xhci_irq_res(dwc, irq, "host");
     39		goto out;
     40	}
     41
     42	if (irq == -EPROBE_DEFER)
     43		goto out;
     44
     45	irq = platform_get_irq_byname_optional(dwc3_pdev, "dwc_usb3");
     46	if (irq > 0) {
     47		dwc3_host_fill_xhci_irq_res(dwc, irq, "dwc_usb3");
     48		goto out;
     49	}
     50
     51	if (irq == -EPROBE_DEFER)
     52		goto out;
     53
     54	irq = platform_get_irq(dwc3_pdev, 0);
     55	if (irq > 0) {
     56		dwc3_host_fill_xhci_irq_res(dwc, irq, NULL);
     57		goto out;
     58	}
     59
     60	if (!irq)
     61		irq = -EINVAL;
     62
     63out:
     64	return irq;
     65}
     66
     67int dwc3_host_init(struct dwc3 *dwc)
     68{
     69	struct property_entry	props[4];
     70	struct platform_device	*xhci;
     71	int			ret, irq;
     72	int			prop_idx = 0;
     73
     74	irq = dwc3_host_get_irq(dwc);
     75	if (irq < 0)
     76		return irq;
     77
     78	xhci = platform_device_alloc("xhci-hcd", PLATFORM_DEVID_AUTO);
     79	if (!xhci) {
     80		dev_err(dwc->dev, "couldn't allocate xHCI device\n");
     81		return -ENOMEM;
     82	}
     83
     84	xhci->dev.parent	= dwc->dev;
     85
     86	dwc->xhci = xhci;
     87
     88	ret = platform_device_add_resources(xhci, dwc->xhci_resources,
     89						DWC3_XHCI_RESOURCES_NUM);
     90	if (ret) {
     91		dev_err(dwc->dev, "couldn't add resources to xHCI device\n");
     92		goto err;
     93	}
     94
     95	memset(props, 0, sizeof(struct property_entry) * ARRAY_SIZE(props));
     96
     97	if (dwc->usb3_lpm_capable)
     98		props[prop_idx++] = PROPERTY_ENTRY_BOOL("usb3-lpm-capable");
     99
    100	if (dwc->usb2_lpm_disable)
    101		props[prop_idx++] = PROPERTY_ENTRY_BOOL("usb2-lpm-disable");
    102
    103	/**
    104	 * WORKAROUND: dwc3 revisions <=3.00a have a limitation
    105	 * where Port Disable command doesn't work.
    106	 *
    107	 * The suggested workaround is that we avoid Port Disable
    108	 * completely.
    109	 *
    110	 * This following flag tells XHCI to do just that.
    111	 */
    112	if (DWC3_VER_IS_WITHIN(DWC3, ANY, 300A))
    113		props[prop_idx++] = PROPERTY_ENTRY_BOOL("quirk-broken-port-ped");
    114
    115	if (prop_idx) {
    116		ret = device_create_managed_software_node(&xhci->dev, props, NULL);
    117		if (ret) {
    118			dev_err(dwc->dev, "failed to add properties to xHCI\n");
    119			goto err;
    120		}
    121	}
    122
    123	ret = platform_device_add(xhci);
    124	if (ret) {
    125		dev_err(dwc->dev, "failed to register xHCI device\n");
    126		goto err;
    127	}
    128
    129	return 0;
    130err:
    131	platform_device_put(xhci);
    132	return ret;
    133}
    134
    135void dwc3_host_exit(struct dwc3 *dwc)
    136{
    137	platform_device_unregister(dwc->xhci);
    138}