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
171struct meson_ao_cec_g12a_data {
172	/* Setup the internal CECB_CTRL2 register */
173	bool				ctrl2_setup;
174};
175
176struct 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
189static 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
214struct 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
222static unsigned long
223meson_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
260static 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
305static 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
315static 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
326static 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
333static 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
372static 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
396static 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
407static 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
415static inline void
416meson_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
427static 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
452static 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
464static 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
499static int
500meson_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
529static 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
582static 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
626static 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
632static 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	void __iomem *base;
637	int ret, irq;
638
639	hdmi_dev = cec_notifier_parse_hdmi_phandle(&pdev->dev);
640	if (IS_ERR(hdmi_dev))
641		return PTR_ERR(hdmi_dev);
642
643	ao_cec = devm_kzalloc(&pdev->dev, sizeof(*ao_cec), GFP_KERNEL);
644	if (!ao_cec)
645		return -ENOMEM;
646
647	ao_cec->data = of_device_get_match_data(&pdev->dev);
648	if (!ao_cec->data) {
649		dev_err(&pdev->dev, "failed to get match data\n");
650		return -ENODEV;
651	}
652
653	spin_lock_init(&ao_cec->cec_reg_lock);
654	ao_cec->pdev = pdev;
655
656	ao_cec->adap = cec_allocate_adapter(&meson_ao_cec_g12a_ops, ao_cec,
657					    "meson_g12a_ao_cec",
658					    CEC_CAP_DEFAULTS |
659					    CEC_CAP_CONNECTOR_INFO,
660					    CEC_MAX_LOG_ADDRS);
661	if (IS_ERR(ao_cec->adap))
662		return PTR_ERR(ao_cec->adap);
663
664	ao_cec->adap->owner = THIS_MODULE;
665
666	base = devm_platform_ioremap_resource(pdev, 0);
667	if (IS_ERR(base)) {
668		ret = PTR_ERR(base);
669		goto out_probe_adapter;
670	}
671
672	ao_cec->regmap = devm_regmap_init_mmio(&pdev->dev, base,
673					       &meson_ao_cec_g12a_regmap_conf);
674	if (IS_ERR(ao_cec->regmap)) {
675		ret = PTR_ERR(ao_cec->regmap);
676		goto out_probe_adapter;
677	}
678
679	ao_cec->regmap_cec = devm_regmap_init(&pdev->dev, NULL, ao_cec,
680					   &meson_ao_cec_g12a_cec_regmap_conf);
681	if (IS_ERR(ao_cec->regmap_cec)) {
682		ret = PTR_ERR(ao_cec->regmap_cec);
683		goto out_probe_adapter;
684	}
685
686	irq = platform_get_irq(pdev, 0);
687	ret = devm_request_threaded_irq(&pdev->dev, irq,
688					meson_ao_cec_g12a_irq,
689					meson_ao_cec_g12a_irq_thread,
690					0, NULL, ao_cec);
691	if (ret) {
692		dev_err(&pdev->dev, "irq request failed\n");
693		goto out_probe_adapter;
694	}
695
696	ao_cec->oscin = devm_clk_get(&pdev->dev, "oscin");
697	if (IS_ERR(ao_cec->oscin)) {
698		dev_err(&pdev->dev, "oscin clock request failed\n");
699		ret = PTR_ERR(ao_cec->oscin);
700		goto out_probe_adapter;
701	}
702
703	ret = meson_ao_cec_g12a_setup_clk(ao_cec);
704	if (ret)
705		goto out_probe_adapter;
706
707	ret = clk_prepare_enable(ao_cec->core);
708	if (ret) {
709		dev_err(&pdev->dev, "core clock enable failed\n");
710		goto out_probe_adapter;
711	}
712
713	device_reset_optional(&pdev->dev);
714
715	platform_set_drvdata(pdev, ao_cec);
716
717	ao_cec->notify = cec_notifier_cec_adap_register(hdmi_dev, NULL,
718							ao_cec->adap);
719	if (!ao_cec->notify) {
720		ret = -ENOMEM;
721		goto out_probe_core_clk;
722	}
723
724	ret = cec_register_adapter(ao_cec->adap, &pdev->dev);
725	if (ret < 0)
726		goto out_probe_notify;
727
728	/* Setup Hardware */
729	regmap_write(ao_cec->regmap, CECB_GEN_CNTL_REG, CECB_GEN_CNTL_RESET);
730
731	return 0;
732
733out_probe_notify:
734	cec_notifier_cec_adap_unregister(ao_cec->notify, ao_cec->adap);
735
736out_probe_core_clk:
737	clk_disable_unprepare(ao_cec->core);
738
739out_probe_adapter:
740	cec_delete_adapter(ao_cec->adap);
741
742	dev_err(&pdev->dev, "CEC controller registration failed\n");
743
744	return ret;
745}
746
747static void meson_ao_cec_g12a_remove(struct platform_device *pdev)
748{
749	struct meson_ao_cec_g12a_device *ao_cec = platform_get_drvdata(pdev);
750
751	clk_disable_unprepare(ao_cec->core);
752
753	cec_notifier_cec_adap_unregister(ao_cec->notify, ao_cec->adap);
754
755	cec_unregister_adapter(ao_cec->adap);
756}
757
758static const struct meson_ao_cec_g12a_data ao_cec_g12a_data = {
759	.ctrl2_setup = false,
760};
761
762static const struct meson_ao_cec_g12a_data ao_cec_sm1_data = {
763	.ctrl2_setup = true,
764};
765
766static const struct of_device_id meson_ao_cec_g12a_of_match[] = {
767	{
768		.compatible = "amlogic,meson-g12a-ao-cec",
769		.data = &ao_cec_g12a_data,
770	},
771	{
772		.compatible = "amlogic,meson-sm1-ao-cec",
773		.data = &ao_cec_sm1_data,
774	},
775	{ /* sentinel */ }
776};
777MODULE_DEVICE_TABLE(of, meson_ao_cec_g12a_of_match);
778
779static struct platform_driver meson_ao_cec_g12a_driver = {
780	.probe   = meson_ao_cec_g12a_probe,
781	.remove_new = meson_ao_cec_g12a_remove,
782	.driver  = {
783		.name = "meson-ao-cec-g12a",
784		.of_match_table = of_match_ptr(meson_ao_cec_g12a_of_match),
785	},
786};
787
788module_platform_driver(meson_ao_cec_g12a_driver);
789
790MODULE_DESCRIPTION("Meson AO CEC G12A Controller driver");
791MODULE_AUTHOR("Neil Armstrong <narmstrong@baylibre.com>");
792MODULE_LICENSE("GPL");
793