xref: /linux/drivers/misc/mei/platform-vsc.c (revision cdd30ebb1b9f36159d66f088b61aee264e649d7a)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (c) 2023, Intel Corporation.
4  * Intel Visual Sensing Controller Interface Linux driver
5  */
6 
7 #include <linux/align.h>
8 #include <linux/cache.h>
9 #include <linux/cleanup.h>
10 #include <linux/iopoll.h>
11 #include <linux/list.h>
12 #include <linux/mei.h>
13 #include <linux/module.h>
14 #include <linux/mutex.h>
15 #include <linux/overflow.h>
16 #include <linux/platform_device.h>
17 #include <linux/pm_runtime.h>
18 #include <linux/timekeeping.h>
19 #include <linux/types.h>
20 
21 #include <asm-generic/bug.h>
22 #include <linux/unaligned.h>
23 
24 #include "mei_dev.h"
25 #include "vsc-tp.h"
26 
27 #define MEI_VSC_DRV_NAME		"intel_vsc"
28 
29 #define MEI_VSC_MAX_MSG_SIZE		512
30 
31 #define MEI_VSC_POLL_DELAY_US		(100 * USEC_PER_MSEC)
32 #define MEI_VSC_POLL_TIMEOUT_US		(400 * USEC_PER_MSEC)
33 
34 #define mei_dev_to_vsc_hw(dev)		((struct mei_vsc_hw *)((dev)->hw))
35 
36 struct mei_vsc_host_timestamp {
37 	u64 realtime;
38 	u64 boottime;
39 };
40 
41 struct mei_vsc_hw {
42 	struct vsc_tp *tp;
43 
44 	bool fw_ready;
45 	bool host_ready;
46 
47 	atomic_t write_lock_cnt;
48 
49 	u32 rx_len;
50 	u32 rx_hdr;
51 
52 	/* buffer for tx */
53 	char tx_buf[MEI_VSC_MAX_MSG_SIZE + sizeof(struct mei_msg_hdr)] ____cacheline_aligned;
54 	/* buffer for rx */
55 	char rx_buf[MEI_VSC_MAX_MSG_SIZE + sizeof(struct mei_msg_hdr)] ____cacheline_aligned;
56 };
57 
mei_vsc_read_helper(struct mei_vsc_hw * hw,u8 * buf,u32 max_len)58 static int mei_vsc_read_helper(struct mei_vsc_hw *hw, u8 *buf,
59 			       u32 max_len)
60 {
61 	struct mei_vsc_host_timestamp ts = {
62 		.realtime = ktime_to_ns(ktime_get_real()),
63 		.boottime = ktime_to_ns(ktime_get_boottime()),
64 	};
65 
66 	return vsc_tp_xfer(hw->tp, VSC_TP_CMD_READ, &ts, sizeof(ts),
67 			   buf, max_len);
68 }
69 
mei_vsc_write_helper(struct mei_vsc_hw * hw,u8 * buf,u32 len)70 static int mei_vsc_write_helper(struct mei_vsc_hw *hw, u8 *buf, u32 len)
71 {
72 	u8 status;
73 
74 	return vsc_tp_xfer(hw->tp, VSC_TP_CMD_WRITE, buf, len, &status,
75 			   sizeof(status));
76 }
77 
mei_vsc_fw_status(struct mei_device * mei_dev,struct mei_fw_status * fw_status)78 static int mei_vsc_fw_status(struct mei_device *mei_dev,
79 			     struct mei_fw_status *fw_status)
80 {
81 	if (!fw_status)
82 		return -EINVAL;
83 
84 	fw_status->count = 0;
85 
86 	return 0;
87 }
88 
mei_vsc_pg_state(struct mei_device * mei_dev)89 static inline enum mei_pg_state mei_vsc_pg_state(struct mei_device *mei_dev)
90 {
91 	return MEI_PG_OFF;
92 }
93 
mei_vsc_intr_enable(struct mei_device * mei_dev)94 static void mei_vsc_intr_enable(struct mei_device *mei_dev)
95 {
96 	struct mei_vsc_hw *hw = mei_dev_to_vsc_hw(mei_dev);
97 
98 	vsc_tp_intr_enable(hw->tp);
99 }
100 
mei_vsc_intr_disable(struct mei_device * mei_dev)101 static void mei_vsc_intr_disable(struct mei_device *mei_dev)
102 {
103 	struct mei_vsc_hw *hw = mei_dev_to_vsc_hw(mei_dev);
104 
105 	vsc_tp_intr_disable(hw->tp);
106 }
107 
108 /* mei framework requires this ops */
mei_vsc_intr_clear(struct mei_device * mei_dev)109 static void mei_vsc_intr_clear(struct mei_device *mei_dev)
110 {
111 }
112 
113 /* wait for pending irq handler */
mei_vsc_synchronize_irq(struct mei_device * mei_dev)114 static void mei_vsc_synchronize_irq(struct mei_device *mei_dev)
115 {
116 	struct mei_vsc_hw *hw = mei_dev_to_vsc_hw(mei_dev);
117 
118 	vsc_tp_intr_synchronize(hw->tp);
119 }
120 
mei_vsc_hw_config(struct mei_device * mei_dev)121 static int mei_vsc_hw_config(struct mei_device *mei_dev)
122 {
123 	return 0;
124 }
125 
mei_vsc_host_is_ready(struct mei_device * mei_dev)126 static bool mei_vsc_host_is_ready(struct mei_device *mei_dev)
127 {
128 	struct mei_vsc_hw *hw = mei_dev_to_vsc_hw(mei_dev);
129 
130 	return hw->host_ready;
131 }
132 
mei_vsc_hw_is_ready(struct mei_device * mei_dev)133 static bool mei_vsc_hw_is_ready(struct mei_device *mei_dev)
134 {
135 	struct mei_vsc_hw *hw = mei_dev_to_vsc_hw(mei_dev);
136 
137 	return hw->fw_ready;
138 }
139 
mei_vsc_hw_start(struct mei_device * mei_dev)140 static int mei_vsc_hw_start(struct mei_device *mei_dev)
141 {
142 	struct mei_vsc_hw *hw = mei_dev_to_vsc_hw(mei_dev);
143 	int ret, rlen;
144 	u8 buf;
145 
146 	hw->host_ready = true;
147 
148 	vsc_tp_intr_enable(hw->tp);
149 
150 	ret = read_poll_timeout(mei_vsc_read_helper, rlen,
151 				rlen >= 0, MEI_VSC_POLL_DELAY_US,
152 				MEI_VSC_POLL_TIMEOUT_US, true,
153 				hw, &buf, sizeof(buf));
154 	if (ret) {
155 		dev_err(mei_dev->dev, "wait fw ready failed: %d\n", ret);
156 		return ret;
157 	}
158 
159 	hw->fw_ready = true;
160 
161 	return 0;
162 }
163 
mei_vsc_hbuf_is_ready(struct mei_device * mei_dev)164 static bool mei_vsc_hbuf_is_ready(struct mei_device *mei_dev)
165 {
166 	struct mei_vsc_hw *hw = mei_dev_to_vsc_hw(mei_dev);
167 
168 	return atomic_read(&hw->write_lock_cnt) == 0;
169 }
170 
mei_vsc_hbuf_empty_slots(struct mei_device * mei_dev)171 static int mei_vsc_hbuf_empty_slots(struct mei_device *mei_dev)
172 {
173 	return MEI_VSC_MAX_MSG_SIZE / MEI_SLOT_SIZE;
174 }
175 
mei_vsc_hbuf_depth(const struct mei_device * mei_dev)176 static u32 mei_vsc_hbuf_depth(const struct mei_device *mei_dev)
177 {
178 	return MEI_VSC_MAX_MSG_SIZE / MEI_SLOT_SIZE;
179 }
180 
mei_vsc_write(struct mei_device * mei_dev,const void * hdr,size_t hdr_len,const void * data,size_t data_len)181 static int mei_vsc_write(struct mei_device *mei_dev,
182 			 const void *hdr, size_t hdr_len,
183 			 const void *data, size_t data_len)
184 {
185 	struct mei_vsc_hw *hw = mei_dev_to_vsc_hw(mei_dev);
186 	char *buf = hw->tx_buf;
187 	int ret;
188 
189 	if (WARN_ON(!hdr || !IS_ALIGNED(hdr_len, 4)))
190 		return -EINVAL;
191 
192 	if (!data || data_len > MEI_VSC_MAX_MSG_SIZE)
193 		return -EINVAL;
194 
195 	atomic_inc(&hw->write_lock_cnt);
196 
197 	memcpy(buf, hdr, hdr_len);
198 	memcpy(buf + hdr_len, data, data_len);
199 
200 	ret = mei_vsc_write_helper(hw, buf, hdr_len + data_len);
201 
202 	atomic_dec_if_positive(&hw->write_lock_cnt);
203 
204 	return ret < 0 ? ret : 0;
205 }
206 
mei_vsc_read(const struct mei_device * mei_dev)207 static inline u32 mei_vsc_read(const struct mei_device *mei_dev)
208 {
209 	struct mei_vsc_hw *hw = mei_dev_to_vsc_hw(mei_dev);
210 	int ret;
211 
212 	ret = mei_vsc_read_helper(hw, hw->rx_buf, sizeof(hw->rx_buf));
213 	if (ret < 0 || ret < sizeof(u32))
214 		return 0;
215 	hw->rx_len = ret;
216 
217 	hw->rx_hdr = get_unaligned_le32(hw->rx_buf);
218 
219 	return hw->rx_hdr;
220 }
221 
mei_vsc_count_full_read_slots(struct mei_device * mei_dev)222 static int mei_vsc_count_full_read_slots(struct mei_device *mei_dev)
223 {
224 	return MEI_VSC_MAX_MSG_SIZE / MEI_SLOT_SIZE;
225 }
226 
mei_vsc_read_slots(struct mei_device * mei_dev,unsigned char * buf,unsigned long len)227 static int mei_vsc_read_slots(struct mei_device *mei_dev, unsigned char *buf,
228 			      unsigned long len)
229 {
230 	struct mei_vsc_hw *hw = mei_dev_to_vsc_hw(mei_dev);
231 	struct mei_msg_hdr *hdr;
232 
233 	hdr = (struct mei_msg_hdr *)&hw->rx_hdr;
234 	if (len != hdr->length || hdr->length + sizeof(*hdr) != hw->rx_len)
235 		return -EINVAL;
236 
237 	memcpy(buf, hw->rx_buf + sizeof(*hdr), len);
238 
239 	return 0;
240 }
241 
mei_vsc_pg_in_transition(struct mei_device * mei_dev)242 static bool mei_vsc_pg_in_transition(struct mei_device *mei_dev)
243 {
244 	return mei_dev->pg_event >= MEI_PG_EVENT_WAIT &&
245 	       mei_dev->pg_event <= MEI_PG_EVENT_INTR_WAIT;
246 }
247 
mei_vsc_pg_is_enabled(struct mei_device * mei_dev)248 static bool mei_vsc_pg_is_enabled(struct mei_device *mei_dev)
249 {
250 	return false;
251 }
252 
mei_vsc_hw_reset(struct mei_device * mei_dev,bool intr_enable)253 static int mei_vsc_hw_reset(struct mei_device *mei_dev, bool intr_enable)
254 {
255 	struct mei_vsc_hw *hw = mei_dev_to_vsc_hw(mei_dev);
256 
257 	vsc_tp_reset(hw->tp);
258 
259 	return vsc_tp_init(hw->tp, mei_dev->dev);
260 }
261 
262 static const struct mei_hw_ops mei_vsc_hw_ops = {
263 	.fw_status = mei_vsc_fw_status,
264 	.pg_state = mei_vsc_pg_state,
265 
266 	.host_is_ready = mei_vsc_host_is_ready,
267 	.hw_is_ready = mei_vsc_hw_is_ready,
268 	.hw_reset = mei_vsc_hw_reset,
269 	.hw_config = mei_vsc_hw_config,
270 	.hw_start = mei_vsc_hw_start,
271 
272 	.pg_in_transition = mei_vsc_pg_in_transition,
273 	.pg_is_enabled = mei_vsc_pg_is_enabled,
274 
275 	.intr_clear = mei_vsc_intr_clear,
276 	.intr_enable = mei_vsc_intr_enable,
277 	.intr_disable = mei_vsc_intr_disable,
278 	.synchronize_irq = mei_vsc_synchronize_irq,
279 
280 	.hbuf_free_slots = mei_vsc_hbuf_empty_slots,
281 	.hbuf_is_ready = mei_vsc_hbuf_is_ready,
282 	.hbuf_depth = mei_vsc_hbuf_depth,
283 	.write = mei_vsc_write,
284 
285 	.rdbuf_full_slots = mei_vsc_count_full_read_slots,
286 	.read_hdr = mei_vsc_read,
287 	.read = mei_vsc_read_slots,
288 };
289 
mei_vsc_event_cb(void * context)290 static void mei_vsc_event_cb(void *context)
291 {
292 	struct mei_device *mei_dev = context;
293 	struct mei_vsc_hw *hw = mei_dev_to_vsc_hw(mei_dev);
294 	struct list_head cmpl_list;
295 	s32 slots;
296 	int ret;
297 
298 	if (mei_dev->dev_state == MEI_DEV_RESETTING ||
299 	    mei_dev->dev_state == MEI_DEV_INITIALIZING)
300 		return;
301 
302 	INIT_LIST_HEAD(&cmpl_list);
303 
304 	guard(mutex)(&mei_dev->device_lock);
305 
306 	while (vsc_tp_need_read(hw->tp)) {
307 		/* check slots available for reading */
308 		slots = mei_count_full_read_slots(mei_dev);
309 
310 		ret = mei_irq_read_handler(mei_dev, &cmpl_list, &slots);
311 		if (ret) {
312 			if (ret != -ENODATA) {
313 				if (mei_dev->dev_state != MEI_DEV_RESETTING &&
314 				    mei_dev->dev_state != MEI_DEV_POWER_DOWN)
315 					schedule_work(&mei_dev->reset_work);
316 			}
317 
318 			return;
319 		}
320 	}
321 
322 	mei_dev->hbuf_is_ready = mei_hbuf_is_ready(mei_dev);
323 	ret = mei_irq_write_handler(mei_dev, &cmpl_list);
324 	if (ret)
325 		dev_err(mei_dev->dev, "dispatch write request failed: %d\n", ret);
326 
327 	mei_dev->hbuf_is_ready = mei_hbuf_is_ready(mei_dev);
328 	mei_irq_compl_handler(mei_dev, &cmpl_list);
329 }
330 
mei_vsc_probe(struct platform_device * pdev)331 static int mei_vsc_probe(struct platform_device *pdev)
332 {
333 	struct device *dev = &pdev->dev;
334 	struct mei_device *mei_dev;
335 	struct mei_vsc_hw *hw;
336 	struct vsc_tp *tp;
337 	int ret;
338 
339 	tp = *(struct vsc_tp **)dev_get_platdata(dev);
340 	if (!tp)
341 		return dev_err_probe(dev, -ENODEV, "no platform data\n");
342 
343 	mei_dev = devm_kzalloc(dev, size_add(sizeof(*mei_dev), sizeof(*hw)),
344 			       GFP_KERNEL);
345 	if (!mei_dev)
346 		return -ENOMEM;
347 
348 	mei_device_init(mei_dev, dev, false, &mei_vsc_hw_ops);
349 	mei_dev->fw_f_fw_ver_supported = 0;
350 	mei_dev->kind = "ivsc";
351 
352 	hw = mei_dev_to_vsc_hw(mei_dev);
353 	atomic_set(&hw->write_lock_cnt, 0);
354 	hw->tp = tp;
355 
356 	platform_set_drvdata(pdev, mei_dev);
357 
358 	vsc_tp_register_event_cb(tp, mei_vsc_event_cb, mei_dev);
359 
360 	ret = mei_start(mei_dev);
361 	if (ret) {
362 		dev_err_probe(dev, ret, "init hw failed\n");
363 		goto err_cancel;
364 	}
365 
366 	ret = mei_register(mei_dev, dev);
367 	if (ret)
368 		goto err_stop;
369 
370 	pm_runtime_enable(mei_dev->dev);
371 
372 	return 0;
373 
374 err_stop:
375 	mei_stop(mei_dev);
376 
377 err_cancel:
378 	mei_cancel_work(mei_dev);
379 
380 	mei_disable_interrupts(mei_dev);
381 
382 	return ret;
383 }
384 
mei_vsc_remove(struct platform_device * pdev)385 static void mei_vsc_remove(struct platform_device *pdev)
386 {
387 	struct mei_device *mei_dev = platform_get_drvdata(pdev);
388 
389 	pm_runtime_disable(mei_dev->dev);
390 
391 	mei_stop(mei_dev);
392 
393 	mei_disable_interrupts(mei_dev);
394 
395 	mei_deregister(mei_dev);
396 }
397 
mei_vsc_suspend(struct device * dev)398 static int mei_vsc_suspend(struct device *dev)
399 {
400 	struct mei_device *mei_dev;
401 	int ret = 0;
402 
403 	mei_dev = dev_get_drvdata(dev);
404 	if (!mei_dev)
405 		return -ENODEV;
406 
407 	mutex_lock(&mei_dev->device_lock);
408 
409 	if (!mei_write_is_idle(mei_dev))
410 		ret = -EAGAIN;
411 
412 	mutex_unlock(&mei_dev->device_lock);
413 
414 	return ret;
415 }
416 
mei_vsc_resume(struct device * dev)417 static int mei_vsc_resume(struct device *dev)
418 {
419 	struct mei_device *mei_dev;
420 
421 	mei_dev = dev_get_drvdata(dev);
422 	if (!mei_dev)
423 		return -ENODEV;
424 
425 	return 0;
426 }
427 
428 static DEFINE_SIMPLE_DEV_PM_OPS(mei_vsc_pm_ops, mei_vsc_suspend, mei_vsc_resume);
429 
430 static const struct platform_device_id mei_vsc_id_table[] = {
431 	{ MEI_VSC_DRV_NAME },
432 	{ /* sentinel */ }
433 };
434 MODULE_DEVICE_TABLE(platform, mei_vsc_id_table);
435 
436 static struct platform_driver mei_vsc_drv = {
437 	.probe = mei_vsc_probe,
438 	.remove = mei_vsc_remove,
439 	.id_table = mei_vsc_id_table,
440 	.driver = {
441 		.name = MEI_VSC_DRV_NAME,
442 		.pm = &mei_vsc_pm_ops,
443 		.probe_type = PROBE_PREFER_ASYNCHRONOUS,
444 	},
445 };
446 module_platform_driver(mei_vsc_drv);
447 
448 MODULE_AUTHOR("Wentong Wu <wentong.wu@intel.com>");
449 MODULE_AUTHOR("Zhifeng Wang <zhifeng.wang@intel.com>");
450 MODULE_DESCRIPTION("Intel Visual Sensing Controller Interface");
451 MODULE_LICENSE("GPL");
452 MODULE_IMPORT_NS("VSC_TP");
453