1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3 * Copyright (C) 2023 Intel Corporation. All rights reserved.
4 * Intel Visual Sensing Controller ACE Linux driver
5 */
6
7 /*
8 * To set ownership of camera sensor, there is specific command, which
9 * is sent via MEI protocol. That's a two-step scheme where the firmware
10 * first acks receipt of the command and later responses the command was
11 * executed. The command sending function uses "completion" as the
12 * synchronization mechanism. The notification for command is received
13 * via a mei callback which wakes up the caller. There can be only one
14 * outstanding command at a time.
15 *
16 * The power line of camera sensor is directly connected to IVSC instead
17 * of host, when camera sensor ownership is switched to host, sensor is
18 * already powered up by firmware.
19 */
20
21 #include <linux/acpi.h>
22 #include <linux/completion.h>
23 #include <linux/delay.h>
24 #include <linux/kernel.h>
25 #include <linux/mei_cl_bus.h>
26 #include <linux/module.h>
27 #include <linux/mutex.h>
28 #include <linux/pm_runtime.h>
29 #include <linux/slab.h>
30 #include <linux/uuid.h>
31 #include <linux/workqueue.h>
32
33 #define MEI_ACE_DRIVER_NAME "ivsc_ace"
34
35 /* indicating driver message */
36 #define ACE_DRV_MSG 1
37 /* indicating set command */
38 #define ACE_CMD_SET 4
39 /* command timeout determined experimentally */
40 #define ACE_CMD_TIMEOUT (5 * HZ)
41 /* indicating the first command block */
42 #define ACE_CMD_INIT_BLOCK 1
43 /* indicating the last command block */
44 #define ACE_CMD_FINAL_BLOCK 1
45 /* size of camera status notification content */
46 #define ACE_CAMERA_STATUS_SIZE 5
47
48 /* UUID used to get firmware id */
49 #define ACE_GET_FW_ID_UUID UUID_LE(0x6167DCFB, 0x72F1, 0x4584, 0xBF, \
50 0xE3, 0x84, 0x17, 0x71, 0xAA, 0x79, 0x0B)
51
52 /* UUID used to get csi device */
53 #define MEI_CSI_UUID UUID_LE(0x92335FCF, 0x3203, 0x4472, \
54 0xAF, 0x93, 0x7b, 0x44, 0x53, 0xAC, 0x29, 0xDA)
55
56 /* identify firmware event type */
57 enum ace_event_type {
58 /* firmware ready */
59 ACE_FW_READY = 0x8,
60
61 /* command response */
62 ACE_CMD_RESPONSE = 0x10,
63 };
64
65 /* identify camera sensor ownership */
66 enum ace_camera_owner {
67 ACE_CAMERA_IVSC,
68 ACE_CAMERA_HOST,
69 };
70
71 /* identify the command id supported by firmware IPC */
72 enum ace_cmd_id {
73 /* used to switch camera sensor to host */
74 ACE_SWITCH_CAMERA_TO_HOST = 0x13,
75
76 /* used to switch camera sensor to IVSC */
77 ACE_SWITCH_CAMERA_TO_IVSC = 0x14,
78
79 /* used to get firmware id */
80 ACE_GET_FW_ID = 0x1A,
81 };
82
83 /* ACE command header structure */
84 struct ace_cmd_hdr {
85 u32 firmware_id : 16;
86 u32 instance_id : 8;
87 u32 type : 5;
88 u32 rsp : 1;
89 u32 msg_tgt : 1;
90 u32 _hw_rsvd_1 : 1;
91 u32 param_size : 20;
92 u32 cmd_id : 8;
93 u32 final_block : 1;
94 u32 init_block : 1;
95 u32 _hw_rsvd_2 : 2;
96 } __packed;
97
98 /* ACE command parameter structure */
99 union ace_cmd_param {
100 uuid_le uuid;
101 u32 param;
102 };
103
104 /* ACE command structure */
105 struct ace_cmd {
106 struct ace_cmd_hdr hdr;
107 union ace_cmd_param param;
108 } __packed;
109
110 /* ACE notification header */
111 union ace_notif_hdr {
112 struct _confirm {
113 u32 status : 24;
114 u32 type : 5;
115 u32 rsp : 1;
116 u32 msg_tgt : 1;
117 u32 _hw_rsvd_1 : 1;
118 u32 param_size : 20;
119 u32 cmd_id : 8;
120 u32 final_block : 1;
121 u32 init_block : 1;
122 u32 _hw_rsvd_2 : 2;
123 } __packed ack;
124
125 struct _event {
126 u32 rsvd1 : 16;
127 u32 event_type : 8;
128 u32 type : 5;
129 u32 ack : 1;
130 u32 msg_tgt : 1;
131 u32 _hw_rsvd_1 : 1;
132 u32 rsvd2 : 30;
133 u32 _hw_rsvd_2 : 2;
134 } __packed event;
135
136 struct _response {
137 u32 event_id : 16;
138 u32 notif_type : 8;
139 u32 type : 5;
140 u32 rsp : 1;
141 u32 msg_tgt : 1;
142 u32 _hw_rsvd_1 : 1;
143 u32 event_data_size : 16;
144 u32 request_target : 1;
145 u32 request_type : 5;
146 u32 cmd_id : 8;
147 u32 _hw_rsvd_2 : 2;
148 } __packed response;
149 };
150
151 /* ACE notification content */
152 union ace_notif_cont {
153 u16 firmware_id;
154 u8 state_notif;
155 u8 camera_status[ACE_CAMERA_STATUS_SIZE];
156 };
157
158 /* ACE notification structure */
159 struct ace_notif {
160 union ace_notif_hdr hdr;
161 union ace_notif_cont cont;
162 } __packed;
163
164 struct mei_ace {
165 struct mei_cl_device *cldev;
166
167 /* command ack */
168 struct ace_notif cmd_ack;
169 /* command response */
170 struct ace_notif cmd_response;
171 /* used to wait for command ack and response */
172 struct completion cmd_completion;
173 /* lock used to prevent multiple call to send command */
174 struct mutex lock;
175
176 /* used to construct command */
177 u16 firmware_id;
178
179 struct device *csi_dev;
180
181 /* runtime PM link from ace to csi */
182 struct device_link *csi_link;
183
184 struct work_struct work;
185 };
186
init_cmd_hdr(struct ace_cmd_hdr * hdr)187 static inline void init_cmd_hdr(struct ace_cmd_hdr *hdr)
188 {
189 memset(hdr, 0, sizeof(struct ace_cmd_hdr));
190
191 hdr->type = ACE_CMD_SET;
192 hdr->msg_tgt = ACE_DRV_MSG;
193 hdr->init_block = ACE_CMD_INIT_BLOCK;
194 hdr->final_block = ACE_CMD_FINAL_BLOCK;
195 }
196
construct_command(struct mei_ace * ace,struct ace_cmd * cmd,enum ace_cmd_id cmd_id)197 static int construct_command(struct mei_ace *ace, struct ace_cmd *cmd,
198 enum ace_cmd_id cmd_id)
199 {
200 union ace_cmd_param *param = &cmd->param;
201 struct ace_cmd_hdr *hdr = &cmd->hdr;
202
203 init_cmd_hdr(hdr);
204
205 hdr->cmd_id = cmd_id;
206 switch (cmd_id) {
207 case ACE_GET_FW_ID:
208 param->uuid = ACE_GET_FW_ID_UUID;
209 hdr->param_size = sizeof(param->uuid);
210 break;
211 case ACE_SWITCH_CAMERA_TO_IVSC:
212 param->param = 0;
213 hdr->firmware_id = ace->firmware_id;
214 hdr->param_size = sizeof(param->param);
215 break;
216 case ACE_SWITCH_CAMERA_TO_HOST:
217 hdr->firmware_id = ace->firmware_id;
218 break;
219 default:
220 return -EINVAL;
221 }
222
223 return hdr->param_size + sizeof(cmd->hdr);
224 }
225
226 /* send command to firmware */
mei_ace_send(struct mei_ace * ace,struct ace_cmd * cmd,size_t len,bool only_ack)227 static int mei_ace_send(struct mei_ace *ace, struct ace_cmd *cmd,
228 size_t len, bool only_ack)
229 {
230 union ace_notif_hdr *resp_hdr = &ace->cmd_response.hdr;
231 union ace_notif_hdr *ack_hdr = &ace->cmd_ack.hdr;
232 struct ace_cmd_hdr *cmd_hdr = &cmd->hdr;
233 int ret;
234
235 mutex_lock(&ace->lock);
236
237 reinit_completion(&ace->cmd_completion);
238
239 ret = mei_cldev_send(ace->cldev, (u8 *)cmd, len);
240 if (ret < 0)
241 goto out;
242
243 ret = wait_for_completion_killable_timeout(&ace->cmd_completion,
244 ACE_CMD_TIMEOUT);
245 if (ret < 0) {
246 goto out;
247 } else if (!ret) {
248 ret = -ETIMEDOUT;
249 goto out;
250 }
251
252 if (ack_hdr->ack.cmd_id != cmd_hdr->cmd_id) {
253 ret = -EINVAL;
254 goto out;
255 }
256
257 /* command ack status */
258 ret = ack_hdr->ack.status;
259 if (ret) {
260 ret = -EIO;
261 goto out;
262 }
263
264 if (only_ack)
265 goto out;
266
267 ret = wait_for_completion_killable_timeout(&ace->cmd_completion,
268 ACE_CMD_TIMEOUT);
269 if (ret < 0) {
270 goto out;
271 } else if (!ret) {
272 ret = -ETIMEDOUT;
273 goto out;
274 } else {
275 ret = 0;
276 }
277
278 if (resp_hdr->response.cmd_id != cmd_hdr->cmd_id)
279 ret = -EINVAL;
280
281 out:
282 mutex_unlock(&ace->lock);
283
284 return ret;
285 }
286
ace_set_camera_owner(struct mei_ace * ace,enum ace_camera_owner owner)287 static int ace_set_camera_owner(struct mei_ace *ace,
288 enum ace_camera_owner owner)
289 {
290 enum ace_cmd_id cmd_id;
291 struct ace_cmd cmd;
292 int cmd_size;
293 int ret;
294
295 if (owner == ACE_CAMERA_IVSC)
296 cmd_id = ACE_SWITCH_CAMERA_TO_IVSC;
297 else
298 cmd_id = ACE_SWITCH_CAMERA_TO_HOST;
299
300 cmd_size = construct_command(ace, &cmd, cmd_id);
301 if (cmd_size >= 0)
302 ret = mei_ace_send(ace, &cmd, cmd_size, false);
303 else
304 ret = cmd_size;
305
306 return ret;
307 }
308
309 /* the first command downloaded to firmware */
ace_get_firmware_id(struct mei_ace * ace)310 static inline int ace_get_firmware_id(struct mei_ace *ace)
311 {
312 struct ace_cmd cmd;
313 int cmd_size;
314 int ret;
315
316 cmd_size = construct_command(ace, &cmd, ACE_GET_FW_ID);
317 if (cmd_size >= 0)
318 ret = mei_ace_send(ace, &cmd, cmd_size, true);
319 else
320 ret = cmd_size;
321
322 return ret;
323 }
324
handle_command_response(struct mei_ace * ace,struct ace_notif * resp,int len)325 static void handle_command_response(struct mei_ace *ace,
326 struct ace_notif *resp, int len)
327 {
328 union ace_notif_hdr *hdr = &resp->hdr;
329
330 switch (hdr->response.cmd_id) {
331 case ACE_SWITCH_CAMERA_TO_IVSC:
332 case ACE_SWITCH_CAMERA_TO_HOST:
333 memcpy(&ace->cmd_response, resp, len);
334 complete(&ace->cmd_completion);
335 break;
336 case ACE_GET_FW_ID:
337 break;
338 default:
339 break;
340 }
341 }
342
handle_command_ack(struct mei_ace * ace,struct ace_notif * ack,int len)343 static void handle_command_ack(struct mei_ace *ace,
344 struct ace_notif *ack, int len)
345 {
346 union ace_notif_hdr *hdr = &ack->hdr;
347
348 switch (hdr->ack.cmd_id) {
349 case ACE_GET_FW_ID:
350 ace->firmware_id = ack->cont.firmware_id;
351 fallthrough;
352 case ACE_SWITCH_CAMERA_TO_IVSC:
353 case ACE_SWITCH_CAMERA_TO_HOST:
354 memcpy(&ace->cmd_ack, ack, len);
355 complete(&ace->cmd_completion);
356 break;
357 default:
358 break;
359 }
360 }
361
362 /* callback for receive */
mei_ace_rx(struct mei_cl_device * cldev)363 static void mei_ace_rx(struct mei_cl_device *cldev)
364 {
365 struct mei_ace *ace = mei_cldev_get_drvdata(cldev);
366 struct ace_notif event;
367 union ace_notif_hdr *hdr = &event.hdr;
368 int ret;
369
370 ret = mei_cldev_recv(cldev, (u8 *)&event, sizeof(event));
371 if (ret < 0) {
372 dev_err(&cldev->dev, "recv error: %d\n", ret);
373 return;
374 }
375
376 if (hdr->event.ack) {
377 handle_command_ack(ace, &event, ret);
378 return;
379 }
380
381 switch (hdr->event.event_type) {
382 case ACE_CMD_RESPONSE:
383 handle_command_response(ace, &event, ret);
384 break;
385 case ACE_FW_READY:
386 /*
387 * firmware ready notification sent to driver
388 * after HECI client connected with firmware.
389 */
390 dev_dbg(&cldev->dev, "firmware ready\n");
391 break;
392 default:
393 break;
394 }
395 }
396
mei_ace_setup_dev_link(struct mei_ace * ace)397 static int mei_ace_setup_dev_link(struct mei_ace *ace)
398 {
399 struct device *dev = &ace->cldev->dev;
400 uuid_le uuid = MEI_CSI_UUID;
401 struct device *csi_dev;
402 char name[64];
403 int ret;
404
405 snprintf(name, sizeof(name), "%s-%pUl", dev_name(dev->parent), &uuid);
406
407 csi_dev = device_find_child_by_name(dev->parent, name);
408 if (!csi_dev) {
409 ret = -EPROBE_DEFER;
410 goto err;
411 }
412
413 /* setup link between mei_ace and mei_csi */
414 ace->csi_link = device_link_add(csi_dev, dev, DL_FLAG_PM_RUNTIME |
415 DL_FLAG_RPM_ACTIVE | DL_FLAG_STATELESS);
416 if (!ace->csi_link) {
417 ret = -EINVAL;
418 dev_err(dev, "failed to link to %s\n", dev_name(csi_dev));
419 goto err_put;
420 }
421
422 ace->csi_dev = csi_dev;
423
424 return 0;
425
426 err_put:
427 put_device(csi_dev);
428
429 err:
430 return ret;
431 }
432
433 /* switch camera to host before probe sensor device */
mei_ace_post_probe_work(struct work_struct * work)434 static void mei_ace_post_probe_work(struct work_struct *work)
435 {
436 struct acpi_device *adev;
437 struct mei_ace *ace;
438 struct device *dev;
439 int ret;
440
441 ace = container_of(work, struct mei_ace, work);
442 dev = &ace->cldev->dev;
443
444 ret = ace_set_camera_owner(ace, ACE_CAMERA_HOST);
445 if (ret) {
446 dev_err(dev, "switch camera to host failed: %d\n", ret);
447 return;
448 }
449
450 adev = ACPI_COMPANION(dev->parent);
451 if (!adev)
452 return;
453
454 acpi_dev_clear_dependencies(adev);
455 }
456
mei_ace_probe(struct mei_cl_device * cldev,const struct mei_cl_device_id * id)457 static int mei_ace_probe(struct mei_cl_device *cldev,
458 const struct mei_cl_device_id *id)
459 {
460 struct device *dev = &cldev->dev;
461 struct mei_ace *ace;
462 int ret;
463
464 ace = devm_kzalloc(dev, sizeof(struct mei_ace), GFP_KERNEL);
465 if (!ace)
466 return -ENOMEM;
467
468 ace->cldev = cldev;
469 mutex_init(&ace->lock);
470 init_completion(&ace->cmd_completion);
471 INIT_WORK(&ace->work, mei_ace_post_probe_work);
472
473 mei_cldev_set_drvdata(cldev, ace);
474
475 ret = mei_cldev_enable(cldev);
476 if (ret < 0) {
477 dev_err(dev, "mei_cldev_enable failed: %d\n", ret);
478 goto destroy_mutex;
479 }
480
481 ret = mei_cldev_register_rx_cb(cldev, mei_ace_rx);
482 if (ret) {
483 dev_err(dev, "event cb registration failed: %d\n", ret);
484 goto err_disable;
485 }
486
487 ret = ace_get_firmware_id(ace);
488 if (ret) {
489 dev_err(dev, "get firmware id failed: %d\n", ret);
490 goto err_disable;
491 }
492
493 pm_runtime_set_active(dev);
494 pm_runtime_enable(dev);
495
496 ret = mei_ace_setup_dev_link(ace);
497 if (ret)
498 goto disable_pm;
499
500 schedule_work(&ace->work);
501
502 return 0;
503
504 disable_pm:
505 pm_runtime_disable(dev);
506 pm_runtime_set_suspended(dev);
507
508 err_disable:
509 mei_cldev_disable(cldev);
510
511 destroy_mutex:
512 mutex_destroy(&ace->lock);
513
514 return ret;
515 }
516
mei_ace_remove(struct mei_cl_device * cldev)517 static void mei_ace_remove(struct mei_cl_device *cldev)
518 {
519 struct mei_ace *ace = mei_cldev_get_drvdata(cldev);
520
521 cancel_work_sync(&ace->work);
522
523 device_link_del(ace->csi_link);
524 put_device(ace->csi_dev);
525
526 pm_runtime_disable(&cldev->dev);
527 pm_runtime_set_suspended(&cldev->dev);
528
529 ace_set_camera_owner(ace, ACE_CAMERA_IVSC);
530
531 mutex_destroy(&ace->lock);
532 }
533
mei_ace_runtime_suspend(struct device * dev)534 static int __maybe_unused mei_ace_runtime_suspend(struct device *dev)
535 {
536 struct mei_ace *ace = dev_get_drvdata(dev);
537
538 return ace_set_camera_owner(ace, ACE_CAMERA_IVSC);
539 }
540
mei_ace_runtime_resume(struct device * dev)541 static int __maybe_unused mei_ace_runtime_resume(struct device *dev)
542 {
543 struct mei_ace *ace = dev_get_drvdata(dev);
544
545 return ace_set_camera_owner(ace, ACE_CAMERA_HOST);
546 }
547
548 static const struct dev_pm_ops mei_ace_pm_ops = {
549 SET_RUNTIME_PM_OPS(mei_ace_runtime_suspend,
550 mei_ace_runtime_resume, NULL)
551 };
552
553 #define MEI_ACE_UUID UUID_LE(0x5DB76CF6, 0x0A68, 0x4ED6, \
554 0x9B, 0x78, 0x03, 0x61, 0x63, 0x5E, 0x24, 0x47)
555
556 static const struct mei_cl_device_id mei_ace_tbl[] = {
557 { MEI_ACE_DRIVER_NAME, MEI_ACE_UUID, MEI_CL_VERSION_ANY },
558 { /* sentinel */ }
559 };
560 MODULE_DEVICE_TABLE(mei, mei_ace_tbl);
561
562 static struct mei_cl_driver mei_ace_driver = {
563 .id_table = mei_ace_tbl,
564 .name = MEI_ACE_DRIVER_NAME,
565
566 .probe = mei_ace_probe,
567 .remove = mei_ace_remove,
568
569 .driver = {
570 .pm = &mei_ace_pm_ops,
571 },
572 };
573
574 module_mei_cl_driver(mei_ace_driver);
575
576 MODULE_AUTHOR("Wentong Wu <wentong.wu@intel.com>");
577 MODULE_AUTHOR("Zhifeng Wang <zhifeng.wang@intel.com>");
578 MODULE_DESCRIPTION("Device driver for IVSC ACE");
579 MODULE_LICENSE("GPL");
580