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-sh.c (3842B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * SuperH EHCI host controller driver
      4 *
      5 * Copyright (C) 2010  Paul Mundt
      6 *
      7 * Based on ohci-sh.c and ehci-atmel.c.
      8 */
      9#include <linux/platform_device.h>
     10#include <linux/clk.h>
     11
     12struct ehci_sh_priv {
     13	struct clk *iclk, *fclk;
     14	struct usb_hcd *hcd;
     15};
     16
     17static int ehci_sh_reset(struct usb_hcd *hcd)
     18{
     19	struct ehci_hcd	*ehci = hcd_to_ehci(hcd);
     20
     21	ehci->caps = hcd->regs;
     22
     23	return ehci_setup(hcd);
     24}
     25
     26static const struct hc_driver ehci_sh_hc_driver = {
     27	.description			= hcd_name,
     28	.product_desc			= "SuperH EHCI",
     29	.hcd_priv_size			= sizeof(struct ehci_hcd),
     30
     31	/*
     32	 * generic hardware linkage
     33	 */
     34	.irq				= ehci_irq,
     35	.flags				= HCD_USB2 | HCD_DMA | HCD_MEMORY | HCD_BH,
     36
     37	/*
     38	 * basic lifecycle operations
     39	 */
     40	.reset				= ehci_sh_reset,
     41	.start				= ehci_run,
     42	.stop				= ehci_stop,
     43	.shutdown			= ehci_shutdown,
     44
     45	/*
     46	 * managing i/o requests and associated device resources
     47	 */
     48	.urb_enqueue			= ehci_urb_enqueue,
     49	.urb_dequeue			= ehci_urb_dequeue,
     50	.endpoint_disable		= ehci_endpoint_disable,
     51	.endpoint_reset			= ehci_endpoint_reset,
     52
     53	/*
     54	 * scheduling support
     55	 */
     56	.get_frame_number		= ehci_get_frame,
     57
     58	/*
     59	 * root hub support
     60	 */
     61	.hub_status_data		= ehci_hub_status_data,
     62	.hub_control			= ehci_hub_control,
     63
     64#ifdef CONFIG_PM
     65	.bus_suspend			= ehci_bus_suspend,
     66	.bus_resume			= ehci_bus_resume,
     67#endif
     68
     69	.relinquish_port		= ehci_relinquish_port,
     70	.port_handed_over		= ehci_port_handed_over,
     71	.clear_tt_buffer_complete	= ehci_clear_tt_buffer_complete,
     72};
     73
     74static int ehci_hcd_sh_probe(struct platform_device *pdev)
     75{
     76	struct resource *res;
     77	struct ehci_sh_priv *priv;
     78	struct usb_hcd *hcd;
     79	int irq, ret;
     80
     81	if (usb_disabled())
     82		return -ENODEV;
     83
     84	irq = platform_get_irq(pdev, 0);
     85	if (irq <= 0) {
     86		ret = -ENODEV;
     87		goto fail_create_hcd;
     88	}
     89
     90	/* initialize hcd */
     91	hcd = usb_create_hcd(&ehci_sh_hc_driver, &pdev->dev,
     92			     dev_name(&pdev->dev));
     93	if (!hcd) {
     94		ret = -ENOMEM;
     95		goto fail_create_hcd;
     96	}
     97
     98	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
     99	hcd->regs = devm_ioremap_resource(&pdev->dev, res);
    100	if (IS_ERR(hcd->regs)) {
    101		ret = PTR_ERR(hcd->regs);
    102		goto fail_request_resource;
    103	}
    104	hcd->rsrc_start = res->start;
    105	hcd->rsrc_len = resource_size(res);
    106
    107	priv = devm_kzalloc(&pdev->dev, sizeof(struct ehci_sh_priv),
    108			    GFP_KERNEL);
    109	if (!priv) {
    110		ret = -ENOMEM;
    111		goto fail_request_resource;
    112	}
    113
    114	/* These are optional, we don't care if they fail */
    115	priv->fclk = devm_clk_get(&pdev->dev, "usb_fck");
    116	if (IS_ERR(priv->fclk))
    117		priv->fclk = NULL;
    118
    119	priv->iclk = devm_clk_get(&pdev->dev, "usb_ick");
    120	if (IS_ERR(priv->iclk))
    121		priv->iclk = NULL;
    122
    123	clk_enable(priv->fclk);
    124	clk_enable(priv->iclk);
    125
    126	ret = usb_add_hcd(hcd, irq, IRQF_SHARED);
    127	if (ret != 0) {
    128		dev_err(&pdev->dev, "Failed to add hcd");
    129		goto fail_add_hcd;
    130	}
    131	device_wakeup_enable(hcd->self.controller);
    132
    133	priv->hcd = hcd;
    134	platform_set_drvdata(pdev, priv);
    135
    136	return ret;
    137
    138fail_add_hcd:
    139	clk_disable(priv->iclk);
    140	clk_disable(priv->fclk);
    141
    142fail_request_resource:
    143	usb_put_hcd(hcd);
    144fail_create_hcd:
    145	dev_err(&pdev->dev, "init %s fail, %d\n", dev_name(&pdev->dev), ret);
    146
    147	return ret;
    148}
    149
    150static int ehci_hcd_sh_remove(struct platform_device *pdev)
    151{
    152	struct ehci_sh_priv *priv = platform_get_drvdata(pdev);
    153	struct usb_hcd *hcd = priv->hcd;
    154
    155	usb_remove_hcd(hcd);
    156	usb_put_hcd(hcd);
    157
    158	clk_disable(priv->fclk);
    159	clk_disable(priv->iclk);
    160
    161	return 0;
    162}
    163
    164static void ehci_hcd_sh_shutdown(struct platform_device *pdev)
    165{
    166	struct ehci_sh_priv *priv = platform_get_drvdata(pdev);
    167	struct usb_hcd *hcd = priv->hcd;
    168
    169	if (hcd->driver->shutdown)
    170		hcd->driver->shutdown(hcd);
    171}
    172
    173static struct platform_driver ehci_hcd_sh_driver = {
    174	.probe		= ehci_hcd_sh_probe,
    175	.remove		= ehci_hcd_sh_remove,
    176	.shutdown	= ehci_hcd_sh_shutdown,
    177	.driver		= {
    178		.name	= "sh_ehci",
    179	},
    180};
    181
    182MODULE_ALIAS("platform:sh_ehci");