xref: /OK3568_Linux_fs/kernel/drivers/memstick/host/rtsx_pci_ms.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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