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

ohci-da8xx.c (13496B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * OHCI HCD (Host Controller Driver) for USB.
      4 *
      5 * TI DA8xx (OMAP-L1x) Bus Glue
      6 *
      7 * Derived from: ohci-omap.c and ohci-s3c2410.c
      8 * Copyright (C) 2008-2009 MontaVista Software, Inc. <source@mvista.com>
      9 */
     10
     11#include <linux/clk.h>
     12#include <linux/gpio/consumer.h>
     13#include <linux/io.h>
     14#include <linux/interrupt.h>
     15#include <linux/jiffies.h>
     16#include <linux/kernel.h>
     17#include <linux/module.h>
     18#include <linux/platform_device.h>
     19#include <linux/phy/phy.h>
     20#include <linux/platform_data/usb-davinci.h>
     21#include <linux/regulator/consumer.h>
     22#include <linux/usb.h>
     23#include <linux/usb/hcd.h>
     24#include <asm/unaligned.h>
     25
     26#include "ohci.h"
     27
     28#define DRIVER_DESC "DA8XX"
     29#define DRV_NAME "ohci-da8xx"
     30
     31static struct hc_driver __read_mostly ohci_da8xx_hc_driver;
     32
     33static int (*orig_ohci_hub_control)(struct usb_hcd  *hcd, u16 typeReq,
     34			u16 wValue, u16 wIndex, char *buf, u16 wLength);
     35static int (*orig_ohci_hub_status_data)(struct usb_hcd *hcd, char *buf);
     36
     37struct da8xx_ohci_hcd {
     38	struct usb_hcd *hcd;
     39	struct clk *usb11_clk;
     40	struct phy *usb11_phy;
     41	struct regulator *vbus_reg;
     42	struct notifier_block nb;
     43	struct gpio_desc *oc_gpio;
     44};
     45
     46#define to_da8xx_ohci(hcd) (struct da8xx_ohci_hcd *)(hcd_to_ohci(hcd)->priv)
     47
     48/* Over-current indicator change bitmask */
     49static volatile u16 ocic_mask;
     50
     51static int ohci_da8xx_enable(struct usb_hcd *hcd)
     52{
     53	struct da8xx_ohci_hcd *da8xx_ohci = to_da8xx_ohci(hcd);
     54	int ret;
     55
     56	ret = clk_prepare_enable(da8xx_ohci->usb11_clk);
     57	if (ret)
     58		return ret;
     59
     60	ret = phy_init(da8xx_ohci->usb11_phy);
     61	if (ret)
     62		goto err_phy_init;
     63
     64	ret = phy_power_on(da8xx_ohci->usb11_phy);
     65	if (ret)
     66		goto err_phy_power_on;
     67
     68	return 0;
     69
     70err_phy_power_on:
     71	phy_exit(da8xx_ohci->usb11_phy);
     72err_phy_init:
     73	clk_disable_unprepare(da8xx_ohci->usb11_clk);
     74
     75	return ret;
     76}
     77
     78static void ohci_da8xx_disable(struct usb_hcd *hcd)
     79{
     80	struct da8xx_ohci_hcd *da8xx_ohci = to_da8xx_ohci(hcd);
     81
     82	phy_power_off(da8xx_ohci->usb11_phy);
     83	phy_exit(da8xx_ohci->usb11_phy);
     84	clk_disable_unprepare(da8xx_ohci->usb11_clk);
     85}
     86
     87static int ohci_da8xx_set_power(struct usb_hcd *hcd, int on)
     88{
     89	struct da8xx_ohci_hcd *da8xx_ohci = to_da8xx_ohci(hcd);
     90	struct device *dev = hcd->self.controller;
     91	int ret;
     92
     93	if (!da8xx_ohci->vbus_reg)
     94		return 0;
     95
     96	if (on) {
     97		ret = regulator_enable(da8xx_ohci->vbus_reg);
     98		if (ret) {
     99			dev_err(dev, "Failed to enable regulator: %d\n", ret);
    100			return ret;
    101		}
    102	} else {
    103		ret = regulator_disable(da8xx_ohci->vbus_reg);
    104		if (ret) {
    105			dev_err(dev, "Failed  to disable regulator: %d\n", ret);
    106			return ret;
    107		}
    108	}
    109
    110	return 0;
    111}
    112
    113static int ohci_da8xx_get_power(struct usb_hcd *hcd)
    114{
    115	struct da8xx_ohci_hcd *da8xx_ohci = to_da8xx_ohci(hcd);
    116
    117	if (da8xx_ohci->vbus_reg)
    118		return regulator_is_enabled(da8xx_ohci->vbus_reg);
    119
    120	return 1;
    121}
    122
    123static int ohci_da8xx_get_oci(struct usb_hcd *hcd)
    124{
    125	struct da8xx_ohci_hcd *da8xx_ohci = to_da8xx_ohci(hcd);
    126	unsigned int flags;
    127	int ret;
    128
    129	if (da8xx_ohci->oc_gpio)
    130		return gpiod_get_value_cansleep(da8xx_ohci->oc_gpio);
    131
    132	if (!da8xx_ohci->vbus_reg)
    133		return 0;
    134
    135	ret = regulator_get_error_flags(da8xx_ohci->vbus_reg, &flags);
    136	if (ret)
    137		return ret;
    138
    139	if (flags & REGULATOR_ERROR_OVER_CURRENT)
    140		return 1;
    141
    142	return 0;
    143}
    144
    145static int ohci_da8xx_has_set_power(struct usb_hcd *hcd)
    146{
    147	struct da8xx_ohci_hcd *da8xx_ohci = to_da8xx_ohci(hcd);
    148
    149	if (da8xx_ohci->vbus_reg)
    150		return 1;
    151
    152	return 0;
    153}
    154
    155static int ohci_da8xx_has_oci(struct usb_hcd *hcd)
    156{
    157	struct da8xx_ohci_hcd *da8xx_ohci = to_da8xx_ohci(hcd);
    158
    159	if (da8xx_ohci->oc_gpio)
    160		return 1;
    161
    162	if (da8xx_ohci->vbus_reg)
    163		return 1;
    164
    165	return 0;
    166}
    167
    168static int ohci_da8xx_has_potpgt(struct usb_hcd *hcd)
    169{
    170	struct device *dev		= hcd->self.controller;
    171	struct da8xx_ohci_root_hub *hub	= dev_get_platdata(dev);
    172
    173	if (hub && hub->potpgt)
    174		return 1;
    175
    176	return 0;
    177}
    178
    179static int ohci_da8xx_regulator_event(struct notifier_block *nb,
    180				unsigned long event, void *data)
    181{
    182	struct da8xx_ohci_hcd *da8xx_ohci =
    183				container_of(nb, struct da8xx_ohci_hcd, nb);
    184
    185	if (event & REGULATOR_EVENT_OVER_CURRENT) {
    186		ocic_mask |= 1 << 1;
    187		ohci_da8xx_set_power(da8xx_ohci->hcd, 0);
    188	}
    189
    190	return 0;
    191}
    192
    193static irqreturn_t ohci_da8xx_oc_thread(int irq, void *data)
    194{
    195	struct da8xx_ohci_hcd *da8xx_ohci = data;
    196	struct device *dev = da8xx_ohci->hcd->self.controller;
    197	int ret;
    198
    199	if (gpiod_get_value_cansleep(da8xx_ohci->oc_gpio) &&
    200	    da8xx_ohci->vbus_reg) {
    201		ret = regulator_disable(da8xx_ohci->vbus_reg);
    202		if (ret)
    203			dev_err(dev, "Failed to disable regulator: %d\n", ret);
    204	}
    205
    206	return IRQ_HANDLED;
    207}
    208
    209static int ohci_da8xx_register_notify(struct usb_hcd *hcd)
    210{
    211	struct da8xx_ohci_hcd *da8xx_ohci = to_da8xx_ohci(hcd);
    212	struct device *dev		= hcd->self.controller;
    213	int ret = 0;
    214
    215	if (!da8xx_ohci->oc_gpio && da8xx_ohci->vbus_reg) {
    216		da8xx_ohci->nb.notifier_call = ohci_da8xx_regulator_event;
    217		ret = devm_regulator_register_notifier(da8xx_ohci->vbus_reg,
    218						&da8xx_ohci->nb);
    219	}
    220
    221	if (ret)
    222		dev_err(dev, "Failed to register notifier: %d\n", ret);
    223
    224	return ret;
    225}
    226
    227static int ohci_da8xx_reset(struct usb_hcd *hcd)
    228{
    229	struct device *dev		= hcd->self.controller;
    230	struct da8xx_ohci_root_hub *hub	= dev_get_platdata(dev);
    231	struct ohci_hcd	*ohci		= hcd_to_ohci(hcd);
    232	int result;
    233	u32 rh_a;
    234
    235	dev_dbg(dev, "starting USB controller\n");
    236
    237	result = ohci_da8xx_enable(hcd);
    238	if (result < 0)
    239		return result;
    240
    241	/*
    242	 * DA8xx only have 1 port connected to the pins but the HC root hub
    243	 * register A reports 2 ports, thus we'll have to override it...
    244	 */
    245	ohci->num_ports = 1;
    246
    247	result = ohci_setup(hcd);
    248	if (result < 0) {
    249		ohci_da8xx_disable(hcd);
    250		return result;
    251	}
    252
    253	/*
    254	 * Since we're providing a board-specific root hub port power control
    255	 * and over-current reporting, we have to override the HC root hub A
    256	 * register's default value, so that ohci_hub_control() could return
    257	 * the correct hub descriptor...
    258	 */
    259	rh_a = ohci_readl(ohci, &ohci->regs->roothub.a);
    260	if (ohci_da8xx_has_set_power(hcd)) {
    261		rh_a &= ~RH_A_NPS;
    262		rh_a |=  RH_A_PSM;
    263	}
    264	if (ohci_da8xx_has_oci(hcd)) {
    265		rh_a &= ~RH_A_NOCP;
    266		rh_a |=  RH_A_OCPM;
    267	}
    268	if (ohci_da8xx_has_potpgt(hcd)) {
    269		rh_a &= ~RH_A_POTPGT;
    270		rh_a |= hub->potpgt << 24;
    271	}
    272	ohci_writel(ohci, rh_a, &ohci->regs->roothub.a);
    273
    274	return result;
    275}
    276
    277/*
    278 * Update the status data from the hub with the over-current indicator change.
    279 */
    280static int ohci_da8xx_hub_status_data(struct usb_hcd *hcd, char *buf)
    281{
    282	int length		= orig_ohci_hub_status_data(hcd, buf);
    283
    284	/* See if we have OCIC bit set on port 1 */
    285	if (ocic_mask & (1 << 1)) {
    286		dev_dbg(hcd->self.controller, "over-current indicator change "
    287			"on port 1\n");
    288
    289		if (!length)
    290			length = 1;
    291
    292		buf[0] |= 1 << 1;
    293	}
    294	return length;
    295}
    296
    297/*
    298 * Look at the control requests to the root hub and see if we need to override.
    299 */
    300static int ohci_da8xx_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
    301				  u16 wIndex, char *buf, u16 wLength)
    302{
    303	struct device *dev		= hcd->self.controller;
    304	int temp;
    305
    306	switch (typeReq) {
    307	case GetPortStatus:
    308		/* Check the port number */
    309		if (wIndex != 1)
    310			break;
    311
    312		dev_dbg(dev, "GetPortStatus(%u)\n", wIndex);
    313
    314		temp = roothub_portstatus(hcd_to_ohci(hcd), wIndex - 1);
    315
    316		/* The port power status (PPS) bit defaults to 1 */
    317		if (!ohci_da8xx_get_power(hcd))
    318			temp &= ~RH_PS_PPS;
    319
    320		/* The port over-current indicator (POCI) bit is always 0 */
    321		if (ohci_da8xx_get_oci(hcd) > 0)
    322			temp |=  RH_PS_POCI;
    323
    324		/* The over-current indicator change (OCIC) bit is 0 too */
    325		if (ocic_mask & (1 << wIndex))
    326			temp |=  RH_PS_OCIC;
    327
    328		put_unaligned(cpu_to_le32(temp), (__le32 *)buf);
    329		return 0;
    330	case SetPortFeature:
    331		temp = 1;
    332		goto check_port;
    333	case ClearPortFeature:
    334		temp = 0;
    335
    336check_port:
    337		/* Check the port number */
    338		if (wIndex != 1)
    339			break;
    340
    341		switch (wValue) {
    342		case USB_PORT_FEAT_POWER:
    343			dev_dbg(dev, "%sPortFeature(%u): %s\n",
    344				temp ? "Set" : "Clear", wIndex, "POWER");
    345
    346			return ohci_da8xx_set_power(hcd, temp) ? -EPIPE : 0;
    347		case USB_PORT_FEAT_C_OVER_CURRENT:
    348			dev_dbg(dev, "%sPortFeature(%u): %s\n",
    349				temp ? "Set" : "Clear", wIndex,
    350				"C_OVER_CURRENT");
    351
    352			if (temp)
    353				ocic_mask |= 1 << wIndex;
    354			else
    355				ocic_mask &= ~(1 << wIndex);
    356			return 0;
    357		}
    358	}
    359
    360	return orig_ohci_hub_control(hcd, typeReq, wValue,
    361			wIndex, buf, wLength);
    362}
    363
    364/*-------------------------------------------------------------------------*/
    365#ifdef CONFIG_OF
    366static const struct of_device_id da8xx_ohci_ids[] = {
    367	{ .compatible = "ti,da830-ohci" },
    368	{ }
    369};
    370MODULE_DEVICE_TABLE(of, da8xx_ohci_ids);
    371#endif
    372
    373static int ohci_da8xx_probe(struct platform_device *pdev)
    374{
    375	struct da8xx_ohci_hcd *da8xx_ohci;
    376	struct device *dev = &pdev->dev;
    377	int error, hcd_irq, oc_irq;
    378	struct usb_hcd	*hcd;
    379	struct resource *mem;
    380
    381	hcd = usb_create_hcd(&ohci_da8xx_hc_driver, dev, dev_name(dev));
    382	if (!hcd)
    383		return -ENOMEM;
    384
    385	da8xx_ohci = to_da8xx_ohci(hcd);
    386	da8xx_ohci->hcd = hcd;
    387
    388	da8xx_ohci->usb11_clk = devm_clk_get(dev, NULL);
    389	if (IS_ERR(da8xx_ohci->usb11_clk)) {
    390		error = PTR_ERR(da8xx_ohci->usb11_clk);
    391		if (error != -EPROBE_DEFER)
    392			dev_err(dev, "Failed to get clock.\n");
    393		goto err;
    394	}
    395
    396	da8xx_ohci->usb11_phy = devm_phy_get(dev, "usb-phy");
    397	if (IS_ERR(da8xx_ohci->usb11_phy)) {
    398		error = PTR_ERR(da8xx_ohci->usb11_phy);
    399		if (error != -EPROBE_DEFER)
    400			dev_err(dev, "Failed to get phy.\n");
    401		goto err;
    402	}
    403
    404	da8xx_ohci->vbus_reg = devm_regulator_get_optional(dev, "vbus");
    405	if (IS_ERR(da8xx_ohci->vbus_reg)) {
    406		error = PTR_ERR(da8xx_ohci->vbus_reg);
    407		if (error == -ENODEV) {
    408			da8xx_ohci->vbus_reg = NULL;
    409		} else if (error == -EPROBE_DEFER) {
    410			goto err;
    411		} else {
    412			dev_err(dev, "Failed to get regulator\n");
    413			goto err;
    414		}
    415	}
    416
    417	da8xx_ohci->oc_gpio = devm_gpiod_get_optional(dev, "oc", GPIOD_IN);
    418	if (IS_ERR(da8xx_ohci->oc_gpio)) {
    419		error = PTR_ERR(da8xx_ohci->oc_gpio);
    420		goto err;
    421	}
    422
    423	if (da8xx_ohci->oc_gpio) {
    424		oc_irq = gpiod_to_irq(da8xx_ohci->oc_gpio);
    425		if (oc_irq < 0) {
    426			error = oc_irq;
    427			goto err;
    428		}
    429
    430		error = devm_request_threaded_irq(dev, oc_irq, NULL,
    431				ohci_da8xx_oc_thread, IRQF_TRIGGER_RISING |
    432				IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
    433				"OHCI over-current indicator", da8xx_ohci);
    434		if (error)
    435			goto err;
    436	}
    437
    438	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
    439	hcd->regs = devm_ioremap_resource(dev, mem);
    440	if (IS_ERR(hcd->regs)) {
    441		error = PTR_ERR(hcd->regs);
    442		goto err;
    443	}
    444	hcd->rsrc_start = mem->start;
    445	hcd->rsrc_len = resource_size(mem);
    446
    447	hcd_irq = platform_get_irq(pdev, 0);
    448	if (hcd_irq < 0) {
    449		error = -ENODEV;
    450		goto err;
    451	}
    452
    453	error = usb_add_hcd(hcd, hcd_irq, 0);
    454	if (error)
    455		goto err;
    456
    457	device_wakeup_enable(hcd->self.controller);
    458
    459	error = ohci_da8xx_register_notify(hcd);
    460	if (error)
    461		goto err_remove_hcd;
    462
    463	return 0;
    464
    465err_remove_hcd:
    466	usb_remove_hcd(hcd);
    467err:
    468	usb_put_hcd(hcd);
    469	return error;
    470}
    471
    472static int ohci_da8xx_remove(struct platform_device *pdev)
    473{
    474	struct usb_hcd	*hcd = platform_get_drvdata(pdev);
    475
    476	usb_remove_hcd(hcd);
    477	usb_put_hcd(hcd);
    478
    479	return 0;
    480}
    481
    482#ifdef CONFIG_PM
    483static int ohci_da8xx_suspend(struct platform_device *pdev,
    484				pm_message_t message)
    485{
    486	struct usb_hcd	*hcd	= platform_get_drvdata(pdev);
    487	struct ohci_hcd	*ohci	= hcd_to_ohci(hcd);
    488	bool		do_wakeup	= device_may_wakeup(&pdev->dev);
    489	int		ret;
    490
    491
    492	if (time_before(jiffies, ohci->next_statechange))
    493		msleep(5);
    494	ohci->next_statechange = jiffies;
    495
    496	ret = ohci_suspend(hcd, do_wakeup);
    497	if (ret)
    498		return ret;
    499
    500	ohci_da8xx_disable(hcd);
    501	hcd->state = HC_STATE_SUSPENDED;
    502
    503	return ret;
    504}
    505
    506static int ohci_da8xx_resume(struct platform_device *dev)
    507{
    508	struct usb_hcd	*hcd	= platform_get_drvdata(dev);
    509	struct ohci_hcd	*ohci	= hcd_to_ohci(hcd);
    510	int ret;
    511
    512	if (time_before(jiffies, ohci->next_statechange))
    513		msleep(5);
    514	ohci->next_statechange = jiffies;
    515
    516	ret = ohci_da8xx_enable(hcd);
    517	if (ret)
    518		return ret;
    519
    520	ohci_resume(hcd, false);
    521
    522	return 0;
    523}
    524#endif
    525
    526static const struct ohci_driver_overrides da8xx_overrides __initconst = {
    527	.reset		 = ohci_da8xx_reset,
    528	.extra_priv_size = sizeof(struct da8xx_ohci_hcd),
    529};
    530
    531/*
    532 * Driver definition to register with platform structure.
    533 */
    534static struct platform_driver ohci_hcd_da8xx_driver = {
    535	.probe		= ohci_da8xx_probe,
    536	.remove		= ohci_da8xx_remove,
    537	.shutdown 	= usb_hcd_platform_shutdown,
    538#ifdef	CONFIG_PM
    539	.suspend	= ohci_da8xx_suspend,
    540	.resume		= ohci_da8xx_resume,
    541#endif
    542	.driver		= {
    543		.name	= DRV_NAME,
    544		.of_match_table = of_match_ptr(da8xx_ohci_ids),
    545	},
    546};
    547
    548static int __init ohci_da8xx_init(void)
    549{
    550
    551	if (usb_disabled())
    552		return -ENODEV;
    553
    554	pr_info("%s: " DRIVER_DESC "\n", DRV_NAME);
    555	ohci_init_driver(&ohci_da8xx_hc_driver, &da8xx_overrides);
    556
    557	/*
    558	 * The Davinci da8xx HW has some unusual quirks, which require
    559	 * da8xx-specific workarounds. We override certain hc_driver
    560	 * functions here to achieve that. We explicitly do not enhance
    561	 * ohci_driver_overrides to allow this more easily, since this
    562	 * is an unusual case, and we don't want to encourage others to
    563	 * override these functions by making it too easy.
    564	 */
    565
    566	orig_ohci_hub_control = ohci_da8xx_hc_driver.hub_control;
    567	orig_ohci_hub_status_data = ohci_da8xx_hc_driver.hub_status_data;
    568
    569	ohci_da8xx_hc_driver.hub_status_data     = ohci_da8xx_hub_status_data;
    570	ohci_da8xx_hc_driver.hub_control         = ohci_da8xx_hub_control;
    571
    572	return platform_driver_register(&ohci_hcd_da8xx_driver);
    573}
    574module_init(ohci_da8xx_init);
    575
    576static void __exit ohci_da8xx_exit(void)
    577{
    578	platform_driver_unregister(&ohci_hcd_da8xx_driver);
    579}
    580module_exit(ohci_da8xx_exit);
    581MODULE_DESCRIPTION(DRIVER_DESC);
    582MODULE_LICENSE("GPL");
    583MODULE_ALIAS("platform:" DRV_NAME);