1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later
2*4882a593Smuzhiyun /* Realtek PCI-Express Memstick Card Interface driver
3*4882a593Smuzhiyun *
4*4882a593Smuzhiyun * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved.
5*4882a593Smuzhiyun *
6*4882a593Smuzhiyun * Author:
7*4882a593Smuzhiyun * Wei WANG <wei_wang@realsil.com.cn>
8*4882a593Smuzhiyun */
9*4882a593Smuzhiyun
10*4882a593Smuzhiyun #include <linux/module.h>
11*4882a593Smuzhiyun #include <linux/highmem.h>
12*4882a593Smuzhiyun #include <linux/delay.h>
13*4882a593Smuzhiyun #include <linux/platform_device.h>
14*4882a593Smuzhiyun #include <linux/memstick.h>
15*4882a593Smuzhiyun #include <linux/rtsx_pci.h>
16*4882a593Smuzhiyun #include <asm/unaligned.h>
17*4882a593Smuzhiyun
18*4882a593Smuzhiyun struct realtek_pci_ms {
19*4882a593Smuzhiyun struct platform_device *pdev;
20*4882a593Smuzhiyun struct rtsx_pcr *pcr;
21*4882a593Smuzhiyun struct memstick_host *msh;
22*4882a593Smuzhiyun struct memstick_request *req;
23*4882a593Smuzhiyun
24*4882a593Smuzhiyun struct mutex host_mutex;
25*4882a593Smuzhiyun struct work_struct handle_req;
26*4882a593Smuzhiyun
27*4882a593Smuzhiyun u8 ssc_depth;
28*4882a593Smuzhiyun unsigned int clock;
29*4882a593Smuzhiyun unsigned char ifmode;
30*4882a593Smuzhiyun bool eject;
31*4882a593Smuzhiyun };
32*4882a593Smuzhiyun
ms_dev(struct realtek_pci_ms * host)33*4882a593Smuzhiyun static inline struct device *ms_dev(struct realtek_pci_ms *host)
34*4882a593Smuzhiyun {
35*4882a593Smuzhiyun return &(host->pdev->dev);
36*4882a593Smuzhiyun }
37*4882a593Smuzhiyun
ms_clear_error(struct realtek_pci_ms * host)38*4882a593Smuzhiyun static inline void ms_clear_error(struct realtek_pci_ms *host)
39*4882a593Smuzhiyun {
40*4882a593Smuzhiyun rtsx_pci_write_register(host->pcr, CARD_STOP,
41*4882a593Smuzhiyun MS_STOP | MS_CLR_ERR, MS_STOP | MS_CLR_ERR);
42*4882a593Smuzhiyun }
43*4882a593Smuzhiyun
44*4882a593Smuzhiyun #ifdef DEBUG
45*4882a593Smuzhiyun
ms_print_debug_regs(struct realtek_pci_ms * host)46*4882a593Smuzhiyun static void ms_print_debug_regs(struct realtek_pci_ms *host)
47*4882a593Smuzhiyun {
48*4882a593Smuzhiyun struct rtsx_pcr *pcr = host->pcr;
49*4882a593Smuzhiyun u16 i;
50*4882a593Smuzhiyun u8 *ptr;
51*4882a593Smuzhiyun
52*4882a593Smuzhiyun /* Print MS host internal registers */
53*4882a593Smuzhiyun rtsx_pci_init_cmd(pcr);
54*4882a593Smuzhiyun for (i = 0xFD40; i <= 0xFD44; i++)
55*4882a593Smuzhiyun rtsx_pci_add_cmd(pcr, READ_REG_CMD, i, 0, 0);
56*4882a593Smuzhiyun for (i = 0xFD52; i <= 0xFD69; i++)
57*4882a593Smuzhiyun rtsx_pci_add_cmd(pcr, READ_REG_CMD, i, 0, 0);
58*4882a593Smuzhiyun rtsx_pci_send_cmd(pcr, 100);
59*4882a593Smuzhiyun
60*4882a593Smuzhiyun ptr = rtsx_pci_get_cmd_data(pcr);
61*4882a593Smuzhiyun for (i = 0xFD40; i <= 0xFD44; i++)
62*4882a593Smuzhiyun dev_dbg(ms_dev(host), "0x%04X: 0x%02x\n", i, *(ptr++));
63*4882a593Smuzhiyun for (i = 0xFD52; i <= 0xFD69; i++)
64*4882a593Smuzhiyun dev_dbg(ms_dev(host), "0x%04X: 0x%02x\n", i, *(ptr++));
65*4882a593Smuzhiyun }
66*4882a593Smuzhiyun
67*4882a593Smuzhiyun #else
68*4882a593Smuzhiyun
69*4882a593Smuzhiyun #define ms_print_debug_regs(host)
70*4882a593Smuzhiyun
71*4882a593Smuzhiyun #endif
72*4882a593Smuzhiyun
ms_power_on(struct realtek_pci_ms * host)73*4882a593Smuzhiyun static int ms_power_on(struct realtek_pci_ms *host)
74*4882a593Smuzhiyun {
75*4882a593Smuzhiyun struct rtsx_pcr *pcr = host->pcr;
76*4882a593Smuzhiyun int err;
77*4882a593Smuzhiyun
78*4882a593Smuzhiyun rtsx_pci_init_cmd(pcr);
79*4882a593Smuzhiyun rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_SELECT, 0x07, MS_MOD_SEL);
80*4882a593Smuzhiyun rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_SHARE_MODE,
81*4882a593Smuzhiyun CARD_SHARE_MASK, CARD_SHARE_48_MS);
82*4882a593Smuzhiyun rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_CLK_EN,
83*4882a593Smuzhiyun MS_CLK_EN, MS_CLK_EN);
84*4882a593Smuzhiyun err = rtsx_pci_send_cmd(pcr, 100);
85*4882a593Smuzhiyun if (err < 0)
86*4882a593Smuzhiyun return err;
87*4882a593Smuzhiyun
88*4882a593Smuzhiyun err = rtsx_pci_card_pull_ctl_enable(pcr, RTSX_MS_CARD);
89*4882a593Smuzhiyun if (err < 0)
90*4882a593Smuzhiyun return err;
91*4882a593Smuzhiyun
92*4882a593Smuzhiyun err = rtsx_pci_card_power_on(pcr, RTSX_MS_CARD);
93*4882a593Smuzhiyun if (err < 0)
94*4882a593Smuzhiyun return err;
95*4882a593Smuzhiyun
96*4882a593Smuzhiyun /* Wait ms power stable */
97*4882a593Smuzhiyun msleep(150);
98*4882a593Smuzhiyun
99*4882a593Smuzhiyun err = rtsx_pci_write_register(pcr, CARD_OE,
100*4882a593Smuzhiyun MS_OUTPUT_EN, MS_OUTPUT_EN);
101*4882a593Smuzhiyun if (err < 0)
102*4882a593Smuzhiyun return err;
103*4882a593Smuzhiyun
104*4882a593Smuzhiyun return 0;
105*4882a593Smuzhiyun }
106*4882a593Smuzhiyun
ms_power_off(struct realtek_pci_ms * host)107*4882a593Smuzhiyun static int ms_power_off(struct realtek_pci_ms *host)
108*4882a593Smuzhiyun {
109*4882a593Smuzhiyun struct rtsx_pcr *pcr = host->pcr;
110*4882a593Smuzhiyun int err;
111*4882a593Smuzhiyun
112*4882a593Smuzhiyun rtsx_pci_init_cmd(pcr);
113*4882a593Smuzhiyun
114*4882a593Smuzhiyun rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_CLK_EN, MS_CLK_EN, 0);
115*4882a593Smuzhiyun rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_OE, MS_OUTPUT_EN, 0);
116*4882a593Smuzhiyun
117*4882a593Smuzhiyun err = rtsx_pci_send_cmd(pcr, 100);
118*4882a593Smuzhiyun if (err < 0)
119*4882a593Smuzhiyun return err;
120*4882a593Smuzhiyun
121*4882a593Smuzhiyun err = rtsx_pci_card_power_off(pcr, RTSX_MS_CARD);
122*4882a593Smuzhiyun if (err < 0)
123*4882a593Smuzhiyun return err;
124*4882a593Smuzhiyun
125*4882a593Smuzhiyun return rtsx_pci_card_pull_ctl_disable(pcr, RTSX_MS_CARD);
126*4882a593Smuzhiyun }
127*4882a593Smuzhiyun
ms_transfer_data(struct realtek_pci_ms * host,unsigned char data_dir,u8 tpc,u8 cfg,struct scatterlist * sg)128*4882a593Smuzhiyun static int ms_transfer_data(struct realtek_pci_ms *host, unsigned char data_dir,
129*4882a593Smuzhiyun u8 tpc, u8 cfg, struct scatterlist *sg)
130*4882a593Smuzhiyun {
131*4882a593Smuzhiyun struct rtsx_pcr *pcr = host->pcr;
132*4882a593Smuzhiyun int err;
133*4882a593Smuzhiyun unsigned int length = sg->length;
134*4882a593Smuzhiyun u16 sec_cnt = (u16)(length / 512);
135*4882a593Smuzhiyun u8 val, trans_mode, dma_dir;
136*4882a593Smuzhiyun struct memstick_dev *card = host->msh->card;
137*4882a593Smuzhiyun bool pro_card = card->id.type == MEMSTICK_TYPE_PRO;
138*4882a593Smuzhiyun
139*4882a593Smuzhiyun dev_dbg(ms_dev(host), "%s: tpc = 0x%02x, data_dir = %s, length = %d\n",
140*4882a593Smuzhiyun __func__, tpc, (data_dir == READ) ? "READ" : "WRITE",
141*4882a593Smuzhiyun length);
142*4882a593Smuzhiyun
143*4882a593Smuzhiyun if (data_dir == READ) {
144*4882a593Smuzhiyun dma_dir = DMA_DIR_FROM_CARD;
145*4882a593Smuzhiyun trans_mode = pro_card ? MS_TM_AUTO_READ : MS_TM_NORMAL_READ;
146*4882a593Smuzhiyun } else {
147*4882a593Smuzhiyun dma_dir = DMA_DIR_TO_CARD;
148*4882a593Smuzhiyun trans_mode = pro_card ? MS_TM_AUTO_WRITE : MS_TM_NORMAL_WRITE;
149*4882a593Smuzhiyun }
150*4882a593Smuzhiyun
151*4882a593Smuzhiyun rtsx_pci_init_cmd(pcr);
152*4882a593Smuzhiyun
153*4882a593Smuzhiyun rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, MS_TPC, 0xFF, tpc);
154*4882a593Smuzhiyun if (pro_card) {
155*4882a593Smuzhiyun rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, MS_SECTOR_CNT_H,
156*4882a593Smuzhiyun 0xFF, (u8)(sec_cnt >> 8));
157*4882a593Smuzhiyun rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, MS_SECTOR_CNT_L,
158*4882a593Smuzhiyun 0xFF, (u8)sec_cnt);
159*4882a593Smuzhiyun }
160*4882a593Smuzhiyun rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, MS_TRANS_CFG, 0xFF, cfg);
161*4882a593Smuzhiyun
162*4882a593Smuzhiyun rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, IRQSTAT0,
163*4882a593Smuzhiyun DMA_DONE_INT, DMA_DONE_INT);
164*4882a593Smuzhiyun rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, DMATC3, 0xFF, (u8)(length >> 24));
165*4882a593Smuzhiyun rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, DMATC2, 0xFF, (u8)(length >> 16));
166*4882a593Smuzhiyun rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, DMATC1, 0xFF, (u8)(length >> 8));
167*4882a593Smuzhiyun rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, DMATC0, 0xFF, (u8)length);
168*4882a593Smuzhiyun rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, DMACTL,
169*4882a593Smuzhiyun 0x03 | DMA_PACK_SIZE_MASK, dma_dir | DMA_EN | DMA_512);
170*4882a593Smuzhiyun rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_DATA_SOURCE,
171*4882a593Smuzhiyun 0x01, RING_BUFFER);
172*4882a593Smuzhiyun
173*4882a593Smuzhiyun rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, MS_TRANSFER,
174*4882a593Smuzhiyun 0xFF, MS_TRANSFER_START | trans_mode);
175*4882a593Smuzhiyun rtsx_pci_add_cmd(pcr, CHECK_REG_CMD, MS_TRANSFER,
176*4882a593Smuzhiyun MS_TRANSFER_END, MS_TRANSFER_END);
177*4882a593Smuzhiyun
178*4882a593Smuzhiyun rtsx_pci_send_cmd_no_wait(pcr);
179*4882a593Smuzhiyun
180*4882a593Smuzhiyun err = rtsx_pci_transfer_data(pcr, sg, 1, data_dir == READ, 10000);
181*4882a593Smuzhiyun if (err < 0) {
182*4882a593Smuzhiyun ms_clear_error(host);
183*4882a593Smuzhiyun return err;
184*4882a593Smuzhiyun }
185*4882a593Smuzhiyun
186*4882a593Smuzhiyun rtsx_pci_read_register(pcr, MS_TRANS_CFG, &val);
187*4882a593Smuzhiyun if (pro_card) {
188*4882a593Smuzhiyun if (val & (MS_INT_CMDNK | MS_INT_ERR |
189*4882a593Smuzhiyun MS_CRC16_ERR | MS_RDY_TIMEOUT))
190*4882a593Smuzhiyun return -EIO;
191*4882a593Smuzhiyun } else {
192*4882a593Smuzhiyun if (val & (MS_CRC16_ERR | MS_RDY_TIMEOUT))
193*4882a593Smuzhiyun return -EIO;
194*4882a593Smuzhiyun }
195*4882a593Smuzhiyun
196*4882a593Smuzhiyun return 0;
197*4882a593Smuzhiyun }
198*4882a593Smuzhiyun
ms_write_bytes(struct realtek_pci_ms * host,u8 tpc,u8 cfg,u8 cnt,u8 * data,u8 * int_reg)199*4882a593Smuzhiyun static int ms_write_bytes(struct realtek_pci_ms *host, u8 tpc,
200*4882a593Smuzhiyun u8 cfg, u8 cnt, u8 *data, u8 *int_reg)
201*4882a593Smuzhiyun {
202*4882a593Smuzhiyun struct rtsx_pcr *pcr = host->pcr;
203*4882a593Smuzhiyun int err, i;
204*4882a593Smuzhiyun
205*4882a593Smuzhiyun dev_dbg(ms_dev(host), "%s: tpc = 0x%02x\n", __func__, tpc);
206*4882a593Smuzhiyun
207*4882a593Smuzhiyun if (!data)
208*4882a593Smuzhiyun return -EINVAL;
209*4882a593Smuzhiyun
210*4882a593Smuzhiyun rtsx_pci_init_cmd(pcr);
211*4882a593Smuzhiyun
212*4882a593Smuzhiyun for (i = 0; i < cnt; i++)
213*4882a593Smuzhiyun rtsx_pci_add_cmd(pcr, WRITE_REG_CMD,
214*4882a593Smuzhiyun PPBUF_BASE2 + i, 0xFF, data[i]);
215*4882a593Smuzhiyun if (cnt % 2)
216*4882a593Smuzhiyun rtsx_pci_add_cmd(pcr, WRITE_REG_CMD,
217*4882a593Smuzhiyun PPBUF_BASE2 + i, 0xFF, 0xFF);
218*4882a593Smuzhiyun
219*4882a593Smuzhiyun rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, MS_TPC, 0xFF, tpc);
220*4882a593Smuzhiyun rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, MS_BYTE_CNT, 0xFF, cnt);
221*4882a593Smuzhiyun rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, MS_TRANS_CFG, 0xFF, cfg);
222*4882a593Smuzhiyun rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_DATA_SOURCE,
223*4882a593Smuzhiyun 0x01, PINGPONG_BUFFER);
224*4882a593Smuzhiyun
225*4882a593Smuzhiyun rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, MS_TRANSFER,
226*4882a593Smuzhiyun 0xFF, MS_TRANSFER_START | MS_TM_WRITE_BYTES);
227*4882a593Smuzhiyun rtsx_pci_add_cmd(pcr, CHECK_REG_CMD, MS_TRANSFER,
228*4882a593Smuzhiyun MS_TRANSFER_END, MS_TRANSFER_END);
229*4882a593Smuzhiyun if (int_reg)
230*4882a593Smuzhiyun rtsx_pci_add_cmd(pcr, READ_REG_CMD, MS_TRANS_CFG, 0, 0);
231*4882a593Smuzhiyun
232*4882a593Smuzhiyun err = rtsx_pci_send_cmd(pcr, 5000);
233*4882a593Smuzhiyun if (err < 0) {
234*4882a593Smuzhiyun u8 val;
235*4882a593Smuzhiyun
236*4882a593Smuzhiyun rtsx_pci_read_register(pcr, MS_TRANS_CFG, &val);
237*4882a593Smuzhiyun dev_dbg(ms_dev(host), "MS_TRANS_CFG: 0x%02x\n", val);
238*4882a593Smuzhiyun
239*4882a593Smuzhiyun if (int_reg)
240*4882a593Smuzhiyun *int_reg = val & 0x0F;
241*4882a593Smuzhiyun
242*4882a593Smuzhiyun ms_print_debug_regs(host);
243*4882a593Smuzhiyun
244*4882a593Smuzhiyun ms_clear_error(host);
245*4882a593Smuzhiyun
246*4882a593Smuzhiyun if (!(tpc & 0x08)) {
247*4882a593Smuzhiyun if (val & MS_CRC16_ERR)
248*4882a593Smuzhiyun return -EIO;
249*4882a593Smuzhiyun } else {
250*4882a593Smuzhiyun if (!(val & 0x80)) {
251*4882a593Smuzhiyun if (val & (MS_INT_ERR | MS_INT_CMDNK))
252*4882a593Smuzhiyun return -EIO;
253*4882a593Smuzhiyun }
254*4882a593Smuzhiyun }
255*4882a593Smuzhiyun
256*4882a593Smuzhiyun return -ETIMEDOUT;
257*4882a593Smuzhiyun }
258*4882a593Smuzhiyun
259*4882a593Smuzhiyun if (int_reg) {
260*4882a593Smuzhiyun u8 *ptr = rtsx_pci_get_cmd_data(pcr) + 1;
261*4882a593Smuzhiyun *int_reg = *ptr & 0x0F;
262*4882a593Smuzhiyun }
263*4882a593Smuzhiyun
264*4882a593Smuzhiyun return 0;
265*4882a593Smuzhiyun }
266*4882a593Smuzhiyun
ms_read_bytes(struct realtek_pci_ms * host,u8 tpc,u8 cfg,u8 cnt,u8 * data,u8 * int_reg)267*4882a593Smuzhiyun static int ms_read_bytes(struct realtek_pci_ms *host, u8 tpc,
268*4882a593Smuzhiyun u8 cfg, u8 cnt, u8 *data, u8 *int_reg)
269*4882a593Smuzhiyun {
270*4882a593Smuzhiyun struct rtsx_pcr *pcr = host->pcr;
271*4882a593Smuzhiyun int err, i;
272*4882a593Smuzhiyun u8 *ptr;
273*4882a593Smuzhiyun
274*4882a593Smuzhiyun dev_dbg(ms_dev(host), "%s: tpc = 0x%02x\n", __func__, tpc);
275*4882a593Smuzhiyun
276*4882a593Smuzhiyun if (!data)
277*4882a593Smuzhiyun return -EINVAL;
278*4882a593Smuzhiyun
279*4882a593Smuzhiyun rtsx_pci_init_cmd(pcr);
280*4882a593Smuzhiyun
281*4882a593Smuzhiyun rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, MS_TPC, 0xFF, tpc);
282*4882a593Smuzhiyun rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, MS_BYTE_CNT, 0xFF, cnt);
283*4882a593Smuzhiyun rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, MS_TRANS_CFG, 0xFF, cfg);
284*4882a593Smuzhiyun rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_DATA_SOURCE,
285*4882a593Smuzhiyun 0x01, PINGPONG_BUFFER);
286*4882a593Smuzhiyun
287*4882a593Smuzhiyun rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, MS_TRANSFER,
288*4882a593Smuzhiyun 0xFF, MS_TRANSFER_START | MS_TM_READ_BYTES);
289*4882a593Smuzhiyun rtsx_pci_add_cmd(pcr, CHECK_REG_CMD, MS_TRANSFER,
290*4882a593Smuzhiyun MS_TRANSFER_END, MS_TRANSFER_END);
291*4882a593Smuzhiyun for (i = 0; i < cnt - 1; i++)
292*4882a593Smuzhiyun rtsx_pci_add_cmd(pcr, READ_REG_CMD, PPBUF_BASE2 + i, 0, 0);
293*4882a593Smuzhiyun if (cnt % 2)
294*4882a593Smuzhiyun rtsx_pci_add_cmd(pcr, READ_REG_CMD, PPBUF_BASE2 + cnt, 0, 0);
295*4882a593Smuzhiyun else
296*4882a593Smuzhiyun rtsx_pci_add_cmd(pcr, READ_REG_CMD,
297*4882a593Smuzhiyun PPBUF_BASE2 + cnt - 1, 0, 0);
298*4882a593Smuzhiyun if (int_reg)
299*4882a593Smuzhiyun rtsx_pci_add_cmd(pcr, READ_REG_CMD, MS_TRANS_CFG, 0, 0);
300*4882a593Smuzhiyun
301*4882a593Smuzhiyun err = rtsx_pci_send_cmd(pcr, 5000);
302*4882a593Smuzhiyun if (err < 0) {
303*4882a593Smuzhiyun u8 val;
304*4882a593Smuzhiyun
305*4882a593Smuzhiyun rtsx_pci_read_register(pcr, MS_TRANS_CFG, &val);
306*4882a593Smuzhiyun dev_dbg(ms_dev(host), "MS_TRANS_CFG: 0x%02x\n", val);
307*4882a593Smuzhiyun
308*4882a593Smuzhiyun if (int_reg)
309*4882a593Smuzhiyun *int_reg = val & 0x0F;
310*4882a593Smuzhiyun
311*4882a593Smuzhiyun ms_print_debug_regs(host);
312*4882a593Smuzhiyun
313*4882a593Smuzhiyun ms_clear_error(host);
314*4882a593Smuzhiyun
315*4882a593Smuzhiyun if (!(tpc & 0x08)) {
316*4882a593Smuzhiyun if (val & MS_CRC16_ERR)
317*4882a593Smuzhiyun return -EIO;
318*4882a593Smuzhiyun } else {
319*4882a593Smuzhiyun if (!(val & 0x80)) {
320*4882a593Smuzhiyun if (val & (MS_INT_ERR | MS_INT_CMDNK))
321*4882a593Smuzhiyun return -EIO;
322*4882a593Smuzhiyun }
323*4882a593Smuzhiyun }
324*4882a593Smuzhiyun
325*4882a593Smuzhiyun return -ETIMEDOUT;
326*4882a593Smuzhiyun }
327*4882a593Smuzhiyun
328*4882a593Smuzhiyun ptr = rtsx_pci_get_cmd_data(pcr) + 1;
329*4882a593Smuzhiyun for (i = 0; i < cnt; i++)
330*4882a593Smuzhiyun data[i] = *ptr++;
331*4882a593Smuzhiyun
332*4882a593Smuzhiyun if (int_reg)
333*4882a593Smuzhiyun *int_reg = *ptr & 0x0F;
334*4882a593Smuzhiyun
335*4882a593Smuzhiyun return 0;
336*4882a593Smuzhiyun }
337*4882a593Smuzhiyun
rtsx_pci_ms_issue_cmd(struct realtek_pci_ms * host)338*4882a593Smuzhiyun static int rtsx_pci_ms_issue_cmd(struct realtek_pci_ms *host)
339*4882a593Smuzhiyun {
340*4882a593Smuzhiyun struct memstick_request *req = host->req;
341*4882a593Smuzhiyun int err = 0;
342*4882a593Smuzhiyun u8 cfg = 0, int_reg;
343*4882a593Smuzhiyun
344*4882a593Smuzhiyun dev_dbg(ms_dev(host), "%s\n", __func__);
345*4882a593Smuzhiyun
346*4882a593Smuzhiyun if (req->need_card_int) {
347*4882a593Smuzhiyun if (host->ifmode != MEMSTICK_SERIAL)
348*4882a593Smuzhiyun cfg = WAIT_INT;
349*4882a593Smuzhiyun }
350*4882a593Smuzhiyun
351*4882a593Smuzhiyun if (req->long_data) {
352*4882a593Smuzhiyun err = ms_transfer_data(host, req->data_dir,
353*4882a593Smuzhiyun req->tpc, cfg, &(req->sg));
354*4882a593Smuzhiyun } else {
355*4882a593Smuzhiyun if (req->data_dir == READ) {
356*4882a593Smuzhiyun err = ms_read_bytes(host, req->tpc, cfg,
357*4882a593Smuzhiyun req->data_len, req->data, &int_reg);
358*4882a593Smuzhiyun } else {
359*4882a593Smuzhiyun err = ms_write_bytes(host, req->tpc, cfg,
360*4882a593Smuzhiyun req->data_len, req->data, &int_reg);
361*4882a593Smuzhiyun }
362*4882a593Smuzhiyun }
363*4882a593Smuzhiyun if (err < 0)
364*4882a593Smuzhiyun return err;
365*4882a593Smuzhiyun
366*4882a593Smuzhiyun if (req->need_card_int && (host->ifmode == MEMSTICK_SERIAL)) {
367*4882a593Smuzhiyun err = ms_read_bytes(host, MS_TPC_GET_INT,
368*4882a593Smuzhiyun NO_WAIT_INT, 1, &int_reg, NULL);
369*4882a593Smuzhiyun if (err < 0)
370*4882a593Smuzhiyun return err;
371*4882a593Smuzhiyun }
372*4882a593Smuzhiyun
373*4882a593Smuzhiyun if (req->need_card_int) {
374*4882a593Smuzhiyun dev_dbg(ms_dev(host), "int_reg: 0x%02x\n", int_reg);
375*4882a593Smuzhiyun
376*4882a593Smuzhiyun if (int_reg & MS_INT_CMDNK)
377*4882a593Smuzhiyun req->int_reg |= MEMSTICK_INT_CMDNAK;
378*4882a593Smuzhiyun if (int_reg & MS_INT_BREQ)
379*4882a593Smuzhiyun req->int_reg |= MEMSTICK_INT_BREQ;
380*4882a593Smuzhiyun if (int_reg & MS_INT_ERR)
381*4882a593Smuzhiyun req->int_reg |= MEMSTICK_INT_ERR;
382*4882a593Smuzhiyun if (int_reg & MS_INT_CED)
383*4882a593Smuzhiyun req->int_reg |= MEMSTICK_INT_CED;
384*4882a593Smuzhiyun }
385*4882a593Smuzhiyun
386*4882a593Smuzhiyun return 0;
387*4882a593Smuzhiyun }
388*4882a593Smuzhiyun
rtsx_pci_ms_handle_req(struct work_struct * work)389*4882a593Smuzhiyun static void rtsx_pci_ms_handle_req(struct work_struct *work)
390*4882a593Smuzhiyun {
391*4882a593Smuzhiyun struct realtek_pci_ms *host = container_of(work,
392*4882a593Smuzhiyun struct realtek_pci_ms, handle_req);
393*4882a593Smuzhiyun struct rtsx_pcr *pcr = host->pcr;
394*4882a593Smuzhiyun struct memstick_host *msh = host->msh;
395*4882a593Smuzhiyun int rc;
396*4882a593Smuzhiyun
397*4882a593Smuzhiyun mutex_lock(&pcr->pcr_mutex);
398*4882a593Smuzhiyun
399*4882a593Smuzhiyun rtsx_pci_start_run(pcr);
400*4882a593Smuzhiyun
401*4882a593Smuzhiyun rtsx_pci_switch_clock(host->pcr, host->clock, host->ssc_depth,
402*4882a593Smuzhiyun false, true, false);
403*4882a593Smuzhiyun rtsx_pci_write_register(pcr, CARD_SELECT, 0x07, MS_MOD_SEL);
404*4882a593Smuzhiyun rtsx_pci_write_register(pcr, CARD_SHARE_MODE,
405*4882a593Smuzhiyun CARD_SHARE_MASK, CARD_SHARE_48_MS);
406*4882a593Smuzhiyun
407*4882a593Smuzhiyun if (!host->req) {
408*4882a593Smuzhiyun do {
409*4882a593Smuzhiyun rc = memstick_next_req(msh, &host->req);
410*4882a593Smuzhiyun dev_dbg(ms_dev(host), "next req %d\n", rc);
411*4882a593Smuzhiyun
412*4882a593Smuzhiyun if (!rc)
413*4882a593Smuzhiyun host->req->error = rtsx_pci_ms_issue_cmd(host);
414*4882a593Smuzhiyun } while (!rc);
415*4882a593Smuzhiyun }
416*4882a593Smuzhiyun
417*4882a593Smuzhiyun mutex_unlock(&pcr->pcr_mutex);
418*4882a593Smuzhiyun }
419*4882a593Smuzhiyun
rtsx_pci_ms_request(struct memstick_host * msh)420*4882a593Smuzhiyun static void rtsx_pci_ms_request(struct memstick_host *msh)
421*4882a593Smuzhiyun {
422*4882a593Smuzhiyun struct realtek_pci_ms *host = memstick_priv(msh);
423*4882a593Smuzhiyun
424*4882a593Smuzhiyun dev_dbg(ms_dev(host), "--> %s\n", __func__);
425*4882a593Smuzhiyun
426*4882a593Smuzhiyun if (rtsx_pci_card_exclusive_check(host->pcr, RTSX_MS_CARD))
427*4882a593Smuzhiyun return;
428*4882a593Smuzhiyun
429*4882a593Smuzhiyun schedule_work(&host->handle_req);
430*4882a593Smuzhiyun }
431*4882a593Smuzhiyun
rtsx_pci_ms_set_param(struct memstick_host * msh,enum memstick_param param,int value)432*4882a593Smuzhiyun static int rtsx_pci_ms_set_param(struct memstick_host *msh,
433*4882a593Smuzhiyun enum memstick_param param, int value)
434*4882a593Smuzhiyun {
435*4882a593Smuzhiyun struct realtek_pci_ms *host = memstick_priv(msh);
436*4882a593Smuzhiyun struct rtsx_pcr *pcr = host->pcr;
437*4882a593Smuzhiyun unsigned int clock = 0;
438*4882a593Smuzhiyun u8 ssc_depth = 0;
439*4882a593Smuzhiyun int err;
440*4882a593Smuzhiyun
441*4882a593Smuzhiyun dev_dbg(ms_dev(host), "%s: param = %d, value = %d\n",
442*4882a593Smuzhiyun __func__, param, value);
443*4882a593Smuzhiyun
444*4882a593Smuzhiyun err = rtsx_pci_card_exclusive_check(host->pcr, RTSX_MS_CARD);
445*4882a593Smuzhiyun if (err)
446*4882a593Smuzhiyun return err;
447*4882a593Smuzhiyun
448*4882a593Smuzhiyun switch (param) {
449*4882a593Smuzhiyun case MEMSTICK_POWER:
450*4882a593Smuzhiyun if (value == MEMSTICK_POWER_ON)
451*4882a593Smuzhiyun err = ms_power_on(host);
452*4882a593Smuzhiyun else if (value == MEMSTICK_POWER_OFF)
453*4882a593Smuzhiyun err = ms_power_off(host);
454*4882a593Smuzhiyun else
455*4882a593Smuzhiyun return -EINVAL;
456*4882a593Smuzhiyun break;
457*4882a593Smuzhiyun
458*4882a593Smuzhiyun case MEMSTICK_INTERFACE:
459*4882a593Smuzhiyun if (value == MEMSTICK_SERIAL) {
460*4882a593Smuzhiyun clock = 19000000;
461*4882a593Smuzhiyun ssc_depth = RTSX_SSC_DEPTH_500K;
462*4882a593Smuzhiyun
463*4882a593Smuzhiyun err = rtsx_pci_write_register(pcr, MS_CFG, 0x58,
464*4882a593Smuzhiyun MS_BUS_WIDTH_1 | PUSH_TIME_DEFAULT);
465*4882a593Smuzhiyun if (err < 0)
466*4882a593Smuzhiyun return err;
467*4882a593Smuzhiyun } else if (value == MEMSTICK_PAR4) {
468*4882a593Smuzhiyun clock = 39000000;
469*4882a593Smuzhiyun ssc_depth = RTSX_SSC_DEPTH_1M;
470*4882a593Smuzhiyun
471*4882a593Smuzhiyun err = rtsx_pci_write_register(pcr, MS_CFG,
472*4882a593Smuzhiyun 0x58, MS_BUS_WIDTH_4 | PUSH_TIME_ODD);
473*4882a593Smuzhiyun if (err < 0)
474*4882a593Smuzhiyun return err;
475*4882a593Smuzhiyun } else {
476*4882a593Smuzhiyun return -EINVAL;
477*4882a593Smuzhiyun }
478*4882a593Smuzhiyun
479*4882a593Smuzhiyun err = rtsx_pci_switch_clock(pcr, clock,
480*4882a593Smuzhiyun ssc_depth, false, true, false);
481*4882a593Smuzhiyun if (err < 0)
482*4882a593Smuzhiyun return err;
483*4882a593Smuzhiyun
484*4882a593Smuzhiyun host->ssc_depth = ssc_depth;
485*4882a593Smuzhiyun host->clock = clock;
486*4882a593Smuzhiyun host->ifmode = value;
487*4882a593Smuzhiyun break;
488*4882a593Smuzhiyun }
489*4882a593Smuzhiyun
490*4882a593Smuzhiyun return 0;
491*4882a593Smuzhiyun }
492*4882a593Smuzhiyun
493*4882a593Smuzhiyun #ifdef CONFIG_PM
494*4882a593Smuzhiyun
rtsx_pci_ms_suspend(struct platform_device * pdev,pm_message_t state)495*4882a593Smuzhiyun static int rtsx_pci_ms_suspend(struct platform_device *pdev, pm_message_t state)
496*4882a593Smuzhiyun {
497*4882a593Smuzhiyun struct realtek_pci_ms *host = platform_get_drvdata(pdev);
498*4882a593Smuzhiyun struct memstick_host *msh = host->msh;
499*4882a593Smuzhiyun
500*4882a593Smuzhiyun dev_dbg(ms_dev(host), "--> %s\n", __func__);
501*4882a593Smuzhiyun
502*4882a593Smuzhiyun memstick_suspend_host(msh);
503*4882a593Smuzhiyun return 0;
504*4882a593Smuzhiyun }
505*4882a593Smuzhiyun
rtsx_pci_ms_resume(struct platform_device * pdev)506*4882a593Smuzhiyun static int rtsx_pci_ms_resume(struct platform_device *pdev)
507*4882a593Smuzhiyun {
508*4882a593Smuzhiyun struct realtek_pci_ms *host = platform_get_drvdata(pdev);
509*4882a593Smuzhiyun struct memstick_host *msh = host->msh;
510*4882a593Smuzhiyun
511*4882a593Smuzhiyun dev_dbg(ms_dev(host), "--> %s\n", __func__);
512*4882a593Smuzhiyun
513*4882a593Smuzhiyun memstick_resume_host(msh);
514*4882a593Smuzhiyun return 0;
515*4882a593Smuzhiyun }
516*4882a593Smuzhiyun
517*4882a593Smuzhiyun #else /* CONFIG_PM */
518*4882a593Smuzhiyun
519*4882a593Smuzhiyun #define rtsx_pci_ms_suspend NULL
520*4882a593Smuzhiyun #define rtsx_pci_ms_resume NULL
521*4882a593Smuzhiyun
522*4882a593Smuzhiyun #endif /* CONFIG_PM */
523*4882a593Smuzhiyun
rtsx_pci_ms_card_event(struct platform_device * pdev)524*4882a593Smuzhiyun static void rtsx_pci_ms_card_event(struct platform_device *pdev)
525*4882a593Smuzhiyun {
526*4882a593Smuzhiyun struct realtek_pci_ms *host = platform_get_drvdata(pdev);
527*4882a593Smuzhiyun
528*4882a593Smuzhiyun memstick_detect_change(host->msh);
529*4882a593Smuzhiyun }
530*4882a593Smuzhiyun
rtsx_pci_ms_drv_probe(struct platform_device * pdev)531*4882a593Smuzhiyun static int rtsx_pci_ms_drv_probe(struct platform_device *pdev)
532*4882a593Smuzhiyun {
533*4882a593Smuzhiyun struct memstick_host *msh;
534*4882a593Smuzhiyun struct realtek_pci_ms *host;
535*4882a593Smuzhiyun struct rtsx_pcr *pcr;
536*4882a593Smuzhiyun struct pcr_handle *handle = pdev->dev.platform_data;
537*4882a593Smuzhiyun int rc;
538*4882a593Smuzhiyun
539*4882a593Smuzhiyun if (!handle)
540*4882a593Smuzhiyun return -ENXIO;
541*4882a593Smuzhiyun
542*4882a593Smuzhiyun pcr = handle->pcr;
543*4882a593Smuzhiyun if (!pcr)
544*4882a593Smuzhiyun return -ENXIO;
545*4882a593Smuzhiyun
546*4882a593Smuzhiyun dev_dbg(&(pdev->dev),
547*4882a593Smuzhiyun ": Realtek PCI-E Memstick controller found\n");
548*4882a593Smuzhiyun
549*4882a593Smuzhiyun msh = memstick_alloc_host(sizeof(*host), &pdev->dev);
550*4882a593Smuzhiyun if (!msh)
551*4882a593Smuzhiyun return -ENOMEM;
552*4882a593Smuzhiyun
553*4882a593Smuzhiyun host = memstick_priv(msh);
554*4882a593Smuzhiyun host->pcr = pcr;
555*4882a593Smuzhiyun host->msh = msh;
556*4882a593Smuzhiyun host->pdev = pdev;
557*4882a593Smuzhiyun platform_set_drvdata(pdev, host);
558*4882a593Smuzhiyun pcr->slots[RTSX_MS_CARD].p_dev = pdev;
559*4882a593Smuzhiyun pcr->slots[RTSX_MS_CARD].card_event = rtsx_pci_ms_card_event;
560*4882a593Smuzhiyun
561*4882a593Smuzhiyun mutex_init(&host->host_mutex);
562*4882a593Smuzhiyun
563*4882a593Smuzhiyun INIT_WORK(&host->handle_req, rtsx_pci_ms_handle_req);
564*4882a593Smuzhiyun msh->request = rtsx_pci_ms_request;
565*4882a593Smuzhiyun msh->set_param = rtsx_pci_ms_set_param;
566*4882a593Smuzhiyun msh->caps = MEMSTICK_CAP_PAR4;
567*4882a593Smuzhiyun
568*4882a593Smuzhiyun rc = memstick_add_host(msh);
569*4882a593Smuzhiyun if (rc) {
570*4882a593Smuzhiyun memstick_free_host(msh);
571*4882a593Smuzhiyun return rc;
572*4882a593Smuzhiyun }
573*4882a593Smuzhiyun
574*4882a593Smuzhiyun return 0;
575*4882a593Smuzhiyun }
576*4882a593Smuzhiyun
rtsx_pci_ms_drv_remove(struct platform_device * pdev)577*4882a593Smuzhiyun static int rtsx_pci_ms_drv_remove(struct platform_device *pdev)
578*4882a593Smuzhiyun {
579*4882a593Smuzhiyun struct realtek_pci_ms *host = platform_get_drvdata(pdev);
580*4882a593Smuzhiyun struct rtsx_pcr *pcr;
581*4882a593Smuzhiyun struct memstick_host *msh;
582*4882a593Smuzhiyun int rc;
583*4882a593Smuzhiyun
584*4882a593Smuzhiyun if (!host)
585*4882a593Smuzhiyun return 0;
586*4882a593Smuzhiyun
587*4882a593Smuzhiyun pcr = host->pcr;
588*4882a593Smuzhiyun pcr->slots[RTSX_MS_CARD].p_dev = NULL;
589*4882a593Smuzhiyun pcr->slots[RTSX_MS_CARD].card_event = NULL;
590*4882a593Smuzhiyun msh = host->msh;
591*4882a593Smuzhiyun host->eject = true;
592*4882a593Smuzhiyun cancel_work_sync(&host->handle_req);
593*4882a593Smuzhiyun
594*4882a593Smuzhiyun mutex_lock(&host->host_mutex);
595*4882a593Smuzhiyun if (host->req) {
596*4882a593Smuzhiyun dev_dbg(&(pdev->dev),
597*4882a593Smuzhiyun "%s: Controller removed during transfer\n",
598*4882a593Smuzhiyun dev_name(&msh->dev));
599*4882a593Smuzhiyun
600*4882a593Smuzhiyun rtsx_pci_complete_unfinished_transfer(pcr);
601*4882a593Smuzhiyun
602*4882a593Smuzhiyun host->req->error = -ENOMEDIUM;
603*4882a593Smuzhiyun do {
604*4882a593Smuzhiyun rc = memstick_next_req(msh, &host->req);
605*4882a593Smuzhiyun if (!rc)
606*4882a593Smuzhiyun host->req->error = -ENOMEDIUM;
607*4882a593Smuzhiyun } while (!rc);
608*4882a593Smuzhiyun }
609*4882a593Smuzhiyun mutex_unlock(&host->host_mutex);
610*4882a593Smuzhiyun
611*4882a593Smuzhiyun memstick_remove_host(msh);
612*4882a593Smuzhiyun memstick_free_host(msh);
613*4882a593Smuzhiyun
614*4882a593Smuzhiyun dev_dbg(&(pdev->dev),
615*4882a593Smuzhiyun ": Realtek PCI-E Memstick controller has been removed\n");
616*4882a593Smuzhiyun
617*4882a593Smuzhiyun return 0;
618*4882a593Smuzhiyun }
619*4882a593Smuzhiyun
620*4882a593Smuzhiyun static struct platform_device_id rtsx_pci_ms_ids[] = {
621*4882a593Smuzhiyun {
622*4882a593Smuzhiyun .name = DRV_NAME_RTSX_PCI_MS,
623*4882a593Smuzhiyun }, {
624*4882a593Smuzhiyun /* sentinel */
625*4882a593Smuzhiyun }
626*4882a593Smuzhiyun };
627*4882a593Smuzhiyun MODULE_DEVICE_TABLE(platform, rtsx_pci_ms_ids);
628*4882a593Smuzhiyun
629*4882a593Smuzhiyun static struct platform_driver rtsx_pci_ms_driver = {
630*4882a593Smuzhiyun .probe = rtsx_pci_ms_drv_probe,
631*4882a593Smuzhiyun .remove = rtsx_pci_ms_drv_remove,
632*4882a593Smuzhiyun .id_table = rtsx_pci_ms_ids,
633*4882a593Smuzhiyun .suspend = rtsx_pci_ms_suspend,
634*4882a593Smuzhiyun .resume = rtsx_pci_ms_resume,
635*4882a593Smuzhiyun .driver = {
636*4882a593Smuzhiyun .name = DRV_NAME_RTSX_PCI_MS,
637*4882a593Smuzhiyun },
638*4882a593Smuzhiyun };
639*4882a593Smuzhiyun module_platform_driver(rtsx_pci_ms_driver);
640*4882a593Smuzhiyun
641*4882a593Smuzhiyun MODULE_LICENSE("GPL");
642*4882a593Smuzhiyun MODULE_AUTHOR("Wei WANG <wei_wang@realsil.com.cn>");
643*4882a593Smuzhiyun MODULE_DESCRIPTION("Realtek PCI-E Memstick Card Host Driver");
644