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 (3308B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Cadence USBSS and USBSSP DRD Driver - host side
      4 *
      5 * Copyright (C) 2018-2019 Cadence Design Systems.
      6 * Copyright (C) 2017-2018 NXP
      7 *
      8 * Authors: Peter Chen <peter.chen@nxp.com>
      9 *          Pawel Laszczak <pawell@cadence.com>
     10 */
     11
     12#include <linux/platform_device.h>
     13#include <linux/slab.h>
     14#include "core.h"
     15#include "drd.h"
     16#include "host-export.h"
     17#include <linux/usb/hcd.h>
     18#include "../host/xhci.h"
     19#include "../host/xhci-plat.h"
     20
     21#define XECP_PORT_CAP_REG	0x8000
     22#define XECP_AUX_CTRL_REG1	0x8120
     23
     24#define CFG_RXDET_P3_EN		BIT(15)
     25#define LPM_2_STB_SWITCH_EN	BIT(25)
     26
     27static int xhci_cdns3_suspend_quirk(struct usb_hcd *hcd);
     28
     29static const struct xhci_plat_priv xhci_plat_cdns3_xhci = {
     30	.quirks = XHCI_SKIP_PHY_INIT | XHCI_AVOID_BEI,
     31	.suspend_quirk = xhci_cdns3_suspend_quirk,
     32};
     33
     34static int __cdns_host_init(struct cdns *cdns)
     35{
     36	struct platform_device *xhci;
     37	int ret;
     38	struct usb_hcd *hcd;
     39
     40	cdns_drd_host_on(cdns);
     41
     42	xhci = platform_device_alloc("xhci-hcd", PLATFORM_DEVID_AUTO);
     43	if (!xhci) {
     44		dev_err(cdns->dev, "couldn't allocate xHCI device\n");
     45		return -ENOMEM;
     46	}
     47
     48	xhci->dev.parent = cdns->dev;
     49	cdns->host_dev = xhci;
     50
     51	ret = platform_device_add_resources(xhci, cdns->xhci_res,
     52					    CDNS_XHCI_RESOURCES_NUM);
     53	if (ret) {
     54		dev_err(cdns->dev, "couldn't add resources to xHCI device\n");
     55		goto err1;
     56	}
     57
     58	cdns->xhci_plat_data = kmemdup(&xhci_plat_cdns3_xhci,
     59			sizeof(struct xhci_plat_priv), GFP_KERNEL);
     60	if (!cdns->xhci_plat_data) {
     61		ret = -ENOMEM;
     62		goto err1;
     63	}
     64
     65	if (cdns->pdata && (cdns->pdata->quirks & CDNS3_DEFAULT_PM_RUNTIME_ALLOW))
     66		cdns->xhci_plat_data->quirks |= XHCI_DEFAULT_PM_RUNTIME_ALLOW;
     67
     68	ret = platform_device_add_data(xhci, cdns->xhci_plat_data,
     69			sizeof(struct xhci_plat_priv));
     70	if (ret)
     71		goto free_memory;
     72
     73	ret = platform_device_add(xhci);
     74	if (ret) {
     75		dev_err(cdns->dev, "failed to register xHCI device\n");
     76		goto free_memory;
     77	}
     78
     79	/* Glue needs to access xHCI region register for Power management */
     80	hcd = platform_get_drvdata(xhci);
     81	if (hcd)
     82		cdns->xhci_regs = hcd->regs;
     83
     84	return 0;
     85
     86free_memory:
     87	kfree(cdns->xhci_plat_data);
     88err1:
     89	platform_device_put(xhci);
     90	return ret;
     91}
     92
     93static int xhci_cdns3_suspend_quirk(struct usb_hcd *hcd)
     94{
     95	struct xhci_hcd	*xhci = hcd_to_xhci(hcd);
     96	u32 value;
     97
     98	if (pm_runtime_status_suspended(hcd->self.controller))
     99		return 0;
    100
    101	/* set usbcmd.EU3S */
    102	value = readl(&xhci->op_regs->command);
    103	value |= CMD_PM_INDEX;
    104	writel(value, &xhci->op_regs->command);
    105
    106	if (hcd->regs) {
    107		value = readl(hcd->regs + XECP_AUX_CTRL_REG1);
    108		value |= CFG_RXDET_P3_EN;
    109		writel(value, hcd->regs + XECP_AUX_CTRL_REG1);
    110
    111		value = readl(hcd->regs + XECP_PORT_CAP_REG);
    112		value |= LPM_2_STB_SWITCH_EN;
    113		writel(value, hcd->regs + XECP_PORT_CAP_REG);
    114	}
    115
    116	return 0;
    117}
    118
    119static void cdns_host_exit(struct cdns *cdns)
    120{
    121	kfree(cdns->xhci_plat_data);
    122	platform_device_unregister(cdns->host_dev);
    123	cdns->host_dev = NULL;
    124	cdns_drd_host_off(cdns);
    125}
    126
    127int cdns_host_init(struct cdns *cdns)
    128{
    129	struct cdns_role_driver *rdrv;
    130
    131	rdrv = devm_kzalloc(cdns->dev, sizeof(*rdrv), GFP_KERNEL);
    132	if (!rdrv)
    133		return -ENOMEM;
    134
    135	rdrv->start	= __cdns_host_init;
    136	rdrv->stop	= cdns_host_exit;
    137	rdrv->state	= CDNS_ROLE_STATE_INACTIVE;
    138	rdrv->name	= "host";
    139
    140	cdns->roles[USB_ROLE_HOST] = rdrv;
    141
    142	return 0;
    143}