aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWei WANG <wei_wang@realsil.com.cn>2012-11-09 07:53:35 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-11-15 20:30:14 -0500
commitb902dd4ecc2cccdd6c033ba5d959d4d6606e55fb (patch)
tree6cbfcd40f223fdcf0c7c348bfc309e3177838231
parent2c94b6452cc6de582584f21066cc5e36d9530c59 (diff)
drivers/memstick: Add realtek pcie memstick host driver
Realtek PCI-E Memstick card host driver is used to access Memstick card, with the help of Realtek PCI-E card reader MFD driver. Signed-off-by: Wei WANG <wei_wang@realsil.com.cn> Acked-by: Alex Dubov <oakad@yahoo.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/memstick/host/Kconfig10
-rw-r--r--drivers/memstick/host/Makefile1
-rw-r--r--drivers/memstick/host/rtsx_pci_ms.c641
3 files changed, 652 insertions, 0 deletions
diff --git a/drivers/memstick/host/Kconfig b/drivers/memstick/host/Kconfig
index cc0997a05171..4f7a17fd1aa7 100644
--- a/drivers/memstick/host/Kconfig
+++ b/drivers/memstick/host/Kconfig
@@ -42,3 +42,13 @@ config MEMSTICK_R592
42 42
43 To compile this driver as a module, choose M here: the module will 43 To compile this driver as a module, choose M here: the module will
44 be called r592. 44 be called r592.
45
46config MEMSTICK_REALTEK_PCI
47 tristate "Realtek PCI-E Memstick Card Interface Driver"
48 depends on MFD_RTSX_PCI
49 help
50 Say Y here to include driver code to support Memstick card interface
51 of Realtek PCI-E card reader
52
53 To compile this driver as a module, choose M here: the module will
54 be called rtsx_pci_ms.
diff --git a/drivers/memstick/host/Makefile b/drivers/memstick/host/Makefile
index 31ba8d378e46..af3459d7686e 100644
--- a/drivers/memstick/host/Makefile
+++ b/drivers/memstick/host/Makefile
@@ -5,3 +5,4 @@
5obj-$(CONFIG_MEMSTICK_TIFM_MS) += tifm_ms.o 5obj-$(CONFIG_MEMSTICK_TIFM_MS) += tifm_ms.o
6obj-$(CONFIG_MEMSTICK_JMICRON_38X) += jmb38x_ms.o 6obj-$(CONFIG_MEMSTICK_JMICRON_38X) += jmb38x_ms.o
7obj-$(CONFIG_MEMSTICK_R592) += r592.o 7obj-$(CONFIG_MEMSTICK_R592) += r592.o
8obj-$(CONFIG_MEMSTICK_REALTEK_PCI) += rtsx_pci_ms.o
diff --git a/drivers/memstick/host/rtsx_pci_ms.c b/drivers/memstick/host/rtsx_pci_ms.c
new file mode 100644
index 000000000000..f5ddb82dadb7
--- /dev/null
+++ b/drivers/memstick/host/rtsx_pci_ms.c
@@ -0,0 +1,641 @@
1/* Realtek PCI-Express Memstick Card Interface driver
2 *
3 * Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2, or (at your option) any
8 * later version.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, see <http://www.gnu.org/licenses/>.
17 *
18 * Author:
19 * Wei WANG <wei_wang@realsil.com.cn>
20 * No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
21 */
22
23#include <linux/module.h>
24#include <linux/highmem.h>
25#include <linux/delay.h>
26#include <linux/platform_device.h>
27#include <linux/memstick.h>
28#include <linux/mfd/rtsx_pci.h>
29#include <asm/unaligned.h>
30
31struct realtek_pci_ms {
32 struct platform_device *pdev;
33 struct rtsx_pcr *pcr;
34 struct memstick_host *msh;
35 struct memstick_request *req;
36
37 struct mutex host_mutex;
38 struct work_struct handle_req;
39
40 u8 ssc_depth;
41 unsigned int clock;
42 unsigned char ifmode;
43 bool eject;
44};
45
46static inline struct device *ms_dev(struct realtek_pci_ms *host)
47{
48 return &(host->pdev->dev);
49}
50
51static inline void ms_clear_error(struct realtek_pci_ms *host)
52{
53 rtsx_pci_write_register(host->pcr, CARD_STOP,
54 MS_STOP | MS_CLR_ERR, MS_STOP | MS_CLR_ERR);
55}
56
57#ifdef DEBUG
58
59static void ms_print_debug_regs(struct realtek_pci_ms *host)
60{
61 struct rtsx_pcr *pcr = host->pcr;
62 u16 i;
63 u8 *ptr;
64
65 /* Print MS host internal registers */
66 rtsx_pci_init_cmd(pcr);
67 for (i = 0xFD40; i <= 0xFD44; i++)
68 rtsx_pci_add_cmd(pcr, READ_REG_CMD, i, 0, 0);
69 for (i = 0xFD52; i <= 0xFD69; i++)
70 rtsx_pci_add_cmd(pcr, READ_REG_CMD, i, 0, 0);
71 rtsx_pci_send_cmd(pcr, 100);
72
73 ptr = rtsx_pci_get_cmd_data(pcr);
74 for (i = 0xFD40; i <= 0xFD44; i++)
75 dev_dbg(ms_dev(host), "0x%04X: 0x%02x\n", i, *(ptr++));
76 for (i = 0xFD52; i <= 0xFD69; i++)
77 dev_dbg(ms_dev(host), "0x%04X: 0x%02x\n", i, *(ptr++));
78}
79
80#else
81
82#define ms_print_debug_regs(host)
83
84#endif
85
86static int ms_power_on(struct realtek_pci_ms *host)
87{
88 struct rtsx_pcr *pcr = host->pcr;
89 int err;
90
91 rtsx_pci_init_cmd(pcr);
92 rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_SELECT, 0x07, MS_MOD_SEL);
93 rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_SHARE_MODE,
94 CARD_SHARE_MASK, CARD_SHARE_48_MS);
95 rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_CLK_EN,
96 MS_CLK_EN, MS_CLK_EN);
97 err = rtsx_pci_send_cmd(pcr, 100);
98 if (err < 0)
99 return err;
100
101 err = rtsx_pci_card_pull_ctl_enable(pcr, RTSX_MS_CARD);
102 if (err < 0)
103 return err;
104
105 err = rtsx_pci_card_power_on(pcr, RTSX_MS_CARD);
106 if (err < 0)
107 return err;
108
109 /* Wait ms power stable */
110 msleep(150);
111
112 err = rtsx_pci_write_register(pcr, CARD_OE,
113 MS_OUTPUT_EN, MS_OUTPUT_EN);
114 if (err < 0)
115 return err;
116
117 return 0;
118}
119
120static int ms_power_off(struct realtek_pci_ms *host)
121{
122 struct rtsx_pcr *pcr = host->pcr;
123 int err;
124
125 rtsx_pci_init_cmd(pcr);
126
127 rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_CLK_EN, MS_CLK_EN, 0);
128 rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_OE, MS_OUTPUT_EN, 0);
129
130 err = rtsx_pci_send_cmd(pcr, 100);
131 if (err < 0)
132 return err;
133
134 err = rtsx_pci_card_power_off(pcr, RTSX_MS_CARD);
135 if (err < 0)
136 return err;
137
138 return rtsx_pci_card_pull_ctl_disable(pcr, RTSX_MS_CARD);
139}
140
141static int ms_transfer_data(struct realtek_pci_ms *host, unsigned char data_dir,
142 u8 tpc, u8 cfg, struct scatterlist *sg)
143{
144 struct rtsx_pcr *pcr = host->pcr;
145 int err;
146 unsigned int length = sg->length;
147 u16 sec_cnt = (u16)(length / 512);
148 u8 val, trans_mode, dma_dir;
149
150 dev_dbg(ms_dev(host), "%s: tpc = 0x%02x, data_dir = %s, length = %d\n",
151 __func__, tpc, (data_dir == READ) ? "READ" : "WRITE",
152 length);
153
154 if (data_dir == READ) {
155 dma_dir = DMA_DIR_FROM_CARD;
156 trans_mode = MS_TM_AUTO_READ;
157 } else {
158 dma_dir = DMA_DIR_TO_CARD;
159 trans_mode = MS_TM_AUTO_WRITE;
160 }
161
162 rtsx_pci_init_cmd(pcr);
163
164 rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, MS_TPC, 0xFF, tpc);
165 rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, MS_SECTOR_CNT_H,
166 0xFF, (u8)(sec_cnt >> 8));
167 rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, MS_SECTOR_CNT_L,
168 0xFF, (u8)sec_cnt);
169 rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, MS_TRANS_CFG, 0xFF, cfg);
170
171 rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, IRQSTAT0,
172 DMA_DONE_INT, DMA_DONE_INT);
173 rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, DMATC3, 0xFF, (u8)(length >> 24));
174 rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, DMATC2, 0xFF, (u8)(length >> 16));
175 rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, DMATC1, 0xFF, (u8)(length >> 8));
176 rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, DMATC0, 0xFF, (u8)length);
177 rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, DMACTL,
178 0x03 | DMA_PACK_SIZE_MASK, dma_dir | DMA_EN | DMA_512);
179 rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CAR