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