1/*
2 * Driver for Amlogic Meson AO CEC Controller
3 *
4 * Copyright (C) 2015 Amlogic, Inc. All rights reserved
5 * Copyright (C) 2017 BayLibre, SAS
6 * Author: Neil Armstrong <narmstrong@baylibre.com>
7 *
8 * SPDX-License-Identifier: GPL-2.0+
9 */
10
11#include <linux/bitfield.h>
12#include <linux/clk.h>
13#include <linux/device.h>
14#include <linux/io.h>
15#include <linux/delay.h>
16#include <linux/kernel.h>
17#include <linux/module.h>
18#include <linux/of.h>
19#include <linux/of_platform.h>
20#include <linux/platform_device.h>
21#include <linux/types.h>
22#include <linux/interrupt.h>
23#include <linux/reset.h>
24#include <media/cec.h>
25#include <media/cec-notifier.h>
26
27/* CEC Registers */
28
29/*
30 * [2:1] cntl_clk
31 *  - 0 = Disable clk (Power-off mode)
32 *  - 1 = Enable gated clock (Normal mode)
33 *  - 2 = Enable free-run clk (Debug mode)
34 */
35#define CEC_GEN_CNTL_REG		0x00
36
37#define CEC_GEN_CNTL_RESET		BIT(0)
38#define CEC_GEN_CNTL_CLK_DISABLE	0
39#define CEC_GEN_CNTL_CLK_ENABLE		1
40#define CEC_GEN_CNTL_CLK_ENABLE_DBG	2
41#define CEC_GEN_CNTL_CLK_CTRL_MASK	GENMASK(2, 1)
42
43/*
44 * [7:0] cec_reg_addr
45 * [15:8] cec_reg_wrdata
46 * [16] cec_reg_wr
47 *  - 0 = Read
48 *  - 1 = Write
49 * [23] bus free
50 * [31:24] cec_reg_rddata
51 */
52#define CEC_RW_REG			0x04
53
54#define CEC_RW_ADDR			GENMASK(7, 0)
55#define CEC_RW_WR_DATA			GENMASK(15, 8)
56#define CEC_RW_WRITE_EN			BIT(16)
57#define CEC_RW_BUS_BUSY			BIT(23)
58#define CEC_RW_RD_DATA			GENMASK(31, 24)
59
60/*
61 * [1] tx intr
62 * [2] rx intr
63 */
64#define CEC_INTR_MASKN_REG		0x08
65#define CEC_INTR_CLR_REG		0x0c
66#define CEC_INTR_STAT_REG		0x10
67
68#define CEC_INTR_TX			BIT(1)
69#define CEC_INTR_RX			BIT(2)
70
71/* CEC Commands */
72
73#define CEC_TX_MSG_0_HEADER		0x00
74#define CEC_TX_MSG_1_OPCODE		0x01
75#define CEC_TX_MSG_2_OP1		0x02
76#define CEC_TX_MSG_3_OP2		0x03
77#define CEC_TX_MSG_4_OP3		0x04
78#define CEC_TX_MSG_5_OP4		0x05
79#define CEC_TX_MSG_6_OP5		0x06
80#define CEC_TX_MSG_7_OP6		0x07
81#define CEC_TX_MSG_8_OP7		0x08
82#define CEC_TX_MSG_9_OP8		0x09
83#define CEC_TX_MSG_A_OP9		0x0A
84#define CEC_TX_MSG_B_OP10		0x0B
85#define CEC_TX_MSG_C_OP11		0x0C
86#define CEC_TX_MSG_D_OP12		0x0D
87#define CEC_TX_MSG_E_OP13		0x0E
88#define CEC_TX_MSG_F_OP14		0x0F
89#define CEC_TX_MSG_LENGTH		0x10
90#define CEC_TX_MSG_CMD			0x11
91#define CEC_TX_WRITE_BUF		0x12
92#define CEC_TX_CLEAR_BUF		0x13
93#define CEC_RX_MSG_CMD			0x14
94#define CEC_RX_CLEAR_BUF		0x15
95#define CEC_LOGICAL_ADDR0		0x16
96#define CEC_LOGICAL_ADDR1		0x17
97#define CEC_LOGICAL_ADDR2		0x18
98#define CEC_LOGICAL_ADDR3		0x19
99#define CEC_LOGICAL_ADDR4		0x1A
100#define CEC_CLOCK_DIV_H			0x1B
101#define CEC_CLOCK_DIV_L			0x1C
102#define CEC_QUIESCENT_25MS_BIT7_0	0x20
103#define CEC_QUIESCENT_25MS_BIT11_8	0x21
104#define CEC_STARTBITMINL2H_3MS5_BIT7_0	0x22
105#define CEC_STARTBITMINL2H_3MS5_BIT8	0x23
106#define CEC_STARTBITMAXL2H_3MS9_BIT7_0	0x24
107#define CEC_STARTBITMAXL2H_3MS9_BIT8	0x25
108#define CEC_STARTBITMINH_0MS6_BIT7_0	0x26
109#define CEC_STARTBITMINH_0MS6_BIT8	0x27
110#define CEC_STARTBITMAXH_1MS0_BIT7_0	0x28
111#define CEC_STARTBITMAXH_1MS0_BIT8	0x29
112#define CEC_STARTBITMINTOT_4MS3_BIT7_0	0x2A
113#define CEC_STARTBITMINTOT_4MS3_BIT9_8	0x2B
114#define CEC_STARTBITMAXTOT_4MS7_BIT7_0	0x2C
115#define CEC_STARTBITMAXTOT_4MS7_BIT9_8	0x2D
116#define CEC_LOGIC1MINL2H_0MS4_BIT7_0	0x2E
117#define CEC_LOGIC1MINL2H_0MS4_BIT8	0x2F
118#define CEC_LOGIC1MAXL2H_0MS8_BIT7_0	0x30
119#define CEC_LOGIC1MAXL2H_0MS8_BIT8	0x31
120#define CEC_LOGIC0MINL2H_1MS3_BIT7_0	0x32
121#define CEC_LOGIC0MINL2H_1MS3_BIT8	0x33
122#define CEC_LOGIC0MAXL2H_1MS7_BIT7_0	0x34
123#define CEC_LOGIC0MAXL2H_1MS7_BIT8	0x35
124#define CEC_LOGICMINTOTAL_2MS05_BIT7_0	0x36
125#define CEC_LOGICMINTOTAL_2MS05_BIT9_8	0x37
126#define CEC_LOGICMAXHIGH_2MS8_BIT7_0	0x38
127#define CEC_LOGICMAXHIGH_2MS8_BIT8	0x39
128#define CEC_LOGICERRLOW_3MS4_BIT7_0	0x3A
129#define CEC_LOGICERRLOW_3MS4_BIT8	0x3B
130#define CEC_NOMSMPPOINT_1MS05		0x3C
131#define CEC_DELCNTR_LOGICERR		0x3E
132#define CEC_TXTIME_17MS_BIT7_0		0x40
133#define CEC_TXTIME_17MS_BIT10_8		0x41
134#define CEC_TXTIME_2BIT_BIT7_0		0x42
135#define CEC_TXTIME_2BIT_BIT10_8		0x43
136#define CEC_TXTIME_4BIT_BIT7_0		0x44
137#define CEC_TXTIME_4BIT_BIT10_8		0x45
138#define CEC_STARTBITNOML2H_3MS7_BIT7_0	0x46
139#define CEC_STARTBITNOML2H_3MS7_BIT8	0x47
140#define CEC_STARTBITNOMH_0MS8_BIT7_0	0x48
141#define CEC_STARTBITNOMH_0MS8_BIT8	0x49
142#define CEC_LOGIC1NOML2H_0MS6_BIT7_0	0x4A
143#define CEC_LOGIC1NOML2H_0MS6_BIT8	0x4B
144#define CEC_LOGIC0NOML2H_1MS5_BIT7_0	0x4C
145#define CEC_LOGIC0NOML2H_1MS5_BIT8	0x4D
146#define CEC_LOGIC1NOMH_1MS8_BIT7_0	0x4E
147#define CEC_LOGIC1NOMH_1MS8_BIT8	0x4F
148#define CEC_LOGIC0NOMH_0MS9_BIT7_0	0x50
149#define CEC_LOGIC0NOMH_0MS9_BIT8	0x51
150#define CEC_LOGICERRLOW_3MS6_BIT7_0	0x52
151#define CEC_LOGICERRLOW_3MS6_BIT8	0x53
152#define CEC_CHKCONTENTION_0MS1		0x54
153#define CEC_PREPARENXTBIT_0MS05_BIT7_0	0x56
154#define CEC_PREPARENXTBIT_0MS05_BIT8	0x57
155#define CEC_NOMSMPACKPOINT_0MS45	0x58
156#define CEC_ACK0NOML2H_1MS5_BIT7_0	0x5A
157#define CEC_ACK0NOML2H_1MS5_BIT8	0x5B
158#define CEC_BUGFIX_DISABLE_0		0x60
159#define CEC_BUGFIX_DISABLE_1		0x61
160#define CEC_RX_MSG_0_HEADER		0x80
161#define CEC_RX_MSG_1_OPCODE		0x81
162#define CEC_RX_MSG_2_OP1		0x82
163#define CEC_RX_MSG_3_OP2		0x83
164#define CEC_RX_MSG_4_OP3		0x84
165#define CEC_RX_MSG_5_OP4		0x85
166#define CEC_RX_MSG_6_OP5		0x86
167#define CEC_RX_MSG_7_OP6		0x87
168#define CEC_RX_MSG_8_OP7		0x88
169#define CEC_RX_MSG_9_OP8		0x89
170#define CEC_RX_MSG_A_OP9		0x8A
171#define CEC_RX_MSG_B_OP10		0x8B
172#define CEC_RX_MSG_C_OP11		0x8C
173#define CEC_RX_MSG_D_OP12		0x8D
174#define CEC_RX_MSG_E_OP13		0x8E
175#define CEC_RX_MSG_F_OP14		0x8F
176#define CEC_RX_MSG_LENGTH		0x90
177#define CEC_RX_MSG_STATUS		0x91
178#define CEC_RX_NUM_MSG			0x92
179#define CEC_TX_MSG_STATUS		0x93
180#define CEC_TX_NUM_MSG			0x94
181
182
183/* CEC_TX_MSG_CMD definition */
184#define TX_NO_OP	0  /* No transaction */
185#define TX_REQ_CURRENT	1  /* Transmit earliest message in buffer */
186#define TX_ABORT	2  /* Abort transmitting earliest message */
187#define TX_REQ_NEXT	3  /* Overwrite earliest msg, transmit next */
188
189/* tx_msg_status definition */
190#define TX_IDLE		0  /* No transaction */
191#define TX_BUSY		1  /* Transmitter is busy */
192#define TX_DONE		2  /* Message successfully transmitted */
193#define TX_ERROR	3  /* Message transmitted with error */
194
195/* rx_msg_cmd */
196#define RX_NO_OP	0  /* No transaction */
197#define RX_ACK_CURRENT	1  /* Read earliest message in buffer */
198#define RX_DISABLE	2  /* Disable receiving latest message */
199#define RX_ACK_NEXT	3  /* Clear earliest msg, read next */
200
201/* rx_msg_status */
202#define RX_IDLE		0  /* No transaction */
203#define RX_BUSY		1  /* Receiver is busy */
204#define RX_DONE		2  /* Message has been received successfully */
205#define RX_ERROR	3  /* Message has been received with error */
206
207/* RX_CLEAR_BUF options */
208#define CLEAR_START	1
209#define CLEAR_STOP	0
210
211/* CEC_LOGICAL_ADDRx options */
212#define LOGICAL_ADDR_MASK	0xf
213#define LOGICAL_ADDR_VALID	BIT(4)
214#define LOGICAL_ADDR_DISABLE	0
215
216#define CEC_CLK_RATE		32768
217
218struct meson_ao_cec_device {
219	struct platform_device		*pdev;
220	void __iomem			*base;
221	struct clk			*core;
222	spinlock_t			cec_reg_lock;
223	struct cec_notifier		*notify;
224	struct cec_adapter		*adap;
225	struct cec_msg			rx_msg;
226};
227
228#define writel_bits_relaxed(mask, val, addr) \
229	writel_relaxed((readl_relaxed(addr) & ~(mask)) | (val), addr)
230
231static inline int meson_ao_cec_wait_busy(struct meson_ao_cec_device *ao_cec)
232{
233	ktime_t timeout = ktime_add_us(ktime_get(), 5000);
234
235	while (readl_relaxed(ao_cec->base + CEC_RW_REG) & CEC_RW_BUS_BUSY) {
236		if (ktime_compare(ktime_get(), timeout) > 0)
237			return -ETIMEDOUT;
238	}
239
240	return 0;
241}
242
243static void meson_ao_cec_read(struct meson_ao_cec_device *ao_cec,
244			     unsigned long address, u8 *data,
245			     int *res)
246{
247	unsigned long flags;
248	u32 reg = FIELD_PREP(CEC_RW_ADDR, address);
249	int ret = 0;
250
251	if (res && *res)
252		return;
253
254	spin_lock_irqsave(&ao_cec->cec_reg_lock, flags);
255
256	ret = meson_ao_cec_wait_busy(ao_cec);
257	if (ret)
258		goto read_out;
259
260	writel_relaxed(reg, ao_cec->base + CEC_RW_REG);
261
262	ret = meson_ao_cec_wait_busy(ao_cec);
263	if (ret)
264		goto read_out;
265
266	*data = FIELD_GET(CEC_RW_RD_DATA,
267			  readl_relaxed(ao_cec->base + CEC_RW_REG));
268
269read_out:
270	spin_unlock_irqrestore(&ao_cec->cec_reg_lock, flags);
271
272	if (res)
273		*res = ret;
274}
275
276static void meson_ao_cec_write(struct meson_ao_cec_device *ao_cec,
277			       unsigned long address, u8 data,
278			       int *res)
279{
280	unsigned long flags;
281	u32 reg = FIELD_PREP(CEC_RW_ADDR, address) |
282		  FIELD_PREP(CEC_RW_WR_DATA, data) |
283		  CEC_RW_WRITE_EN;
284	int ret = 0;
285
286	if (res && *res)
287		return;
288
289	spin_lock_irqsave(&ao_cec->cec_reg_lock, flags);
290
291	ret = meson_ao_cec_wait_busy(ao_cec);
292	if (ret)
293		goto write_out;
294
295	writel_relaxed(reg, ao_cec->base + CEC_RW_REG);
296
297write_out:
298	spin_unlock_irqrestore(&ao_cec->cec_reg_lock, flags);
299
300	if (res)
301		*res = ret;
302}
303
304static inline void meson_ao_cec_irq_setup(struct meson_ao_cec_device *ao_cec,
305				      bool enable)
306{
307	u32 cfg = CEC_INTR_TX | CEC_INTR_RX;
308
309	writel_bits_relaxed(cfg, enable ? cfg : 0,
310			    ao_cec->base + CEC_INTR_MASKN_REG);
311}
312
313static inline int meson_ao_cec_clear(struct meson_ao_cec_device *ao_cec)
314{
315	int ret = 0;
316
317	meson_ao_cec_write(ao_cec, CEC_RX_MSG_CMD, RX_DISABLE, &ret);
318	meson_ao_cec_write(ao_cec, CEC_TX_MSG_CMD, TX_ABORT, &ret);
319	meson_ao_cec_write(ao_cec, CEC_RX_CLEAR_BUF, 1, &ret);
320	meson_ao_cec_write(ao_cec, CEC_TX_CLEAR_BUF, 1, &ret);
321	if (ret)
322		return ret;
323
324	udelay(100);
325
326	meson_ao_cec_write(ao_cec, CEC_RX_CLEAR_BUF, 0, &ret);
327	meson_ao_cec_write(ao_cec, CEC_TX_CLEAR_BUF, 0, &ret);
328	if (ret)
329		return ret;
330
331	udelay(100);
332
333	meson_ao_cec_write(ao_cec, CEC_RX_MSG_CMD, RX_NO_OP, &ret);
334	meson_ao_cec_write(ao_cec, CEC_TX_MSG_CMD, TX_NO_OP, &ret);
335
336	return ret;
337}
338
339static int meson_ao_cec_arbit_bit_time_set(struct meson_ao_cec_device *ao_cec,
340					   unsigned int bit_set,
341					   unsigned int time_set)
342{
343	int ret = 0;
344
345	switch (bit_set) {
346	case CEC_SIGNAL_FREE_TIME_RETRY:
347		meson_ao_cec_write(ao_cec, CEC_TXTIME_4BIT_BIT7_0,
348				   time_set & 0xff, &ret);
349		meson_ao_cec_write(ao_cec, CEC_TXTIME_4BIT_BIT10_8,
350				   (time_set >> 8) & 0x7, &ret);
351		break;
352
353	case CEC_SIGNAL_FREE_TIME_NEW_INITIATOR:
354		meson_ao_cec_write(ao_cec, CEC_TXTIME_2BIT_BIT7_0,
355				   time_set & 0xff, &ret);
356		meson_ao_cec_write(ao_cec, CEC_TXTIME_2BIT_BIT10_8,
357				   (time_set >> 8) & 0x7, &ret);
358		break;
359
360	case CEC_SIGNAL_FREE_TIME_NEXT_XFER:
361		meson_ao_cec_write(ao_cec, CEC_TXTIME_17MS_BIT7_0,
362				   time_set & 0xff, &ret);
363		meson_ao_cec_write(ao_cec, CEC_TXTIME_17MS_BIT10_8,
364				   (time_set >> 8) & 0x7, &ret);
365		break;
366	}
367
368	return ret;
369}
370
371static irqreturn_t meson_ao_cec_irq(int irq, void *data)
372{
373	struct meson_ao_cec_device *ao_cec = data;
374	u32 stat = readl_relaxed(ao_cec->base + CEC_INTR_STAT_REG);
375
376	if (stat)
377		return IRQ_WAKE_THREAD;
378
379	return IRQ_NONE;
380}
381
382static void meson_ao_cec_irq_tx(struct meson_ao_cec_device *ao_cec)
383{
384	unsigned long tx_status = 0;
385	u8 stat;
386	int ret = 0;
387
388	meson_ao_cec_read(ao_cec, CEC_TX_MSG_STATUS, &stat, &ret);
389	if (ret)
390		goto tx_reg_err;
391
392	switch (stat) {
393	case TX_DONE:
394		tx_status = CEC_TX_STATUS_OK;
395		break;
396
397	case TX_BUSY:
398		tx_status = CEC_TX_STATUS_ARB_LOST;
399		break;
400
401	case TX_IDLE:
402		tx_status = CEC_TX_STATUS_LOW_DRIVE;
403		break;
404
405	case TX_ERROR:
406	default:
407		tx_status = CEC_TX_STATUS_NACK;
408		break;
409	}
410
411	/* Clear Interruption */
412	writel_relaxed(CEC_INTR_TX, ao_cec->base + CEC_INTR_CLR_REG);
413
414	/* Stop TX */
415	meson_ao_cec_write(ao_cec, CEC_TX_MSG_CMD, TX_NO_OP, &ret);
416	if (ret)
417		goto tx_reg_err;
418
419	cec_transmit_attempt_done(ao_cec->adap, tx_status);
420	return;
421
422tx_reg_err:
423	cec_transmit_attempt_done(ao_cec->adap, CEC_TX_STATUS_ERROR);
424}
425
426static void meson_ao_cec_irq_rx(struct meson_ao_cec_device *ao_cec)
427{
428	int i, ret = 0;
429	u8 reg;
430
431	meson_ao_cec_read(ao_cec, CEC_RX_MSG_STATUS, &reg, &ret);
432	if (reg != RX_DONE)
433		goto rx_out;
434
435	meson_ao_cec_read(ao_cec, CEC_RX_NUM_MSG, &reg, &ret);
436	if (reg != 1)
437		goto rx_out;
438
439	meson_ao_cec_read(ao_cec, CEC_RX_MSG_LENGTH, &reg, &ret);
440
441	ao_cec->rx_msg.len = reg + 1;
442	if (ao_cec->rx_msg.len > CEC_MAX_MSG_SIZE)
443		ao_cec->rx_msg.len = CEC_MAX_MSG_SIZE;
444
445	for (i = 0; i < ao_cec->rx_msg.len; i++) {
446		u8 byte;
447
448		meson_ao_cec_read(ao_cec, CEC_RX_MSG_0_HEADER + i, &byte, &ret);
449
450		ao_cec->rx_msg.msg[i] = byte;
451	}
452
453	if (ret)
454		goto rx_out;
455
456	cec_received_msg(ao_cec->adap, &ao_cec->rx_msg);
457
458rx_out:
459	/* Clear Interruption */
460	writel_relaxed(CEC_INTR_RX, ao_cec->base + CEC_INTR_CLR_REG);
461
462	/* Ack RX message */
463	meson_ao_cec_write(ao_cec, CEC_RX_MSG_CMD, RX_ACK_CURRENT, &ret);
464	meson_ao_cec_write(ao_cec, CEC_RX_MSG_CMD, RX_NO_OP, &ret);
465
466	/* Clear RX buffer */
467	meson_ao_cec_write(ao_cec, CEC_RX_CLEAR_BUF, CLEAR_START, &ret);
468	meson_ao_cec_write(ao_cec, CEC_RX_CLEAR_BUF, CLEAR_STOP, &ret);
469}
470
471static irqreturn_t meson_ao_cec_irq_thread(int irq, void *data)
472{
473	struct meson_ao_cec_device *ao_cec = data;
474	u32 stat = readl_relaxed(ao_cec->base + CEC_INTR_STAT_REG);
475
476	if (stat & CEC_INTR_TX)
477		meson_ao_cec_irq_tx(ao_cec);
478
479	meson_ao_cec_irq_rx(ao_cec);
480
481	return IRQ_HANDLED;
482}
483
484static int meson_ao_cec_set_log_addr(struct cec_adapter *adap, u8 logical_addr)
485{
486	struct meson_ao_cec_device *ao_cec = adap->priv;
487	int ret = 0;
488
489	meson_ao_cec_write(ao_cec, CEC_LOGICAL_ADDR0,
490			   LOGICAL_ADDR_DISABLE, &ret);
491	if (ret)
492		return ret;
493
494	ret = meson_ao_cec_clear(ao_cec);
495	if (ret)
496		return ret;
497
498	if (logical_addr == CEC_LOG_ADDR_INVALID)
499		return 0;
500
501	meson_ao_cec_write(ao_cec, CEC_LOGICAL_ADDR0,
502			   logical_addr & LOGICAL_ADDR_MASK, &ret);
503	if (ret)
504		return ret;
505
506	udelay(100);
507
508	meson_ao_cec_write(ao_cec, CEC_LOGICAL_ADDR0,
509			   (logical_addr & LOGICAL_ADDR_MASK) |
510			   LOGICAL_ADDR_VALID, &ret);
511
512	return ret;
513}
514
515static int meson_ao_cec_transmit(struct cec_adapter *adap, u8 attempts,
516				 u32 signal_free_time, struct cec_msg *msg)
517{
518	struct meson_ao_cec_device *ao_cec = adap->priv;
519	int i, ret = 0;
520	u8 reg;
521
522	meson_ao_cec_read(ao_cec, CEC_TX_MSG_STATUS, &reg, &ret);
523	if (ret)
524		return ret;
525
526	if (reg == TX_BUSY) {
527		dev_dbg(&ao_cec->pdev->dev, "%s: busy TX: aborting\n",
528			__func__);
529		meson_ao_cec_write(ao_cec, CEC_TX_MSG_CMD, TX_ABORT, &ret);
530	}
531
532	for (i = 0; i < msg->len; i++) {
533		meson_ao_cec_write(ao_cec, CEC_TX_MSG_0_HEADER + i,
534				   msg->msg[i], &ret);
535	}
536
537	meson_ao_cec_write(ao_cec, CEC_TX_MSG_LENGTH, msg->len - 1, &ret);
538	meson_ao_cec_write(ao_cec, CEC_TX_MSG_CMD, TX_REQ_CURRENT, &ret);
539
540	return ret;
541}
542
543static int meson_ao_cec_adap_enable(struct cec_adapter *adap, bool enable)
544{
545	struct meson_ao_cec_device *ao_cec = adap->priv;
546	int ret;
547
548	meson_ao_cec_irq_setup(ao_cec, false);
549
550	writel_bits_relaxed(CEC_GEN_CNTL_RESET, CEC_GEN_CNTL_RESET,
551			    ao_cec->base + CEC_GEN_CNTL_REG);
552
553	if (!enable)
554		return 0;
555
556	/* Enable gated clock (Normal mode). */
557	writel_bits_relaxed(CEC_GEN_CNTL_CLK_CTRL_MASK,
558			    FIELD_PREP(CEC_GEN_CNTL_CLK_CTRL_MASK,
559				       CEC_GEN_CNTL_CLK_ENABLE),
560			    ao_cec->base + CEC_GEN_CNTL_REG);
561
562	udelay(100);
563
564	/* Release Reset */
565	writel_bits_relaxed(CEC_GEN_CNTL_RESET, 0,
566			    ao_cec->base + CEC_GEN_CNTL_REG);
567
568	/* Clear buffers */
569	ret = meson_ao_cec_clear(ao_cec);
570	if (ret)
571		return ret;
572
573	/* CEC arbitration 3/5/7 bit time set. */
574	ret = meson_ao_cec_arbit_bit_time_set(ao_cec,
575					CEC_SIGNAL_FREE_TIME_RETRY,
576					0x118);
577	if (ret)
578		return ret;
579	ret = meson_ao_cec_arbit_bit_time_set(ao_cec,
580					CEC_SIGNAL_FREE_TIME_NEW_INITIATOR,
581					0x000);
582	if (ret)
583		return ret;
584	ret = meson_ao_cec_arbit_bit_time_set(ao_cec,
585					CEC_SIGNAL_FREE_TIME_NEXT_XFER,
586					0x2aa);
587	if (ret)
588		return ret;
589
590	meson_ao_cec_irq_setup(ao_cec, true);
591
592	return 0;
593}
594
595static const struct cec_adap_ops meson_ao_cec_ops = {
596	.adap_enable = meson_ao_cec_adap_enable,
597	.adap_log_addr = meson_ao_cec_set_log_addr,
598	.adap_transmit = meson_ao_cec_transmit,
599};
600
601static int meson_ao_cec_probe(struct platform_device *pdev)
602{
603	struct meson_ao_cec_device *ao_cec;
604	struct device *hdmi_dev;
605	int ret, irq;
606
607	hdmi_dev = cec_notifier_parse_hdmi_phandle(&pdev->dev);
608
609	if (IS_ERR(hdmi_dev))
610		return PTR_ERR(hdmi_dev);
611
612	ao_cec = devm_kzalloc(&pdev->dev, sizeof(*ao_cec), GFP_KERNEL);
613	if (!ao_cec)
614		return -ENOMEM;
615
616	spin_lock_init(&ao_cec->cec_reg_lock);
617
618	ao_cec->adap = cec_allocate_adapter(&meson_ao_cec_ops, ao_cec,
619					    "meson_ao_cec",
620					    CEC_CAP_DEFAULTS |
621					    CEC_CAP_CONNECTOR_INFO,
622					    1); /* Use 1 for now */
623	if (IS_ERR(ao_cec->adap))
624		return PTR_ERR(ao_cec->adap);
625
626	ao_cec->adap->owner = THIS_MODULE;
627
628	ao_cec->base = devm_platform_ioremap_resource(pdev, 0);
629	if (IS_ERR(ao_cec->base)) {
630		ret = PTR_ERR(ao_cec->base);
631		goto out_probe_adapter;
632	}
633
634	irq = platform_get_irq(pdev, 0);
635	ret = devm_request_threaded_irq(&pdev->dev, irq,
636					meson_ao_cec_irq,
637					meson_ao_cec_irq_thread,
638					0, NULL, ao_cec);
639	if (ret) {
640		dev_err(&pdev->dev, "irq request failed\n");
641		goto out_probe_adapter;
642	}
643
644	ao_cec->core = devm_clk_get(&pdev->dev, "core");
645	if (IS_ERR(ao_cec->core)) {
646		dev_err(&pdev->dev, "core clock request failed\n");
647		ret = PTR_ERR(ao_cec->core);
648		goto out_probe_adapter;
649	}
650
651	ret = clk_prepare_enable(ao_cec->core);
652	if (ret) {
653		dev_err(&pdev->dev, "core clock enable failed\n");
654		goto out_probe_adapter;
655	}
656
657	ret = clk_set_rate(ao_cec->core, CEC_CLK_RATE);
658	if (ret) {
659		dev_err(&pdev->dev, "core clock set rate failed\n");
660		goto out_probe_clk;
661	}
662
663	device_reset_optional(&pdev->dev);
664
665	ao_cec->pdev = pdev;
666	platform_set_drvdata(pdev, ao_cec);
667
668	ao_cec->notify = cec_notifier_cec_adap_register(hdmi_dev, NULL,
669							ao_cec->adap);
670	if (!ao_cec->notify) {
671		ret = -ENOMEM;
672		goto out_probe_clk;
673	}
674
675	ret = cec_register_adapter(ao_cec->adap, &pdev->dev);
676	if (ret < 0)
677		goto out_probe_notify;
678
679	/* Setup Hardware */
680	writel_relaxed(CEC_GEN_CNTL_RESET,
681		       ao_cec->base + CEC_GEN_CNTL_REG);
682
683	return 0;
684
685out_probe_notify:
686	cec_notifier_cec_adap_unregister(ao_cec->notify, ao_cec->adap);
687
688out_probe_clk:
689	clk_disable_unprepare(ao_cec->core);
690
691out_probe_adapter:
692	cec_delete_adapter(ao_cec->adap);
693
694	dev_err(&pdev->dev, "CEC controller registration failed\n");
695
696	return ret;
697}
698
699static void meson_ao_cec_remove(struct platform_device *pdev)
700{
701	struct meson_ao_cec_device *ao_cec = platform_get_drvdata(pdev);
702
703	clk_disable_unprepare(ao_cec->core);
704
705	cec_notifier_cec_adap_unregister(ao_cec->notify, ao_cec->adap);
706	cec_unregister_adapter(ao_cec->adap);
707}
708
709static const struct of_device_id meson_ao_cec_of_match[] = {
710	{ .compatible = "amlogic,meson-gx-ao-cec", },
711	{ /* sentinel */ }
712};
713MODULE_DEVICE_TABLE(of, meson_ao_cec_of_match);
714
715static struct platform_driver meson_ao_cec_driver = {
716	.probe   = meson_ao_cec_probe,
717	.remove_new = meson_ao_cec_remove,
718	.driver  = {
719		.name = "meson-ao-cec",
720		.of_match_table = meson_ao_cec_of_match,
721	},
722};
723
724module_platform_driver(meson_ao_cec_driver);
725
726MODULE_DESCRIPTION("Meson AO CEC Controller driver");
727MODULE_AUTHOR("Neil Armstrong <narmstrong@baylibre.com>");
728MODULE_LICENSE("GPL");
729