2 * jmb38x_ms.c - JMicron jmb38x MemoryStick card reader
4 * Copyright (C) 2008 Alex Dubov <oakad@yahoo.com>
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.
12 #include <linux/spinlock.h>
13 #include <linux/interrupt.h>
14 #include <linux/pci.h>
15 #include <linux/delay.h>
16 #include <linux/highmem.h>
17 #include <linux/memstick.h>
19 #define DRIVER_NAME "jmb38x_ms"
22 module_param(no_dma, bool, 0644);
35 INT_STATUS_ENABLE = 0x28,
36 INT_SIGNAL_ENABLE = 0x2c,
39 PAD_OUTPUT_ENABLE = 0x38,
48 struct jmb38x_ms_host {
49 struct jmb38x_ms *chip;
53 char host_id[DEVICE_ID_SIZE];
55 unsigned int block_pos;
56 unsigned long timeout_jiffies;
57 struct timer_list timer;
58 struct memstick_request *req;
59 unsigned char eject:1,
61 unsigned char cmd_flags;
63 unsigned int io_word[2];
69 struct memstick_host *hosts[];
72 #define BLOCK_COUNT_MASK 0xffff0000
73 #define BLOCK_SIZE_MASK 0x00000fff
75 #define DMA_CONTROL_ENABLE 0x00000001
77 #define TPC_DATA_SEL 0x00008000
78 #define TPC_DIR 0x00004000
79 #define TPC_WAIT_INT 0x00002000
80 #define TPC_GET_INT 0x00000800
81 #define TPC_CODE_SZ_MASK 0x00000700
82 #define TPC_DATA_SZ_MASK 0x00000007
84 #define HOST_CONTROL_RESET_REQ 0x00008000
85 #define HOST_CONTROL_REI 0x00004000
86 #define HOST_CONTROL_LED 0x00000400
87 #define HOST_CONTROL_FAST_CLK 0x00000200
88 #define HOST_CONTROL_RESET 0x00000100
89 #define HOST_CONTROL_POWER_EN 0x00000080
90 #define HOST_CONTROL_CLOCK_EN 0x00000040
91 #define HOST_CONTROL_IF_SHIFT 4
93 #define HOST_CONTROL_IF_SERIAL 0x0
94 #define HOST_CONTROL_IF_PAR4 0x1
95 #define HOST_CONTROL_IF_PAR8 0x3
97 #define STATUS_HAS_MEDIA 0x00000400
98 #define STATUS_FIFO_EMPTY 0x00000200
99 #define STATUS_FIFO_FULL 0x00000100
101 #define INT_STATUS_TPC_ERR 0x00080000
102 #define INT_STATUS_CRC_ERR 0x00040000
103 #define INT_STATUS_TIMER_TO 0x00020000
104 #define INT_STATUS_HSK_TO 0x00010000
105 #define INT_STATUS_ANY_ERR 0x00008000
106 #define INT_STATUS_FIFO_WRDY 0x00000080
107 #define INT_STATUS_FIFO_RRDY 0x00000040
108 #define INT_STATUS_MEDIA_OUT 0x00000010
109 #define INT_STATUS_MEDIA_IN 0x00000008
110 #define INT_STATUS_DMA_BOUNDARY 0x00000004
111 #define INT_STATUS_EOTRAN 0x00000002
112 #define INT_STATUS_EOTPC 0x00000001
114 #define INT_STATUS_ALL 0x000f801f
116 #define PAD_OUTPUT_ENABLE_MS 0x0F3F
118 #define PAD_PU_PD_OFF 0x7FFF0000
119 #define PAD_PU_PD_ON_MS_SOCK0 0x5f8f0000
120 #define PAD_PU_PD_ON_MS_SOCK1 0x0f0f0000
129 static unsigned int jmb38x_ms_read_data(struct jmb38x_ms_host *host,
130 unsigned char *buf, unsigned int length)
132 unsigned int off = 0;
134 while (host->io_pos && length) {
135 buf[off++] = host->io_word[0] & 0xff;
136 host->io_word[0] >>= 8;
144 while (!(STATUS_FIFO_EMPTY & readl(host->addr + STATUS))) {
147 *(unsigned int *)(buf + off) = __raw_readl(host->addr + DATA);
153 && !(STATUS_FIFO_EMPTY & readl(host->addr + STATUS))) {
154 host->io_word[0] = readl(host->addr + DATA);
155 for (host->io_pos = 4; host->io_pos; --host->io_pos) {
156 buf[off++] = host->io_word[0] & 0xff;
157 host->io_word[0] >>= 8;
167 static unsigned int jmb38x_ms_read_reg_data(struct jmb38x_ms_host *host,
171 unsigned int off = 0;
173 while (host->io_pos > 4 && length) {
174 buf[off++] = host->io_word[0] & 0xff;
175 host->io_word[0] >>= 8;
183 while (host->io_pos && length) {
184 buf[off++] = host->io_word[1] & 0xff;
185 host->io_word[1] >>= 8;
193 static unsigned int jmb38x_ms_write_data(struct jmb38x_ms_host *host,
197 unsigned int off = 0;
200 while (host->io_pos < 4 && length) {
201 host->io_word[0] |= buf[off++] << (host->io_pos * 8);
207 if (host->io_pos == 4
208 && !(STATUS_FIFO_FULL & readl(host->addr + STATUS))) {
209 writel(host->io_word[0], host->addr + DATA);
211 host->io_word[0] = 0;
212 } else if (host->io_pos) {
219 while (!(STATUS_FIFO_FULL & readl(host->addr + STATUS))) {
223 __raw_writel(*(unsigned int *)(buf + off),
231 host->io_word[0] |= buf[off + 2] << 16;
234 host->io_word[0] |= buf[off + 1] << 8;
237 host->io_word[0] |= buf[off];
246 static unsigned int jmb38x_ms_write_reg_data(struct jmb38x_ms_host *host,
250 unsigned int off = 0;
252 while (host->io_pos < 4 && length) {
253 host->io_word[0] &= ~(0xff << (host->io_pos * 8));
254 host->io_word[0] |= buf[off++] << (host->io_pos * 8);
262 while (host->io_pos < 8 && length) {
263 host->io_word[1] &= ~(0xff << (host->io_pos * 8));
264 host->io_word[1] |= buf[off++] << (host->io_pos * 8);
272 static int jmb38x_ms_transfer_data(struct jmb38x_ms_host *host)
276 unsigned int t_size, p_off, p_cnt;
279 unsigned long flags = 0;
281 if (host->req->long_data) {
282 length = host->req->sg.length - host->block_pos;
283 off = host->req->sg.offset + host->block_pos;
285 length = host->req->data_len - host->block_pos;
290 if (host->req->long_data) {
291 pg = nth_page(sg_page(&host->req->sg),
293 p_off = offset_in_page(off);
294 p_cnt = PAGE_SIZE - p_off;
295 p_cnt = min(p_cnt, length);
297 local_irq_save(flags);
298 buf = kmap_atomic(pg, KM_BIO_SRC_IRQ) + p_off;
300 buf = host->req->data + host->block_pos;
301 p_cnt = host->req->data_len - host->block_pos;
304 if (host->req->data_dir == WRITE)
305 t_size = !(host->cmd_flags & REG_DATA)
306 ? jmb38x_ms_write_data(host, buf, p_cnt)
307 : jmb38x_ms_write_reg_data(host, buf, p_cnt);
309 t_size = !(host->cmd_flags & REG_DATA)
310 ? jmb38x_ms_read_data(host, buf, p_cnt)
311 : jmb38x_ms_read_reg_data(host, buf, p_cnt);
313 if (host->req->long_data) {
314 kunmap_atomic(buf - p_off, KM_BIO_SRC_IRQ);
315 local_irq_restore(flags);
320 host->block_pos += t_size;
325 if (!length && host->req->data_dir == WRITE) {
326 if (host->cmd_flags & REG_DATA) {
327 writel(host->io_word[0], host->addr + TPC_P0);
328 writel(host->io_word[1], host->addr + TPC_P1);
329 } else if (host->io_pos) {
330 writel(host->io_word[0], host->addr + DATA);
337 static int jmb38x_ms_issue_cmd(struct memstick_host *msh)
339 struct jmb38x_ms_host *host = memstick_priv(msh);
341 unsigned int data_len, cmd, t_val;
343 if (!(STATUS_HAS_MEDIA & readl(host->addr + STATUS))) {
344 dev_dbg(msh->cdev.dev, "no media status\n");
345 host->req->error = -ETIME;
346 return host->req->error;
349 dev_dbg(msh->cdev.dev, "control %08x\n",
350 readl(host->addr + HOST_CONTROL));
351 dev_dbg(msh->cdev.dev, "status %08x\n", readl(host->addr + INT_STATUS));
352 dev_dbg(msh->cdev.dev, "hstatus %08x\n", readl(host->addr + STATUS));
357 host->io_word[0] = 0;
358 host->io_word[1] = 0;
360 cmd = host->req->tpc << 16;
363 if (host->req->data_dir == READ)
365 if (host->req->need_card_int)
367 if (host->req->get_int_reg)
370 data = host->req->data;
372 host->use_dma = !no_dma;
374 if (host->req->long_data) {
375 data_len = host->req->sg.length;
377 data_len = host->req->data_len;
382 cmd &= ~(TPC_DATA_SEL | 0xf);
383 host->cmd_flags |= REG_DATA;
384 cmd |= data_len & 0xf;
389 if (1 != pci_map_sg(host->chip->pdev, &host->req->sg, 1,
390 host->req->data_dir == READ
392 : PCI_DMA_TODEVICE)) {
393 host->req->error = -ENOMEM;
394 return host->req->error;
396 data_len = sg_dma_len(&host->req->sg);
397 writel(sg_dma_address(&host->req->sg),
398 host->addr + DMA_ADDRESS);
399 writel(((1 << 16) & BLOCK_COUNT_MASK)
400 | (data_len & BLOCK_SIZE_MASK),
402 writel(DMA_CONTROL_ENABLE, host->addr + DMA_CONTROL);
403 } else if (!(host->cmd_flags & REG_DATA)) {
404 writel(((1 << 16) & BLOCK_COUNT_MASK)
405 | (data_len & BLOCK_SIZE_MASK),
407 t_val = readl(host->addr + INT_STATUS_ENABLE);
408 t_val |= host->req->data_dir == READ
409 ? INT_STATUS_FIFO_RRDY
410 : INT_STATUS_FIFO_WRDY;
412 writel(t_val, host->addr + INT_STATUS_ENABLE);
413 writel(t_val, host->addr + INT_SIGNAL_ENABLE);
415 cmd &= ~(TPC_DATA_SEL | 0xf);
416 host->cmd_flags |= REG_DATA;
417 cmd |= data_len & 0xf;
419 if (host->req->data_dir == WRITE) {
420 jmb38x_ms_transfer_data(host);
421 writel(host->io_word[0], host->addr + TPC_P0);
422 writel(host->io_word[1], host->addr + TPC_P1);
426 mod_timer(&host->timer, jiffies + host->timeout_jiffies);
427 writel(HOST_CONTROL_LED | readl(host->addr + HOST_CONTROL),
428 host->addr + HOST_CONTROL);
429 host->req->error = 0;
431 writel(cmd, host->addr + TPC);
432 dev_dbg(msh->cdev.dev, "executing TPC %08x, len %x\n", cmd, data_len);
437 static void jmb38x_ms_complete_cmd(struct memstick_host *msh, int last)
439 struct jmb38x_ms_host *host = memstick_priv(msh);
440 unsigned int t_val = 0;
443 del_timer(&host->timer);
445 dev_dbg(msh->cdev.dev, "c control %08x\n",
446 readl(host->addr + HOST_CONTROL));
447 dev_dbg(msh->cdev.dev, "c status %08x\n",
448 readl(host->addr + INT_STATUS));
449 dev_dbg(msh->cdev.dev, "c hstatus %08x\n", readl(host->addr + STATUS));
451 if (host->req->get_int_reg) {
452 t_val = readl(host->addr + TPC_P0);
453 host->req->int_reg = (t_val & 0xff);
457 writel(0, host->addr + DMA_CONTROL);
458 pci_unmap_sg(host->chip->pdev, &host->req->sg, 1,
459 host->req->data_dir == READ
460 ? PCI_DMA_FROMDEVICE : PCI_DMA_TODEVICE);
462 t_val = readl(host->addr + INT_STATUS_ENABLE);
463 if (host->req->data_dir == READ)
464 t_val &= ~INT_STATUS_FIFO_RRDY;
466 t_val &= ~INT_STATUS_FIFO_WRDY;
468 writel(t_val, host->addr + INT_STATUS_ENABLE);
469 writel(t_val, host->addr + INT_SIGNAL_ENABLE);
472 writel((~HOST_CONTROL_LED) & readl(host->addr + HOST_CONTROL),
473 host->addr + HOST_CONTROL);
477 rc = memstick_next_req(msh, &host->req);
478 } while (!rc && jmb38x_ms_issue_cmd(msh));
481 rc = memstick_next_req(msh, &host->req);
483 host->req->error = -ETIME;
488 static irqreturn_t jmb38x_ms_isr(int irq, void *dev_id)
490 struct memstick_host *msh = dev_id;
491 struct jmb38x_ms_host *host = memstick_priv(msh);
492 unsigned int irq_status;
494 spin_lock(&host->lock);
495 irq_status = readl(host->addr + INT_STATUS);
496 dev_dbg(&host->chip->pdev->dev, "irq_status = %08x\n", irq_status);
497 if (irq_status == 0 || irq_status == (~0)) {
498 spin_unlock(&host->lock);
503 if (irq_status & INT_STATUS_ANY_ERR) {
504 if (irq_status & INT_STATUS_CRC_ERR)
505 host->req->error = -EILSEQ;
507 host->req->error = -ETIME;
510 if (irq_status & INT_STATUS_EOTRAN)
511 host->cmd_flags |= FIFO_READY;
513 if (irq_status & (INT_STATUS_FIFO_RRDY
514 | INT_STATUS_FIFO_WRDY))
515 jmb38x_ms_transfer_data(host);
517 if (irq_status & INT_STATUS_EOTRAN) {
518 jmb38x_ms_transfer_data(host);
519 host->cmd_flags |= FIFO_READY;
523 if (irq_status & INT_STATUS_EOTPC) {
524 host->cmd_flags |= CMD_READY;
525 if (host->cmd_flags & REG_DATA) {
526 if (host->req->data_dir == READ) {
535 jmb38x_ms_transfer_data(host);
537 host->cmd_flags |= FIFO_READY;
543 if (irq_status & (INT_STATUS_MEDIA_IN | INT_STATUS_MEDIA_OUT)) {
544 dev_dbg(&host->chip->pdev->dev, "media changed\n");
545 memstick_detect_change(msh);
548 writel(irq_status, host->addr + INT_STATUS);
551 && (((host->cmd_flags & CMD_READY)
552 && (host->cmd_flags & FIFO_READY))
553 || host->req->error))
554 jmb38x_ms_complete_cmd(msh, 0);
556 spin_unlock(&host->lock);
560 static void jmb38x_ms_abort(unsigned long data)
562 struct memstick_host *msh = (struct memstick_host *)data;
563 struct jmb38x_ms_host *host = memstick_priv(msh);
566 dev_dbg(&host->chip->pdev->dev, "abort\n");
567 spin_lock_irqsave(&host->lock, flags);
569 host->req->error = -ETIME;
570 jmb38x_ms_complete_cmd(msh, 0);
572 spin_unlock_irqrestore(&host->lock, flags);
575 static void jmb38x_ms_request(struct memstick_host *msh)
577 struct jmb38x_ms_host *host = memstick_priv(msh);
581 spin_lock_irqsave(&host->lock, flags);
583 spin_unlock_irqrestore(&host->lock, flags);
589 rc = memstick_next_req(msh, &host->req);
590 } while (!rc && jmb38x_ms_issue_cmd(msh));
591 spin_unlock_irqrestore(&host->lock, flags);
594 static void jmb38x_ms_reset(struct jmb38x_ms_host *host)
596 unsigned int host_ctl = readl(host->addr + HOST_CONTROL);
598 writel(host_ctl | HOST_CONTROL_RESET_REQ | HOST_CONTROL_RESET,
599 host->addr + HOST_CONTROL);
601 while (HOST_CONTROL_RESET_REQ
602 & (host_ctl = readl(host->addr + HOST_CONTROL))) {
604 dev_dbg(&host->chip->pdev->dev, "reset\n");
607 writel(INT_STATUS_ALL, host->addr + INT_STATUS_ENABLE);
608 writel(INT_STATUS_ALL, host->addr + INT_SIGNAL_ENABLE);
610 dev_dbg(&host->chip->pdev->dev, "reset\n");
613 static void jmb38x_ms_set_param(struct memstick_host *msh,
614 enum memstick_param param,
617 struct jmb38x_ms_host *host = memstick_priv(msh);
618 unsigned int host_ctl;
621 spin_lock_irqsave(&host->lock, flags);
625 if (value == MEMSTICK_POWER_ON) {
626 jmb38x_ms_reset(host);
628 writel(host->id ? PAD_PU_PD_ON_MS_SOCK1
629 : PAD_PU_PD_ON_MS_SOCK0,
630 host->addr + PAD_PU_PD);
632 writel(PAD_OUTPUT_ENABLE_MS,
633 host->addr + PAD_OUTPUT_ENABLE);
635 host_ctl = readl(host->addr + HOST_CONTROL);
637 writel(host_ctl | (HOST_CONTROL_POWER_EN
638 | HOST_CONTROL_CLOCK_EN),
639 host->addr + HOST_CONTROL);
641 dev_dbg(&host->chip->pdev->dev, "power on\n");
642 } else if (value == MEMSTICK_POWER_OFF) {
643 writel(readl(host->addr + HOST_CONTROL)
644 & ~(HOST_CONTROL_POWER_EN
645 | HOST_CONTROL_CLOCK_EN),
646 host->addr + HOST_CONTROL);
647 writel(0, host->addr + PAD_OUTPUT_ENABLE);
648 writel(PAD_PU_PD_OFF, host->addr + PAD_PU_PD);
649 dev_dbg(&host->chip->pdev->dev, "power off\n");
652 case MEMSTICK_INTERFACE:
653 /* jmb38x_ms_reset(host); */
655 host_ctl = readl(host->addr + HOST_CONTROL);
656 host_ctl &= ~(3 << HOST_CONTROL_IF_SHIFT);
659 if (value == MEMSTICK_SERIAL) {
660 host_ctl &= ~HOST_CONTROL_FAST_CLK;
661 host_ctl |= HOST_CONTROL_IF_SERIAL
662 << HOST_CONTROL_IF_SHIFT;
663 host_ctl |= HOST_CONTROL_REI;
664 writel(0, host->addr + CLOCK_DELAY);
665 } else if (value == MEMSTICK_PAR4) {
666 host_ctl |= HOST_CONTROL_FAST_CLK;
667 host_ctl |= HOST_CONTROL_IF_PAR4
668 << HOST_CONTROL_IF_SHIFT;
669 host_ctl &= ~HOST_CONTROL_REI;
670 writel(4, host->addr + CLOCK_DELAY);
671 } else if (value == MEMSTICK_PAR8) {
672 host_ctl |= HOST_CONTROL_FAST_CLK;
673 host_ctl |= HOST_CONTROL_IF_PAR8
674 << HOST_CONTROL_IF_SHIFT;
675 host_ctl &= ~HOST_CONTROL_REI;
676 writel(4, host->addr + CLOCK_DELAY);
678 writel(host_ctl, host->addr + HOST_CONTROL);
682 spin_unlock_irqrestore(&host->lock, flags);
687 static int jmb38x_ms_suspend(struct pci_dev *dev, pm_message_t state)
689 struct jmb38x_ms *jm = pci_get_drvdata(dev);
692 for (cnt = 0; cnt < jm->host_cnt; ++cnt) {
695 memstick_suspend_host(jm->hosts[cnt]);
699 pci_enable_wake(dev, pci_choose_state(dev, state), 0);
700 pci_disable_device(dev);
701 pci_set_power_state(dev, pci_choose_state(dev, state));
705 static int jmb38x_ms_resume(struct pci_dev *dev)
707 struct jmb38x_ms *jm = pci_get_drvdata(dev);
710 pci_set_power_state(dev, PCI_D0);
711 pci_restore_state(dev);
712 rc = pci_enable_device(dev);
717 pci_read_config_dword(dev, 0xac, &rc);
718 pci_write_config_dword(dev, 0xac, rc | 0x00470000);
720 for (rc = 0; rc < jm->host_cnt; ++rc) {
723 memstick_resume_host(jm->hosts[rc]);
724 memstick_detect_change(jm->hosts[rc]);
732 #define jmb38x_ms_suspend NULL
733 #define jmb38x_ms_resume NULL
735 #endif /* CONFIG_PM */
737 static int jmb38x_ms_count_slots(struct pci_dev *pdev)
741 for (cnt = 0; cnt < PCI_ROM_RESOURCE; ++cnt) {
742 if (!(IORESOURCE_MEM & pci_resource_flags(pdev, cnt)))
745 if (256 != pci_resource_len(pdev, cnt))
753 static struct memstick_host *jmb38x_ms_alloc_host(struct jmb38x_ms *jm, int cnt)
755 struct memstick_host *msh;
756 struct jmb38x_ms_host *host;
758 msh = memstick_alloc_host(sizeof(struct jmb38x_ms_host),
763 host = memstick_priv(msh);
765 host->addr = ioremap(pci_resource_start(jm->pdev, cnt),
766 pci_resource_len(jm->pdev, cnt));
770 spin_lock_init(&host->lock);
772 snprintf(host->host_id, DEVICE_ID_SIZE, DRIVER_NAME ":slot%d",
774 host->irq = jm->pdev->irq;
775 host->timeout_jiffies = msecs_to_jiffies(4000);
776 msh->request = jmb38x_ms_request;
777 msh->set_param = jmb38x_ms_set_param;
779 msh->caps = MEMSTICK_CAP_AUTO_GET_INT | MEMSTICK_CAP_PAR4
782 msh->caps = MEMSTICK_CAP_PAR4 | MEMSTICK_CAP_PAR8;
784 setup_timer(&host->timer, jmb38x_ms_abort, (unsigned long)msh);
786 if (!request_irq(host->irq, jmb38x_ms_isr, IRQF_SHARED, host->host_id,
796 static void jmb38x_ms_free_host(struct memstick_host *msh)
798 struct jmb38x_ms_host *host = memstick_priv(msh);
800 free_irq(host->irq, msh);
802 memstick_free_host(msh);
805 static int jmb38x_ms_probe(struct pci_dev *pdev,
806 const struct pci_device_id *dev_id)
808 struct jmb38x_ms *jm;
809 int pci_dev_busy = 0;
812 rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
816 rc = pci_enable_device(pdev);
820 pci_set_master(pdev);
822 rc = pci_request_regions(pdev, DRIVER_NAME);
828 pci_read_config_dword(pdev, 0xac, &rc);
829 pci_write_config_dword(pdev, 0xac, rc | 0x00470000);
831 cnt = jmb38x_ms_count_slots(pdev);
838 jm = kzalloc(sizeof(struct jmb38x_ms)
839 + cnt * sizeof(struct memstick_host *), GFP_KERNEL);
847 pci_set_drvdata(pdev, jm);
849 for (cnt = 0; cnt < jm->host_cnt; ++cnt) {
850 jm->hosts[cnt] = jmb38x_ms_alloc_host(jm, cnt);
854 rc = memstick_add_host(jm->hosts[cnt]);
857 jmb38x_ms_free_host(jm->hosts[cnt]);
858 jm->hosts[cnt] = NULL;
868 pci_set_drvdata(pdev, NULL);
871 pci_release_regions(pdev);
874 pci_disable_device(pdev);
878 static void jmb38x_ms_remove(struct pci_dev *dev)
880 struct jmb38x_ms *jm = pci_get_drvdata(dev);
881 struct jmb38x_ms_host *host;
885 for (cnt = 0; cnt < jm->host_cnt; ++cnt) {
889 host = memstick_priv(jm->hosts[cnt]);
891 writel(0, host->addr + INT_SIGNAL_ENABLE);
892 writel(0, host->addr + INT_STATUS_ENABLE);
894 dev_dbg(&jm->pdev->dev, "interrupts off\n");
895 spin_lock_irqsave(&host->lock, flags);
897 host->req->error = -ETIME;
898 jmb38x_ms_complete_cmd(jm->hosts[cnt], 1);
900 spin_unlock_irqrestore(&host->lock, flags);
902 memstick_remove_host(jm->hosts[cnt]);
903 dev_dbg(&jm->pdev->dev, "host removed\n");
905 jmb38x_ms_free_host(jm->hosts[cnt]);
908 pci_set_drvdata(dev, NULL);
909 pci_release_regions(dev);
910 pci_disable_device(dev);
914 static struct pci_device_id jmb38x_ms_id_tbl [] = {
915 { PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB38X_MS, PCI_ANY_ID,
916 PCI_ANY_ID, 0, 0, 0 },
920 static struct pci_driver jmb38x_ms_driver = {
922 .id_table = jmb38x_ms_id_tbl,
923 .probe = jmb38x_ms_probe,
924 .remove = jmb38x_ms_remove,
925 .suspend = jmb38x_ms_suspend,
926 .resume = jmb38x_ms_resume
929 static int __init jmb38x_ms_init(void)
931 return pci_register_driver(&jmb38x_ms_driver);
934 static void __exit jmb38x_ms_exit(void)
936 pci_unregister_driver(&jmb38x_ms_driver);
939 MODULE_AUTHOR("Alex Dubov");
940 MODULE_DESCRIPTION("JMicron jmb38x MemoryStick driver");
941 MODULE_LICENSE("GPL");
942 MODULE_DEVICE_TABLE(pci, jmb38x_ms_id_tbl);
944 module_init(jmb38x_ms_init);
945 module_exit(jmb38x_ms_exit);