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

ushc.c (13523B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * USB SD Host Controller (USHC) controller driver.
      4 *
      5 * Copyright (C) 2010 Cambridge Silicon Radio Ltd.
      6 *
      7 * Notes:
      8 *   - Only version 2 devices are supported.
      9 *   - Version 2 devices only support SDIO cards/devices (R2 response is
     10 *     unsupported).
     11 *
     12 * References:
     13 *   [USHC] USB SD Host Controller specification (CS-118793-SP)
     14 */
     15#include <linux/module.h>
     16#include <linux/usb.h>
     17#include <linux/kernel.h>
     18#include <linux/slab.h>
     19#include <linux/dma-mapping.h>
     20#include <linux/mmc/host.h>
     21
     22enum ushc_request {
     23	USHC_GET_CAPS  = 0x00,
     24	USHC_HOST_CTRL = 0x01,
     25	USHC_PWR_CTRL  = 0x02,
     26	USHC_CLK_FREQ  = 0x03,
     27	USHC_EXEC_CMD  = 0x04,
     28	USHC_READ_RESP = 0x05,
     29	USHC_RESET     = 0x06,
     30};
     31
     32enum ushc_request_type {
     33	USHC_GET_CAPS_TYPE  = USB_DIR_IN  | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
     34	USHC_HOST_CTRL_TYPE = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
     35	USHC_PWR_CTRL_TYPE  = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
     36	USHC_CLK_FREQ_TYPE  = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
     37	USHC_EXEC_CMD_TYPE  = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
     38	USHC_READ_RESP_TYPE = USB_DIR_IN  | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
     39	USHC_RESET_TYPE     = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
     40};
     41
     42#define USHC_GET_CAPS_VERSION_MASK 0xff
     43#define USHC_GET_CAPS_3V3      (1 << 8)
     44#define USHC_GET_CAPS_3V0      (1 << 9)
     45#define USHC_GET_CAPS_1V8      (1 << 10)
     46#define USHC_GET_CAPS_HIGH_SPD (1 << 16)
     47
     48#define USHC_HOST_CTRL_4BIT     (1 << 1)
     49#define USHC_HOST_CTRL_HIGH_SPD (1 << 0)
     50
     51#define USHC_PWR_CTRL_OFF 0x00
     52#define USHC_PWR_CTRL_3V3 0x01
     53#define USHC_PWR_CTRL_3V0 0x02
     54#define USHC_PWR_CTRL_1V8 0x03
     55
     56#define USHC_READ_RESP_BUSY        (1 << 4)
     57#define USHC_READ_RESP_ERR_TIMEOUT (1 << 3)
     58#define USHC_READ_RESP_ERR_CRC     (1 << 2)
     59#define USHC_READ_RESP_ERR_DAT     (1 << 1)
     60#define USHC_READ_RESP_ERR_CMD     (1 << 0)
     61#define USHC_READ_RESP_ERR_MASK    0x0f
     62
     63struct ushc_cbw {
     64	__u8 signature;
     65	__u8 cmd_idx;
     66	__le16 block_size;
     67	__le32 arg;
     68} __attribute__((packed));
     69
     70#define USHC_CBW_SIGNATURE 'C'
     71
     72struct ushc_csw {
     73	__u8 signature;
     74	__u8 status;
     75	__le32 response;
     76} __attribute__((packed));
     77
     78#define USHC_CSW_SIGNATURE 'S'
     79
     80struct ushc_int_data {
     81	u8 status;
     82	u8 reserved[3];
     83};
     84
     85#define USHC_INT_STATUS_SDIO_INT     (1 << 1)
     86#define USHC_INT_STATUS_CARD_PRESENT (1 << 0)
     87
     88
     89struct ushc_data {
     90	struct usb_device *usb_dev;
     91	struct mmc_host *mmc;
     92
     93	struct urb *int_urb;
     94	struct ushc_int_data *int_data;
     95
     96	struct urb *cbw_urb;
     97	struct ushc_cbw *cbw;
     98
     99	struct urb *data_urb;
    100
    101	struct urb *csw_urb;
    102	struct ushc_csw *csw;
    103
    104	spinlock_t lock;
    105	struct mmc_request *current_req;
    106	u32 caps;
    107	u16 host_ctrl;
    108	unsigned long flags;
    109	u8 last_status;
    110	int clock_freq;
    111};
    112
    113#define DISCONNECTED    0
    114#define INT_EN          1
    115#define IGNORE_NEXT_INT 2
    116
    117static void data_callback(struct urb *urb);
    118
    119static int ushc_hw_reset(struct ushc_data *ushc)
    120{
    121	return usb_control_msg(ushc->usb_dev, usb_sndctrlpipe(ushc->usb_dev, 0),
    122			       USHC_RESET, USHC_RESET_TYPE,
    123			       0, 0, NULL, 0, 100);
    124}
    125
    126static int ushc_hw_get_caps(struct ushc_data *ushc)
    127{
    128	int ret;
    129	int version;
    130
    131	ret = usb_control_msg(ushc->usb_dev, usb_rcvctrlpipe(ushc->usb_dev, 0),
    132			      USHC_GET_CAPS, USHC_GET_CAPS_TYPE,
    133			      0, 0, &ushc->caps, sizeof(ushc->caps), 100);
    134	if (ret < 0)
    135		return ret;
    136
    137	ushc->caps = le32_to_cpu(ushc->caps);
    138
    139	version = ushc->caps & USHC_GET_CAPS_VERSION_MASK;
    140	if (version != 0x02) {
    141		dev_err(&ushc->usb_dev->dev, "controller version %d is not supported\n", version);
    142		return -EINVAL;
    143	}
    144
    145	return 0;
    146}
    147
    148static int ushc_hw_set_host_ctrl(struct ushc_data *ushc, u16 mask, u16 val)
    149{
    150	u16 host_ctrl;
    151	int ret;
    152
    153	host_ctrl = (ushc->host_ctrl & ~mask) | val;
    154	ret = usb_control_msg(ushc->usb_dev, usb_sndctrlpipe(ushc->usb_dev, 0),
    155			      USHC_HOST_CTRL, USHC_HOST_CTRL_TYPE,
    156			      host_ctrl, 0, NULL, 0, 100);
    157	if (ret < 0)
    158		return ret;
    159	ushc->host_ctrl = host_ctrl;
    160	return 0;
    161}
    162
    163static void int_callback(struct urb *urb)
    164{
    165	struct ushc_data *ushc = urb->context;
    166	u8 status, last_status;
    167
    168	if (urb->status < 0)
    169		return;
    170
    171	status = ushc->int_data->status;
    172	last_status = ushc->last_status;
    173	ushc->last_status = status;
    174
    175	/*
    176	 * Ignore the card interrupt status on interrupt transfers that
    177	 * were submitted while card interrupts where disabled.
    178	 *
    179	 * This avoid occasional spurious interrupts when enabling
    180	 * interrupts immediately after clearing the source on the card.
    181	 */
    182
    183	if (!test_and_clear_bit(IGNORE_NEXT_INT, &ushc->flags)
    184	    && test_bit(INT_EN, &ushc->flags)
    185	    && status & USHC_INT_STATUS_SDIO_INT) {
    186		mmc_signal_sdio_irq(ushc->mmc);
    187	}
    188
    189	if ((status ^ last_status) & USHC_INT_STATUS_CARD_PRESENT)
    190		mmc_detect_change(ushc->mmc, msecs_to_jiffies(100));
    191
    192	if (!test_bit(INT_EN, &ushc->flags))
    193		set_bit(IGNORE_NEXT_INT, &ushc->flags);
    194	usb_submit_urb(ushc->int_urb, GFP_ATOMIC);
    195}
    196
    197static void cbw_callback(struct urb *urb)
    198{
    199	struct ushc_data *ushc = urb->context;
    200
    201	if (urb->status != 0) {
    202		usb_unlink_urb(ushc->data_urb);
    203		usb_unlink_urb(ushc->csw_urb);
    204	}
    205}
    206
    207static void data_callback(struct urb *urb)
    208{
    209	struct ushc_data *ushc = urb->context;
    210
    211	if (urb->status != 0)
    212		usb_unlink_urb(ushc->csw_urb);
    213}
    214
    215static void csw_callback(struct urb *urb)
    216{
    217	struct ushc_data *ushc = urb->context;
    218	struct mmc_request *req = ushc->current_req;
    219	int status;
    220
    221	status = ushc->csw->status;
    222
    223	if (urb->status != 0) {
    224		req->cmd->error = urb->status;
    225	} else if (status & USHC_READ_RESP_ERR_CMD) {
    226		if (status & USHC_READ_RESP_ERR_CRC)
    227			req->cmd->error = -EIO;
    228		else
    229			req->cmd->error = -ETIMEDOUT;
    230	}
    231	if (req->data) {
    232		if (status & USHC_READ_RESP_ERR_DAT) {
    233			if (status & USHC_READ_RESP_ERR_CRC)
    234				req->data->error = -EIO;
    235			else
    236				req->data->error = -ETIMEDOUT;
    237			req->data->bytes_xfered = 0;
    238		} else {
    239			req->data->bytes_xfered = req->data->blksz * req->data->blocks;
    240		}
    241	}
    242
    243	req->cmd->resp[0] = le32_to_cpu(ushc->csw->response);
    244
    245	mmc_request_done(ushc->mmc, req);
    246}
    247
    248static void ushc_request(struct mmc_host *mmc, struct mmc_request *req)
    249{
    250	struct ushc_data *ushc = mmc_priv(mmc);
    251	int ret;
    252	unsigned long flags;
    253
    254	spin_lock_irqsave(&ushc->lock, flags);
    255
    256	if (test_bit(DISCONNECTED, &ushc->flags)) {
    257		ret = -ENODEV;
    258		goto out;
    259	}
    260
    261	/* Version 2 firmware doesn't support the R2 response format. */
    262	if (req->cmd->flags & MMC_RSP_136) {
    263		ret = -EINVAL;
    264		goto out;
    265	}
    266
    267	/* The Astoria's data FIFOs don't work with clock speeds < 5MHz so
    268	   limit commands with data to 6MHz or more. */
    269	if (req->data && ushc->clock_freq < 6000000) {
    270		ret = -EINVAL;
    271		goto out;
    272	}
    273
    274	ushc->current_req = req;
    275
    276	/* Start cmd with CBW. */
    277	ushc->cbw->cmd_idx = cpu_to_le16(req->cmd->opcode);
    278	if (req->data)
    279		ushc->cbw->block_size = cpu_to_le16(req->data->blksz);
    280	else
    281		ushc->cbw->block_size = 0;
    282	ushc->cbw->arg = cpu_to_le32(req->cmd->arg);
    283
    284	ret = usb_submit_urb(ushc->cbw_urb, GFP_ATOMIC);
    285	if (ret < 0)
    286		goto out;
    287
    288	/* Submit data (if any). */
    289	if (req->data) {
    290		struct mmc_data *data = req->data;
    291		int pipe;
    292
    293		if (data->flags & MMC_DATA_READ)
    294			pipe = usb_rcvbulkpipe(ushc->usb_dev, 6);
    295		else
    296			pipe = usb_sndbulkpipe(ushc->usb_dev, 2);
    297
    298		usb_fill_bulk_urb(ushc->data_urb, ushc->usb_dev, pipe,
    299				  NULL, data->sg->length,
    300				  data_callback, ushc);
    301		ushc->data_urb->num_sgs = 1;
    302		ushc->data_urb->sg = data->sg;
    303		ret = usb_submit_urb(ushc->data_urb, GFP_ATOMIC);
    304		if (ret < 0)
    305			goto out;
    306	}
    307
    308	/* Submit CSW. */
    309	ret = usb_submit_urb(ushc->csw_urb, GFP_ATOMIC);
    310
    311out:
    312	spin_unlock_irqrestore(&ushc->lock, flags);
    313	if (ret < 0) {
    314		usb_unlink_urb(ushc->cbw_urb);
    315		usb_unlink_urb(ushc->data_urb);
    316		req->cmd->error = ret;
    317		mmc_request_done(mmc, req);
    318	}
    319}
    320
    321static int ushc_set_power(struct ushc_data *ushc, unsigned char power_mode)
    322{
    323	u16 voltage;
    324
    325	switch (power_mode) {
    326	case MMC_POWER_OFF:
    327		voltage = USHC_PWR_CTRL_OFF;
    328		break;
    329	case MMC_POWER_UP:
    330	case MMC_POWER_ON:
    331		voltage = USHC_PWR_CTRL_3V3;
    332		break;
    333	default:
    334		return -EINVAL;
    335	}
    336
    337	return usb_control_msg(ushc->usb_dev, usb_sndctrlpipe(ushc->usb_dev, 0),
    338			       USHC_PWR_CTRL, USHC_PWR_CTRL_TYPE,
    339			       voltage, 0, NULL, 0, 100);
    340}
    341
    342static int ushc_set_bus_width(struct ushc_data *ushc, int bus_width)
    343{
    344	return ushc_hw_set_host_ctrl(ushc, USHC_HOST_CTRL_4BIT,
    345				     bus_width == 4 ? USHC_HOST_CTRL_4BIT : 0);
    346}
    347
    348static int ushc_set_bus_freq(struct ushc_data *ushc, int clk, bool enable_hs)
    349{
    350	int ret;
    351
    352	/* Hardware can't detect interrupts while the clock is off. */
    353	if (clk == 0)
    354		clk = 400000;
    355
    356	ret = ushc_hw_set_host_ctrl(ushc, USHC_HOST_CTRL_HIGH_SPD,
    357				    enable_hs ? USHC_HOST_CTRL_HIGH_SPD : 0);
    358	if (ret < 0)
    359		return ret;
    360
    361	ret = usb_control_msg(ushc->usb_dev, usb_sndctrlpipe(ushc->usb_dev, 0),
    362			      USHC_CLK_FREQ, USHC_CLK_FREQ_TYPE,
    363			      clk & 0xffff, (clk >> 16) & 0xffff, NULL, 0, 100);
    364	if (ret < 0)
    365		return ret;
    366
    367	ushc->clock_freq = clk;
    368	return 0;
    369}
    370
    371static void ushc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
    372{
    373	struct ushc_data *ushc = mmc_priv(mmc);
    374
    375	ushc_set_power(ushc, ios->power_mode);
    376	ushc_set_bus_width(ushc, 1 << ios->bus_width);
    377	ushc_set_bus_freq(ushc, ios->clock, ios->timing == MMC_TIMING_SD_HS);
    378}
    379
    380static int ushc_get_cd(struct mmc_host *mmc)
    381{
    382	struct ushc_data *ushc = mmc_priv(mmc);
    383
    384	return !!(ushc->last_status & USHC_INT_STATUS_CARD_PRESENT);
    385}
    386
    387static void ushc_enable_sdio_irq(struct mmc_host *mmc, int enable)
    388{
    389	struct ushc_data *ushc = mmc_priv(mmc);
    390
    391	if (enable)
    392		set_bit(INT_EN, &ushc->flags);
    393	else
    394		clear_bit(INT_EN, &ushc->flags);
    395}
    396
    397static void ushc_clean_up(struct ushc_data *ushc)
    398{
    399	usb_free_urb(ushc->int_urb);
    400	usb_free_urb(ushc->csw_urb);
    401	usb_free_urb(ushc->data_urb);
    402	usb_free_urb(ushc->cbw_urb);
    403
    404	kfree(ushc->int_data);
    405	kfree(ushc->cbw);
    406	kfree(ushc->csw);
    407
    408	mmc_free_host(ushc->mmc);
    409}
    410
    411static const struct mmc_host_ops ushc_ops = {
    412	.request         = ushc_request,
    413	.set_ios         = ushc_set_ios,
    414	.get_cd          = ushc_get_cd,
    415	.enable_sdio_irq = ushc_enable_sdio_irq,
    416};
    417
    418static int ushc_probe(struct usb_interface *intf, const struct usb_device_id *id)
    419{
    420	struct usb_device *usb_dev = interface_to_usbdev(intf);
    421	struct mmc_host *mmc;
    422	struct ushc_data *ushc;
    423	int ret;
    424
    425	if (intf->cur_altsetting->desc.bNumEndpoints < 1)
    426		return -ENODEV;
    427
    428	mmc = mmc_alloc_host(sizeof(struct ushc_data), &intf->dev);
    429	if (mmc == NULL)
    430		return -ENOMEM;
    431	ushc = mmc_priv(mmc);
    432	usb_set_intfdata(intf, ushc);
    433
    434	ushc->usb_dev = usb_dev;
    435	ushc->mmc = mmc;
    436
    437	spin_lock_init(&ushc->lock);
    438
    439	ret = ushc_hw_reset(ushc);
    440	if (ret < 0)
    441		goto err;
    442
    443	/* Read capabilities. */
    444	ret = ushc_hw_get_caps(ushc);
    445	if (ret < 0)
    446		goto err;
    447
    448	mmc->ops = &ushc_ops;
    449
    450	mmc->f_min = 400000;
    451	mmc->f_max = 50000000;
    452	mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
    453	mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_SDIO_IRQ;
    454	mmc->caps |= (ushc->caps & USHC_GET_CAPS_HIGH_SPD) ? MMC_CAP_SD_HIGHSPEED : 0;
    455
    456	mmc->max_seg_size  = 512*511;
    457	mmc->max_segs      = 1;
    458	mmc->max_req_size  = 512*511;
    459	mmc->max_blk_size  = 512;
    460	mmc->max_blk_count = 511;
    461
    462	ushc->int_urb = usb_alloc_urb(0, GFP_KERNEL);
    463	if (ushc->int_urb == NULL) {
    464		ret = -ENOMEM;
    465		goto err;
    466	}
    467	ushc->int_data = kzalloc(sizeof(struct ushc_int_data), GFP_KERNEL);
    468	if (ushc->int_data == NULL) {
    469		ret = -ENOMEM;
    470		goto err;
    471	}
    472	usb_fill_int_urb(ushc->int_urb, ushc->usb_dev,
    473			 usb_rcvintpipe(usb_dev,
    474					intf->cur_altsetting->endpoint[0].desc.bEndpointAddress),
    475			 ushc->int_data, sizeof(struct ushc_int_data),
    476			 int_callback, ushc,
    477			 intf->cur_altsetting->endpoint[0].desc.bInterval);
    478
    479	ushc->cbw_urb = usb_alloc_urb(0, GFP_KERNEL);
    480	if (ushc->cbw_urb == NULL) {
    481		ret = -ENOMEM;
    482		goto err;
    483	}
    484	ushc->cbw = kzalloc(sizeof(struct ushc_cbw), GFP_KERNEL);
    485	if (ushc->cbw == NULL) {
    486		ret = -ENOMEM;
    487		goto err;
    488	}
    489	ushc->cbw->signature = USHC_CBW_SIGNATURE;
    490
    491	usb_fill_bulk_urb(ushc->cbw_urb, ushc->usb_dev, usb_sndbulkpipe(usb_dev, 2),
    492			  ushc->cbw, sizeof(struct ushc_cbw),
    493			  cbw_callback, ushc);
    494
    495	ushc->data_urb = usb_alloc_urb(0, GFP_KERNEL);
    496	if (ushc->data_urb == NULL) {
    497		ret = -ENOMEM;
    498		goto err;
    499	}
    500
    501	ushc->csw_urb = usb_alloc_urb(0, GFP_KERNEL);
    502	if (ushc->csw_urb == NULL) {
    503		ret = -ENOMEM;
    504		goto err;
    505	}
    506	ushc->csw = kzalloc(sizeof(struct ushc_csw), GFP_KERNEL);
    507	if (ushc->csw == NULL) {
    508		ret = -ENOMEM;
    509		goto err;
    510	}
    511	usb_fill_bulk_urb(ushc->csw_urb, ushc->usb_dev, usb_rcvbulkpipe(usb_dev, 6),
    512			  ushc->csw, sizeof(struct ushc_csw),
    513			  csw_callback, ushc);
    514
    515	ret = mmc_add_host(ushc->mmc);
    516	if (ret)
    517		goto err;
    518
    519	ret = usb_submit_urb(ushc->int_urb, GFP_KERNEL);
    520	if (ret < 0) {
    521		mmc_remove_host(ushc->mmc);
    522		goto err;
    523	}
    524
    525	return 0;
    526
    527err:
    528	ushc_clean_up(ushc);
    529	return ret;
    530}
    531
    532static void ushc_disconnect(struct usb_interface *intf)
    533{
    534	struct ushc_data *ushc = usb_get_intfdata(intf);
    535
    536	spin_lock_irq(&ushc->lock);
    537	set_bit(DISCONNECTED, &ushc->flags);
    538	spin_unlock_irq(&ushc->lock);
    539
    540	usb_kill_urb(ushc->int_urb);
    541	usb_kill_urb(ushc->cbw_urb);
    542	usb_kill_urb(ushc->data_urb);
    543	usb_kill_urb(ushc->csw_urb);
    544
    545	mmc_remove_host(ushc->mmc);
    546
    547	ushc_clean_up(ushc);
    548}
    549
    550static struct usb_device_id ushc_id_table[] = {
    551	/* CSR USB SD Host Controller */
    552	{ USB_DEVICE(0x0a12, 0x5d10) },
    553	{ },
    554};
    555MODULE_DEVICE_TABLE(usb, ushc_id_table);
    556
    557static struct usb_driver ushc_driver = {
    558	.name       = "ushc",
    559	.id_table   = ushc_id_table,
    560	.probe      = ushc_probe,
    561	.disconnect = ushc_disconnect,
    562};
    563
    564module_usb_driver(ushc_driver);
    565
    566MODULE_DESCRIPTION("USB SD Host Controller driver");
    567MODULE_AUTHOR("David Vrabel <david.vrabel@csr.com>");
    568MODULE_LICENSE("GPL");