linux/drivers/media/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#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
 168struct 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
 180static 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
 205struct 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
 213static unsigned long
 214meson_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
 251static 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
 296static 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
 306static 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
 317static 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
 324static 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
 363static 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
 387read_out:
 388        spin_unlock_irqrestore(&ao_cec->cec_reg_lock, flags);
 389
 390        return ret;
 391}
 392
 393static 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
 412static 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
 421static inline void
 422meson_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
 433static 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
 458static 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
 470static 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
 505static int
 506meson_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
 535static 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
 588static 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
 628static 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
 634static 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
 733out_probe_core_clk:
 734        clk_disable_unprepare(ao_cec->core);
 735
 736out_probe_adapter:
 737        cec_delete_adapter(ao_cec->adap);
 738
 739out_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
 747static 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
 760static const struct of_device_id meson_ao_cec_g12a_of_match[] = {
 761        { .compatible = "amlogic,meson-g12a-ao-cec", },
 762        { /* sentinel */ }
 763};
 764MODULE_DEVICE_TABLE(of, meson_ao_cec_g12a_of_match);
 765
 766static 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
 775module_platform_driver(meson_ao_cec_g12a_driver);
 776
 777MODULE_DESCRIPTION("Meson AO CEC G12A Controller driver");
 778MODULE_AUTHOR("Neil Armstrong <narmstrong@baylibre.com>");
 779MODULE_LICENSE("GPL");
 780