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
meson_ao_cec_g12a_dualdiv_clk_recalc_rate(struct clk_hw * hw,unsigned long parent_rate)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, ®0);
232 regmap_read(dualdiv_clk->regmap, CECB_CLK_CNTL_REG0, ®1);
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
meson_ao_cec_g12a_dualdiv_clk_enable(struct clk_hw * hw)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
meson_ao_cec_g12a_dualdiv_clk_disable(struct clk_hw * hw)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
meson_ao_cec_g12a_dualdiv_clk_is_enabled(struct clk_hw * hw)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
meson_ao_cec_g12a_setup_clk(struct meson_ao_cec_g12a_device * ao_cec)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
meson_ao_cec_g12a_read(void * context,unsigned int addr,unsigned int * data)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, ®);
390
391 *data = FIELD_GET(CECB_RW_RD_DATA, reg);
392
393 return ret;
394 }
395
meson_ao_cec_g12a_write(void * context,unsigned int addr,unsigned int data)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
meson_ao_cec_g12a_irq_setup(struct meson_ao_cec_g12a_device * ao_cec,bool enable)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
meson_ao_cec_g12a_irq_rx(struct meson_ao_cec_g12a_device * ao_cec)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
meson_ao_cec_g12a_irq(int irq,void * data)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
meson_ao_cec_g12a_irq_thread(int irq,void * data)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
meson_ao_cec_g12a_set_log_addr(struct cec_adapter * adap,u8 logical_addr)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
meson_ao_cec_g12a_transmit(struct cec_adapter * adap,u8 attempts,u32 signal_free_time,struct cec_msg * msg)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
meson_ao_cec_g12a_adap_enable(struct cec_adapter * adap,bool enable)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
meson_ao_cec_g12a_probe(struct platform_device * pdev)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 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
733 out_probe_notify:
734 cec_notifier_cec_adap_unregister(ao_cec->notify, ao_cec->adap);
735
736 out_probe_core_clk:
737 clk_disable_unprepare(ao_cec->core);
738
739 out_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
meson_ao_cec_g12a_remove(struct platform_device * pdev)747 static int 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 return 0;
758 }
759
760 static const struct meson_ao_cec_g12a_data ao_cec_g12a_data = {
761 .ctrl2_setup = false,
762 };
763
764 static const struct meson_ao_cec_g12a_data ao_cec_sm1_data = {
765 .ctrl2_setup = true,
766 };
767
768 static const struct of_device_id meson_ao_cec_g12a_of_match[] = {
769 {
770 .compatible = "amlogic,meson-g12a-ao-cec",
771 .data = &ao_cec_g12a_data,
772 },
773 {
774 .compatible = "amlogic,meson-sm1-ao-cec",
775 .data = &ao_cec_sm1_data,
776 },
777 { /* sentinel */ }
778 };
779 MODULE_DEVICE_TABLE(of, meson_ao_cec_g12a_of_match);
780
781 static struct platform_driver meson_ao_cec_g12a_driver = {
782 .probe = meson_ao_cec_g12a_probe,
783 .remove = meson_ao_cec_g12a_remove,
784 .driver = {
785 .name = "meson-ao-cec-g12a",
786 .of_match_table = of_match_ptr(meson_ao_cec_g12a_of_match),
787 },
788 };
789
790 module_platform_driver(meson_ao_cec_g12a_driver);
791
792 MODULE_DESCRIPTION("Meson AO CEC G12A Controller driver");
793 MODULE_AUTHOR("Neil Armstrong <narmstrong@baylibre.com>");
794 MODULE_LICENSE("GPL");
795