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 218 struct 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 231 static 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 243 static 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 269 read_out: 270 spin_unlock_irqrestore(&ao_cec->cec_reg_lock, flags); 271 272 if (res) 273 *res = ret; 274 } 275 276 static 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 297 write_out: 298 spin_unlock_irqrestore(&ao_cec->cec_reg_lock, flags); 299 300 if (res) 301 *res = ret; 302 } 303 304 static 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 313 static 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 339 static 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 371 static 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 382 static 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 422 tx_reg_err: 423 cec_transmit_attempt_done(ao_cec->adap, CEC_TX_STATUS_ERROR); 424 } 425 426 static 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, ®, &ret); 432 if (reg != RX_DONE) 433 goto rx_out; 434 435 meson_ao_cec_read(ao_cec, CEC_RX_NUM_MSG, ®, &ret); 436 if (reg != 1) 437 goto rx_out; 438 439 meson_ao_cec_read(ao_cec, CEC_RX_MSG_LENGTH, ®, &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 458 rx_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 471 static 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 484 static 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 515 static 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, ®, &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 543 static 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 595 static 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 601 static 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 685 out_probe_notify: 686 cec_notifier_cec_adap_unregister(ao_cec->notify, ao_cec->adap); 687 688 out_probe_clk: 689 clk_disable_unprepare(ao_cec->core); 690 691 out_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 699 static 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 711 static const struct of_device_id meson_ao_cec_of_match[] = { 712 { .compatible = "amlogic,meson-gx-ao-cec", }, 713 { /* sentinel */ } 714 }; 715 MODULE_DEVICE_TABLE(of, meson_ao_cec_of_match); 716 717 static 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 726 module_platform_driver(meson_ao_cec_driver); 727 728 MODULE_DESCRIPTION("Meson AO CEC Controller driver"); 729 MODULE_AUTHOR("Neil Armstrong <narmstrong@baylibre.com>"); 730 MODULE_LICENSE("GPL"); 731