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