blob: fcfa24b7b1db31a0dfcf2f20a88baf280d786630 [file] [log] [blame]
Alex Dubov60fdd932008-03-10 11:43:43 -07001/*
2 * jmb38x_ms.c - JMicron jmb38x MemoryStick card reader
3 *
4 * Copyright (C) 2008 Alex Dubov <oakad@yahoo.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 */
11
12#include <linux/spinlock.h>
13#include <linux/interrupt.h>
14#include <linux/pci.h>
Andrew Mortond3597ea2008-03-19 17:01:03 -070015#include <linux/dma-mapping.h>
Alex Dubov60fdd932008-03-10 11:43:43 -070016#include <linux/delay.h>
17#include <linux/highmem.h>
18#include <linux/memstick.h>
19
20#define DRIVER_NAME "jmb38x_ms"
21
22static int no_dma;
23module_param(no_dma, bool, 0644);
24
25enum {
26 DMA_ADDRESS = 0x00,
27 BLOCK = 0x04,
28 DMA_CONTROL = 0x08,
29 TPC_P0 = 0x0c,
30 TPC_P1 = 0x10,
31 TPC = 0x14,
32 HOST_CONTROL = 0x18,
33 DATA = 0x1c,
34 STATUS = 0x20,
35 INT_STATUS = 0x24,
36 INT_STATUS_ENABLE = 0x28,
37 INT_SIGNAL_ENABLE = 0x2c,
38 TIMER = 0x30,
39 TIMER_CONTROL = 0x34,
40 PAD_OUTPUT_ENABLE = 0x38,
41 PAD_PU_PD = 0x3c,
42 CLOCK_DELAY = 0x40,
43 ADMA_ADDRESS = 0x44,
44 CLOCK_CONTROL = 0x48,
45 LED_CONTROL = 0x4c,
46 VERSION = 0x50
47};
48
49struct jmb38x_ms_host {
50 struct jmb38x_ms *chip;
51 void __iomem *addr;
52 spinlock_t lock;
53 int id;
54 char host_id[DEVICE_ID_SIZE];
55 int irq;
56 unsigned int block_pos;
57 unsigned long timeout_jiffies;
58 struct timer_list timer;
59 struct memstick_request *req;
60 unsigned char eject:1,
61 use_dma:1;
62 unsigned char cmd_flags;
63 unsigned char io_pos;
64 unsigned int io_word[2];
65};
66
67struct jmb38x_ms {
68 struct pci_dev *pdev;
69 int host_cnt;
70 struct memstick_host *hosts[];
71};
72
73#define BLOCK_COUNT_MASK 0xffff0000
74#define BLOCK_SIZE_MASK 0x00000fff
75
76#define DMA_CONTROL_ENABLE 0x00000001
77
78#define TPC_DATA_SEL 0x00008000
79#define TPC_DIR 0x00004000
80#define TPC_WAIT_INT 0x00002000
81#define TPC_GET_INT 0x00000800
82#define TPC_CODE_SZ_MASK 0x00000700
83#define TPC_DATA_SZ_MASK 0x00000007
84
85#define HOST_CONTROL_RESET_REQ 0x00008000
86#define HOST_CONTROL_REI 0x00004000
87#define HOST_CONTROL_LED 0x00000400
88#define HOST_CONTROL_FAST_CLK 0x00000200
89#define HOST_CONTROL_RESET 0x00000100
90#define HOST_CONTROL_POWER_EN 0x00000080
91#define HOST_CONTROL_CLOCK_EN 0x00000040
92#define HOST_CONTROL_IF_SHIFT 4
93
94#define HOST_CONTROL_IF_SERIAL 0x0
95#define HOST_CONTROL_IF_PAR4 0x1
96#define HOST_CONTROL_IF_PAR8 0x3
97
98#define STATUS_HAS_MEDIA 0x00000400
99#define STATUS_FIFO_EMPTY 0x00000200
100#define STATUS_FIFO_FULL 0x00000100
101
102#define INT_STATUS_TPC_ERR 0x00080000
103#define INT_STATUS_CRC_ERR 0x00040000
104#define INT_STATUS_TIMER_TO 0x00020000
105#define INT_STATUS_HSK_TO 0x00010000
106#define INT_STATUS_ANY_ERR 0x00008000
107#define INT_STATUS_FIFO_WRDY 0x00000080
108#define INT_STATUS_FIFO_RRDY 0x00000040
109#define INT_STATUS_MEDIA_OUT 0x00000010
110#define INT_STATUS_MEDIA_IN 0x00000008
111#define INT_STATUS_DMA_BOUNDARY 0x00000004
112#define INT_STATUS_EOTRAN 0x00000002
113#define INT_STATUS_EOTPC 0x00000001
114
115#define INT_STATUS_ALL 0x000f801f
116
117#define PAD_OUTPUT_ENABLE_MS 0x0F3F
118
119#define PAD_PU_PD_OFF 0x7FFF0000
120#define PAD_PU_PD_ON_MS_SOCK0 0x5f8f0000
121#define PAD_PU_PD_ON_MS_SOCK1 0x0f0f0000
122
123enum {
124 CMD_READY = 0x01,
125 FIFO_READY = 0x02,
126 REG_DATA = 0x04,
127 AUTO_GET_INT = 0x08
128};
129
130static unsigned int jmb38x_ms_read_data(struct jmb38x_ms_host *host,
131 unsigned char *buf, unsigned int length)
132{
133 unsigned int off = 0;
134
135 while (host->io_pos && length) {
136 buf[off++] = host->io_word[0] & 0xff;
137 host->io_word[0] >>= 8;
138 length--;
139 host->io_pos--;
140 }
141
142 if (!length)
143 return off;
144
145 while (!(STATUS_FIFO_EMPTY & readl(host->addr + STATUS))) {
146 if (length < 4)
147 break;
148 *(unsigned int *)(buf + off) = __raw_readl(host->addr + DATA);
149 length -= 4;
150 off += 4;
151 }
152
153 if (length
154 && !(STATUS_FIFO_EMPTY & readl(host->addr + STATUS))) {
155 host->io_word[0] = readl(host->addr + DATA);
156 for (host->io_pos = 4; host->io_pos; --host->io_pos) {
157 buf[off++] = host->io_word[0] & 0xff;
158 host->io_word[0] >>= 8;
159 length--;
160 if (!length)
161 break;
162 }
163 }
164
165 return off;
166}
167
168static unsigned int jmb38x_ms_read_reg_data(struct jmb38x_ms_host *host,
169 unsigned char *buf,
170 unsigned int length)
171{
172 unsigned int off = 0;
173
174 while (host->io_pos > 4 && length) {
175 buf[off++] = host->io_word[0] & 0xff;
176 host->io_word[0] >>= 8;
177 length--;
178 host->io_pos--;
179 }
180
181 if (!length)
182 return off;
183
184 while (host->io_pos && length) {
185 buf[off++] = host->io_word[1] & 0xff;
186 host->io_word[1] >>= 8;
187 length--;
188 host->io_pos--;
189 }
190
191 return off;
192}
193
194static unsigned int jmb38x_ms_write_data(struct jmb38x_ms_host *host,
195 unsigned char *buf,
196 unsigned int length)
197{
198 unsigned int off = 0;
199
200 if (host->io_pos) {
201 while (host->io_pos < 4 && length) {
202 host->io_word[0] |= buf[off++] << (host->io_pos * 8);
203 host->io_pos++;
204 length--;
205 }
206 }
207
208 if (host->io_pos == 4
209 && !(STATUS_FIFO_FULL & readl(host->addr + STATUS))) {
210 writel(host->io_word[0], host->addr + DATA);
211 host->io_pos = 0;
212 host->io_word[0] = 0;
213 } else if (host->io_pos) {
214 return off;
215 }
216
217 if (!length)
218 return off;
219
220 while (!(STATUS_FIFO_FULL & readl(host->addr + STATUS))) {
221 if (length < 4)
222 break;
223
224 __raw_writel(*(unsigned int *)(buf + off),
225 host->addr + DATA);
226 length -= 4;
227 off += 4;
228 }
229
230 switch (length) {
231 case 3:
232 host->io_word[0] |= buf[off + 2] << 16;
233 host->io_pos++;
234 case 2:
235 host->io_word[0] |= buf[off + 1] << 8;
236 host->io_pos++;
237 case 1:
238 host->io_word[0] |= buf[off];
239 host->io_pos++;
240 }
241
242 off += host->io_pos;
243
244 return off;
245}
246
247static unsigned int jmb38x_ms_write_reg_data(struct jmb38x_ms_host *host,
248 unsigned char *buf,
249 unsigned int length)
250{
251 unsigned int off = 0;
252
253 while (host->io_pos < 4 && length) {
254 host->io_word[0] &= ~(0xff << (host->io_pos * 8));
255 host->io_word[0] |= buf[off++] << (host->io_pos * 8);
256 host->io_pos++;
257 length--;
258 }
259
260 if (!length)
261 return off;
262
263 while (host->io_pos < 8 && length) {
264 host->io_word[1] &= ~(0xff << (host->io_pos * 8));
265 host->io_word[1] |= buf[off++] << (host->io_pos * 8);
266 host->io_pos++;
267 length--;
268 }
269
270 return off;
271}
272
273static int jmb38x_ms_transfer_data(struct jmb38x_ms_host *host)
274{
275 unsigned int length;
276 unsigned int off;
277 unsigned int t_size, p_off, p_cnt;
278 unsigned char *buf;
279 struct page *pg;
280 unsigned long flags = 0;
281
282 if (host->req->long_data) {
283 length = host->req->sg.length - host->block_pos;
284 off = host->req->sg.offset + host->block_pos;
285 } else {
286 length = host->req->data_len - host->block_pos;
287 off = 0;
288 }
289
290 while (length) {
291 if (host->req->long_data) {
292 pg = nth_page(sg_page(&host->req->sg),
293 off >> PAGE_SHIFT);
294 p_off = offset_in_page(off);
295 p_cnt = PAGE_SIZE - p_off;
296 p_cnt = min(p_cnt, length);
297
298 local_irq_save(flags);
299 buf = kmap_atomic(pg, KM_BIO_SRC_IRQ) + p_off;
300 } else {
301 buf = host->req->data + host->block_pos;
302 p_cnt = host->req->data_len - host->block_pos;
303 }
304
305 if (host->req->data_dir == WRITE)
306 t_size = !(host->cmd_flags & REG_DATA)
307 ? jmb38x_ms_write_data(host, buf, p_cnt)
308 : jmb38x_ms_write_reg_data(host, buf, p_cnt);
309 else
310 t_size = !(host->cmd_flags & REG_DATA)
311 ? jmb38x_ms_read_data(host, buf, p_cnt)
312 : jmb38x_ms_read_reg_data(host, buf, p_cnt);
313
314 if (host->req->long_data) {
315 kunmap_atomic(buf - p_off, KM_BIO_SRC_IRQ);
316 local_irq_restore(flags);
317 }
318
319 if (!t_size)
320 break;
321 host->block_pos += t_size;
322 length -= t_size;
323 off += t_size;
324 }
325
326 if (!length && host->req->data_dir == WRITE) {
327 if (host->cmd_flags & REG_DATA) {
328 writel(host->io_word[0], host->addr + TPC_P0);
329 writel(host->io_word[1], host->addr + TPC_P1);
330 } else if (host->io_pos) {
331 writel(host->io_word[0], host->addr + DATA);
332 }
333 }
334
335 return length;
336}
337
338static int jmb38x_ms_issue_cmd(struct memstick_host *msh)
339{
340 struct jmb38x_ms_host *host = memstick_priv(msh);
341 unsigned char *data;
342 unsigned int data_len, cmd, t_val;
343
344 if (!(STATUS_HAS_MEDIA & readl(host->addr + STATUS))) {
345 dev_dbg(msh->cdev.dev, "no media status\n");
346 host->req->error = -ETIME;
347 return host->req->error;
348 }
349
350 dev_dbg(msh->cdev.dev, "control %08x\n",
351 readl(host->addr + HOST_CONTROL));
352 dev_dbg(msh->cdev.dev, "status %08x\n", readl(host->addr + INT_STATUS));
353 dev_dbg(msh->cdev.dev, "hstatus %08x\n", readl(host->addr + STATUS));
354
355 host->cmd_flags = 0;
356 host->block_pos = 0;
357 host->io_pos = 0;
358 host->io_word[0] = 0;
359 host->io_word[1] = 0;
360
361 cmd = host->req->tpc << 16;
362 cmd |= TPC_DATA_SEL;
363
364 if (host->req->data_dir == READ)
365 cmd |= TPC_DIR;
366 if (host->req->need_card_int)
367 cmd |= TPC_WAIT_INT;
368 if (host->req->get_int_reg)
369 cmd |= TPC_GET_INT;
370
371 data = host->req->data;
372
373 host->use_dma = !no_dma;
374
375 if (host->req->long_data) {
376 data_len = host->req->sg.length;
377 } else {
378 data_len = host->req->data_len;
379 host->use_dma = 0;
380 }
381
382 if (data_len <= 8) {
383 cmd &= ~(TPC_DATA_SEL | 0xf);
384 host->cmd_flags |= REG_DATA;
385 cmd |= data_len & 0xf;
386 host->use_dma = 0;
387 }
388
389 if (host->use_dma) {
390 if (1 != pci_map_sg(host->chip->pdev, &host->req->sg, 1,
391 host->req->data_dir == READ
392 ? PCI_DMA_FROMDEVICE
393 : PCI_DMA_TODEVICE)) {
394 host->req->error = -ENOMEM;
395 return host->req->error;
396 }
397 data_len = sg_dma_len(&host->req->sg);
398 writel(sg_dma_address(&host->req->sg),
399 host->addr + DMA_ADDRESS);
400 writel(((1 << 16) & BLOCK_COUNT_MASK)
401 | (data_len & BLOCK_SIZE_MASK),
402 host->addr + BLOCK);
403 writel(DMA_CONTROL_ENABLE, host->addr + DMA_CONTROL);
404 } else if (!(host->cmd_flags & REG_DATA)) {
405 writel(((1 << 16) & BLOCK_COUNT_MASK)
406 | (data_len & BLOCK_SIZE_MASK),
407 host->addr + BLOCK);
408 t_val = readl(host->addr + INT_STATUS_ENABLE);
409 t_val |= host->req->data_dir == READ
410 ? INT_STATUS_FIFO_RRDY
411 : INT_STATUS_FIFO_WRDY;
412
413 writel(t_val, host->addr + INT_STATUS_ENABLE);
414 writel(t_val, host->addr + INT_SIGNAL_ENABLE);
415 } else {
416 cmd &= ~(TPC_DATA_SEL | 0xf);
417 host->cmd_flags |= REG_DATA;
418 cmd |= data_len & 0xf;
419
420 if (host->req->data_dir == WRITE) {
421 jmb38x_ms_transfer_data(host);
422 writel(host->io_word[0], host->addr + TPC_P0);
423 writel(host->io_word[1], host->addr + TPC_P1);
424 }
425 }
426
427 mod_timer(&host->timer, jiffies + host->timeout_jiffies);
428 writel(HOST_CONTROL_LED | readl(host->addr + HOST_CONTROL),
429 host->addr + HOST_CONTROL);
430 host->req->error = 0;
431
432 writel(cmd, host->addr + TPC);
433 dev_dbg(msh->cdev.dev, "executing TPC %08x, len %x\n", cmd, data_len);
434
435 return 0;
436}
437
438static void jmb38x_ms_complete_cmd(struct memstick_host *msh, int last)
439{
440 struct jmb38x_ms_host *host = memstick_priv(msh);
441 unsigned int t_val = 0;
442 int rc;
443
444 del_timer(&host->timer);
445
446 dev_dbg(msh->cdev.dev, "c control %08x\n",
447 readl(host->addr + HOST_CONTROL));
448 dev_dbg(msh->cdev.dev, "c status %08x\n",
449 readl(host->addr + INT_STATUS));
450 dev_dbg(msh->cdev.dev, "c hstatus %08x\n", readl(host->addr + STATUS));
451
452 if (host->req->get_int_reg) {
453 t_val = readl(host->addr + TPC_P0);
454 host->req->int_reg = (t_val & 0xff);
455 }
456
457 if (host->use_dma) {
458 writel(0, host->addr + DMA_CONTROL);
459 pci_unmap_sg(host->chip->pdev, &host->req->sg, 1,
460 host->req->data_dir == READ
461 ? PCI_DMA_FROMDEVICE : PCI_DMA_TODEVICE);
462 } else {
463 t_val = readl(host->addr + INT_STATUS_ENABLE);
464 if (host->req->data_dir == READ)
465 t_val &= ~INT_STATUS_FIFO_RRDY;
466 else
467 t_val &= ~INT_STATUS_FIFO_WRDY;
468
469 writel(t_val, host->addr + INT_STATUS_ENABLE);
470 writel(t_val, host->addr + INT_SIGNAL_ENABLE);
471 }
472
473 writel((~HOST_CONTROL_LED) & readl(host->addr + HOST_CONTROL),
474 host->addr + HOST_CONTROL);
475
476 if (!last) {
477 do {
478 rc = memstick_next_req(msh, &host->req);
479 } while (!rc && jmb38x_ms_issue_cmd(msh));
480 } else {
481 do {
482 rc = memstick_next_req(msh, &host->req);
483 if (!rc)
484 host->req->error = -ETIME;
485 } while (!rc);
486 }
487}
488
489static irqreturn_t jmb38x_ms_isr(int irq, void *dev_id)
490{
491 struct memstick_host *msh = dev_id;
492 struct jmb38x_ms_host *host = memstick_priv(msh);
493 unsigned int irq_status;
494
495 spin_lock(&host->lock);
496 irq_status = readl(host->addr + INT_STATUS);
497 dev_dbg(&host->chip->pdev->dev, "irq_status = %08x\n", irq_status);
498 if (irq_status == 0 || irq_status == (~0)) {
499 spin_unlock(&host->lock);
500 return IRQ_NONE;
501 }
502
503 if (host->req) {
504 if (irq_status & INT_STATUS_ANY_ERR) {
505 if (irq_status & INT_STATUS_CRC_ERR)
506 host->req->error = -EILSEQ;
507 else
508 host->req->error = -ETIME;
509 } else {
510 if (host->use_dma) {
511 if (irq_status & INT_STATUS_EOTRAN)
512 host->cmd_flags |= FIFO_READY;
513 } else {
514 if (irq_status & (INT_STATUS_FIFO_RRDY
515 | INT_STATUS_FIFO_WRDY))
516 jmb38x_ms_transfer_data(host);
517
518 if (irq_status & INT_STATUS_EOTRAN) {
519 jmb38x_ms_transfer_data(host);
520 host->cmd_flags |= FIFO_READY;
521 }
522 }
523
524 if (irq_status & INT_STATUS_EOTPC) {
525 host->cmd_flags |= CMD_READY;
526 if (host->cmd_flags & REG_DATA) {
527 if (host->req->data_dir == READ) {
528 host->io_word[0]
529 = readl(host->addr
530 + TPC_P0);
531 host->io_word[1]
532 = readl(host->addr
533 + TPC_P1);
534 host->io_pos = 8;
535
536 jmb38x_ms_transfer_data(host);
537 }
538 host->cmd_flags |= FIFO_READY;
539 }
540 }
541 }
542 }
543
544 if (irq_status & (INT_STATUS_MEDIA_IN | INT_STATUS_MEDIA_OUT)) {
545 dev_dbg(&host->chip->pdev->dev, "media changed\n");
546 memstick_detect_change(msh);
547 }
548
549 writel(irq_status, host->addr + INT_STATUS);
550
551 if (host->req
552 && (((host->cmd_flags & CMD_READY)
553 && (host->cmd_flags & FIFO_READY))
554 || host->req->error))
555 jmb38x_ms_complete_cmd(msh, 0);
556
557 spin_unlock(&host->lock);
558 return IRQ_HANDLED;
559}
560
561static void jmb38x_ms_abort(unsigned long data)
562{
563 struct memstick_host *msh = (struct memstick_host *)data;
564 struct jmb38x_ms_host *host = memstick_priv(msh);
565 unsigned long flags;
566
567 dev_dbg(&host->chip->pdev->dev, "abort\n");
568 spin_lock_irqsave(&host->lock, flags);
569 if (host->req) {
570 host->req->error = -ETIME;
571 jmb38x_ms_complete_cmd(msh, 0);
572 }
573 spin_unlock_irqrestore(&host->lock, flags);
574}
575
576static void jmb38x_ms_request(struct memstick_host *msh)
577{
578 struct jmb38x_ms_host *host = memstick_priv(msh);
579 unsigned long flags;
580 int rc;
581
582 spin_lock_irqsave(&host->lock, flags);
583 if (host->req) {
584 spin_unlock_irqrestore(&host->lock, flags);
585 BUG();
586 return;
587 }
588
589 do {
590 rc = memstick_next_req(msh, &host->req);
591 } while (!rc && jmb38x_ms_issue_cmd(msh));
592 spin_unlock_irqrestore(&host->lock, flags);
593}
594
595static void jmb38x_ms_reset(struct jmb38x_ms_host *host)
596{
597 unsigned int host_ctl = readl(host->addr + HOST_CONTROL);
598
599 writel(host_ctl | HOST_CONTROL_RESET_REQ | HOST_CONTROL_RESET,
600 host->addr + HOST_CONTROL);
601
602 while (HOST_CONTROL_RESET_REQ
603 & (host_ctl = readl(host->addr + HOST_CONTROL))) {
604 ndelay(100);
605 dev_dbg(&host->chip->pdev->dev, "reset\n");
606 }
607
608 writel(INT_STATUS_ALL, host->addr + INT_STATUS_ENABLE);
609 writel(INT_STATUS_ALL, host->addr + INT_SIGNAL_ENABLE);
610
611 dev_dbg(&host->chip->pdev->dev, "reset\n");
612}
613
614static void jmb38x_ms_set_param(struct memstick_host *msh,
615 enum memstick_param param,
616 int value)
617{
618 struct jmb38x_ms_host *host = memstick_priv(msh);
619 unsigned int host_ctl;
620 unsigned long flags;
621
622 spin_lock_irqsave(&host->lock, flags);
623
624 switch (param) {
625 case MEMSTICK_POWER:
626 if (value == MEMSTICK_POWER_ON) {
627 jmb38x_ms_reset(host);
628
629 writel(host->id ? PAD_PU_PD_ON_MS_SOCK1
630 : PAD_PU_PD_ON_MS_SOCK0,
631 host->addr + PAD_PU_PD);
632
633 writel(PAD_OUTPUT_ENABLE_MS,
634 host->addr + PAD_OUTPUT_ENABLE);
635
636 host_ctl = readl(host->addr + HOST_CONTROL);
637 host_ctl |= 7;
638 writel(host_ctl | (HOST_CONTROL_POWER_EN
639 | HOST_CONTROL_CLOCK_EN),
640 host->addr + HOST_CONTROL);
641
642 dev_dbg(&host->chip->pdev->dev, "power on\n");
643 } else if (value == MEMSTICK_POWER_OFF) {
644 writel(readl(host->addr + HOST_CONTROL)
645 & ~(HOST_CONTROL_POWER_EN
646 | HOST_CONTROL_CLOCK_EN),
647 host->addr + HOST_CONTROL);
648 writel(0, host->addr + PAD_OUTPUT_ENABLE);
649 writel(PAD_PU_PD_OFF, host->addr + PAD_PU_PD);
650 dev_dbg(&host->chip->pdev->dev, "power off\n");
651 }
652 break;
653 case MEMSTICK_INTERFACE:
654 /* jmb38x_ms_reset(host); */
655
656 host_ctl = readl(host->addr + HOST_CONTROL);
657 host_ctl &= ~(3 << HOST_CONTROL_IF_SHIFT);
658 /* host_ctl |= 7; */
659
660 if (value == MEMSTICK_SERIAL) {
661 host_ctl &= ~HOST_CONTROL_FAST_CLK;
662 host_ctl |= HOST_CONTROL_IF_SERIAL
663 << HOST_CONTROL_IF_SHIFT;
664 host_ctl |= HOST_CONTROL_REI;
665 writel(0, host->addr + CLOCK_DELAY);
666 } else if (value == MEMSTICK_PAR4) {
667 host_ctl |= HOST_CONTROL_FAST_CLK;
668 host_ctl |= HOST_CONTROL_IF_PAR4
669 << HOST_CONTROL_IF_SHIFT;
670 host_ctl &= ~HOST_CONTROL_REI;
671 writel(4, host->addr + CLOCK_DELAY);
672 } else if (value == MEMSTICK_PAR8) {
673 host_ctl |= HOST_CONTROL_FAST_CLK;
674 host_ctl |= HOST_CONTROL_IF_PAR8
675 << HOST_CONTROL_IF_SHIFT;
676 host_ctl &= ~HOST_CONTROL_REI;
677 writel(4, host->addr + CLOCK_DELAY);
678 }
679 writel(host_ctl, host->addr + HOST_CONTROL);
680 break;
681 };
682
683 spin_unlock_irqrestore(&host->lock, flags);
684}
685
686#ifdef CONFIG_PM
687
688static int jmb38x_ms_suspend(struct pci_dev *dev, pm_message_t state)
689{
690 struct jmb38x_ms *jm = pci_get_drvdata(dev);
691 int cnt;
692
693 for (cnt = 0; cnt < jm->host_cnt; ++cnt) {
694 if (!jm->hosts[cnt])
695 break;
696 memstick_suspend_host(jm->hosts[cnt]);
697 }
698
699 pci_save_state(dev);
700 pci_enable_wake(dev, pci_choose_state(dev, state), 0);
701 pci_disable_device(dev);
702 pci_set_power_state(dev, pci_choose_state(dev, state));
703 return 0;
704}
705
706static int jmb38x_ms_resume(struct pci_dev *dev)
707{
708 struct jmb38x_ms *jm = pci_get_drvdata(dev);
709 int rc;
710
711 pci_set_power_state(dev, PCI_D0);
712 pci_restore_state(dev);
713 rc = pci_enable_device(dev);
714 if (rc)
715 return rc;
716 pci_set_master(dev);
717
718 pci_read_config_dword(dev, 0xac, &rc);
719 pci_write_config_dword(dev, 0xac, rc | 0x00470000);
720
721 for (rc = 0; rc < jm->host_cnt; ++rc) {
722 if (!jm->hosts[rc])
723 break;
724 memstick_resume_host(jm->hosts[rc]);
725 memstick_detect_change(jm->hosts[rc]);
726 }
727
728 return 0;
729}
730
731#else
732
733#define jmb38x_ms_suspend NULL
734#define jmb38x_ms_resume NULL
735
736#endif /* CONFIG_PM */
737
738static int jmb38x_ms_count_slots(struct pci_dev *pdev)
739{
740 int cnt, rc = 0;
741
742 for (cnt = 0; cnt < PCI_ROM_RESOURCE; ++cnt) {
743 if (!(IORESOURCE_MEM & pci_resource_flags(pdev, cnt)))
744 break;
745
746 if (256 != pci_resource_len(pdev, cnt))
747 break;
748
749 ++rc;
750 }
751 return rc;
752}
753
754static struct memstick_host *jmb38x_ms_alloc_host(struct jmb38x_ms *jm, int cnt)
755{
756 struct memstick_host *msh;
757 struct jmb38x_ms_host *host;
758
759 msh = memstick_alloc_host(sizeof(struct jmb38x_ms_host),
760 &jm->pdev->dev);
761 if (!msh)
762 return NULL;
763
764 host = memstick_priv(msh);
765 host->chip = jm;
766 host->addr = ioremap(pci_resource_start(jm->pdev, cnt),
767 pci_resource_len(jm->pdev, cnt));
768 if (!host->addr)
769 goto err_out_free;
770
771 spin_lock_init(&host->lock);
772 host->id = cnt;
773 snprintf(host->host_id, DEVICE_ID_SIZE, DRIVER_NAME ":slot%d",
774 host->id);
775 host->irq = jm->pdev->irq;
776 host->timeout_jiffies = msecs_to_jiffies(4000);
777 msh->request = jmb38x_ms_request;
778 msh->set_param = jmb38x_ms_set_param;
779 /*
780 msh->caps = MEMSTICK_CAP_AUTO_GET_INT | MEMSTICK_CAP_PAR4
781 | MEMSTICK_CAP_PAR8;
782 */
783 msh->caps = MEMSTICK_CAP_PAR4 | MEMSTICK_CAP_PAR8;
784
785 setup_timer(&host->timer, jmb38x_ms_abort, (unsigned long)msh);
786
787 if (!request_irq(host->irq, jmb38x_ms_isr, IRQF_SHARED, host->host_id,
788 msh))
789 return msh;
790
791 iounmap(host->addr);
792err_out_free:
793 kfree(msh);
794 return NULL;
795}
796
797static void jmb38x_ms_free_host(struct memstick_host *msh)
798{
799 struct jmb38x_ms_host *host = memstick_priv(msh);
800
801 free_irq(host->irq, msh);
802 iounmap(host->addr);
803 memstick_free_host(msh);
804}
805
806static int jmb38x_ms_probe(struct pci_dev *pdev,
807 const struct pci_device_id *dev_id)
808{
809 struct jmb38x_ms *jm;
810 int pci_dev_busy = 0;
811 int rc, cnt;
812
813 rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
814 if (rc)
815 return rc;
816
817 rc = pci_enable_device(pdev);
818 if (rc)
819 return rc;
820
821 pci_set_master(pdev);
822
823 rc = pci_request_regions(pdev, DRIVER_NAME);
824 if (rc) {
825 pci_dev_busy = 1;
826 goto err_out;
827 }
828
829 pci_read_config_dword(pdev, 0xac, &rc);
830 pci_write_config_dword(pdev, 0xac, rc | 0x00470000);
831
832 cnt = jmb38x_ms_count_slots(pdev);
833 if (!cnt) {
834 rc = -ENODEV;
835 pci_dev_busy = 1;
836 goto err_out;
837 }
838
839 jm = kzalloc(sizeof(struct jmb38x_ms)
840 + cnt * sizeof(struct memstick_host *), GFP_KERNEL);
841 if (!jm) {
842 rc = -ENOMEM;
843 goto err_out_int;
844 }
845
846 jm->pdev = pdev;
847 jm->host_cnt = cnt;
848 pci_set_drvdata(pdev, jm);
849
850 for (cnt = 0; cnt < jm->host_cnt; ++cnt) {
851 jm->hosts[cnt] = jmb38x_ms_alloc_host(jm, cnt);
852 if (!jm->hosts[cnt])
853 break;
854
855 rc = memstick_add_host(jm->hosts[cnt]);
856
857 if (rc) {
858 jmb38x_ms_free_host(jm->hosts[cnt]);
859 jm->hosts[cnt] = NULL;
860 break;
861 }
862 }
863
864 if (cnt)
865 return 0;
866
867 rc = -ENODEV;
868
869 pci_set_drvdata(pdev, NULL);
870 kfree(jm);
871err_out_int:
872 pci_release_regions(pdev);
873err_out:
874 if (!pci_dev_busy)
875 pci_disable_device(pdev);
876 return rc;
877}
878
879static void jmb38x_ms_remove(struct pci_dev *dev)
880{
881 struct jmb38x_ms *jm = pci_get_drvdata(dev);
882 struct jmb38x_ms_host *host;
883 int cnt;
884 unsigned long flags;
885
886 for (cnt = 0; cnt < jm->host_cnt; ++cnt) {
887 if (!jm->hosts[cnt])
888 break;
889
890 host = memstick_priv(jm->hosts[cnt]);
891
892 writel(0, host->addr + INT_SIGNAL_ENABLE);
893 writel(0, host->addr + INT_STATUS_ENABLE);
894 mmiowb();
895 dev_dbg(&jm->pdev->dev, "interrupts off\n");
896 spin_lock_irqsave(&host->lock, flags);
897 if (host->req) {
898 host->req->error = -ETIME;
899 jmb38x_ms_complete_cmd(jm->hosts[cnt], 1);
900 }
901 spin_unlock_irqrestore(&host->lock, flags);
902
903 memstick_remove_host(jm->hosts[cnt]);
904 dev_dbg(&jm->pdev->dev, "host removed\n");
905
906 jmb38x_ms_free_host(jm->hosts[cnt]);
907 }
908
909 pci_set_drvdata(dev, NULL);
910 pci_release_regions(dev);
911 pci_disable_device(dev);
912 kfree(jm);
913}
914
915static struct pci_device_id jmb38x_ms_id_tbl [] = {
916 { PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB38X_MS, PCI_ANY_ID,
917 PCI_ANY_ID, 0, 0, 0 },
918 { }
919};
920
921static struct pci_driver jmb38x_ms_driver = {
922 .name = DRIVER_NAME,
923 .id_table = jmb38x_ms_id_tbl,
924 .probe = jmb38x_ms_probe,
925 .remove = jmb38x_ms_remove,
926 .suspend = jmb38x_ms_suspend,
927 .resume = jmb38x_ms_resume
928};
929
930static int __init jmb38x_ms_init(void)
931{
932 return pci_register_driver(&jmb38x_ms_driver);
933}
934
935static void __exit jmb38x_ms_exit(void)
936{
937 pci_unregister_driver(&jmb38x_ms_driver);
938}
939
940MODULE_AUTHOR("Alex Dubov");
941MODULE_DESCRIPTION("JMicron jmb38x MemoryStick driver");
942MODULE_LICENSE("GPL");
943MODULE_DEVICE_TABLE(pci, jmb38x_ms_id_tbl);
944
945module_init(jmb38x_ms_init);
946module_exit(jmb38x_ms_exit);