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

1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * sdricoh_cs.c - driver for Ricoh Secure Digital Card Readers that can be
6 * Copyright (C) 2006 - 2008 Sascha Sommer <saschasommer@freenet.de>
25 #include <linux/mmc/host.h>
26 #include <linux/mmc/mmc.h>
70 PCMCIA_DEVICE_PROD_ID12("RICOH", "Bay Controller", 0xd9f522ed,
77 /* mmc privdata */
80 struct mmc_host *mmc; /* MMC structure */ member
91 unsigned int value = readl(host->iobase + reg); in sdricoh_readl()
92 dev_vdbg(host->dev, "rl %x 0x%x\n", reg, value); in sdricoh_readl()
99 writel(value, host->iobase + reg); in sdricoh_writel()
100 dev_vdbg(host->dev, "wl %x 0x%x\n", reg, value); in sdricoh_writel()
107 writew(value, host->iobase + reg); in sdricoh_writew()
108 dev_vdbg(host->dev, "ww %x 0x%x\n", reg, value); in sdricoh_writew()
114 unsigned int value = readb(host->iobase + reg); in sdricoh_readb()
115 dev_vdbg(host->dev, "rb %x 0x%x\n", reg, value); in sdricoh_readb()
130 struct device *dev = host->dev; in sdricoh_query_status()
138 return -ETIMEDOUT; in sdricoh_query_status()
144 return -EINVAL; in sdricoh_query_status()
154 unsigned char opcode = cmd->opcode; in sdricoh_mmc_cmd()
160 if (host->app_cmd) { in sdricoh_mmc_cmd()
162 host->app_cmd = 0; in sdricoh_mmc_cmd()
164 host->app_cmd = 1; in sdricoh_mmc_cmd()
167 sdricoh_writel(host, R204_CMD_ARG, cmd->arg); in sdricoh_mmc_cmd()
174 timeout_us = cmd->busy_timeout ? cmd->busy_timeout * 1000 : in sdricoh_mmc_cmd()
187 return -ETIMEDOUT; in sdricoh_mmc_cmd()
194 dev_dbg(host->dev, "reset\n"); in sdricoh_reset()
198 return -EIO; in sdricoh_reset()
219 return -ETIMEDOUT; in sdricoh_blockio()
225 len -= size; in sdricoh_blockio()
230 size--; in sdricoh_blockio()
235 return -ETIMEDOUT; in sdricoh_blockio()
240 len -= size; in sdricoh_blockio()
245 size--; in sdricoh_blockio()
254 static void sdricoh_request(struct mmc_host *mmc, struct mmc_request *mrq) in sdricoh_request() argument
256 struct sdricoh_host *host = mmc_priv(mmc); in sdricoh_request()
257 struct mmc_command *cmd = mrq->cmd; in sdricoh_request()
258 struct mmc_data *data = cmd->data; in sdricoh_request()
259 struct device *dev = host->dev; in sdricoh_request()
263 dev_dbg(dev, "sdricoh_request opcode=%i\n", cmd->opcode); in sdricoh_request()
269 sdricoh_writew(host, R226_BLOCKSIZE, data->blksz); in sdricoh_request()
273 cmd->error = sdricoh_mmc_cmd(host, cmd); in sdricoh_request()
276 if (cmd->flags & MMC_RSP_PRESENT) { in sdricoh_request()
277 if (cmd->flags & MMC_RSP_136) { in sdricoh_request()
280 cmd->resp[i] = in sdricoh_request()
282 R20C_RESP + (3 - i) * 4) << 8; in sdricoh_request()
284 cmd->resp[i] |= in sdricoh_request()
286 (3 - i) * 4 - 1); in sdricoh_request()
289 cmd->resp[0] = sdricoh_readl(host, R20C_RESP); in sdricoh_request()
293 if (data && cmd->error == 0) { in sdricoh_request()
295 "sg length %i\n", data->blksz, data->blocks, in sdricoh_request()
296 data->sg_len, data->sg->length); in sdricoh_request()
300 for (i = 0; i < data->blocks; i++) { in sdricoh_request()
301 size_t len = data->blksz; in sdricoh_request()
305 page = sg_page(data->sg); in sdricoh_request()
307 buf = kmap(page) + data->sg->offset + (len * i); in sdricoh_request()
310 data->flags & MMC_DATA_READ, buf, len); in sdricoh_request()
315 "block transfer failed\n", cmd->opcode); in sdricoh_request()
316 cmd->error = result; in sdricoh_request()
319 data->bytes_xfered += len; in sdricoh_request()
326 cmd->error = -EINVAL; in sdricoh_request()
331 mmc_request_done(mmc, mrq); in sdricoh_request()
335 static void sdricoh_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) in sdricoh_set_ios() argument
337 struct sdricoh_host *host = mmc_priv(mmc); in sdricoh_set_ios()
338 dev_dbg(host->dev, "set_ios\n"); in sdricoh_set_ios()
340 if (ios->power_mode == MMC_POWER_ON) { in sdricoh_set_ios()
343 if (ios->bus_width == MMC_BUS_WIDTH_4) { in sdricoh_set_ios()
350 } else if (ios->power_mode == MMC_POWER_UP) { in sdricoh_set_ios()
356 static int sdricoh_get_ro(struct mmc_host *mmc) in sdricoh_get_ro() argument
358 struct sdricoh_host *host = mmc_priv(mmc); in sdricoh_get_ro()
377 /* initialize the control and register it to the mmc framework */
383 struct mmc_host *mmc; in sdricoh_init_mmc() local
385 struct device *dev = &pcmcia_dev->dev; in sdricoh_init_mmc()
390 return -ENODEV; in sdricoh_init_mmc()
396 return -ENODEV; in sdricoh_init_mmc()
400 dev_dbg(dev, "no supported mmc controller found\n"); in sdricoh_init_mmc()
401 result = -ENODEV; in sdricoh_init_mmc()
405 mmc = pcmcia_dev->priv = in sdricoh_init_mmc()
406 mmc_alloc_host(sizeof(struct sdricoh_host), &pcmcia_dev->dev); in sdricoh_init_mmc()
407 if (!mmc) { in sdricoh_init_mmc()
409 result = -ENOMEM; in sdricoh_init_mmc()
412 host = mmc_priv(mmc); in sdricoh_init_mmc()
414 host->iobase = iobase; in sdricoh_init_mmc()
415 host->dev = dev; in sdricoh_init_mmc()
416 host->pci_dev = pci_dev; in sdricoh_init_mmc()
418 mmc->ops = &sdricoh_ops; in sdricoh_init_mmc()
420 /* FIXME: frequency and voltage handling is done by the controller in sdricoh_init_mmc()
422 mmc->f_min = 450000; in sdricoh_init_mmc()
423 mmc->f_max = 24000000; in sdricoh_init_mmc()
424 mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; in sdricoh_init_mmc()
425 mmc->caps |= MMC_CAP_4_BIT_DATA; in sdricoh_init_mmc()
427 mmc->max_seg_size = 1024 * 512; in sdricoh_init_mmc()
428 mmc->max_blk_size = 512; in sdricoh_init_mmc()
430 /* reset the controller */ in sdricoh_init_mmc()
433 result = -EIO; in sdricoh_init_mmc()
437 result = mmc_add_host(mmc); in sdricoh_init_mmc()
440 dev_dbg(dev, "mmc host registered\n"); in sdricoh_init_mmc()
444 mmc_free_host(mmc); in sdricoh_init_mmc()
450 /* search for supported mmc controllers */
455 dev_info(&pcmcia_dev->dev, "Searching MMC controller for pcmcia device" in sdricoh_pcmcia_probe()
456 " %s %s ...\n", pcmcia_dev->prod_id[0], pcmcia_dev->prod_id[1]); in sdricoh_pcmcia_probe()
458 /* search pci cardbus bridge that contains the mmc controller */ in sdricoh_pcmcia_probe()
465 dev_info(&pcmcia_dev->dev, "MMC controller found\n"); in sdricoh_pcmcia_probe()
470 dev_err(&pcmcia_dev->dev, "No MMC controller was found.\n"); in sdricoh_pcmcia_probe()
471 return -ENODEV; in sdricoh_pcmcia_probe()
476 struct mmc_host *mmc = link->priv; in sdricoh_pcmcia_detach() local
478 dev_dbg(&link->dev, "detach\n"); in sdricoh_pcmcia_detach()
480 /* remove mmc host */ in sdricoh_pcmcia_detach()
481 if (mmc) { in sdricoh_pcmcia_detach()
482 struct sdricoh_host *host = mmc_priv(mmc); in sdricoh_pcmcia_detach()
483 mmc_remove_host(mmc); in sdricoh_pcmcia_detach()
484 pci_iounmap(host->pci_dev, host->iobase); in sdricoh_pcmcia_detach()
485 pci_dev_put(host->pci_dev); in sdricoh_pcmcia_detach()
486 mmc_free_host(mmc); in sdricoh_pcmcia_detach()
495 dev_dbg(&link->dev, "suspend\n"); in sdricoh_pcmcia_suspend()
501 struct mmc_host *mmc = link->priv; in sdricoh_pcmcia_resume() local
502 dev_dbg(&link->dev, "resume\n"); in sdricoh_pcmcia_resume()
503 sdricoh_reset(mmc_priv(mmc)); in sdricoh_pcmcia_resume()