root/drivers/media/platform/meson/ao-cec-g12a.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. meson_ao_cec_g12a_dualdiv_clk_recalc_rate
  2. meson_ao_cec_g12a_dualdiv_clk_enable
  3. meson_ao_cec_g12a_dualdiv_clk_disable
  4. meson_ao_cec_g12a_dualdiv_clk_is_enabled
  5. meson_ao_cec_g12a_setup_clk
  6. meson_ao_cec_g12a_read
  7. meson_ao_cec_g12a_write
  8. meson_ao_cec_g12a_irq_setup
  9. meson_ao_cec_g12a_irq_rx
  10. meson_ao_cec_g12a_irq
  11. meson_ao_cec_g12a_irq_thread
  12. meson_ao_cec_g12a_set_log_addr
  13. meson_ao_cec_g12a_transmit
  14. meson_ao_cec_g12a_adap_enable
  15. meson_ao_cec_g12a_probe
  16. meson_ao_cec_g12a_remove

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

/* [<][>][^][v][top][bottom][index][help] */