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

dev.c (14684B)


      1// SPDX-License-Identifier: GPL-2.0+
      2/*
      3 * aspeed-vhub -- Driver for Aspeed SoC "vHub" USB gadget
      4 *
      5 * dev.c - Individual device/gadget management (ie, a port = a gadget)
      6 *
      7 * Copyright 2017 IBM Corporation
      8 */
      9
     10#include <linux/kernel.h>
     11#include <linux/module.h>
     12#include <linux/platform_device.h>
     13#include <linux/delay.h>
     14#include <linux/ioport.h>
     15#include <linux/slab.h>
     16#include <linux/errno.h>
     17#include <linux/list.h>
     18#include <linux/interrupt.h>
     19#include <linux/proc_fs.h>
     20#include <linux/prefetch.h>
     21#include <linux/clk.h>
     22#include <linux/usb/gadget.h>
     23#include <linux/of.h>
     24#include <linux/of_gpio.h>
     25#include <linux/regmap.h>
     26#include <linux/dma-mapping.h>
     27#include <linux/usb.h>
     28#include <linux/usb/hcd.h>
     29
     30#include "vhub.h"
     31
     32void ast_vhub_dev_irq(struct ast_vhub_dev *d)
     33{
     34	u32 istat = readl(d->regs + AST_VHUB_DEV_ISR);
     35
     36	writel(istat, d->regs + AST_VHUB_DEV_ISR);
     37
     38	if (istat & VHUV_DEV_IRQ_EP0_IN_ACK_STALL)
     39		ast_vhub_ep0_handle_ack(&d->ep0, true);
     40	if (istat & VHUV_DEV_IRQ_EP0_OUT_ACK_STALL)
     41		ast_vhub_ep0_handle_ack(&d->ep0, false);
     42	if (istat & VHUV_DEV_IRQ_EP0_SETUP)
     43		ast_vhub_ep0_handle_setup(&d->ep0);
     44}
     45
     46static void ast_vhub_dev_enable(struct ast_vhub_dev *d)
     47{
     48	u32 reg, hmsk, i;
     49
     50	if (d->enabled)
     51		return;
     52
     53	/* Cleanup EP0 state */
     54	ast_vhub_reset_ep0(d);
     55
     56	/* Enable device and its EP0 interrupts */
     57	reg = VHUB_DEV_EN_ENABLE_PORT |
     58		VHUB_DEV_EN_EP0_IN_ACK_IRQEN |
     59		VHUB_DEV_EN_EP0_OUT_ACK_IRQEN |
     60		VHUB_DEV_EN_EP0_SETUP_IRQEN;
     61	if (d->gadget.speed == USB_SPEED_HIGH)
     62		reg |= VHUB_DEV_EN_SPEED_SEL_HIGH;
     63	writel(reg, d->regs + AST_VHUB_DEV_EN_CTRL);
     64
     65	/* Enable device interrupt in the hub as well */
     66	hmsk = VHUB_IRQ_DEVICE1 << d->index;
     67	reg = readl(d->vhub->regs + AST_VHUB_IER);
     68	reg |= hmsk;
     69	writel(reg, d->vhub->regs + AST_VHUB_IER);
     70
     71	/* Set EP0 DMA buffer address */
     72	writel(d->ep0.buf_dma, d->regs + AST_VHUB_DEV_EP0_DATA);
     73
     74	/* Clear stall on all EPs */
     75	for (i = 0; i < d->max_epns; i++) {
     76		struct ast_vhub_ep *ep = d->epns[i];
     77
     78		if (ep && (ep->epn.stalled || ep->epn.wedged)) {
     79			ep->epn.stalled = false;
     80			ep->epn.wedged = false;
     81			ast_vhub_update_epn_stall(ep);
     82		}
     83	}
     84
     85	/* Additional cleanups */
     86	d->wakeup_en = false;
     87	d->enabled = true;
     88}
     89
     90static void ast_vhub_dev_disable(struct ast_vhub_dev *d)
     91{
     92	u32 reg, hmsk;
     93
     94	if (!d->enabled)
     95		return;
     96
     97	/* Disable device interrupt in the hub */
     98	hmsk = VHUB_IRQ_DEVICE1 << d->index;
     99	reg = readl(d->vhub->regs + AST_VHUB_IER);
    100	reg &= ~hmsk;
    101	writel(reg, d->vhub->regs + AST_VHUB_IER);
    102
    103	/* Then disable device */
    104	writel(0, d->regs + AST_VHUB_DEV_EN_CTRL);
    105	d->gadget.speed = USB_SPEED_UNKNOWN;
    106	d->enabled = false;
    107}
    108
    109static int ast_vhub_dev_feature(struct ast_vhub_dev *d,
    110				u16 wIndex, u16 wValue,
    111				bool is_set)
    112{
    113	u32 val;
    114
    115	DDBG(d, "%s_FEATURE(dev val=%02x)\n",
    116	     is_set ? "SET" : "CLEAR", wValue);
    117
    118	if (wValue == USB_DEVICE_REMOTE_WAKEUP) {
    119		d->wakeup_en = is_set;
    120		return std_req_complete;
    121	}
    122
    123	if (wValue == USB_DEVICE_TEST_MODE) {
    124		val = readl(d->vhub->regs + AST_VHUB_CTRL);
    125		val &= ~GENMASK(10, 8);
    126		val |= VHUB_CTRL_SET_TEST_MODE((wIndex >> 8) & 0x7);
    127		writel(val, d->vhub->regs + AST_VHUB_CTRL);
    128
    129		return std_req_complete;
    130	}
    131
    132	return std_req_driver;
    133}
    134
    135static int ast_vhub_ep_feature(struct ast_vhub_dev *d,
    136			       u16 wIndex, u16 wValue, bool is_set)
    137{
    138	struct ast_vhub_ep *ep;
    139	int ep_num;
    140
    141	ep_num = wIndex & USB_ENDPOINT_NUMBER_MASK;
    142	DDBG(d, "%s_FEATURE(ep%d val=%02x)\n",
    143	     is_set ? "SET" : "CLEAR", ep_num, wValue);
    144	if (ep_num == 0)
    145		return std_req_complete;
    146	if (ep_num >= d->max_epns || !d->epns[ep_num - 1])
    147		return std_req_stall;
    148	if (wValue != USB_ENDPOINT_HALT)
    149		return std_req_driver;
    150
    151	ep = d->epns[ep_num - 1];
    152	if (WARN_ON(!ep))
    153		return std_req_stall;
    154
    155	if (!ep->epn.enabled || !ep->ep.desc || ep->epn.is_iso ||
    156	    ep->epn.is_in != !!(wIndex & USB_DIR_IN))
    157		return std_req_stall;
    158
    159	DDBG(d, "%s stall on EP %d\n",
    160	     is_set ? "setting" : "clearing", ep_num);
    161	ep->epn.stalled = is_set;
    162	ast_vhub_update_epn_stall(ep);
    163
    164	return std_req_complete;
    165}
    166
    167static int ast_vhub_dev_status(struct ast_vhub_dev *d,
    168			       u16 wIndex, u16 wValue)
    169{
    170	u8 st0;
    171
    172	DDBG(d, "GET_STATUS(dev)\n");
    173
    174	st0 = d->gadget.is_selfpowered << USB_DEVICE_SELF_POWERED;
    175	if (d->wakeup_en)
    176		st0 |= 1 << USB_DEVICE_REMOTE_WAKEUP;
    177
    178	return ast_vhub_simple_reply(&d->ep0, st0, 0);
    179}
    180
    181static int ast_vhub_ep_status(struct ast_vhub_dev *d,
    182			      u16 wIndex, u16 wValue)
    183{
    184	int ep_num = wIndex & USB_ENDPOINT_NUMBER_MASK;
    185	struct ast_vhub_ep *ep;
    186	u8 st0 = 0;
    187
    188	DDBG(d, "GET_STATUS(ep%d)\n", ep_num);
    189
    190	if (ep_num >= d->max_epns)
    191		return std_req_stall;
    192	if (ep_num != 0) {
    193		ep = d->epns[ep_num - 1];
    194		if (!ep)
    195			return std_req_stall;
    196		if (!ep->epn.enabled || !ep->ep.desc || ep->epn.is_iso ||
    197		    ep->epn.is_in != !!(wIndex & USB_DIR_IN))
    198			return std_req_stall;
    199		if (ep->epn.stalled)
    200			st0 |= 1 << USB_ENDPOINT_HALT;
    201	}
    202
    203	return ast_vhub_simple_reply(&d->ep0, st0, 0);
    204}
    205
    206static void ast_vhub_dev_set_address(struct ast_vhub_dev *d, u8 addr)
    207{
    208	u32 reg;
    209
    210	DDBG(d, "SET_ADDRESS: Got address %x\n", addr);
    211
    212	reg = readl(d->regs + AST_VHUB_DEV_EN_CTRL);
    213	reg &= ~VHUB_DEV_EN_ADDR_MASK;
    214	reg |= VHUB_DEV_EN_SET_ADDR(addr);
    215	writel(reg, d->regs + AST_VHUB_DEV_EN_CTRL);
    216}
    217
    218int ast_vhub_std_dev_request(struct ast_vhub_ep *ep,
    219			     struct usb_ctrlrequest *crq)
    220{
    221	struct ast_vhub_dev *d = ep->dev;
    222	u16 wValue, wIndex;
    223
    224	/* No driver, we shouldn't be enabled ... */
    225	if (!d->driver || !d->enabled) {
    226		EPDBG(ep,
    227		      "Device is wrong state driver=%p enabled=%d\n",
    228		      d->driver, d->enabled);
    229		return std_req_stall;
    230	}
    231
    232	/*
    233	 * Note: we used to reject/stall requests while suspended,
    234	 * we don't do that anymore as we seem to have cases of
    235	 * mass storage getting very upset.
    236	 */
    237
    238	/* First packet, grab speed */
    239	if (d->gadget.speed == USB_SPEED_UNKNOWN) {
    240		d->gadget.speed = ep->vhub->speed;
    241		if (d->gadget.speed > d->driver->max_speed)
    242			d->gadget.speed = d->driver->max_speed;
    243		DDBG(d, "fist packet, captured speed %d\n",
    244		     d->gadget.speed);
    245	}
    246
    247	wValue = le16_to_cpu(crq->wValue);
    248	wIndex = le16_to_cpu(crq->wIndex);
    249
    250	switch ((crq->bRequestType << 8) | crq->bRequest) {
    251		/* SET_ADDRESS */
    252	case DeviceOutRequest | USB_REQ_SET_ADDRESS:
    253		ast_vhub_dev_set_address(d, wValue);
    254		return std_req_complete;
    255
    256		/* GET_STATUS */
    257	case DeviceRequest | USB_REQ_GET_STATUS:
    258		return ast_vhub_dev_status(d, wIndex, wValue);
    259	case InterfaceRequest | USB_REQ_GET_STATUS:
    260		return ast_vhub_simple_reply(ep, 0, 0);
    261	case EndpointRequest | USB_REQ_GET_STATUS:
    262		return ast_vhub_ep_status(d, wIndex, wValue);
    263
    264		/* SET/CLEAR_FEATURE */
    265	case DeviceOutRequest | USB_REQ_SET_FEATURE:
    266		return ast_vhub_dev_feature(d, wIndex, wValue, true);
    267	case DeviceOutRequest | USB_REQ_CLEAR_FEATURE:
    268		return ast_vhub_dev_feature(d, wIndex, wValue, false);
    269	case EndpointOutRequest | USB_REQ_SET_FEATURE:
    270		return ast_vhub_ep_feature(d, wIndex, wValue, true);
    271	case EndpointOutRequest | USB_REQ_CLEAR_FEATURE:
    272		return ast_vhub_ep_feature(d, wIndex, wValue, false);
    273	}
    274	return std_req_driver;
    275}
    276
    277static int ast_vhub_udc_wakeup(struct usb_gadget* gadget)
    278{
    279	struct ast_vhub_dev *d = to_ast_dev(gadget);
    280	unsigned long flags;
    281	int rc = -EINVAL;
    282
    283	spin_lock_irqsave(&d->vhub->lock, flags);
    284	if (!d->wakeup_en)
    285		goto err;
    286
    287	DDBG(d, "Device initiated wakeup\n");
    288
    289	/* Wakeup the host */
    290	ast_vhub_hub_wake_all(d->vhub);
    291	rc = 0;
    292 err:
    293	spin_unlock_irqrestore(&d->vhub->lock, flags);
    294	return rc;
    295}
    296
    297static int ast_vhub_udc_get_frame(struct usb_gadget* gadget)
    298{
    299	struct ast_vhub_dev *d = to_ast_dev(gadget);
    300
    301	return (readl(d->vhub->regs + AST_VHUB_USBSTS) >> 16) & 0x7ff;
    302}
    303
    304static void ast_vhub_dev_nuke(struct ast_vhub_dev *d)
    305{
    306	unsigned int i;
    307
    308	for (i = 0; i < d->max_epns; i++) {
    309		if (!d->epns[i])
    310			continue;
    311		ast_vhub_nuke(d->epns[i], -ESHUTDOWN);
    312	}
    313}
    314
    315static int ast_vhub_udc_pullup(struct usb_gadget* gadget, int on)
    316{
    317	struct ast_vhub_dev *d = to_ast_dev(gadget);
    318	unsigned long flags;
    319
    320	spin_lock_irqsave(&d->vhub->lock, flags);
    321
    322	DDBG(d, "pullup(%d)\n", on);
    323
    324	/* Mark disconnected in the hub */
    325	ast_vhub_device_connect(d->vhub, d->index, on);
    326
    327	/*
    328	 * If enabled, nuke all requests if any (there shouldn't be)
    329	 * and disable the port. This will clear the address too.
    330	 */
    331	if (d->enabled) {
    332		ast_vhub_dev_nuke(d);
    333		ast_vhub_dev_disable(d);
    334	}
    335
    336	spin_unlock_irqrestore(&d->vhub->lock, flags);
    337
    338	return 0;
    339}
    340
    341static int ast_vhub_udc_start(struct usb_gadget *gadget,
    342			      struct usb_gadget_driver *driver)
    343{
    344	struct ast_vhub_dev *d = to_ast_dev(gadget);
    345	unsigned long flags;
    346
    347	spin_lock_irqsave(&d->vhub->lock, flags);
    348
    349	DDBG(d, "start\n");
    350
    351	/* We don't do much more until the hub enables us */
    352	d->driver = driver;
    353	d->gadget.is_selfpowered = 1;
    354
    355	spin_unlock_irqrestore(&d->vhub->lock, flags);
    356
    357	return 0;
    358}
    359
    360static struct usb_ep *ast_vhub_udc_match_ep(struct usb_gadget *gadget,
    361					    struct usb_endpoint_descriptor *desc,
    362					    struct usb_ss_ep_comp_descriptor *ss)
    363{
    364	struct ast_vhub_dev *d = to_ast_dev(gadget);
    365	struct ast_vhub_ep *ep;
    366	struct usb_ep *u_ep;
    367	unsigned int max, addr, i;
    368
    369	DDBG(d, "Match EP type %d\n", usb_endpoint_type(desc));
    370
    371	/*
    372	 * First we need to look for an existing unclaimed EP as another
    373	 * configuration may have already associated a bunch of EPs with
    374	 * this gadget. This duplicates the code in usb_ep_autoconfig_ss()
    375	 * unfortunately.
    376	 */
    377	list_for_each_entry(u_ep, &gadget->ep_list, ep_list) {
    378		if (usb_gadget_ep_match_desc(gadget, u_ep, desc, ss)) {
    379			DDBG(d, " -> using existing EP%d\n",
    380			     to_ast_ep(u_ep)->d_idx);
    381			return u_ep;
    382		}
    383	}
    384
    385	/*
    386	 * We didn't find one, we need to grab one from the pool.
    387	 *
    388	 * First let's do some sanity checking
    389	 */
    390	switch(usb_endpoint_type(desc)) {
    391	case USB_ENDPOINT_XFER_CONTROL:
    392		/* Only EP0 can be a control endpoint */
    393		return NULL;
    394	case USB_ENDPOINT_XFER_ISOC:
    395		/* ISO:	 limit 1023 bytes full speed, 1024 high/super speed */
    396		if (gadget_is_dualspeed(gadget))
    397			max = 1024;
    398		else
    399			max = 1023;
    400		break;
    401	case USB_ENDPOINT_XFER_BULK:
    402		if (gadget_is_dualspeed(gadget))
    403			max = 512;
    404		else
    405			max = 64;
    406		break;
    407	case USB_ENDPOINT_XFER_INT:
    408		if (gadget_is_dualspeed(gadget))
    409			max = 1024;
    410		else
    411			max = 64;
    412		break;
    413	}
    414	if (usb_endpoint_maxp(desc) > max)
    415		return NULL;
    416
    417	/*
    418	 * Find a free EP address for that device. We can't
    419	 * let the generic code assign these as it would
    420	 * create overlapping numbers for IN and OUT which
    421	 * we don't support, so also create a suitable name
    422	 * that will allow the generic code to use our
    423	 * assigned address.
    424	 */
    425	for (i = 0; i < d->max_epns; i++)
    426		if (d->epns[i] == NULL)
    427			break;
    428	if (i >= d->max_epns)
    429		return NULL;
    430	addr = i + 1;
    431
    432	/*
    433	 * Now grab an EP from the shared pool and associate
    434	 * it with our device
    435	 */
    436	ep = ast_vhub_alloc_epn(d, addr);
    437	if (!ep)
    438		return NULL;
    439	DDBG(d, "Allocated epn#%d for port EP%d\n",
    440	     ep->epn.g_idx, addr);
    441
    442	return &ep->ep;
    443}
    444
    445static int ast_vhub_udc_stop(struct usb_gadget *gadget)
    446{
    447	struct ast_vhub_dev *d = to_ast_dev(gadget);
    448	unsigned long flags;
    449
    450	spin_lock_irqsave(&d->vhub->lock, flags);
    451
    452	DDBG(d, "stop\n");
    453
    454	d->driver = NULL;
    455	d->gadget.speed = USB_SPEED_UNKNOWN;
    456
    457	ast_vhub_dev_nuke(d);
    458
    459	if (d->enabled)
    460		ast_vhub_dev_disable(d);
    461
    462	spin_unlock_irqrestore(&d->vhub->lock, flags);
    463
    464	return 0;
    465}
    466
    467static const struct usb_gadget_ops ast_vhub_udc_ops = {
    468	.get_frame	= ast_vhub_udc_get_frame,
    469	.wakeup		= ast_vhub_udc_wakeup,
    470	.pullup		= ast_vhub_udc_pullup,
    471	.udc_start	= ast_vhub_udc_start,
    472	.udc_stop	= ast_vhub_udc_stop,
    473	.match_ep	= ast_vhub_udc_match_ep,
    474};
    475
    476void ast_vhub_dev_suspend(struct ast_vhub_dev *d)
    477{
    478	if (d->driver && d->driver->suspend) {
    479		spin_unlock(&d->vhub->lock);
    480		d->driver->suspend(&d->gadget);
    481		spin_lock(&d->vhub->lock);
    482	}
    483}
    484
    485void ast_vhub_dev_resume(struct ast_vhub_dev *d)
    486{
    487	if (d->driver && d->driver->resume) {
    488		spin_unlock(&d->vhub->lock);
    489		d->driver->resume(&d->gadget);
    490		spin_lock(&d->vhub->lock);
    491	}
    492}
    493
    494void ast_vhub_dev_reset(struct ast_vhub_dev *d)
    495{
    496	/* No driver, just disable the device and return */
    497	if (!d->driver) {
    498		ast_vhub_dev_disable(d);
    499		return;
    500	}
    501
    502	/* If the port isn't enabled, just enable it */
    503	if (!d->enabled) {
    504		DDBG(d, "Reset of disabled device, enabling...\n");
    505		ast_vhub_dev_enable(d);
    506	} else {
    507		DDBG(d, "Reset of enabled device, resetting...\n");
    508		spin_unlock(&d->vhub->lock);
    509		usb_gadget_udc_reset(&d->gadget, d->driver);
    510		spin_lock(&d->vhub->lock);
    511
    512		/*
    513		 * Disable and maybe re-enable HW, this will clear the address
    514		 * and speed setting.
    515		 */
    516		ast_vhub_dev_disable(d);
    517		ast_vhub_dev_enable(d);
    518	}
    519}
    520
    521void ast_vhub_del_dev(struct ast_vhub_dev *d)
    522{
    523	unsigned long flags;
    524
    525	spin_lock_irqsave(&d->vhub->lock, flags);
    526	if (!d->registered) {
    527		spin_unlock_irqrestore(&d->vhub->lock, flags);
    528		return;
    529	}
    530	d->registered = false;
    531	spin_unlock_irqrestore(&d->vhub->lock, flags);
    532
    533	usb_del_gadget_udc(&d->gadget);
    534	device_unregister(d->port_dev);
    535	kfree(d->epns);
    536}
    537
    538static void ast_vhub_dev_release(struct device *dev)
    539{
    540	kfree(dev);
    541}
    542
    543int ast_vhub_init_dev(struct ast_vhub *vhub, unsigned int idx)
    544{
    545	struct ast_vhub_dev *d = &vhub->ports[idx].dev;
    546	struct device *parent = &vhub->pdev->dev;
    547	int rc;
    548
    549	d->vhub = vhub;
    550	d->index = idx;
    551	d->name = devm_kasprintf(parent, GFP_KERNEL, "port%d", idx+1);
    552	d->regs = vhub->regs + 0x100 + 0x10 * idx;
    553
    554	ast_vhub_init_ep0(vhub, &d->ep0, d);
    555
    556	/*
    557	 * A USB device can have up to 30 endpoints besides control
    558	 * endpoint 0.
    559	 */
    560	d->max_epns = min_t(u32, vhub->max_epns, 30);
    561	d->epns = kcalloc(d->max_epns, sizeof(*d->epns), GFP_KERNEL);
    562	if (!d->epns)
    563		return -ENOMEM;
    564
    565	/*
    566	 * The UDC core really needs us to have separate and uniquely
    567	 * named "parent" devices for each port so we create a sub device
    568	 * here for that purpose
    569	 */
    570	d->port_dev = kzalloc(sizeof(struct device), GFP_KERNEL);
    571	if (!d->port_dev) {
    572		rc = -ENOMEM;
    573		goto fail_alloc;
    574	}
    575	device_initialize(d->port_dev);
    576	d->port_dev->release = ast_vhub_dev_release;
    577	d->port_dev->parent = parent;
    578	dev_set_name(d->port_dev, "%s:p%d", dev_name(parent), idx + 1);
    579	rc = device_add(d->port_dev);
    580	if (rc)
    581		goto fail_add;
    582
    583	/* Populate gadget */
    584	INIT_LIST_HEAD(&d->gadget.ep_list);
    585	d->gadget.ops = &ast_vhub_udc_ops;
    586	d->gadget.ep0 = &d->ep0.ep;
    587	d->gadget.name = KBUILD_MODNAME;
    588	if (vhub->force_usb1)
    589		d->gadget.max_speed = USB_SPEED_FULL;
    590	else
    591		d->gadget.max_speed = USB_SPEED_HIGH;
    592	d->gadget.speed = USB_SPEED_UNKNOWN;
    593	d->gadget.dev.of_node = vhub->pdev->dev.of_node;
    594
    595	rc = usb_add_gadget_udc(d->port_dev, &d->gadget);
    596	if (rc != 0)
    597		goto fail_udc;
    598	d->registered = true;
    599
    600	return 0;
    601 fail_udc:
    602	device_del(d->port_dev);
    603 fail_add:
    604	put_device(d->port_dev);
    605 fail_alloc:
    606	kfree(d->epns);
    607
    608	return rc;
    609}