xref: /linux/drivers/media/cec/platform/tegra/tegra_cec.c (revision 78964fcac47fc1525ecb4c37cd5fbc873c28320b)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Tegra CEC implementation
4  *
5  * The original 3.10 CEC driver using a custom API:
6  *
7  * Copyright (c) 2012-2015, NVIDIA CORPORATION.  All rights reserved.
8  *
9  * Conversion to the CEC framework and to the mainline kernel:
10  *
11  * Copyright 2016-2017 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
12  */
13 
14 #include <linux/module.h>
15 #include <linux/kernel.h>
16 #include <linux/err.h>
17 #include <linux/errno.h>
18 #include <linux/interrupt.h>
19 #include <linux/slab.h>
20 #include <linux/io.h>
21 #include <linux/clk.h>
22 #include <linux/delay.h>
23 #include <linux/pm.h>
24 #include <linux/of.h>
25 #include <linux/of_platform.h>
26 #include <linux/platform_device.h>
27 #include <linux/clk/tegra.h>
28 
29 #include <media/cec-notifier.h>
30 
31 #include "tegra_cec.h"
32 
33 #define TEGRA_CEC_NAME "tegra-cec"
34 
35 struct tegra_cec {
36 	struct cec_adapter	*adap;
37 	struct device		*dev;
38 	struct clk		*clk;
39 	void __iomem		*cec_base;
40 	struct cec_notifier	*notifier;
41 	int			tegra_cec_irq;
42 	bool			rx_done;
43 	bool			tx_done;
44 	int			tx_status;
45 	u8			rx_buf[CEC_MAX_MSG_SIZE];
46 	u8			rx_buf_cnt;
47 	u32			tx_buf[CEC_MAX_MSG_SIZE];
48 	u8			tx_buf_cur;
49 	u8			tx_buf_cnt;
50 };
51 
52 static inline u32 cec_read(struct tegra_cec *cec, u32 reg)
53 {
54 	return readl(cec->cec_base + reg);
55 }
56 
57 static inline void cec_write(struct tegra_cec *cec, u32 reg, u32 val)
58 {
59 	writel(val, cec->cec_base + reg);
60 }
61 
62 static void tegra_cec_error_recovery(struct tegra_cec *cec)
63 {
64 	u32 hw_ctrl;
65 
66 	hw_ctrl = cec_read(cec, TEGRA_CEC_HW_CONTROL);
67 	cec_write(cec, TEGRA_CEC_HW_CONTROL, 0);
68 	cec_write(cec, TEGRA_CEC_INT_STAT, 0xffffffff);
69 	cec_write(cec, TEGRA_CEC_HW_CONTROL, hw_ctrl);
70 }
71 
72 static irqreturn_t tegra_cec_irq_thread_handler(int irq, void *data)
73 {
74 	struct device *dev = data;
75 	struct tegra_cec *cec = dev_get_drvdata(dev);
76 
77 	if (cec->tx_done) {
78 		cec_transmit_attempt_done(cec->adap, cec->tx_status);
79 		cec->tx_done = false;
80 	}
81 	if (cec->rx_done) {
82 		struct cec_msg msg = {};
83 
84 		msg.len = cec->rx_buf_cnt;
85 		memcpy(msg.msg, cec->rx_buf, msg.len);
86 		cec_received_msg(cec->adap, &msg);
87 		cec->rx_done = false;
88 		cec->rx_buf_cnt = 0;
89 	}
90 	return IRQ_HANDLED;
91 }
92 
93 static irqreturn_t tegra_cec_irq_handler(int irq, void *data)
94 {
95 	struct device *dev = data;
96 	struct tegra_cec *cec = dev_get_drvdata(dev);
97 	u32 status, mask;
98 
99 	status = cec_read(cec, TEGRA_CEC_INT_STAT);
100 	mask = cec_read(cec, TEGRA_CEC_INT_MASK);
101 
102 	status &= mask;
103 
104 	if (!status)
105 		return IRQ_HANDLED;
106 
107 	if (status & TEGRA_CEC_INT_STAT_TX_REGISTER_UNDERRUN) {
108 		dev_err(dev, "TX underrun, interrupt timing issue!\n");
109 
110 		tegra_cec_error_recovery(cec);
111 		cec_write(cec, TEGRA_CEC_INT_MASK,
112 			  mask & ~TEGRA_CEC_INT_MASK_TX_REGISTER_EMPTY);
113 
114 		cec->tx_done = true;
115 		cec->tx_status = CEC_TX_STATUS_ERROR;
116 		return IRQ_WAKE_THREAD;
117 	}
118 
119 	if ((status & TEGRA_CEC_INT_STAT_TX_ARBITRATION_FAILED) ||
120 		   (status & TEGRA_CEC_INT_STAT_TX_BUS_ANOMALY_DETECTED)) {
121 		tegra_cec_error_recovery(cec);
122 		cec_write(cec, TEGRA_CEC_INT_MASK,
123 			  mask & ~TEGRA_CEC_INT_MASK_TX_REGISTER_EMPTY);
124 
125 		cec->tx_done = true;
126 		if (status & TEGRA_CEC_INT_STAT_TX_BUS_ANOMALY_DETECTED)
127 			cec->tx_status = CEC_TX_STATUS_LOW_DRIVE;
128 		else
129 			cec->tx_status = CEC_TX_STATUS_ARB_LOST;
130 		return IRQ_WAKE_THREAD;
131 	}
132 
133 	if (status & TEGRA_CEC_INT_STAT_TX_FRAME_TRANSMITTED) {
134 		cec_write(cec, TEGRA_CEC_INT_STAT,
135 			  TEGRA_CEC_INT_STAT_TX_FRAME_TRANSMITTED);
136 
137 		if (status & TEGRA_CEC_INT_STAT_TX_FRAME_OR_BLOCK_NAKD) {
138 			tegra_cec_error_recovery(cec);
139 
140 			cec->tx_done = true;
141 			cec->tx_status = CEC_TX_STATUS_NACK;
142 		} else {
143 			cec->tx_done = true;
144 			cec->tx_status = CEC_TX_STATUS_OK;
145 		}
146 		return IRQ_WAKE_THREAD;
147 	}
148 
149 	if (status & TEGRA_CEC_INT_STAT_TX_FRAME_OR_BLOCK_NAKD)
150 		dev_warn(dev, "TX NAKed on the fly!\n");
151 
152 	if (status & TEGRA_CEC_INT_STAT_TX_REGISTER_EMPTY) {
153 		if (cec->tx_buf_cur == cec->tx_buf_cnt) {
154 			cec_write(cec, TEGRA_CEC_INT_MASK,
155 				  mask & ~TEGRA_CEC_INT_MASK_TX_REGISTER_EMPTY);
156 		} else {
157 			cec_write(cec, TEGRA_CEC_TX_REGISTER,
158 				  cec->tx_buf[cec->tx_buf_cur++]);
159 			cec_write(cec, TEGRA_CEC_INT_STAT,
160 				  TEGRA_CEC_INT_STAT_TX_REGISTER_EMPTY);
161 		}
162 	}
163 
164 	if (status & TEGRA_CEC_INT_STAT_RX_START_BIT_DETECTED) {
165 		cec_write(cec, TEGRA_CEC_INT_STAT,
166 			  TEGRA_CEC_INT_STAT_RX_START_BIT_DETECTED);
167 		cec->rx_done = false;
168 		cec->rx_buf_cnt = 0;
169 	}
170 	if (status & TEGRA_CEC_INT_STAT_RX_REGISTER_FULL) {
171 		u32 v;
172 
173 		cec_write(cec, TEGRA_CEC_INT_STAT,
174 			  TEGRA_CEC_INT_STAT_RX_REGISTER_FULL);
175 		v = cec_read(cec, TEGRA_CEC_RX_REGISTER);
176 		if (cec->rx_buf_cnt < CEC_MAX_MSG_SIZE)
177 			cec->rx_buf[cec->rx_buf_cnt++] = v & 0xff;
178 		if (v & TEGRA_CEC_RX_REGISTER_EOM) {
179 			cec->rx_done = true;
180 			return IRQ_WAKE_THREAD;
181 		}
182 	}
183 
184 	return IRQ_HANDLED;
185 }
186 
187 static int tegra_cec_adap_enable(struct cec_adapter *adap, bool enable)
188 {
189 	struct tegra_cec *cec = adap->priv;
190 
191 	cec->rx_buf_cnt = 0;
192 	cec->tx_buf_cnt = 0;
193 	cec->tx_buf_cur = 0;
194 
195 	cec_write(cec, TEGRA_CEC_HW_CONTROL, 0);
196 	cec_write(cec, TEGRA_CEC_INT_MASK, 0);
197 	cec_write(cec, TEGRA_CEC_INT_STAT, 0xffffffff);
198 	cec_write(cec, TEGRA_CEC_SW_CONTROL, 0);
199 
200 	if (!enable)
201 		return 0;
202 
203 	cec_write(cec, TEGRA_CEC_INPUT_FILTER, (1U << 31) | 0x20);
204 
205 	cec_write(cec, TEGRA_CEC_RX_TIMING_0,
206 		  (0x7a << TEGRA_CEC_RX_TIM0_START_BIT_MAX_LO_TIME_SHIFT) |
207 		  (0x6d << TEGRA_CEC_RX_TIM0_START_BIT_MIN_LO_TIME_SHIFT) |
208 		  (0x93 << TEGRA_CEC_RX_TIM0_START_BIT_MAX_DURATION_SHIFT) |
209 		  (0x86 << TEGRA_CEC_RX_TIM0_START_BIT_MIN_DURATION_SHIFT));
210 
211 	cec_write(cec, TEGRA_CEC_RX_TIMING_1,
212 		  (0x35 << TEGRA_CEC_RX_TIM1_DATA_BIT_MAX_LO_TIME_SHIFT) |
213 		  (0x21 << TEGRA_CEC_RX_TIM1_DATA_BIT_SAMPLE_TIME_SHIFT) |
214 		  (0x56 << TEGRA_CEC_RX_TIM1_DATA_BIT_MAX_DURATION_SHIFT) |
215 		  (0x40 << TEGRA_CEC_RX_TIM1_DATA_BIT_MIN_DURATION_SHIFT));
216 
217 	cec_write(cec, TEGRA_CEC_RX_TIMING_2,
218 		  (0x50 << TEGRA_CEC_RX_TIM2_END_OF_BLOCK_TIME_SHIFT));
219 
220 	cec_write(cec, TEGRA_CEC_TX_TIMING_0,
221 		  (0x74 << TEGRA_CEC_TX_TIM0_START_BIT_LO_TIME_SHIFT) |
222 		  (0x8d << TEGRA_CEC_TX_TIM0_START_BIT_DURATION_SHIFT) |
223 		  (0x08 << TEGRA_CEC_TX_TIM0_BUS_XITION_TIME_SHIFT) |
224 		  (0x71 << TEGRA_CEC_TX_TIM0_BUS_ERROR_LO_TIME_SHIFT));
225 
226 	cec_write(cec, TEGRA_CEC_TX_TIMING_1,
227 		  (0x2f << TEGRA_CEC_TX_TIM1_LO_DATA_BIT_LO_TIME_SHIFT) |
228 		  (0x13 << TEGRA_CEC_TX_TIM1_HI_DATA_BIT_LO_TIME_SHIFT) |
229 		  (0x4b << TEGRA_CEC_TX_TIM1_DATA_BIT_DURATION_SHIFT) |
230 		  (0x21 << TEGRA_CEC_TX_TIM1_ACK_NAK_BIT_SAMPLE_TIME_SHIFT));
231 
232 	cec_write(cec, TEGRA_CEC_TX_TIMING_2,
233 		  (0x07 << TEGRA_CEC_TX_TIM2_BUS_IDLE_TIME_ADDITIONAL_FRAME_SHIFT) |
234 		  (0x05 << TEGRA_CEC_TX_TIM2_BUS_IDLE_TIME_NEW_FRAME_SHIFT) |
235 		  (0x03 << TEGRA_CEC_TX_TIM2_BUS_IDLE_TIME_RETRY_FRAME_SHIFT));
236 
237 	cec_write(cec, TEGRA_CEC_INT_MASK,
238 		  TEGRA_CEC_INT_MASK_TX_REGISTER_UNDERRUN |
239 		  TEGRA_CEC_INT_MASK_TX_FRAME_OR_BLOCK_NAKD |
240 		  TEGRA_CEC_INT_MASK_TX_ARBITRATION_FAILED |
241 		  TEGRA_CEC_INT_MASK_TX_BUS_ANOMALY_DETECTED |
242 		  TEGRA_CEC_INT_MASK_TX_FRAME_TRANSMITTED |
243 		  TEGRA_CEC_INT_MASK_RX_REGISTER_FULL |
244 		  TEGRA_CEC_INT_MASK_RX_START_BIT_DETECTED);
245 
246 	cec_write(cec, TEGRA_CEC_HW_CONTROL, TEGRA_CEC_HWCTRL_TX_RX_MODE);
247 	return 0;
248 }
249 
250 static int tegra_cec_adap_log_addr(struct cec_adapter *adap, u8 logical_addr)
251 {
252 	struct tegra_cec *cec = adap->priv;
253 	u32 state = cec_read(cec, TEGRA_CEC_HW_CONTROL);
254 
255 	if (logical_addr == CEC_LOG_ADDR_INVALID)
256 		state &= ~TEGRA_CEC_HWCTRL_RX_LADDR_MASK;
257 	else
258 		state |= TEGRA_CEC_HWCTRL_RX_LADDR((1 << logical_addr));
259 
260 	cec_write(cec, TEGRA_CEC_HW_CONTROL, state);
261 	return 0;
262 }
263 
264 static int tegra_cec_adap_monitor_all_enable(struct cec_adapter *adap,
265 					     bool enable)
266 {
267 	struct tegra_cec *cec = adap->priv;
268 	u32 reg = cec_read(cec, TEGRA_CEC_HW_CONTROL);
269 
270 	if (enable)
271 		reg |= TEGRA_CEC_HWCTRL_RX_SNOOP;
272 	else
273 		reg &= ~TEGRA_CEC_HWCTRL_RX_SNOOP;
274 	cec_write(cec, TEGRA_CEC_HW_CONTROL, reg);
275 	return 0;
276 }
277 
278 static int tegra_cec_adap_transmit(struct cec_adapter *adap, u8 attempts,
279 				   u32 signal_free_time_ms, struct cec_msg *msg)
280 {
281 	bool retry_xfer = signal_free_time_ms == CEC_SIGNAL_FREE_TIME_RETRY;
282 	struct tegra_cec *cec = adap->priv;
283 	unsigned int i;
284 	u32 mode = 0;
285 	u32 mask;
286 
287 	if (cec_msg_is_broadcast(msg))
288 		mode = TEGRA_CEC_TX_REG_BCAST;
289 
290 	cec->tx_buf_cur = 0;
291 	cec->tx_buf_cnt = msg->len;
292 
293 	for (i = 0; i < msg->len; i++) {
294 		cec->tx_buf[i] = mode | msg->msg[i];
295 		if (i == 0)
296 			cec->tx_buf[i] |= TEGRA_CEC_TX_REG_START_BIT;
297 		if (i == msg->len - 1)
298 			cec->tx_buf[i] |= TEGRA_CEC_TX_REG_EOM;
299 		if (i == 0 && retry_xfer)
300 			cec->tx_buf[i] |= TEGRA_CEC_TX_REG_RETRY;
301 	}
302 
303 	mask = cec_read(cec, TEGRA_CEC_INT_MASK);
304 	cec_write(cec, TEGRA_CEC_INT_MASK,
305 		  mask | TEGRA_CEC_INT_MASK_TX_REGISTER_EMPTY);
306 
307 	return 0;
308 }
309 
310 static const struct cec_adap_ops tegra_cec_ops = {
311 	.adap_enable = tegra_cec_adap_enable,
312 	.adap_log_addr = tegra_cec_adap_log_addr,
313 	.adap_transmit = tegra_cec_adap_transmit,
314 	.adap_monitor_all_enable = tegra_cec_adap_monitor_all_enable,
315 };
316 
317 static int tegra_cec_probe(struct platform_device *pdev)
318 {
319 	struct device *hdmi_dev;
320 	struct tegra_cec *cec;
321 	struct resource *res;
322 	int ret = 0;
323 
324 	hdmi_dev = cec_notifier_parse_hdmi_phandle(&pdev->dev);
325 
326 	if (IS_ERR(hdmi_dev))
327 		return PTR_ERR(hdmi_dev);
328 
329 	cec = devm_kzalloc(&pdev->dev, sizeof(struct tegra_cec), GFP_KERNEL);
330 
331 	if (!cec)
332 		return -ENOMEM;
333 
334 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
335 
336 	if (!res) {
337 		dev_err(&pdev->dev,
338 			"Unable to allocate resources for device\n");
339 		return -EBUSY;
340 	}
341 
342 	if (!devm_request_mem_region(&pdev->dev, res->start, resource_size(res),
343 		pdev->name)) {
344 		dev_err(&pdev->dev,
345 			"Unable to request mem region for device\n");
346 		return -EBUSY;
347 	}
348 
349 	cec->tegra_cec_irq = platform_get_irq(pdev, 0);
350 
351 	if (cec->tegra_cec_irq < 0)
352 		return cec->tegra_cec_irq;
353 
354 	cec->cec_base = devm_ioremap(&pdev->dev, res->start,
355 					     resource_size(res));
356 
357 	if (!cec->cec_base) {
358 		dev_err(&pdev->dev, "Unable to grab IOs for device\n");
359 		return -EBUSY;
360 	}
361 
362 	cec->clk = devm_clk_get(&pdev->dev, "cec");
363 
364 	if (IS_ERR_OR_NULL(cec->clk)) {
365 		dev_err(&pdev->dev, "Can't get clock for CEC\n");
366 		return -ENOENT;
367 	}
368 
369 	ret = clk_prepare_enable(cec->clk);
370 	if (ret) {
371 		dev_err(&pdev->dev, "Unable to prepare clock for CEC\n");
372 		return ret;
373 	}
374 
375 	/* set context info. */
376 	cec->dev = &pdev->dev;
377 
378 	platform_set_drvdata(pdev, cec);
379 
380 	ret = devm_request_threaded_irq(&pdev->dev, cec->tegra_cec_irq,
381 		tegra_cec_irq_handler, tegra_cec_irq_thread_handler,
382 		0, "cec_irq", &pdev->dev);
383 
384 	if (ret) {
385 		dev_err(&pdev->dev,
386 			"Unable to request interrupt for device\n");
387 		goto err_clk;
388 	}
389 
390 	cec->adap = cec_allocate_adapter(&tegra_cec_ops, cec, TEGRA_CEC_NAME,
391 			CEC_CAP_DEFAULTS | CEC_CAP_MONITOR_ALL |
392 			CEC_CAP_CONNECTOR_INFO,
393 			CEC_MAX_LOG_ADDRS);
394 	if (IS_ERR(cec->adap)) {
395 		ret = -ENOMEM;
396 		dev_err(&pdev->dev, "Couldn't create cec adapter\n");
397 		goto err_clk;
398 	}
399 
400 	cec->notifier = cec_notifier_cec_adap_register(hdmi_dev, NULL,
401 						       cec->adap);
402 	if (!cec->notifier) {
403 		ret = -ENOMEM;
404 		goto err_adapter;
405 	}
406 
407 	ret = cec_register_adapter(cec->adap, &pdev->dev);
408 	if (ret) {
409 		dev_err(&pdev->dev, "Couldn't register device\n");
410 		goto err_notifier;
411 	}
412 
413 	return 0;
414 
415 err_notifier:
416 	cec_notifier_cec_adap_unregister(cec->notifier, cec->adap);
417 err_adapter:
418 	cec_delete_adapter(cec->adap);
419 err_clk:
420 	clk_disable_unprepare(cec->clk);
421 	return ret;
422 }
423 
424 static void tegra_cec_remove(struct platform_device *pdev)
425 {
426 	struct tegra_cec *cec = platform_get_drvdata(pdev);
427 
428 	clk_disable_unprepare(cec->clk);
429 
430 	cec_notifier_cec_adap_unregister(cec->notifier, cec->adap);
431 	cec_unregister_adapter(cec->adap);
432 }
433 
434 #ifdef CONFIG_PM
435 static int tegra_cec_suspend(struct platform_device *pdev, pm_message_t state)
436 {
437 	struct tegra_cec *cec = platform_get_drvdata(pdev);
438 
439 	clk_disable_unprepare(cec->clk);
440 
441 	dev_notice(&pdev->dev, "suspended\n");
442 	return 0;
443 }
444 
445 static int tegra_cec_resume(struct platform_device *pdev)
446 {
447 	struct tegra_cec *cec = platform_get_drvdata(pdev);
448 
449 	dev_notice(&pdev->dev, "Resuming\n");
450 
451 	return clk_prepare_enable(cec->clk);
452 }
453 #endif
454 
455 static const struct of_device_id tegra_cec_of_match[] = {
456 	{ .compatible = "nvidia,tegra114-cec", },
457 	{ .compatible = "nvidia,tegra124-cec", },
458 	{ .compatible = "nvidia,tegra210-cec", },
459 	{},
460 };
461 
462 static struct platform_driver tegra_cec_driver = {
463 	.driver = {
464 		.name = TEGRA_CEC_NAME,
465 		.of_match_table = tegra_cec_of_match,
466 	},
467 	.probe = tegra_cec_probe,
468 	.remove_new = tegra_cec_remove,
469 
470 #ifdef CONFIG_PM
471 	.suspend = tegra_cec_suspend,
472 	.resume = tegra_cec_resume,
473 #endif
474 };
475 
476 module_platform_driver(tegra_cec_driver);
477 
478 MODULE_DESCRIPTION("Tegra HDMI CEC driver");
479 MODULE_AUTHOR("NVIDIA CORPORATION");
480 MODULE_AUTHOR("Cisco Systems, Inc. and/or its affiliates");
481 MODULE_LICENSE("GPL v2");
482