0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <linux/bitfield.h>
0012 #include <linux/clk.h>
0013 #include <linux/device.h>
0014 #include <linux/io.h>
0015 #include <linux/delay.h>
0016 #include <linux/kernel.h>
0017 #include <linux/module.h>
0018 #include <linux/of.h>
0019 #include <linux/of_platform.h>
0020 #include <linux/platform_device.h>
0021 #include <linux/types.h>
0022 #include <linux/interrupt.h>
0023 #include <linux/reset.h>
0024 #include <media/cec.h>
0025 #include <media/cec-notifier.h>
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035 #define CEC_GEN_CNTL_REG 0x00
0036
0037 #define CEC_GEN_CNTL_RESET BIT(0)
0038 #define CEC_GEN_CNTL_CLK_DISABLE 0
0039 #define CEC_GEN_CNTL_CLK_ENABLE 1
0040 #define CEC_GEN_CNTL_CLK_ENABLE_DBG 2
0041 #define CEC_GEN_CNTL_CLK_CTRL_MASK GENMASK(2, 1)
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052 #define CEC_RW_REG 0x04
0053
0054 #define CEC_RW_ADDR GENMASK(7, 0)
0055 #define CEC_RW_WR_DATA GENMASK(15, 8)
0056 #define CEC_RW_WRITE_EN BIT(16)
0057 #define CEC_RW_BUS_BUSY BIT(23)
0058 #define CEC_RW_RD_DATA GENMASK(31, 24)
0059
0060
0061
0062
0063
0064 #define CEC_INTR_MASKN_REG 0x08
0065 #define CEC_INTR_CLR_REG 0x0c
0066 #define CEC_INTR_STAT_REG 0x10
0067
0068 #define CEC_INTR_TX BIT(1)
0069 #define CEC_INTR_RX BIT(2)
0070
0071
0072
0073 #define CEC_TX_MSG_0_HEADER 0x00
0074 #define CEC_TX_MSG_1_OPCODE 0x01
0075 #define CEC_TX_MSG_2_OP1 0x02
0076 #define CEC_TX_MSG_3_OP2 0x03
0077 #define CEC_TX_MSG_4_OP3 0x04
0078 #define CEC_TX_MSG_5_OP4 0x05
0079 #define CEC_TX_MSG_6_OP5 0x06
0080 #define CEC_TX_MSG_7_OP6 0x07
0081 #define CEC_TX_MSG_8_OP7 0x08
0082 #define CEC_TX_MSG_9_OP8 0x09
0083 #define CEC_TX_MSG_A_OP9 0x0A
0084 #define CEC_TX_MSG_B_OP10 0x0B
0085 #define CEC_TX_MSG_C_OP11 0x0C
0086 #define CEC_TX_MSG_D_OP12 0x0D
0087 #define CEC_TX_MSG_E_OP13 0x0E
0088 #define CEC_TX_MSG_F_OP14 0x0F
0089 #define CEC_TX_MSG_LENGTH 0x10
0090 #define CEC_TX_MSG_CMD 0x11
0091 #define CEC_TX_WRITE_BUF 0x12
0092 #define CEC_TX_CLEAR_BUF 0x13
0093 #define CEC_RX_MSG_CMD 0x14
0094 #define CEC_RX_CLEAR_BUF 0x15
0095 #define CEC_LOGICAL_ADDR0 0x16
0096 #define CEC_LOGICAL_ADDR1 0x17
0097 #define CEC_LOGICAL_ADDR2 0x18
0098 #define CEC_LOGICAL_ADDR3 0x19
0099 #define CEC_LOGICAL_ADDR4 0x1A
0100 #define CEC_CLOCK_DIV_H 0x1B
0101 #define CEC_CLOCK_DIV_L 0x1C
0102 #define CEC_QUIESCENT_25MS_BIT7_0 0x20
0103 #define CEC_QUIESCENT_25MS_BIT11_8 0x21
0104 #define CEC_STARTBITMINL2H_3MS5_BIT7_0 0x22
0105 #define CEC_STARTBITMINL2H_3MS5_BIT8 0x23
0106 #define CEC_STARTBITMAXL2H_3MS9_BIT7_0 0x24
0107 #define CEC_STARTBITMAXL2H_3MS9_BIT8 0x25
0108 #define CEC_STARTBITMINH_0MS6_BIT7_0 0x26
0109 #define CEC_STARTBITMINH_0MS6_BIT8 0x27
0110 #define CEC_STARTBITMAXH_1MS0_BIT7_0 0x28
0111 #define CEC_STARTBITMAXH_1MS0_BIT8 0x29
0112 #define CEC_STARTBITMINTOT_4MS3_BIT7_0 0x2A
0113 #define CEC_STARTBITMINTOT_4MS3_BIT9_8 0x2B
0114 #define CEC_STARTBITMAXTOT_4MS7_BIT7_0 0x2C
0115 #define CEC_STARTBITMAXTOT_4MS7_BIT9_8 0x2D
0116 #define CEC_LOGIC1MINL2H_0MS4_BIT7_0 0x2E
0117 #define CEC_LOGIC1MINL2H_0MS4_BIT8 0x2F
0118 #define CEC_LOGIC1MAXL2H_0MS8_BIT7_0 0x30
0119 #define CEC_LOGIC1MAXL2H_0MS8_BIT8 0x31
0120 #define CEC_LOGIC0MINL2H_1MS3_BIT7_0 0x32
0121 #define CEC_LOGIC0MINL2H_1MS3_BIT8 0x33
0122 #define CEC_LOGIC0MAXL2H_1MS7_BIT7_0 0x34
0123 #define CEC_LOGIC0MAXL2H_1MS7_BIT8 0x35
0124 #define CEC_LOGICMINTOTAL_2MS05_BIT7_0 0x36
0125 #define CEC_LOGICMINTOTAL_2MS05_BIT9_8 0x37
0126 #define CEC_LOGICMAXHIGH_2MS8_BIT7_0 0x38
0127 #define CEC_LOGICMAXHIGH_2MS8_BIT8 0x39
0128 #define CEC_LOGICERRLOW_3MS4_BIT7_0 0x3A
0129 #define CEC_LOGICERRLOW_3MS4_BIT8 0x3B
0130 #define CEC_NOMSMPPOINT_1MS05 0x3C
0131 #define CEC_DELCNTR_LOGICERR 0x3E
0132 #define CEC_TXTIME_17MS_BIT7_0 0x40
0133 #define CEC_TXTIME_17MS_BIT10_8 0x41
0134 #define CEC_TXTIME_2BIT_BIT7_0 0x42
0135 #define CEC_TXTIME_2BIT_BIT10_8 0x43
0136 #define CEC_TXTIME_4BIT_BIT7_0 0x44
0137 #define CEC_TXTIME_4BIT_BIT10_8 0x45
0138 #define CEC_STARTBITNOML2H_3MS7_BIT7_0 0x46
0139 #define CEC_STARTBITNOML2H_3MS7_BIT8 0x47
0140 #define CEC_STARTBITNOMH_0MS8_BIT7_0 0x48
0141 #define CEC_STARTBITNOMH_0MS8_BIT8 0x49
0142 #define CEC_LOGIC1NOML2H_0MS6_BIT7_0 0x4A
0143 #define CEC_LOGIC1NOML2H_0MS6_BIT8 0x4B
0144 #define CEC_LOGIC0NOML2H_1MS5_BIT7_0 0x4C
0145 #define CEC_LOGIC0NOML2H_1MS5_BIT8 0x4D
0146 #define CEC_LOGIC1NOMH_1MS8_BIT7_0 0x4E
0147 #define CEC_LOGIC1NOMH_1MS8_BIT8 0x4F
0148 #define CEC_LOGIC0NOMH_0MS9_BIT7_0 0x50
0149 #define CEC_LOGIC0NOMH_0MS9_BIT8 0x51
0150 #define CEC_LOGICERRLOW_3MS6_BIT7_0 0x52
0151 #define CEC_LOGICERRLOW_3MS6_BIT8 0x53
0152 #define CEC_CHKCONTENTION_0MS1 0x54
0153 #define CEC_PREPARENXTBIT_0MS05_BIT7_0 0x56
0154 #define CEC_PREPARENXTBIT_0MS05_BIT8 0x57
0155 #define CEC_NOMSMPACKPOINT_0MS45 0x58
0156 #define CEC_ACK0NOML2H_1MS5_BIT7_0 0x5A
0157 #define CEC_ACK0NOML2H_1MS5_BIT8 0x5B
0158 #define CEC_BUGFIX_DISABLE_0 0x60
0159 #define CEC_BUGFIX_DISABLE_1 0x61
0160 #define CEC_RX_MSG_0_HEADER 0x80
0161 #define CEC_RX_MSG_1_OPCODE 0x81
0162 #define CEC_RX_MSG_2_OP1 0x82
0163 #define CEC_RX_MSG_3_OP2 0x83
0164 #define CEC_RX_MSG_4_OP3 0x84
0165 #define CEC_RX_MSG_5_OP4 0x85
0166 #define CEC_RX_MSG_6_OP5 0x86
0167 #define CEC_RX_MSG_7_OP6 0x87
0168 #define CEC_RX_MSG_8_OP7 0x88
0169 #define CEC_RX_MSG_9_OP8 0x89
0170 #define CEC_RX_MSG_A_OP9 0x8A
0171 #define CEC_RX_MSG_B_OP10 0x8B
0172 #define CEC_RX_MSG_C_OP11 0x8C
0173 #define CEC_RX_MSG_D_OP12 0x8D
0174 #define CEC_RX_MSG_E_OP13 0x8E
0175 #define CEC_RX_MSG_F_OP14 0x8F
0176 #define CEC_RX_MSG_LENGTH 0x90
0177 #define CEC_RX_MSG_STATUS 0x91
0178 #define CEC_RX_NUM_MSG 0x92
0179 #define CEC_TX_MSG_STATUS 0x93
0180 #define CEC_TX_NUM_MSG 0x94
0181
0182
0183
0184 #define TX_NO_OP 0
0185 #define TX_REQ_CURRENT 1
0186 #define TX_ABORT 2
0187 #define TX_REQ_NEXT 3
0188
0189
0190 #define TX_IDLE 0
0191 #define TX_BUSY 1
0192 #define TX_DONE 2
0193 #define TX_ERROR 3
0194
0195
0196 #define RX_NO_OP 0
0197 #define RX_ACK_CURRENT 1
0198 #define RX_DISABLE 2
0199 #define RX_ACK_NEXT 3
0200
0201
0202 #define RX_IDLE 0
0203 #define RX_BUSY 1
0204 #define RX_DONE 2
0205 #define RX_ERROR 3
0206
0207
0208 #define CLEAR_START 1
0209 #define CLEAR_STOP 0
0210
0211
0212 #define LOGICAL_ADDR_MASK 0xf
0213 #define LOGICAL_ADDR_VALID BIT(4)
0214 #define LOGICAL_ADDR_DISABLE 0
0215
0216 #define CEC_CLK_RATE 32768
0217
0218 struct meson_ao_cec_device {
0219 struct platform_device *pdev;
0220 void __iomem *base;
0221 struct clk *core;
0222 spinlock_t cec_reg_lock;
0223 struct cec_notifier *notify;
0224 struct cec_adapter *adap;
0225 struct cec_msg rx_msg;
0226 };
0227
0228 #define writel_bits_relaxed(mask, val, addr) \
0229 writel_relaxed((readl_relaxed(addr) & ~(mask)) | (val), addr)
0230
0231 static inline int meson_ao_cec_wait_busy(struct meson_ao_cec_device *ao_cec)
0232 {
0233 ktime_t timeout = ktime_add_us(ktime_get(), 5000);
0234
0235 while (readl_relaxed(ao_cec->base + CEC_RW_REG) & CEC_RW_BUS_BUSY) {
0236 if (ktime_compare(ktime_get(), timeout) > 0)
0237 return -ETIMEDOUT;
0238 }
0239
0240 return 0;
0241 }
0242
0243 static void meson_ao_cec_read(struct meson_ao_cec_device *ao_cec,
0244 unsigned long address, u8 *data,
0245 int *res)
0246 {
0247 unsigned long flags;
0248 u32 reg = FIELD_PREP(CEC_RW_ADDR, address);
0249 int ret = 0;
0250
0251 if (res && *res)
0252 return;
0253
0254 spin_lock_irqsave(&ao_cec->cec_reg_lock, flags);
0255
0256 ret = meson_ao_cec_wait_busy(ao_cec);
0257 if (ret)
0258 goto read_out;
0259
0260 writel_relaxed(reg, ao_cec->base + CEC_RW_REG);
0261
0262 ret = meson_ao_cec_wait_busy(ao_cec);
0263 if (ret)
0264 goto read_out;
0265
0266 *data = FIELD_GET(CEC_RW_RD_DATA,
0267 readl_relaxed(ao_cec->base + CEC_RW_REG));
0268
0269 read_out:
0270 spin_unlock_irqrestore(&ao_cec->cec_reg_lock, flags);
0271
0272 if (res)
0273 *res = ret;
0274 }
0275
0276 static void meson_ao_cec_write(struct meson_ao_cec_device *ao_cec,
0277 unsigned long address, u8 data,
0278 int *res)
0279 {
0280 unsigned long flags;
0281 u32 reg = FIELD_PREP(CEC_RW_ADDR, address) |
0282 FIELD_PREP(CEC_RW_WR_DATA, data) |
0283 CEC_RW_WRITE_EN;
0284 int ret = 0;
0285
0286 if (res && *res)
0287 return;
0288
0289 spin_lock_irqsave(&ao_cec->cec_reg_lock, flags);
0290
0291 ret = meson_ao_cec_wait_busy(ao_cec);
0292 if (ret)
0293 goto write_out;
0294
0295 writel_relaxed(reg, ao_cec->base + CEC_RW_REG);
0296
0297 write_out:
0298 spin_unlock_irqrestore(&ao_cec->cec_reg_lock, flags);
0299
0300 if (res)
0301 *res = ret;
0302 }
0303
0304 static inline void meson_ao_cec_irq_setup(struct meson_ao_cec_device *ao_cec,
0305 bool enable)
0306 {
0307 u32 cfg = CEC_INTR_TX | CEC_INTR_RX;
0308
0309 writel_bits_relaxed(cfg, enable ? cfg : 0,
0310 ao_cec->base + CEC_INTR_MASKN_REG);
0311 }
0312
0313 static inline int meson_ao_cec_clear(struct meson_ao_cec_device *ao_cec)
0314 {
0315 int ret = 0;
0316
0317 meson_ao_cec_write(ao_cec, CEC_RX_MSG_CMD, RX_DISABLE, &ret);
0318 meson_ao_cec_write(ao_cec, CEC_TX_MSG_CMD, TX_ABORT, &ret);
0319 meson_ao_cec_write(ao_cec, CEC_RX_CLEAR_BUF, 1, &ret);
0320 meson_ao_cec_write(ao_cec, CEC_TX_CLEAR_BUF, 1, &ret);
0321 if (ret)
0322 return ret;
0323
0324 udelay(100);
0325
0326 meson_ao_cec_write(ao_cec, CEC_RX_CLEAR_BUF, 0, &ret);
0327 meson_ao_cec_write(ao_cec, CEC_TX_CLEAR_BUF, 0, &ret);
0328 if (ret)
0329 return ret;
0330
0331 udelay(100);
0332
0333 meson_ao_cec_write(ao_cec, CEC_RX_MSG_CMD, RX_NO_OP, &ret);
0334 meson_ao_cec_write(ao_cec, CEC_TX_MSG_CMD, TX_NO_OP, &ret);
0335
0336 return ret;
0337 }
0338
0339 static int meson_ao_cec_arbit_bit_time_set(struct meson_ao_cec_device *ao_cec,
0340 unsigned int bit_set,
0341 unsigned int time_set)
0342 {
0343 int ret = 0;
0344
0345 switch (bit_set) {
0346 case CEC_SIGNAL_FREE_TIME_RETRY:
0347 meson_ao_cec_write(ao_cec, CEC_TXTIME_4BIT_BIT7_0,
0348 time_set & 0xff, &ret);
0349 meson_ao_cec_write(ao_cec, CEC_TXTIME_4BIT_BIT10_8,
0350 (time_set >> 8) & 0x7, &ret);
0351 break;
0352
0353 case CEC_SIGNAL_FREE_TIME_NEW_INITIATOR:
0354 meson_ao_cec_write(ao_cec, CEC_TXTIME_2BIT_BIT7_0,
0355 time_set & 0xff, &ret);
0356 meson_ao_cec_write(ao_cec, CEC_TXTIME_2BIT_BIT10_8,
0357 (time_set >> 8) & 0x7, &ret);
0358 break;
0359
0360 case CEC_SIGNAL_FREE_TIME_NEXT_XFER:
0361 meson_ao_cec_write(ao_cec, CEC_TXTIME_17MS_BIT7_0,
0362 time_set & 0xff, &ret);
0363 meson_ao_cec_write(ao_cec, CEC_TXTIME_17MS_BIT10_8,
0364 (time_set >> 8) & 0x7, &ret);
0365 break;
0366 }
0367
0368 return ret;
0369 }
0370
0371 static irqreturn_t meson_ao_cec_irq(int irq, void *data)
0372 {
0373 struct meson_ao_cec_device *ao_cec = data;
0374 u32 stat = readl_relaxed(ao_cec->base + CEC_INTR_STAT_REG);
0375
0376 if (stat)
0377 return IRQ_WAKE_THREAD;
0378
0379 return IRQ_NONE;
0380 }
0381
0382 static void meson_ao_cec_irq_tx(struct meson_ao_cec_device *ao_cec)
0383 {
0384 unsigned long tx_status = 0;
0385 u8 stat;
0386 int ret = 0;
0387
0388 meson_ao_cec_read(ao_cec, CEC_TX_MSG_STATUS, &stat, &ret);
0389 if (ret)
0390 goto tx_reg_err;
0391
0392 switch (stat) {
0393 case TX_DONE:
0394 tx_status = CEC_TX_STATUS_OK;
0395 break;
0396
0397 case TX_BUSY:
0398 tx_status = CEC_TX_STATUS_ARB_LOST;
0399 break;
0400
0401 case TX_IDLE:
0402 tx_status = CEC_TX_STATUS_LOW_DRIVE;
0403 break;
0404
0405 case TX_ERROR:
0406 default:
0407 tx_status = CEC_TX_STATUS_NACK;
0408 break;
0409 }
0410
0411
0412 writel_relaxed(CEC_INTR_TX, ao_cec->base + CEC_INTR_CLR_REG);
0413
0414
0415 meson_ao_cec_write(ao_cec, CEC_TX_MSG_CMD, TX_NO_OP, &ret);
0416 if (ret)
0417 goto tx_reg_err;
0418
0419 cec_transmit_attempt_done(ao_cec->adap, tx_status);
0420 return;
0421
0422 tx_reg_err:
0423 cec_transmit_attempt_done(ao_cec->adap, CEC_TX_STATUS_ERROR);
0424 }
0425
0426 static void meson_ao_cec_irq_rx(struct meson_ao_cec_device *ao_cec)
0427 {
0428 int i, ret = 0;
0429 u8 reg;
0430
0431 meson_ao_cec_read(ao_cec, CEC_RX_MSG_STATUS, ®, &ret);
0432 if (reg != RX_DONE)
0433 goto rx_out;
0434
0435 meson_ao_cec_read(ao_cec, CEC_RX_NUM_MSG, ®, &ret);
0436 if (reg != 1)
0437 goto rx_out;
0438
0439 meson_ao_cec_read(ao_cec, CEC_RX_MSG_LENGTH, ®, &ret);
0440
0441 ao_cec->rx_msg.len = reg + 1;
0442 if (ao_cec->rx_msg.len > CEC_MAX_MSG_SIZE)
0443 ao_cec->rx_msg.len = CEC_MAX_MSG_SIZE;
0444
0445 for (i = 0; i < ao_cec->rx_msg.len; i++) {
0446 u8 byte;
0447
0448 meson_ao_cec_read(ao_cec, CEC_RX_MSG_0_HEADER + i, &byte, &ret);
0449
0450 ao_cec->rx_msg.msg[i] = byte;
0451 }
0452
0453 if (ret)
0454 goto rx_out;
0455
0456 cec_received_msg(ao_cec->adap, &ao_cec->rx_msg);
0457
0458 rx_out:
0459
0460 writel_relaxed(CEC_INTR_RX, ao_cec->base + CEC_INTR_CLR_REG);
0461
0462
0463 meson_ao_cec_write(ao_cec, CEC_RX_MSG_CMD, RX_ACK_CURRENT, &ret);
0464 meson_ao_cec_write(ao_cec, CEC_RX_MSG_CMD, RX_NO_OP, &ret);
0465
0466
0467 meson_ao_cec_write(ao_cec, CEC_RX_CLEAR_BUF, CLEAR_START, &ret);
0468 meson_ao_cec_write(ao_cec, CEC_RX_CLEAR_BUF, CLEAR_STOP, &ret);
0469 }
0470
0471 static irqreturn_t meson_ao_cec_irq_thread(int irq, void *data)
0472 {
0473 struct meson_ao_cec_device *ao_cec = data;
0474 u32 stat = readl_relaxed(ao_cec->base + CEC_INTR_STAT_REG);
0475
0476 if (stat & CEC_INTR_TX)
0477 meson_ao_cec_irq_tx(ao_cec);
0478
0479 meson_ao_cec_irq_rx(ao_cec);
0480
0481 return IRQ_HANDLED;
0482 }
0483
0484 static int meson_ao_cec_set_log_addr(struct cec_adapter *adap, u8 logical_addr)
0485 {
0486 struct meson_ao_cec_device *ao_cec = adap->priv;
0487 int ret = 0;
0488
0489 meson_ao_cec_write(ao_cec, CEC_LOGICAL_ADDR0,
0490 LOGICAL_ADDR_DISABLE, &ret);
0491 if (ret)
0492 return ret;
0493
0494 ret = meson_ao_cec_clear(ao_cec);
0495 if (ret)
0496 return ret;
0497
0498 if (logical_addr == CEC_LOG_ADDR_INVALID)
0499 return 0;
0500
0501 meson_ao_cec_write(ao_cec, CEC_LOGICAL_ADDR0,
0502 logical_addr & LOGICAL_ADDR_MASK, &ret);
0503 if (ret)
0504 return ret;
0505
0506 udelay(100);
0507
0508 meson_ao_cec_write(ao_cec, CEC_LOGICAL_ADDR0,
0509 (logical_addr & LOGICAL_ADDR_MASK) |
0510 LOGICAL_ADDR_VALID, &ret);
0511
0512 return ret;
0513 }
0514
0515 static int meson_ao_cec_transmit(struct cec_adapter *adap, u8 attempts,
0516 u32 signal_free_time, struct cec_msg *msg)
0517 {
0518 struct meson_ao_cec_device *ao_cec = adap->priv;
0519 int i, ret = 0;
0520 u8 reg;
0521
0522 meson_ao_cec_read(ao_cec, CEC_TX_MSG_STATUS, ®, &ret);
0523 if (ret)
0524 return ret;
0525
0526 if (reg == TX_BUSY) {
0527 dev_dbg(&ao_cec->pdev->dev, "%s: busy TX: aborting\n",
0528 __func__);
0529 meson_ao_cec_write(ao_cec, CEC_TX_MSG_CMD, TX_ABORT, &ret);
0530 }
0531
0532 for (i = 0; i < msg->len; i++) {
0533 meson_ao_cec_write(ao_cec, CEC_TX_MSG_0_HEADER + i,
0534 msg->msg[i], &ret);
0535 }
0536
0537 meson_ao_cec_write(ao_cec, CEC_TX_MSG_LENGTH, msg->len - 1, &ret);
0538 meson_ao_cec_write(ao_cec, CEC_TX_MSG_CMD, TX_REQ_CURRENT, &ret);
0539
0540 return ret;
0541 }
0542
0543 static int meson_ao_cec_adap_enable(struct cec_adapter *adap, bool enable)
0544 {
0545 struct meson_ao_cec_device *ao_cec = adap->priv;
0546 int ret;
0547
0548 meson_ao_cec_irq_setup(ao_cec, false);
0549
0550 writel_bits_relaxed(CEC_GEN_CNTL_RESET, CEC_GEN_CNTL_RESET,
0551 ao_cec->base + CEC_GEN_CNTL_REG);
0552
0553 if (!enable)
0554 return 0;
0555
0556
0557 writel_bits_relaxed(CEC_GEN_CNTL_CLK_CTRL_MASK,
0558 FIELD_PREP(CEC_GEN_CNTL_CLK_CTRL_MASK,
0559 CEC_GEN_CNTL_CLK_ENABLE),
0560 ao_cec->base + CEC_GEN_CNTL_REG);
0561
0562 udelay(100);
0563
0564
0565 writel_bits_relaxed(CEC_GEN_CNTL_RESET, 0,
0566 ao_cec->base + CEC_GEN_CNTL_REG);
0567
0568
0569 ret = meson_ao_cec_clear(ao_cec);
0570 if (ret)
0571 return ret;
0572
0573
0574 ret = meson_ao_cec_arbit_bit_time_set(ao_cec,
0575 CEC_SIGNAL_FREE_TIME_RETRY,
0576 0x118);
0577 if (ret)
0578 return ret;
0579 ret = meson_ao_cec_arbit_bit_time_set(ao_cec,
0580 CEC_SIGNAL_FREE_TIME_NEW_INITIATOR,
0581 0x000);
0582 if (ret)
0583 return ret;
0584 ret = meson_ao_cec_arbit_bit_time_set(ao_cec,
0585 CEC_SIGNAL_FREE_TIME_NEXT_XFER,
0586 0x2aa);
0587 if (ret)
0588 return ret;
0589
0590 meson_ao_cec_irq_setup(ao_cec, true);
0591
0592 return 0;
0593 }
0594
0595 static const struct cec_adap_ops meson_ao_cec_ops = {
0596 .adap_enable = meson_ao_cec_adap_enable,
0597 .adap_log_addr = meson_ao_cec_set_log_addr,
0598 .adap_transmit = meson_ao_cec_transmit,
0599 };
0600
0601 static int meson_ao_cec_probe(struct platform_device *pdev)
0602 {
0603 struct meson_ao_cec_device *ao_cec;
0604 struct device *hdmi_dev;
0605 int ret, irq;
0606
0607 hdmi_dev = cec_notifier_parse_hdmi_phandle(&pdev->dev);
0608
0609 if (IS_ERR(hdmi_dev))
0610 return PTR_ERR(hdmi_dev);
0611
0612 ao_cec = devm_kzalloc(&pdev->dev, sizeof(*ao_cec), GFP_KERNEL);
0613 if (!ao_cec)
0614 return -ENOMEM;
0615
0616 spin_lock_init(&ao_cec->cec_reg_lock);
0617
0618 ao_cec->adap = cec_allocate_adapter(&meson_ao_cec_ops, ao_cec,
0619 "meson_ao_cec",
0620 CEC_CAP_DEFAULTS |
0621 CEC_CAP_CONNECTOR_INFO,
0622 1);
0623 if (IS_ERR(ao_cec->adap))
0624 return PTR_ERR(ao_cec->adap);
0625
0626 ao_cec->adap->owner = THIS_MODULE;
0627
0628 ao_cec->base = devm_platform_ioremap_resource(pdev, 0);
0629 if (IS_ERR(ao_cec->base)) {
0630 ret = PTR_ERR(ao_cec->base);
0631 goto out_probe_adapter;
0632 }
0633
0634 irq = platform_get_irq(pdev, 0);
0635 ret = devm_request_threaded_irq(&pdev->dev, irq,
0636 meson_ao_cec_irq,
0637 meson_ao_cec_irq_thread,
0638 0, NULL, ao_cec);
0639 if (ret) {
0640 dev_err(&pdev->dev, "irq request failed\n");
0641 goto out_probe_adapter;
0642 }
0643
0644 ao_cec->core = devm_clk_get(&pdev->dev, "core");
0645 if (IS_ERR(ao_cec->core)) {
0646 dev_err(&pdev->dev, "core clock request failed\n");
0647 ret = PTR_ERR(ao_cec->core);
0648 goto out_probe_adapter;
0649 }
0650
0651 ret = clk_prepare_enable(ao_cec->core);
0652 if (ret) {
0653 dev_err(&pdev->dev, "core clock enable failed\n");
0654 goto out_probe_adapter;
0655 }
0656
0657 ret = clk_set_rate(ao_cec->core, CEC_CLK_RATE);
0658 if (ret) {
0659 dev_err(&pdev->dev, "core clock set rate failed\n");
0660 goto out_probe_clk;
0661 }
0662
0663 device_reset_optional(&pdev->dev);
0664
0665 ao_cec->pdev = pdev;
0666 platform_set_drvdata(pdev, ao_cec);
0667
0668 ao_cec->notify = cec_notifier_cec_adap_register(hdmi_dev, NULL,
0669 ao_cec->adap);
0670 if (!ao_cec->notify) {
0671 ret = -ENOMEM;
0672 goto out_probe_clk;
0673 }
0674
0675 ret = cec_register_adapter(ao_cec->adap, &pdev->dev);
0676 if (ret < 0)
0677 goto out_probe_notify;
0678
0679
0680 writel_relaxed(CEC_GEN_CNTL_RESET,
0681 ao_cec->base + CEC_GEN_CNTL_REG);
0682
0683 return 0;
0684
0685 out_probe_notify:
0686 cec_notifier_cec_adap_unregister(ao_cec->notify, ao_cec->adap);
0687
0688 out_probe_clk:
0689 clk_disable_unprepare(ao_cec->core);
0690
0691 out_probe_adapter:
0692 cec_delete_adapter(ao_cec->adap);
0693
0694 dev_err(&pdev->dev, "CEC controller registration failed\n");
0695
0696 return ret;
0697 }
0698
0699 static int meson_ao_cec_remove(struct platform_device *pdev)
0700 {
0701 struct meson_ao_cec_device *ao_cec = platform_get_drvdata(pdev);
0702
0703 clk_disable_unprepare(ao_cec->core);
0704
0705 cec_notifier_cec_adap_unregister(ao_cec->notify, ao_cec->adap);
0706 cec_unregister_adapter(ao_cec->adap);
0707
0708 return 0;
0709 }
0710
0711 static const struct of_device_id meson_ao_cec_of_match[] = {
0712 { .compatible = "amlogic,meson-gx-ao-cec", },
0713 { }
0714 };
0715 MODULE_DEVICE_TABLE(of, meson_ao_cec_of_match);
0716
0717 static struct platform_driver meson_ao_cec_driver = {
0718 .probe = meson_ao_cec_probe,
0719 .remove = meson_ao_cec_remove,
0720 .driver = {
0721 .name = "meson-ao-cec",
0722 .of_match_table = of_match_ptr(meson_ao_cec_of_match),
0723 },
0724 };
0725
0726 module_platform_driver(meson_ao_cec_driver);
0727
0728 MODULE_DESCRIPTION("Meson AO CEC Controller driver");
0729 MODULE_AUTHOR("Neil Armstrong <narmstrong@baylibre.com>");
0730 MODULE_LICENSE("GPL");