xref: /OK3568_Linux_fs/kernel/drivers/nfc/mei_phy.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * Copyright (c) 2013, Intel Corporation.
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * MEI Library for mei bus nfc device access
6*4882a593Smuzhiyun  */
7*4882a593Smuzhiyun #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
8*4882a593Smuzhiyun 
9*4882a593Smuzhiyun #include <linux/module.h>
10*4882a593Smuzhiyun #include <linux/slab.h>
11*4882a593Smuzhiyun #include <linux/nfc.h>
12*4882a593Smuzhiyun 
13*4882a593Smuzhiyun #include "mei_phy.h"
14*4882a593Smuzhiyun 
15*4882a593Smuzhiyun struct mei_nfc_hdr {
16*4882a593Smuzhiyun 	u8 cmd;
17*4882a593Smuzhiyun 	u8 status;
18*4882a593Smuzhiyun 	u16 req_id;
19*4882a593Smuzhiyun 	u32 reserved;
20*4882a593Smuzhiyun 	u16 data_size;
21*4882a593Smuzhiyun } __packed;
22*4882a593Smuzhiyun 
23*4882a593Smuzhiyun struct mei_nfc_cmd {
24*4882a593Smuzhiyun 	struct mei_nfc_hdr hdr;
25*4882a593Smuzhiyun 	u8 sub_command;
26*4882a593Smuzhiyun 	u8 data[];
27*4882a593Smuzhiyun } __packed;
28*4882a593Smuzhiyun 
29*4882a593Smuzhiyun struct mei_nfc_reply {
30*4882a593Smuzhiyun 	struct mei_nfc_hdr hdr;
31*4882a593Smuzhiyun 	u8 sub_command;
32*4882a593Smuzhiyun 	u8 reply_status;
33*4882a593Smuzhiyun 	u8 data[];
34*4882a593Smuzhiyun } __packed;
35*4882a593Smuzhiyun 
36*4882a593Smuzhiyun struct mei_nfc_if_version {
37*4882a593Smuzhiyun 	u8 radio_version_sw[3];
38*4882a593Smuzhiyun 	u8 reserved[3];
39*4882a593Smuzhiyun 	u8 radio_version_hw[3];
40*4882a593Smuzhiyun 	u8 i2c_addr;
41*4882a593Smuzhiyun 	u8 fw_ivn;
42*4882a593Smuzhiyun 	u8 vendor_id;
43*4882a593Smuzhiyun 	u8 radio_type;
44*4882a593Smuzhiyun } __packed;
45*4882a593Smuzhiyun 
46*4882a593Smuzhiyun struct mei_nfc_connect {
47*4882a593Smuzhiyun 	u8 fw_ivn;
48*4882a593Smuzhiyun 	u8 vendor_id;
49*4882a593Smuzhiyun } __packed;
50*4882a593Smuzhiyun 
51*4882a593Smuzhiyun struct mei_nfc_connect_resp {
52*4882a593Smuzhiyun 	u8 fw_ivn;
53*4882a593Smuzhiyun 	u8 vendor_id;
54*4882a593Smuzhiyun 	u16 me_major;
55*4882a593Smuzhiyun 	u16 me_minor;
56*4882a593Smuzhiyun 	u16 me_hotfix;
57*4882a593Smuzhiyun 	u16 me_build;
58*4882a593Smuzhiyun } __packed;
59*4882a593Smuzhiyun 
60*4882a593Smuzhiyun 
61*4882a593Smuzhiyun #define MEI_NFC_CMD_MAINTENANCE 0x00
62*4882a593Smuzhiyun #define MEI_NFC_CMD_HCI_SEND 0x01
63*4882a593Smuzhiyun #define MEI_NFC_CMD_HCI_RECV 0x02
64*4882a593Smuzhiyun 
65*4882a593Smuzhiyun #define MEI_NFC_SUBCMD_CONNECT    0x00
66*4882a593Smuzhiyun #define MEI_NFC_SUBCMD_IF_VERSION 0x01
67*4882a593Smuzhiyun 
68*4882a593Smuzhiyun #define MEI_NFC_MAX_READ (MEI_NFC_HEADER_SIZE + MEI_NFC_MAX_HCI_PAYLOAD)
69*4882a593Smuzhiyun 
70*4882a593Smuzhiyun #define MEI_DUMP_SKB_IN(info, skb)				\
71*4882a593Smuzhiyun do {								\
72*4882a593Smuzhiyun 	pr_debug("%s:\n", info);				\
73*4882a593Smuzhiyun 	print_hex_dump_debug("mei in : ", DUMP_PREFIX_OFFSET,	\
74*4882a593Smuzhiyun 			16, 1, (skb)->data, (skb)->len, false);	\
75*4882a593Smuzhiyun } while (0)
76*4882a593Smuzhiyun 
77*4882a593Smuzhiyun #define MEI_DUMP_SKB_OUT(info, skb)				\
78*4882a593Smuzhiyun do {								\
79*4882a593Smuzhiyun 	pr_debug("%s:\n", info);				\
80*4882a593Smuzhiyun 	print_hex_dump_debug("mei out: ", DUMP_PREFIX_OFFSET,	\
81*4882a593Smuzhiyun 			16, 1, (skb)->data, (skb)->len, false);	\
82*4882a593Smuzhiyun } while (0)
83*4882a593Smuzhiyun 
84*4882a593Smuzhiyun #define MEI_DUMP_NFC_HDR(info, _hdr)                                \
85*4882a593Smuzhiyun do {                                                                \
86*4882a593Smuzhiyun 	pr_debug("%s:\n", info);                                    \
87*4882a593Smuzhiyun 	pr_debug("cmd=%02d status=%d req_id=%d rsvd=%d size=%d\n",  \
88*4882a593Smuzhiyun 		 (_hdr)->cmd, (_hdr)->status, (_hdr)->req_id,       \
89*4882a593Smuzhiyun 		 (_hdr)->reserved, (_hdr)->data_size);              \
90*4882a593Smuzhiyun } while (0)
91*4882a593Smuzhiyun 
mei_nfc_if_version(struct nfc_mei_phy * phy)92*4882a593Smuzhiyun static int mei_nfc_if_version(struct nfc_mei_phy *phy)
93*4882a593Smuzhiyun {
94*4882a593Smuzhiyun 
95*4882a593Smuzhiyun 	struct mei_nfc_cmd cmd;
96*4882a593Smuzhiyun 	struct mei_nfc_reply *reply = NULL;
97*4882a593Smuzhiyun 	struct mei_nfc_if_version *version;
98*4882a593Smuzhiyun 	size_t if_version_length;
99*4882a593Smuzhiyun 	int bytes_recv, r;
100*4882a593Smuzhiyun 
101*4882a593Smuzhiyun 	pr_info("%s\n", __func__);
102*4882a593Smuzhiyun 
103*4882a593Smuzhiyun 	memset(&cmd, 0, sizeof(struct mei_nfc_cmd));
104*4882a593Smuzhiyun 	cmd.hdr.cmd = MEI_NFC_CMD_MAINTENANCE;
105*4882a593Smuzhiyun 	cmd.hdr.data_size = 1;
106*4882a593Smuzhiyun 	cmd.sub_command = MEI_NFC_SUBCMD_IF_VERSION;
107*4882a593Smuzhiyun 
108*4882a593Smuzhiyun 	MEI_DUMP_NFC_HDR("version", &cmd.hdr);
109*4882a593Smuzhiyun 	r = mei_cldev_send(phy->cldev, (u8 *)&cmd, sizeof(struct mei_nfc_cmd));
110*4882a593Smuzhiyun 	if (r < 0) {
111*4882a593Smuzhiyun 		pr_err("Could not send IF version cmd\n");
112*4882a593Smuzhiyun 		return r;
113*4882a593Smuzhiyun 	}
114*4882a593Smuzhiyun 
115*4882a593Smuzhiyun 	/* to be sure on the stack we alloc memory */
116*4882a593Smuzhiyun 	if_version_length = sizeof(struct mei_nfc_reply) +
117*4882a593Smuzhiyun 		sizeof(struct mei_nfc_if_version);
118*4882a593Smuzhiyun 
119*4882a593Smuzhiyun 	reply = kzalloc(if_version_length, GFP_KERNEL);
120*4882a593Smuzhiyun 	if (!reply)
121*4882a593Smuzhiyun 		return -ENOMEM;
122*4882a593Smuzhiyun 
123*4882a593Smuzhiyun 	bytes_recv = mei_cldev_recv(phy->cldev, (u8 *)reply, if_version_length);
124*4882a593Smuzhiyun 	if (bytes_recv < 0 || bytes_recv < if_version_length) {
125*4882a593Smuzhiyun 		pr_err("Could not read IF version\n");
126*4882a593Smuzhiyun 		r = -EIO;
127*4882a593Smuzhiyun 		goto err;
128*4882a593Smuzhiyun 	}
129*4882a593Smuzhiyun 
130*4882a593Smuzhiyun 	version = (struct mei_nfc_if_version *)reply->data;
131*4882a593Smuzhiyun 
132*4882a593Smuzhiyun 	phy->fw_ivn = version->fw_ivn;
133*4882a593Smuzhiyun 	phy->vendor_id = version->vendor_id;
134*4882a593Smuzhiyun 	phy->radio_type = version->radio_type;
135*4882a593Smuzhiyun 
136*4882a593Smuzhiyun err:
137*4882a593Smuzhiyun 	kfree(reply);
138*4882a593Smuzhiyun 	return r;
139*4882a593Smuzhiyun }
140*4882a593Smuzhiyun 
mei_nfc_connect(struct nfc_mei_phy * phy)141*4882a593Smuzhiyun static int mei_nfc_connect(struct nfc_mei_phy *phy)
142*4882a593Smuzhiyun {
143*4882a593Smuzhiyun 	struct mei_nfc_cmd *cmd, *reply;
144*4882a593Smuzhiyun 	struct mei_nfc_connect *connect;
145*4882a593Smuzhiyun 	struct mei_nfc_connect_resp *connect_resp;
146*4882a593Smuzhiyun 	size_t connect_length, connect_resp_length;
147*4882a593Smuzhiyun 	int bytes_recv, r;
148*4882a593Smuzhiyun 
149*4882a593Smuzhiyun 	pr_info("%s\n", __func__);
150*4882a593Smuzhiyun 
151*4882a593Smuzhiyun 	connect_length = sizeof(struct mei_nfc_cmd) +
152*4882a593Smuzhiyun 			sizeof(struct mei_nfc_connect);
153*4882a593Smuzhiyun 
154*4882a593Smuzhiyun 	connect_resp_length = sizeof(struct mei_nfc_cmd) +
155*4882a593Smuzhiyun 			sizeof(struct mei_nfc_connect_resp);
156*4882a593Smuzhiyun 
157*4882a593Smuzhiyun 	cmd = kzalloc(connect_length, GFP_KERNEL);
158*4882a593Smuzhiyun 	if (!cmd)
159*4882a593Smuzhiyun 		return -ENOMEM;
160*4882a593Smuzhiyun 	connect = (struct mei_nfc_connect *)cmd->data;
161*4882a593Smuzhiyun 
162*4882a593Smuzhiyun 	reply = kzalloc(connect_resp_length, GFP_KERNEL);
163*4882a593Smuzhiyun 	if (!reply) {
164*4882a593Smuzhiyun 		kfree(cmd);
165*4882a593Smuzhiyun 		return -ENOMEM;
166*4882a593Smuzhiyun 	}
167*4882a593Smuzhiyun 
168*4882a593Smuzhiyun 	connect_resp = (struct mei_nfc_connect_resp *)reply->data;
169*4882a593Smuzhiyun 
170*4882a593Smuzhiyun 	cmd->hdr.cmd = MEI_NFC_CMD_MAINTENANCE;
171*4882a593Smuzhiyun 	cmd->hdr.data_size = 3;
172*4882a593Smuzhiyun 	cmd->sub_command = MEI_NFC_SUBCMD_CONNECT;
173*4882a593Smuzhiyun 	connect->fw_ivn = phy->fw_ivn;
174*4882a593Smuzhiyun 	connect->vendor_id = phy->vendor_id;
175*4882a593Smuzhiyun 
176*4882a593Smuzhiyun 	MEI_DUMP_NFC_HDR("connect request", &cmd->hdr);
177*4882a593Smuzhiyun 	r = mei_cldev_send(phy->cldev, (u8 *)cmd, connect_length);
178*4882a593Smuzhiyun 	if (r < 0) {
179*4882a593Smuzhiyun 		pr_err("Could not send connect cmd %d\n", r);
180*4882a593Smuzhiyun 		goto err;
181*4882a593Smuzhiyun 	}
182*4882a593Smuzhiyun 
183*4882a593Smuzhiyun 	bytes_recv = mei_cldev_recv(phy->cldev, (u8 *)reply,
184*4882a593Smuzhiyun 				    connect_resp_length);
185*4882a593Smuzhiyun 	if (bytes_recv < 0) {
186*4882a593Smuzhiyun 		r = bytes_recv;
187*4882a593Smuzhiyun 		pr_err("Could not read connect response %d\n", r);
188*4882a593Smuzhiyun 		goto err;
189*4882a593Smuzhiyun 	}
190*4882a593Smuzhiyun 
191*4882a593Smuzhiyun 	MEI_DUMP_NFC_HDR("connect reply", &reply->hdr);
192*4882a593Smuzhiyun 
193*4882a593Smuzhiyun 	pr_info("IVN 0x%x Vendor ID 0x%x\n",
194*4882a593Smuzhiyun 		 connect_resp->fw_ivn, connect_resp->vendor_id);
195*4882a593Smuzhiyun 
196*4882a593Smuzhiyun 	pr_info("ME FW %d.%d.%d.%d\n",
197*4882a593Smuzhiyun 		connect_resp->me_major, connect_resp->me_minor,
198*4882a593Smuzhiyun 		connect_resp->me_hotfix, connect_resp->me_build);
199*4882a593Smuzhiyun 
200*4882a593Smuzhiyun 	r = 0;
201*4882a593Smuzhiyun 
202*4882a593Smuzhiyun err:
203*4882a593Smuzhiyun 	kfree(reply);
204*4882a593Smuzhiyun 	kfree(cmd);
205*4882a593Smuzhiyun 
206*4882a593Smuzhiyun 	return r;
207*4882a593Smuzhiyun }
208*4882a593Smuzhiyun 
mei_nfc_send(struct nfc_mei_phy * phy,u8 * buf,size_t length)209*4882a593Smuzhiyun static int mei_nfc_send(struct nfc_mei_phy *phy, u8 *buf, size_t length)
210*4882a593Smuzhiyun {
211*4882a593Smuzhiyun 	struct mei_nfc_hdr *hdr;
212*4882a593Smuzhiyun 	u8 *mei_buf;
213*4882a593Smuzhiyun 	int err;
214*4882a593Smuzhiyun 
215*4882a593Smuzhiyun 	err = -ENOMEM;
216*4882a593Smuzhiyun 	mei_buf = kzalloc(length + MEI_NFC_HEADER_SIZE, GFP_KERNEL);
217*4882a593Smuzhiyun 	if (!mei_buf)
218*4882a593Smuzhiyun 		goto out;
219*4882a593Smuzhiyun 
220*4882a593Smuzhiyun 	hdr = (struct mei_nfc_hdr *)mei_buf;
221*4882a593Smuzhiyun 	hdr->cmd = MEI_NFC_CMD_HCI_SEND;
222*4882a593Smuzhiyun 	hdr->status = 0;
223*4882a593Smuzhiyun 	hdr->req_id = phy->req_id;
224*4882a593Smuzhiyun 	hdr->reserved = 0;
225*4882a593Smuzhiyun 	hdr->data_size = length;
226*4882a593Smuzhiyun 
227*4882a593Smuzhiyun 	MEI_DUMP_NFC_HDR("send", hdr);
228*4882a593Smuzhiyun 
229*4882a593Smuzhiyun 	memcpy(mei_buf + MEI_NFC_HEADER_SIZE, buf, length);
230*4882a593Smuzhiyun 	err = mei_cldev_send(phy->cldev, mei_buf, length + MEI_NFC_HEADER_SIZE);
231*4882a593Smuzhiyun 	if (err < 0)
232*4882a593Smuzhiyun 		goto out;
233*4882a593Smuzhiyun 
234*4882a593Smuzhiyun 	if (!wait_event_interruptible_timeout(phy->send_wq,
235*4882a593Smuzhiyun 				phy->recv_req_id == phy->req_id, HZ)) {
236*4882a593Smuzhiyun 		pr_err("NFC MEI command timeout\n");
237*4882a593Smuzhiyun 		err = -ETIME;
238*4882a593Smuzhiyun 	} else {
239*4882a593Smuzhiyun 		phy->req_id++;
240*4882a593Smuzhiyun 	}
241*4882a593Smuzhiyun out:
242*4882a593Smuzhiyun 	kfree(mei_buf);
243*4882a593Smuzhiyun 	return err;
244*4882a593Smuzhiyun }
245*4882a593Smuzhiyun 
246*4882a593Smuzhiyun /*
247*4882a593Smuzhiyun  * Writing a frame must not return the number of written bytes.
248*4882a593Smuzhiyun  * It must return either zero for success, or <0 for error.
249*4882a593Smuzhiyun  * In addition, it must not alter the skb
250*4882a593Smuzhiyun  */
nfc_mei_phy_write(void * phy_id,struct sk_buff * skb)251*4882a593Smuzhiyun static int nfc_mei_phy_write(void *phy_id, struct sk_buff *skb)
252*4882a593Smuzhiyun {
253*4882a593Smuzhiyun 	struct nfc_mei_phy *phy = phy_id;
254*4882a593Smuzhiyun 	int r;
255*4882a593Smuzhiyun 
256*4882a593Smuzhiyun 	MEI_DUMP_SKB_OUT("mei frame sent", skb);
257*4882a593Smuzhiyun 
258*4882a593Smuzhiyun 	r = mei_nfc_send(phy, skb->data, skb->len);
259*4882a593Smuzhiyun 	if (r > 0)
260*4882a593Smuzhiyun 		r = 0;
261*4882a593Smuzhiyun 
262*4882a593Smuzhiyun 	return r;
263*4882a593Smuzhiyun }
264*4882a593Smuzhiyun 
mei_nfc_recv(struct nfc_mei_phy * phy,u8 * buf,size_t length)265*4882a593Smuzhiyun static int mei_nfc_recv(struct nfc_mei_phy *phy, u8 *buf, size_t length)
266*4882a593Smuzhiyun {
267*4882a593Smuzhiyun 	struct mei_nfc_hdr *hdr;
268*4882a593Smuzhiyun 	int received_length;
269*4882a593Smuzhiyun 
270*4882a593Smuzhiyun 	received_length = mei_cldev_recv(phy->cldev, buf, length);
271*4882a593Smuzhiyun 	if (received_length < 0)
272*4882a593Smuzhiyun 		return received_length;
273*4882a593Smuzhiyun 
274*4882a593Smuzhiyun 	hdr = (struct mei_nfc_hdr *) buf;
275*4882a593Smuzhiyun 
276*4882a593Smuzhiyun 	MEI_DUMP_NFC_HDR("receive", hdr);
277*4882a593Smuzhiyun 	if (hdr->cmd == MEI_NFC_CMD_HCI_SEND) {
278*4882a593Smuzhiyun 		phy->recv_req_id = hdr->req_id;
279*4882a593Smuzhiyun 		wake_up(&phy->send_wq);
280*4882a593Smuzhiyun 
281*4882a593Smuzhiyun 		return 0;
282*4882a593Smuzhiyun 	}
283*4882a593Smuzhiyun 
284*4882a593Smuzhiyun 	return received_length;
285*4882a593Smuzhiyun }
286*4882a593Smuzhiyun 
287*4882a593Smuzhiyun 
nfc_mei_rx_cb(struct mei_cl_device * cldev)288*4882a593Smuzhiyun static void nfc_mei_rx_cb(struct mei_cl_device *cldev)
289*4882a593Smuzhiyun {
290*4882a593Smuzhiyun 	struct nfc_mei_phy *phy = mei_cldev_get_drvdata(cldev);
291*4882a593Smuzhiyun 	struct sk_buff *skb;
292*4882a593Smuzhiyun 	int reply_size;
293*4882a593Smuzhiyun 
294*4882a593Smuzhiyun 	if (!phy)
295*4882a593Smuzhiyun 		return;
296*4882a593Smuzhiyun 
297*4882a593Smuzhiyun 	if (phy->hard_fault != 0)
298*4882a593Smuzhiyun 		return;
299*4882a593Smuzhiyun 
300*4882a593Smuzhiyun 	skb = alloc_skb(MEI_NFC_MAX_READ, GFP_KERNEL);
301*4882a593Smuzhiyun 	if (!skb)
302*4882a593Smuzhiyun 		return;
303*4882a593Smuzhiyun 
304*4882a593Smuzhiyun 	reply_size = mei_nfc_recv(phy, skb->data, MEI_NFC_MAX_READ);
305*4882a593Smuzhiyun 	if (reply_size < MEI_NFC_HEADER_SIZE) {
306*4882a593Smuzhiyun 		kfree_skb(skb);
307*4882a593Smuzhiyun 		return;
308*4882a593Smuzhiyun 	}
309*4882a593Smuzhiyun 
310*4882a593Smuzhiyun 	skb_put(skb, reply_size);
311*4882a593Smuzhiyun 	skb_pull(skb, MEI_NFC_HEADER_SIZE);
312*4882a593Smuzhiyun 
313*4882a593Smuzhiyun 	MEI_DUMP_SKB_IN("mei frame read", skb);
314*4882a593Smuzhiyun 
315*4882a593Smuzhiyun 	nfc_hci_recv_frame(phy->hdev, skb);
316*4882a593Smuzhiyun }
317*4882a593Smuzhiyun 
nfc_mei_phy_enable(void * phy_id)318*4882a593Smuzhiyun static int nfc_mei_phy_enable(void *phy_id)
319*4882a593Smuzhiyun {
320*4882a593Smuzhiyun 	int r;
321*4882a593Smuzhiyun 	struct nfc_mei_phy *phy = phy_id;
322*4882a593Smuzhiyun 
323*4882a593Smuzhiyun 	pr_info("%s\n", __func__);
324*4882a593Smuzhiyun 
325*4882a593Smuzhiyun 	if (phy->powered == 1)
326*4882a593Smuzhiyun 		return 0;
327*4882a593Smuzhiyun 
328*4882a593Smuzhiyun 	r = mei_cldev_enable(phy->cldev);
329*4882a593Smuzhiyun 	if (r < 0) {
330*4882a593Smuzhiyun 		pr_err("Could not enable device %d\n", r);
331*4882a593Smuzhiyun 		return r;
332*4882a593Smuzhiyun 	}
333*4882a593Smuzhiyun 
334*4882a593Smuzhiyun 	r = mei_nfc_if_version(phy);
335*4882a593Smuzhiyun 	if (r < 0) {
336*4882a593Smuzhiyun 		pr_err("Could not enable device %d\n", r);
337*4882a593Smuzhiyun 		goto err;
338*4882a593Smuzhiyun 	}
339*4882a593Smuzhiyun 
340*4882a593Smuzhiyun 	r = mei_nfc_connect(phy);
341*4882a593Smuzhiyun 	if (r < 0) {
342*4882a593Smuzhiyun 		pr_err("Could not connect to device %d\n", r);
343*4882a593Smuzhiyun 		goto err;
344*4882a593Smuzhiyun 	}
345*4882a593Smuzhiyun 
346*4882a593Smuzhiyun 	r = mei_cldev_register_rx_cb(phy->cldev, nfc_mei_rx_cb);
347*4882a593Smuzhiyun 	if (r) {
348*4882a593Smuzhiyun 		pr_err("Event cb registration failed %d\n", r);
349*4882a593Smuzhiyun 		goto err;
350*4882a593Smuzhiyun 	}
351*4882a593Smuzhiyun 
352*4882a593Smuzhiyun 	phy->powered = 1;
353*4882a593Smuzhiyun 
354*4882a593Smuzhiyun 	return 0;
355*4882a593Smuzhiyun 
356*4882a593Smuzhiyun err:
357*4882a593Smuzhiyun 	phy->powered = 0;
358*4882a593Smuzhiyun 	mei_cldev_disable(phy->cldev);
359*4882a593Smuzhiyun 	return r;
360*4882a593Smuzhiyun }
361*4882a593Smuzhiyun 
nfc_mei_phy_disable(void * phy_id)362*4882a593Smuzhiyun static void nfc_mei_phy_disable(void *phy_id)
363*4882a593Smuzhiyun {
364*4882a593Smuzhiyun 	struct nfc_mei_phy *phy = phy_id;
365*4882a593Smuzhiyun 
366*4882a593Smuzhiyun 	pr_info("%s\n", __func__);
367*4882a593Smuzhiyun 
368*4882a593Smuzhiyun 	mei_cldev_disable(phy->cldev);
369*4882a593Smuzhiyun 
370*4882a593Smuzhiyun 	phy->powered = 0;
371*4882a593Smuzhiyun }
372*4882a593Smuzhiyun 
373*4882a593Smuzhiyun struct nfc_phy_ops mei_phy_ops = {
374*4882a593Smuzhiyun 	.write = nfc_mei_phy_write,
375*4882a593Smuzhiyun 	.enable = nfc_mei_phy_enable,
376*4882a593Smuzhiyun 	.disable = nfc_mei_phy_disable,
377*4882a593Smuzhiyun };
378*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(mei_phy_ops);
379*4882a593Smuzhiyun 
nfc_mei_phy_alloc(struct mei_cl_device * cldev)380*4882a593Smuzhiyun struct nfc_mei_phy *nfc_mei_phy_alloc(struct mei_cl_device *cldev)
381*4882a593Smuzhiyun {
382*4882a593Smuzhiyun 	struct nfc_mei_phy *phy;
383*4882a593Smuzhiyun 
384*4882a593Smuzhiyun 	phy = kzalloc(sizeof(struct nfc_mei_phy), GFP_KERNEL);
385*4882a593Smuzhiyun 	if (!phy)
386*4882a593Smuzhiyun 		return NULL;
387*4882a593Smuzhiyun 
388*4882a593Smuzhiyun 	phy->cldev = cldev;
389*4882a593Smuzhiyun 	init_waitqueue_head(&phy->send_wq);
390*4882a593Smuzhiyun 	mei_cldev_set_drvdata(cldev, phy);
391*4882a593Smuzhiyun 
392*4882a593Smuzhiyun 	return phy;
393*4882a593Smuzhiyun }
394*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(nfc_mei_phy_alloc);
395*4882a593Smuzhiyun 
nfc_mei_phy_free(struct nfc_mei_phy * phy)396*4882a593Smuzhiyun void nfc_mei_phy_free(struct nfc_mei_phy *phy)
397*4882a593Smuzhiyun {
398*4882a593Smuzhiyun 	mei_cldev_disable(phy->cldev);
399*4882a593Smuzhiyun 	kfree(phy);
400*4882a593Smuzhiyun }
401*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(nfc_mei_phy_free);
402*4882a593Smuzhiyun 
403*4882a593Smuzhiyun MODULE_LICENSE("GPL");
404*4882a593Smuzhiyun MODULE_DESCRIPTION("mei bus NFC device interface");
405