Merge tag 'selinux-pr-20190702' of git://git.kernel.org/pub/scm/linux/kernel/git...
[linux-2.6-microblaze.git] / drivers / mmc / host / sdricoh_cs.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  *  sdricoh_cs.c - driver for Ricoh Secure Digital Card Readers that can be
4  *     found on some Ricoh RL5c476 II cardbus bridge
5  *
6  *  Copyright (C) 2006 - 2008 Sascha Sommer <saschasommer@freenet.de>
7  */
8
9 /*
10 #define DEBUG
11 #define VERBOSE_DEBUG
12 */
13 #include <linux/delay.h>
14 #include <linux/highmem.h>
15 #include <linux/module.h>
16 #include <linux/pci.h>
17 #include <linux/ioport.h>
18 #include <linux/scatterlist.h>
19
20 #include <pcmcia/cistpl.h>
21 #include <pcmcia/ds.h>
22 #include <linux/io.h>
23
24 #include <linux/mmc/host.h>
25
26 #define DRIVER_NAME "sdricoh_cs"
27
28 static unsigned int switchlocked;
29
30 /* i/o region */
31 #define SDRICOH_PCI_REGION 0
32 #define SDRICOH_PCI_REGION_SIZE 0x1000
33
34 /* registers */
35 #define R104_VERSION     0x104
36 #define R200_CMD         0x200
37 #define R204_CMD_ARG     0x204
38 #define R208_DATAIO      0x208
39 #define R20C_RESP        0x20c
40 #define R21C_STATUS      0x21c
41 #define R2E0_INIT        0x2e0
42 #define R2E4_STATUS_RESP 0x2e4
43 #define R2F0_RESET       0x2f0
44 #define R224_MODE        0x224
45 #define R226_BLOCKSIZE   0x226
46 #define R228_POWER       0x228
47 #define R230_DATA        0x230
48
49 /* flags for the R21C_STATUS register */
50 #define STATUS_CMD_FINISHED      0x00000001
51 #define STATUS_TRANSFER_FINISHED 0x00000004
52 #define STATUS_CARD_INSERTED     0x00000020
53 #define STATUS_CARD_LOCKED       0x00000080
54 #define STATUS_CMD_TIMEOUT       0x00400000
55 #define STATUS_READY_TO_READ     0x01000000
56 #define STATUS_READY_TO_WRITE    0x02000000
57 #define STATUS_BUSY              0x40000000
58
59 /* timeouts */
60 #define INIT_TIMEOUT      100
61 #define CMD_TIMEOUT       100000
62 #define TRANSFER_TIMEOUT  100000
63 #define BUSY_TIMEOUT      32767
64
65 /* list of supported pcmcia devices */
66 static const struct pcmcia_device_id pcmcia_ids[] = {
67         /* vendor and device strings followed by their crc32 hashes */
68         PCMCIA_DEVICE_PROD_ID12("RICOH", "Bay1Controller", 0xd9f522ed,
69                                 0xc3901202),
70         PCMCIA_DEVICE_PROD_ID12("RICOH", "Bay Controller", 0xd9f522ed,
71                                 0xace80909),
72         PCMCIA_DEVICE_NULL,
73 };
74
75 MODULE_DEVICE_TABLE(pcmcia, pcmcia_ids);
76
77 /* mmc privdata */
78 struct sdricoh_host {
79         struct device *dev;
80         struct mmc_host *mmc;   /* MMC structure */
81         unsigned char __iomem *iobase;
82         struct pci_dev *pci_dev;
83         int app_cmd;
84 };
85
86 /***************** register i/o helper functions *****************************/
87
88 static inline unsigned int sdricoh_readl(struct sdricoh_host *host,
89                                          unsigned int reg)
90 {
91         unsigned int value = readl(host->iobase + reg);
92         dev_vdbg(host->dev, "rl %x 0x%x\n", reg, value);
93         return value;
94 }
95
96 static inline void sdricoh_writel(struct sdricoh_host *host, unsigned int reg,
97                                   unsigned int value)
98 {
99         writel(value, host->iobase + reg);
100         dev_vdbg(host->dev, "wl %x 0x%x\n", reg, value);
101
102 }
103
104 static inline unsigned int sdricoh_readw(struct sdricoh_host *host,
105                                          unsigned int reg)
106 {
107         unsigned int value = readw(host->iobase + reg);
108         dev_vdbg(host->dev, "rb %x 0x%x\n", reg, value);
109         return value;
110 }
111
112 static inline void sdricoh_writew(struct sdricoh_host *host, unsigned int reg,
113                                          unsigned short value)
114 {
115         writew(value, host->iobase + reg);
116         dev_vdbg(host->dev, "ww %x 0x%x\n", reg, value);
117 }
118
119 static inline unsigned int sdricoh_readb(struct sdricoh_host *host,
120                                          unsigned int reg)
121 {
122         unsigned int value = readb(host->iobase + reg);
123         dev_vdbg(host->dev, "rb %x 0x%x\n", reg, value);
124         return value;
125 }
126
127 static int sdricoh_query_status(struct sdricoh_host *host, unsigned int wanted,
128                                 unsigned int timeout){
129         unsigned int loop;
130         unsigned int status = 0;
131         struct device *dev = host->dev;
132         for (loop = 0; loop < timeout; loop++) {
133                 status = sdricoh_readl(host, R21C_STATUS);
134                 sdricoh_writel(host, R2E4_STATUS_RESP, status);
135                 if (status & wanted)
136                         break;
137         }
138
139         if (loop == timeout) {
140                 dev_err(dev, "query_status: timeout waiting for %x\n", wanted);
141                 return -ETIMEDOUT;
142         }
143
144         /* do not do this check in the loop as some commands fail otherwise */
145         if (status & 0x7F0000) {
146                 dev_err(dev, "waiting for status bit %x failed\n", wanted);
147                 return -EINVAL;
148         }
149         return 0;
150
151 }
152
153 static int sdricoh_mmc_cmd(struct sdricoh_host *host, unsigned char opcode,
154                            unsigned int arg)
155 {
156         unsigned int status;
157         int result = 0;
158         unsigned int loop = 0;
159         /* reset status reg? */
160         sdricoh_writel(host, R21C_STATUS, 0x18);
161         /* fill parameters */
162         sdricoh_writel(host, R204_CMD_ARG, arg);
163         sdricoh_writel(host, R200_CMD, (0x10000 << 8) | opcode);
164         /* wait for command completion */
165         if (opcode) {
166                 for (loop = 0; loop < CMD_TIMEOUT; loop++) {
167                         status = sdricoh_readl(host, R21C_STATUS);
168                         sdricoh_writel(host, R2E4_STATUS_RESP, status);
169                         if (status  & STATUS_CMD_FINISHED)
170                                 break;
171                 }
172                 /* don't check for timeout in the loop it is not always
173                    reset correctly
174                 */
175                 if (loop == CMD_TIMEOUT || status & STATUS_CMD_TIMEOUT)
176                         result = -ETIMEDOUT;
177
178         }
179
180         return result;
181
182 }
183
184 static int sdricoh_reset(struct sdricoh_host *host)
185 {
186         dev_dbg(host->dev, "reset\n");
187         sdricoh_writel(host, R2F0_RESET, 0x10001);
188         sdricoh_writel(host, R2E0_INIT, 0x10000);
189         if (sdricoh_readl(host, R2E0_INIT) != 0x10000)
190                 return -EIO;
191         sdricoh_writel(host, R2E0_INIT, 0x10007);
192
193         sdricoh_writel(host, R224_MODE, 0x2000000);
194         sdricoh_writel(host, R228_POWER, 0xe0);
195
196
197         /* status register ? */
198         sdricoh_writel(host, R21C_STATUS, 0x18);
199
200         return 0;
201 }
202
203 static int sdricoh_blockio(struct sdricoh_host *host, int read,
204                                 u8 *buf, int len)
205 {
206         int size;
207         u32 data = 0;
208         /* wait until the data is available */
209         if (read) {
210                 if (sdricoh_query_status(host, STATUS_READY_TO_READ,
211                                                 TRANSFER_TIMEOUT))
212                         return -ETIMEDOUT;
213                 sdricoh_writel(host, R21C_STATUS, 0x18);
214                 /* read data */
215                 while (len) {
216                         data = sdricoh_readl(host, R230_DATA);
217                         size = min(len, 4);
218                         len -= size;
219                         while (size) {
220                                 *buf = data & 0xFF;
221                                 buf++;
222                                 data >>= 8;
223                                 size--;
224                         }
225                 }
226         } else {
227                 if (sdricoh_query_status(host, STATUS_READY_TO_WRITE,
228                                                 TRANSFER_TIMEOUT))
229                         return -ETIMEDOUT;
230                 sdricoh_writel(host, R21C_STATUS, 0x18);
231                 /* write data */
232                 while (len) {
233                         size = min(len, 4);
234                         len -= size;
235                         while (size) {
236                                 data >>= 8;
237                                 data |= (u32)*buf << 24;
238                                 buf++;
239                                 size--;
240                         }
241                         sdricoh_writel(host, R230_DATA, data);
242                 }
243         }
244
245         return 0;
246 }
247
248 static void sdricoh_request(struct mmc_host *mmc, struct mmc_request *mrq)
249 {
250         struct sdricoh_host *host = mmc_priv(mmc);
251         struct mmc_command *cmd = mrq->cmd;
252         struct mmc_data *data = cmd->data;
253         struct device *dev = host->dev;
254         unsigned char opcode = cmd->opcode;
255         int i;
256
257         dev_dbg(dev, "=============================\n");
258         dev_dbg(dev, "sdricoh_request opcode=%i\n", opcode);
259
260         sdricoh_writel(host, R21C_STATUS, 0x18);
261
262         /* MMC_APP_CMDs need some special handling */
263         if (host->app_cmd) {
264                 opcode |= 64;
265                 host->app_cmd = 0;
266         } else if (opcode == 55)
267                 host->app_cmd = 1;
268
269         /* read/write commands seem to require this */
270         if (data) {
271                 sdricoh_writew(host, R226_BLOCKSIZE, data->blksz);
272                 sdricoh_writel(host, R208_DATAIO, 0);
273         }
274
275         cmd->error = sdricoh_mmc_cmd(host, opcode, cmd->arg);
276
277         /* read response buffer */
278         if (cmd->flags & MMC_RSP_PRESENT) {
279                 if (cmd->flags & MMC_RSP_136) {
280                         /* CRC is stripped so we need to do some shifting. */
281                         for (i = 0; i < 4; i++) {
282                                 cmd->resp[i] =
283                                     sdricoh_readl(host,
284                                                   R20C_RESP + (3 - i) * 4) << 8;
285                                 if (i != 3)
286                                         cmd->resp[i] |=
287                                             sdricoh_readb(host, R20C_RESP +
288                                                           (3 - i) * 4 - 1);
289                         }
290                 } else
291                         cmd->resp[0] = sdricoh_readl(host, R20C_RESP);
292         }
293
294         /* transfer data */
295         if (data && cmd->error == 0) {
296                 dev_dbg(dev, "transfer: blksz %i blocks %i sg_len %i "
297                         "sg length %i\n", data->blksz, data->blocks,
298                         data->sg_len, data->sg->length);
299
300                 /* enter data reading mode */
301                 sdricoh_writel(host, R21C_STATUS, 0x837f031e);
302                 for (i = 0; i < data->blocks; i++) {
303                         size_t len = data->blksz;
304                         u8 *buf;
305                         struct page *page;
306                         int result;
307                         page = sg_page(data->sg);
308
309                         buf = kmap(page) + data->sg->offset + (len * i);
310                         result =
311                                 sdricoh_blockio(host,
312                                         data->flags & MMC_DATA_READ, buf, len);
313                         kunmap(page);
314                         flush_dcache_page(page);
315                         if (result) {
316                                 dev_err(dev, "sdricoh_request: cmd %i "
317                                         "block transfer failed\n", cmd->opcode);
318                                 cmd->error = result;
319                                 break;
320                         } else
321                                 data->bytes_xfered += len;
322                 }
323
324                 sdricoh_writel(host, R208_DATAIO, 1);
325
326                 if (sdricoh_query_status(host, STATUS_TRANSFER_FINISHED,
327                                         TRANSFER_TIMEOUT)) {
328                         dev_err(dev, "sdricoh_request: transfer end error\n");
329                         cmd->error = -EINVAL;
330                 }
331         }
332         /* FIXME check busy flag */
333
334         mmc_request_done(mmc, mrq);
335         dev_dbg(dev, "=============================\n");
336 }
337
338 static void sdricoh_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
339 {
340         struct sdricoh_host *host = mmc_priv(mmc);
341         dev_dbg(host->dev, "set_ios\n");
342
343         if (ios->power_mode == MMC_POWER_ON) {
344                 sdricoh_writel(host, R228_POWER, 0xc0e0);
345
346                 if (ios->bus_width == MMC_BUS_WIDTH_4) {
347                         sdricoh_writel(host, R224_MODE, 0x2000300);
348                         sdricoh_writel(host, R228_POWER, 0x40e0);
349                 } else {
350                         sdricoh_writel(host, R224_MODE, 0x2000340);
351                 }
352
353         } else if (ios->power_mode == MMC_POWER_UP) {
354                 sdricoh_writel(host, R224_MODE, 0x2000320);
355                 sdricoh_writel(host, R228_POWER, 0xe0);
356         }
357 }
358
359 static int sdricoh_get_ro(struct mmc_host *mmc)
360 {
361         struct sdricoh_host *host = mmc_priv(mmc);
362         unsigned int status;
363
364         status = sdricoh_readl(host, R21C_STATUS);
365         sdricoh_writel(host, R2E4_STATUS_RESP, status);
366
367         /* some notebooks seem to have the locked flag switched */
368         if (switchlocked)
369                 return !(status & STATUS_CARD_LOCKED);
370
371         return (status & STATUS_CARD_LOCKED);
372 }
373
374 static const struct mmc_host_ops sdricoh_ops = {
375         .request = sdricoh_request,
376         .set_ios = sdricoh_set_ios,
377         .get_ro = sdricoh_get_ro,
378 };
379
380 /* initialize the control and register it to the mmc framework */
381 static int sdricoh_init_mmc(struct pci_dev *pci_dev,
382                             struct pcmcia_device *pcmcia_dev)
383 {
384         int result;
385         void __iomem *iobase;
386         struct mmc_host *mmc;
387         struct sdricoh_host *host;
388         struct device *dev = &pcmcia_dev->dev;
389         /* map iomem */
390         if (pci_resource_len(pci_dev, SDRICOH_PCI_REGION) !=
391             SDRICOH_PCI_REGION_SIZE) {
392                 dev_dbg(dev, "unexpected pci resource len\n");
393                 return -ENODEV;
394         }
395         iobase =
396             pci_iomap(pci_dev, SDRICOH_PCI_REGION, SDRICOH_PCI_REGION_SIZE);
397         if (!iobase) {
398                 dev_err(dev, "unable to map iobase\n");
399                 return -ENODEV;
400         }
401         /* check version? */
402         if (readl(iobase + R104_VERSION) != 0x4000) {
403                 dev_dbg(dev, "no supported mmc controller found\n");
404                 result = -ENODEV;
405                 goto unmap_io;
406         }
407         /* allocate privdata */
408         mmc = pcmcia_dev->priv =
409             mmc_alloc_host(sizeof(struct sdricoh_host), &pcmcia_dev->dev);
410         if (!mmc) {
411                 dev_err(dev, "mmc_alloc_host failed\n");
412                 result = -ENOMEM;
413                 goto unmap_io;
414         }
415         host = mmc_priv(mmc);
416
417         host->iobase = iobase;
418         host->dev = dev;
419         host->pci_dev = pci_dev;
420
421         mmc->ops = &sdricoh_ops;
422
423         /* FIXME: frequency and voltage handling is done by the controller
424          */
425         mmc->f_min = 450000;
426         mmc->f_max = 24000000;
427         mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
428         mmc->caps |= MMC_CAP_4_BIT_DATA;
429
430         mmc->max_seg_size = 1024 * 512;
431         mmc->max_blk_size = 512;
432
433         /* reset the controller */
434         if (sdricoh_reset(host)) {
435                 dev_dbg(dev, "could not reset\n");
436                 result = -EIO;
437                 goto free_host;
438         }
439
440         result = mmc_add_host(mmc);
441
442         if (!result) {
443                 dev_dbg(dev, "mmc host registered\n");
444                 return 0;
445         }
446 free_host:
447         mmc_free_host(mmc);
448 unmap_io:
449         pci_iounmap(pci_dev, iobase);
450         return result;
451 }
452
453 /* search for supported mmc controllers */
454 static int sdricoh_pcmcia_probe(struct pcmcia_device *pcmcia_dev)
455 {
456         struct pci_dev *pci_dev = NULL;
457
458         dev_info(&pcmcia_dev->dev, "Searching MMC controller for pcmcia device"
459                 " %s %s ...\n", pcmcia_dev->prod_id[0], pcmcia_dev->prod_id[1]);
460
461         /* search pci cardbus bridge that contains the mmc controller */
462         /* the io region is already claimed by yenta_socket... */
463         while ((pci_dev =
464                 pci_get_device(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_RL5C476,
465                                pci_dev))) {
466                 /* try to init the device */
467                 if (!sdricoh_init_mmc(pci_dev, pcmcia_dev)) {
468                         dev_info(&pcmcia_dev->dev, "MMC controller found\n");
469                         return 0;
470                 }
471
472         }
473         dev_err(&pcmcia_dev->dev, "No MMC controller was found.\n");
474         return -ENODEV;
475 }
476
477 static void sdricoh_pcmcia_detach(struct pcmcia_device *link)
478 {
479         struct mmc_host *mmc = link->priv;
480
481         dev_dbg(&link->dev, "detach\n");
482
483         /* remove mmc host */
484         if (mmc) {
485                 struct sdricoh_host *host = mmc_priv(mmc);
486                 mmc_remove_host(mmc);
487                 pci_iounmap(host->pci_dev, host->iobase);
488                 pci_dev_put(host->pci_dev);
489                 mmc_free_host(mmc);
490         }
491         pcmcia_disable_device(link);
492
493 }
494
495 #ifdef CONFIG_PM
496 static int sdricoh_pcmcia_suspend(struct pcmcia_device *link)
497 {
498         dev_dbg(&link->dev, "suspend\n");
499         return 0;
500 }
501
502 static int sdricoh_pcmcia_resume(struct pcmcia_device *link)
503 {
504         struct mmc_host *mmc = link->priv;
505         dev_dbg(&link->dev, "resume\n");
506         sdricoh_reset(mmc_priv(mmc));
507         return 0;
508 }
509 #else
510 #define sdricoh_pcmcia_suspend NULL
511 #define sdricoh_pcmcia_resume NULL
512 #endif
513
514 static struct pcmcia_driver sdricoh_driver = {
515         .name = DRIVER_NAME,
516         .probe = sdricoh_pcmcia_probe,
517         .remove = sdricoh_pcmcia_detach,
518         .id_table = pcmcia_ids,
519         .suspend = sdricoh_pcmcia_suspend,
520         .resume = sdricoh_pcmcia_resume,
521 };
522 module_pcmcia_driver(sdricoh_driver);
523
524 module_param(switchlocked, uint, 0444);
525
526 MODULE_AUTHOR("Sascha Sommer <saschasommer@freenet.de>");
527 MODULE_DESCRIPTION("Ricoh PCMCIA Secure Digital Interface driver");
528 MODULE_LICENSE("GPL");
529
530 MODULE_PARM_DESC(switchlocked, "Switch the cards locked status."
531                 "Use this when unlocked cards are shown readonly (default 0)");