Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 /*
0003  * Driver for Amlogic Meson AO CEC G12A Controller
0004  *
0005  * Copyright (C) 2017 Amlogic, Inc. All rights reserved
0006  * Copyright (C) 2019 BayLibre, SAS
0007  * Author: Neil Armstrong <narmstrong@baylibre.com>
0008  */
0009 
0010 #include <linux/bitfield.h>
0011 #include <linux/clk.h>
0012 #include <linux/device.h>
0013 #include <linux/io.h>
0014 #include <linux/delay.h>
0015 #include <linux/kernel.h>
0016 #include <linux/module.h>
0017 #include <linux/of.h>
0018 #include <linux/of_platform.h>
0019 #include <linux/platform_device.h>
0020 #include <linux/types.h>
0021 #include <linux/interrupt.h>
0022 #include <linux/reset.h>
0023 #include <linux/slab.h>
0024 #include <linux/regmap.h>
0025 #include <media/cec.h>
0026 #include <media/cec-notifier.h>
0027 #include <linux/clk-provider.h>
0028 
0029 /* CEC Registers */
0030 
0031 #define CECB_CLK_CNTL_REG0      0x00
0032 
0033 #define CECB_CLK_CNTL_N1        GENMASK(11, 0)
0034 #define CECB_CLK_CNTL_N2        GENMASK(23, 12)
0035 #define CECB_CLK_CNTL_DUAL_EN       BIT(28)
0036 #define CECB_CLK_CNTL_OUTPUT_EN     BIT(30)
0037 #define CECB_CLK_CNTL_INPUT_EN      BIT(31)
0038 
0039 #define CECB_CLK_CNTL_REG1      0x04
0040 
0041 #define CECB_CLK_CNTL_M1        GENMASK(11, 0)
0042 #define CECB_CLK_CNTL_M2        GENMASK(23, 12)
0043 #define CECB_CLK_CNTL_BYPASS_EN     BIT(24)
0044 
0045 /*
0046  * [14:12] Filter_del. For glitch-filtering CEC line, ignore signal
0047  *       change pulse width < filter_del * T(filter_tick) * 3.
0048  * [9:8] Filter_tick_sel: Select which periodical pulse for
0049  *       glitch-filtering CEC line signal.
0050  *  - 0=Use T(xtal)*3 = 125ns;
0051  *  - 1=Use once-per-1us pulse;
0052  *  - 2=Use once-per-10us pulse;
0053  *  - 3=Use once-per-100us pulse.
0054  * [3]   Sysclk_en. 0=Disable system clock; 1=Enable system clock.
0055  * [2:1] cntl_clk
0056  *  - 0 = Disable clk (Power-off mode)
0057  *  - 1 = Enable gated clock (Normal mode)
0058  *  - 2 = Enable free-run clk (Debug mode)
0059  * [0] SW_RESET 1=Apply reset; 0=No reset.
0060  */
0061 #define CECB_GEN_CNTL_REG       0x08
0062 
0063 #define CECB_GEN_CNTL_RESET     BIT(0)
0064 #define CECB_GEN_CNTL_CLK_DISABLE   0
0065 #define CECB_GEN_CNTL_CLK_ENABLE    1
0066 #define CECB_GEN_CNTL_CLK_ENABLE_DBG    2
0067 #define CECB_GEN_CNTL_CLK_CTRL_MASK GENMASK(2, 1)
0068 #define CECB_GEN_CNTL_SYS_CLK_EN    BIT(3)
0069 #define CECB_GEN_CNTL_FILTER_TICK_125NS 0
0070 #define CECB_GEN_CNTL_FILTER_TICK_1US   1
0071 #define CECB_GEN_CNTL_FILTER_TICK_10US  2
0072 #define CECB_GEN_CNTL_FILTER_TICK_100US 3
0073 #define CECB_GEN_CNTL_FILTER_TICK_SEL   GENMASK(9, 8)
0074 #define CECB_GEN_CNTL_FILTER_DEL    GENMASK(14, 12)
0075 
0076 /*
0077  * [7:0] cec_reg_addr
0078  * [15:8] cec_reg_wrdata
0079  * [16] cec_reg_wr
0080  *  - 0 = Read
0081  *  - 1 = Write
0082  * [31:24] cec_reg_rddata
0083  */
0084 #define CECB_RW_REG         0x0c
0085 
0086 #define CECB_RW_ADDR            GENMASK(7, 0)
0087 #define CECB_RW_WR_DATA         GENMASK(15, 8)
0088 #define CECB_RW_WRITE_EN        BIT(16)
0089 #define CECB_RW_BUS_BUSY        BIT(23)
0090 #define CECB_RW_RD_DATA         GENMASK(31, 24)
0091 
0092 /*
0093  * [0] DONE Interrupt
0094  * [1] End Of Message Interrupt
0095  * [2] Not Acknowlegde Interrupt
0096  * [3] Arbitration Loss Interrupt
0097  * [4] Initiator Error Interrupt
0098  * [5] Follower Error Interrupt
0099  * [6] Wake-Up Interrupt
0100  */
0101 #define CECB_INTR_MASKN_REG     0x10
0102 #define CECB_INTR_CLR_REG       0x14
0103 #define CECB_INTR_STAT_REG      0x18
0104 
0105 #define CECB_INTR_DONE          BIT(0)
0106 #define CECB_INTR_EOM           BIT(1)
0107 #define CECB_INTR_NACK          BIT(2)
0108 #define CECB_INTR_ARB_LOSS      BIT(3)
0109 #define CECB_INTR_INITIATOR_ERR     BIT(4)
0110 #define CECB_INTR_FOLLOWER_ERR      BIT(5)
0111 #define CECB_INTR_WAKE_UP       BIT(6)
0112 
0113 /* CEC Commands */
0114 
0115 #define CECB_CTRL       0x00
0116 
0117 #define CECB_CTRL_SEND      BIT(0)
0118 #define CECB_CTRL_TYPE      GENMASK(2, 1)
0119 #define CECB_CTRL_TYPE_RETRY    0
0120 #define CECB_CTRL_TYPE_NEW  1
0121 #define CECB_CTRL_TYPE_NEXT 2
0122 
0123 #define CECB_CTRL2      0x01
0124 
0125 #define CECB_CTRL2_RISE_DEL_MAX GENMASK(4, 0)
0126 
0127 #define CECB_INTR_MASK      0x02
0128 #define CECB_LADD_LOW       0x05
0129 #define CECB_LADD_HIGH      0x06
0130 #define CECB_TX_CNT     0x07
0131 #define CECB_RX_CNT     0x08
0132 #define CECB_STAT0      0x09
0133 #define CECB_TX_DATA00      0x10
0134 #define CECB_TX_DATA01      0x11
0135 #define CECB_TX_DATA02      0x12
0136 #define CECB_TX_DATA03      0x13
0137 #define CECB_TX_DATA04      0x14
0138 #define CECB_TX_DATA05      0x15
0139 #define CECB_TX_DATA06      0x16
0140 #define CECB_TX_DATA07      0x17
0141 #define CECB_TX_DATA08      0x18
0142 #define CECB_TX_DATA09      0x19
0143 #define CECB_TX_DATA10      0x1A
0144 #define CECB_TX_DATA11      0x1B
0145 #define CECB_TX_DATA12      0x1C
0146 #define CECB_TX_DATA13      0x1D
0147 #define CECB_TX_DATA14      0x1E
0148 #define CECB_TX_DATA15      0x1F
0149 #define CECB_RX_DATA00      0x20
0150 #define CECB_RX_DATA01      0x21
0151 #define CECB_RX_DATA02      0x22
0152 #define CECB_RX_DATA03      0x23
0153 #define CECB_RX_DATA04      0x24
0154 #define CECB_RX_DATA05      0x25
0155 #define CECB_RX_DATA06      0x26
0156 #define CECB_RX_DATA07      0x27
0157 #define CECB_RX_DATA08      0x28
0158 #define CECB_RX_DATA09      0x29
0159 #define CECB_RX_DATA10      0x2A
0160 #define CECB_RX_DATA11      0x2B
0161 #define CECB_RX_DATA12      0x2C
0162 #define CECB_RX_DATA13      0x2D
0163 #define CECB_RX_DATA14      0x2E
0164 #define CECB_RX_DATA15      0x2F
0165 #define CECB_LOCK_BUF       0x30
0166 
0167 #define CECB_LOCK_BUF_EN    BIT(0)
0168 
0169 #define CECB_WAKEUPCTRL     0x31
0170 
0171 struct meson_ao_cec_g12a_data {
0172     /* Setup the internal CECB_CTRL2 register */
0173     bool                ctrl2_setup;
0174 };
0175 
0176 struct meson_ao_cec_g12a_device {
0177     struct platform_device      *pdev;
0178     struct regmap           *regmap;
0179     struct regmap           *regmap_cec;
0180     spinlock_t          cec_reg_lock;
0181     struct cec_notifier     *notify;
0182     struct cec_adapter      *adap;
0183     struct cec_msg          rx_msg;
0184     struct clk          *oscin;
0185     struct clk          *core;
0186     const struct meson_ao_cec_g12a_data *data;
0187 };
0188 
0189 static const struct regmap_config meson_ao_cec_g12a_regmap_conf = {
0190     .reg_bits = 8,
0191     .val_bits = 32,
0192     .reg_stride = 4,
0193     .max_register = CECB_INTR_STAT_REG,
0194 };
0195 
0196 /*
0197  * The AO-CECB embeds a dual/divider to generate a more precise
0198  * 32,768KHz clock for CEC core clock.
0199  *                      ______   ______
0200  *                     |      | |      |
0201  *         ______      | Div1 |-| Cnt1 |       ______
0202  *        |      |    /|______| |______|\     |      |
0203  * Xtal-->| Gate |---|  ______   ______  X-X--| Gate |-->
0204  *        |______| |  \|      | |      |/  |  |______|
0205  *                 |   | Div2 |-| Cnt2 |   |
0206  *                 |   |______| |______|   |
0207  *                 |_______________________|
0208  *
0209  * The dividing can be switched to single or dual, with a counter
0210  * for each divider to set when the switching is done.
0211  * The entire dividing mechanism can be also bypassed.
0212  */
0213 
0214 struct meson_ao_cec_g12a_dualdiv_clk {
0215     struct clk_hw hw;
0216     struct regmap *regmap;
0217 };
0218 
0219 #define hw_to_meson_ao_cec_g12a_dualdiv_clk(_hw)            \
0220     container_of(_hw, struct meson_ao_cec_g12a_dualdiv_clk, hw) \
0221 
0222 static unsigned long
0223 meson_ao_cec_g12a_dualdiv_clk_recalc_rate(struct clk_hw *hw,
0224                       unsigned long parent_rate)
0225 {
0226     struct meson_ao_cec_g12a_dualdiv_clk *dualdiv_clk =
0227         hw_to_meson_ao_cec_g12a_dualdiv_clk(hw);
0228     unsigned long n1;
0229     u32 reg0, reg1;
0230 
0231     regmap_read(dualdiv_clk->regmap, CECB_CLK_CNTL_REG0, &reg0);
0232     regmap_read(dualdiv_clk->regmap, CECB_CLK_CNTL_REG0, &reg1);
0233 
0234     if (reg1 & CECB_CLK_CNTL_BYPASS_EN)
0235         return parent_rate;
0236 
0237     if (reg0 & CECB_CLK_CNTL_DUAL_EN) {
0238         unsigned long n2, m1, m2, f1, f2, p1, p2;
0239 
0240         n1 = FIELD_GET(CECB_CLK_CNTL_N1, reg0) + 1;
0241         n2 = FIELD_GET(CECB_CLK_CNTL_N2, reg0) + 1;
0242 
0243         m1 = FIELD_GET(CECB_CLK_CNTL_M1, reg1) + 1;
0244         m2 = FIELD_GET(CECB_CLK_CNTL_M1, reg1) + 1;
0245 
0246         f1 = DIV_ROUND_CLOSEST(parent_rate, n1);
0247         f2 = DIV_ROUND_CLOSEST(parent_rate, n2);
0248 
0249         p1 = DIV_ROUND_CLOSEST(100000000 * m1, f1 * (m1 + m2));
0250         p2 = DIV_ROUND_CLOSEST(100000000 * m2, f2 * (m1 + m2));
0251 
0252         return DIV_ROUND_UP(100000000, p1 + p2);
0253     }
0254 
0255     n1 = FIELD_GET(CECB_CLK_CNTL_N1, reg0) + 1;
0256 
0257     return DIV_ROUND_CLOSEST(parent_rate, n1);
0258 }
0259 
0260 static int meson_ao_cec_g12a_dualdiv_clk_enable(struct clk_hw *hw)
0261 {
0262     struct meson_ao_cec_g12a_dualdiv_clk *dualdiv_clk =
0263         hw_to_meson_ao_cec_g12a_dualdiv_clk(hw);
0264 
0265 
0266     /* Disable Input & Output */
0267     regmap_update_bits(dualdiv_clk->regmap, CECB_CLK_CNTL_REG0,
0268                CECB_CLK_CNTL_INPUT_EN | CECB_CLK_CNTL_OUTPUT_EN,
0269                0);
0270 
0271     /* Set N1 & N2 */
0272     regmap_update_bits(dualdiv_clk->regmap, CECB_CLK_CNTL_REG0,
0273                CECB_CLK_CNTL_N1,
0274                FIELD_PREP(CECB_CLK_CNTL_N1, 733 - 1));
0275 
0276     regmap_update_bits(dualdiv_clk->regmap, CECB_CLK_CNTL_REG0,
0277                CECB_CLK_CNTL_N2,
0278                FIELD_PREP(CECB_CLK_CNTL_N2, 732 - 1));
0279 
0280     /* Set M1 & M2 */
0281     regmap_update_bits(dualdiv_clk->regmap, CECB_CLK_CNTL_REG1,
0282                CECB_CLK_CNTL_M1,
0283                FIELD_PREP(CECB_CLK_CNTL_M1, 8 - 1));
0284 
0285     regmap_update_bits(dualdiv_clk->regmap, CECB_CLK_CNTL_REG1,
0286                CECB_CLK_CNTL_M2,
0287                FIELD_PREP(CECB_CLK_CNTL_M2, 11 - 1));
0288 
0289     /* Enable Dual divisor */
0290     regmap_update_bits(dualdiv_clk->regmap, CECB_CLK_CNTL_REG0,
0291                CECB_CLK_CNTL_DUAL_EN, CECB_CLK_CNTL_DUAL_EN);
0292 
0293     /* Disable divisor bypass */
0294     regmap_update_bits(dualdiv_clk->regmap, CECB_CLK_CNTL_REG1,
0295                CECB_CLK_CNTL_BYPASS_EN, 0);
0296 
0297     /* Enable Input & Output */
0298     regmap_update_bits(dualdiv_clk->regmap, CECB_CLK_CNTL_REG0,
0299                CECB_CLK_CNTL_INPUT_EN | CECB_CLK_CNTL_OUTPUT_EN,
0300                CECB_CLK_CNTL_INPUT_EN | CECB_CLK_CNTL_OUTPUT_EN);
0301 
0302     return 0;
0303 }
0304 
0305 static void meson_ao_cec_g12a_dualdiv_clk_disable(struct clk_hw *hw)
0306 {
0307     struct meson_ao_cec_g12a_dualdiv_clk *dualdiv_clk =
0308         hw_to_meson_ao_cec_g12a_dualdiv_clk(hw);
0309 
0310     regmap_update_bits(dualdiv_clk->regmap, CECB_CLK_CNTL_REG0,
0311                CECB_CLK_CNTL_INPUT_EN | CECB_CLK_CNTL_OUTPUT_EN,
0312                0);
0313 }
0314 
0315 static int meson_ao_cec_g12a_dualdiv_clk_is_enabled(struct clk_hw *hw)
0316 {
0317     struct meson_ao_cec_g12a_dualdiv_clk *dualdiv_clk =
0318         hw_to_meson_ao_cec_g12a_dualdiv_clk(hw);
0319     int val;
0320 
0321     regmap_read(dualdiv_clk->regmap, CECB_CLK_CNTL_REG0, &val);
0322 
0323     return !!(val & (CECB_CLK_CNTL_INPUT_EN | CECB_CLK_CNTL_OUTPUT_EN));
0324 }
0325 
0326 static const struct clk_ops meson_ao_cec_g12a_dualdiv_clk_ops = {
0327     .recalc_rate    = meson_ao_cec_g12a_dualdiv_clk_recalc_rate,
0328     .is_enabled = meson_ao_cec_g12a_dualdiv_clk_is_enabled,
0329     .enable     = meson_ao_cec_g12a_dualdiv_clk_enable,
0330     .disable    = meson_ao_cec_g12a_dualdiv_clk_disable,
0331 };
0332 
0333 static int meson_ao_cec_g12a_setup_clk(struct meson_ao_cec_g12a_device *ao_cec)
0334 {
0335     struct meson_ao_cec_g12a_dualdiv_clk *dualdiv_clk;
0336     struct device *dev = &ao_cec->pdev->dev;
0337     struct clk_init_data init;
0338     const char *parent_name;
0339     struct clk *clk;
0340     char *name;
0341 
0342     dualdiv_clk = devm_kzalloc(dev, sizeof(*dualdiv_clk), GFP_KERNEL);
0343     if (!dualdiv_clk)
0344         return -ENOMEM;
0345 
0346     name = kasprintf(GFP_KERNEL, "%s#dualdiv_clk", dev_name(dev));
0347     if (!name)
0348         return -ENOMEM;
0349 
0350     parent_name = __clk_get_name(ao_cec->oscin);
0351 
0352     init.name = name;
0353     init.ops = &meson_ao_cec_g12a_dualdiv_clk_ops;
0354     init.flags = 0;
0355     init.parent_names = &parent_name;
0356     init.num_parents = 1;
0357     dualdiv_clk->regmap = ao_cec->regmap;
0358     dualdiv_clk->hw.init = &init;
0359 
0360     clk = devm_clk_register(dev, &dualdiv_clk->hw);
0361     kfree(name);
0362     if (IS_ERR(clk)) {
0363         dev_err(dev, "failed to register clock\n");
0364         return PTR_ERR(clk);
0365     }
0366 
0367     ao_cec->core = clk;
0368 
0369     return 0;
0370 }
0371 
0372 static int meson_ao_cec_g12a_read(void *context, unsigned int addr,
0373                   unsigned int *data)
0374 {
0375     struct meson_ao_cec_g12a_device *ao_cec = context;
0376     u32 reg = FIELD_PREP(CECB_RW_ADDR, addr);
0377     int ret = 0;
0378 
0379     ret = regmap_write(ao_cec->regmap, CECB_RW_REG, reg);
0380     if (ret)
0381         return ret;
0382 
0383     ret = regmap_read_poll_timeout(ao_cec->regmap, CECB_RW_REG, reg,
0384                        !(reg & CECB_RW_BUS_BUSY),
0385                        5, 1000);
0386     if (ret)
0387         return ret;
0388 
0389     ret = regmap_read(ao_cec->regmap, CECB_RW_REG, &reg);
0390 
0391     *data = FIELD_GET(CECB_RW_RD_DATA, reg);
0392 
0393     return ret;
0394 }
0395 
0396 static int meson_ao_cec_g12a_write(void *context, unsigned int addr,
0397                    unsigned int data)
0398 {
0399     struct meson_ao_cec_g12a_device *ao_cec = context;
0400     u32 reg = FIELD_PREP(CECB_RW_ADDR, addr) |
0401           FIELD_PREP(CECB_RW_WR_DATA, data) |
0402           CECB_RW_WRITE_EN;
0403 
0404     return regmap_write(ao_cec->regmap, CECB_RW_REG, reg);
0405 }
0406 
0407 static const struct regmap_config meson_ao_cec_g12a_cec_regmap_conf = {
0408     .reg_bits = 8,
0409     .val_bits = 8,
0410     .reg_read = meson_ao_cec_g12a_read,
0411     .reg_write = meson_ao_cec_g12a_write,
0412     .max_register = 0xffff,
0413 };
0414 
0415 static inline void
0416 meson_ao_cec_g12a_irq_setup(struct meson_ao_cec_g12a_device *ao_cec,
0417                 bool enable)
0418 {
0419     u32 cfg = CECB_INTR_DONE | CECB_INTR_EOM | CECB_INTR_NACK |
0420           CECB_INTR_ARB_LOSS | CECB_INTR_INITIATOR_ERR |
0421           CECB_INTR_FOLLOWER_ERR;
0422 
0423     regmap_write(ao_cec->regmap, CECB_INTR_MASKN_REG,
0424              enable ? cfg : 0);
0425 }
0426 
0427 static void meson_ao_cec_g12a_irq_rx(struct meson_ao_cec_g12a_device *ao_cec)
0428 {
0429     int i, ret = 0;
0430     u32 val;
0431 
0432     ret = regmap_read(ao_cec->regmap_cec, CECB_RX_CNT, &val);
0433 
0434     ao_cec->rx_msg.len = val;
0435     if (ao_cec->rx_msg.len > CEC_MAX_MSG_SIZE)
0436         ao_cec->rx_msg.len = CEC_MAX_MSG_SIZE;
0437 
0438     for (i = 0; i < ao_cec->rx_msg.len; i++) {
0439         ret |= regmap_read(ao_cec->regmap_cec,
0440                    CECB_RX_DATA00 + i, &val);
0441 
0442         ao_cec->rx_msg.msg[i] = val & 0xff;
0443     }
0444 
0445     ret |= regmap_write(ao_cec->regmap_cec, CECB_LOCK_BUF, 0);
0446     if (ret)
0447         return;
0448 
0449     cec_received_msg(ao_cec->adap, &ao_cec->rx_msg);
0450 }
0451 
0452 static irqreturn_t meson_ao_cec_g12a_irq(int irq, void *data)
0453 {
0454     struct meson_ao_cec_g12a_device *ao_cec = data;
0455     u32 stat;
0456 
0457     regmap_read(ao_cec->regmap, CECB_INTR_STAT_REG, &stat);
0458     if (stat)
0459         return IRQ_WAKE_THREAD;
0460 
0461     return IRQ_NONE;
0462 }
0463 
0464 static irqreturn_t meson_ao_cec_g12a_irq_thread(int irq, void *data)
0465 {
0466     struct meson_ao_cec_g12a_device *ao_cec = data;
0467     u32 stat;
0468 
0469     regmap_read(ao_cec->regmap, CECB_INTR_STAT_REG, &stat);
0470     regmap_write(ao_cec->regmap, CECB_INTR_CLR_REG, stat);
0471 
0472     if (stat & CECB_INTR_DONE)
0473         cec_transmit_attempt_done(ao_cec->adap, CEC_TX_STATUS_OK);
0474 
0475     if (stat & CECB_INTR_EOM)
0476         meson_ao_cec_g12a_irq_rx(ao_cec);
0477 
0478     if (stat & CECB_INTR_NACK)
0479         cec_transmit_attempt_done(ao_cec->adap, CEC_TX_STATUS_NACK);
0480 
0481     if (stat & CECB_INTR_ARB_LOSS) {
0482         regmap_write(ao_cec->regmap_cec, CECB_TX_CNT, 0);
0483         regmap_update_bits(ao_cec->regmap_cec, CECB_CTRL,
0484                    CECB_CTRL_SEND | CECB_CTRL_TYPE, 0);
0485         cec_transmit_attempt_done(ao_cec->adap, CEC_TX_STATUS_ARB_LOST);
0486     }
0487 
0488     /* Initiator reports an error on the CEC bus */
0489     if (stat & CECB_INTR_INITIATOR_ERR)
0490         cec_transmit_attempt_done(ao_cec->adap, CEC_TX_STATUS_ERROR);
0491 
0492     /* Follower reports a receive error, just reset RX buffer */
0493     if (stat & CECB_INTR_FOLLOWER_ERR)
0494         regmap_write(ao_cec->regmap_cec, CECB_LOCK_BUF, 0);
0495 
0496     return IRQ_HANDLED;
0497 }
0498 
0499 static int
0500 meson_ao_cec_g12a_set_log_addr(struct cec_adapter *adap, u8 logical_addr)
0501 {
0502     struct meson_ao_cec_g12a_device *ao_cec = adap->priv;
0503     int ret = 0;
0504 
0505     if (logical_addr == CEC_LOG_ADDR_INVALID) {
0506         /* Assume this will allways succeed */
0507         regmap_write(ao_cec->regmap_cec, CECB_LADD_LOW, 0);
0508         regmap_write(ao_cec->regmap_cec, CECB_LADD_HIGH, 0);
0509 
0510         return 0;
0511     } else if (logical_addr < 8) {
0512         ret = regmap_update_bits(ao_cec->regmap_cec, CECB_LADD_LOW,
0513                      BIT(logical_addr),
0514                      BIT(logical_addr));
0515     } else {
0516         ret = regmap_update_bits(ao_cec->regmap_cec, CECB_LADD_HIGH,
0517                      BIT(logical_addr - 8),
0518                      BIT(logical_addr - 8));
0519     }
0520 
0521     /* Always set Broadcast/Unregistered 15 address */
0522     ret |= regmap_update_bits(ao_cec->regmap_cec, CECB_LADD_HIGH,
0523                   BIT(CEC_LOG_ADDR_UNREGISTERED - 8),
0524                   BIT(CEC_LOG_ADDR_UNREGISTERED - 8));
0525 
0526     return ret ? -EIO : 0;
0527 }
0528 
0529 static int meson_ao_cec_g12a_transmit(struct cec_adapter *adap, u8 attempts,
0530                  u32 signal_free_time, struct cec_msg *msg)
0531 {
0532     struct meson_ao_cec_g12a_device *ao_cec = adap->priv;
0533     unsigned int type;
0534     int ret = 0;
0535     u32 val;
0536     int i;
0537 
0538     /* Check if RX is in progress */
0539     ret = regmap_read(ao_cec->regmap_cec, CECB_LOCK_BUF, &val);
0540     if (ret)
0541         return ret;
0542     if (val & CECB_LOCK_BUF_EN)
0543         return -EBUSY;
0544 
0545     /* Check if TX Busy */
0546     ret = regmap_read(ao_cec->regmap_cec, CECB_CTRL, &val);
0547     if (ret)
0548         return ret;
0549     if (val & CECB_CTRL_SEND)
0550         return -EBUSY;
0551 
0552     switch (signal_free_time) {
0553     case CEC_SIGNAL_FREE_TIME_RETRY:
0554         type = CECB_CTRL_TYPE_RETRY;
0555         break;
0556     case CEC_SIGNAL_FREE_TIME_NEXT_XFER:
0557         type = CECB_CTRL_TYPE_NEXT;
0558         break;
0559     case CEC_SIGNAL_FREE_TIME_NEW_INITIATOR:
0560     default:
0561         type = CECB_CTRL_TYPE_NEW;
0562         break;
0563     }
0564 
0565     for (i = 0; i < msg->len; i++)
0566         ret |= regmap_write(ao_cec->regmap_cec, CECB_TX_DATA00 + i,
0567                     msg->msg[i]);
0568 
0569     ret |= regmap_write(ao_cec->regmap_cec, CECB_TX_CNT, msg->len);
0570     if (ret)
0571         return -EIO;
0572 
0573     ret = regmap_update_bits(ao_cec->regmap_cec, CECB_CTRL,
0574                  CECB_CTRL_SEND |
0575                  CECB_CTRL_TYPE,
0576                  CECB_CTRL_SEND |
0577                  FIELD_PREP(CECB_CTRL_TYPE, type));
0578 
0579     return ret;
0580 }
0581 
0582 static int meson_ao_cec_g12a_adap_enable(struct cec_adapter *adap, bool enable)
0583 {
0584     struct meson_ao_cec_g12a_device *ao_cec = adap->priv;
0585 
0586     meson_ao_cec_g12a_irq_setup(ao_cec, false);
0587 
0588     regmap_update_bits(ao_cec->regmap, CECB_GEN_CNTL_REG,
0589                CECB_GEN_CNTL_RESET, CECB_GEN_CNTL_RESET);
0590 
0591     if (!enable)
0592         return 0;
0593 
0594     /* Setup Filter */
0595     regmap_update_bits(ao_cec->regmap, CECB_GEN_CNTL_REG,
0596                CECB_GEN_CNTL_FILTER_TICK_SEL |
0597                CECB_GEN_CNTL_FILTER_DEL,
0598                FIELD_PREP(CECB_GEN_CNTL_FILTER_TICK_SEL,
0599                       CECB_GEN_CNTL_FILTER_TICK_1US) |
0600                FIELD_PREP(CECB_GEN_CNTL_FILTER_DEL, 7));
0601 
0602     /* Enable System Clock */
0603     regmap_update_bits(ao_cec->regmap, CECB_GEN_CNTL_REG,
0604                CECB_GEN_CNTL_SYS_CLK_EN,
0605                CECB_GEN_CNTL_SYS_CLK_EN);
0606 
0607     /* Enable gated clock (Normal mode). */
0608     regmap_update_bits(ao_cec->regmap, CECB_GEN_CNTL_REG,
0609                CECB_GEN_CNTL_CLK_CTRL_MASK,
0610                 FIELD_PREP(CECB_GEN_CNTL_CLK_CTRL_MASK,
0611                        CECB_GEN_CNTL_CLK_ENABLE));
0612 
0613     /* Release Reset */
0614     regmap_update_bits(ao_cec->regmap, CECB_GEN_CNTL_REG,
0615                CECB_GEN_CNTL_RESET, 0);
0616 
0617     if (ao_cec->data->ctrl2_setup)
0618         regmap_write(ao_cec->regmap_cec, CECB_CTRL2,
0619                  FIELD_PREP(CECB_CTRL2_RISE_DEL_MAX, 2));
0620 
0621     meson_ao_cec_g12a_irq_setup(ao_cec, true);
0622 
0623     return 0;
0624 }
0625 
0626 static const struct cec_adap_ops meson_ao_cec_g12a_ops = {
0627     .adap_enable = meson_ao_cec_g12a_adap_enable,
0628     .adap_log_addr = meson_ao_cec_g12a_set_log_addr,
0629     .adap_transmit = meson_ao_cec_g12a_transmit,
0630 };
0631 
0632 static int meson_ao_cec_g12a_probe(struct platform_device *pdev)
0633 {
0634     struct meson_ao_cec_g12a_device *ao_cec;
0635     struct device *hdmi_dev;
0636     void __iomem *base;
0637     int ret, irq;
0638 
0639     hdmi_dev = cec_notifier_parse_hdmi_phandle(&pdev->dev);
0640     if (IS_ERR(hdmi_dev))
0641         return PTR_ERR(hdmi_dev);
0642 
0643     ao_cec = devm_kzalloc(&pdev->dev, sizeof(*ao_cec), GFP_KERNEL);
0644     if (!ao_cec)
0645         return -ENOMEM;
0646 
0647     ao_cec->data = of_device_get_match_data(&pdev->dev);
0648     if (!ao_cec->data) {
0649         dev_err(&pdev->dev, "failed to get match data\n");
0650         return -ENODEV;
0651     }
0652 
0653     spin_lock_init(&ao_cec->cec_reg_lock);
0654     ao_cec->pdev = pdev;
0655 
0656     ao_cec->adap = cec_allocate_adapter(&meson_ao_cec_g12a_ops, ao_cec,
0657                         "meson_g12a_ao_cec",
0658                         CEC_CAP_DEFAULTS |
0659                         CEC_CAP_CONNECTOR_INFO,
0660                         CEC_MAX_LOG_ADDRS);
0661     if (IS_ERR(ao_cec->adap))
0662         return PTR_ERR(ao_cec->adap);
0663 
0664     ao_cec->adap->owner = THIS_MODULE;
0665 
0666     base = devm_platform_ioremap_resource(pdev, 0);
0667     if (IS_ERR(base)) {
0668         ret = PTR_ERR(base);
0669         goto out_probe_adapter;
0670     }
0671 
0672     ao_cec->regmap = devm_regmap_init_mmio(&pdev->dev, base,
0673                            &meson_ao_cec_g12a_regmap_conf);
0674     if (IS_ERR(ao_cec->regmap)) {
0675         ret = PTR_ERR(ao_cec->regmap);
0676         goto out_probe_adapter;
0677     }
0678 
0679     ao_cec->regmap_cec = devm_regmap_init(&pdev->dev, NULL, ao_cec,
0680                        &meson_ao_cec_g12a_cec_regmap_conf);
0681     if (IS_ERR(ao_cec->regmap_cec)) {
0682         ret = PTR_ERR(ao_cec->regmap_cec);
0683         goto out_probe_adapter;
0684     }
0685 
0686     irq = platform_get_irq(pdev, 0);
0687     ret = devm_request_threaded_irq(&pdev->dev, irq,
0688                     meson_ao_cec_g12a_irq,
0689                     meson_ao_cec_g12a_irq_thread,
0690                     0, NULL, ao_cec);
0691     if (ret) {
0692         dev_err(&pdev->dev, "irq request failed\n");
0693         goto out_probe_adapter;
0694     }
0695 
0696     ao_cec->oscin = devm_clk_get(&pdev->dev, "oscin");
0697     if (IS_ERR(ao_cec->oscin)) {
0698         dev_err(&pdev->dev, "oscin clock request failed\n");
0699         ret = PTR_ERR(ao_cec->oscin);
0700         goto out_probe_adapter;
0701     }
0702 
0703     ret = meson_ao_cec_g12a_setup_clk(ao_cec);
0704     if (ret)
0705         goto out_probe_adapter;
0706 
0707     ret = clk_prepare_enable(ao_cec->core);
0708     if (ret) {
0709         dev_err(&pdev->dev, "core clock enable failed\n");
0710         goto out_probe_adapter;
0711     }
0712 
0713     device_reset_optional(&pdev->dev);
0714 
0715     platform_set_drvdata(pdev, ao_cec);
0716 
0717     ao_cec->notify = cec_notifier_cec_adap_register(hdmi_dev, NULL,
0718                             ao_cec->adap);
0719     if (!ao_cec->notify) {
0720         ret = -ENOMEM;
0721         goto out_probe_core_clk;
0722     }
0723 
0724     ret = cec_register_adapter(ao_cec->adap, &pdev->dev);
0725     if (ret < 0)
0726         goto out_probe_notify;
0727 
0728     /* Setup Hardware */
0729     regmap_write(ao_cec->regmap, CECB_GEN_CNTL_REG, CECB_GEN_CNTL_RESET);
0730 
0731     return 0;
0732 
0733 out_probe_notify:
0734     cec_notifier_cec_adap_unregister(ao_cec->notify, ao_cec->adap);
0735 
0736 out_probe_core_clk:
0737     clk_disable_unprepare(ao_cec->core);
0738 
0739 out_probe_adapter:
0740     cec_delete_adapter(ao_cec->adap);
0741 
0742     dev_err(&pdev->dev, "CEC controller registration failed\n");
0743 
0744     return ret;
0745 }
0746 
0747 static int meson_ao_cec_g12a_remove(struct platform_device *pdev)
0748 {
0749     struct meson_ao_cec_g12a_device *ao_cec = platform_get_drvdata(pdev);
0750 
0751     clk_disable_unprepare(ao_cec->core);
0752 
0753     cec_notifier_cec_adap_unregister(ao_cec->notify, ao_cec->adap);
0754 
0755     cec_unregister_adapter(ao_cec->adap);
0756 
0757     return 0;
0758 }
0759 
0760 static const struct meson_ao_cec_g12a_data ao_cec_g12a_data = {
0761     .ctrl2_setup = false,
0762 };
0763 
0764 static const struct meson_ao_cec_g12a_data ao_cec_sm1_data = {
0765     .ctrl2_setup = true,
0766 };
0767 
0768 static const struct of_device_id meson_ao_cec_g12a_of_match[] = {
0769     {
0770         .compatible = "amlogic,meson-g12a-ao-cec",
0771         .data = &ao_cec_g12a_data,
0772     },
0773     {
0774         .compatible = "amlogic,meson-sm1-ao-cec",
0775         .data = &ao_cec_sm1_data,
0776     },
0777     { /* sentinel */ }
0778 };
0779 MODULE_DEVICE_TABLE(of, meson_ao_cec_g12a_of_match);
0780 
0781 static struct platform_driver meson_ao_cec_g12a_driver = {
0782     .probe   = meson_ao_cec_g12a_probe,
0783     .remove  = meson_ao_cec_g12a_remove,
0784     .driver  = {
0785         .name = "meson-ao-cec-g12a",
0786         .of_match_table = of_match_ptr(meson_ao_cec_g12a_of_match),
0787     },
0788 };
0789 
0790 module_platform_driver(meson_ao_cec_g12a_driver);
0791 
0792 MODULE_DESCRIPTION("Meson AO CEC G12A Controller driver");
0793 MODULE_AUTHOR("Neil Armstrong <narmstrong@baylibre.com>");
0794 MODULE_LICENSE("GPL");