Lines Matching +full:mmc +full:- +full:controller

1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * USB SD Host Controller (USHC) controller driver.
8 * - Only version 2 devices are supported.
9 * - Version 2 devices only support SDIO cards/devices (R2 response is
13 * [USHC] USB SD Host Controller specification (CS-118793-SP)
19 #include <linux/dma-mapping.h>
20 #include <linux/mmc/host.h>
91 struct mmc_host *mmc; member
121 return usb_control_msg(ushc->usb_dev, usb_sndctrlpipe(ushc->usb_dev, 0), in ushc_hw_reset()
131 ret = usb_control_msg(ushc->usb_dev, usb_rcvctrlpipe(ushc->usb_dev, 0), in ushc_hw_get_caps()
133 0, 0, &ushc->caps, sizeof(ushc->caps), 100); in ushc_hw_get_caps()
137 ushc->caps = le32_to_cpu(ushc->caps); in ushc_hw_get_caps()
139 version = ushc->caps & USHC_GET_CAPS_VERSION_MASK; in ushc_hw_get_caps()
141 dev_err(&ushc->usb_dev->dev, "controller version %d is not supported\n", version); in ushc_hw_get_caps()
142 return -EINVAL; in ushc_hw_get_caps()
153 host_ctrl = (ushc->host_ctrl & ~mask) | val; in ushc_hw_set_host_ctrl()
154 ret = usb_control_msg(ushc->usb_dev, usb_sndctrlpipe(ushc->usb_dev, 0), in ushc_hw_set_host_ctrl()
159 ushc->host_ctrl = host_ctrl; in ushc_hw_set_host_ctrl()
165 struct ushc_data *ushc = urb->context; in int_callback()
168 if (urb->status < 0) in int_callback()
171 status = ushc->int_data->status; in int_callback()
172 last_status = ushc->last_status; in int_callback()
173 ushc->last_status = status; in int_callback()
183 if (!test_and_clear_bit(IGNORE_NEXT_INT, &ushc->flags) in int_callback()
184 && test_bit(INT_EN, &ushc->flags) in int_callback()
186 mmc_signal_sdio_irq(ushc->mmc); in int_callback()
190 mmc_detect_change(ushc->mmc, msecs_to_jiffies(100)); in int_callback()
192 if (!test_bit(INT_EN, &ushc->flags)) in int_callback()
193 set_bit(IGNORE_NEXT_INT, &ushc->flags); in int_callback()
194 usb_submit_urb(ushc->int_urb, GFP_ATOMIC); in int_callback()
199 struct ushc_data *ushc = urb->context; in cbw_callback()
201 if (urb->status != 0) { in cbw_callback()
202 usb_unlink_urb(ushc->data_urb); in cbw_callback()
203 usb_unlink_urb(ushc->csw_urb); in cbw_callback()
209 struct ushc_data *ushc = urb->context; in data_callback()
211 if (urb->status != 0) in data_callback()
212 usb_unlink_urb(ushc->csw_urb); in data_callback()
217 struct ushc_data *ushc = urb->context; in csw_callback()
218 struct mmc_request *req = ushc->current_req; in csw_callback()
221 status = ushc->csw->status; in csw_callback()
223 if (urb->status != 0) { in csw_callback()
224 req->cmd->error = urb->status; in csw_callback()
227 req->cmd->error = -EIO; in csw_callback()
229 req->cmd->error = -ETIMEDOUT; in csw_callback()
231 if (req->data) { in csw_callback()
234 req->data->error = -EIO; in csw_callback()
236 req->data->error = -ETIMEDOUT; in csw_callback()
237 req->data->bytes_xfered = 0; in csw_callback()
239 req->data->bytes_xfered = req->data->blksz * req->data->blocks; in csw_callback()
243 req->cmd->resp[0] = le32_to_cpu(ushc->csw->response); in csw_callback()
245 mmc_request_done(ushc->mmc, req); in csw_callback()
248 static void ushc_request(struct mmc_host *mmc, struct mmc_request *req) in ushc_request() argument
250 struct ushc_data *ushc = mmc_priv(mmc); in ushc_request()
254 spin_lock_irqsave(&ushc->lock, flags); in ushc_request()
256 if (test_bit(DISCONNECTED, &ushc->flags)) { in ushc_request()
257 ret = -ENODEV; in ushc_request()
262 if (req->cmd->flags & MMC_RSP_136) { in ushc_request()
263 ret = -EINVAL; in ushc_request()
269 if (req->data && ushc->clock_freq < 6000000) { in ushc_request()
270 ret = -EINVAL; in ushc_request()
274 ushc->current_req = req; in ushc_request()
277 ushc->cbw->cmd_idx = cpu_to_le16(req->cmd->opcode); in ushc_request()
278 if (req->data) in ushc_request()
279 ushc->cbw->block_size = cpu_to_le16(req->data->blksz); in ushc_request()
281 ushc->cbw->block_size = 0; in ushc_request()
282 ushc->cbw->arg = cpu_to_le32(req->cmd->arg); in ushc_request()
284 ret = usb_submit_urb(ushc->cbw_urb, GFP_ATOMIC); in ushc_request()
289 if (req->data) { in ushc_request()
290 struct mmc_data *data = req->data; in ushc_request()
293 if (data->flags & MMC_DATA_READ) in ushc_request()
294 pipe = usb_rcvbulkpipe(ushc->usb_dev, 6); in ushc_request()
296 pipe = usb_sndbulkpipe(ushc->usb_dev, 2); in ushc_request()
298 usb_fill_bulk_urb(ushc->data_urb, ushc->usb_dev, pipe, in ushc_request()
299 NULL, data->sg->length, in ushc_request()
301 ushc->data_urb->num_sgs = 1; in ushc_request()
302 ushc->data_urb->sg = data->sg; in ushc_request()
303 ret = usb_submit_urb(ushc->data_urb, GFP_ATOMIC); in ushc_request()
309 ret = usb_submit_urb(ushc->csw_urb, GFP_ATOMIC); in ushc_request()
312 spin_unlock_irqrestore(&ushc->lock, flags); in ushc_request()
314 usb_unlink_urb(ushc->cbw_urb); in ushc_request()
315 usb_unlink_urb(ushc->data_urb); in ushc_request()
316 req->cmd->error = ret; in ushc_request()
317 mmc_request_done(mmc, req); in ushc_request()
334 return -EINVAL; in ushc_set_power()
337 return usb_control_msg(ushc->usb_dev, usb_sndctrlpipe(ushc->usb_dev, 0), in ushc_set_power()
361 ret = usb_control_msg(ushc->usb_dev, usb_sndctrlpipe(ushc->usb_dev, 0), in ushc_set_bus_freq()
367 ushc->clock_freq = clk; in ushc_set_bus_freq()
371 static void ushc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) in ushc_set_ios() argument
373 struct ushc_data *ushc = mmc_priv(mmc); in ushc_set_ios()
375 ushc_set_power(ushc, ios->power_mode); in ushc_set_ios()
376 ushc_set_bus_width(ushc, 1 << ios->bus_width); in ushc_set_ios()
377 ushc_set_bus_freq(ushc, ios->clock, ios->timing == MMC_TIMING_SD_HS); in ushc_set_ios()
380 static int ushc_get_cd(struct mmc_host *mmc) in ushc_get_cd() argument
382 struct ushc_data *ushc = mmc_priv(mmc); in ushc_get_cd()
384 return !!(ushc->last_status & USHC_INT_STATUS_CARD_PRESENT); in ushc_get_cd()
387 static void ushc_enable_sdio_irq(struct mmc_host *mmc, int enable) in ushc_enable_sdio_irq() argument
389 struct ushc_data *ushc = mmc_priv(mmc); in ushc_enable_sdio_irq()
392 set_bit(INT_EN, &ushc->flags); in ushc_enable_sdio_irq()
394 clear_bit(INT_EN, &ushc->flags); in ushc_enable_sdio_irq()
399 usb_free_urb(ushc->int_urb); in ushc_clean_up()
400 usb_free_urb(ushc->csw_urb); in ushc_clean_up()
401 usb_free_urb(ushc->data_urb); in ushc_clean_up()
402 usb_free_urb(ushc->cbw_urb); in ushc_clean_up()
404 kfree(ushc->int_data); in ushc_clean_up()
405 kfree(ushc->cbw); in ushc_clean_up()
406 kfree(ushc->csw); in ushc_clean_up()
408 mmc_free_host(ushc->mmc); in ushc_clean_up()
421 struct mmc_host *mmc; in ushc_probe() local
425 if (intf->cur_altsetting->desc.bNumEndpoints < 1) in ushc_probe()
426 return -ENODEV; in ushc_probe()
428 mmc = mmc_alloc_host(sizeof(struct ushc_data), &intf->dev); in ushc_probe()
429 if (mmc == NULL) in ushc_probe()
430 return -ENOMEM; in ushc_probe()
431 ushc = mmc_priv(mmc); in ushc_probe()
434 ushc->usb_dev = usb_dev; in ushc_probe()
435 ushc->mmc = mmc; in ushc_probe()
437 spin_lock_init(&ushc->lock); in ushc_probe()
448 mmc->ops = &ushc_ops; in ushc_probe()
450 mmc->f_min = 400000; in ushc_probe()
451 mmc->f_max = 50000000; in ushc_probe()
452 mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; in ushc_probe()
453 mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_SDIO_IRQ; in ushc_probe()
454 mmc->caps |= (ushc->caps & USHC_GET_CAPS_HIGH_SPD) ? MMC_CAP_SD_HIGHSPEED : 0; in ushc_probe()
456 mmc->max_seg_size = 512*511; in ushc_probe()
457 mmc->max_segs = 1; in ushc_probe()
458 mmc->max_req_size = 512*511; in ushc_probe()
459 mmc->max_blk_size = 512; in ushc_probe()
460 mmc->max_blk_count = 511; in ushc_probe()
462 ushc->int_urb = usb_alloc_urb(0, GFP_KERNEL); in ushc_probe()
463 if (ushc->int_urb == NULL) { in ushc_probe()
464 ret = -ENOMEM; in ushc_probe()
467 ushc->int_data = kzalloc(sizeof(struct ushc_int_data), GFP_KERNEL); in ushc_probe()
468 if (ushc->int_data == NULL) { in ushc_probe()
469 ret = -ENOMEM; in ushc_probe()
472 usb_fill_int_urb(ushc->int_urb, ushc->usb_dev, in ushc_probe()
474 intf->cur_altsetting->endpoint[0].desc.bEndpointAddress), in ushc_probe()
475 ushc->int_data, sizeof(struct ushc_int_data), in ushc_probe()
477 intf->cur_altsetting->endpoint[0].desc.bInterval); in ushc_probe()
479 ushc->cbw_urb = usb_alloc_urb(0, GFP_KERNEL); in ushc_probe()
480 if (ushc->cbw_urb == NULL) { in ushc_probe()
481 ret = -ENOMEM; in ushc_probe()
484 ushc->cbw = kzalloc(sizeof(struct ushc_cbw), GFP_KERNEL); in ushc_probe()
485 if (ushc->cbw == NULL) { in ushc_probe()
486 ret = -ENOMEM; in ushc_probe()
489 ushc->cbw->signature = USHC_CBW_SIGNATURE; in ushc_probe()
491 usb_fill_bulk_urb(ushc->cbw_urb, ushc->usb_dev, usb_sndbulkpipe(usb_dev, 2), in ushc_probe()
492 ushc->cbw, sizeof(struct ushc_cbw), in ushc_probe()
495 ushc->data_urb = usb_alloc_urb(0, GFP_KERNEL); in ushc_probe()
496 if (ushc->data_urb == NULL) { in ushc_probe()
497 ret = -ENOMEM; in ushc_probe()
501 ushc->csw_urb = usb_alloc_urb(0, GFP_KERNEL); in ushc_probe()
502 if (ushc->csw_urb == NULL) { in ushc_probe()
503 ret = -ENOMEM; in ushc_probe()
506 ushc->csw = kzalloc(sizeof(struct ushc_csw), GFP_KERNEL); in ushc_probe()
507 if (ushc->csw == NULL) { in ushc_probe()
508 ret = -ENOMEM; in ushc_probe()
511 usb_fill_bulk_urb(ushc->csw_urb, ushc->usb_dev, usb_rcvbulkpipe(usb_dev, 6), in ushc_probe()
512 ushc->csw, sizeof(struct ushc_csw), in ushc_probe()
515 ret = mmc_add_host(ushc->mmc); in ushc_probe()
519 ret = usb_submit_urb(ushc->int_urb, GFP_KERNEL); in ushc_probe()
521 mmc_remove_host(ushc->mmc); in ushc_probe()
536 spin_lock_irq(&ushc->lock); in ushc_disconnect()
537 set_bit(DISCONNECTED, &ushc->flags); in ushc_disconnect()
538 spin_unlock_irq(&ushc->lock); in ushc_disconnect()
540 usb_kill_urb(ushc->int_urb); in ushc_disconnect()
541 usb_kill_urb(ushc->cbw_urb); in ushc_disconnect()
542 usb_kill_urb(ushc->data_urb); in ushc_disconnect()
543 usb_kill_urb(ushc->csw_urb); in ushc_disconnect()
545 mmc_remove_host(ushc->mmc); in ushc_disconnect()
551 /* CSR USB SD Host Controller */
566 MODULE_DESCRIPTION("USB SD Host Controller driver");