]> Git Repo - linux.git/blob - drivers/media/platform/meson/ao-cec-g12a.c
ARM: dts: imx7s: Enable SNVS power key according to board design
[linux.git] / drivers / media / platform / meson / ao-cec-g12a.c
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 <[email protected]>
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 #define CECB_INTR_MASK          0x02
125 #define CECB_LADD_LOW           0x05
126 #define CECB_LADD_HIGH          0x06
127 #define CECB_TX_CNT             0x07
128 #define CECB_RX_CNT             0x08
129 #define CECB_STAT0              0x09
130 #define CECB_TX_DATA00          0x10
131 #define CECB_TX_DATA01          0x11
132 #define CECB_TX_DATA02          0x12
133 #define CECB_TX_DATA03          0x13
134 #define CECB_TX_DATA04          0x14
135 #define CECB_TX_DATA05          0x15
136 #define CECB_TX_DATA06          0x16
137 #define CECB_TX_DATA07          0x17
138 #define CECB_TX_DATA08          0x18
139 #define CECB_TX_DATA09          0x19
140 #define CECB_TX_DATA10          0x1A
141 #define CECB_TX_DATA11          0x1B
142 #define CECB_TX_DATA12          0x1C
143 #define CECB_TX_DATA13          0x1D
144 #define CECB_TX_DATA14          0x1E
145 #define CECB_TX_DATA15          0x1F
146 #define CECB_RX_DATA00          0x20
147 #define CECB_RX_DATA01          0x21
148 #define CECB_RX_DATA02          0x22
149 #define CECB_RX_DATA03          0x23
150 #define CECB_RX_DATA04          0x24
151 #define CECB_RX_DATA05          0x25
152 #define CECB_RX_DATA06          0x26
153 #define CECB_RX_DATA07          0x27
154 #define CECB_RX_DATA08          0x28
155 #define CECB_RX_DATA09          0x29
156 #define CECB_RX_DATA10          0x2A
157 #define CECB_RX_DATA11          0x2B
158 #define CECB_RX_DATA12          0x2C
159 #define CECB_RX_DATA13          0x2D
160 #define CECB_RX_DATA14          0x2E
161 #define CECB_RX_DATA15          0x2F
162 #define CECB_LOCK_BUF           0x30
163
164 #define CECB_LOCK_BUF_EN        BIT(0)
165
166 #define CECB_WAKEUPCTRL         0x31
167
168 struct meson_ao_cec_g12a_device {
169         struct platform_device          *pdev;
170         struct regmap                   *regmap;
171         struct regmap                   *regmap_cec;
172         spinlock_t                      cec_reg_lock;
173         struct cec_notifier             *notify;
174         struct cec_adapter              *adap;
175         struct cec_msg                  rx_msg;
176         struct clk                      *oscin;
177         struct clk                      *core;
178 };
179
180 static const struct regmap_config meson_ao_cec_g12a_regmap_conf = {
181         .reg_bits = 8,
182         .val_bits = 32,
183         .reg_stride = 4,
184         .max_register = CECB_INTR_STAT_REG,
185 };
186
187 /*
188  * The AO-CECB embeds a dual/divider to generate a more precise
189  * 32,768KHz clock for CEC core clock.
190  *                      ______   ______
191  *                     |      | |      |
192  *         ______      | Div1 |-| Cnt1 |       ______
193  *        |      |    /|______| |______|\     |      |
194  * Xtal-->| Gate |---|  ______   ______  X-X--| Gate |-->
195  *        |______| |  \|      | |      |/  |  |______|
196  *                 |   | Div2 |-| Cnt2 |   |
197  *                 |   |______| |______|   |
198  *                 |_______________________|
199  *
200  * The dividing can be switched to single or dual, with a counter
201  * for each divider to set when the switching is done.
202  * The entire dividing mechanism can be also bypassed.
203  */
204
205 struct meson_ao_cec_g12a_dualdiv_clk {
206         struct clk_hw hw;
207         struct regmap *regmap;
208 };
209
210 #define hw_to_meson_ao_cec_g12a_dualdiv_clk(_hw)                        \
211         container_of(_hw, struct meson_ao_cec_g12a_dualdiv_clk, hw)     \
212
213 static unsigned long
214 meson_ao_cec_g12a_dualdiv_clk_recalc_rate(struct clk_hw *hw,
215                                           unsigned long parent_rate)
216 {
217         struct meson_ao_cec_g12a_dualdiv_clk *dualdiv_clk =
218                 hw_to_meson_ao_cec_g12a_dualdiv_clk(hw);
219         unsigned long n1;
220         u32 reg0, reg1;
221
222         regmap_read(dualdiv_clk->regmap, CECB_CLK_CNTL_REG0, &reg0);
223         regmap_read(dualdiv_clk->regmap, CECB_CLK_CNTL_REG0, &reg1);
224
225         if (reg1 & CECB_CLK_CNTL_BYPASS_EN)
226                 return parent_rate;
227
228         if (reg0 & CECB_CLK_CNTL_DUAL_EN) {
229                 unsigned long n2, m1, m2, f1, f2, p1, p2;
230
231                 n1 = FIELD_GET(CECB_CLK_CNTL_N1, reg0) + 1;
232                 n2 = FIELD_GET(CECB_CLK_CNTL_N2, reg0) + 1;
233
234                 m1 = FIELD_GET(CECB_CLK_CNTL_M1, reg1) + 1;
235                 m2 = FIELD_GET(CECB_CLK_CNTL_M1, reg1) + 1;
236
237                 f1 = DIV_ROUND_CLOSEST(parent_rate, n1);
238                 f2 = DIV_ROUND_CLOSEST(parent_rate, n2);
239
240                 p1 = DIV_ROUND_CLOSEST(100000000 * m1, f1 * (m1 + m2));
241                 p2 = DIV_ROUND_CLOSEST(100000000 * m2, f2 * (m1 + m2));
242
243                 return DIV_ROUND_UP(100000000, p1 + p2);
244         }
245
246         n1 = FIELD_GET(CECB_CLK_CNTL_N1, reg0) + 1;
247
248         return DIV_ROUND_CLOSEST(parent_rate, n1);
249 }
250
251 static int meson_ao_cec_g12a_dualdiv_clk_enable(struct clk_hw *hw)
252 {
253         struct meson_ao_cec_g12a_dualdiv_clk *dualdiv_clk =
254                 hw_to_meson_ao_cec_g12a_dualdiv_clk(hw);
255
256
257         /* Disable Input & Output */
258         regmap_update_bits(dualdiv_clk->regmap, CECB_CLK_CNTL_REG0,
259                            CECB_CLK_CNTL_INPUT_EN | CECB_CLK_CNTL_OUTPUT_EN,
260                            0);
261
262         /* Set N1 & N2 */
263         regmap_update_bits(dualdiv_clk->regmap, CECB_CLK_CNTL_REG0,
264                            CECB_CLK_CNTL_N1,
265                            FIELD_PREP(CECB_CLK_CNTL_N1, 733 - 1));
266
267         regmap_update_bits(dualdiv_clk->regmap, CECB_CLK_CNTL_REG0,
268                            CECB_CLK_CNTL_N2,
269                            FIELD_PREP(CECB_CLK_CNTL_N2, 732 - 1));
270
271         /* Set M1 & M2 */
272         regmap_update_bits(dualdiv_clk->regmap, CECB_CLK_CNTL_REG1,
273                            CECB_CLK_CNTL_M1,
274                            FIELD_PREP(CECB_CLK_CNTL_M1, 8 - 1));
275
276         regmap_update_bits(dualdiv_clk->regmap, CECB_CLK_CNTL_REG1,
277                            CECB_CLK_CNTL_M2,
278                            FIELD_PREP(CECB_CLK_CNTL_M2, 11 - 1));
279
280         /* Enable Dual divisor */
281         regmap_update_bits(dualdiv_clk->regmap, CECB_CLK_CNTL_REG0,
282                            CECB_CLK_CNTL_DUAL_EN, CECB_CLK_CNTL_DUAL_EN);
283
284         /* Disable divisor bypass */
285         regmap_update_bits(dualdiv_clk->regmap, CECB_CLK_CNTL_REG1,
286                            CECB_CLK_CNTL_BYPASS_EN, 0);
287
288         /* Enable Input & Output */
289         regmap_update_bits(dualdiv_clk->regmap, CECB_CLK_CNTL_REG0,
290                            CECB_CLK_CNTL_INPUT_EN | CECB_CLK_CNTL_OUTPUT_EN,
291                            CECB_CLK_CNTL_INPUT_EN | CECB_CLK_CNTL_OUTPUT_EN);
292
293         return 0;
294 }
295
296 static void meson_ao_cec_g12a_dualdiv_clk_disable(struct clk_hw *hw)
297 {
298         struct meson_ao_cec_g12a_dualdiv_clk *dualdiv_clk =
299                 hw_to_meson_ao_cec_g12a_dualdiv_clk(hw);
300
301         regmap_update_bits(dualdiv_clk->regmap, CECB_CLK_CNTL_REG0,
302                            CECB_CLK_CNTL_INPUT_EN | CECB_CLK_CNTL_OUTPUT_EN,
303                            0);
304 }
305
306 static int meson_ao_cec_g12a_dualdiv_clk_is_enabled(struct clk_hw *hw)
307 {
308         struct meson_ao_cec_g12a_dualdiv_clk *dualdiv_clk =
309                 hw_to_meson_ao_cec_g12a_dualdiv_clk(hw);
310         int val;
311
312         regmap_read(dualdiv_clk->regmap, CECB_CLK_CNTL_REG0, &val);
313
314         return !!(val & (CECB_CLK_CNTL_INPUT_EN | CECB_CLK_CNTL_OUTPUT_EN));
315 }
316
317 static const struct clk_ops meson_ao_cec_g12a_dualdiv_clk_ops = {
318         .recalc_rate    = meson_ao_cec_g12a_dualdiv_clk_recalc_rate,
319         .is_enabled     = meson_ao_cec_g12a_dualdiv_clk_is_enabled,
320         .enable         = meson_ao_cec_g12a_dualdiv_clk_enable,
321         .disable        = meson_ao_cec_g12a_dualdiv_clk_disable,
322 };
323
324 static int meson_ao_cec_g12a_setup_clk(struct meson_ao_cec_g12a_device *ao_cec)
325 {
326         struct meson_ao_cec_g12a_dualdiv_clk *dualdiv_clk;
327         struct device *dev = &ao_cec->pdev->dev;
328         struct clk_init_data init;
329         const char *parent_name;
330         struct clk *clk;
331         char *name;
332
333         dualdiv_clk = devm_kzalloc(dev, sizeof(*dualdiv_clk), GFP_KERNEL);
334         if (!dualdiv_clk)
335                 return -ENOMEM;
336
337         name = kasprintf(GFP_KERNEL, "%s#dualdiv_clk", dev_name(dev));
338         if (!name)
339                 return -ENOMEM;
340
341         parent_name = __clk_get_name(ao_cec->oscin);
342
343         init.name = name;
344         init.ops = &meson_ao_cec_g12a_dualdiv_clk_ops;
345         init.flags = 0;
346         init.parent_names = &parent_name;
347         init.num_parents = 1;
348         dualdiv_clk->regmap = ao_cec->regmap;
349         dualdiv_clk->hw.init = &init;
350
351         clk = devm_clk_register(dev, &dualdiv_clk->hw);
352         kfree(name);
353         if (IS_ERR(clk)) {
354                 dev_err(dev, "failed to register clock\n");
355                 return PTR_ERR(clk);
356         }
357
358         ao_cec->core = clk;
359
360         return 0;
361 }
362
363 static int meson_ao_cec_g12a_read(void *context, unsigned int addr,
364                                   unsigned int *data)
365 {
366         struct meson_ao_cec_g12a_device *ao_cec = context;
367         u32 reg = FIELD_PREP(CECB_RW_ADDR, addr);
368         unsigned long flags;
369         int ret = 0;
370
371         spin_lock_irqsave(&ao_cec->cec_reg_lock, flags);
372
373         ret = regmap_write(ao_cec->regmap, CECB_RW_REG, reg);
374         if (ret)
375                 goto read_out;
376
377         ret = regmap_read_poll_timeout(ao_cec->regmap, CECB_RW_REG, reg,
378                                        !(reg & CECB_RW_BUS_BUSY),
379                                        5, 1000);
380         if (ret)
381                 goto read_out;
382
383         ret = regmap_read(ao_cec->regmap, CECB_RW_REG, &reg);
384
385         *data = FIELD_GET(CECB_RW_RD_DATA, reg);
386
387 read_out:
388         spin_unlock_irqrestore(&ao_cec->cec_reg_lock, flags);
389
390         return ret;
391 }
392
393 static int meson_ao_cec_g12a_write(void *context, unsigned int addr,
394                                    unsigned int data)
395 {
396         struct meson_ao_cec_g12a_device *ao_cec = context;
397         unsigned long flags;
398         u32 reg = FIELD_PREP(CECB_RW_ADDR, addr) |
399                   FIELD_PREP(CECB_RW_WR_DATA, data) |
400                   CECB_RW_WRITE_EN;
401         int ret = 0;
402
403         spin_lock_irqsave(&ao_cec->cec_reg_lock, flags);
404
405         ret = regmap_write(ao_cec->regmap, CECB_RW_REG, reg);
406
407         spin_unlock_irqrestore(&ao_cec->cec_reg_lock, flags);
408
409         return ret;
410 }
411
412 static const struct regmap_config meson_ao_cec_g12a_cec_regmap_conf = {
413         .reg_bits = 8,
414         .val_bits = 8,
415         .reg_read = meson_ao_cec_g12a_read,
416         .reg_write = meson_ao_cec_g12a_write,
417         .max_register = 0xffff,
418         .fast_io = true,
419 };
420
421 static inline void
422 meson_ao_cec_g12a_irq_setup(struct meson_ao_cec_g12a_device *ao_cec,
423                             bool enable)
424 {
425         u32 cfg = CECB_INTR_DONE | CECB_INTR_EOM | CECB_INTR_NACK |
426                   CECB_INTR_ARB_LOSS | CECB_INTR_INITIATOR_ERR |
427                   CECB_INTR_FOLLOWER_ERR;
428
429         regmap_write(ao_cec->regmap, CECB_INTR_MASKN_REG,
430                      enable ? cfg : 0);
431 }
432
433 static void meson_ao_cec_g12a_irq_rx(struct meson_ao_cec_g12a_device *ao_cec)
434 {
435         int i, ret = 0;
436         u32 val;
437
438         ret = regmap_read(ao_cec->regmap_cec, CECB_RX_CNT, &val);
439
440         ao_cec->rx_msg.len = val;
441         if (ao_cec->rx_msg.len > CEC_MAX_MSG_SIZE)
442                 ao_cec->rx_msg.len = CEC_MAX_MSG_SIZE;
443
444         for (i = 0; i < ao_cec->rx_msg.len; i++) {
445                 ret |= regmap_read(ao_cec->regmap_cec,
446                                    CECB_RX_DATA00 + i, &val);
447
448                 ao_cec->rx_msg.msg[i] = val & 0xff;
449         }
450
451         ret |= regmap_write(ao_cec->regmap_cec, CECB_LOCK_BUF, 0);
452         if (ret)
453                 return;
454
455         cec_received_msg(ao_cec->adap, &ao_cec->rx_msg);
456 }
457
458 static irqreturn_t meson_ao_cec_g12a_irq(int irq, void *data)
459 {
460         struct meson_ao_cec_g12a_device *ao_cec = data;
461         u32 stat;
462
463         regmap_read(ao_cec->regmap, CECB_INTR_STAT_REG, &stat);
464         if (stat)
465                 return IRQ_WAKE_THREAD;
466
467         return IRQ_NONE;
468 }
469
470 static irqreturn_t meson_ao_cec_g12a_irq_thread(int irq, void *data)
471 {
472         struct meson_ao_cec_g12a_device *ao_cec = data;
473         u32 stat;
474
475         regmap_read(ao_cec->regmap, CECB_INTR_STAT_REG, &stat);
476         regmap_write(ao_cec->regmap, CECB_INTR_CLR_REG, stat);
477
478         if (stat & CECB_INTR_DONE)
479                 cec_transmit_attempt_done(ao_cec->adap, CEC_TX_STATUS_OK);
480
481         if (stat & CECB_INTR_EOM)
482                 meson_ao_cec_g12a_irq_rx(ao_cec);
483
484         if (stat & CECB_INTR_NACK)
485                 cec_transmit_attempt_done(ao_cec->adap, CEC_TX_STATUS_NACK);
486
487         if (stat & CECB_INTR_ARB_LOSS) {
488                 regmap_write(ao_cec->regmap_cec, CECB_TX_CNT, 0);
489                 regmap_update_bits(ao_cec->regmap_cec, CECB_CTRL,
490                                    CECB_CTRL_SEND | CECB_CTRL_TYPE, 0);
491                 cec_transmit_attempt_done(ao_cec->adap, CEC_TX_STATUS_ARB_LOST);
492         }
493
494         /* Initiator reports an error on the CEC bus */
495         if (stat & CECB_INTR_INITIATOR_ERR)
496                 cec_transmit_attempt_done(ao_cec->adap, CEC_TX_STATUS_ERROR);
497
498         /* Follower reports a receive error, just reset RX buffer */
499         if (stat & CECB_INTR_FOLLOWER_ERR)
500                 regmap_write(ao_cec->regmap_cec, CECB_LOCK_BUF, 0);
501
502         return IRQ_HANDLED;
503 }
504
505 static int
506 meson_ao_cec_g12a_set_log_addr(struct cec_adapter *adap, u8 logical_addr)
507 {
508         struct meson_ao_cec_g12a_device *ao_cec = adap->priv;
509         int ret = 0;
510
511         if (logical_addr == CEC_LOG_ADDR_INVALID) {
512                 /* Assume this will allways succeed */
513                 regmap_write(ao_cec->regmap_cec, CECB_LADD_LOW, 0);
514                 regmap_write(ao_cec->regmap_cec, CECB_LADD_HIGH, 0);
515
516                 return 0;
517         } else if (logical_addr < 8) {
518                 ret = regmap_update_bits(ao_cec->regmap_cec, CECB_LADD_LOW,
519                                          BIT(logical_addr),
520                                          BIT(logical_addr));
521         } else {
522                 ret = regmap_update_bits(ao_cec->regmap_cec, CECB_LADD_HIGH,
523                                          BIT(logical_addr - 8),
524                                          BIT(logical_addr - 8));
525         }
526
527         /* Always set Broadcast/Unregistered 15 address */
528         ret |= regmap_update_bits(ao_cec->regmap_cec, CECB_LADD_HIGH,
529                                   BIT(CEC_LOG_ADDR_UNREGISTERED - 8),
530                                   BIT(CEC_LOG_ADDR_UNREGISTERED - 8));
531
532         return ret ? -EIO : 0;
533 }
534
535 static int meson_ao_cec_g12a_transmit(struct cec_adapter *adap, u8 attempts,
536                                  u32 signal_free_time, struct cec_msg *msg)
537 {
538         struct meson_ao_cec_g12a_device *ao_cec = adap->priv;
539         unsigned int type;
540         int ret = 0;
541         u32 val;
542         int i;
543
544         /* Check if RX is in progress */
545         ret = regmap_read(ao_cec->regmap_cec, CECB_LOCK_BUF, &val);
546         if (ret)
547                 return ret;
548         if (val & CECB_LOCK_BUF_EN)
549                 return -EBUSY;
550
551         /* Check if TX Busy */
552         ret = regmap_read(ao_cec->regmap_cec, CECB_CTRL, &val);
553         if (ret)
554                 return ret;
555         if (val & CECB_CTRL_SEND)
556                 return -EBUSY;
557
558         switch (signal_free_time) {
559         case CEC_SIGNAL_FREE_TIME_RETRY:
560                 type = CECB_CTRL_TYPE_RETRY;
561                 break;
562         case CEC_SIGNAL_FREE_TIME_NEXT_XFER:
563                 type = CECB_CTRL_TYPE_NEXT;
564                 break;
565         case CEC_SIGNAL_FREE_TIME_NEW_INITIATOR:
566         default:
567                 type = CECB_CTRL_TYPE_NEW;
568                 break;
569         }
570
571         for (i = 0; i < msg->len; i++)
572                 ret |= regmap_write(ao_cec->regmap_cec, CECB_TX_DATA00 + i,
573                                     msg->msg[i]);
574
575         ret |= regmap_write(ao_cec->regmap_cec, CECB_TX_CNT, msg->len);
576         if (ret)
577                 return -EIO;
578
579         ret = regmap_update_bits(ao_cec->regmap_cec, CECB_CTRL,
580                                  CECB_CTRL_SEND |
581                                  CECB_CTRL_TYPE,
582                                  CECB_CTRL_SEND |
583                                  FIELD_PREP(CECB_CTRL_TYPE, type));
584
585         return ret;
586 }
587
588 static int meson_ao_cec_g12a_adap_enable(struct cec_adapter *adap, bool enable)
589 {
590         struct meson_ao_cec_g12a_device *ao_cec = adap->priv;
591
592         meson_ao_cec_g12a_irq_setup(ao_cec, false);
593
594         regmap_update_bits(ao_cec->regmap, CECB_GEN_CNTL_REG,
595                            CECB_GEN_CNTL_RESET, CECB_GEN_CNTL_RESET);
596
597         if (!enable)
598                 return 0;
599
600         /* Setup Filter */
601         regmap_update_bits(ao_cec->regmap, CECB_GEN_CNTL_REG,
602                            CECB_GEN_CNTL_FILTER_TICK_SEL |
603                            CECB_GEN_CNTL_FILTER_DEL,
604                            FIELD_PREP(CECB_GEN_CNTL_FILTER_TICK_SEL,
605                                       CECB_GEN_CNTL_FILTER_TICK_1US) |
606                            FIELD_PREP(CECB_GEN_CNTL_FILTER_DEL, 7));
607
608         /* Enable System Clock */
609         regmap_update_bits(ao_cec->regmap, CECB_GEN_CNTL_REG,
610                            CECB_GEN_CNTL_SYS_CLK_EN,
611                            CECB_GEN_CNTL_SYS_CLK_EN);
612
613         /* Enable gated clock (Normal mode). */
614         regmap_update_bits(ao_cec->regmap, CECB_GEN_CNTL_REG,
615                            CECB_GEN_CNTL_CLK_CTRL_MASK,
616                             FIELD_PREP(CECB_GEN_CNTL_CLK_CTRL_MASK,
617                                        CECB_GEN_CNTL_CLK_ENABLE));
618
619         /* Release Reset */
620         regmap_update_bits(ao_cec->regmap, CECB_GEN_CNTL_REG,
621                            CECB_GEN_CNTL_RESET, 0);
622
623         meson_ao_cec_g12a_irq_setup(ao_cec, true);
624
625         return 0;
626 }
627
628 static const struct cec_adap_ops meson_ao_cec_g12a_ops = {
629         .adap_enable = meson_ao_cec_g12a_adap_enable,
630         .adap_log_addr = meson_ao_cec_g12a_set_log_addr,
631         .adap_transmit = meson_ao_cec_g12a_transmit,
632 };
633
634 static int meson_ao_cec_g12a_probe(struct platform_device *pdev)
635 {
636         struct meson_ao_cec_g12a_device *ao_cec;
637         struct device *hdmi_dev;
638         struct resource *res;
639         void __iomem *base;
640         int ret, irq;
641
642         hdmi_dev = cec_notifier_parse_hdmi_phandle(&pdev->dev);
643         if (IS_ERR(hdmi_dev))
644                 return PTR_ERR(hdmi_dev);
645
646         ao_cec = devm_kzalloc(&pdev->dev, sizeof(*ao_cec), GFP_KERNEL);
647         if (!ao_cec)
648                 return -ENOMEM;
649
650         spin_lock_init(&ao_cec->cec_reg_lock);
651         ao_cec->pdev = pdev;
652
653         ao_cec->notify = cec_notifier_get(hdmi_dev);
654         if (!ao_cec->notify)
655                 return -ENOMEM;
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_MAX_LOG_ADDRS);
661         if (IS_ERR(ao_cec->adap)) {
662                 ret = PTR_ERR(ao_cec->adap);
663                 goto out_probe_notify;
664         }
665
666         ao_cec->adap->owner = THIS_MODULE;
667
668         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
669         base = devm_ioremap_resource(&pdev->dev, res);
670         if (IS_ERR(base)) {
671                 ret = PTR_ERR(base);
672                 goto out_probe_adapter;
673         }
674
675         ao_cec->regmap = devm_regmap_init_mmio(&pdev->dev, base,
676                                                &meson_ao_cec_g12a_regmap_conf);
677         if (IS_ERR(ao_cec->regmap)) {
678                 ret = PTR_ERR(ao_cec->regmap);
679                 goto out_probe_adapter;
680         }
681
682         ao_cec->regmap_cec = devm_regmap_init(&pdev->dev, NULL, ao_cec,
683                                            &meson_ao_cec_g12a_cec_regmap_conf);
684         if (IS_ERR(ao_cec->regmap_cec)) {
685                 ret = PTR_ERR(ao_cec->regmap_cec);
686                 goto out_probe_adapter;
687         }
688
689         irq = platform_get_irq(pdev, 0);
690         ret = devm_request_threaded_irq(&pdev->dev, irq,
691                                         meson_ao_cec_g12a_irq,
692                                         meson_ao_cec_g12a_irq_thread,
693                                         0, NULL, ao_cec);
694         if (ret) {
695                 dev_err(&pdev->dev, "irq request failed\n");
696                 goto out_probe_adapter;
697         }
698
699         ao_cec->oscin = devm_clk_get(&pdev->dev, "oscin");
700         if (IS_ERR(ao_cec->oscin)) {
701                 dev_err(&pdev->dev, "oscin clock request failed\n");
702                 ret = PTR_ERR(ao_cec->oscin);
703                 goto out_probe_adapter;
704         }
705
706         ret = meson_ao_cec_g12a_setup_clk(ao_cec);
707         if (ret)
708                 goto out_probe_adapter;
709
710         ret = clk_prepare_enable(ao_cec->core);
711         if (ret) {
712                 dev_err(&pdev->dev, "core clock enable failed\n");
713                 goto out_probe_adapter;
714         }
715
716         device_reset_optional(&pdev->dev);
717
718         platform_set_drvdata(pdev, ao_cec);
719
720         ret = cec_register_adapter(ao_cec->adap, &pdev->dev);
721         if (ret < 0) {
722                 cec_notifier_put(ao_cec->notify);
723                 goto out_probe_core_clk;
724         }
725
726         /* Setup Hardware */
727         regmap_write(ao_cec->regmap, CECB_GEN_CNTL_REG, CECB_GEN_CNTL_RESET);
728
729         cec_register_cec_notifier(ao_cec->adap, ao_cec->notify);
730
731         return 0;
732
733 out_probe_core_clk:
734         clk_disable_unprepare(ao_cec->core);
735
736 out_probe_adapter:
737         cec_delete_adapter(ao_cec->adap);
738
739 out_probe_notify:
740         cec_notifier_put(ao_cec->notify);
741
742         dev_err(&pdev->dev, "CEC controller registration failed\n");
743
744         return ret;
745 }
746
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_unregister_adapter(ao_cec->adap);
754
755         cec_notifier_put(ao_cec->notify);
756
757         return 0;
758 }
759
760 static const struct of_device_id meson_ao_cec_g12a_of_match[] = {
761         { .compatible = "amlogic,meson-g12a-ao-cec", },
762         { /* sentinel */ }
763 };
764 MODULE_DEVICE_TABLE(of, meson_ao_cec_g12a_of_match);
765
766 static struct platform_driver meson_ao_cec_g12a_driver = {
767         .probe   = meson_ao_cec_g12a_probe,
768         .remove  = meson_ao_cec_g12a_remove,
769         .driver  = {
770                 .name = "meson-ao-cec-g12a",
771                 .of_match_table = of_match_ptr(meson_ao_cec_g12a_of_match),
772         },
773 };
774
775 module_platform_driver(meson_ao_cec_g12a_driver);
776
777 MODULE_DESCRIPTION("Meson AO CEC G12A Controller driver");
778 MODULE_AUTHOR("Neil Armstrong <[email protected]>");
779 MODULE_LICENSE("GPL");
This page took 0.075803 seconds and 4 git commands to generate.