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, ®, &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 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, ®, &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");