1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Driver for Amlogic Meson AO CEC G12A Controller
4  *
5  * Copyright (C) 2017 Amlogic, Inc. All rights reserved
6  * Copyright (C) 2019 BayLibre, SAS
7  * Author: Neil Armstrong <narmstrong@baylibre.com>
8  */
9 
10 #include <linux/bitfield.h>
11 #include <linux/clk.h>
12 #include <linux/device.h>
13 #include <linux/io.h>
14 #include <linux/delay.h>
15 #include <linux/kernel.h>
16 #include <linux/module.h>
17 #include <linux/of.h>
18 #include <linux/of_platform.h>
19 #include <linux/platform_device.h>
20 #include <linux/types.h>
21 #include <linux/interrupt.h>
22 #include <linux/reset.h>
23 #include <linux/slab.h>
24 #include <linux/regmap.h>
25 #include <media/cec.h>
26 #include <media/cec-notifier.h>
27 #include <linux/clk-provider.h>
28 
29 /* CEC Registers */
30 
31 #define CECB_CLK_CNTL_REG0		0x00
32 
33 #define CECB_CLK_CNTL_N1		GENMASK(11, 0)
34 #define CECB_CLK_CNTL_N2		GENMASK(23, 12)
35 #define CECB_CLK_CNTL_DUAL_EN		BIT(28)
36 #define CECB_CLK_CNTL_OUTPUT_EN		BIT(30)
37 #define CECB_CLK_CNTL_INPUT_EN		BIT(31)
38 
39 #define CECB_CLK_CNTL_REG1		0x04
40 
41 #define CECB_CLK_CNTL_M1		GENMASK(11, 0)
42 #define CECB_CLK_CNTL_M2		GENMASK(23, 12)
43 #define CECB_CLK_CNTL_BYPASS_EN		BIT(24)
44 
45 /*
46  * [14:12] Filter_del. For glitch-filtering CEC line, ignore signal
47  *       change pulse width < filter_del * T(filter_tick) * 3.
48  * [9:8] Filter_tick_sel: Select which periodical pulse for
49  *       glitch-filtering CEC line signal.
50  *  - 0=Use T(xtal)*3 = 125ns;
51  *  - 1=Use once-per-1us pulse;
52  *  - 2=Use once-per-10us pulse;
53  *  - 3=Use once-per-100us pulse.
54  * [3]   Sysclk_en. 0=Disable system clock; 1=Enable system clock.
55  * [2:1] cntl_clk
56  *  - 0 = Disable clk (Power-off mode)
57  *  - 1 = Enable gated clock (Normal mode)
58  *  - 2 = Enable free-run clk (Debug mode)
59  * [0] SW_RESET 1=Apply reset; 0=No reset.
60  */
61 #define CECB_GEN_CNTL_REG		0x08
62 
63 #define CECB_GEN_CNTL_RESET		BIT(0)
64 #define CECB_GEN_CNTL_CLK_DISABLE	0
65 #define CECB_GEN_CNTL_CLK_ENABLE	1
66 #define CECB_GEN_CNTL_CLK_ENABLE_DBG	2
67 #define CECB_GEN_CNTL_CLK_CTRL_MASK	GENMASK(2, 1)
68 #define CECB_GEN_CNTL_SYS_CLK_EN	BIT(3)
69 #define CECB_GEN_CNTL_FILTER_TICK_125NS	0
70 #define CECB_GEN_CNTL_FILTER_TICK_1US	1
71 #define CECB_GEN_CNTL_FILTER_TICK_10US	2
72 #define CECB_GEN_CNTL_FILTER_TICK_100US	3
73 #define CECB_GEN_CNTL_FILTER_TICK_SEL	GENMASK(9, 8)
74 #define CECB_GEN_CNTL_FILTER_DEL	GENMASK(14, 12)
75 
76 /*
77  * [7:0] cec_reg_addr
78  * [15:8] cec_reg_wrdata
79  * [16] cec_reg_wr
80  *  - 0 = Read
81  *  - 1 = Write
82  * [31:24] cec_reg_rddata
83  */
84 #define CECB_RW_REG			0x0c
85 
86 #define CECB_RW_ADDR			GENMASK(7, 0)
87 #define CECB_RW_WR_DATA			GENMASK(15, 8)
88 #define CECB_RW_WRITE_EN		BIT(16)
89 #define CECB_RW_BUS_BUSY		BIT(23)
90 #define CECB_RW_RD_DATA			GENMASK(31, 24)
91 
92 /*
93  * [0] DONE Interrupt
94  * [1] End Of Message Interrupt
95  * [2] Not Acknowlegde Interrupt
96  * [3] Arbitration Loss Interrupt
97  * [4] Initiator Error Interrupt
98  * [5] Follower Error Interrupt
99  * [6] Wake-Up Interrupt
100  */
101 #define CECB_INTR_MASKN_REG		0x10
102 #define CECB_INTR_CLR_REG		0x14
103 #define CECB_INTR_STAT_REG		0x18
104 
105 #define CECB_INTR_DONE			BIT(0)
106 #define CECB_INTR_EOM			BIT(1)
107 #define CECB_INTR_NACK			BIT(2)
108 #define CECB_INTR_ARB_LOSS		BIT(3)
109 #define CECB_INTR_INITIATOR_ERR		BIT(4)
110 #define CECB_INTR_FOLLOWER_ERR		BIT(5)
111 #define CECB_INTR_WAKE_UP		BIT(6)
112 
113 /* CEC Commands */
114 
115 #define CECB_CTRL		0x00
116 
117 #define CECB_CTRL_SEND		BIT(0)
118 #define CECB_CTRL_TYPE		GENMASK(2, 1)
119 #define CECB_CTRL_TYPE_RETRY	0
120 #define CECB_CTRL_TYPE_NEW	1
121 #define CECB_CTRL_TYPE_NEXT	2
122 
123 #define CECB_CTRL2		0x01
124 
125 #define CECB_CTRL2_RISE_DEL_MAX	GENMASK(4, 0)
126 
127 #define CECB_INTR_MASK		0x02
128 #define CECB_LADD_LOW		0x05
129 #define CECB_LADD_HIGH		0x06
130 #define CECB_TX_CNT		0x07
131 #define CECB_RX_CNT		0x08
132 #define CECB_STAT0		0x09
133 #define CECB_TX_DATA00		0x10
134 #define CECB_TX_DATA01		0x11
135 #define CECB_TX_DATA02		0x12
136 #define CECB_TX_DATA03		0x13
137 #define CECB_TX_DATA04		0x14
138 #define CECB_TX_DATA05		0x15
139 #define CECB_TX_DATA06		0x16
140 #define CECB_TX_DATA07		0x17
141 #define CECB_TX_DATA08		0x18
142 #define CECB_TX_DATA09		0x19
143 #define CECB_TX_DATA10		0x1A
144 #define CECB_TX_DATA11		0x1B
145 #define CECB_TX_DATA12		0x1C
146 #define CECB_TX_DATA13		0x1D
147 #define CECB_TX_DATA14		0x1E
148 #define CECB_TX_DATA15		0x1F
149 #define CECB_RX_DATA00		0x20
150 #define CECB_RX_DATA01		0x21
151 #define CECB_RX_DATA02		0x22
152 #define CECB_RX_DATA03		0x23
153 #define CECB_RX_DATA04		0x24
154 #define CECB_RX_DATA05		0x25
155 #define CECB_RX_DATA06		0x26
156 #define CECB_RX_DATA07		0x27
157 #define CECB_RX_DATA08		0x28
158 #define CECB_RX_DATA09		0x29
159 #define CECB_RX_DATA10		0x2A
160 #define CECB_RX_DATA11		0x2B
161 #define CECB_RX_DATA12		0x2C
162 #define CECB_RX_DATA13		0x2D
163 #define CECB_RX_DATA14		0x2E
164 #define CECB_RX_DATA15		0x2F
165 #define CECB_LOCK_BUF		0x30
166 
167 #define CECB_LOCK_BUF_EN	BIT(0)
168 
169 #define CECB_WAKEUPCTRL		0x31
170 
171 struct meson_ao_cec_g12a_data {
172 	/* Setup the internal CECB_CTRL2 register */
173 	bool				ctrl2_setup;
174 };
175 
176 struct meson_ao_cec_g12a_device {
177 	struct platform_device		*pdev;
178 	struct regmap			*regmap;
179 	struct regmap			*regmap_cec;
180 	spinlock_t			cec_reg_lock;
181 	struct cec_notifier		*notify;
182 	struct cec_adapter		*adap;
183 	struct cec_msg			rx_msg;
184 	struct clk			*oscin;
185 	struct clk			*core;
186 	const struct meson_ao_cec_g12a_data *data;
187 };
188 
189 static const struct regmap_config meson_ao_cec_g12a_regmap_conf = {
190 	.reg_bits = 8,
191 	.val_bits = 32,
192 	.reg_stride = 4,
193 	.max_register = CECB_INTR_STAT_REG,
194 };
195 
196 /*
197  * The AO-CECB embeds a dual/divider to generate a more precise
198  * 32,768KHz clock for CEC core clock.
199  *                      ______   ______
200  *                     |      | |      |
201  *         ______      | Div1 |-| Cnt1 |       ______
202  *        |      |    /|______| |______|\     |      |
203  * Xtal-->| Gate |---|  ______   ______  X-X--| Gate |-->
204  *        |______| |  \|      | |      |/  |  |______|
205  *                 |   | Div2 |-| Cnt2 |   |
206  *                 |   |______| |______|   |
207  *                 |_______________________|
208  *
209  * The dividing can be switched to single or dual, with a counter
210  * for each divider to set when the switching is done.
211  * The entire dividing mechanism can be also bypassed.
212  */
213 
214 struct meson_ao_cec_g12a_dualdiv_clk {
215 	struct clk_hw hw;
216 	struct regmap *regmap;
217 };
218 
219 #define hw_to_meson_ao_cec_g12a_dualdiv_clk(_hw)			\
220 	container_of(_hw, struct meson_ao_cec_g12a_dualdiv_clk, hw)	\
221 
222 static unsigned long
223 meson_ao_cec_g12a_dualdiv_clk_recalc_rate(struct clk_hw *hw,
224 					  unsigned long parent_rate)
225 {
226 	struct meson_ao_cec_g12a_dualdiv_clk *dualdiv_clk =
227 		hw_to_meson_ao_cec_g12a_dualdiv_clk(hw);
228 	unsigned long n1;
229 	u32 reg0, reg1;
230 
231 	regmap_read(dualdiv_clk->regmap, CECB_CLK_CNTL_REG0, &reg0);
232 	regmap_read(dualdiv_clk->regmap, CECB_CLK_CNTL_REG0, &reg1);
233 
234 	if (reg1 & CECB_CLK_CNTL_BYPASS_EN)
235 		return parent_rate;
236 
237 	if (reg0 & CECB_CLK_CNTL_DUAL_EN) {
238 		unsigned long n2, m1, m2, f1, f2, p1, p2;
239 
240 		n1 = FIELD_GET(CECB_CLK_CNTL_N1, reg0) + 1;
241 		n2 = FIELD_GET(CECB_CLK_CNTL_N2, reg0) + 1;
242 
243 		m1 = FIELD_GET(CECB_CLK_CNTL_M1, reg1) + 1;
244 		m2 = FIELD_GET(CECB_CLK_CNTL_M1, reg1) + 1;
245 
246 		f1 = DIV_ROUND_CLOSEST(parent_rate, n1);
247 		f2 = DIV_ROUND_CLOSEST(parent_rate, n2);
248 
249 		p1 = DIV_ROUND_CLOSEST(100000000 * m1, f1 * (m1 + m2));
250 		p2 = DIV_ROUND_CLOSEST(100000000 * m2, f2 * (m1 + m2));
251 
252 		return DIV_ROUND_UP(100000000, p1 + p2);
253 	}
254 
255 	n1 = FIELD_GET(CECB_CLK_CNTL_N1, reg0) + 1;
256 
257 	return DIV_ROUND_CLOSEST(parent_rate, n1);
258 }
259 
260 static int meson_ao_cec_g12a_dualdiv_clk_enable(struct clk_hw *hw)
261 {
262 	struct meson_ao_cec_g12a_dualdiv_clk *dualdiv_clk =
263 		hw_to_meson_ao_cec_g12a_dualdiv_clk(hw);
264 
265 
266 	/* Disable Input & Output */
267 	regmap_update_bits(dualdiv_clk->regmap, CECB_CLK_CNTL_REG0,
268 			   CECB_CLK_CNTL_INPUT_EN | CECB_CLK_CNTL_OUTPUT_EN,
269 			   0);
270 
271 	/* Set N1 & N2 */
272 	regmap_update_bits(dualdiv_clk->regmap, CECB_CLK_CNTL_REG0,
273 			   CECB_CLK_CNTL_N1,
274 			   FIELD_PREP(CECB_CLK_CNTL_N1, 733 - 1));
275 
276 	regmap_update_bits(dualdiv_clk->regmap, CECB_CLK_CNTL_REG0,
277 			   CECB_CLK_CNTL_N2,
278 			   FIELD_PREP(CECB_CLK_CNTL_N2, 732 - 1));
279 
280 	/* Set M1 & M2 */
281 	regmap_update_bits(dualdiv_clk->regmap, CECB_CLK_CNTL_REG1,
282 			   CECB_CLK_CNTL_M1,
283 			   FIELD_PREP(CECB_CLK_CNTL_M1, 8 - 1));
284 
285 	regmap_update_bits(dualdiv_clk->regmap, CECB_CLK_CNTL_REG1,
286 			   CECB_CLK_CNTL_M2,
287 			   FIELD_PREP(CECB_CLK_CNTL_M2, 11 - 1));
288 
289 	/* Enable Dual divisor */
290 	regmap_update_bits(dualdiv_clk->regmap, CECB_CLK_CNTL_REG0,
291 			   CECB_CLK_CNTL_DUAL_EN, CECB_CLK_CNTL_DUAL_EN);
292 
293 	/* Disable divisor bypass */
294 	regmap_update_bits(dualdiv_clk->regmap, CECB_CLK_CNTL_REG1,
295 			   CECB_CLK_CNTL_BYPASS_EN, 0);
296 
297 	/* Enable Input & Output */
298 	regmap_update_bits(dualdiv_clk->regmap, CECB_CLK_CNTL_REG0,
299 			   CECB_CLK_CNTL_INPUT_EN | CECB_CLK_CNTL_OUTPUT_EN,
300 			   CECB_CLK_CNTL_INPUT_EN | CECB_CLK_CNTL_OUTPUT_EN);
301 
302 	return 0;
303 }
304 
305 static void meson_ao_cec_g12a_dualdiv_clk_disable(struct clk_hw *hw)
306 {
307 	struct meson_ao_cec_g12a_dualdiv_clk *dualdiv_clk =
308 		hw_to_meson_ao_cec_g12a_dualdiv_clk(hw);
309 
310 	regmap_update_bits(dualdiv_clk->regmap, CECB_CLK_CNTL_REG0,
311 			   CECB_CLK_CNTL_INPUT_EN | CECB_CLK_CNTL_OUTPUT_EN,
312 			   0);
313 }
314 
315 static int meson_ao_cec_g12a_dualdiv_clk_is_enabled(struct clk_hw *hw)
316 {
317 	struct meson_ao_cec_g12a_dualdiv_clk *dualdiv_clk =
318 		hw_to_meson_ao_cec_g12a_dualdiv_clk(hw);
319 	int val;
320 
321 	regmap_read(dualdiv_clk->regmap, CECB_CLK_CNTL_REG0, &val);
322 
323 	return !!(val & (CECB_CLK_CNTL_INPUT_EN | CECB_CLK_CNTL_OUTPUT_EN));
324 }
325 
326 static const struct clk_ops meson_ao_cec_g12a_dualdiv_clk_ops = {
327 	.recalc_rate	= meson_ao_cec_g12a_dualdiv_clk_recalc_rate,
328 	.is_enabled	= meson_ao_cec_g12a_dualdiv_clk_is_enabled,
329 	.enable		= meson_ao_cec_g12a_dualdiv_clk_enable,
330 	.disable	= meson_ao_cec_g12a_dualdiv_clk_disable,
331 };
332 
333 static int meson_ao_cec_g12a_setup_clk(struct meson_ao_cec_g12a_device *ao_cec)
334 {
335 	struct meson_ao_cec_g12a_dualdiv_clk *dualdiv_clk;
336 	struct device *dev = &ao_cec->pdev->dev;
337 	struct clk_init_data init;
338 	const char *parent_name;
339 	struct clk *clk;
340 	char *name;
341 
342 	dualdiv_clk = devm_kzalloc(dev, sizeof(*dualdiv_clk), GFP_KERNEL);
343 	if (!dualdiv_clk)
344 		return -ENOMEM;
345 
346 	name = kasprintf(GFP_KERNEL, "%s#dualdiv_clk", dev_name(dev));
347 	if (!name)
348 		return -ENOMEM;
349 
350 	parent_name = __clk_get_name(ao_cec->oscin);
351 
352 	init.name = name;
353 	init.ops = &meson_ao_cec_g12a_dualdiv_clk_ops;
354 	init.flags = 0;
355 	init.parent_names = &parent_name;
356 	init.num_parents = 1;
357 	dualdiv_clk->regmap = ao_cec->regmap;
358 	dualdiv_clk->hw.init = &init;
359 
360 	clk = devm_clk_register(dev, &dualdiv_clk->hw);
361 	kfree(name);
362 	if (IS_ERR(clk)) {
363 		dev_err(dev, "failed to register clock\n");
364 		return PTR_ERR(clk);
365 	}
366 
367 	ao_cec->core = clk;
368 
369 	return 0;
370 }
371 
372 static int meson_ao_cec_g12a_read(void *context, unsigned int addr,
373 				  unsigned int *data)
374 {
375 	struct meson_ao_cec_g12a_device *ao_cec = context;
376 	u32 reg = FIELD_PREP(CECB_RW_ADDR, addr);
377 	int ret = 0;
378 
379 	ret = regmap_write(ao_cec->regmap, CECB_RW_REG, reg);
380 	if (ret)
381 		return ret;
382 
383 	ret = regmap_read_poll_timeout(ao_cec->regmap, CECB_RW_REG, reg,
384 				       !(reg & CECB_RW_BUS_BUSY),
385 				       5, 1000);
386 	if (ret)
387 		return ret;
388 
389 	ret = regmap_read(ao_cec->regmap, CECB_RW_REG, &reg);
390 
391 	*data = FIELD_GET(CECB_RW_RD_DATA, reg);
392 
393 	return ret;
394 }
395 
396 static int meson_ao_cec_g12a_write(void *context, unsigned int addr,
397 				   unsigned int data)
398 {
399 	struct meson_ao_cec_g12a_device *ao_cec = context;
400 	u32 reg = FIELD_PREP(CECB_RW_ADDR, addr) |
401 		  FIELD_PREP(CECB_RW_WR_DATA, data) |
402 		  CECB_RW_WRITE_EN;
403 
404 	return regmap_write(ao_cec->regmap, CECB_RW_REG, reg);
405 }
406 
407 static const struct regmap_config meson_ao_cec_g12a_cec_regmap_conf = {
408 	.reg_bits = 8,
409 	.val_bits = 8,
410 	.reg_read = meson_ao_cec_g12a_read,
411 	.reg_write = meson_ao_cec_g12a_write,
412 	.max_register = 0xffff,
413 };
414 
415 static inline void
416 meson_ao_cec_g12a_irq_setup(struct meson_ao_cec_g12a_device *ao_cec,
417 			    bool enable)
418 {
419 	u32 cfg = CECB_INTR_DONE | CECB_INTR_EOM | CECB_INTR_NACK |
420 		  CECB_INTR_ARB_LOSS | CECB_INTR_INITIATOR_ERR |
421 		  CECB_INTR_FOLLOWER_ERR;
422 
423 	regmap_write(ao_cec->regmap, CECB_INTR_MASKN_REG,
424 		     enable ? cfg : 0);
425 }
426 
427 static void meson_ao_cec_g12a_irq_rx(struct meson_ao_cec_g12a_device *ao_cec)
428 {
429 	int i, ret = 0;
430 	u32 val;
431 
432 	ret = regmap_read(ao_cec->regmap_cec, CECB_RX_CNT, &val);
433 
434 	ao_cec->rx_msg.len = val;
435 	if (ao_cec->rx_msg.len > CEC_MAX_MSG_SIZE)
436 		ao_cec->rx_msg.len = CEC_MAX_MSG_SIZE;
437 
438 	for (i = 0; i < ao_cec->rx_msg.len; i++) {
439 		ret |= regmap_read(ao_cec->regmap_cec,
440 				   CECB_RX_DATA00 + i, &val);
441 
442 		ao_cec->rx_msg.msg[i] = val & 0xff;
443 	}
444 
445 	ret |= regmap_write(ao_cec->regmap_cec, CECB_LOCK_BUF, 0);
446 	if (ret)
447 		return;
448 
449 	cec_received_msg(ao_cec->adap, &ao_cec->rx_msg);
450 }
451 
452 static irqreturn_t meson_ao_cec_g12a_irq(int irq, void *data)
453 {
454 	struct meson_ao_cec_g12a_device *ao_cec = data;
455 	u32 stat;
456 
457 	regmap_read(ao_cec->regmap, CECB_INTR_STAT_REG, &stat);
458 	if (stat)
459 		return IRQ_WAKE_THREAD;
460 
461 	return IRQ_NONE;
462 }
463 
464 static irqreturn_t meson_ao_cec_g12a_irq_thread(int irq, void *data)
465 {
466 	struct meson_ao_cec_g12a_device *ao_cec = data;
467 	u32 stat;
468 
469 	regmap_read(ao_cec->regmap, CECB_INTR_STAT_REG, &stat);
470 	regmap_write(ao_cec->regmap, CECB_INTR_CLR_REG, stat);
471 
472 	if (stat & CECB_INTR_DONE)
473 		cec_transmit_attempt_done(ao_cec->adap, CEC_TX_STATUS_OK);
474 
475 	if (stat & CECB_INTR_EOM)
476 		meson_ao_cec_g12a_irq_rx(ao_cec);
477 
478 	if (stat & CECB_INTR_NACK)
479 		cec_transmit_attempt_done(ao_cec->adap, CEC_TX_STATUS_NACK);
480 
481 	if (stat & CECB_INTR_ARB_LOSS) {
482 		regmap_write(ao_cec->regmap_cec, CECB_TX_CNT, 0);
483 		regmap_update_bits(ao_cec->regmap_cec, CECB_CTRL,
484 				   CECB_CTRL_SEND | CECB_CTRL_TYPE, 0);
485 		cec_transmit_attempt_done(ao_cec->adap, CEC_TX_STATUS_ARB_LOST);
486 	}
487 
488 	/* Initiator reports an error on the CEC bus */
489 	if (stat & CECB_INTR_INITIATOR_ERR)
490 		cec_transmit_attempt_done(ao_cec->adap, CEC_TX_STATUS_ERROR);
491 
492 	/* Follower reports a receive error, just reset RX buffer */
493 	if (stat & CECB_INTR_FOLLOWER_ERR)
494 		regmap_write(ao_cec->regmap_cec, CECB_LOCK_BUF, 0);
495 
496 	return IRQ_HANDLED;
497 }
498 
499 static int
500 meson_ao_cec_g12a_set_log_addr(struct cec_adapter *adap, u8 logical_addr)
501 {
502 	struct meson_ao_cec_g12a_device *ao_cec = adap->priv;
503 	int ret = 0;
504 
505 	if (logical_addr == CEC_LOG_ADDR_INVALID) {
506 		/* Assume this will allways succeed */
507 		regmap_write(ao_cec->regmap_cec, CECB_LADD_LOW, 0);
508 		regmap_write(ao_cec->regmap_cec, CECB_LADD_HIGH, 0);
509 
510 		return 0;
511 	} else if (logical_addr < 8) {
512 		ret = regmap_update_bits(ao_cec->regmap_cec, CECB_LADD_LOW,
513 					 BIT(logical_addr),
514 					 BIT(logical_addr));
515 	} else {
516 		ret = regmap_update_bits(ao_cec->regmap_cec, CECB_LADD_HIGH,
517 					 BIT(logical_addr - 8),
518 					 BIT(logical_addr - 8));
519 	}
520 
521 	/* Always set Broadcast/Unregistered 15 address */
522 	ret |= regmap_update_bits(ao_cec->regmap_cec, CECB_LADD_HIGH,
523 				  BIT(CEC_LOG_ADDR_UNREGISTERED - 8),
524 				  BIT(CEC_LOG_ADDR_UNREGISTERED - 8));
525 
526 	return ret ? -EIO : 0;
527 }
528 
529 static int meson_ao_cec_g12a_transmit(struct cec_adapter *adap, u8 attempts,
530 				 u32 signal_free_time, struct cec_msg *msg)
531 {
532 	struct meson_ao_cec_g12a_device *ao_cec = adap->priv;
533 	unsigned int type;
534 	int ret = 0;
535 	u32 val;
536 	int i;
537 
538 	/* Check if RX is in progress */
539 	ret = regmap_read(ao_cec->regmap_cec, CECB_LOCK_BUF, &val);
540 	if (ret)
541 		return ret;
542 	if (val & CECB_LOCK_BUF_EN)
543 		return -EBUSY;
544 
545 	/* Check if TX Busy */
546 	ret = regmap_read(ao_cec->regmap_cec, CECB_CTRL, &val);
547 	if (ret)
548 		return ret;
549 	if (val & CECB_CTRL_SEND)
550 		return -EBUSY;
551 
552 	switch (signal_free_time) {
553 	case CEC_SIGNAL_FREE_TIME_RETRY:
554 		type = CECB_CTRL_TYPE_RETRY;
555 		break;
556 	case CEC_SIGNAL_FREE_TIME_NEXT_XFER:
557 		type = CECB_CTRL_TYPE_NEXT;
558 		break;
559 	case CEC_SIGNAL_FREE_TIME_NEW_INITIATOR:
560 	default:
561 		type = CECB_CTRL_TYPE_NEW;
562 		break;
563 	}
564 
565 	for (i = 0; i < msg->len; i++)
566 		ret |= regmap_write(ao_cec->regmap_cec, CECB_TX_DATA00 + i,
567 				    msg->msg[i]);
568 
569 	ret |= regmap_write(ao_cec->regmap_cec, CECB_TX_CNT, msg->len);
570 	if (ret)
571 		return -EIO;
572 
573 	ret = regmap_update_bits(ao_cec->regmap_cec, CECB_CTRL,
574 				 CECB_CTRL_SEND |
575 				 CECB_CTRL_TYPE,
576 				 CECB_CTRL_SEND |
577 				 FIELD_PREP(CECB_CTRL_TYPE, type));
578 
579 	return ret;
580 }
581 
582 static int meson_ao_cec_g12a_adap_enable(struct cec_adapter *adap, bool enable)
583 {
584 	struct meson_ao_cec_g12a_device *ao_cec = adap->priv;
585 
586 	meson_ao_cec_g12a_irq_setup(ao_cec, false);
587 
588 	regmap_update_bits(ao_cec->regmap, CECB_GEN_CNTL_REG,
589 			   CECB_GEN_CNTL_RESET, CECB_GEN_CNTL_RESET);
590 
591 	if (!enable)
592 		return 0;
593 
594 	/* Setup Filter */
595 	regmap_update_bits(ao_cec->regmap, CECB_GEN_CNTL_REG,
596 			   CECB_GEN_CNTL_FILTER_TICK_SEL |
597 			   CECB_GEN_CNTL_FILTER_DEL,
598 			   FIELD_PREP(CECB_GEN_CNTL_FILTER_TICK_SEL,
599 				      CECB_GEN_CNTL_FILTER_TICK_1US) |
600 			   FIELD_PREP(CECB_GEN_CNTL_FILTER_DEL, 7));
601 
602 	/* Enable System Clock */
603 	regmap_update_bits(ao_cec->regmap, CECB_GEN_CNTL_REG,
604 			   CECB_GEN_CNTL_SYS_CLK_EN,
605 			   CECB_GEN_CNTL_SYS_CLK_EN);
606 
607 	/* Enable gated clock (Normal mode). */
608 	regmap_update_bits(ao_cec->regmap, CECB_GEN_CNTL_REG,
609 			   CECB_GEN_CNTL_CLK_CTRL_MASK,
610 			    FIELD_PREP(CECB_GEN_CNTL_CLK_CTRL_MASK,
611 				       CECB_GEN_CNTL_CLK_ENABLE));
612 
613 	/* Release Reset */
614 	regmap_update_bits(ao_cec->regmap, CECB_GEN_CNTL_REG,
615 			   CECB_GEN_CNTL_RESET, 0);
616 
617 	if (ao_cec->data->ctrl2_setup)
618 		regmap_write(ao_cec->regmap_cec, CECB_CTRL2,
619 			     FIELD_PREP(CECB_CTRL2_RISE_DEL_MAX, 2));
620 
621 	meson_ao_cec_g12a_irq_setup(ao_cec, true);
622 
623 	return 0;
624 }
625 
626 static const struct cec_adap_ops meson_ao_cec_g12a_ops = {
627 	.adap_enable = meson_ao_cec_g12a_adap_enable,
628 	.adap_log_addr = meson_ao_cec_g12a_set_log_addr,
629 	.adap_transmit = meson_ao_cec_g12a_transmit,
630 };
631 
632 static int meson_ao_cec_g12a_probe(struct platform_device *pdev)
633 {
634 	struct meson_ao_cec_g12a_device *ao_cec;
635 	struct device *hdmi_dev;
636 	struct resource *res;
637 	void __iomem *base;
638 	int ret, irq;
639 
640 	hdmi_dev = cec_notifier_parse_hdmi_phandle(&pdev->dev);
641 	if (IS_ERR(hdmi_dev))
642 		return PTR_ERR(hdmi_dev);
643 
644 	ao_cec = devm_kzalloc(&pdev->dev, sizeof(*ao_cec), GFP_KERNEL);
645 	if (!ao_cec)
646 		return -ENOMEM;
647 
648 	ao_cec->data = of_device_get_match_data(&pdev->dev);
649 	if (!ao_cec->data) {
650 		dev_err(&pdev->dev, "failed to get match data\n");
651 		return -ENODEV;
652 	}
653 
654 	spin_lock_init(&ao_cec->cec_reg_lock);
655 	ao_cec->pdev = pdev;
656 
657 	ao_cec->adap = cec_allocate_adapter(&meson_ao_cec_g12a_ops, ao_cec,
658 					    "meson_g12a_ao_cec",
659 					    CEC_CAP_DEFAULTS |
660 					    CEC_CAP_CONNECTOR_INFO,
661 					    CEC_MAX_LOG_ADDRS);
662 	if (IS_ERR(ao_cec->adap))
663 		return PTR_ERR(ao_cec->adap);
664 
665 	ao_cec->adap->owner = THIS_MODULE;
666 
667 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
668 	base = devm_ioremap_resource(&pdev->dev, res);
669 	if (IS_ERR(base)) {
670 		ret = PTR_ERR(base);
671 		goto out_probe_adapter;
672 	}
673 
674 	ao_cec->regmap = devm_regmap_init_mmio(&pdev->dev, base,
675 					       &meson_ao_cec_g12a_regmap_conf);
676 	if (IS_ERR(ao_cec->regmap)) {
677 		ret = PTR_ERR(ao_cec->regmap);
678 		goto out_probe_adapter;
679 	}
680 
681 	ao_cec->regmap_cec = devm_regmap_init(&pdev->dev, NULL, ao_cec,
682 					   &meson_ao_cec_g12a_cec_regmap_conf);
683 	if (IS_ERR(ao_cec->regmap_cec)) {
684 		ret = PTR_ERR(ao_cec->regmap_cec);
685 		goto out_probe_adapter;
686 	}
687 
688 	irq = platform_get_irq(pdev, 0);
689 	ret = devm_request_threaded_irq(&pdev->dev, irq,
690 					meson_ao_cec_g12a_irq,
691 					meson_ao_cec_g12a_irq_thread,
692 					0, NULL, ao_cec);
693 	if (ret) {
694 		dev_err(&pdev->dev, "irq request failed\n");
695 		goto out_probe_adapter;
696 	}
697 
698 	ao_cec->oscin = devm_clk_get(&pdev->dev, "oscin");
699 	if (IS_ERR(ao_cec->oscin)) {
700 		dev_err(&pdev->dev, "oscin clock request failed\n");
701 		ret = PTR_ERR(ao_cec->oscin);
702 		goto out_probe_adapter;
703 	}
704 
705 	ret = meson_ao_cec_g12a_setup_clk(ao_cec);
706 	if (ret)
707 		goto out_probe_adapter;
708 
709 	ret = clk_prepare_enable(ao_cec->core);
710 	if (ret) {
711 		dev_err(&pdev->dev, "core clock enable failed\n");
712 		goto out_probe_adapter;
713 	}
714 
715 	device_reset_optional(&pdev->dev);
716 
717 	platform_set_drvdata(pdev, ao_cec);
718 
719 	ao_cec->notify = cec_notifier_cec_adap_register(hdmi_dev, NULL,
720 							ao_cec->adap);
721 	if (!ao_cec->notify) {
722 		ret = -ENOMEM;
723 		goto out_probe_core_clk;
724 	}
725 
726 	ret = cec_register_adapter(ao_cec->adap, &pdev->dev);
727 	if (ret < 0)
728 		goto out_probe_notify;
729 
730 	/* Setup Hardware */
731 	regmap_write(ao_cec->regmap, CECB_GEN_CNTL_REG, CECB_GEN_CNTL_RESET);
732 
733 	return 0;
734 
735 out_probe_notify:
736 	cec_notifier_cec_adap_unregister(ao_cec->notify, ao_cec->adap);
737 
738 out_probe_core_clk:
739 	clk_disable_unprepare(ao_cec->core);
740 
741 out_probe_adapter:
742 	cec_delete_adapter(ao_cec->adap);
743 
744 	dev_err(&pdev->dev, "CEC controller registration failed\n");
745 
746 	return ret;
747 }
748 
749 static int meson_ao_cec_g12a_remove(struct platform_device *pdev)
750 {
751 	struct meson_ao_cec_g12a_device *ao_cec = platform_get_drvdata(pdev);
752 
753 	clk_disable_unprepare(ao_cec->core);
754 
755 	cec_notifier_cec_adap_unregister(ao_cec->notify, ao_cec->adap);
756 
757 	cec_unregister_adapter(ao_cec->adap);
758 
759 	return 0;
760 }
761 
762 static const struct meson_ao_cec_g12a_data ao_cec_g12a_data = {
763 	.ctrl2_setup = false,
764 };
765 
766 static const struct meson_ao_cec_g12a_data ao_cec_sm1_data = {
767 	.ctrl2_setup = true,
768 };
769 
770 static const struct of_device_id meson_ao_cec_g12a_of_match[] = {
771 	{
772 		.compatible = "amlogic,meson-g12a-ao-cec",
773 		.data = &ao_cec_g12a_data,
774 	},
775 	{
776 		.compatible = "amlogic,meson-sm1-ao-cec",
777 		.data = &ao_cec_sm1_data,
778 	},
779 	{ /* sentinel */ }
780 };
781 MODULE_DEVICE_TABLE(of, meson_ao_cec_g12a_of_match);
782 
783 static struct platform_driver meson_ao_cec_g12a_driver = {
784 	.probe   = meson_ao_cec_g12a_probe,
785 	.remove  = meson_ao_cec_g12a_remove,
786 	.driver  = {
787 		.name = "meson-ao-cec-g12a",
788 		.of_match_table = of_match_ptr(meson_ao_cec_g12a_of_match),
789 	},
790 };
791 
792 module_platform_driver(meson_ao_cec_g12a_driver);
793 
794 MODULE_DESCRIPTION("Meson AO CEC G12A Controller driver");
795 MODULE_AUTHOR("Neil Armstrong <narmstrong@baylibre.com>");
796 MODULE_LICENSE("GPL");
797