xref: /openbmc/linux/drivers/nfc/st95hf/core.c (revision 4f2c0a4acffbec01079c28f839422e64ddeff004)
146fe7771SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2cab47333SShikha Singh /*
3cab47333SShikha Singh  * --------------------------------------------------------------------
4cab47333SShikha Singh  * Driver for ST NFC Transceiver ST95HF
5cab47333SShikha Singh  * --------------------------------------------------------------------
6cab47333SShikha Singh  * Copyright (C) 2015 STMicroelectronics Pvt. Ltd. All rights reserved.
7cab47333SShikha Singh  */
8cab47333SShikha Singh 
9cab47333SShikha Singh #include <linux/err.h>
10cab47333SShikha Singh #include <linux/gpio.h>
11cab47333SShikha Singh #include <linux/init.h>
12cab47333SShikha Singh #include <linux/interrupt.h>
13cab47333SShikha Singh #include <linux/irq.h>
14cab47333SShikha Singh #include <linux/module.h>
15cab47333SShikha Singh #include <linux/netdevice.h>
16cab47333SShikha Singh #include <linux/nfc.h>
17cab47333SShikha Singh #include <linux/of_gpio.h>
18cab47333SShikha Singh #include <linux/of.h>
19cab47333SShikha Singh #include <linux/property.h>
20cab47333SShikha Singh #include <linux/regulator/consumer.h>
21cab47333SShikha Singh #include <linux/wait.h>
22cab47333SShikha Singh #include <net/nfc/digital.h>
23cab47333SShikha Singh #include <net/nfc/nfc.h>
24cab47333SShikha Singh 
25cab47333SShikha Singh #include "spi.h"
26cab47333SShikha Singh 
27cab47333SShikha Singh /* supported protocols */
28cab47333SShikha Singh #define ST95HF_SUPPORTED_PROT		(NFC_PROTO_ISO14443_MASK | \
29cab47333SShikha Singh 					NFC_PROTO_ISO14443_B_MASK | \
30cab47333SShikha Singh 					NFC_PROTO_ISO15693_MASK)
31cab47333SShikha Singh /* driver capabilities */
32cab47333SShikha Singh #define ST95HF_CAPABILITIES		NFC_DIGITAL_DRV_CAPS_IN_CRC
33cab47333SShikha Singh 
34cab47333SShikha Singh /* Command Send Interface */
35cab47333SShikha Singh /* ST95HF_COMMAND_SEND CMD Ids */
36cab47333SShikha Singh #define ECHO_CMD			0x55
37cab47333SShikha Singh #define WRITE_REGISTER_CMD		0x9
38cab47333SShikha Singh #define PROTOCOL_SELECT_CMD		0x2
39cab47333SShikha Singh #define SEND_RECEIVE_CMD		0x4
40cab47333SShikha Singh 
41cab47333SShikha Singh /* Select protocol codes */
42cab47333SShikha Singh #define ISO15693_PROTOCOL_CODE		0x1
43cab47333SShikha Singh #define ISO14443A_PROTOCOL_CODE		0x2
44cab47333SShikha Singh #define ISO14443B_PROTOCOL_CODE		0x3
45cab47333SShikha Singh 
46cab47333SShikha Singh /*
47cab47333SShikha Singh  * head room len is 3
48cab47333SShikha Singh  * 1 byte for control byte
49cab47333SShikha Singh  * 1 byte for cmd
50cab47333SShikha Singh  * 1 byte for size
51cab47333SShikha Singh  */
52cab47333SShikha Singh #define ST95HF_HEADROOM_LEN		3
53cab47333SShikha Singh 
54cab47333SShikha Singh /*
55cab47333SShikha Singh  * tailroom is 1 for ISO14443A
56cab47333SShikha Singh  * and 0 for ISO14443B/ISO15693,
57cab47333SShikha Singh  * hence the max value 1 should be
58cab47333SShikha Singh  * taken.
59cab47333SShikha Singh  */
60cab47333SShikha Singh #define ST95HF_TAILROOM_LEN		1
61cab47333SShikha Singh 
62cab47333SShikha Singh /* Command Response interface */
63cab47333SShikha Singh #define MAX_RESPONSE_BUFFER_SIZE	280
64cab47333SShikha Singh #define ECHORESPONSE			0x55
65cab47333SShikha Singh #define ST95HF_ERR_MASK			0xF
66cab47333SShikha Singh #define ST95HF_TIMEOUT_ERROR		0x87
67cab47333SShikha Singh #define ST95HF_NFCA_CRC_ERR_MASK	0x20
68cab47333SShikha Singh #define ST95HF_NFCB_CRC_ERR_MASK	0x01
69cab47333SShikha Singh 
70cab47333SShikha Singh /* ST95HF transmission flag values */
71cab47333SShikha Singh #define TRFLAG_NFCA_SHORT_FRAME		0x07
72cab47333SShikha Singh #define TRFLAG_NFCA_STD_FRAME		0x08
73cab47333SShikha Singh #define TRFLAG_NFCA_STD_FRAME_CRC	0x28
74cab47333SShikha Singh 
75cab47333SShikha Singh /* Misc defs */
76cab47333SShikha Singh #define HIGH				1
77cab47333SShikha Singh #define LOW				0
78cab47333SShikha Singh #define ISO14443A_RATS_REQ		0xE0
79cab47333SShikha Singh #define RATS_TB1_PRESENT_MASK		0x20
80cab47333SShikha Singh #define RATS_TA1_PRESENT_MASK		0x10
81cab47333SShikha Singh #define TB1_FWI_MASK			0xF0
82cab47333SShikha Singh #define WTX_REQ_FROM_TAG		0xF2
83cab47333SShikha Singh 
84cab47333SShikha Singh #define MAX_CMD_LEN			0x7
85cab47333SShikha Singh 
86cab47333SShikha Singh #define MAX_CMD_PARAMS			4
87cab47333SShikha Singh struct cmd {
88cab47333SShikha Singh 	int cmd_len;
89cab47333SShikha Singh 	unsigned char cmd_id;
90cab47333SShikha Singh 	unsigned char no_cmd_params;
91cab47333SShikha Singh 	unsigned char cmd_params[MAX_CMD_PARAMS];
92cab47333SShikha Singh 	enum req_type req;
93cab47333SShikha Singh };
94cab47333SShikha Singh 
95cab47333SShikha Singh struct param_list {
96cab47333SShikha Singh 	int param_offset;
97cab47333SShikha Singh 	int new_param_val;
98cab47333SShikha Singh };
99cab47333SShikha Singh 
100cab47333SShikha Singh /*
101cab47333SShikha Singh  * List of top-level cmds to be used internally by the driver.
102cab47333SShikha Singh  * All these commands are build on top of ST95HF basic commands
103cab47333SShikha Singh  * such as SEND_RECEIVE_CMD, PROTOCOL_SELECT_CMD, etc.
104cab47333SShikha Singh  * These top level cmds are used internally while implementing various ops of
105cab47333SShikha Singh  * digital layer/driver probe or extending the digital framework layer for
106cab47333SShikha Singh  * features that are not yet implemented there, for example, WTX cmd handling.
107cab47333SShikha Singh  */
108cab47333SShikha Singh enum st95hf_cmd_list {
109cab47333SShikha Singh 	CMD_ECHO,
110cab47333SShikha Singh 	CMD_ISO14443A_CONFIG,
111cab47333SShikha Singh 	CMD_ISO14443A_DEMOGAIN,
112cab47333SShikha Singh 	CMD_ISO14443B_DEMOGAIN,
113cab47333SShikha Singh 	CMD_ISO14443A_PROTOCOL_SELECT,
114cab47333SShikha Singh 	CMD_ISO14443B_PROTOCOL_SELECT,
115cab47333SShikha Singh 	CMD_WTX_RESPONSE,
116cab47333SShikha Singh 	CMD_FIELD_OFF,
117cab47333SShikha Singh 	CMD_ISO15693_PROTOCOL_SELECT,
118cab47333SShikha Singh };
119cab47333SShikha Singh 
120cab47333SShikha Singh static const struct cmd cmd_array[] = {
121cab47333SShikha Singh 	[CMD_ECHO] = {
122cab47333SShikha Singh 		.cmd_len = 0x2,
123cab47333SShikha Singh 		.cmd_id = ECHO_CMD,
124cab47333SShikha Singh 		.no_cmd_params = 0,
125cab47333SShikha Singh 		.req = SYNC,
126cab47333SShikha Singh 	},
127cab47333SShikha Singh 	[CMD_ISO14443A_CONFIG] = {
128cab47333SShikha Singh 		.cmd_len = 0x7,
129cab47333SShikha Singh 		.cmd_id = WRITE_REGISTER_CMD,
130cab47333SShikha Singh 		.no_cmd_params = 0x4,
131cab47333SShikha Singh 		.cmd_params = {0x3A, 0x00, 0x5A, 0x04},
132cab47333SShikha Singh 		.req = SYNC,
133cab47333SShikha Singh 	},
134cab47333SShikha Singh 	[CMD_ISO14443A_DEMOGAIN] = {
135cab47333SShikha Singh 		.cmd_len = 0x7,
136cab47333SShikha Singh 		.cmd_id = WRITE_REGISTER_CMD,
137cab47333SShikha Singh 		.no_cmd_params = 0x4,
138cab47333SShikha Singh 		.cmd_params = {0x68, 0x01, 0x01, 0xDF},
139cab47333SShikha Singh 		.req = SYNC,
140cab47333SShikha Singh 	},
141cab47333SShikha Singh 	[CMD_ISO14443B_DEMOGAIN] = {
142cab47333SShikha Singh 		.cmd_len = 0x7,
143cab47333SShikha Singh 		.cmd_id = WRITE_REGISTER_CMD,
144cab47333SShikha Singh 		.no_cmd_params = 0x4,
145cab47333SShikha Singh 		.cmd_params = {0x68, 0x01, 0x01, 0x51},
146cab47333SShikha Singh 		.req = SYNC,
147cab47333SShikha Singh 	},
148cab47333SShikha Singh 	[CMD_ISO14443A_PROTOCOL_SELECT] = {
149cab47333SShikha Singh 		.cmd_len = 0x7,
150cab47333SShikha Singh 		.cmd_id = PROTOCOL_SELECT_CMD,
151cab47333SShikha Singh 		.no_cmd_params = 0x4,
152cab47333SShikha Singh 		.cmd_params = {ISO14443A_PROTOCOL_CODE, 0x00, 0x01, 0xA0},
153cab47333SShikha Singh 		.req = SYNC,
154cab47333SShikha Singh 	},
155cab47333SShikha Singh 	[CMD_ISO14443B_PROTOCOL_SELECT] = {
156cab47333SShikha Singh 		.cmd_len = 0x7,
157cab47333SShikha Singh 		.cmd_id = PROTOCOL_SELECT_CMD,
158cab47333SShikha Singh 		.no_cmd_params = 0x4,
159cab47333SShikha Singh 		.cmd_params = {ISO14443B_PROTOCOL_CODE, 0x01, 0x03, 0xFF},
160cab47333SShikha Singh 		.req = SYNC,
161cab47333SShikha Singh 	},
162cab47333SShikha Singh 	[CMD_WTX_RESPONSE] = {
163cab47333SShikha Singh 		.cmd_len = 0x6,
164cab47333SShikha Singh 		.cmd_id = SEND_RECEIVE_CMD,
165cab47333SShikha Singh 		.no_cmd_params = 0x3,
166cab47333SShikha Singh 		.cmd_params = {0xF2, 0x00, TRFLAG_NFCA_STD_FRAME_CRC},
167cab47333SShikha Singh 		.req = ASYNC,
168cab47333SShikha Singh 	},
169cab47333SShikha Singh 	[CMD_FIELD_OFF] = {
170cab47333SShikha Singh 		.cmd_len = 0x5,
171cab47333SShikha Singh 		.cmd_id = PROTOCOL_SELECT_CMD,
172cab47333SShikha Singh 		.no_cmd_params = 0x2,
173cab47333SShikha Singh 		.cmd_params = {0x0, 0x0},
174cab47333SShikha Singh 		.req = SYNC,
175cab47333SShikha Singh 	},
176cab47333SShikha Singh 	[CMD_ISO15693_PROTOCOL_SELECT] = {
177cab47333SShikha Singh 		.cmd_len = 0x5,
178cab47333SShikha Singh 		.cmd_id = PROTOCOL_SELECT_CMD,
179cab47333SShikha Singh 		.no_cmd_params = 0x2,
180cab47333SShikha Singh 		.cmd_params = {ISO15693_PROTOCOL_CODE, 0x0D},
181cab47333SShikha Singh 		.req = SYNC,
182cab47333SShikha Singh 	},
183cab47333SShikha Singh };
184cab47333SShikha Singh 
185cab47333SShikha Singh /* st95_digital_cmd_complete_arg stores client context */
186cab47333SShikha Singh struct st95_digital_cmd_complete_arg {
187cab47333SShikha Singh 	struct sk_buff *skb_resp;
188cab47333SShikha Singh 	nfc_digital_cmd_complete_t complete_cb;
189cab47333SShikha Singh 	void *cb_usrarg;
190cab47333SShikha Singh 	bool rats;
191cab47333SShikha Singh };
192cab47333SShikha Singh 
193cab47333SShikha Singh /*
194cab47333SShikha Singh  * structure containing ST95HF driver specific data.
195cab47333SShikha Singh  * @spicontext: structure containing information required
196cab47333SShikha Singh  *	for spi communication between st95hf and host.
197cab47333SShikha Singh  * @ddev: nfc digital device object.
198cab47333SShikha Singh  * @nfcdev: nfc device object.
199cab47333SShikha Singh  * @enable_gpio: gpio used to enable st95hf transceiver.
200cab47333SShikha Singh  * @complete_cb_arg: structure to store various context information
201cab47333SShikha Singh  *	that is passed from nfc requesting thread to the threaded ISR.
202cab47333SShikha Singh  * @st95hf_supply: regulator "consumer" for NFC device.
203cab47333SShikha Singh  * @sendrcv_trflag: last byte of frame send by sendrecv command
204cab47333SShikha Singh  *	of st95hf. This byte contains transmission flag info.
205cab47333SShikha Singh  * @exchange_lock: semaphore used for signaling the st95hf_remove
206cab47333SShikha Singh  *	function that the last outstanding async nfc request is finished.
207cab47333SShikha Singh  * @rm_lock: mutex for ensuring safe access of nfc digital object
208cab47333SShikha Singh  *	from threaded ISR. Usage of this mutex avoids any race between
209cab47333SShikha Singh  *	deletion of the object from st95hf_remove() and its access from
210cab47333SShikha Singh  *	the threaded ISR.
211cab47333SShikha Singh  * @nfcdev_free: flag to have the state of nfc device object.
212cab47333SShikha Singh  *	[alive | died]
213cab47333SShikha Singh  * @current_protocol: current nfc protocol.
214cab47333SShikha Singh  * @current_rf_tech: current rf technology.
215cab47333SShikha Singh  * @fwi: frame waiting index, received in reply of RATS according to
216cab47333SShikha Singh  *	digital protocol.
217cab47333SShikha Singh  */
218cab47333SShikha Singh struct st95hf_context {
219cab47333SShikha Singh 	struct st95hf_spi_context spicontext;
220cab47333SShikha Singh 	struct nfc_digital_dev *ddev;
221cab47333SShikha Singh 	struct nfc_dev *nfcdev;
222cab47333SShikha Singh 	unsigned int enable_gpio;
223cab47333SShikha Singh 	struct st95_digital_cmd_complete_arg complete_cb_arg;
224cab47333SShikha Singh 	struct regulator *st95hf_supply;
225cab47333SShikha Singh 	unsigned char sendrcv_trflag;
226cab47333SShikha Singh 	struct semaphore exchange_lock;
227cab47333SShikha Singh 	struct mutex rm_lock;
228cab47333SShikha Singh 	bool nfcdev_free;
229cab47333SShikha Singh 	u8 current_protocol;
230cab47333SShikha Singh 	u8 current_rf_tech;
231cab47333SShikha Singh 	int fwi;
232cab47333SShikha Singh };
233cab47333SShikha Singh 
234cab47333SShikha Singh /*
235cab47333SShikha Singh  * st95hf_send_recv_cmd() is for sending commands to ST95HF
236cab47333SShikha Singh  * that are described in the cmd_array[]. It can optionally
237cab47333SShikha Singh  * receive the response if the cmd request is of type
238cab47333SShikha Singh  * SYNC. For that to happen caller must pass true to recv_res.
239cab47333SShikha Singh  * For ASYNC request, recv_res is ignored and the
240cab47333SShikha Singh  * function will never try to receive the response on behalf
241cab47333SShikha Singh  * of the caller.
242cab47333SShikha Singh  */
st95hf_send_recv_cmd(struct st95hf_context * st95context,enum st95hf_cmd_list cmd,int no_modif,struct param_list * list_array,bool recv_res)243cab47333SShikha Singh static int st95hf_send_recv_cmd(struct st95hf_context *st95context,
244cab47333SShikha Singh 				enum st95hf_cmd_list cmd,
245cab47333SShikha Singh 				int no_modif,
246cab47333SShikha Singh 				struct param_list *list_array,
247cab47333SShikha Singh 				bool recv_res)
248cab47333SShikha Singh {
249cab47333SShikha Singh 	unsigned char spi_cmd_buffer[MAX_CMD_LEN];
250cab47333SShikha Singh 	int i, ret;
251cab47333SShikha Singh 	struct device *dev = &st95context->spicontext.spidev->dev;
252cab47333SShikha Singh 
253cab47333SShikha Singh 	if (cmd_array[cmd].cmd_len > MAX_CMD_LEN)
254cab47333SShikha Singh 		return -EINVAL;
255cab47333SShikha Singh 	if (cmd_array[cmd].no_cmd_params < no_modif)
256cab47333SShikha Singh 		return -EINVAL;
257cab47333SShikha Singh 	if (no_modif && !list_array)
258cab47333SShikha Singh 		return -EINVAL;
259cab47333SShikha Singh 
260cab47333SShikha Singh 	spi_cmd_buffer[0] = ST95HF_COMMAND_SEND;
261cab47333SShikha Singh 	spi_cmd_buffer[1] = cmd_array[cmd].cmd_id;
262cab47333SShikha Singh 	spi_cmd_buffer[2] = cmd_array[cmd].no_cmd_params;
263cab47333SShikha Singh 
264cab47333SShikha Singh 	memcpy(&spi_cmd_buffer[3], cmd_array[cmd].cmd_params,
265cab47333SShikha Singh 	       spi_cmd_buffer[2]);
266cab47333SShikha Singh 
267cab47333SShikha Singh 	for (i = 0; i < no_modif; i++) {
268cab47333SShikha Singh 		if (list_array[i].param_offset >= cmd_array[cmd].no_cmd_params)
269cab47333SShikha Singh 			return -EINVAL;
270cab47333SShikha Singh 		spi_cmd_buffer[3 + list_array[i].param_offset] =
271cab47333SShikha Singh 						list_array[i].new_param_val;
272cab47333SShikha Singh 	}
273cab47333SShikha Singh 
274cab47333SShikha Singh 	ret = st95hf_spi_send(&st95context->spicontext,
275cab47333SShikha Singh 			      spi_cmd_buffer,
276cab47333SShikha Singh 			      cmd_array[cmd].cmd_len,
277cab47333SShikha Singh 			      cmd_array[cmd].req);
278cab47333SShikha Singh 	if (ret) {
279cab47333SShikha Singh 		dev_err(dev, "st95hf_spi_send failed with error %d\n", ret);
280cab47333SShikha Singh 		return ret;
281cab47333SShikha Singh 	}
282cab47333SShikha Singh 
283cab47333SShikha Singh 	if (cmd_array[cmd].req == SYNC && recv_res) {
284cab47333SShikha Singh 		unsigned char st95hf_response_arr[2];
285cab47333SShikha Singh 
286cab47333SShikha Singh 		ret = st95hf_spi_recv_response(&st95context->spicontext,
287cab47333SShikha Singh 					       st95hf_response_arr);
288cab47333SShikha Singh 		if (ret < 0) {
289cab47333SShikha Singh 			dev_err(dev, "spi error from st95hf_spi_recv_response(), err = 0x%x\n",
290cab47333SShikha Singh 				ret);
291cab47333SShikha Singh 			return ret;
292cab47333SShikha Singh 		}
293cab47333SShikha Singh 
294cab47333SShikha Singh 		if (st95hf_response_arr[0]) {
295cab47333SShikha Singh 			dev_err(dev, "st95hf error from st95hf_spi_recv_response(), err = 0x%x\n",
296cab47333SShikha Singh 				st95hf_response_arr[0]);
297cab47333SShikha Singh 			return -EIO;
298cab47333SShikha Singh 		}
299cab47333SShikha Singh 	}
300cab47333SShikha Singh 
301cab47333SShikha Singh 	return 0;
302cab47333SShikha Singh }
303cab47333SShikha Singh 
st95hf_echo_command(struct st95hf_context * st95context)304cab47333SShikha Singh static int st95hf_echo_command(struct st95hf_context *st95context)
305cab47333SShikha Singh {
306cab47333SShikha Singh 	int result = 0;
307cab47333SShikha Singh 	unsigned char echo_response;
308cab47333SShikha Singh 
309cab47333SShikha Singh 	result = st95hf_send_recv_cmd(st95context, CMD_ECHO, 0, NULL, false);
310cab47333SShikha Singh 	if (result)
311cab47333SShikha Singh 		return result;
312cab47333SShikha Singh 
313cab47333SShikha Singh 	/* If control reached here, response can be taken */
314cab47333SShikha Singh 	result = st95hf_spi_recv_echo_res(&st95context->spicontext,
315cab47333SShikha Singh 					  &echo_response);
316cab47333SShikha Singh 	if (result) {
317cab47333SShikha Singh 		dev_err(&st95context->spicontext.spidev->dev,
31890aa11f1SColin Ian King 			"err: echo response receive error = 0x%x\n", result);
319cab47333SShikha Singh 		return result;
320cab47333SShikha Singh 	}
321cab47333SShikha Singh 
322cab47333SShikha Singh 	if (echo_response == ECHORESPONSE)
323cab47333SShikha Singh 		return 0;
324cab47333SShikha Singh 
325cab47333SShikha Singh 	dev_err(&st95context->spicontext.spidev->dev, "err: echo res is 0x%x\n",
326cab47333SShikha Singh 		echo_response);
327cab47333SShikha Singh 
328cab47333SShikha Singh 	return -EIO;
329cab47333SShikha Singh }
330cab47333SShikha Singh 
secondary_configuration_type4a(struct st95hf_context * stcontext)331cab47333SShikha Singh static int secondary_configuration_type4a(struct st95hf_context *stcontext)
332cab47333SShikha Singh {
333cab47333SShikha Singh 	int result = 0;
334cab47333SShikha Singh 	struct device *dev = &stcontext->nfcdev->dev;
335cab47333SShikha Singh 
336cab47333SShikha Singh 	/* 14443A config setting after select protocol */
337cab47333SShikha Singh 	result = st95hf_send_recv_cmd(stcontext,
338cab47333SShikha Singh 				      CMD_ISO14443A_CONFIG,
339cab47333SShikha Singh 				      0,
340cab47333SShikha Singh 				      NULL,
341cab47333SShikha Singh 				      true);
342cab47333SShikha Singh 	if (result) {
343cab47333SShikha Singh 		dev_err(dev, "type a config cmd, err = 0x%x\n", result);
344cab47333SShikha Singh 		return result;
345cab47333SShikha Singh 	}
346cab47333SShikha Singh 
347cab47333SShikha Singh 	/* 14443A demo gain setting */
348cab47333SShikha Singh 	result = st95hf_send_recv_cmd(stcontext,
349cab47333SShikha Singh 				      CMD_ISO14443A_DEMOGAIN,
350cab47333SShikha Singh 				      0,
351cab47333SShikha Singh 				      NULL,
352cab47333SShikha Singh 				      true);
353cab47333SShikha Singh 	if (result)
354cab47333SShikha Singh 		dev_err(dev, "type a demogain cmd, err = 0x%x\n", result);
355cab47333SShikha Singh 
356cab47333SShikha Singh 	return result;
357cab47333SShikha Singh }
358cab47333SShikha Singh 
secondary_configuration_type4b(struct st95hf_context * stcontext)359cab47333SShikha Singh static int secondary_configuration_type4b(struct st95hf_context *stcontext)
360cab47333SShikha Singh {
361cab47333SShikha Singh 	int result = 0;
362cab47333SShikha Singh 	struct device *dev = &stcontext->nfcdev->dev;
363cab47333SShikha Singh 
364cab47333SShikha Singh 	result = st95hf_send_recv_cmd(stcontext,
365cab47333SShikha Singh 				      CMD_ISO14443B_DEMOGAIN,
366cab47333SShikha Singh 				      0,
367cab47333SShikha Singh 				      NULL,
368cab47333SShikha Singh 				      true);
369cab47333SShikha Singh 	if (result)
370cab47333SShikha Singh 		dev_err(dev, "type b demogain cmd, err = 0x%x\n", result);
371cab47333SShikha Singh 
372cab47333SShikha Singh 	return result;
373cab47333SShikha Singh }
374cab47333SShikha Singh 
st95hf_select_protocol(struct st95hf_context * stcontext,int type)375cab47333SShikha Singh static int st95hf_select_protocol(struct st95hf_context *stcontext, int type)
376cab47333SShikha Singh {
377cab47333SShikha Singh 	int result = 0;
378cab47333SShikha Singh 	struct device *dev;
379cab47333SShikha Singh 
380cab47333SShikha Singh 	dev = &stcontext->nfcdev->dev;
381cab47333SShikha Singh 
382cab47333SShikha Singh 	switch (type) {
383cab47333SShikha Singh 	case NFC_DIGITAL_RF_TECH_106A:
384cab47333SShikha Singh 		stcontext->current_rf_tech = NFC_DIGITAL_RF_TECH_106A;
385cab47333SShikha Singh 		result = st95hf_send_recv_cmd(stcontext,
386cab47333SShikha Singh 					      CMD_ISO14443A_PROTOCOL_SELECT,
387cab47333SShikha Singh 					      0,
388cab47333SShikha Singh 					      NULL,
389cab47333SShikha Singh 					      true);
390cab47333SShikha Singh 		if (result) {
391cab47333SShikha Singh 			dev_err(dev, "protocol sel, err = 0x%x\n",
392cab47333SShikha Singh 				result);
393cab47333SShikha Singh 			return result;
394cab47333SShikha Singh 		}
395cab47333SShikha Singh 
396cab47333SShikha Singh 		/* secondary config. for 14443Type 4A after protocol select */
397cab47333SShikha Singh 		result = secondary_configuration_type4a(stcontext);
398cab47333SShikha Singh 		if (result) {
399cab47333SShikha Singh 			dev_err(dev, "type a secondary config, err = 0x%x\n",
400cab47333SShikha Singh 				result);
401cab47333SShikha Singh 			return result;
402cab47333SShikha Singh 		}
403cab47333SShikha Singh 		break;
404cab47333SShikha Singh 	case NFC_DIGITAL_RF_TECH_106B:
405cab47333SShikha Singh 		stcontext->current_rf_tech = NFC_DIGITAL_RF_TECH_106B;
406cab47333SShikha Singh 		result = st95hf_send_recv_cmd(stcontext,
407cab47333SShikha Singh 					      CMD_ISO14443B_PROTOCOL_SELECT,
408cab47333SShikha Singh 					      0,
409cab47333SShikha Singh 					      NULL,
410cab47333SShikha Singh 					      true);
411cab47333SShikha Singh 		if (result) {
412cab47333SShikha Singh 			dev_err(dev, "protocol sel send, err = 0x%x\n",
413cab47333SShikha Singh 				result);
414cab47333SShikha Singh 			return result;
415cab47333SShikha Singh 		}
416cab47333SShikha Singh 
417cab47333SShikha Singh 		/*
418cab47333SShikha Singh 		 * delay of 5-6 ms is required after select protocol
419cab47333SShikha Singh 		 * command in case of ISO14443 Type B
420cab47333SShikha Singh 		 */
421cab47333SShikha Singh 		usleep_range(50000, 60000);
422cab47333SShikha Singh 
423cab47333SShikha Singh 		/* secondary config. for 14443Type 4B after protocol select */
424cab47333SShikha Singh 		result = secondary_configuration_type4b(stcontext);
425cab47333SShikha Singh 		if (result) {
426cab47333SShikha Singh 			dev_err(dev, "type b secondary config, err = 0x%x\n",
427cab47333SShikha Singh 				result);
428cab47333SShikha Singh 			return result;
429cab47333SShikha Singh 		}
430cab47333SShikha Singh 		break;
431cab47333SShikha Singh 	case NFC_DIGITAL_RF_TECH_ISO15693:
432cab47333SShikha Singh 		stcontext->current_rf_tech = NFC_DIGITAL_RF_TECH_ISO15693;
433cab47333SShikha Singh 		result = st95hf_send_recv_cmd(stcontext,
434cab47333SShikha Singh 					      CMD_ISO15693_PROTOCOL_SELECT,
435cab47333SShikha Singh 					      0,
436cab47333SShikha Singh 					      NULL,
437cab47333SShikha Singh 					      true);
438cab47333SShikha Singh 		if (result) {
439cab47333SShikha Singh 			dev_err(dev, "protocol sel send, err = 0x%x\n",
440cab47333SShikha Singh 				result);
441cab47333SShikha Singh 			return result;
442cab47333SShikha Singh 		}
443cab47333SShikha Singh 		break;
444cab47333SShikha Singh 	default:
445cab47333SShikha Singh 		return -EINVAL;
446cab47333SShikha Singh 	}
447cab47333SShikha Singh 
448cab47333SShikha Singh 	return 0;
449cab47333SShikha Singh }
450cab47333SShikha Singh 
st95hf_send_st95enable_negativepulse(struct st95hf_context * st95con)451cab47333SShikha Singh static void st95hf_send_st95enable_negativepulse(struct st95hf_context *st95con)
452cab47333SShikha Singh {
453cab47333SShikha Singh 	/* First make irq_in pin high */
454cab47333SShikha Singh 	gpio_set_value(st95con->enable_gpio, HIGH);
455cab47333SShikha Singh 
456cab47333SShikha Singh 	/* wait for 1 milisecond */
457cab47333SShikha Singh 	usleep_range(1000, 2000);
458cab47333SShikha Singh 
459cab47333SShikha Singh 	/* Make irq_in pin low */
460cab47333SShikha Singh 	gpio_set_value(st95con->enable_gpio, LOW);
461cab47333SShikha Singh 
462cab47333SShikha Singh 	/* wait for minimum interrupt pulse to make st95 active */
463cab47333SShikha Singh 	usleep_range(1000, 2000);
464cab47333SShikha Singh 
465cab47333SShikha Singh 	/* At end make it high */
466cab47333SShikha Singh 	gpio_set_value(st95con->enable_gpio, HIGH);
467cab47333SShikha Singh }
468cab47333SShikha Singh 
469cab47333SShikha Singh /*
470cab47333SShikha Singh  * Send a reset sequence over SPI bus (Reset command + wait 3ms +
471cab47333SShikha Singh  * negative pulse on st95hf enable gpio
472cab47333SShikha Singh  */
st95hf_send_spi_reset_sequence(struct st95hf_context * st95context)473cab47333SShikha Singh static int st95hf_send_spi_reset_sequence(struct st95hf_context *st95context)
474cab47333SShikha Singh {
475cab47333SShikha Singh 	int result = 0;
476cab47333SShikha Singh 	unsigned char reset_cmd = ST95HF_COMMAND_RESET;
477cab47333SShikha Singh 
478cab47333SShikha Singh 	result = st95hf_spi_send(&st95context->spicontext,
479cab47333SShikha Singh 				 &reset_cmd,
480cab47333SShikha Singh 				 ST95HF_RESET_CMD_LEN,
481cab47333SShikha Singh 				 ASYNC);
482cab47333SShikha Singh 	if (result) {
483cab47333SShikha Singh 		dev_err(&st95context->spicontext.spidev->dev,
484cab47333SShikha Singh 			"spi reset sequence cmd error = %d", result);
485cab47333SShikha Singh 		return result;
486cab47333SShikha Singh 	}
487cab47333SShikha Singh 
488cab47333SShikha Singh 	/* wait for 3 milisecond to complete the controller reset process */
489cab47333SShikha Singh 	usleep_range(3000, 4000);
490cab47333SShikha Singh 
491cab47333SShikha Singh 	/* send negative pulse to make st95hf active */
492cab47333SShikha Singh 	st95hf_send_st95enable_negativepulse(st95context);
493cab47333SShikha Singh 
494cab47333SShikha Singh 	/* wait for 10 milisecond : HFO setup time */
495cab47333SShikha Singh 	usleep_range(10000, 20000);
496cab47333SShikha Singh 
497cab47333SShikha Singh 	return result;
498cab47333SShikha Singh }
499cab47333SShikha Singh 
st95hf_por_sequence(struct st95hf_context * st95context)500cab47333SShikha Singh static int st95hf_por_sequence(struct st95hf_context *st95context)
501cab47333SShikha Singh {
502cab47333SShikha Singh 	int nth_attempt = 1;
503cab47333SShikha Singh 	int result;
504cab47333SShikha Singh 
505cab47333SShikha Singh 	st95hf_send_st95enable_negativepulse(st95context);
506cab47333SShikha Singh 
507cab47333SShikha Singh 	usleep_range(5000, 6000);
508cab47333SShikha Singh 	do {
509cab47333SShikha Singh 		/* send an ECHO command and checks ST95HF response */
510cab47333SShikha Singh 		result = st95hf_echo_command(st95context);
511cab47333SShikha Singh 
512cab47333SShikha Singh 		dev_dbg(&st95context->spicontext.spidev->dev,
513cab47333SShikha Singh 			"response from echo function = 0x%x, attempt = %d\n",
514cab47333SShikha Singh 			result, nth_attempt);
515cab47333SShikha Singh 
516cab47333SShikha Singh 		if (!result)
517cab47333SShikha Singh 			return 0;
518cab47333SShikha Singh 
519cab47333SShikha Singh 		/* send an pulse on IRQ in case of the chip is on sleep state */
520cab47333SShikha Singh 		if (nth_attempt == 2)
521cab47333SShikha Singh 			st95hf_send_st95enable_negativepulse(st95context);
522cab47333SShikha Singh 		else
523cab47333SShikha Singh 			st95hf_send_spi_reset_sequence(st95context);
524cab47333SShikha Singh 
525cab47333SShikha Singh 		/* delay of 50 milisecond */
526cab47333SShikha Singh 		usleep_range(50000, 51000);
527cab47333SShikha Singh 	} while (nth_attempt++ < 3);
528cab47333SShikha Singh 
529cab47333SShikha Singh 	return -ETIMEDOUT;
530cab47333SShikha Singh }
531cab47333SShikha Singh 
iso14443_config_fdt(struct st95hf_context * st95context,int wtxm)532cab47333SShikha Singh static int iso14443_config_fdt(struct st95hf_context *st95context, int wtxm)
533cab47333SShikha Singh {
534cab47333SShikha Singh 	int result = 0;
535cab47333SShikha Singh 	struct device *dev = &st95context->spicontext.spidev->dev;
536cab47333SShikha Singh 	struct nfc_digital_dev *nfcddev = st95context->ddev;
537cab47333SShikha Singh 	unsigned char pp_typeb;
538cab47333SShikha Singh 	struct param_list new_params[2];
539cab47333SShikha Singh 
540cab47333SShikha Singh 	pp_typeb = cmd_array[CMD_ISO14443B_PROTOCOL_SELECT].cmd_params[2];
541cab47333SShikha Singh 
542cab47333SShikha Singh 	if (nfcddev->curr_protocol == NFC_PROTO_ISO14443 &&
543cab47333SShikha Singh 	    st95context->fwi < 4)
544cab47333SShikha Singh 		st95context->fwi = 4;
545cab47333SShikha Singh 
546cab47333SShikha Singh 	new_params[0].param_offset = 2;
547cab47333SShikha Singh 	if (nfcddev->curr_protocol == NFC_PROTO_ISO14443)
548cab47333SShikha Singh 		new_params[0].new_param_val = st95context->fwi;
549cab47333SShikha Singh 	else if (nfcddev->curr_protocol == NFC_PROTO_ISO14443_B)
550cab47333SShikha Singh 		new_params[0].new_param_val = pp_typeb;
551cab47333SShikha Singh 
552cab47333SShikha Singh 	new_params[1].param_offset = 3;
553cab47333SShikha Singh 	new_params[1].new_param_val = wtxm;
554cab47333SShikha Singh 
555cab47333SShikha Singh 	switch (nfcddev->curr_protocol) {
556cab47333SShikha Singh 	case NFC_PROTO_ISO14443:
557cab47333SShikha Singh 		result = st95hf_send_recv_cmd(st95context,
558cab47333SShikha Singh 					      CMD_ISO14443A_PROTOCOL_SELECT,
559cab47333SShikha Singh 					      2,
560cab47333SShikha Singh 					      new_params,
561cab47333SShikha Singh 					      true);
562cab47333SShikha Singh 		if (result) {
563cab47333SShikha Singh 			dev_err(dev, "WTX type a sel proto, err = 0x%x\n",
564cab47333SShikha Singh 				result);
565cab47333SShikha Singh 			return result;
566cab47333SShikha Singh 		}
567cab47333SShikha Singh 
568cab47333SShikha Singh 		/* secondary config. for 14443Type 4A after protocol select */
569cab47333SShikha Singh 		result = secondary_configuration_type4a(st95context);
570cab47333SShikha Singh 		if (result) {
571cab47333SShikha Singh 			dev_err(dev, "WTX type a second. config, err = 0x%x\n",
572cab47333SShikha Singh 				result);
573cab47333SShikha Singh 			return result;
574cab47333SShikha Singh 		}
575cab47333SShikha Singh 		break;
576cab47333SShikha Singh 	case NFC_PROTO_ISO14443_B:
577cab47333SShikha Singh 		result = st95hf_send_recv_cmd(st95context,
578cab47333SShikha Singh 					      CMD_ISO14443B_PROTOCOL_SELECT,
579cab47333SShikha Singh 					      2,
580cab47333SShikha Singh 					      new_params,
581cab47333SShikha Singh 					      true);
582cab47333SShikha Singh 		if (result) {
583cab47333SShikha Singh 			dev_err(dev, "WTX type b sel proto, err = 0x%x\n",
584cab47333SShikha Singh 				result);
585cab47333SShikha Singh 			return result;
586cab47333SShikha Singh 		}
587cab47333SShikha Singh 
588cab47333SShikha Singh 		/* secondary config. for 14443Type 4B after protocol select */
589cab47333SShikha Singh 		result = secondary_configuration_type4b(st95context);
590cab47333SShikha Singh 		if (result) {
591cab47333SShikha Singh 			dev_err(dev, "WTX type b second. config, err = 0x%x\n",
592cab47333SShikha Singh 				result);
593cab47333SShikha Singh 			return result;
594cab47333SShikha Singh 		}
595cab47333SShikha Singh 		break;
596cab47333SShikha Singh 	default:
597cab47333SShikha Singh 		return -EINVAL;
598cab47333SShikha Singh 	}
599cab47333SShikha Singh 
600cab47333SShikha Singh 	return 0;
601cab47333SShikha Singh }
602cab47333SShikha Singh 
st95hf_handle_wtx(struct st95hf_context * stcontext,bool new_wtx,int wtx_val)603cab47333SShikha Singh static int st95hf_handle_wtx(struct st95hf_context *stcontext,
604cab47333SShikha Singh 			     bool new_wtx,
605cab47333SShikha Singh 			     int wtx_val)
606cab47333SShikha Singh {
607cab47333SShikha Singh 	int result = 0;
608cab47333SShikha Singh 	unsigned char val_mm = 0;
609cab47333SShikha Singh 	struct param_list new_params[1];
610cab47333SShikha Singh 	struct nfc_digital_dev *nfcddev = stcontext->ddev;
611cab47333SShikha Singh 	struct device *dev = &stcontext->nfcdev->dev;
612cab47333SShikha Singh 
613cab47333SShikha Singh 	if (new_wtx) {
614cab47333SShikha Singh 		result = iso14443_config_fdt(stcontext, wtx_val & 0x3f);
615cab47333SShikha Singh 		if (result) {
616cab47333SShikha Singh 			dev_err(dev, "Config. setting error on WTX req, err = 0x%x\n",
617cab47333SShikha Singh 				result);
618cab47333SShikha Singh 			return result;
619cab47333SShikha Singh 		}
620cab47333SShikha Singh 
621cab47333SShikha Singh 		/* Send response of wtx with ASYNC as no response expected */
622cab47333SShikha Singh 		new_params[0].param_offset = 1;
623cab47333SShikha Singh 		new_params[0].new_param_val = wtx_val;
624cab47333SShikha Singh 
625cab47333SShikha Singh 		result = st95hf_send_recv_cmd(stcontext,
626cab47333SShikha Singh 					      CMD_WTX_RESPONSE,
627cab47333SShikha Singh 					      1,
628cab47333SShikha Singh 					      new_params,
629cab47333SShikha Singh 					      false);
630cab47333SShikha Singh 		if (result)
631cab47333SShikha Singh 			dev_err(dev, "WTX response send, err = 0x%x\n", result);
632cab47333SShikha Singh 		return result;
633cab47333SShikha Singh 	}
634cab47333SShikha Singh 
635cab47333SShikha Singh 	/* if no new wtx, cofigure with default values */
636cab47333SShikha Singh 	if (nfcddev->curr_protocol == NFC_PROTO_ISO14443)
637cab47333SShikha Singh 		val_mm = cmd_array[CMD_ISO14443A_PROTOCOL_SELECT].cmd_params[3];
638cab47333SShikha Singh 	else if (nfcddev->curr_protocol == NFC_PROTO_ISO14443_B)
639cab47333SShikha Singh 		val_mm = cmd_array[CMD_ISO14443B_PROTOCOL_SELECT].cmd_params[3];
640cab47333SShikha Singh 
641cab47333SShikha Singh 	result = iso14443_config_fdt(stcontext, val_mm);
642cab47333SShikha Singh 	if (result)
643cab47333SShikha Singh 		dev_err(dev, "Default config. setting error after WTX processing, err = 0x%x\n",
644cab47333SShikha Singh 			result);
645cab47333SShikha Singh 
646cab47333SShikha Singh 	return result;
647cab47333SShikha Singh }
648cab47333SShikha Singh 
st95hf_error_handling(struct st95hf_context * stcontext,struct sk_buff * skb_resp,int res_len)649cab47333SShikha Singh static int st95hf_error_handling(struct st95hf_context *stcontext,
650cab47333SShikha Singh 				 struct sk_buff *skb_resp,
651cab47333SShikha Singh 				 int res_len)
652cab47333SShikha Singh {
653cab47333SShikha Singh 	int result = 0;
654cab47333SShikha Singh 	unsigned char error_byte;
655cab47333SShikha Singh 	struct device *dev = &stcontext->nfcdev->dev;
656cab47333SShikha Singh 
657cab47333SShikha Singh 	/* First check ST95HF specific error */
658cab47333SShikha Singh 	if (skb_resp->data[0] & ST95HF_ERR_MASK) {
659cab47333SShikha Singh 		if (skb_resp->data[0] == ST95HF_TIMEOUT_ERROR)
660cab47333SShikha Singh 			result = -ETIMEDOUT;
661cab47333SShikha Singh 		else
662cab47333SShikha Singh 			result = -EIO;
663cab47333SShikha Singh 		return result;
664cab47333SShikha Singh 	}
665cab47333SShikha Singh 
666cab47333SShikha Singh 	/* Check for CRC err only if CRC is present in the tag response */
667cab47333SShikha Singh 	switch (stcontext->current_rf_tech) {
668cab47333SShikha Singh 	case NFC_DIGITAL_RF_TECH_106A:
669cab47333SShikha Singh 		if (stcontext->sendrcv_trflag == TRFLAG_NFCA_STD_FRAME_CRC) {
670cab47333SShikha Singh 			error_byte = skb_resp->data[res_len - 3];
671cab47333SShikha Singh 			if (error_byte & ST95HF_NFCA_CRC_ERR_MASK) {
672cab47333SShikha Singh 				/* CRC error occurred */
673cab47333SShikha Singh 				dev_err(dev, "CRC error, byte received = 0x%x\n",
674cab47333SShikha Singh 					error_byte);
675cab47333SShikha Singh 				result = -EIO;
676cab47333SShikha Singh 			}
677cab47333SShikha Singh 		}
678cab47333SShikha Singh 		break;
679cab47333SShikha Singh 	case NFC_DIGITAL_RF_TECH_106B:
680cab47333SShikha Singh 	case NFC_DIGITAL_RF_TECH_ISO15693:
681cab47333SShikha Singh 		error_byte = skb_resp->data[res_len - 1];
682cab47333SShikha Singh 		if (error_byte & ST95HF_NFCB_CRC_ERR_MASK) {
683cab47333SShikha Singh 			/* CRC error occurred */
684cab47333SShikha Singh 			dev_err(dev, "CRC error, byte received = 0x%x\n",
685cab47333SShikha Singh 				error_byte);
686cab47333SShikha Singh 			result = -EIO;
687cab47333SShikha Singh 		}
688cab47333SShikha Singh 		break;
689cab47333SShikha Singh 	}
690cab47333SShikha Singh 
691cab47333SShikha Singh 	return result;
692cab47333SShikha Singh }
693cab47333SShikha Singh 
st95hf_response_handler(struct st95hf_context * stcontext,struct sk_buff * skb_resp,int res_len)694cab47333SShikha Singh static int st95hf_response_handler(struct st95hf_context *stcontext,
695cab47333SShikha Singh 				   struct sk_buff *skb_resp,
696cab47333SShikha Singh 				   int res_len)
697cab47333SShikha Singh {
698cab47333SShikha Singh 	int result = 0;
699cab47333SShikha Singh 	int skb_len;
700cab47333SShikha Singh 	unsigned char val_mm;
701cab47333SShikha Singh 	struct nfc_digital_dev *nfcddev = stcontext->ddev;
702cab47333SShikha Singh 	struct device *dev = &stcontext->nfcdev->dev;
703cab47333SShikha Singh 	struct st95_digital_cmd_complete_arg *cb_arg;
704cab47333SShikha Singh 
705cab47333SShikha Singh 	cb_arg = &stcontext->complete_cb_arg;
706cab47333SShikha Singh 
707cab47333SShikha Singh 	/* Process the response */
708cab47333SShikha Singh 	skb_put(skb_resp, res_len);
709cab47333SShikha Singh 
710cab47333SShikha Singh 	/* Remove st95 header */
711cab47333SShikha Singh 	skb_pull(skb_resp, 2);
712cab47333SShikha Singh 
713cab47333SShikha Singh 	skb_len = skb_resp->len;
714cab47333SShikha Singh 
715cab47333SShikha Singh 	/* check if it is case of RATS request reply & FWI is present */
716cab47333SShikha Singh 	if (nfcddev->curr_protocol == NFC_PROTO_ISO14443 && cb_arg->rats &&
717cab47333SShikha Singh 	    (skb_resp->data[1] & RATS_TB1_PRESENT_MASK)) {
718cab47333SShikha Singh 		if (skb_resp->data[1] & RATS_TA1_PRESENT_MASK)
719cab47333SShikha Singh 			stcontext->fwi =
720cab47333SShikha Singh 				(skb_resp->data[3] & TB1_FWI_MASK) >> 4;
721cab47333SShikha Singh 		else
722cab47333SShikha Singh 			stcontext->fwi =
723cab47333SShikha Singh 				(skb_resp->data[2] & TB1_FWI_MASK) >> 4;
724cab47333SShikha Singh 
725cab47333SShikha Singh 		val_mm = cmd_array[CMD_ISO14443A_PROTOCOL_SELECT].cmd_params[3];
726cab47333SShikha Singh 
727cab47333SShikha Singh 		result = iso14443_config_fdt(stcontext, val_mm);
728cab47333SShikha Singh 		if (result) {
729cab47333SShikha Singh 			dev_err(dev, "error in config_fdt to handle fwi of ATS, error=%d\n",
730cab47333SShikha Singh 				result);
731cab47333SShikha Singh 			return result;
732cab47333SShikha Singh 		}
733cab47333SShikha Singh 	}
734cab47333SShikha Singh 	cb_arg->rats = false;
735cab47333SShikha Singh 
736cab47333SShikha Singh 	/* Remove CRC bytes only if received frames data has an eod (CRC) */
737cab47333SShikha Singh 	switch (stcontext->current_rf_tech) {
738cab47333SShikha Singh 	case NFC_DIGITAL_RF_TECH_106A:
739cab47333SShikha Singh 		if (stcontext->sendrcv_trflag == TRFLAG_NFCA_STD_FRAME_CRC)
740cab47333SShikha Singh 			skb_trim(skb_resp, (skb_len - 5));
741cab47333SShikha Singh 		else
742cab47333SShikha Singh 			skb_trim(skb_resp, (skb_len - 3));
743cab47333SShikha Singh 		break;
744cab47333SShikha Singh 	case NFC_DIGITAL_RF_TECH_106B:
745cab47333SShikha Singh 	case NFC_DIGITAL_RF_TECH_ISO15693:
746cab47333SShikha Singh 		skb_trim(skb_resp, (skb_len - 3));
747cab47333SShikha Singh 		break;
748cab47333SShikha Singh 	}
749cab47333SShikha Singh 
750cab47333SShikha Singh 	return result;
751cab47333SShikha Singh }
752cab47333SShikha Singh 
st95hf_irq_handler(int irq,void * st95hfcontext)7536b52d994SShikha Singh static irqreturn_t st95hf_irq_handler(int irq, void  *st95hfcontext)
754cab47333SShikha Singh {
755cab47333SShikha Singh 	struct st95hf_context *stcontext  =
756cab47333SShikha Singh 		(struct st95hf_context *)st95hfcontext;
757cab47333SShikha Singh 
758cab47333SShikha Singh 	if (stcontext->spicontext.req_issync) {
759cab47333SShikha Singh 		complete(&stcontext->spicontext.done);
760cab47333SShikha Singh 		stcontext->spicontext.req_issync = false;
761cab47333SShikha Singh 		return IRQ_HANDLED;
762cab47333SShikha Singh 	}
763cab47333SShikha Singh 
764cab47333SShikha Singh 	return IRQ_WAKE_THREAD;
765cab47333SShikha Singh }
766cab47333SShikha Singh 
st95hf_irq_thread_handler(int irq,void * st95hfcontext)7676b52d994SShikha Singh static irqreturn_t st95hf_irq_thread_handler(int irq, void  *st95hfcontext)
768cab47333SShikha Singh {
769cab47333SShikha Singh 	int result = 0;
770cab47333SShikha Singh 	int res_len;
771cab47333SShikha Singh 	static bool wtx;
772cab47333SShikha Singh 	struct device *spidevice;
773cab47333SShikha Singh 	struct sk_buff *skb_resp;
774cab47333SShikha Singh 	struct st95hf_context *stcontext  =
775cab47333SShikha Singh 		(struct st95hf_context *)st95hfcontext;
776cab47333SShikha Singh 	struct st95_digital_cmd_complete_arg *cb_arg;
777cab47333SShikha Singh 
778cab47333SShikha Singh 	spidevice = &stcontext->spicontext.spidev->dev;
779cab47333SShikha Singh 
780cab47333SShikha Singh 	/*
781cab47333SShikha Singh 	 * check semaphore, if not down() already, then we don't
782cab47333SShikha Singh 	 * know in which context the ISR is called and surely it
783cab47333SShikha Singh 	 * will be a bug. Note that down() of the semaphore is done
784cab47333SShikha Singh 	 * in the corresponding st95hf_in_send_cmd() and then
785cab47333SShikha Singh 	 * only this ISR should be called. ISR will up() the
786cab47333SShikha Singh 	 * semaphore before leaving. Hence when the ISR is called
787cab47333SShikha Singh 	 * the correct behaviour is down_trylock() should always
788cab47333SShikha Singh 	 * return 1 (indicating semaphore cant be taken and hence no
789cab47333SShikha Singh 	 * change in semaphore count).
790cab47333SShikha Singh 	 * If not, then we up() the semaphore and crash on
791cab47333SShikha Singh 	 * a BUG() !
792cab47333SShikha Singh 	 */
793cab47333SShikha Singh 	if (!down_trylock(&stcontext->exchange_lock)) {
794cab47333SShikha Singh 		up(&stcontext->exchange_lock);
795cab47333SShikha Singh 		WARN(1, "unknown context in ST95HF ISR");
796cab47333SShikha Singh 		return IRQ_NONE;
797cab47333SShikha Singh 	}
798cab47333SShikha Singh 
799cab47333SShikha Singh 	cb_arg = &stcontext->complete_cb_arg;
800cab47333SShikha Singh 	skb_resp = cb_arg->skb_resp;
801cab47333SShikha Singh 
802cab47333SShikha Singh 	mutex_lock(&stcontext->rm_lock);
803cab47333SShikha Singh 	res_len = st95hf_spi_recv_response(&stcontext->spicontext,
804cab47333SShikha Singh 					   skb_resp->data);
805cab47333SShikha Singh 	if (res_len < 0) {
806cab47333SShikha Singh 		dev_err(spidevice, "TISR spi response err = 0x%x\n", res_len);
807cab47333SShikha Singh 		result = res_len;
808cab47333SShikha Singh 		goto end;
809cab47333SShikha Singh 	}
810cab47333SShikha Singh 
811cab47333SShikha Singh 	/* if stcontext->nfcdev_free is true, it means remove already ran */
812cab47333SShikha Singh 	if (stcontext->nfcdev_free) {
813cab47333SShikha Singh 		result = -ENODEV;
814cab47333SShikha Singh 		goto end;
815cab47333SShikha Singh 	}
816cab47333SShikha Singh 
817cab47333SShikha Singh 	if (skb_resp->data[2] == WTX_REQ_FROM_TAG) {
818cab47333SShikha Singh 		/* Request for new FWT from tag */
819cab47333SShikha Singh 		result = st95hf_handle_wtx(stcontext, true, skb_resp->data[3]);
820cab47333SShikha Singh 		if (result)
821cab47333SShikha Singh 			goto end;
822cab47333SShikha Singh 
823cab47333SShikha Singh 		wtx = true;
824cab47333SShikha Singh 		mutex_unlock(&stcontext->rm_lock);
825cab47333SShikha Singh 		return IRQ_HANDLED;
826cab47333SShikha Singh 	}
827cab47333SShikha Singh 
828cab47333SShikha Singh 	result = st95hf_error_handling(stcontext, skb_resp, res_len);
829cab47333SShikha Singh 	if (result)
830cab47333SShikha Singh 		goto end;
831cab47333SShikha Singh 
832cab47333SShikha Singh 	result = st95hf_response_handler(stcontext, skb_resp, res_len);
833cab47333SShikha Singh 	if (result)
834cab47333SShikha Singh 		goto end;
835cab47333SShikha Singh 
836cab47333SShikha Singh 	/*
837cab47333SShikha Singh 	 * If select protocol is done on wtx req. do select protocol
838cab47333SShikha Singh 	 * again with default values
839cab47333SShikha Singh 	 */
840cab47333SShikha Singh 	if (wtx) {
841cab47333SShikha Singh 		wtx = false;
842cab47333SShikha Singh 		result = st95hf_handle_wtx(stcontext, false, 0);
843cab47333SShikha Singh 		if (result)
844cab47333SShikha Singh 			goto end;
845cab47333SShikha Singh 	}
846cab47333SShikha Singh 
847cab47333SShikha Singh 	/* call digital layer callback */
848cab47333SShikha Singh 	cb_arg->complete_cb(stcontext->ddev, cb_arg->cb_usrarg, skb_resp);
849cab47333SShikha Singh 
850cab47333SShikha Singh 	/* up the semaphore before returning */
851cab47333SShikha Singh 	up(&stcontext->exchange_lock);
852cab47333SShikha Singh 	mutex_unlock(&stcontext->rm_lock);
853cab47333SShikha Singh 
854cab47333SShikha Singh 	return IRQ_HANDLED;
855cab47333SShikha Singh 
856cab47333SShikha Singh end:
857cab47333SShikha Singh 	kfree_skb(skb_resp);
858cab47333SShikha Singh 	wtx = false;
859cab47333SShikha Singh 	cb_arg->rats = false;
860cab47333SShikha Singh 	skb_resp = ERR_PTR(result);
861cab47333SShikha Singh 	/* call of callback with error */
862cab47333SShikha Singh 	cb_arg->complete_cb(stcontext->ddev, cb_arg->cb_usrarg, skb_resp);
863cab47333SShikha Singh 	/* up the semaphore before returning */
864cab47333SShikha Singh 	up(&stcontext->exchange_lock);
865cab47333SShikha Singh 	mutex_unlock(&stcontext->rm_lock);
866cab47333SShikha Singh 	return IRQ_HANDLED;
867cab47333SShikha Singh }
868cab47333SShikha Singh 
869cab47333SShikha Singh /* NFC ops functions definition */
st95hf_in_configure_hw(struct nfc_digital_dev * ddev,int type,int param)870cab47333SShikha Singh static int st95hf_in_configure_hw(struct nfc_digital_dev *ddev,
871cab47333SShikha Singh 				  int type,
872cab47333SShikha Singh 				  int param)
873cab47333SShikha Singh {
874cab47333SShikha Singh 	struct st95hf_context *stcontext = nfc_digital_get_drvdata(ddev);
875cab47333SShikha Singh 
876cab47333SShikha Singh 	if (type == NFC_DIGITAL_CONFIG_RF_TECH)
877cab47333SShikha Singh 		return st95hf_select_protocol(stcontext, param);
878cab47333SShikha Singh 
879cab47333SShikha Singh 	if (type == NFC_DIGITAL_CONFIG_FRAMING) {
880cab47333SShikha Singh 		switch (param) {
881cab47333SShikha Singh 		case NFC_DIGITAL_FRAMING_NFCA_SHORT:
882cab47333SShikha Singh 			stcontext->sendrcv_trflag = TRFLAG_NFCA_SHORT_FRAME;
883cab47333SShikha Singh 			break;
884cab47333SShikha Singh 		case NFC_DIGITAL_FRAMING_NFCA_STANDARD:
885cab47333SShikha Singh 			stcontext->sendrcv_trflag = TRFLAG_NFCA_STD_FRAME;
886cab47333SShikha Singh 			break;
887cab47333SShikha Singh 		case NFC_DIGITAL_FRAMING_NFCA_T4T:
888cab47333SShikha Singh 		case NFC_DIGITAL_FRAMING_NFCA_NFC_DEP:
889cab47333SShikha Singh 		case NFC_DIGITAL_FRAMING_NFCA_STANDARD_WITH_CRC_A:
890cab47333SShikha Singh 			stcontext->sendrcv_trflag = TRFLAG_NFCA_STD_FRAME_CRC;
891cab47333SShikha Singh 			break;
892cab47333SShikha Singh 		case NFC_DIGITAL_FRAMING_NFCB:
893cab47333SShikha Singh 		case NFC_DIGITAL_FRAMING_ISO15693_INVENTORY:
894cab47333SShikha Singh 		case NFC_DIGITAL_FRAMING_ISO15693_T5T:
895cab47333SShikha Singh 			break;
896cab47333SShikha Singh 		}
897cab47333SShikha Singh 	}
898cab47333SShikha Singh 
899cab47333SShikha Singh 	return 0;
900cab47333SShikha Singh }
901cab47333SShikha Singh 
rf_off(struct st95hf_context * stcontext)902cab47333SShikha Singh static int rf_off(struct st95hf_context *stcontext)
903cab47333SShikha Singh {
904cab47333SShikha Singh 	int rc;
905cab47333SShikha Singh 	struct device *dev;
906cab47333SShikha Singh 
907cab47333SShikha Singh 	dev = &stcontext->nfcdev->dev;
908cab47333SShikha Singh 
909cab47333SShikha Singh 	rc = st95hf_send_recv_cmd(stcontext, CMD_FIELD_OFF, 0, NULL, true);
910cab47333SShikha Singh 	if (rc)
911cab47333SShikha Singh 		dev_err(dev, "protocol sel send field off, err = 0x%x\n", rc);
912cab47333SShikha Singh 
913cab47333SShikha Singh 	return rc;
914cab47333SShikha Singh }
915cab47333SShikha Singh 
st95hf_in_send_cmd(struct nfc_digital_dev * ddev,struct sk_buff * skb,u16 timeout,nfc_digital_cmd_complete_t cb,void * arg)916cab47333SShikha Singh static int st95hf_in_send_cmd(struct nfc_digital_dev *ddev,
917cab47333SShikha Singh 			      struct sk_buff *skb,
918cab47333SShikha Singh 			      u16 timeout,
919cab47333SShikha Singh 			      nfc_digital_cmd_complete_t cb,
920cab47333SShikha Singh 			      void *arg)
921cab47333SShikha Singh {
922cab47333SShikha Singh 	struct st95hf_context *stcontext = nfc_digital_get_drvdata(ddev);
923cab47333SShikha Singh 	int rc;
924cab47333SShikha Singh 	struct sk_buff *skb_resp;
925cab47333SShikha Singh 	int len_data_to_tag = 0;
926cab47333SShikha Singh 
927cab47333SShikha Singh 	skb_resp = nfc_alloc_recv_skb(MAX_RESPONSE_BUFFER_SIZE, GFP_KERNEL);
928568e7142Swengjianfeng 	if (!skb_resp)
929568e7142Swengjianfeng 		return -ENOMEM;
930cab47333SShikha Singh 
931cab47333SShikha Singh 	switch (stcontext->current_rf_tech) {
932cab47333SShikha Singh 	case NFC_DIGITAL_RF_TECH_106A:
933cab47333SShikha Singh 		len_data_to_tag = skb->len + 1;
934634fef61SJohannes Berg 		skb_put_u8(skb, stcontext->sendrcv_trflag);
935cab47333SShikha Singh 		break;
936cab47333SShikha Singh 	case NFC_DIGITAL_RF_TECH_106B:
937cab47333SShikha Singh 	case NFC_DIGITAL_RF_TECH_ISO15693:
938cab47333SShikha Singh 		len_data_to_tag = skb->len;
939cab47333SShikha Singh 		break;
940cab47333SShikha Singh 	default:
941cab47333SShikha Singh 		rc = -EINVAL;
942cab47333SShikha Singh 		goto free_skb_resp;
943cab47333SShikha Singh 	}
944cab47333SShikha Singh 
945cab47333SShikha Singh 	skb_push(skb, 3);
946cab47333SShikha Singh 	skb->data[0] = ST95HF_COMMAND_SEND;
947cab47333SShikha Singh 	skb->data[1] = SEND_RECEIVE_CMD;
948cab47333SShikha Singh 	skb->data[2] = len_data_to_tag;
949cab47333SShikha Singh 
950cab47333SShikha Singh 	stcontext->complete_cb_arg.skb_resp = skb_resp;
951cab47333SShikha Singh 	stcontext->complete_cb_arg.cb_usrarg = arg;
952cab47333SShikha Singh 	stcontext->complete_cb_arg.complete_cb = cb;
953cab47333SShikha Singh 
954cab47333SShikha Singh 	if ((skb->data[3] == ISO14443A_RATS_REQ) &&
955cab47333SShikha Singh 	    ddev->curr_protocol == NFC_PROTO_ISO14443)
956cab47333SShikha Singh 		stcontext->complete_cb_arg.rats = true;
957cab47333SShikha Singh 
958cab47333SShikha Singh 	/*
959cab47333SShikha Singh 	 * down the semaphore to indicate to remove func that an
960cab47333SShikha Singh 	 * ISR is pending, note that it will not block here in any case.
961cab47333SShikha Singh 	 * If found blocked, it is a BUG!
962cab47333SShikha Singh 	 */
963cab47333SShikha Singh 	rc = down_killable(&stcontext->exchange_lock);
964cab47333SShikha Singh 	if (rc) {
965cab47333SShikha Singh 		WARN(1, "Semaphore is not found up in st95hf_in_send_cmd\n");
966f97c04c3SDinghao Liu 		goto free_skb_resp;
967cab47333SShikha Singh 	}
968cab47333SShikha Singh 
969cab47333SShikha Singh 	rc = st95hf_spi_send(&stcontext->spicontext, skb->data,
970cab47333SShikha Singh 			     skb->len,
971cab47333SShikha Singh 			     ASYNC);
972cab47333SShikha Singh 	if (rc) {
973cab47333SShikha Singh 		dev_err(&stcontext->nfcdev->dev,
974cab47333SShikha Singh 			"Error %d trying to perform data_exchange", rc);
975cab47333SShikha Singh 		/* up the semaphore since ISR will never come in this case */
976cab47333SShikha Singh 		up(&stcontext->exchange_lock);
977cab47333SShikha Singh 		goto free_skb_resp;
978cab47333SShikha Singh 	}
979cab47333SShikha Singh 
980cab47333SShikha Singh 	kfree_skb(skb);
981cab47333SShikha Singh 
982cab47333SShikha Singh 	return rc;
983cab47333SShikha Singh 
984cab47333SShikha Singh free_skb_resp:
985cab47333SShikha Singh 	kfree_skb(skb_resp);
986cab47333SShikha Singh 	return rc;
987cab47333SShikha Singh }
988cab47333SShikha Singh 
989cab47333SShikha Singh /* p2p will be supported in a later release ! */
st95hf_tg_configure_hw(struct nfc_digital_dev * ddev,int type,int param)990cab47333SShikha Singh static int st95hf_tg_configure_hw(struct nfc_digital_dev *ddev,
991cab47333SShikha Singh 				  int type,
992cab47333SShikha Singh 				  int param)
993cab47333SShikha Singh {
994cab47333SShikha Singh 	return 0;
995cab47333SShikha Singh }
996cab47333SShikha Singh 
st95hf_tg_send_cmd(struct nfc_digital_dev * ddev,struct sk_buff * skb,u16 timeout,nfc_digital_cmd_complete_t cb,void * arg)997cab47333SShikha Singh static int st95hf_tg_send_cmd(struct nfc_digital_dev *ddev,
998cab47333SShikha Singh 			      struct sk_buff *skb,
999cab47333SShikha Singh 			      u16 timeout,
1000cab47333SShikha Singh 			      nfc_digital_cmd_complete_t cb,
1001cab47333SShikha Singh 			      void *arg)
1002cab47333SShikha Singh {
1003cab47333SShikha Singh 	return 0;
1004cab47333SShikha Singh }
1005cab47333SShikha Singh 
st95hf_tg_listen(struct nfc_digital_dev * ddev,u16 timeout,nfc_digital_cmd_complete_t cb,void * arg)1006cab47333SShikha Singh static int st95hf_tg_listen(struct nfc_digital_dev *ddev,
1007cab47333SShikha Singh 			    u16 timeout,
1008cab47333SShikha Singh 			    nfc_digital_cmd_complete_t cb,
1009cab47333SShikha Singh 			    void *arg)
1010cab47333SShikha Singh {
1011cab47333SShikha Singh 	return 0;
1012cab47333SShikha Singh }
1013cab47333SShikha Singh 
st95hf_tg_get_rf_tech(struct nfc_digital_dev * ddev,u8 * rf_tech)1014cab47333SShikha Singh static int st95hf_tg_get_rf_tech(struct nfc_digital_dev *ddev, u8 *rf_tech)
1015cab47333SShikha Singh {
1016cab47333SShikha Singh 	return 0;
1017cab47333SShikha Singh }
1018cab47333SShikha Singh 
st95hf_switch_rf(struct nfc_digital_dev * ddev,bool on)1019cab47333SShikha Singh static int st95hf_switch_rf(struct nfc_digital_dev *ddev, bool on)
1020cab47333SShikha Singh {
1021cab47333SShikha Singh 	u8 rf_tech;
1022cab47333SShikha Singh 	struct st95hf_context *stcontext = nfc_digital_get_drvdata(ddev);
1023cab47333SShikha Singh 
1024cab47333SShikha Singh 	rf_tech = ddev->curr_rf_tech;
1025cab47333SShikha Singh 
1026cab47333SShikha Singh 	if (on)
1027cab47333SShikha Singh 		/* switch on RF field */
1028cab47333SShikha Singh 		return st95hf_select_protocol(stcontext, rf_tech);
1029cab47333SShikha Singh 
1030cab47333SShikha Singh 	/* switch OFF RF field */
1031cab47333SShikha Singh 	return rf_off(stcontext);
1032cab47333SShikha Singh }
1033cab47333SShikha Singh 
1034cab47333SShikha Singh /* TODO st95hf_abort_cmd */
st95hf_abort_cmd(struct nfc_digital_dev * ddev)1035cab47333SShikha Singh static void st95hf_abort_cmd(struct nfc_digital_dev *ddev)
1036cab47333SShikha Singh {
1037cab47333SShikha Singh }
1038cab47333SShikha Singh 
10397186aac9SKrzysztof Kozlowski static const struct nfc_digital_ops st95hf_nfc_digital_ops = {
1040cab47333SShikha Singh 	.in_configure_hw = st95hf_in_configure_hw,
1041cab47333SShikha Singh 	.in_send_cmd = st95hf_in_send_cmd,
1042cab47333SShikha Singh 
1043cab47333SShikha Singh 	.tg_listen = st95hf_tg_listen,
1044cab47333SShikha Singh 	.tg_configure_hw = st95hf_tg_configure_hw,
1045cab47333SShikha Singh 	.tg_send_cmd = st95hf_tg_send_cmd,
1046cab47333SShikha Singh 	.tg_get_rf_tech = st95hf_tg_get_rf_tech,
1047cab47333SShikha Singh 
1048cab47333SShikha Singh 	.switch_rf = st95hf_switch_rf,
1049cab47333SShikha Singh 	.abort_cmd = st95hf_abort_cmd,
1050cab47333SShikha Singh };
1051cab47333SShikha Singh 
1052cab47333SShikha Singh static const struct spi_device_id st95hf_id[] = {
1053cab47333SShikha Singh 	{ "st95hf", 0 },
1054cab47333SShikha Singh 	{}
1055cab47333SShikha Singh };
1056cab47333SShikha Singh MODULE_DEVICE_TABLE(spi, st95hf_id);
1057cab47333SShikha Singh 
10581ab4fe09SKrzysztof Kozlowski static const struct of_device_id st95hf_spi_of_match[] __maybe_unused = {
1059d0483053SDaniel Gomez 	{ .compatible = "st,st95hf" },
1060d0483053SDaniel Gomez 	{},
1061d0483053SDaniel Gomez };
1062d0483053SDaniel Gomez MODULE_DEVICE_TABLE(of, st95hf_spi_of_match);
1063d0483053SDaniel Gomez 
st95hf_probe(struct spi_device * nfc_spi_dev)1064cab47333SShikha Singh static int st95hf_probe(struct spi_device *nfc_spi_dev)
1065cab47333SShikha Singh {
1066cab47333SShikha Singh 	int ret;
1067cab47333SShikha Singh 
1068cab47333SShikha Singh 	struct st95hf_context *st95context;
1069cab47333SShikha Singh 	struct st95hf_spi_context *spicontext;
1070cab47333SShikha Singh 
1071cab47333SShikha Singh 	nfc_info(&nfc_spi_dev->dev, "ST95HF driver probe called.\n");
1072cab47333SShikha Singh 
1073cab47333SShikha Singh 	st95context = devm_kzalloc(&nfc_spi_dev->dev,
1074cab47333SShikha Singh 				   sizeof(struct st95hf_context),
1075cab47333SShikha Singh 				   GFP_KERNEL);
1076cab47333SShikha Singh 	if (!st95context)
1077cab47333SShikha Singh 		return -ENOMEM;
1078cab47333SShikha Singh 
1079cab47333SShikha Singh 	spicontext = &st95context->spicontext;
1080cab47333SShikha Singh 
1081cab47333SShikha Singh 	spicontext->spidev = nfc_spi_dev;
1082cab47333SShikha Singh 
1083cab47333SShikha Singh 	st95context->fwi =
1084cab47333SShikha Singh 		cmd_array[CMD_ISO14443A_PROTOCOL_SELECT].cmd_params[2];
1085cab47333SShikha Singh 
1086cab47333SShikha Singh 	if (device_property_present(&nfc_spi_dev->dev, "st95hfvin")) {
1087cab47333SShikha Singh 		st95context->st95hf_supply =
1088cab47333SShikha Singh 			devm_regulator_get(&nfc_spi_dev->dev,
1089cab47333SShikha Singh 					   "st95hfvin");
1090cab47333SShikha Singh 		if (IS_ERR(st95context->st95hf_supply)) {
1091cab47333SShikha Singh 			dev_err(&nfc_spi_dev->dev, "failed to acquire regulator\n");
1092cab47333SShikha Singh 			return PTR_ERR(st95context->st95hf_supply);
1093cab47333SShikha Singh 		}
1094cab47333SShikha Singh 
1095cab47333SShikha Singh 		ret = regulator_enable(st95context->st95hf_supply);
1096cab47333SShikha Singh 		if (ret) {
1097cab47333SShikha Singh 			dev_err(&nfc_spi_dev->dev, "failed to enable regulator\n");
1098cab47333SShikha Singh 			return ret;
1099cab47333SShikha Singh 		}
1100cab47333SShikha Singh 	}
1101cab47333SShikha Singh 
1102cab47333SShikha Singh 	init_completion(&spicontext->done);
1103cab47333SShikha Singh 	mutex_init(&spicontext->spi_lock);
1104cab47333SShikha Singh 
1105cab47333SShikha Singh 	/*
1106cab47333SShikha Singh 	 * Store spicontext in spi device object for using it in
1107cab47333SShikha Singh 	 * remove function
1108cab47333SShikha Singh 	 */
1109cab47333SShikha Singh 	dev_set_drvdata(&nfc_spi_dev->dev, spicontext);
1110cab47333SShikha Singh 
1111cab47333SShikha Singh 	st95context->enable_gpio =
1112cab47333SShikha Singh 		of_get_named_gpio(nfc_spi_dev->dev.of_node,
1113cab47333SShikha Singh 				  "enable-gpio",
1114cab47333SShikha Singh 				  0);
1115cab47333SShikha Singh 	if (!gpio_is_valid(st95context->enable_gpio)) {
1116cab47333SShikha Singh 		dev_err(&nfc_spi_dev->dev, "No valid enable gpio\n");
1117cab47333SShikha Singh 		ret = st95context->enable_gpio;
1118cab47333SShikha Singh 		goto err_disable_regulator;
1119cab47333SShikha Singh 	}
1120cab47333SShikha Singh 
1121cab47333SShikha Singh 	ret = devm_gpio_request_one(&nfc_spi_dev->dev, st95context->enable_gpio,
1122cab47333SShikha Singh 				    GPIOF_DIR_OUT | GPIOF_INIT_HIGH,
1123cab47333SShikha Singh 				    "enable_gpio");
1124cab47333SShikha Singh 	if (ret)
1125cab47333SShikha Singh 		goto err_disable_regulator;
1126cab47333SShikha Singh 
1127cab47333SShikha Singh 	if (nfc_spi_dev->irq > 0) {
1128cab47333SShikha Singh 		if (devm_request_threaded_irq(&nfc_spi_dev->dev,
1129cab47333SShikha Singh 					      nfc_spi_dev->irq,
11306b52d994SShikha Singh 					      st95hf_irq_handler,
11316b52d994SShikha Singh 					      st95hf_irq_thread_handler,
1132cab47333SShikha Singh 					      IRQF_TRIGGER_FALLING,
1133cab47333SShikha Singh 					      "st95hf",
1134cab47333SShikha Singh 					      (void *)st95context) < 0) {
1135cab47333SShikha Singh 			dev_err(&nfc_spi_dev->dev, "err: irq request for st95hf is failed\n");
1136cab47333SShikha Singh 			ret =  -EINVAL;
1137cab47333SShikha Singh 			goto err_disable_regulator;
1138cab47333SShikha Singh 		}
1139cab47333SShikha Singh 	} else {
1140cab47333SShikha Singh 		dev_err(&nfc_spi_dev->dev, "not a valid IRQ associated with ST95HF\n");
1141cab47333SShikha Singh 		ret = -EINVAL;
1142cab47333SShikha Singh 		goto err_disable_regulator;
1143cab47333SShikha Singh 	}
1144cab47333SShikha Singh 
1145cab47333SShikha Singh 	/*
1146cab47333SShikha Singh 	 * First reset SPI to handle warm reset of the system.
1147cab47333SShikha Singh 	 * It will put the ST95HF device in Power ON state
1148cab47333SShikha Singh 	 * which make the state of device identical to state
1149cab47333SShikha Singh 	 * at the time of cold reset of the system.
1150cab47333SShikha Singh 	 */
1151cab47333SShikha Singh 	ret = st95hf_send_spi_reset_sequence(st95context);
1152cab47333SShikha Singh 	if (ret) {
1153cab47333SShikha Singh 		dev_err(&nfc_spi_dev->dev, "err: spi_reset_sequence failed\n");
1154cab47333SShikha Singh 		goto err_disable_regulator;
1155cab47333SShikha Singh 	}
1156cab47333SShikha Singh 
1157cab47333SShikha Singh 	/* call PowerOnReset sequence of ST95hf to activate it */
1158cab47333SShikha Singh 	ret = st95hf_por_sequence(st95context);
1159cab47333SShikha Singh 	if (ret) {
1160cab47333SShikha Singh 		dev_err(&nfc_spi_dev->dev, "err: por seq failed for st95hf\n");
1161cab47333SShikha Singh 		goto err_disable_regulator;
1162cab47333SShikha Singh 	}
1163cab47333SShikha Singh 
1164cab47333SShikha Singh 	/* create NFC dev object and register with NFC Subsystem */
1165cab47333SShikha Singh 	st95context->ddev = nfc_digital_allocate_device(&st95hf_nfc_digital_ops,
1166cab47333SShikha Singh 							ST95HF_SUPPORTED_PROT,
1167cab47333SShikha Singh 							ST95HF_CAPABILITIES,
1168cab47333SShikha Singh 							ST95HF_HEADROOM_LEN,
1169cab47333SShikha Singh 							ST95HF_TAILROOM_LEN);
1170cab47333SShikha Singh 	if (!st95context->ddev) {
1171cab47333SShikha Singh 		ret = -ENOMEM;
1172cab47333SShikha Singh 		goto err_disable_regulator;
1173cab47333SShikha Singh 	}
1174cab47333SShikha Singh 
1175cab47333SShikha Singh 	st95context->nfcdev = st95context->ddev->nfc_dev;
1176cab47333SShikha Singh 	nfc_digital_set_parent_dev(st95context->ddev, &nfc_spi_dev->dev);
1177cab47333SShikha Singh 
1178cab47333SShikha Singh 	ret =  nfc_digital_register_device(st95context->ddev);
1179cab47333SShikha Singh 	if (ret) {
1180cab47333SShikha Singh 		dev_err(&st95context->nfcdev->dev, "st95hf registration failed\n");
1181cab47333SShikha Singh 		goto err_free_digital_device;
1182cab47333SShikha Singh 	}
1183cab47333SShikha Singh 
1184cab47333SShikha Singh 	/* store st95context in nfc device object */
1185cab47333SShikha Singh 	nfc_digital_set_drvdata(st95context->ddev, st95context);
1186cab47333SShikha Singh 
1187cab47333SShikha Singh 	sema_init(&st95context->exchange_lock, 1);
1188cab47333SShikha Singh 	mutex_init(&st95context->rm_lock);
1189cab47333SShikha Singh 
1190cab47333SShikha Singh 	return ret;
1191cab47333SShikha Singh 
1192cab47333SShikha Singh err_free_digital_device:
1193cab47333SShikha Singh 	nfc_digital_free_device(st95context->ddev);
1194cab47333SShikha Singh err_disable_regulator:
1195cab47333SShikha Singh 	if (st95context->st95hf_supply)
1196cab47333SShikha Singh 		regulator_disable(st95context->st95hf_supply);
1197cab47333SShikha Singh 
1198cab47333SShikha Singh 	return ret;
1199cab47333SShikha Singh }
1200cab47333SShikha Singh 
st95hf_remove(struct spi_device * nfc_spi_dev)1201*a0386bbaSUwe Kleine-König static void st95hf_remove(struct spi_device *nfc_spi_dev)
1202cab47333SShikha Singh {
1203cab47333SShikha Singh 	int result = 0;
1204cab47333SShikha Singh 	unsigned char reset_cmd = ST95HF_COMMAND_RESET;
1205cab47333SShikha Singh 	struct st95hf_spi_context *spictx = dev_get_drvdata(&nfc_spi_dev->dev);
1206cab47333SShikha Singh 
1207cab47333SShikha Singh 	struct st95hf_context *stcontext = container_of(spictx,
1208cab47333SShikha Singh 							struct st95hf_context,
1209cab47333SShikha Singh 							spicontext);
1210cab47333SShikha Singh 
1211cab47333SShikha Singh 	mutex_lock(&stcontext->rm_lock);
1212cab47333SShikha Singh 
1213cab47333SShikha Singh 	nfc_digital_unregister_device(stcontext->ddev);
1214cab47333SShikha Singh 	nfc_digital_free_device(stcontext->ddev);
1215cab47333SShikha Singh 	stcontext->nfcdev_free = true;
1216cab47333SShikha Singh 
1217cab47333SShikha Singh 	mutex_unlock(&stcontext->rm_lock);
1218cab47333SShikha Singh 
1219cab47333SShikha Singh 	/* if last in_send_cmd's ISR is pending, wait for it to finish */
1220cab47333SShikha Singh 	result = down_killable(&stcontext->exchange_lock);
1221cab47333SShikha Singh 	if (result == -EINTR)
1222cab47333SShikha Singh 		dev_err(&spictx->spidev->dev, "sleep for semaphore interrupted by signal\n");
1223cab47333SShikha Singh 
1224cab47333SShikha Singh 	/* next reset the ST95HF controller */
1225cab47333SShikha Singh 	result = st95hf_spi_send(&stcontext->spicontext,
1226cab47333SShikha Singh 				 &reset_cmd,
1227cab47333SShikha Singh 				 ST95HF_RESET_CMD_LEN,
1228cab47333SShikha Singh 				 ASYNC);
1229641e3fd1SUwe Kleine-König 	if (result)
1230cab47333SShikha Singh 		dev_err(&spictx->spidev->dev,
1231cab47333SShikha Singh 			"ST95HF reset failed in remove() err = %d\n", result);
1232cab47333SShikha Singh 
1233cab47333SShikha Singh 	/* wait for 3 ms to complete the controller reset process */
1234cab47333SShikha Singh 	usleep_range(3000, 4000);
1235cab47333SShikha Singh 
1236cab47333SShikha Singh 	/* disable regulator */
1237cab47333SShikha Singh 	if (stcontext->st95hf_supply)
1238cab47333SShikha Singh 		regulator_disable(stcontext->st95hf_supply);
1239cab47333SShikha Singh }
1240cab47333SShikha Singh 
1241cab47333SShikha Singh /* Register as SPI protocol driver */
1242cab47333SShikha Singh static struct spi_driver st95hf_driver = {
1243cab47333SShikha Singh 	.driver = {
1244cab47333SShikha Singh 		.name = "st95hf",
1245cab47333SShikha Singh 		.owner = THIS_MODULE,
1246d0483053SDaniel Gomez 		.of_match_table = of_match_ptr(st95hf_spi_of_match),
1247cab47333SShikha Singh 	},
1248cab47333SShikha Singh 	.id_table = st95hf_id,
1249cab47333SShikha Singh 	.probe = st95hf_probe,
1250cab47333SShikha Singh 	.remove = st95hf_remove,
1251cab47333SShikha Singh };
1252cab47333SShikha Singh 
1253cab47333SShikha Singh module_spi_driver(st95hf_driver);
1254cab47333SShikha Singh 
1255cab47333SShikha Singh MODULE_AUTHOR("Shikha Singh <shikha.singh@st.com>");
1256cab47333SShikha Singh MODULE_DESCRIPTION("ST NFC Transceiver ST95HF driver");
1257cab47333SShikha Singh MODULE_LICENSE("GPL v2");
1258