cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

ao-cec.c (18642B)


      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	int ret, irq;
    606
    607	hdmi_dev = cec_notifier_parse_hdmi_phandle(&pdev->dev);
    608
    609	if (IS_ERR(hdmi_dev))
    610		return PTR_ERR(hdmi_dev);
    611
    612	ao_cec = devm_kzalloc(&pdev->dev, sizeof(*ao_cec), GFP_KERNEL);
    613	if (!ao_cec)
    614		return -ENOMEM;
    615
    616	spin_lock_init(&ao_cec->cec_reg_lock);
    617
    618	ao_cec->adap = cec_allocate_adapter(&meson_ao_cec_ops, ao_cec,
    619					    "meson_ao_cec",
    620					    CEC_CAP_DEFAULTS |
    621					    CEC_CAP_CONNECTOR_INFO,
    622					    1); /* Use 1 for now */
    623	if (IS_ERR(ao_cec->adap))
    624		return PTR_ERR(ao_cec->adap);
    625
    626	ao_cec->adap->owner = THIS_MODULE;
    627
    628	ao_cec->base = devm_platform_ioremap_resource(pdev, 0);
    629	if (IS_ERR(ao_cec->base)) {
    630		ret = PTR_ERR(ao_cec->base);
    631		goto out_probe_adapter;
    632	}
    633
    634	irq = platform_get_irq(pdev, 0);
    635	ret = devm_request_threaded_irq(&pdev->dev, irq,
    636					meson_ao_cec_irq,
    637					meson_ao_cec_irq_thread,
    638					0, NULL, ao_cec);
    639	if (ret) {
    640		dev_err(&pdev->dev, "irq request failed\n");
    641		goto out_probe_adapter;
    642	}
    643
    644	ao_cec->core = devm_clk_get(&pdev->dev, "core");
    645	if (IS_ERR(ao_cec->core)) {
    646		dev_err(&pdev->dev, "core clock request failed\n");
    647		ret = PTR_ERR(ao_cec->core);
    648		goto out_probe_adapter;
    649	}
    650
    651	ret = clk_prepare_enable(ao_cec->core);
    652	if (ret) {
    653		dev_err(&pdev->dev, "core clock enable failed\n");
    654		goto out_probe_adapter;
    655	}
    656
    657	ret = clk_set_rate(ao_cec->core, CEC_CLK_RATE);
    658	if (ret) {
    659		dev_err(&pdev->dev, "core clock set rate failed\n");
    660		goto out_probe_clk;
    661	}
    662
    663	device_reset_optional(&pdev->dev);
    664
    665	ao_cec->pdev = pdev;
    666	platform_set_drvdata(pdev, ao_cec);
    667
    668	ao_cec->notify = cec_notifier_cec_adap_register(hdmi_dev, NULL,
    669							ao_cec->adap);
    670	if (!ao_cec->notify) {
    671		ret = -ENOMEM;
    672		goto out_probe_clk;
    673	}
    674
    675	ret = cec_register_adapter(ao_cec->adap, &pdev->dev);
    676	if (ret < 0)
    677		goto out_probe_notify;
    678
    679	/* Setup Hardware */
    680	writel_relaxed(CEC_GEN_CNTL_RESET,
    681		       ao_cec->base + CEC_GEN_CNTL_REG);
    682
    683	return 0;
    684
    685out_probe_notify:
    686	cec_notifier_cec_adap_unregister(ao_cec->notify, ao_cec->adap);
    687
    688out_probe_clk:
    689	clk_disable_unprepare(ao_cec->core);
    690
    691out_probe_adapter:
    692	cec_delete_adapter(ao_cec->adap);
    693
    694	dev_err(&pdev->dev, "CEC controller registration failed\n");
    695
    696	return ret;
    697}
    698
    699static int meson_ao_cec_remove(struct platform_device *pdev)
    700{
    701	struct meson_ao_cec_device *ao_cec = platform_get_drvdata(pdev);
    702
    703	clk_disable_unprepare(ao_cec->core);
    704
    705	cec_notifier_cec_adap_unregister(ao_cec->notify, ao_cec->adap);
    706	cec_unregister_adapter(ao_cec->adap);
    707
    708	return 0;
    709}
    710
    711static const struct of_device_id meson_ao_cec_of_match[] = {
    712	{ .compatible = "amlogic,meson-gx-ao-cec", },
    713	{ /* sentinel */ }
    714};
    715MODULE_DEVICE_TABLE(of, meson_ao_cec_of_match);
    716
    717static struct platform_driver meson_ao_cec_driver = {
    718	.probe   = meson_ao_cec_probe,
    719	.remove  = meson_ao_cec_remove,
    720	.driver  = {
    721		.name = "meson-ao-cec",
    722		.of_match_table = of_match_ptr(meson_ao_cec_of_match),
    723	},
    724};
    725
    726module_platform_driver(meson_ao_cec_driver);
    727
    728MODULE_DESCRIPTION("Meson AO CEC Controller driver");
    729MODULE_AUTHOR("Neil Armstrong <narmstrong@baylibre.com>");
    730MODULE_LICENSE("GPL");