xref: /OK3568_Linux_fs/kernel/drivers/misc/rk_scr.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * Driver for Rockchip Smart Card Reader Controller
3*4882a593Smuzhiyun  *
4*4882a593Smuzhiyun  * Copyright (C) 2012-2016 ROCKCHIP, Inc.
5*4882a593Smuzhiyun  *
6*4882a593Smuzhiyun  * This software is licensed under the terms of the GNU General Public
7*4882a593Smuzhiyun  * License version 2, as published by the Free Software Foundation, and
8*4882a593Smuzhiyun  * may be copied, distributed, and modified under those terms.
9*4882a593Smuzhiyun  *
10*4882a593Smuzhiyun  * This program is distributed in the hope that it will be useful,
11*4882a593Smuzhiyun  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12*4882a593Smuzhiyun  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13*4882a593Smuzhiyun  * GNU General Public License for more details.
14*4882a593Smuzhiyun  */
15*4882a593Smuzhiyun 
16*4882a593Smuzhiyun #include <linux/list.h>
17*4882a593Smuzhiyun #include <linux/kernel.h>
18*4882a593Smuzhiyun #include <linux/clk.h>
19*4882a593Smuzhiyun #include <linux/io.h>
20*4882a593Smuzhiyun #include <linux/module.h>
21*4882a593Smuzhiyun #include <linux/of.h>
22*4882a593Smuzhiyun #include <linux/of_device.h>
23*4882a593Smuzhiyun #include <linux/platform_device.h>
24*4882a593Smuzhiyun #include <linux/time.h>
25*4882a593Smuzhiyun #include <linux/delay.h>
26*4882a593Smuzhiyun #include <linux/interrupt.h>
27*4882a593Smuzhiyun #include <linux/slab.h>
28*4882a593Smuzhiyun #include <linux/kobject.h>
29*4882a593Smuzhiyun #include <linux/sysfs.h>
30*4882a593Smuzhiyun #include <linux/kthread.h>
31*4882a593Smuzhiyun 
32*4882a593Smuzhiyun #include "rk_scr.h"
33*4882a593Smuzhiyun 
34*4882a593Smuzhiyun #undef DEBUG_RK_SCR
35*4882a593Smuzhiyun #define DEBUG_RK_SCR 1
36*4882a593Smuzhiyun 
37*4882a593Smuzhiyun #if DEBUG_RK_SCR
38*4882a593Smuzhiyun #define DAL_LOGV(x...) pr_info("RK_SCR: "x)
39*4882a593Smuzhiyun #else
40*4882a593Smuzhiyun #define DAL_LOGV(x...) do { } while (0)
41*4882a593Smuzhiyun #endif
42*4882a593Smuzhiyun 
43*4882a593Smuzhiyun #define SMC_DEFAULT_TIMEOUT		2000 /*ms*/
44*4882a593Smuzhiyun #define SMC_RECEIVE_BUF_LEN		(64 * 1024)
45*4882a593Smuzhiyun 
46*4882a593Smuzhiyun struct rk_scr_device {
47*4882a593Smuzhiyun 	int irq;
48*4882a593Smuzhiyun 	struct clk *clk_scr;
49*4882a593Smuzhiyun 	void __iomem *regs;
50*4882a593Smuzhiyun 	struct scr_chip_info chip_info[RK_SCR_NUM];
51*4882a593Smuzhiyun 	struct rk_scr scr[RK_SCR_NUM];
52*4882a593Smuzhiyun 	struct completion is_done;
53*4882a593Smuzhiyun 	struct mutex scr_mutex; /* mutex for scr operation */
54*4882a593Smuzhiyun 	unsigned char *recv_buffer;
55*4882a593Smuzhiyun 	unsigned recv_data_count;
56*4882a593Smuzhiyun 	unsigned recv_data_offset;
57*4882a593Smuzhiyun 	unsigned char atr_buffer[SMC_ATR_MAX_LENGTH];
58*4882a593Smuzhiyun 	unsigned char atr_length;
59*4882a593Smuzhiyun };
60*4882a593Smuzhiyun 
61*4882a593Smuzhiyun static struct rk_scr_device *rk_scr;
62*4882a593Smuzhiyun 
to_rk_scr(int id)63*4882a593Smuzhiyun static struct rk_scr *to_rk_scr(int id)
64*4882a593Smuzhiyun {
65*4882a593Smuzhiyun 	if (id < RK_SCR_NUM)
66*4882a593Smuzhiyun 		return &rk_scr->scr[id];
67*4882a593Smuzhiyun 
68*4882a593Smuzhiyun 	return NULL;
69*4882a593Smuzhiyun }
70*4882a593Smuzhiyun 
to_opened_rk_scr(int id)71*4882a593Smuzhiyun static struct rk_scr *to_opened_rk_scr(int id)
72*4882a593Smuzhiyun {
73*4882a593Smuzhiyun 	struct rk_scr *scr;
74*4882a593Smuzhiyun 
75*4882a593Smuzhiyun 	scr = to_rk_scr(id);
76*4882a593Smuzhiyun 
77*4882a593Smuzhiyun 	if (scr && scr->is_open)
78*4882a593Smuzhiyun 		return scr;
79*4882a593Smuzhiyun 
80*4882a593Smuzhiyun 	return NULL;
81*4882a593Smuzhiyun }
82*4882a593Smuzhiyun 
rk_scr_deactive(struct rk_scr * scr)83*4882a593Smuzhiyun static void rk_scr_deactive(struct rk_scr *scr)
84*4882a593Smuzhiyun {
85*4882a593Smuzhiyun 	struct scr_reg_t *scr_reg = scr->hw->reg_base;
86*4882a593Smuzhiyun 
87*4882a593Smuzhiyun 	DAL_LOGV("Deactive card\n");
88*4882a593Smuzhiyun 	scr_reg->CTRL2 |= DEACT;
89*4882a593Smuzhiyun 	scr_reg->CTRL1 = 0;
90*4882a593Smuzhiyun 	scr->is_active = false;
91*4882a593Smuzhiyun }
92*4882a593Smuzhiyun 
rk_scr_set_clk(struct rk_scr * scr)93*4882a593Smuzhiyun static void rk_scr_set_clk(struct rk_scr *scr)
94*4882a593Smuzhiyun {
95*4882a593Smuzhiyun 	struct scr_reg_t *scr_reg = scr->hw->reg_base;
96*4882a593Smuzhiyun 	unsigned int freq_mhz;
97*4882a593Smuzhiyun 
98*4882a593Smuzhiyun 	freq_mhz = clk_get_rate(scr->clk) / 1000 / 1000;
99*4882a593Smuzhiyun 	DAL_LOGV("freq_mhz = %d\n", freq_mhz);
100*4882a593Smuzhiyun 	scr_reg->CGSCDIV = ((2 * freq_mhz / 13 - 1)
101*4882a593Smuzhiyun 				+ (freq_mhz / 8 - 1) + 1) / 2;
102*4882a593Smuzhiyun 	DAL_LOGV("scr_reg->CGSCDIV = %d\n", scr_reg->CGSCDIV);
103*4882a593Smuzhiyun }
104*4882a593Smuzhiyun 
rk_scr_set_work_waitingtime(struct rk_scr * scr,unsigned char wi)105*4882a593Smuzhiyun static void rk_scr_set_work_waitingtime(struct rk_scr *scr,
106*4882a593Smuzhiyun 					unsigned char wi)
107*4882a593Smuzhiyun {
108*4882a593Smuzhiyun 	struct scr_reg_t *scr_reg = scr->hw->reg_base;
109*4882a593Smuzhiyun 	unsigned int wt;
110*4882a593Smuzhiyun 
111*4882a593Smuzhiyun 	DAL_LOGV("WI: %d\n", wi);
112*4882a593Smuzhiyun 	wt = 960 * wi * scr->D;
113*4882a593Smuzhiyun 	scr_reg->C2CLIM = (wt > 0x0FFFF) ? 0x0FFFF : wt;
114*4882a593Smuzhiyun }
115*4882a593Smuzhiyun 
rk_scr_set_etu_duration(struct rk_scr * scr,unsigned int F,unsigned int D)116*4882a593Smuzhiyun static void rk_scr_set_etu_duration(struct rk_scr *scr,	unsigned int F,
117*4882a593Smuzhiyun 				    unsigned int D)
118*4882a593Smuzhiyun {
119*4882a593Smuzhiyun 	struct scr_reg_t *scr_reg = scr->hw->reg_base;
120*4882a593Smuzhiyun 
121*4882a593Smuzhiyun 	DAL_LOGV("Set Etu F: %d D: %d\n", F, D);
122*4882a593Smuzhiyun 
123*4882a593Smuzhiyun 	scr->F = F;
124*4882a593Smuzhiyun 	scr->D = D;
125*4882a593Smuzhiyun 	scr_reg->CGBITDIV = (scr_reg->CGSCDIV + 1) * (F / D) - 1;
126*4882a593Smuzhiyun 	DAL_LOGV("scr_reg->CGBITDIV = %d\n", scr_reg->CGBITDIV);
127*4882a593Smuzhiyun 	scr_reg->CGBITTUNE = 0;
128*4882a593Smuzhiyun 
129*4882a593Smuzhiyun 	rk_scr_set_work_waitingtime(scr, 10);
130*4882a593Smuzhiyun }
131*4882a593Smuzhiyun 
rk_scr_set_scr_voltage(struct rk_scr * scr,enum hal_scr_voltage_e level)132*4882a593Smuzhiyun static void rk_scr_set_scr_voltage(struct rk_scr *scr,
133*4882a593Smuzhiyun 				   enum hal_scr_voltage_e level)
134*4882a593Smuzhiyun {
135*4882a593Smuzhiyun 	struct scr_reg_t *scr_reg = scr->hw->reg_base;
136*4882a593Smuzhiyun 
137*4882a593Smuzhiyun 	scr_reg->CTRL2 = 0;
138*4882a593Smuzhiyun 
139*4882a593Smuzhiyun 	switch (level) {
140*4882a593Smuzhiyun 	case HAL_SCR_VOLTAGE_CLASS_A:
141*4882a593Smuzhiyun 		scr_reg->CTRL2 |= VCC50;
142*4882a593Smuzhiyun 		break;
143*4882a593Smuzhiyun 
144*4882a593Smuzhiyun 	case HAL_SCR_VOLTAGE_CLASS_B:
145*4882a593Smuzhiyun 		scr_reg->CTRL2 |= VCC33;
146*4882a593Smuzhiyun 		break;
147*4882a593Smuzhiyun 
148*4882a593Smuzhiyun 	case HAL_SCR_VOLTAGE_CLASS_C:
149*4882a593Smuzhiyun 		scr_reg->CTRL2 |= VCC18;
150*4882a593Smuzhiyun 		break;
151*4882a593Smuzhiyun 
152*4882a593Smuzhiyun 	case HAL_SCR_VOLTAGE_NULL:
153*4882a593Smuzhiyun 		break;
154*4882a593Smuzhiyun 	}
155*4882a593Smuzhiyun }
156*4882a593Smuzhiyun 
rk_scr_powerdown(struct rk_scr * scr)157*4882a593Smuzhiyun static void rk_scr_powerdown(struct rk_scr *scr)
158*4882a593Smuzhiyun {
159*4882a593Smuzhiyun 	rk_scr_set_scr_voltage(scr, HAL_SCR_VOLTAGE_NULL);
160*4882a593Smuzhiyun }
161*4882a593Smuzhiyun 
rk_scr_set_clockstop_mode(struct rk_scr * scr,enum hal_scr_clock_stop_mode_e mode)162*4882a593Smuzhiyun static void rk_scr_set_clockstop_mode(struct rk_scr *scr,
163*4882a593Smuzhiyun 				      enum hal_scr_clock_stop_mode_e mode)
164*4882a593Smuzhiyun {
165*4882a593Smuzhiyun 	struct scr_reg_t *scr_reg = scr->hw->reg_base;
166*4882a593Smuzhiyun 
167*4882a593Smuzhiyun 	if (mode == HAL_SCR_CLOCK_STOP_L)
168*4882a593Smuzhiyun 		scr_reg->CTRL1 &= ~CLKSTOPVAL;
169*4882a593Smuzhiyun 	else if (mode == HAL_SCR_CLOCK_STOP_H)
170*4882a593Smuzhiyun 		scr_reg->CTRL1 |= CLKSTOPVAL;
171*4882a593Smuzhiyun }
172*4882a593Smuzhiyun 
rk_scr_clock_start(struct rk_scr * scr)173*4882a593Smuzhiyun static void rk_scr_clock_start(struct rk_scr *scr)
174*4882a593Smuzhiyun {
175*4882a593Smuzhiyun 	struct scr_reg_t *scr_reg = scr->hw->reg_base;
176*4882a593Smuzhiyun 	int time_out = 10000;
177*4882a593Smuzhiyun 
178*4882a593Smuzhiyun #ifdef SCR_DEBUG
179*4882a593Smuzhiyun 	scr_reg->INTEN1 = CLKSTOPRUN;
180*4882a593Smuzhiyun #endif
181*4882a593Smuzhiyun 	scr_reg->CTRL1 &= ~CLKSTOP;
182*4882a593Smuzhiyun #ifdef SCR_DEBUG
183*4882a593Smuzhiyun 	if (scr_reg->CTRL1 & CLKSTOP)
184*4882a593Smuzhiyun 		DAL_LOGV("Before clock is Stopped\n");
185*4882a593Smuzhiyun 	else
186*4882a593Smuzhiyun 		DAL_LOGV("Before clock is running\n");
187*4882a593Smuzhiyun #endif
188*4882a593Smuzhiyun 	while ((scr_reg->CTRL1 & CLKSTOP) && (time_out-- > 0))
189*4882a593Smuzhiyun 		usleep_range(100, 110);
190*4882a593Smuzhiyun }
191*4882a593Smuzhiyun 
rk_scr_clock_stop(struct rk_scr * scr)192*4882a593Smuzhiyun static void rk_scr_clock_stop(struct rk_scr *scr)
193*4882a593Smuzhiyun {
194*4882a593Smuzhiyun 	struct scr_reg_t *scr_reg = scr->hw->reg_base;
195*4882a593Smuzhiyun 	int time_out = 10000;
196*4882a593Smuzhiyun 
197*4882a593Smuzhiyun #ifdef SCR_DEBUG
198*4882a593Smuzhiyun 	scr_reg->INTEN1 = CLKSTOPRUN;
199*4882a593Smuzhiyun #endif
200*4882a593Smuzhiyun 	scr_reg->CTRL1 |= CLKSTOP;
201*4882a593Smuzhiyun 	DAL_LOGV("Stop Clock\n");
202*4882a593Smuzhiyun 	if (scr->is_active) {
203*4882a593Smuzhiyun 		while ((!(scr_reg->CTRL1 & CLKSTOP)) && (time_out-- > 0))
204*4882a593Smuzhiyun 			usleep_range(100, 110);
205*4882a593Smuzhiyun 	}
206*4882a593Smuzhiyun }
207*4882a593Smuzhiyun 
rk_scr_reset(struct rk_scr * scr,unsigned char * rx_buffer)208*4882a593Smuzhiyun static void rk_scr_reset(struct rk_scr *scr, unsigned char *rx_buffer)
209*4882a593Smuzhiyun {
210*4882a593Smuzhiyun 	struct scr_reg_t *scr_reg = scr->hw->reg_base;
211*4882a593Smuzhiyun 
212*4882a593Smuzhiyun 	if (!rx_buffer)
213*4882a593Smuzhiyun 		DAL_LOGV("_scr_reset: invalid argument\n");
214*4882a593Smuzhiyun 
215*4882a593Smuzhiyun 	/*
216*4882a593Smuzhiyun 	 * must disable all SCR interrupts.
217*4882a593Smuzhiyun 	 * It will protect the global data.
218*4882a593Smuzhiyun 	 */
219*4882a593Smuzhiyun 	scr_reg->INTEN1 = 0;
220*4882a593Smuzhiyun 
221*4882a593Smuzhiyun 	scr->rx_buf = rx_buffer;
222*4882a593Smuzhiyun 	scr->rx_expected = 0xff;
223*4882a593Smuzhiyun 	scr->rx_cnt = 0;
224*4882a593Smuzhiyun 
225*4882a593Smuzhiyun 	/*
226*4882a593Smuzhiyun 	 * must in the critical section. If we don't, when we have written CTRL2
227*4882a593Smuzhiyun 	 * before enable expected interrupts, other interrupts occurred,
228*4882a593Smuzhiyun 	 * we may miss expected interrupts.
229*4882a593Smuzhiyun 	 */
230*4882a593Smuzhiyun 	if (scr->is_active) {
231*4882a593Smuzhiyun 		DAL_LOGV("Warm Reset\n");
232*4882a593Smuzhiyun 		scr_reg->CTRL2 |= WARMRST;
233*4882a593Smuzhiyun 	} else {
234*4882a593Smuzhiyun 		DAL_LOGV("Active & Cold Reset\n");
235*4882a593Smuzhiyun 		scr->is_active = true;
236*4882a593Smuzhiyun 		scr_reg->CTRL1 = TXEN | RXEN | TS2FIFO | ATRSTFLUSH | GINTEN;
237*4882a593Smuzhiyun 		scr_reg->CTRL2 |= ACT;
238*4882a593Smuzhiyun 	}
239*4882a593Smuzhiyun 
240*4882a593Smuzhiyun 	/*
241*4882a593Smuzhiyun 	 * If we enable the interrupts before write CTRL2, we may get
242*4882a593Smuzhiyun 	 * expected interrupts which belong to the last transfer not
243*4882a593Smuzhiyun 	 * for the reset.This may damage the global data.
244*4882a593Smuzhiyun 	 */
245*4882a593Smuzhiyun 	scr_reg->RXFIFOTH = MAX_RXTHR;
246*4882a593Smuzhiyun 	scr_reg->TXFIFOTH = MAX_TXTHR;
247*4882a593Smuzhiyun 	scr_reg->INTEN1 = RXTHRESHOLD | RXFIFULL | RXPERR |
248*4882a593Smuzhiyun 			C2CFULL | ATRFAIL | ATRDONE;
249*4882a593Smuzhiyun 	DAL_LOGV("Start Rx\n");
250*4882a593Smuzhiyun }
251*4882a593Smuzhiyun 
rk_scr_write_bytes(struct rk_scr * scr)252*4882a593Smuzhiyun static void rk_scr_write_bytes(struct rk_scr *scr)
253*4882a593Smuzhiyun {
254*4882a593Smuzhiyun 	struct scr_reg_t *scr_reg = scr->hw->reg_base;
255*4882a593Smuzhiyun 	int	count = FIFO_DEPTH - scr_reg->TXFIFOCNT;
256*4882a593Smuzhiyun 	int	remainder = scr->tx_expected - scr->tx_cnt;
257*4882a593Smuzhiyun 	int i = 0;
258*4882a593Smuzhiyun 
259*4882a593Smuzhiyun 	if (remainder < count)
260*4882a593Smuzhiyun 		count = remainder;
261*4882a593Smuzhiyun 
262*4882a593Smuzhiyun 	while (i++ < count)
263*4882a593Smuzhiyun 		scr_reg->FIFODATA = scr->tx_buf[scr->tx_cnt++];
264*4882a593Smuzhiyun }
265*4882a593Smuzhiyun 
rk_scr_read_bytes(struct rk_scr * scr)266*4882a593Smuzhiyun static void rk_scr_read_bytes(struct rk_scr *scr)
267*4882a593Smuzhiyun {
268*4882a593Smuzhiyun 	struct scr_reg_t *scr_reg = scr->hw->reg_base;
269*4882a593Smuzhiyun 	int count = scr_reg->RXFIFOCNT;
270*4882a593Smuzhiyun 	int remainder = scr->rx_expected - scr->rx_cnt;
271*4882a593Smuzhiyun 	int i = 0;
272*4882a593Smuzhiyun 
273*4882a593Smuzhiyun 	if (remainder < count)
274*4882a593Smuzhiyun 		count = remainder;
275*4882a593Smuzhiyun 
276*4882a593Smuzhiyun 	while (i++ < count)
277*4882a593Smuzhiyun 		scr->rx_buf[scr->rx_cnt++] = (unsigned char)scr_reg->FIFODATA;
278*4882a593Smuzhiyun }
279*4882a593Smuzhiyun 
rk_scr_irqhandler(int irq,void * priv)280*4882a593Smuzhiyun static irqreturn_t rk_scr_irqhandler(int irq, void *priv)
281*4882a593Smuzhiyun {
282*4882a593Smuzhiyun 	struct rk_scr *scr = (struct rk_scr *)priv;
283*4882a593Smuzhiyun 	struct scr_reg_t *scr_reg = scr->hw->reg_base;
284*4882a593Smuzhiyun 	enum hal_scr_irq_cause_e user_cause = HAL_SCR_IRQ_INVALID;
285*4882a593Smuzhiyun 	unsigned int stat;
286*4882a593Smuzhiyun 
287*4882a593Smuzhiyun 	stat = (unsigned int)scr_reg->INTSTAT1;
288*4882a593Smuzhiyun 	if (!stat)
289*4882a593Smuzhiyun 		return 0;
290*4882a593Smuzhiyun 
291*4882a593Smuzhiyun 	if (stat & TXFIEMPTY) {
292*4882a593Smuzhiyun 		scr_reg->INTSTAT1 |= TXFIEMPTY;
293*4882a593Smuzhiyun 
294*4882a593Smuzhiyun 		/* during this period, TXFIEMPTY may occurred. */
295*4882a593Smuzhiyun 		rk_scr_write_bytes(scr);
296*4882a593Smuzhiyun 
297*4882a593Smuzhiyun 		if (scr->tx_cnt == scr->tx_expected) {
298*4882a593Smuzhiyun 			scr_reg->INTEN1 &= ~TXFIEMPTY;
299*4882a593Smuzhiyun 			scr_reg->INTSTAT1 |= TXFIEMPTY;
300*4882a593Smuzhiyun 		}
301*4882a593Smuzhiyun 	}
302*4882a593Smuzhiyun #ifdef SCR_DEBUG
303*4882a593Smuzhiyun 	else if (stat & CLKSTOPRUN) {
304*4882a593Smuzhiyun 		scr_reg->INTSTAT1 |= CLKSTOPRUN;
305*4882a593Smuzhiyun 
306*4882a593Smuzhiyun 		if (scr_reg->CTRL1 & CLKSTOP)
307*4882a593Smuzhiyun 			DAL_LOGV("Clock	is stopped\n");
308*4882a593Smuzhiyun 		else
309*4882a593Smuzhiyun 			DAL_LOGV("Clock	is started\n");
310*4882a593Smuzhiyun 	}
311*4882a593Smuzhiyun #endif
312*4882a593Smuzhiyun 	else if ((stat & RXTHRESHOLD) || (stat & RXFIFULL)) {
313*4882a593Smuzhiyun 		unsigned int threshold;
314*4882a593Smuzhiyun 
315*4882a593Smuzhiyun 		scr_reg->INTEN1 &= ~RXTHRESHOLD;
316*4882a593Smuzhiyun 		scr_reg->INTSTAT1 |= RXTHRESHOLD | RXFIFULL;
317*4882a593Smuzhiyun 
318*4882a593Smuzhiyun 		if (scr->rx_cnt < scr->rx_expected) {
319*4882a593Smuzhiyun 			rk_scr_read_bytes(scr);
320*4882a593Smuzhiyun 			if (scr->rx_cnt < scr->rx_expected) {
321*4882a593Smuzhiyun 				unsigned int remainder =
322*4882a593Smuzhiyun 						scr->rx_expected - scr->rx_cnt;
323*4882a593Smuzhiyun 
324*4882a593Smuzhiyun 				threshold = (remainder < MAX_RXTHR)
325*4882a593Smuzhiyun 						? remainder : MAX_RXTHR;
326*4882a593Smuzhiyun 			} else {
327*4882a593Smuzhiyun 				scr_reg->INTEN1 &= ~C2CFULL;
328*4882a593Smuzhiyun 				threshold = 1;
329*4882a593Smuzhiyun 				if (scr->user_mask.rx_success)
330*4882a593Smuzhiyun 					user_cause = HAL_SCR_RX_SUCCESS;
331*4882a593Smuzhiyun 			}
332*4882a593Smuzhiyun 		} else {
333*4882a593Smuzhiyun 			threshold = 1;
334*4882a593Smuzhiyun 			scr->rx_buf[scr->rx_cnt++] =
335*4882a593Smuzhiyun 					(unsigned char)scr_reg->FIFODATA;
336*4882a593Smuzhiyun 			if (scr->user_mask.extra_rx)
337*4882a593Smuzhiyun 				user_cause = HAL_SCR_EXTRA_RX;
338*4882a593Smuzhiyun 		}
339*4882a593Smuzhiyun 		scr_reg->INTEN1 |= RXTHRESHOLD;
340*4882a593Smuzhiyun 		/*
341*4882a593Smuzhiyun 		 * when RX FIFO now is FULL,
342*4882a593Smuzhiyun 		 * that will not generate RXTHRESHOLD interrupt.
343*4882a593Smuzhiyun 		 * But it will generate RXFIFULL interrupt.
344*4882a593Smuzhiyun 		 */
345*4882a593Smuzhiyun 		scr_reg->RXFIFOTH = FIFO_DEPTH;
346*4882a593Smuzhiyun 		scr_reg->RXFIFOTH = threshold;
347*4882a593Smuzhiyun 	} else if (stat & ATRDONE) {
348*4882a593Smuzhiyun 		DAL_LOGV("ATR Done\n");
349*4882a593Smuzhiyun 		scr_reg->INTSTAT1 |= ATRDONE;
350*4882a593Smuzhiyun 		scr_reg->INTEN1 = 0;
351*4882a593Smuzhiyun 		rk_scr_read_bytes(scr);
352*4882a593Smuzhiyun 		if (scr->user_mask.atr_success)
353*4882a593Smuzhiyun 			user_cause = HAL_SCR_ATR_SUCCESS;
354*4882a593Smuzhiyun 	} else if (stat & ATRFAIL) {
355*4882a593Smuzhiyun 		DAL_LOGV("ATR Fail\n");
356*4882a593Smuzhiyun 
357*4882a593Smuzhiyun 		scr_reg->INTSTAT1 |= ATRFAIL;
358*4882a593Smuzhiyun 		scr_reg->INTEN1 = 0;
359*4882a593Smuzhiyun 
360*4882a593Smuzhiyun 		if (scr->user_mask.reset_timeout)
361*4882a593Smuzhiyun 			user_cause = HAL_SCR_RESET_TIMEOUT;
362*4882a593Smuzhiyun 	} else if (stat & TXPERR) {
363*4882a593Smuzhiyun 		DAL_LOGV("TXPERR\n");
364*4882a593Smuzhiyun 
365*4882a593Smuzhiyun 		scr_reg->INTSTAT1 |= TXPERR;
366*4882a593Smuzhiyun 		scr_reg->INTEN1 = 0;
367*4882a593Smuzhiyun 
368*4882a593Smuzhiyun 		if (scr->user_mask.parity_error)
369*4882a593Smuzhiyun 			user_cause = HAL_SCR_PARITY_ERROR;
370*4882a593Smuzhiyun 	} else if (stat & RXPERR) {
371*4882a593Smuzhiyun 		DAL_LOGV("RXPERR\n");
372*4882a593Smuzhiyun 		scr_reg->INTSTAT1 |= RXPERR;
373*4882a593Smuzhiyun 		scr_reg->INTEN1 = 0;
374*4882a593Smuzhiyun 		rk_scr_read_bytes(scr);
375*4882a593Smuzhiyun 		if (scr->user_mask.parity_error)
376*4882a593Smuzhiyun 			user_cause = HAL_SCR_PARITY_ERROR;
377*4882a593Smuzhiyun 	} else if (stat & C2CFULL) {
378*4882a593Smuzhiyun 		DAL_LOGV("Timeout\n");
379*4882a593Smuzhiyun 		scr_reg->INTSTAT1 |= C2CFULL;
380*4882a593Smuzhiyun 		scr_reg->INTEN1 = 0;
381*4882a593Smuzhiyun 		rk_scr_read_bytes(scr);
382*4882a593Smuzhiyun 
383*4882a593Smuzhiyun 		if (scr->user_mask.wwt_timeout)
384*4882a593Smuzhiyun 			user_cause = HAL_SCR_WWT_TIMEOUT;
385*4882a593Smuzhiyun 	}
386*4882a593Smuzhiyun 
387*4882a593Smuzhiyun 	if (user_cause != HAL_SCR_IRQ_INVALID) {
388*4882a593Smuzhiyun 		scr->in_process = false;
389*4882a593Smuzhiyun 		if (scr->user_handler)
390*4882a593Smuzhiyun 			scr->user_handler(user_cause);
391*4882a593Smuzhiyun 	}
392*4882a593Smuzhiyun 	return 0;
393*4882a593Smuzhiyun }
394*4882a593Smuzhiyun 
_rk_scr_init(struct rk_scr * scr)395*4882a593Smuzhiyun static void _rk_scr_init(struct rk_scr *scr)
396*4882a593Smuzhiyun {
397*4882a593Smuzhiyun 	struct scr_reg_t *scr_reg = scr->hw->reg_base;
398*4882a593Smuzhiyun 
399*4882a593Smuzhiyun 	rk_scr_deactive(scr);
400*4882a593Smuzhiyun 	rk_scr_set_clk(scr);
401*4882a593Smuzhiyun 	rk_scr_set_etu_duration(scr, 372, 1);
402*4882a593Smuzhiyun 
403*4882a593Smuzhiyun 	/* TXREPEAT = 3 & RXREPEAT = 3 */
404*4882a593Smuzhiyun 	scr_reg->REPEAT = 0x33;
405*4882a593Smuzhiyun 
406*4882a593Smuzhiyun 	/*
407*4882a593Smuzhiyun 	 * Character LeadEdge to Character LeadEdge minimum waiting time
408*4882a593Smuzhiyun 	 * in terms of ETUs. (GT)
409*4882a593Smuzhiyun 	 */
410*4882a593Smuzhiyun 	scr_reg->SCGT = 12;
411*4882a593Smuzhiyun 
412*4882a593Smuzhiyun 	/*
413*4882a593Smuzhiyun 	 * Character LeadEdge to Character LeadEdge maximum waiting time
414*4882a593Smuzhiyun 	 * in terms of ETUs. (WT)
415*4882a593Smuzhiyun 	 */
416*4882a593Smuzhiyun 	scr_reg->C2CLIM = 9600;
417*4882a593Smuzhiyun 
418*4882a593Smuzhiyun 	/*
419*4882a593Smuzhiyun 	 * If no Vpp is necessary, the activation and deactivation part of Vpp
420*4882a593Smuzhiyun 	 * can be omitted by clearing the AUTOADEAVPP bit in SCPADS register.
421*4882a593Smuzhiyun 	 */
422*4882a593Smuzhiyun 	scr_reg->SCPADS = 0;
423*4882a593Smuzhiyun 
424*4882a593Smuzhiyun 	/*
425*4882a593Smuzhiyun 	 * Activation / deactivation step time
426*4882a593Smuzhiyun 	 * in terms of SmartCard Clock Cycles
427*4882a593Smuzhiyun 	 */
428*4882a593Smuzhiyun 	scr_reg->ADEATIME = 0;
429*4882a593Smuzhiyun 
430*4882a593Smuzhiyun 	/*
431*4882a593Smuzhiyun 	 * Duration of low state during Smart Card reset sequence
432*4882a593Smuzhiyun 	 * in terms of smart card clock cycles
433*4882a593Smuzhiyun 	 * require >
434*4882a593Smuzhiyun 	 */
435*4882a593Smuzhiyun 	scr_reg->LOWRSTTIME = 1000;
436*4882a593Smuzhiyun 
437*4882a593Smuzhiyun 	/*
438*4882a593Smuzhiyun 	 * ATR start limit - in terms of SmartCard Clock Cycles
439*4882a593Smuzhiyun 	 * require 400 ~ 40000
440*4882a593Smuzhiyun 	 */
441*4882a593Smuzhiyun 	scr_reg->ATRSTARTLIMIT = 40000;
442*4882a593Smuzhiyun 
443*4882a593Smuzhiyun 	/* enable the detect interrupt */
444*4882a593Smuzhiyun 	scr_reg->INTEN1 = SCINS;
445*4882a593Smuzhiyun 	scr_reg->INTEN2 = 0;
446*4882a593Smuzhiyun 
447*4882a593Smuzhiyun 	scr_reg->INTSTAT1 = 0xffff;
448*4882a593Smuzhiyun 	scr_reg->INTSTAT2 = 0xffff;
449*4882a593Smuzhiyun 
450*4882a593Smuzhiyun 	scr_reg->FIFOCTRL = FC_TXFIFLUSH | FC_RXFIFLUSH;
451*4882a593Smuzhiyun 	scr_reg->TXFIFOTH = 0;
452*4882a593Smuzhiyun 	scr_reg->RXFIFOTH = 0;
453*4882a593Smuzhiyun 
454*4882a593Smuzhiyun 	scr_reg->CTRL1 = 0;
455*4882a593Smuzhiyun 	scr_reg->CTRL2 = 0;
456*4882a593Smuzhiyun }
457*4882a593Smuzhiyun 
_rk_scr_deinit(struct rk_scr * scr)458*4882a593Smuzhiyun static void _rk_scr_deinit(struct rk_scr *scr)
459*4882a593Smuzhiyun {
460*4882a593Smuzhiyun 	struct scr_reg_t *scr_reg = scr->hw->reg_base;
461*4882a593Smuzhiyun 
462*4882a593Smuzhiyun 	/* disable all interrupt */
463*4882a593Smuzhiyun 	scr_reg->INTEN1 = 0;
464*4882a593Smuzhiyun 	scr_reg->INTEN2 = 0;
465*4882a593Smuzhiyun 
466*4882a593Smuzhiyun 	rk_scr_deactive(scr);
467*4882a593Smuzhiyun 	rk_scr_powerdown(scr);
468*4882a593Smuzhiyun }
469*4882a593Smuzhiyun 
rk_scr_freqchanged_notifiy(struct notifier_block * nb,unsigned long action,void * data,int len)470*4882a593Smuzhiyun int rk_scr_freqchanged_notifiy(struct notifier_block *nb,
471*4882a593Smuzhiyun 			       unsigned long action, void *data, int len)
472*4882a593Smuzhiyun {
473*4882a593Smuzhiyun 	int idx;
474*4882a593Smuzhiyun 	struct rk_scr *scr = NULL;
475*4882a593Smuzhiyun 	/*alter by xieshufa not sure*/
476*4882a593Smuzhiyun 	struct clk_notifier_data *msg;
477*4882a593Smuzhiyun 
478*4882a593Smuzhiyun 	switch (action) {
479*4882a593Smuzhiyun 	/*case ABORT_RATE_CHANGE:*/
480*4882a593Smuzhiyun 	case POST_RATE_CHANGE:
481*4882a593Smuzhiyun 		break;
482*4882a593Smuzhiyun 	default:
483*4882a593Smuzhiyun 		return 0;
484*4882a593Smuzhiyun 	}
485*4882a593Smuzhiyun 
486*4882a593Smuzhiyun 	msg = data;
487*4882a593Smuzhiyun 	for (idx = 0; idx < RK_SCR_NUM; idx++) {
488*4882a593Smuzhiyun 		struct rk_scr *p = to_rk_scr(idx);
489*4882a593Smuzhiyun 
490*4882a593Smuzhiyun 		if (msg->clk == p->clk) {
491*4882a593Smuzhiyun 			scr = p;
492*4882a593Smuzhiyun 			break;
493*4882a593Smuzhiyun 		}
494*4882a593Smuzhiyun 	}
495*4882a593Smuzhiyun 
496*4882a593Smuzhiyun 	if (scr) {
497*4882a593Smuzhiyun 		rk_scr_set_clk(scr);
498*4882a593Smuzhiyun 		rk_scr_set_etu_duration(scr, scr->F, scr->D);
499*4882a593Smuzhiyun 	}
500*4882a593Smuzhiyun 
501*4882a593Smuzhiyun 	return 0;
502*4882a593Smuzhiyun }
503*4882a593Smuzhiyun 
rk_scr_open(int id)504*4882a593Smuzhiyun static int rk_scr_open(int id)
505*4882a593Smuzhiyun {
506*4882a593Smuzhiyun 	struct rk_scr_device *rk_scr_dev = rk_scr;
507*4882a593Smuzhiyun 	struct rk_scr *scr = to_rk_scr(id);
508*4882a593Smuzhiyun 	struct hal_scr_irq_status_t
509*4882a593Smuzhiyun 		default_scr_user_mask = {1, 1, 1, 1, 1, 1, 1, 1};
510*4882a593Smuzhiyun 	int result = 0;
511*4882a593Smuzhiyun 
512*4882a593Smuzhiyun 	if (!scr)
513*4882a593Smuzhiyun 		return -1;
514*4882a593Smuzhiyun 
515*4882a593Smuzhiyun 	rk_scr_dev->chip_info[id].reg_base = rk_scr_dev->regs;
516*4882a593Smuzhiyun 	rk_scr_dev->chip_info[id].irq = rk_scr_dev->irq;
517*4882a593Smuzhiyun 
518*4882a593Smuzhiyun 	scr->hw = &rk_scr_dev->chip_info[id];
519*4882a593Smuzhiyun 	scr->clk = rk_scr_dev->clk_scr;
520*4882a593Smuzhiyun 
521*4882a593Smuzhiyun 	result = clk_prepare_enable(scr->clk);
522*4882a593Smuzhiyun 	DAL_LOGV("scr clk_enable result = %d\n", result);
523*4882a593Smuzhiyun 
524*4882a593Smuzhiyun 	(&scr->freq_changed_notifier)->priority = 0;
525*4882a593Smuzhiyun 	clk_notifier_register(scr->clk, &scr->freq_changed_notifier);
526*4882a593Smuzhiyun 	scr->user_mask = default_scr_user_mask;
527*4882a593Smuzhiyun 
528*4882a593Smuzhiyun 	_rk_scr_init(scr);
529*4882a593Smuzhiyun 
530*4882a593Smuzhiyun 	scr->is_open = true;
531*4882a593Smuzhiyun 
532*4882a593Smuzhiyun 	return 0;
533*4882a593Smuzhiyun }
534*4882a593Smuzhiyun 
rk_scr_close(int id)535*4882a593Smuzhiyun static void rk_scr_close(int id)
536*4882a593Smuzhiyun {
537*4882a593Smuzhiyun 	struct rk_scr *scr;
538*4882a593Smuzhiyun 
539*4882a593Smuzhiyun 	scr = to_opened_rk_scr(id);
540*4882a593Smuzhiyun 	if (!scr)
541*4882a593Smuzhiyun 		return;
542*4882a593Smuzhiyun 
543*4882a593Smuzhiyun 	scr->is_open = false;
544*4882a593Smuzhiyun 
545*4882a593Smuzhiyun 	_rk_scr_deinit(scr);
546*4882a593Smuzhiyun 
547*4882a593Smuzhiyun 	if (scr->clk) {
548*4882a593Smuzhiyun 		clk_disable(scr->clk);
549*4882a593Smuzhiyun 		clk_notifier_unregister(scr->clk, &scr->freq_changed_notifier);
550*4882a593Smuzhiyun 	}
551*4882a593Smuzhiyun }
552*4882a593Smuzhiyun 
rk_scr_read(int id,unsigned int n_rx_byte,unsigned char * p_rx_byte)553*4882a593Smuzhiyun static int rk_scr_read(int id, unsigned int n_rx_byte,
554*4882a593Smuzhiyun 		       unsigned char *p_rx_byte)
555*4882a593Smuzhiyun {
556*4882a593Smuzhiyun 	struct rk_scr *scr;
557*4882a593Smuzhiyun 	struct scr_reg_t *scr_reg;
558*4882a593Smuzhiyun 	unsigned int inten1 = 0;
559*4882a593Smuzhiyun 
560*4882a593Smuzhiyun 	scr = to_opened_rk_scr(id);
561*4882a593Smuzhiyun 	if (!scr)
562*4882a593Smuzhiyun 		return -1;
563*4882a593Smuzhiyun 
564*4882a593Smuzhiyun 	if (!((n_rx_byte != 0) && (p_rx_byte))) {
565*4882a593Smuzhiyun 		DAL_LOGV("rk_scr_read: invalid argument\n");
566*4882a593Smuzhiyun 		return -1;
567*4882a593Smuzhiyun 	}
568*4882a593Smuzhiyun 
569*4882a593Smuzhiyun 	scr_reg = scr->hw->reg_base;
570*4882a593Smuzhiyun 
571*4882a593Smuzhiyun 	/*
572*4882a593Smuzhiyun 	 * must disable all SCR interrupts.
573*4882a593Smuzhiyun 	 * It will protect the global data.
574*4882a593Smuzhiyun 	 */
575*4882a593Smuzhiyun 	scr_reg->INTEN1 = 0;
576*4882a593Smuzhiyun 
577*4882a593Smuzhiyun 	scr->rx_buf = p_rx_byte;
578*4882a593Smuzhiyun 	scr->rx_expected = n_rx_byte;
579*4882a593Smuzhiyun 	scr->rx_cnt = 0;
580*4882a593Smuzhiyun 
581*4882a593Smuzhiyun 	scr_reg->RXFIFOTH = (scr->rx_expected < MAX_RXTHR)
582*4882a593Smuzhiyun 				? scr->rx_expected : MAX_RXTHR;
583*4882a593Smuzhiyun 	inten1 = RXTHRESHOLD | RXFIFULL | RXPERR | C2CFULL;
584*4882a593Smuzhiyun 
585*4882a593Smuzhiyun 	scr_reg->INTEN1 = inten1;
586*4882a593Smuzhiyun 
587*4882a593Smuzhiyun 	return 0;
588*4882a593Smuzhiyun }
589*4882a593Smuzhiyun 
rk_scr_write(int id,unsigned int n_tx_byte,const unsigned char * p_tx_byte)590*4882a593Smuzhiyun static int rk_scr_write(int id, unsigned int n_tx_byte,
591*4882a593Smuzhiyun 			const unsigned char *p_tx_byte)
592*4882a593Smuzhiyun {
593*4882a593Smuzhiyun 	struct rk_scr *scr;
594*4882a593Smuzhiyun 	struct scr_reg_t *scr_reg;
595*4882a593Smuzhiyun 	unsigned int inten1 = 0;
596*4882a593Smuzhiyun 	unsigned timeout_count = 1500;
597*4882a593Smuzhiyun 	unsigned long udelay = 0;
598*4882a593Smuzhiyun 
599*4882a593Smuzhiyun 	timeout_count = 1500;
600*4882a593Smuzhiyun 	udelay = msecs_to_jiffies(timeout_count) + jiffies;
601*4882a593Smuzhiyun 
602*4882a593Smuzhiyun 	scr = to_opened_rk_scr(id);
603*4882a593Smuzhiyun 	if (!scr)
604*4882a593Smuzhiyun 		return -1;
605*4882a593Smuzhiyun 
606*4882a593Smuzhiyun 	if (!((n_tx_byte != 0) && (p_tx_byte))) {
607*4882a593Smuzhiyun 		DAL_LOGV("rk_scr_write: invalid argument\n");
608*4882a593Smuzhiyun 		return -1;
609*4882a593Smuzhiyun 	}
610*4882a593Smuzhiyun 
611*4882a593Smuzhiyun 	scr_reg = scr->hw->reg_base;
612*4882a593Smuzhiyun 
613*4882a593Smuzhiyun 	/*
614*4882a593Smuzhiyun 	 * must disable all SCR interrupts.
615*4882a593Smuzhiyun 	 * It will protect the global data.
616*4882a593Smuzhiyun 	 */
617*4882a593Smuzhiyun 	scr_reg->INTEN1 = 0;
618*4882a593Smuzhiyun 
619*4882a593Smuzhiyun 	scr->tx_buf = p_tx_byte;
620*4882a593Smuzhiyun 	scr->tx_expected = n_tx_byte;
621*4882a593Smuzhiyun 	scr->tx_cnt = 0;
622*4882a593Smuzhiyun 
623*4882a593Smuzhiyun 	scr_reg->FIFOCTRL = FC_TXFIFLUSH | FC_RXFIFLUSH;
624*4882a593Smuzhiyun 
625*4882a593Smuzhiyun 	/* send data until FIFO full or send over. */
626*4882a593Smuzhiyun 	while ((scr->tx_cnt < scr->tx_expected) &&
627*4882a593Smuzhiyun 	       (time_before(jiffies, udelay))) {
628*4882a593Smuzhiyun 		if (!(scr_reg->FIFOCTRL & FC_TXFIFULL))
629*4882a593Smuzhiyun 			scr_reg->FIFODATA = scr->tx_buf[scr->tx_cnt++];
630*4882a593Smuzhiyun 	}
631*4882a593Smuzhiyun 	/* need enable tx interrupt to continue */
632*4882a593Smuzhiyun 	if (scr->tx_cnt < scr->tx_expected) {
633*4882a593Smuzhiyun 		pr_err("\n@rk_scr_write: FC_TXFIFULL@\n");
634*4882a593Smuzhiyun 		inten1 |= TXFIEMPTY | TXPERR;
635*4882a593Smuzhiyun 	}
636*4882a593Smuzhiyun 
637*4882a593Smuzhiyun 	scr_reg->INTEN1 = inten1;
638*4882a593Smuzhiyun 
639*4882a593Smuzhiyun 	return 0;
640*4882a593Smuzhiyun }
641*4882a593Smuzhiyun 
rk_scr_transfer(int id,unsigned int n_tx_byte,unsigned char * p_tx_byte,unsigned int n_rx_byte,unsigned char * p_rx_byte)642*4882a593Smuzhiyun int rk_scr_transfer(int id,
643*4882a593Smuzhiyun 		    unsigned int n_tx_byte, unsigned char *p_tx_byte,
644*4882a593Smuzhiyun 		    unsigned int n_rx_byte, unsigned char *p_rx_byte)
645*4882a593Smuzhiyun {
646*4882a593Smuzhiyun 	struct rk_scr *scr;
647*4882a593Smuzhiyun 	struct scr_reg_t *scr_reg;
648*4882a593Smuzhiyun 	unsigned int inten1;
649*4882a593Smuzhiyun 
650*4882a593Smuzhiyun 	scr = to_opened_rk_scr(id);
651*4882a593Smuzhiyun 	if (!scr)
652*4882a593Smuzhiyun 		return -1;
653*4882a593Smuzhiyun 
654*4882a593Smuzhiyun 	if (!((n_tx_byte != 0) &&
655*4882a593Smuzhiyun 	      (p_tx_byte) &&
656*4882a593Smuzhiyun 	      (n_rx_byte != 0) &&
657*4882a593Smuzhiyun 	      (p_rx_byte))) {
658*4882a593Smuzhiyun 		DAL_LOGV("rk_scr_transfer: invalid argument\n");
659*4882a593Smuzhiyun 		return -1;
660*4882a593Smuzhiyun 	}
661*4882a593Smuzhiyun 
662*4882a593Smuzhiyun 	if (scr->in_process)
663*4882a593Smuzhiyun 		return -1;
664*4882a593Smuzhiyun 
665*4882a593Smuzhiyun 	scr->in_process = true;
666*4882a593Smuzhiyun 	scr_reg = scr->hw->reg_base;
667*4882a593Smuzhiyun 
668*4882a593Smuzhiyun 	/*
669*4882a593Smuzhiyun 	 * must disable all SCR interrupts.
670*4882a593Smuzhiyun 	 * It will protect the global data.
671*4882a593Smuzhiyun 	 */
672*4882a593Smuzhiyun 	scr_reg->INTEN1 = 0;
673*4882a593Smuzhiyun 	rk_scr_clock_start(scr);
674*4882a593Smuzhiyun 
675*4882a593Smuzhiyun 	scr->tx_buf = p_tx_byte;
676*4882a593Smuzhiyun 	scr->tx_expected = n_tx_byte;
677*4882a593Smuzhiyun 	scr->tx_cnt = 0;
678*4882a593Smuzhiyun 
679*4882a593Smuzhiyun 	scr->rx_buf = p_rx_byte;
680*4882a593Smuzhiyun 	scr->rx_expected = n_rx_byte;
681*4882a593Smuzhiyun 	scr->rx_cnt = 0;
682*4882a593Smuzhiyun 
683*4882a593Smuzhiyun 	scr_reg->FIFOCTRL = FC_TXFIFLUSH | FC_RXFIFLUSH;
684*4882a593Smuzhiyun 
685*4882a593Smuzhiyun 	scr_reg->RXFIFOTH = (scr->rx_expected < MAX_RXTHR)
686*4882a593Smuzhiyun 				? scr->rx_expected : MAX_RXTHR;
687*4882a593Smuzhiyun 	scr_reg->TXFIFOTH = MAX_TXTHR;
688*4882a593Smuzhiyun 
689*4882a593Smuzhiyun 	inten1 = RXTHRESHOLD | RXFIFULL | RXPERR | C2CFULL;
690*4882a593Smuzhiyun 
691*4882a593Smuzhiyun 	/* send data until FIFO full or send over. */
692*4882a593Smuzhiyun 	while ((scr->tx_cnt < scr->tx_expected) &&
693*4882a593Smuzhiyun 	       !(scr_reg->FIFOCTRL & FC_TXFIFULL)) {
694*4882a593Smuzhiyun 		scr_reg->FIFODATA = scr->tx_buf[scr->tx_cnt++];
695*4882a593Smuzhiyun 	}
696*4882a593Smuzhiyun 
697*4882a593Smuzhiyun 	/* need enable tx interrupt to continue */
698*4882a593Smuzhiyun 	if (scr->tx_cnt < scr->tx_expected)
699*4882a593Smuzhiyun 		inten1 |= TXFIEMPTY | TXPERR;
700*4882a593Smuzhiyun 
701*4882a593Smuzhiyun 	scr_reg->INTEN1 = inten1;
702*4882a593Smuzhiyun 
703*4882a593Smuzhiyun 	return 0;
704*4882a593Smuzhiyun }
705*4882a593Smuzhiyun 
706*4882a593Smuzhiyun static	enum hal_scr_id_e g_curr_sur_id = HAL_SCR_ID0;
_scr_init(void)707*4882a593Smuzhiyun void _scr_init(void)
708*4882a593Smuzhiyun {
709*4882a593Smuzhiyun 	enum hal_scr_id_e id = g_curr_sur_id;
710*4882a593Smuzhiyun 
711*4882a593Smuzhiyun 	rk_scr_open(id);
712*4882a593Smuzhiyun }
713*4882a593Smuzhiyun 
_scr_close(void)714*4882a593Smuzhiyun void _scr_close(void)
715*4882a593Smuzhiyun {
716*4882a593Smuzhiyun 	enum hal_scr_id_e id = g_curr_sur_id;
717*4882a593Smuzhiyun 
718*4882a593Smuzhiyun 	rk_scr_close(id);
719*4882a593Smuzhiyun }
720*4882a593Smuzhiyun 
_scr_set_voltage(enum hal_scr_voltage_e level)721*4882a593Smuzhiyun bool _scr_set_voltage(enum hal_scr_voltage_e level)
722*4882a593Smuzhiyun {
723*4882a593Smuzhiyun 	enum hal_scr_id_e id = g_curr_sur_id;
724*4882a593Smuzhiyun 	struct rk_scr *scr = to_opened_rk_scr(id);
725*4882a593Smuzhiyun 
726*4882a593Smuzhiyun 	if (scr) {
727*4882a593Smuzhiyun 		rk_scr_set_scr_voltage(scr, level);
728*4882a593Smuzhiyun 		return true;
729*4882a593Smuzhiyun 	}
730*4882a593Smuzhiyun 
731*4882a593Smuzhiyun 	return false;
732*4882a593Smuzhiyun }
733*4882a593Smuzhiyun 
_scr_reset(unsigned char * rx_bytes)734*4882a593Smuzhiyun void _scr_reset(unsigned char *rx_bytes)
735*4882a593Smuzhiyun {
736*4882a593Smuzhiyun 	enum hal_scr_id_e id = g_curr_sur_id;
737*4882a593Smuzhiyun 	struct rk_scr *scr = to_opened_rk_scr(id);
738*4882a593Smuzhiyun 
739*4882a593Smuzhiyun 	if (scr)
740*4882a593Smuzhiyun 		rk_scr_reset(scr, rx_bytes);
741*4882a593Smuzhiyun }
742*4882a593Smuzhiyun 
_scr_set_etu_duration(unsigned int F,unsigned int D)743*4882a593Smuzhiyun void _scr_set_etu_duration(unsigned int F, unsigned int D)
744*4882a593Smuzhiyun {
745*4882a593Smuzhiyun 	enum hal_scr_id_e id = g_curr_sur_id;
746*4882a593Smuzhiyun 	struct rk_scr *scr = to_opened_rk_scr(id);
747*4882a593Smuzhiyun 
748*4882a593Smuzhiyun 	if (scr)
749*4882a593Smuzhiyun 		rk_scr_set_etu_duration(scr, F, D);
750*4882a593Smuzhiyun }
751*4882a593Smuzhiyun 
_scr_set_clock_stopmode(enum hal_scr_clock_stop_mode_e mode)752*4882a593Smuzhiyun void _scr_set_clock_stopmode(enum hal_scr_clock_stop_mode_e mode)
753*4882a593Smuzhiyun {
754*4882a593Smuzhiyun 	enum hal_scr_id_e id = g_curr_sur_id;
755*4882a593Smuzhiyun 	struct rk_scr *scr = to_opened_rk_scr(id);
756*4882a593Smuzhiyun 
757*4882a593Smuzhiyun 	if (scr)
758*4882a593Smuzhiyun 		rk_scr_set_clockstop_mode(scr, mode);
759*4882a593Smuzhiyun }
760*4882a593Smuzhiyun 
_scr_set_work_waitingtime(unsigned char wi)761*4882a593Smuzhiyun void _scr_set_work_waitingtime(unsigned char wi)
762*4882a593Smuzhiyun {
763*4882a593Smuzhiyun 	enum hal_scr_id_e id = g_curr_sur_id;
764*4882a593Smuzhiyun 	struct rk_scr *scr = to_opened_rk_scr(id);
765*4882a593Smuzhiyun 
766*4882a593Smuzhiyun 	if (scr)
767*4882a593Smuzhiyun 		rk_scr_set_work_waitingtime(scr, wi);
768*4882a593Smuzhiyun }
769*4882a593Smuzhiyun 
_scr_clock_start(void)770*4882a593Smuzhiyun void _scr_clock_start(void)
771*4882a593Smuzhiyun {
772*4882a593Smuzhiyun 	enum hal_scr_id_e id = g_curr_sur_id;
773*4882a593Smuzhiyun 	struct rk_scr *scr = to_opened_rk_scr(id);
774*4882a593Smuzhiyun 
775*4882a593Smuzhiyun 	if (scr)
776*4882a593Smuzhiyun 		rk_scr_clock_start(scr);
777*4882a593Smuzhiyun }
778*4882a593Smuzhiyun 
_scr_clock_stop(void)779*4882a593Smuzhiyun void _scr_clock_stop(void)
780*4882a593Smuzhiyun {
781*4882a593Smuzhiyun 	enum hal_scr_id_e id = g_curr_sur_id;
782*4882a593Smuzhiyun 	struct rk_scr *scr = to_opened_rk_scr(id);
783*4882a593Smuzhiyun 
784*4882a593Smuzhiyun 	if (scr)
785*4882a593Smuzhiyun 		rk_scr_clock_stop(scr);
786*4882a593Smuzhiyun }
787*4882a593Smuzhiyun 
_scr_tx_byte(unsigned int n_tx_byte,const unsigned char * p_tx_byte)788*4882a593Smuzhiyun bool _scr_tx_byte(unsigned int n_tx_byte,
789*4882a593Smuzhiyun 		  const unsigned char *p_tx_byte)
790*4882a593Smuzhiyun {
791*4882a593Smuzhiyun 	enum hal_scr_id_e id = g_curr_sur_id;
792*4882a593Smuzhiyun 	int ret = 0;
793*4882a593Smuzhiyun 
794*4882a593Smuzhiyun 	ret = rk_scr_write(id, n_tx_byte, p_tx_byte);
795*4882a593Smuzhiyun 	if (ret)
796*4882a593Smuzhiyun 		return false;
797*4882a593Smuzhiyun 	return true;
798*4882a593Smuzhiyun }
799*4882a593Smuzhiyun 
_scr_rx_byte(unsigned int n_rx_byte,unsigned char * p_rx_byte)800*4882a593Smuzhiyun bool _scr_rx_byte(unsigned int n_rx_byte, unsigned char *p_rx_byte)
801*4882a593Smuzhiyun {
802*4882a593Smuzhiyun 	enum hal_scr_id_e id = g_curr_sur_id;
803*4882a593Smuzhiyun 	int ret = 0;
804*4882a593Smuzhiyun 
805*4882a593Smuzhiyun 	ret = rk_scr_read(id, n_rx_byte, p_rx_byte);
806*4882a593Smuzhiyun 	if (ret)
807*4882a593Smuzhiyun 		return false;
808*4882a593Smuzhiyun 	return true;
809*4882a593Smuzhiyun }
810*4882a593Smuzhiyun 
_scr_tx_byte_rx_byte(unsigned int n_tx_byte,unsigned char * p_tx_byte,unsigned int n_rx_byte,unsigned char * p_rx_byte)811*4882a593Smuzhiyun bool _scr_tx_byte_rx_byte(unsigned int n_tx_byte,
812*4882a593Smuzhiyun 			  unsigned char *p_tx_byte,
813*4882a593Smuzhiyun 			  unsigned int n_rx_byte,
814*4882a593Smuzhiyun 			  unsigned char *p_rx_byte)
815*4882a593Smuzhiyun {
816*4882a593Smuzhiyun 	enum hal_scr_id_e id = g_curr_sur_id;
817*4882a593Smuzhiyun 	int ret;
818*4882a593Smuzhiyun 
819*4882a593Smuzhiyun 	ret = rk_scr_transfer(id, n_tx_byte, p_tx_byte, n_rx_byte, p_rx_byte);
820*4882a593Smuzhiyun 	if (ret)
821*4882a593Smuzhiyun 		return false;
822*4882a593Smuzhiyun 
823*4882a593Smuzhiyun 	return true;
824*4882a593Smuzhiyun }
825*4882a593Smuzhiyun 
_scr_get_num_rx_bytes(void)826*4882a593Smuzhiyun unsigned int _scr_get_num_rx_bytes(void)
827*4882a593Smuzhiyun {
828*4882a593Smuzhiyun 	enum hal_scr_id_e id = g_curr_sur_id;
829*4882a593Smuzhiyun 	struct rk_scr *scr = to_opened_rk_scr(id);
830*4882a593Smuzhiyun 
831*4882a593Smuzhiyun 	if (scr)
832*4882a593Smuzhiyun 		return scr->rx_cnt;
833*4882a593Smuzhiyun 
834*4882a593Smuzhiyun 	return 0;
835*4882a593Smuzhiyun }
836*4882a593Smuzhiyun 
_scr_get_num_tx_bytes(void)837*4882a593Smuzhiyun unsigned int _scr_get_num_tx_bytes(void)
838*4882a593Smuzhiyun {
839*4882a593Smuzhiyun 	enum hal_scr_id_e id = g_curr_sur_id;
840*4882a593Smuzhiyun 	struct rk_scr *scr = to_opened_rk_scr(id);
841*4882a593Smuzhiyun 
842*4882a593Smuzhiyun 	if (scr)
843*4882a593Smuzhiyun 		return scr->tx_cnt;
844*4882a593Smuzhiyun 
845*4882a593Smuzhiyun 	return 0;
846*4882a593Smuzhiyun }
847*4882a593Smuzhiyun 
_scr_powerdown(void)848*4882a593Smuzhiyun void _scr_powerdown(void)
849*4882a593Smuzhiyun {
850*4882a593Smuzhiyun 	enum hal_scr_id_e id = g_curr_sur_id;
851*4882a593Smuzhiyun 	struct rk_scr *scr = to_opened_rk_scr(id);
852*4882a593Smuzhiyun 
853*4882a593Smuzhiyun 	if (scr)
854*4882a593Smuzhiyun 		rk_scr_powerdown(scr);
855*4882a593Smuzhiyun }
856*4882a593Smuzhiyun 
_scr_irq_set_handler(hal_scr_irq_handler_t handler)857*4882a593Smuzhiyun void _scr_irq_set_handler(hal_scr_irq_handler_t handler)
858*4882a593Smuzhiyun {
859*4882a593Smuzhiyun 	enum hal_scr_id_e id = g_curr_sur_id;
860*4882a593Smuzhiyun 	struct rk_scr *scr = to_rk_scr(id);
861*4882a593Smuzhiyun 
862*4882a593Smuzhiyun 	if (scr)
863*4882a593Smuzhiyun 		scr->user_handler = handler;
864*4882a593Smuzhiyun }
865*4882a593Smuzhiyun 
_scr_irq_set_mask(struct hal_scr_irq_status_t mask)866*4882a593Smuzhiyun void _scr_irq_set_mask(struct hal_scr_irq_status_t mask)
867*4882a593Smuzhiyun {
868*4882a593Smuzhiyun 	enum hal_scr_id_e id = g_curr_sur_id;
869*4882a593Smuzhiyun 	struct rk_scr *scr = to_rk_scr(id);
870*4882a593Smuzhiyun 
871*4882a593Smuzhiyun 	if (scr)
872*4882a593Smuzhiyun 		scr->user_mask = mask;
873*4882a593Smuzhiyun }
874*4882a593Smuzhiyun 
_scr_irq_get_mask(void)875*4882a593Smuzhiyun struct hal_scr_irq_status_t _scr_irq_get_mask(void)
876*4882a593Smuzhiyun {
877*4882a593Smuzhiyun 	enum hal_scr_id_e id = g_curr_sur_id;
878*4882a593Smuzhiyun 	struct rk_scr *scr = to_rk_scr(id);
879*4882a593Smuzhiyun 	struct hal_scr_irq_status_t user_mask = {0};
880*4882a593Smuzhiyun 
881*4882a593Smuzhiyun 	if (scr)
882*4882a593Smuzhiyun 		return scr->user_mask;
883*4882a593Smuzhiyun 
884*4882a593Smuzhiyun 	return user_mask;
885*4882a593Smuzhiyun }
886*4882a593Smuzhiyun 
_scr_irq_get_detect_status(void)887*4882a593Smuzhiyun enum hal_scr_detect_status_e _scr_irq_get_detect_status(void)
888*4882a593Smuzhiyun {
889*4882a593Smuzhiyun 	enum hal_scr_id_e id = g_curr_sur_id;
890*4882a593Smuzhiyun 	struct rk_scr *scr = to_rk_scr(id);
891*4882a593Smuzhiyun 
892*4882a593Smuzhiyun 	if (scr && (scr->hw->reg_base->SCPADS & SCPRESENT)) {
893*4882a593Smuzhiyun 		DAL_LOGV("\n scr_check_card_insert: yes.\n");
894*4882a593Smuzhiyun 		return SMC_DRV_INT_CARDIN;
895*4882a593Smuzhiyun 	}
896*4882a593Smuzhiyun 
897*4882a593Smuzhiyun 	DAL_LOGV("\n scr_check_card_insert: no.\n");
898*4882a593Smuzhiyun 	return SMC_DRV_INT_CARDOUT;
899*4882a593Smuzhiyun }
900*4882a593Smuzhiyun 
_scr_rx_done(void)901*4882a593Smuzhiyun unsigned char _scr_rx_done(void)
902*4882a593Smuzhiyun {
903*4882a593Smuzhiyun 	enum hal_scr_id_e id = g_curr_sur_id;
904*4882a593Smuzhiyun 	struct rk_scr *scr = to_rk_scr(id);
905*4882a593Smuzhiyun 
906*4882a593Smuzhiyun 	if (scr->hw->reg_base->INTSTAT1 & RXDONE)
907*4882a593Smuzhiyun 		return 1;
908*4882a593Smuzhiyun 	else
909*4882a593Smuzhiyun 		return 0;
910*4882a593Smuzhiyun }
911*4882a593Smuzhiyun 
scr_set_etu_duration_struct(int f_and_d)912*4882a593Smuzhiyun void scr_set_etu_duration_struct(int f_and_d)
913*4882a593Smuzhiyun {
914*4882a593Smuzhiyun 	switch (f_and_d) {
915*4882a593Smuzhiyun 	case HAL_SCR_ETU_F_372_AND_D_1:
916*4882a593Smuzhiyun 		_scr_set_etu_duration(372, 1);
917*4882a593Smuzhiyun 		break;
918*4882a593Smuzhiyun 	case HAL_SCR_ETU_F_512_AND_D_8:
919*4882a593Smuzhiyun 		_scr_set_etu_duration(512, 8);
920*4882a593Smuzhiyun 		break;
921*4882a593Smuzhiyun 	case HAL_SCR_ETU_F_512_AND_D_4:
922*4882a593Smuzhiyun 		_scr_set_etu_duration(512, 4);
923*4882a593Smuzhiyun 		break;
924*4882a593Smuzhiyun 	}
925*4882a593Smuzhiyun }
926*4882a593Smuzhiyun 
scr_check_card_insert(void)927*4882a593Smuzhiyun int scr_check_card_insert(void)
928*4882a593Smuzhiyun {
929*4882a593Smuzhiyun 	int card_detect = -1;
930*4882a593Smuzhiyun 
931*4882a593Smuzhiyun 	card_detect = _scr_irq_get_detect_status();
932*4882a593Smuzhiyun 	if (card_detect)
933*4882a593Smuzhiyun 		return SMC_DRV_INT_CARDIN;
934*4882a593Smuzhiyun 	else
935*4882a593Smuzhiyun 		return SMC_DRV_INT_CARDOUT;
936*4882a593Smuzhiyun }
937*4882a593Smuzhiyun 
scr_activate_card(void)938*4882a593Smuzhiyun static void scr_activate_card(void)
939*4882a593Smuzhiyun {
940*4882a593Smuzhiyun 	_scr_init();
941*4882a593Smuzhiyun 	_scr_set_voltage(HAL_SCR_VOLTAGE_CLASS_B);
942*4882a593Smuzhiyun }
943*4882a593Smuzhiyun 
scr_deactivate_card(void)944*4882a593Smuzhiyun static void scr_deactivate_card(void)
945*4882a593Smuzhiyun {
946*4882a593Smuzhiyun 	_scr_close();
947*4882a593Smuzhiyun }
948*4882a593Smuzhiyun 
scr_isr_callback(enum hal_scr_irq_cause_e cause)949*4882a593Smuzhiyun static void scr_isr_callback(enum hal_scr_irq_cause_e cause)
950*4882a593Smuzhiyun {
951*4882a593Smuzhiyun 	complete(&rk_scr->is_done);
952*4882a593Smuzhiyun }
953*4882a593Smuzhiyun 
scr_write(unsigned char * buf,unsigned int write_cnt,unsigned int * to_read_cnt)954*4882a593Smuzhiyun ssize_t scr_write(unsigned char *buf,
955*4882a593Smuzhiyun 		  unsigned int write_cnt, unsigned int *to_read_cnt)
956*4882a593Smuzhiyun {
957*4882a593Smuzhiyun 	unsigned time_out = SMC_DEFAULT_TIMEOUT;
958*4882a593Smuzhiyun 	unsigned long udelay = 0;
959*4882a593Smuzhiyun 	int ret;
960*4882a593Smuzhiyun 
961*4882a593Smuzhiyun 	mutex_lock(&rk_scr->scr_mutex);
962*4882a593Smuzhiyun 	if (scr_check_card_insert() == SMC_DRV_INT_CARDOUT) {
963*4882a593Smuzhiyun 		mutex_unlock(&rk_scr->scr_mutex);
964*4882a593Smuzhiyun 		return SMC_ERROR_CARD_NOT_INSERT;
965*4882a593Smuzhiyun 	}
966*4882a593Smuzhiyun 
967*4882a593Smuzhiyun 	udelay = msecs_to_jiffies(time_out) + jiffies;
968*4882a593Smuzhiyun 
969*4882a593Smuzhiyun 	init_completion(&rk_scr->is_done);
970*4882a593Smuzhiyun 	rk_scr->recv_data_count = 0;
971*4882a593Smuzhiyun 	rk_scr->recv_data_offset = 0;
972*4882a593Smuzhiyun 	_scr_clock_start();
973*4882a593Smuzhiyun 
974*4882a593Smuzhiyun 	_scr_tx_byte(write_cnt, buf);
975*4882a593Smuzhiyun 	if (*to_read_cnt != 0) {
976*4882a593Smuzhiyun 		/* Set registers, ready to receive.*/
977*4882a593Smuzhiyun 		_scr_rx_byte(*to_read_cnt, rk_scr->recv_buffer);
978*4882a593Smuzhiyun 
979*4882a593Smuzhiyun 		ret = wait_for_completion_timeout(&rk_scr->is_done,
980*4882a593Smuzhiyun 						  msecs_to_jiffies(time_out));
981*4882a593Smuzhiyun 		rk_scr->recv_data_count = _scr_get_num_rx_bytes();
982*4882a593Smuzhiyun 		if (ret == 0) {
983*4882a593Smuzhiyun 			_scr_clock_stop();
984*4882a593Smuzhiyun 			mutex_unlock(&rk_scr->scr_mutex);
985*4882a593Smuzhiyun 			return TIMEOUT;
986*4882a593Smuzhiyun 		}
987*4882a593Smuzhiyun 	}
988*4882a593Smuzhiyun 	_scr_clock_stop();
989*4882a593Smuzhiyun 	mutex_unlock(&rk_scr->scr_mutex);
990*4882a593Smuzhiyun 	return SUCCESSFUL;
991*4882a593Smuzhiyun }
992*4882a593Smuzhiyun 
scr_read(unsigned char * buf,unsigned int to_read_cnt,unsigned int * have_read_cnt)993*4882a593Smuzhiyun ssize_t scr_read(unsigned char *buf, unsigned int to_read_cnt,
994*4882a593Smuzhiyun 		 unsigned int *have_read_cnt)
995*4882a593Smuzhiyun {
996*4882a593Smuzhiyun 	unsigned data_len = 0;
997*4882a593Smuzhiyun 	unsigned data_remain = 0;
998*4882a593Smuzhiyun 	unsigned data_available = 0;
999*4882a593Smuzhiyun 	unsigned data_offset = 0;
1000*4882a593Smuzhiyun 	unsigned time_out_ms = SMC_DEFAULT_TIMEOUT;
1001*4882a593Smuzhiyun 	unsigned data_count = 0;
1002*4882a593Smuzhiyun 	unsigned char data_remain_flag = 0;
1003*4882a593Smuzhiyun 	unsigned long udelay = 0;
1004*4882a593Smuzhiyun 
1005*4882a593Smuzhiyun 	if (!rk_scr->recv_buffer)
1006*4882a593Smuzhiyun 		return SMC_ERROR_RX_ERR;
1007*4882a593Smuzhiyun 
1008*4882a593Smuzhiyun 	mutex_lock(&rk_scr->scr_mutex);
1009*4882a593Smuzhiyun 	if (scr_check_card_insert() == SMC_DRV_INT_CARDOUT) {
1010*4882a593Smuzhiyun 		mutex_unlock(&rk_scr->scr_mutex);
1011*4882a593Smuzhiyun 		return SMC_ERROR_CARD_NOT_INSERT;
1012*4882a593Smuzhiyun 	}
1013*4882a593Smuzhiyun 
1014*4882a593Smuzhiyun 	udelay = msecs_to_jiffies(time_out_ms) + jiffies;
1015*4882a593Smuzhiyun 	data_remain = to_read_cnt;
1016*4882a593Smuzhiyun 	data_count = 0;
1017*4882a593Smuzhiyun 	_scr_clock_start();
1018*4882a593Smuzhiyun 
1019*4882a593Smuzhiyun 	if (data_remain != 0xffffff)
1020*4882a593Smuzhiyun 		data_remain_flag = 1;
1021*4882a593Smuzhiyun 
1022*4882a593Smuzhiyun 	while (time_before(jiffies, udelay)) {
1023*4882a593Smuzhiyun 		data_available = rk_scr->recv_data_count
1024*4882a593Smuzhiyun 				- rk_scr->recv_data_offset;
1025*4882a593Smuzhiyun 		if (data_available) {
1026*4882a593Smuzhiyun 			if (data_remain_flag)
1027*4882a593Smuzhiyun 				data_len = (data_available > data_remain)
1028*4882a593Smuzhiyun 					? (data_remain) : (data_available);
1029*4882a593Smuzhiyun 			else
1030*4882a593Smuzhiyun 				data_len = data_available;
1031*4882a593Smuzhiyun 			data_offset = rk_scr->recv_data_offset;
1032*4882a593Smuzhiyun 			memcpy(&buf[data_count],
1033*4882a593Smuzhiyun 			       &rk_scr->recv_buffer[data_offset],
1034*4882a593Smuzhiyun 			       data_len);
1035*4882a593Smuzhiyun 			data_count += data_len;
1036*4882a593Smuzhiyun 			rk_scr->recv_data_offset += data_len;
1037*4882a593Smuzhiyun 			if (data_remain_flag)
1038*4882a593Smuzhiyun 				data_remain -= data_len;
1039*4882a593Smuzhiyun 		}
1040*4882a593Smuzhiyun 
1041*4882a593Smuzhiyun 		if (data_remain_flag && (data_remain == 0))
1042*4882a593Smuzhiyun 			break;
1043*4882a593Smuzhiyun 		msleep(50);
1044*4882a593Smuzhiyun 	}
1045*4882a593Smuzhiyun 	_scr_clock_stop();
1046*4882a593Smuzhiyun 	*have_read_cnt = data_count;
1047*4882a593Smuzhiyun 	mutex_unlock(&rk_scr->scr_mutex);
1048*4882a593Smuzhiyun 
1049*4882a593Smuzhiyun 	return SUCCESSFUL;
1050*4882a593Smuzhiyun }
1051*4882a593Smuzhiyun 
scr_open(void)1052*4882a593Smuzhiyun int scr_open(void)
1053*4882a593Smuzhiyun {
1054*4882a593Smuzhiyun 	mutex_lock(&rk_scr->scr_mutex);
1055*4882a593Smuzhiyun 	_scr_irq_set_handler(scr_isr_callback);
1056*4882a593Smuzhiyun 	if (!rk_scr->recv_buffer) {
1057*4882a593Smuzhiyun 		rk_scr->recv_buffer = kmalloc(SMC_RECEIVE_BUF_LEN, GFP_DMA);
1058*4882a593Smuzhiyun 		if (!rk_scr->recv_buffer)
1059*4882a593Smuzhiyun 			return NO_MEMORY;
1060*4882a593Smuzhiyun 	}
1061*4882a593Smuzhiyun 	memset(rk_scr->recv_buffer, 0, SMC_RECEIVE_BUF_LEN);
1062*4882a593Smuzhiyun 	init_completion(&rk_scr->is_done);
1063*4882a593Smuzhiyun 	rk_scr->recv_data_count = 0;
1064*4882a593Smuzhiyun 	rk_scr->recv_data_offset = 0;
1065*4882a593Smuzhiyun 	scr_activate_card();
1066*4882a593Smuzhiyun 	mutex_unlock(&rk_scr->scr_mutex);
1067*4882a593Smuzhiyun 
1068*4882a593Smuzhiyun 	return SUCCESSFUL;
1069*4882a593Smuzhiyun }
1070*4882a593Smuzhiyun 
scr_close(void)1071*4882a593Smuzhiyun int scr_close(void)
1072*4882a593Smuzhiyun {
1073*4882a593Smuzhiyun 	mutex_lock(&rk_scr->scr_mutex);
1074*4882a593Smuzhiyun 	scr_deactivate_card();
1075*4882a593Smuzhiyun 	kfree(rk_scr->recv_buffer);
1076*4882a593Smuzhiyun 	rk_scr->recv_buffer = NULL;
1077*4882a593Smuzhiyun 	mutex_unlock(&rk_scr->scr_mutex);
1078*4882a593Smuzhiyun 
1079*4882a593Smuzhiyun 	return SUCCESSFUL;
1080*4882a593Smuzhiyun }
1081*4882a593Smuzhiyun 
scr_reset(void)1082*4882a593Smuzhiyun int scr_reset(void)
1083*4882a593Smuzhiyun {
1084*4882a593Smuzhiyun 	unsigned long timeout_ms = SMC_DEFAULT_TIMEOUT;
1085*4882a593Smuzhiyun 	int i = 0;
1086*4882a593Smuzhiyun 	int ret;
1087*4882a593Smuzhiyun 
1088*4882a593Smuzhiyun 	DAL_LOGV("-----------------scr_reset------------------\n");
1089*4882a593Smuzhiyun 	mutex_lock(&rk_scr->scr_mutex);
1090*4882a593Smuzhiyun 	if (scr_check_card_insert() == SMC_DRV_INT_CARDOUT) {
1091*4882a593Smuzhiyun 		mutex_unlock(&rk_scr->scr_mutex);
1092*4882a593Smuzhiyun 		return SMC_ERROR_CARD_NOT_INSERT;
1093*4882a593Smuzhiyun 	}
1094*4882a593Smuzhiyun 
1095*4882a593Smuzhiyun 	init_completion(&rk_scr->is_done);
1096*4882a593Smuzhiyun 
1097*4882a593Smuzhiyun 	rk_scr->recv_data_count = 0;
1098*4882a593Smuzhiyun 	rk_scr->recv_data_offset = 0;
1099*4882a593Smuzhiyun 	memset(rk_scr->atr_buffer, 0, SMC_ATR_MAX_LENGTH);
1100*4882a593Smuzhiyun 	rk_scr->atr_length = 0;
1101*4882a593Smuzhiyun 
1102*4882a593Smuzhiyun 	_scr_clock_start();
1103*4882a593Smuzhiyun 	_scr_reset(rk_scr->recv_buffer);
1104*4882a593Smuzhiyun 
1105*4882a593Smuzhiyun 	ret = wait_for_completion_timeout(&rk_scr->is_done,
1106*4882a593Smuzhiyun 					  msecs_to_jiffies(timeout_ms));
1107*4882a593Smuzhiyun 	rk_scr->recv_data_count = _scr_get_num_rx_bytes();
1108*4882a593Smuzhiyun 
1109*4882a593Smuzhiyun 	_scr_clock_stop();
1110*4882a593Smuzhiyun 
1111*4882a593Smuzhiyun 	if ((rk_scr->recv_data_count <= SMC_ATR_MAX_LENGTH) &&
1112*4882a593Smuzhiyun 	    (rk_scr->recv_data_count > 0)) {
1113*4882a593Smuzhiyun 		memcpy(rk_scr->atr_buffer, rk_scr->recv_buffer,
1114*4882a593Smuzhiyun 		       rk_scr->recv_data_count);
1115*4882a593Smuzhiyun 		rk_scr->atr_length = rk_scr->recv_data_count;
1116*4882a593Smuzhiyun 	} else {
1117*4882a593Smuzhiyun 		DAL_LOGV("ATR error: rk_scr->recv_data_count = %d.\n",
1118*4882a593Smuzhiyun 			 rk_scr->recv_data_count);
1119*4882a593Smuzhiyun 		mutex_unlock(&rk_scr->scr_mutex);
1120*4882a593Smuzhiyun 		return SMC_ERROR_ATR_ERR;
1121*4882a593Smuzhiyun 	}
1122*4882a593Smuzhiyun 
1123*4882a593Smuzhiyun 	DAL_LOGV("\n--------ATR start-----------\n");
1124*4882a593Smuzhiyun 	DAL_LOGV("rk_scr->atr_length = %d\n", rk_scr->atr_length);
1125*4882a593Smuzhiyun 	for (i = 0; i < rk_scr->recv_data_count; i++)
1126*4882a593Smuzhiyun 		DAL_LOGV("0x%2x\n", rk_scr->atr_buffer[i]);
1127*4882a593Smuzhiyun 	DAL_LOGV("\n--------ATR end-----------\n");
1128*4882a593Smuzhiyun 	mutex_unlock(&rk_scr->scr_mutex);
1129*4882a593Smuzhiyun 
1130*4882a593Smuzhiyun 	return SUCCESSFUL;
1131*4882a593Smuzhiyun }
1132*4882a593Smuzhiyun 
scr_get_atr_data(unsigned char * atr_buf,unsigned char * atr_len)1133*4882a593Smuzhiyun int scr_get_atr_data(unsigned char *atr_buf, unsigned char *atr_len)
1134*4882a593Smuzhiyun {
1135*4882a593Smuzhiyun 	if ((!atr_buf) || (!atr_len))
1136*4882a593Smuzhiyun 		return SMC_ERROR_BAD_PARAMETER;
1137*4882a593Smuzhiyun 
1138*4882a593Smuzhiyun 	mutex_lock(&rk_scr->scr_mutex);
1139*4882a593Smuzhiyun 	if ((rk_scr->atr_length < SMC_ATR_MIN_LENGTH) ||
1140*4882a593Smuzhiyun 	    (rk_scr->atr_length > SMC_ATR_MAX_LENGTH)) {
1141*4882a593Smuzhiyun 		mutex_unlock(&rk_scr->scr_mutex);
1142*4882a593Smuzhiyun 		return SMC_ERROR_ATR_ERR;
1143*4882a593Smuzhiyun 	}
1144*4882a593Smuzhiyun 
1145*4882a593Smuzhiyun 	memcpy(atr_buf, &rk_scr->atr_buffer[0], rk_scr->atr_length);
1146*4882a593Smuzhiyun 	*atr_len = rk_scr->atr_length;
1147*4882a593Smuzhiyun 	mutex_unlock(&rk_scr->scr_mutex);
1148*4882a593Smuzhiyun 
1149*4882a593Smuzhiyun 	return SUCCESSFUL;
1150*4882a593Smuzhiyun }
1151*4882a593Smuzhiyun 
scr_set_etu_duration(unsigned int F,unsigned int D)1152*4882a593Smuzhiyun void scr_set_etu_duration(unsigned int F, unsigned int D)
1153*4882a593Smuzhiyun {
1154*4882a593Smuzhiyun 	mutex_lock(&rk_scr->scr_mutex);
1155*4882a593Smuzhiyun 	_scr_set_etu_duration(F, D);
1156*4882a593Smuzhiyun 	mutex_unlock(&rk_scr->scr_mutex);
1157*4882a593Smuzhiyun }
1158*4882a593Smuzhiyun 
scr_set_work_waitingtime(unsigned char wi)1159*4882a593Smuzhiyun void scr_set_work_waitingtime(unsigned char wi)
1160*4882a593Smuzhiyun {
1161*4882a593Smuzhiyun 	mutex_lock(&rk_scr->scr_mutex);
1162*4882a593Smuzhiyun 	_scr_set_work_waitingtime(wi);
1163*4882a593Smuzhiyun 	mutex_unlock(&rk_scr->scr_mutex);
1164*4882a593Smuzhiyun }
1165*4882a593Smuzhiyun 
1166*4882a593Smuzhiyun static int scr_sysfs_value;
1167*4882a593Smuzhiyun 
scr_sysfs_show(struct kobject * kobj,struct kobj_attribute * attr,char * buf)1168*4882a593Smuzhiyun static ssize_t scr_sysfs_show(struct kobject *kobj,
1169*4882a593Smuzhiyun 			      struct kobj_attribute *attr,
1170*4882a593Smuzhiyun 			      char *buf)
1171*4882a593Smuzhiyun {
1172*4882a593Smuzhiyun 	scr_open();
1173*4882a593Smuzhiyun 	scr_reset();
1174*4882a593Smuzhiyun 	scr_close();
1175*4882a593Smuzhiyun 
1176*4882a593Smuzhiyun 	return sprintf(buf, "%d\n", scr_sysfs_value);
1177*4882a593Smuzhiyun }
1178*4882a593Smuzhiyun 
scr_sysfs_store(struct kobject * kobj,struct kobj_attribute * attr,const char * buf,size_t count)1179*4882a593Smuzhiyun static ssize_t scr_sysfs_store(struct kobject *kobj,
1180*4882a593Smuzhiyun 			       struct kobj_attribute *attr,
1181*4882a593Smuzhiyun 			       const char *buf, size_t count)
1182*4882a593Smuzhiyun {
1183*4882a593Smuzhiyun 	int ret;
1184*4882a593Smuzhiyun 
1185*4882a593Smuzhiyun 	ret = sscanf(buf, "%du", &scr_sysfs_value);
1186*4882a593Smuzhiyun 	if (ret != 1)
1187*4882a593Smuzhiyun 		return -EINVAL;
1188*4882a593Smuzhiyun 
1189*4882a593Smuzhiyun 	return 0;
1190*4882a593Smuzhiyun }
1191*4882a593Smuzhiyun 
1192*4882a593Smuzhiyun static struct kobj_attribute scr_sysfs_attribute =
1193*4882a593Smuzhiyun 		__ATTR(scr_sysfs, 0664, scr_sysfs_show, scr_sysfs_store);
1194*4882a593Smuzhiyun 
1195*4882a593Smuzhiyun struct attribute *rockchip_smartcard_attributes[] = {
1196*4882a593Smuzhiyun 	&scr_sysfs_attribute.attr,
1197*4882a593Smuzhiyun 	NULL
1198*4882a593Smuzhiyun };
1199*4882a593Smuzhiyun 
1200*4882a593Smuzhiyun static const struct attribute_group rockchip_smartcard_group = {
1201*4882a593Smuzhiyun 	.attrs = rockchip_smartcard_attributes,
1202*4882a593Smuzhiyun };
1203*4882a593Smuzhiyun 
1204*4882a593Smuzhiyun /* #define CONFIG_SMARTCARD_MUX_SEL_T0 */
1205*4882a593Smuzhiyun /* #define CONFIG_SMARTCARD_MUX_SEL_T1 */
1206*4882a593Smuzhiyun #define RK_SCR_CLK_NAME "g_pclk_sim_card"
rk_scr_probe(struct platform_device * pdev)1207*4882a593Smuzhiyun static int rk_scr_probe(struct platform_device *pdev)
1208*4882a593Smuzhiyun {
1209*4882a593Smuzhiyun 	struct rk_scr_device *rk_scr_dev = NULL;
1210*4882a593Smuzhiyun 	struct resource *res = NULL;
1211*4882a593Smuzhiyun 	struct device *dev = NULL;
1212*4882a593Smuzhiyun 	int ret = 0;
1213*4882a593Smuzhiyun 
1214*4882a593Smuzhiyun 	dev = &pdev->dev;
1215*4882a593Smuzhiyun 	rk_scr_dev = devm_kzalloc(dev, sizeof(*rk_scr_dev), GFP_KERNEL);
1216*4882a593Smuzhiyun 	if (!rk_scr_dev) {
1217*4882a593Smuzhiyun 		dev_err(dev, "failed to allocate scr_device\n");
1218*4882a593Smuzhiyun 		return -ENOMEM;
1219*4882a593Smuzhiyun 	}
1220*4882a593Smuzhiyun 	rk_scr = rk_scr_dev;
1221*4882a593Smuzhiyun 	mutex_init(&rk_scr->scr_mutex);
1222*4882a593Smuzhiyun 
1223*4882a593Smuzhiyun 	rk_scr_dev->irq = platform_get_irq(pdev, 0);
1224*4882a593Smuzhiyun 	if (rk_scr_dev->irq < 0) {
1225*4882a593Smuzhiyun 		dev_err(dev, "failed to get scr irq\n");
1226*4882a593Smuzhiyun 		return -ENOENT;
1227*4882a593Smuzhiyun 	}
1228*4882a593Smuzhiyun 
1229*4882a593Smuzhiyun 	ret = devm_request_irq(dev, rk_scr_dev->irq, rk_scr_irqhandler,
1230*4882a593Smuzhiyun 			       0, "rockchip-scr",
1231*4882a593Smuzhiyun 			       (void *)&rk_scr->scr[g_curr_sur_id]);
1232*4882a593Smuzhiyun 	if (ret < 0) {
1233*4882a593Smuzhiyun 		dev_err(dev, "failed to attach scr irq\n");
1234*4882a593Smuzhiyun 		return ret;
1235*4882a593Smuzhiyun 	}
1236*4882a593Smuzhiyun 
1237*4882a593Smuzhiyun 	rk_scr_dev->clk_scr = devm_clk_get(dev, RK_SCR_CLK_NAME);
1238*4882a593Smuzhiyun 	if (IS_ERR(rk_scr_dev->clk_scr)) {
1239*4882a593Smuzhiyun 		dev_err(dev, "failed to get scr clock\n");
1240*4882a593Smuzhiyun 		return PTR_ERR(rk_scr_dev->clk_scr);
1241*4882a593Smuzhiyun 	}
1242*4882a593Smuzhiyun 
1243*4882a593Smuzhiyun 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1244*4882a593Smuzhiyun 	rk_scr_dev->regs = devm_ioremap_resource(dev, res);
1245*4882a593Smuzhiyun 	if (IS_ERR(rk_scr_dev->regs))
1246*4882a593Smuzhiyun 		return PTR_ERR(rk_scr_dev->regs);
1247*4882a593Smuzhiyun 
1248*4882a593Smuzhiyun #ifdef CONFIG_SMARTCARD_MUX_SEL_T0
1249*4882a593Smuzhiyun 	writel_relaxed(((0x1 << 22) | (0x1 << 6)),
1250*4882a593Smuzhiyun 		       RK_GRF_VIRT + RK3288_GRF_SOC_CON2);
1251*4882a593Smuzhiyun #endif
1252*4882a593Smuzhiyun 
1253*4882a593Smuzhiyun #ifdef CONFIG_SMARTCARD_MUX_SEL_T1
1254*4882a593Smuzhiyun 	pinctrl_select_state(dev->pins->p,
1255*4882a593Smuzhiyun 			     pinctrl_lookup_state(dev->pins->p, "sc_t1"));
1256*4882a593Smuzhiyun 	writel_relaxed(((0x1 << 22) | (0x0 << 6)),
1257*4882a593Smuzhiyun 		       (RK_GRF_VIRT + RK3288_GRF_SOC_CON2));
1258*4882a593Smuzhiyun #endif
1259*4882a593Smuzhiyun 
1260*4882a593Smuzhiyun 	dev_set_drvdata(dev, rk_scr_dev);
1261*4882a593Smuzhiyun 
1262*4882a593Smuzhiyun 	ret = sysfs_create_group(&pdev->dev.kobj, &rockchip_smartcard_group);
1263*4882a593Smuzhiyun 	if (ret < 0)
1264*4882a593Smuzhiyun 		dev_err(&pdev->dev, "Create sysfs group failed (%d)\n", ret);
1265*4882a593Smuzhiyun 	DAL_LOGV("rk_scr_pdev->name = %s\n", pdev->name);
1266*4882a593Smuzhiyun 	DAL_LOGV("rk_scr_dev->irq = 0x%x\n", rk_scr_dev->irq);
1267*4882a593Smuzhiyun 
1268*4882a593Smuzhiyun 	return ret;
1269*4882a593Smuzhiyun }
1270*4882a593Smuzhiyun 
1271*4882a593Smuzhiyun #ifdef CONFIG_PM
rk_scr_suspend(struct device * dev)1272*4882a593Smuzhiyun static int rk_scr_suspend(struct device *dev)
1273*4882a593Smuzhiyun {
1274*4882a593Smuzhiyun 	struct rk_scr_device *rk_scr_dev = dev_get_drvdata(dev);
1275*4882a593Smuzhiyun 
1276*4882a593Smuzhiyun 	disable_irq(rk_scr_dev->irq);
1277*4882a593Smuzhiyun 	clk_disable(rk_scr_dev->clk_scr);
1278*4882a593Smuzhiyun 
1279*4882a593Smuzhiyun 	return 0;
1280*4882a593Smuzhiyun }
1281*4882a593Smuzhiyun 
rk_scr_resume(struct device * dev)1282*4882a593Smuzhiyun static int rk_scr_resume(struct device *dev)
1283*4882a593Smuzhiyun {
1284*4882a593Smuzhiyun 	struct rk_scr_device *rk_scr_dev = dev_get_drvdata(dev);
1285*4882a593Smuzhiyun 
1286*4882a593Smuzhiyun 	clk_enable(rk_scr_dev->clk_scr);
1287*4882a593Smuzhiyun 	enable_irq(rk_scr_dev->irq);
1288*4882a593Smuzhiyun 
1289*4882a593Smuzhiyun 	return 0;
1290*4882a593Smuzhiyun }
1291*4882a593Smuzhiyun #else
1292*4882a593Smuzhiyun #define rk_scr_suspend NULL
1293*4882a593Smuzhiyun #define rk_scr_resume NULL
1294*4882a593Smuzhiyun #endif
1295*4882a593Smuzhiyun 
1296*4882a593Smuzhiyun #ifdef CONFIG_OF
1297*4882a593Smuzhiyun static const struct of_device_id rockchip_scr_dt_match[] = {
1298*4882a593Smuzhiyun 	{ .compatible = "rockchip-scr",},
1299*4882a593Smuzhiyun 	{},
1300*4882a593Smuzhiyun };
1301*4882a593Smuzhiyun MODULE_DEVICE_TABLE(of, rockchip_scr_dt_match);
1302*4882a593Smuzhiyun #endif /* CONFIG_OF */
1303*4882a593Smuzhiyun 
1304*4882a593Smuzhiyun static const struct dev_pm_ops scr_pm_ops = {
1305*4882a593Smuzhiyun 	.suspend	= rk_scr_suspend,
1306*4882a593Smuzhiyun 	.resume		= rk_scr_resume,
1307*4882a593Smuzhiyun };
1308*4882a593Smuzhiyun 
1309*4882a593Smuzhiyun static struct platform_driver rk_scr_driver = {
1310*4882a593Smuzhiyun 	.driver		= {
1311*4882a593Smuzhiyun 		.name	= "rockchip-scr",
1312*4882a593Smuzhiyun 		.owner	= THIS_MODULE,
1313*4882a593Smuzhiyun 		.pm	= &scr_pm_ops,
1314*4882a593Smuzhiyun 		.of_match_table = of_match_ptr(rockchip_scr_dt_match),
1315*4882a593Smuzhiyun 	},
1316*4882a593Smuzhiyun 	.probe		= rk_scr_probe,
1317*4882a593Smuzhiyun };
1318*4882a593Smuzhiyun 
1319*4882a593Smuzhiyun module_platform_driver(rk_scr_driver);
1320*4882a593Smuzhiyun 
1321*4882a593Smuzhiyun MODULE_DESCRIPTION("rockchip Smart Card controller driver");
1322*4882a593Smuzhiyun MODULE_AUTHOR("<rockchip>");
1323*4882a593Smuzhiyun MODULE_LICENSE("GPL");
1324