linux/drivers/media/cec/platform/meson/ao-cec.c
<<
>>
Prefs
   1/*
   2 * Driver for Amlogic Meson AO CEC Controller
   3 *
   4 * Copyright (C) 2015 Amlogic, Inc. All rights reserved
   5 * Copyright (C) 2017 BayLibre, SAS
   6 * Author: Neil Armstrong <narmstrong@baylibre.com>
   7 *
   8 * SPDX-License-Identifier: GPL-2.0+
   9 */
  10
  11#include <linux/bitfield.h>
  12#include <linux/clk.h>
  13#include <linux/device.h>
  14#include <linux/io.h>
  15#include <linux/delay.h>
  16#include <linux/kernel.h>
  17#include <linux/module.h>
  18#include <linux/of.h>
  19#include <linux/of_platform.h>
  20#include <linux/platform_device.h>
  21#include <linux/types.h>
  22#include <linux/interrupt.h>
  23#include <linux/reset.h>
  24#include <media/cec.h>
  25#include <media/cec-notifier.h>
  26
  27/* CEC Registers */
  28
  29/*
  30 * [2:1] cntl_clk
  31 *  - 0 = Disable clk (Power-off mode)
  32 *  - 1 = Enable gated clock (Normal mode)
  33 *  - 2 = Enable free-run clk (Debug mode)
  34 */
  35#define CEC_GEN_CNTL_REG                0x00
  36
  37#define CEC_GEN_CNTL_RESET              BIT(0)
  38#define CEC_GEN_CNTL_CLK_DISABLE        0
  39#define CEC_GEN_CNTL_CLK_ENABLE         1
  40#define CEC_GEN_CNTL_CLK_ENABLE_DBG     2
  41#define CEC_GEN_CNTL_CLK_CTRL_MASK      GENMASK(2, 1)
  42
  43/*
  44 * [7:0] cec_reg_addr
  45 * [15:8] cec_reg_wrdata
  46 * [16] cec_reg_wr
  47 *  - 0 = Read
  48 *  - 1 = Write
  49 * [23] bus free
  50 * [31:24] cec_reg_rddata
  51 */
  52#define CEC_RW_REG                      0x04
  53
  54#define CEC_RW_ADDR                     GENMASK(7, 0)
  55#define CEC_RW_WR_DATA                  GENMASK(15, 8)
  56#define CEC_RW_WRITE_EN                 BIT(16)
  57#define CEC_RW_BUS_BUSY                 BIT(23)
  58#define CEC_RW_RD_DATA                  GENMASK(31, 24)
  59
  60/*
  61 * [1] tx intr
  62 * [2] rx intr
  63 */
  64#define CEC_INTR_MASKN_REG              0x08
  65#define CEC_INTR_CLR_REG                0x0c
  66#define CEC_INTR_STAT_REG               0x10
  67
  68#define CEC_INTR_TX                     BIT(1)
  69#define CEC_INTR_RX                     BIT(2)
  70
  71/* CEC Commands */
  72
  73#define CEC_TX_MSG_0_HEADER             0x00
  74#define CEC_TX_MSG_1_OPCODE             0x01
  75#define CEC_TX_MSG_2_OP1                0x02
  76#define CEC_TX_MSG_3_OP2                0x03
  77#define CEC_TX_MSG_4_OP3                0x04
  78#define CEC_TX_MSG_5_OP4                0x05
  79#define CEC_TX_MSG_6_OP5                0x06
  80#define CEC_TX_MSG_7_OP6                0x07
  81#define CEC_TX_MSG_8_OP7                0x08
  82#define CEC_TX_MSG_9_OP8                0x09
  83#define CEC_TX_MSG_A_OP9                0x0A
  84#define CEC_TX_MSG_B_OP10               0x0B
  85#define CEC_TX_MSG_C_OP11               0x0C
  86#define CEC_TX_MSG_D_OP12               0x0D
  87#define CEC_TX_MSG_E_OP13               0x0E
  88#define CEC_TX_MSG_F_OP14               0x0F
  89#define CEC_TX_MSG_LENGTH               0x10
  90#define CEC_TX_MSG_CMD                  0x11
  91#define CEC_TX_WRITE_BUF                0x12
  92#define CEC_TX_CLEAR_BUF                0x13
  93#define CEC_RX_MSG_CMD                  0x14
  94#define CEC_RX_CLEAR_BUF                0x15
  95#define CEC_LOGICAL_ADDR0               0x16
  96#define CEC_LOGICAL_ADDR1               0x17
  97#define CEC_LOGICAL_ADDR2               0x18
  98#define CEC_LOGICAL_ADDR3               0x19
  99#define CEC_LOGICAL_ADDR4               0x1A
 100#define CEC_CLOCK_DIV_H                 0x1B
 101#define CEC_CLOCK_DIV_L                 0x1C
 102#define CEC_QUIESCENT_25MS_BIT7_0       0x20
 103#define CEC_QUIESCENT_25MS_BIT11_8      0x21
 104#define CEC_STARTBITMINL2H_3MS5_BIT7_0  0x22
 105#define CEC_STARTBITMINL2H_3MS5_BIT8    0x23
 106#define CEC_STARTBITMAXL2H_3MS9_BIT7_0  0x24
 107#define CEC_STARTBITMAXL2H_3MS9_BIT8    0x25
 108#define CEC_STARTBITMINH_0MS6_BIT7_0    0x26
 109#define CEC_STARTBITMINH_0MS6_BIT8      0x27
 110#define CEC_STARTBITMAXH_1MS0_BIT7_0    0x28
 111#define CEC_STARTBITMAXH_1MS0_BIT8      0x29
 112#define CEC_STARTBITMINTOT_4MS3_BIT7_0  0x2A
 113#define CEC_STARTBITMINTOT_4MS3_BIT9_8  0x2B
 114#define CEC_STARTBITMAXTOT_4MS7_BIT7_0  0x2C
 115#define CEC_STARTBITMAXTOT_4MS7_BIT9_8  0x2D
 116#define CEC_LOGIC1MINL2H_0MS4_BIT7_0    0x2E
 117#define CEC_LOGIC1MINL2H_0MS4_BIT8      0x2F
 118#define CEC_LOGIC1MAXL2H_0MS8_BIT7_0    0x30
 119#define CEC_LOGIC1MAXL2H_0MS8_BIT8      0x31
 120#define CEC_LOGIC0MINL2H_1MS3_BIT7_0    0x32
 121#define CEC_LOGIC0MINL2H_1MS3_BIT8      0x33
 122#define CEC_LOGIC0MAXL2H_1MS7_BIT7_0    0x34
 123#define CEC_LOGIC0MAXL2H_1MS7_BIT8      0x35
 124#define CEC_LOGICMINTOTAL_2MS05_BIT7_0  0x36
 125#define CEC_LOGICMINTOTAL_2MS05_BIT9_8  0x37
 126#define CEC_LOGICMAXHIGH_2MS8_BIT7_0    0x38
 127#define CEC_LOGICMAXHIGH_2MS8_BIT8      0x39
 128#define CEC_LOGICERRLOW_3MS4_BIT7_0     0x3A
 129#define CEC_LOGICERRLOW_3MS4_BIT8       0x3B
 130#define CEC_NOMSMPPOINT_1MS05           0x3C
 131#define CEC_DELCNTR_LOGICERR            0x3E
 132#define CEC_TXTIME_17MS_BIT7_0          0x40
 133#define CEC_TXTIME_17MS_BIT10_8         0x41
 134#define CEC_TXTIME_2BIT_BIT7_0          0x42
 135#define CEC_TXTIME_2BIT_BIT10_8         0x43
 136#define CEC_TXTIME_4BIT_BIT7_0          0x44
 137#define CEC_TXTIME_4BIT_BIT10_8         0x45
 138#define CEC_STARTBITNOML2H_3MS7_BIT7_0  0x46
 139#define CEC_STARTBITNOML2H_3MS7_BIT8    0x47
 140#define CEC_STARTBITNOMH_0MS8_BIT7_0    0x48
 141#define CEC_STARTBITNOMH_0MS8_BIT8      0x49
 142#define CEC_LOGIC1NOML2H_0MS6_BIT7_0    0x4A
 143#define CEC_LOGIC1NOML2H_0MS6_BIT8      0x4B
 144#define CEC_LOGIC0NOML2H_1MS5_BIT7_0    0x4C
 145#define CEC_LOGIC0NOML2H_1MS5_BIT8      0x4D
 146#define CEC_LOGIC1NOMH_1MS8_BIT7_0      0x4E
 147#define CEC_LOGIC1NOMH_1MS8_BIT8        0x4F
 148#define CEC_LOGIC0NOMH_0MS9_BIT7_0      0x50
 149#define CEC_LOGIC0NOMH_0MS9_BIT8        0x51
 150#define CEC_LOGICERRLOW_3MS6_BIT7_0     0x52
 151#define CEC_LOGICERRLOW_3MS6_BIT8       0x53
 152#define CEC_CHKCONTENTION_0MS1          0x54
 153#define CEC_PREPARENXTBIT_0MS05_BIT7_0  0x56
 154#define CEC_PREPARENXTBIT_0MS05_BIT8    0x57
 155#define CEC_NOMSMPACKPOINT_0MS45        0x58
 156#define CEC_ACK0NOML2H_1MS5_BIT7_0      0x5A
 157#define CEC_ACK0NOML2H_1MS5_BIT8        0x5B
 158#define CEC_BUGFIX_DISABLE_0            0x60
 159#define CEC_BUGFIX_DISABLE_1            0x61
 160#define CEC_RX_MSG_0_HEADER             0x80
 161#define CEC_RX_MSG_1_OPCODE             0x81
 162#define CEC_RX_MSG_2_OP1                0x82
 163#define CEC_RX_MSG_3_OP2                0x83
 164#define CEC_RX_MSG_4_OP3                0x84
 165#define CEC_RX_MSG_5_OP4                0x85
 166#define CEC_RX_MSG_6_OP5                0x86
 167#define CEC_RX_MSG_7_OP6                0x87
 168#define CEC_RX_MSG_8_OP7                0x88
 169#define CEC_RX_MSG_9_OP8                0x89
 170#define CEC_RX_MSG_A_OP9                0x8A
 171#define CEC_RX_MSG_B_OP10               0x8B
 172#define CEC_RX_MSG_C_OP11               0x8C
 173#define CEC_RX_MSG_D_OP12               0x8D
 174#define CEC_RX_MSG_E_OP13               0x8E
 175#define CEC_RX_MSG_F_OP14               0x8F
 176#define CEC_RX_MSG_LENGTH               0x90
 177#define CEC_RX_MSG_STATUS               0x91
 178#define CEC_RX_NUM_MSG                  0x92
 179#define CEC_TX_MSG_STATUS               0x93
 180#define CEC_TX_NUM_MSG                  0x94
 181
 182
 183/* CEC_TX_MSG_CMD definition */
 184#define TX_NO_OP        0  /* No transaction */
 185#define TX_REQ_CURRENT  1  /* Transmit earliest message in buffer */
 186#define TX_ABORT        2  /* Abort transmitting earliest message */
 187#define TX_REQ_NEXT     3  /* Overwrite earliest msg, transmit next */
 188
 189/* tx_msg_status definition */
 190#define TX_IDLE         0  /* No transaction */
 191#define TX_BUSY         1  /* Transmitter is busy */
 192#define TX_DONE         2  /* Message successfully transmitted */
 193#define TX_ERROR        3  /* Message transmitted with error */
 194
 195/* rx_msg_cmd */
 196#define RX_NO_OP        0  /* No transaction */
 197#define RX_ACK_CURRENT  1  /* Read earliest message in buffer */
 198#define RX_DISABLE      2  /* Disable receiving latest message */
 199#define RX_ACK_NEXT     3  /* Clear earliest msg, read next */
 200
 201/* rx_msg_status */
 202#define RX_IDLE         0  /* No transaction */
 203#define RX_BUSY         1  /* Receiver is busy */
 204#define RX_DONE         2  /* Message has been received successfully */
 205#define RX_ERROR        3  /* Message has been received with error */
 206
 207/* RX_CLEAR_BUF options */
 208#define CLEAR_START     1
 209#define CLEAR_STOP      0
 210
 211/* CEC_LOGICAL_ADDRx options */
 212#define LOGICAL_ADDR_MASK       0xf
 213#define LOGICAL_ADDR_VALID      BIT(4)
 214#define LOGICAL_ADDR_DISABLE    0
 215
 216#define CEC_CLK_RATE            32768
 217
 218struct meson_ao_cec_device {
 219        struct platform_device          *pdev;
 220        void __iomem                    *base;
 221        struct clk                      *core;
 222        spinlock_t                      cec_reg_lock;
 223        struct cec_notifier             *notify;
 224        struct cec_adapter              *adap;
 225        struct cec_msg                  rx_msg;
 226};
 227
 228#define writel_bits_relaxed(mask, val, addr) \
 229        writel_relaxed((readl_relaxed(addr) & ~(mask)) | (val), addr)
 230
 231static inline int meson_ao_cec_wait_busy(struct meson_ao_cec_device *ao_cec)
 232{
 233        ktime_t timeout = ktime_add_us(ktime_get(), 5000);
 234
 235        while (readl_relaxed(ao_cec->base + CEC_RW_REG) & CEC_RW_BUS_BUSY) {
 236                if (ktime_compare(ktime_get(), timeout) > 0)
 237                        return -ETIMEDOUT;
 238        }
 239
 240        return 0;
 241}
 242
 243static void meson_ao_cec_read(struct meson_ao_cec_device *ao_cec,
 244                             unsigned long address, u8 *data,
 245                             int *res)
 246{
 247        unsigned long flags;
 248        u32 reg = FIELD_PREP(CEC_RW_ADDR, address);
 249        int ret = 0;
 250
 251        if (res && *res)
 252                return;
 253
 254        spin_lock_irqsave(&ao_cec->cec_reg_lock, flags);
 255
 256        ret = meson_ao_cec_wait_busy(ao_cec);
 257        if (ret)
 258                goto read_out;
 259
 260        writel_relaxed(reg, ao_cec->base + CEC_RW_REG);
 261
 262        ret = meson_ao_cec_wait_busy(ao_cec);
 263        if (ret)
 264                goto read_out;
 265
 266        *data = FIELD_GET(CEC_RW_RD_DATA,
 267                          readl_relaxed(ao_cec->base + CEC_RW_REG));
 268
 269read_out:
 270        spin_unlock_irqrestore(&ao_cec->cec_reg_lock, flags);
 271
 272        if (res)
 273                *res = ret;
 274}
 275
 276static void meson_ao_cec_write(struct meson_ao_cec_device *ao_cec,
 277                               unsigned long address, u8 data,
 278                               int *res)
 279{
 280        unsigned long flags;
 281        u32 reg = FIELD_PREP(CEC_RW_ADDR, address) |
 282                  FIELD_PREP(CEC_RW_WR_DATA, data) |
 283                  CEC_RW_WRITE_EN;
 284        int ret = 0;
 285
 286        if (res && *res)
 287                return;
 288
 289        spin_lock_irqsave(&ao_cec->cec_reg_lock, flags);
 290
 291        ret = meson_ao_cec_wait_busy(ao_cec);
 292        if (ret)
 293                goto write_out;
 294
 295        writel_relaxed(reg, ao_cec->base + CEC_RW_REG);
 296
 297write_out:
 298        spin_unlock_irqrestore(&ao_cec->cec_reg_lock, flags);
 299
 300        if (res)
 301                *res = ret;
 302}
 303
 304static inline void meson_ao_cec_irq_setup(struct meson_ao_cec_device *ao_cec,
 305                                      bool enable)
 306{
 307        u32 cfg = CEC_INTR_TX | CEC_INTR_RX;
 308
 309        writel_bits_relaxed(cfg, enable ? cfg : 0,
 310                            ao_cec->base + CEC_INTR_MASKN_REG);
 311}
 312
 313static inline int meson_ao_cec_clear(struct meson_ao_cec_device *ao_cec)
 314{
 315        int ret = 0;
 316
 317        meson_ao_cec_write(ao_cec, CEC_RX_MSG_CMD, RX_DISABLE, &ret);
 318        meson_ao_cec_write(ao_cec, CEC_TX_MSG_CMD, TX_ABORT, &ret);
 319        meson_ao_cec_write(ao_cec, CEC_RX_CLEAR_BUF, 1, &ret);
 320        meson_ao_cec_write(ao_cec, CEC_TX_CLEAR_BUF, 1, &ret);
 321        if (ret)
 322                return ret;
 323
 324        udelay(100);
 325
 326        meson_ao_cec_write(ao_cec, CEC_RX_CLEAR_BUF, 0, &ret);
 327        meson_ao_cec_write(ao_cec, CEC_TX_CLEAR_BUF, 0, &ret);
 328        if (ret)
 329                return ret;
 330
 331        udelay(100);
 332
 333        meson_ao_cec_write(ao_cec, CEC_RX_MSG_CMD, RX_NO_OP, &ret);
 334        meson_ao_cec_write(ao_cec, CEC_TX_MSG_CMD, TX_NO_OP, &ret);
 335
 336        return ret;
 337}
 338
 339static int meson_ao_cec_arbit_bit_time_set(struct meson_ao_cec_device *ao_cec,
 340                                           unsigned int bit_set,
 341                                           unsigned int time_set)
 342{
 343        int ret = 0;
 344
 345        switch (bit_set) {
 346        case CEC_SIGNAL_FREE_TIME_RETRY:
 347                meson_ao_cec_write(ao_cec, CEC_TXTIME_4BIT_BIT7_0,
 348                                   time_set & 0xff, &ret);
 349                meson_ao_cec_write(ao_cec, CEC_TXTIME_4BIT_BIT10_8,
 350                                   (time_set >> 8) & 0x7, &ret);
 351                break;
 352
 353        case CEC_SIGNAL_FREE_TIME_NEW_INITIATOR:
 354                meson_ao_cec_write(ao_cec, CEC_TXTIME_2BIT_BIT7_0,
 355                                   time_set & 0xff, &ret);
 356                meson_ao_cec_write(ao_cec, CEC_TXTIME_2BIT_BIT10_8,
 357                                   (time_set >> 8) & 0x7, &ret);
 358                break;
 359
 360        case CEC_SIGNAL_FREE_TIME_NEXT_XFER:
 361                meson_ao_cec_write(ao_cec, CEC_TXTIME_17MS_BIT7_0,
 362                                   time_set & 0xff, &ret);
 363                meson_ao_cec_write(ao_cec, CEC_TXTIME_17MS_BIT10_8,
 364                                   (time_set >> 8) & 0x7, &ret);
 365                break;
 366        }
 367
 368        return ret;
 369}
 370
 371static irqreturn_t meson_ao_cec_irq(int irq, void *data)
 372{
 373        struct meson_ao_cec_device *ao_cec = data;
 374        u32 stat = readl_relaxed(ao_cec->base + CEC_INTR_STAT_REG);
 375
 376        if (stat)
 377                return IRQ_WAKE_THREAD;
 378
 379        return IRQ_NONE;
 380}
 381
 382static void meson_ao_cec_irq_tx(struct meson_ao_cec_device *ao_cec)
 383{
 384        unsigned long tx_status = 0;
 385        u8 stat;
 386        int ret = 0;
 387
 388        meson_ao_cec_read(ao_cec, CEC_TX_MSG_STATUS, &stat, &ret);
 389        if (ret)
 390                goto tx_reg_err;
 391
 392        switch (stat) {
 393        case TX_DONE:
 394                tx_status = CEC_TX_STATUS_OK;
 395                break;
 396
 397        case TX_BUSY:
 398                tx_status = CEC_TX_STATUS_ARB_LOST;
 399                break;
 400
 401        case TX_IDLE:
 402                tx_status = CEC_TX_STATUS_LOW_DRIVE;
 403                break;
 404
 405        case TX_ERROR:
 406        default:
 407                tx_status = CEC_TX_STATUS_NACK;
 408                break;
 409        }
 410
 411        /* Clear Interruption */
 412        writel_relaxed(CEC_INTR_TX, ao_cec->base + CEC_INTR_CLR_REG);
 413
 414        /* Stop TX */
 415        meson_ao_cec_write(ao_cec, CEC_TX_MSG_CMD, TX_NO_OP, &ret);
 416        if (ret)
 417                goto tx_reg_err;
 418
 419        cec_transmit_attempt_done(ao_cec->adap, tx_status);
 420        return;
 421
 422tx_reg_err:
 423        cec_transmit_attempt_done(ao_cec->adap, CEC_TX_STATUS_ERROR);
 424}
 425
 426static void meson_ao_cec_irq_rx(struct meson_ao_cec_device *ao_cec)
 427{
 428        int i, ret = 0;
 429        u8 reg;
 430
 431        meson_ao_cec_read(ao_cec, CEC_RX_MSG_STATUS, &reg, &ret);
 432        if (reg != RX_DONE)
 433                goto rx_out;
 434
 435        meson_ao_cec_read(ao_cec, CEC_RX_NUM_MSG, &reg, &ret);
 436        if (reg != 1)
 437                goto rx_out;
 438
 439        meson_ao_cec_read(ao_cec, CEC_RX_MSG_LENGTH, &reg, &ret);
 440
 441        ao_cec->rx_msg.len = reg + 1;
 442        if (ao_cec->rx_msg.len > CEC_MAX_MSG_SIZE)
 443                ao_cec->rx_msg.len = CEC_MAX_MSG_SIZE;
 444
 445        for (i = 0; i < ao_cec->rx_msg.len; i++) {
 446                u8 byte;
 447
 448                meson_ao_cec_read(ao_cec, CEC_RX_MSG_0_HEADER + i, &byte, &ret);
 449
 450                ao_cec->rx_msg.msg[i] = byte;
 451        }
 452
 453        if (ret)
 454                goto rx_out;
 455
 456        cec_received_msg(ao_cec->adap, &ao_cec->rx_msg);
 457
 458rx_out:
 459        /* Clear Interruption */
 460        writel_relaxed(CEC_INTR_RX, ao_cec->base + CEC_INTR_CLR_REG);
 461
 462        /* Ack RX message */
 463        meson_ao_cec_write(ao_cec, CEC_RX_MSG_CMD, RX_ACK_CURRENT, &ret);
 464        meson_ao_cec_write(ao_cec, CEC_RX_MSG_CMD, RX_NO_OP, &ret);
 465
 466        /* Clear RX buffer */
 467        meson_ao_cec_write(ao_cec, CEC_RX_CLEAR_BUF, CLEAR_START, &ret);
 468        meson_ao_cec_write(ao_cec, CEC_RX_CLEAR_BUF, CLEAR_STOP, &ret);
 469}
 470
 471static irqreturn_t meson_ao_cec_irq_thread(int irq, void *data)
 472{
 473        struct meson_ao_cec_device *ao_cec = data;
 474        u32 stat = readl_relaxed(ao_cec->base + CEC_INTR_STAT_REG);
 475
 476        if (stat & CEC_INTR_TX)
 477                meson_ao_cec_irq_tx(ao_cec);
 478
 479        meson_ao_cec_irq_rx(ao_cec);
 480
 481        return IRQ_HANDLED;
 482}
 483
 484static int meson_ao_cec_set_log_addr(struct cec_adapter *adap, u8 logical_addr)
 485{
 486        struct meson_ao_cec_device *ao_cec = adap->priv;
 487        int ret = 0;
 488
 489        meson_ao_cec_write(ao_cec, CEC_LOGICAL_ADDR0,
 490                           LOGICAL_ADDR_DISABLE, &ret);
 491        if (ret)
 492                return ret;
 493
 494        ret = meson_ao_cec_clear(ao_cec);
 495        if (ret)
 496                return ret;
 497
 498        if (logical_addr == CEC_LOG_ADDR_INVALID)
 499                return 0;
 500
 501        meson_ao_cec_write(ao_cec, CEC_LOGICAL_ADDR0,
 502                           logical_addr & LOGICAL_ADDR_MASK, &ret);
 503        if (ret)
 504                return ret;
 505
 506        udelay(100);
 507
 508        meson_ao_cec_write(ao_cec, CEC_LOGICAL_ADDR0,
 509                           (logical_addr & LOGICAL_ADDR_MASK) |
 510                           LOGICAL_ADDR_VALID, &ret);
 511
 512        return ret;
 513}
 514
 515static int meson_ao_cec_transmit(struct cec_adapter *adap, u8 attempts,
 516                                 u32 signal_free_time, struct cec_msg *msg)
 517{
 518        struct meson_ao_cec_device *ao_cec = adap->priv;
 519        int i, ret = 0;
 520        u8 reg;
 521
 522        meson_ao_cec_read(ao_cec, CEC_TX_MSG_STATUS, &reg, &ret);
 523        if (ret)
 524                return ret;
 525
 526        if (reg == TX_BUSY) {
 527                dev_dbg(&ao_cec->pdev->dev, "%s: busy TX: aborting\n",
 528                        __func__);
 529                meson_ao_cec_write(ao_cec, CEC_TX_MSG_CMD, TX_ABORT, &ret);
 530        }
 531
 532        for (i = 0; i < msg->len; i++) {
 533                meson_ao_cec_write(ao_cec, CEC_TX_MSG_0_HEADER + i,
 534                                   msg->msg[i], &ret);
 535        }
 536
 537        meson_ao_cec_write(ao_cec, CEC_TX_MSG_LENGTH, msg->len - 1, &ret);
 538        meson_ao_cec_write(ao_cec, CEC_TX_MSG_CMD, TX_REQ_CURRENT, &ret);
 539
 540        return ret;
 541}
 542
 543static int meson_ao_cec_adap_enable(struct cec_adapter *adap, bool enable)
 544{
 545        struct meson_ao_cec_device *ao_cec = adap->priv;
 546        int ret;
 547
 548        meson_ao_cec_irq_setup(ao_cec, false);
 549
 550        writel_bits_relaxed(CEC_GEN_CNTL_RESET, CEC_GEN_CNTL_RESET,
 551                            ao_cec->base + CEC_GEN_CNTL_REG);
 552
 553        if (!enable)
 554                return 0;
 555
 556        /* Enable gated clock (Normal mode). */
 557        writel_bits_relaxed(CEC_GEN_CNTL_CLK_CTRL_MASK,
 558                            FIELD_PREP(CEC_GEN_CNTL_CLK_CTRL_MASK,
 559                                       CEC_GEN_CNTL_CLK_ENABLE),
 560                            ao_cec->base + CEC_GEN_CNTL_REG);
 561
 562        udelay(100);
 563
 564        /* Release Reset */
 565        writel_bits_relaxed(CEC_GEN_CNTL_RESET, 0,
 566                            ao_cec->base + CEC_GEN_CNTL_REG);
 567
 568        /* Clear buffers */
 569        ret = meson_ao_cec_clear(ao_cec);
 570        if (ret)
 571                return ret;
 572
 573        /* CEC arbitration 3/5/7 bit time set. */
 574        ret = meson_ao_cec_arbit_bit_time_set(ao_cec,
 575                                        CEC_SIGNAL_FREE_TIME_RETRY,
 576                                        0x118);
 577        if (ret)
 578                return ret;
 579        ret = meson_ao_cec_arbit_bit_time_set(ao_cec,
 580                                        CEC_SIGNAL_FREE_TIME_NEW_INITIATOR,
 581                                        0x000);
 582        if (ret)
 583                return ret;
 584        ret = meson_ao_cec_arbit_bit_time_set(ao_cec,
 585                                        CEC_SIGNAL_FREE_TIME_NEXT_XFER,
 586                                        0x2aa);
 587        if (ret)
 588                return ret;
 589
 590        meson_ao_cec_irq_setup(ao_cec, true);
 591
 592        return 0;
 593}
 594
 595static const struct cec_adap_ops meson_ao_cec_ops = {
 596        .adap_enable = meson_ao_cec_adap_enable,
 597        .adap_log_addr = meson_ao_cec_set_log_addr,
 598        .adap_transmit = meson_ao_cec_transmit,
 599};
 600
 601static int meson_ao_cec_probe(struct platform_device *pdev)
 602{
 603        struct meson_ao_cec_device *ao_cec;
 604        struct device *hdmi_dev;
 605        struct resource *res;
 606        int ret, irq;
 607
 608        hdmi_dev = cec_notifier_parse_hdmi_phandle(&pdev->dev);
 609
 610        if (IS_ERR(hdmi_dev))
 611                return PTR_ERR(hdmi_dev);
 612
 613        ao_cec = devm_kzalloc(&pdev->dev, sizeof(*ao_cec), GFP_KERNEL);
 614        if (!ao_cec)
 615                return -ENOMEM;
 616
 617        spin_lock_init(&ao_cec->cec_reg_lock);
 618
 619        ao_cec->adap = cec_allocate_adapter(&meson_ao_cec_ops, ao_cec,
 620                                            "meson_ao_cec",
 621                                            CEC_CAP_DEFAULTS |
 622                                            CEC_CAP_CONNECTOR_INFO,
 623                                            1); /* Use 1 for now */
 624        if (IS_ERR(ao_cec->adap))
 625                return PTR_ERR(ao_cec->adap);
 626
 627        ao_cec->adap->owner = THIS_MODULE;
 628
 629        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 630        ao_cec->base = devm_ioremap_resource(&pdev->dev, res);
 631        if (IS_ERR(ao_cec->base)) {
 632                ret = PTR_ERR(ao_cec->base);
 633                goto out_probe_adapter;
 634        }
 635
 636        irq = platform_get_irq(pdev, 0);
 637        ret = devm_request_threaded_irq(&pdev->dev, irq,
 638                                        meson_ao_cec_irq,
 639                                        meson_ao_cec_irq_thread,
 640                                        0, NULL, ao_cec);
 641        if (ret) {
 642                dev_err(&pdev->dev, "irq request failed\n");
 643                goto out_probe_adapter;
 644        }
 645
 646        ao_cec->core = devm_clk_get(&pdev->dev, "core");
 647        if (IS_ERR(ao_cec->core)) {
 648                dev_err(&pdev->dev, "core clock request failed\n");
 649                ret = PTR_ERR(ao_cec->core);
 650                goto out_probe_adapter;
 651        }
 652
 653        ret = clk_prepare_enable(ao_cec->core);
 654        if (ret) {
 655                dev_err(&pdev->dev, "core clock enable failed\n");
 656                goto out_probe_adapter;
 657        }
 658
 659        ret = clk_set_rate(ao_cec->core, CEC_CLK_RATE);
 660        if (ret) {
 661                dev_err(&pdev->dev, "core clock set rate failed\n");
 662                goto out_probe_clk;
 663        }
 664
 665        device_reset_optional(&pdev->dev);
 666
 667        ao_cec->pdev = pdev;
 668        platform_set_drvdata(pdev, ao_cec);
 669
 670        ao_cec->notify = cec_notifier_cec_adap_register(hdmi_dev, NULL,
 671                                                        ao_cec->adap);
 672        if (!ao_cec->notify) {
 673                ret = -ENOMEM;
 674                goto out_probe_clk;
 675        }
 676
 677        ret = cec_register_adapter(ao_cec->adap, &pdev->dev);
 678        if (ret < 0)
 679                goto out_probe_notify;
 680
 681        /* Setup Hardware */
 682        writel_relaxed(CEC_GEN_CNTL_RESET,
 683                       ao_cec->base + CEC_GEN_CNTL_REG);
 684
 685        return 0;
 686
 687out_probe_notify:
 688        cec_notifier_cec_adap_unregister(ao_cec->notify, ao_cec->adap);
 689
 690out_probe_clk:
 691        clk_disable_unprepare(ao_cec->core);
 692
 693out_probe_adapter:
 694        cec_delete_adapter(ao_cec->adap);
 695
 696        dev_err(&pdev->dev, "CEC controller registration failed\n");
 697
 698        return ret;
 699}
 700
 701static int meson_ao_cec_remove(struct platform_device *pdev)
 702{
 703        struct meson_ao_cec_device *ao_cec = platform_get_drvdata(pdev);
 704
 705        clk_disable_unprepare(ao_cec->core);
 706
 707        cec_notifier_cec_adap_unregister(ao_cec->notify, ao_cec->adap);
 708        cec_unregister_adapter(ao_cec->adap);
 709
 710        return 0;
 711}
 712
 713static const struct of_device_id meson_ao_cec_of_match[] = {
 714        { .compatible = "amlogic,meson-gx-ao-cec", },
 715        { /* sentinel */ }
 716};
 717MODULE_DEVICE_TABLE(of, meson_ao_cec_of_match);
 718
 719static struct platform_driver meson_ao_cec_driver = {
 720        .probe   = meson_ao_cec_probe,
 721        .remove  = meson_ao_cec_remove,
 722        .driver  = {
 723                .name = "meson-ao-cec",
 724                .of_match_table = of_match_ptr(meson_ao_cec_of_match),
 725        },
 726};
 727
 728module_platform_driver(meson_ao_cec_driver);
 729
 730MODULE_DESCRIPTION("Meson AO CEC Controller driver");
 731MODULE_AUTHOR("Neil Armstrong <narmstrong@baylibre.com>");
 732MODULE_LICENSE("GPL");
 733