ao-cec-g12a.c (21305B)
1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * Driver for Amlogic Meson AO CEC G12A Controller 4 * 5 * Copyright (C) 2017 Amlogic, Inc. All rights reserved 6 * Copyright (C) 2019 BayLibre, SAS 7 * Author: Neil Armstrong <narmstrong@baylibre.com> 8 */ 9 10#include <linux/bitfield.h> 11#include <linux/clk.h> 12#include <linux/device.h> 13#include <linux/io.h> 14#include <linux/delay.h> 15#include <linux/kernel.h> 16#include <linux/module.h> 17#include <linux/of.h> 18#include <linux/of_platform.h> 19#include <linux/platform_device.h> 20#include <linux/types.h> 21#include <linux/interrupt.h> 22#include <linux/reset.h> 23#include <linux/slab.h> 24#include <linux/regmap.h> 25#include <media/cec.h> 26#include <media/cec-notifier.h> 27#include <linux/clk-provider.h> 28 29/* CEC Registers */ 30 31#define CECB_CLK_CNTL_REG0 0x00 32 33#define CECB_CLK_CNTL_N1 GENMASK(11, 0) 34#define CECB_CLK_CNTL_N2 GENMASK(23, 12) 35#define CECB_CLK_CNTL_DUAL_EN BIT(28) 36#define CECB_CLK_CNTL_OUTPUT_EN BIT(30) 37#define CECB_CLK_CNTL_INPUT_EN BIT(31) 38 39#define CECB_CLK_CNTL_REG1 0x04 40 41#define CECB_CLK_CNTL_M1 GENMASK(11, 0) 42#define CECB_CLK_CNTL_M2 GENMASK(23, 12) 43#define CECB_CLK_CNTL_BYPASS_EN BIT(24) 44 45/* 46 * [14:12] Filter_del. For glitch-filtering CEC line, ignore signal 47 * change pulse width < filter_del * T(filter_tick) * 3. 48 * [9:8] Filter_tick_sel: Select which periodical pulse for 49 * glitch-filtering CEC line signal. 50 * - 0=Use T(xtal)*3 = 125ns; 51 * - 1=Use once-per-1us pulse; 52 * - 2=Use once-per-10us pulse; 53 * - 3=Use once-per-100us pulse. 54 * [3] Sysclk_en. 0=Disable system clock; 1=Enable system clock. 55 * [2:1] cntl_clk 56 * - 0 = Disable clk (Power-off mode) 57 * - 1 = Enable gated clock (Normal mode) 58 * - 2 = Enable free-run clk (Debug mode) 59 * [0] SW_RESET 1=Apply reset; 0=No reset. 60 */ 61#define CECB_GEN_CNTL_REG 0x08 62 63#define CECB_GEN_CNTL_RESET BIT(0) 64#define CECB_GEN_CNTL_CLK_DISABLE 0 65#define CECB_GEN_CNTL_CLK_ENABLE 1 66#define CECB_GEN_CNTL_CLK_ENABLE_DBG 2 67#define CECB_GEN_CNTL_CLK_CTRL_MASK GENMASK(2, 1) 68#define CECB_GEN_CNTL_SYS_CLK_EN BIT(3) 69#define CECB_GEN_CNTL_FILTER_TICK_125NS 0 70#define CECB_GEN_CNTL_FILTER_TICK_1US 1 71#define CECB_GEN_CNTL_FILTER_TICK_10US 2 72#define CECB_GEN_CNTL_FILTER_TICK_100US 3 73#define CECB_GEN_CNTL_FILTER_TICK_SEL GENMASK(9, 8) 74#define CECB_GEN_CNTL_FILTER_DEL GENMASK(14, 12) 75 76/* 77 * [7:0] cec_reg_addr 78 * [15:8] cec_reg_wrdata 79 * [16] cec_reg_wr 80 * - 0 = Read 81 * - 1 = Write 82 * [31:24] cec_reg_rddata 83 */ 84#define CECB_RW_REG 0x0c 85 86#define CECB_RW_ADDR GENMASK(7, 0) 87#define CECB_RW_WR_DATA GENMASK(15, 8) 88#define CECB_RW_WRITE_EN BIT(16) 89#define CECB_RW_BUS_BUSY BIT(23) 90#define CECB_RW_RD_DATA GENMASK(31, 24) 91 92/* 93 * [0] DONE Interrupt 94 * [1] End Of Message Interrupt 95 * [2] Not Acknowlegde Interrupt 96 * [3] Arbitration Loss Interrupt 97 * [4] Initiator Error Interrupt 98 * [5] Follower Error Interrupt 99 * [6] Wake-Up Interrupt 100 */ 101#define CECB_INTR_MASKN_REG 0x10 102#define CECB_INTR_CLR_REG 0x14 103#define CECB_INTR_STAT_REG 0x18 104 105#define CECB_INTR_DONE BIT(0) 106#define CECB_INTR_EOM BIT(1) 107#define CECB_INTR_NACK BIT(2) 108#define CECB_INTR_ARB_LOSS BIT(3) 109#define CECB_INTR_INITIATOR_ERR BIT(4) 110#define CECB_INTR_FOLLOWER_ERR BIT(5) 111#define CECB_INTR_WAKE_UP BIT(6) 112 113/* CEC Commands */ 114 115#define CECB_CTRL 0x00 116 117#define CECB_CTRL_SEND BIT(0) 118#define CECB_CTRL_TYPE GENMASK(2, 1) 119#define CECB_CTRL_TYPE_RETRY 0 120#define CECB_CTRL_TYPE_NEW 1 121#define CECB_CTRL_TYPE_NEXT 2 122 123#define CECB_CTRL2 0x01 124 125#define CECB_CTRL2_RISE_DEL_MAX GENMASK(4, 0) 126 127#define CECB_INTR_MASK 0x02 128#define CECB_LADD_LOW 0x05 129#define CECB_LADD_HIGH 0x06 130#define CECB_TX_CNT 0x07 131#define CECB_RX_CNT 0x08 132#define CECB_STAT0 0x09 133#define CECB_TX_DATA00 0x10 134#define CECB_TX_DATA01 0x11 135#define CECB_TX_DATA02 0x12 136#define CECB_TX_DATA03 0x13 137#define CECB_TX_DATA04 0x14 138#define CECB_TX_DATA05 0x15 139#define CECB_TX_DATA06 0x16 140#define CECB_TX_DATA07 0x17 141#define CECB_TX_DATA08 0x18 142#define CECB_TX_DATA09 0x19 143#define CECB_TX_DATA10 0x1A 144#define CECB_TX_DATA11 0x1B 145#define CECB_TX_DATA12 0x1C 146#define CECB_TX_DATA13 0x1D 147#define CECB_TX_DATA14 0x1E 148#define CECB_TX_DATA15 0x1F 149#define CECB_RX_DATA00 0x20 150#define CECB_RX_DATA01 0x21 151#define CECB_RX_DATA02 0x22 152#define CECB_RX_DATA03 0x23 153#define CECB_RX_DATA04 0x24 154#define CECB_RX_DATA05 0x25 155#define CECB_RX_DATA06 0x26 156#define CECB_RX_DATA07 0x27 157#define CECB_RX_DATA08 0x28 158#define CECB_RX_DATA09 0x29 159#define CECB_RX_DATA10 0x2A 160#define CECB_RX_DATA11 0x2B 161#define CECB_RX_DATA12 0x2C 162#define CECB_RX_DATA13 0x2D 163#define CECB_RX_DATA14 0x2E 164#define CECB_RX_DATA15 0x2F 165#define CECB_LOCK_BUF 0x30 166 167#define CECB_LOCK_BUF_EN BIT(0) 168 169#define CECB_WAKEUPCTRL 0x31 170 171struct meson_ao_cec_g12a_data { 172 /* Setup the internal CECB_CTRL2 register */ 173 bool ctrl2_setup; 174}; 175 176struct meson_ao_cec_g12a_device { 177 struct platform_device *pdev; 178 struct regmap *regmap; 179 struct regmap *regmap_cec; 180 spinlock_t cec_reg_lock; 181 struct cec_notifier *notify; 182 struct cec_adapter *adap; 183 struct cec_msg rx_msg; 184 struct clk *oscin; 185 struct clk *core; 186 const struct meson_ao_cec_g12a_data *data; 187}; 188 189static const struct regmap_config meson_ao_cec_g12a_regmap_conf = { 190 .reg_bits = 8, 191 .val_bits = 32, 192 .reg_stride = 4, 193 .max_register = CECB_INTR_STAT_REG, 194}; 195 196/* 197 * The AO-CECB embeds a dual/divider to generate a more precise 198 * 32,768KHz clock for CEC core clock. 199 * ______ ______ 200 * | | | | 201 * ______ | Div1 |-| Cnt1 | ______ 202 * | | /|______| |______|\ | | 203 * Xtal-->| Gate |---| ______ ______ X-X--| Gate |--> 204 * |______| | \| | | |/ | |______| 205 * | | Div2 |-| Cnt2 | | 206 * | |______| |______| | 207 * |_______________________| 208 * 209 * The dividing can be switched to single or dual, with a counter 210 * for each divider to set when the switching is done. 211 * The entire dividing mechanism can be also bypassed. 212 */ 213 214struct meson_ao_cec_g12a_dualdiv_clk { 215 struct clk_hw hw; 216 struct regmap *regmap; 217}; 218 219#define hw_to_meson_ao_cec_g12a_dualdiv_clk(_hw) \ 220 container_of(_hw, struct meson_ao_cec_g12a_dualdiv_clk, hw) \ 221 222static unsigned long 223meson_ao_cec_g12a_dualdiv_clk_recalc_rate(struct clk_hw *hw, 224 unsigned long parent_rate) 225{ 226 struct meson_ao_cec_g12a_dualdiv_clk *dualdiv_clk = 227 hw_to_meson_ao_cec_g12a_dualdiv_clk(hw); 228 unsigned long n1; 229 u32 reg0, reg1; 230 231 regmap_read(dualdiv_clk->regmap, CECB_CLK_CNTL_REG0, ®0); 232 regmap_read(dualdiv_clk->regmap, CECB_CLK_CNTL_REG0, ®1); 233 234 if (reg1 & CECB_CLK_CNTL_BYPASS_EN) 235 return parent_rate; 236 237 if (reg0 & CECB_CLK_CNTL_DUAL_EN) { 238 unsigned long n2, m1, m2, f1, f2, p1, p2; 239 240 n1 = FIELD_GET(CECB_CLK_CNTL_N1, reg0) + 1; 241 n2 = FIELD_GET(CECB_CLK_CNTL_N2, reg0) + 1; 242 243 m1 = FIELD_GET(CECB_CLK_CNTL_M1, reg1) + 1; 244 m2 = FIELD_GET(CECB_CLK_CNTL_M1, reg1) + 1; 245 246 f1 = DIV_ROUND_CLOSEST(parent_rate, n1); 247 f2 = DIV_ROUND_CLOSEST(parent_rate, n2); 248 249 p1 = DIV_ROUND_CLOSEST(100000000 * m1, f1 * (m1 + m2)); 250 p2 = DIV_ROUND_CLOSEST(100000000 * m2, f2 * (m1 + m2)); 251 252 return DIV_ROUND_UP(100000000, p1 + p2); 253 } 254 255 n1 = FIELD_GET(CECB_CLK_CNTL_N1, reg0) + 1; 256 257 return DIV_ROUND_CLOSEST(parent_rate, n1); 258} 259 260static int meson_ao_cec_g12a_dualdiv_clk_enable(struct clk_hw *hw) 261{ 262 struct meson_ao_cec_g12a_dualdiv_clk *dualdiv_clk = 263 hw_to_meson_ao_cec_g12a_dualdiv_clk(hw); 264 265 266 /* Disable Input & Output */ 267 regmap_update_bits(dualdiv_clk->regmap, CECB_CLK_CNTL_REG0, 268 CECB_CLK_CNTL_INPUT_EN | CECB_CLK_CNTL_OUTPUT_EN, 269 0); 270 271 /* Set N1 & N2 */ 272 regmap_update_bits(dualdiv_clk->regmap, CECB_CLK_CNTL_REG0, 273 CECB_CLK_CNTL_N1, 274 FIELD_PREP(CECB_CLK_CNTL_N1, 733 - 1)); 275 276 regmap_update_bits(dualdiv_clk->regmap, CECB_CLK_CNTL_REG0, 277 CECB_CLK_CNTL_N2, 278 FIELD_PREP(CECB_CLK_CNTL_N2, 732 - 1)); 279 280 /* Set M1 & M2 */ 281 regmap_update_bits(dualdiv_clk->regmap, CECB_CLK_CNTL_REG1, 282 CECB_CLK_CNTL_M1, 283 FIELD_PREP(CECB_CLK_CNTL_M1, 8 - 1)); 284 285 regmap_update_bits(dualdiv_clk->regmap, CECB_CLK_CNTL_REG1, 286 CECB_CLK_CNTL_M2, 287 FIELD_PREP(CECB_CLK_CNTL_M2, 11 - 1)); 288 289 /* Enable Dual divisor */ 290 regmap_update_bits(dualdiv_clk->regmap, CECB_CLK_CNTL_REG0, 291 CECB_CLK_CNTL_DUAL_EN, CECB_CLK_CNTL_DUAL_EN); 292 293 /* Disable divisor bypass */ 294 regmap_update_bits(dualdiv_clk->regmap, CECB_CLK_CNTL_REG1, 295 CECB_CLK_CNTL_BYPASS_EN, 0); 296 297 /* Enable Input & Output */ 298 regmap_update_bits(dualdiv_clk->regmap, CECB_CLK_CNTL_REG0, 299 CECB_CLK_CNTL_INPUT_EN | CECB_CLK_CNTL_OUTPUT_EN, 300 CECB_CLK_CNTL_INPUT_EN | CECB_CLK_CNTL_OUTPUT_EN); 301 302 return 0; 303} 304 305static void meson_ao_cec_g12a_dualdiv_clk_disable(struct clk_hw *hw) 306{ 307 struct meson_ao_cec_g12a_dualdiv_clk *dualdiv_clk = 308 hw_to_meson_ao_cec_g12a_dualdiv_clk(hw); 309 310 regmap_update_bits(dualdiv_clk->regmap, CECB_CLK_CNTL_REG0, 311 CECB_CLK_CNTL_INPUT_EN | CECB_CLK_CNTL_OUTPUT_EN, 312 0); 313} 314 315static int meson_ao_cec_g12a_dualdiv_clk_is_enabled(struct clk_hw *hw) 316{ 317 struct meson_ao_cec_g12a_dualdiv_clk *dualdiv_clk = 318 hw_to_meson_ao_cec_g12a_dualdiv_clk(hw); 319 int val; 320 321 regmap_read(dualdiv_clk->regmap, CECB_CLK_CNTL_REG0, &val); 322 323 return !!(val & (CECB_CLK_CNTL_INPUT_EN | CECB_CLK_CNTL_OUTPUT_EN)); 324} 325 326static const struct clk_ops meson_ao_cec_g12a_dualdiv_clk_ops = { 327 .recalc_rate = meson_ao_cec_g12a_dualdiv_clk_recalc_rate, 328 .is_enabled = meson_ao_cec_g12a_dualdiv_clk_is_enabled, 329 .enable = meson_ao_cec_g12a_dualdiv_clk_enable, 330 .disable = meson_ao_cec_g12a_dualdiv_clk_disable, 331}; 332 333static int meson_ao_cec_g12a_setup_clk(struct meson_ao_cec_g12a_device *ao_cec) 334{ 335 struct meson_ao_cec_g12a_dualdiv_clk *dualdiv_clk; 336 struct device *dev = &ao_cec->pdev->dev; 337 struct clk_init_data init; 338 const char *parent_name; 339 struct clk *clk; 340 char *name; 341 342 dualdiv_clk = devm_kzalloc(dev, sizeof(*dualdiv_clk), GFP_KERNEL); 343 if (!dualdiv_clk) 344 return -ENOMEM; 345 346 name = kasprintf(GFP_KERNEL, "%s#dualdiv_clk", dev_name(dev)); 347 if (!name) 348 return -ENOMEM; 349 350 parent_name = __clk_get_name(ao_cec->oscin); 351 352 init.name = name; 353 init.ops = &meson_ao_cec_g12a_dualdiv_clk_ops; 354 init.flags = 0; 355 init.parent_names = &parent_name; 356 init.num_parents = 1; 357 dualdiv_clk->regmap = ao_cec->regmap; 358 dualdiv_clk->hw.init = &init; 359 360 clk = devm_clk_register(dev, &dualdiv_clk->hw); 361 kfree(name); 362 if (IS_ERR(clk)) { 363 dev_err(dev, "failed to register clock\n"); 364 return PTR_ERR(clk); 365 } 366 367 ao_cec->core = clk; 368 369 return 0; 370} 371 372static int meson_ao_cec_g12a_read(void *context, unsigned int addr, 373 unsigned int *data) 374{ 375 struct meson_ao_cec_g12a_device *ao_cec = context; 376 u32 reg = FIELD_PREP(CECB_RW_ADDR, addr); 377 int ret = 0; 378 379 ret = regmap_write(ao_cec->regmap, CECB_RW_REG, reg); 380 if (ret) 381 return ret; 382 383 ret = regmap_read_poll_timeout(ao_cec->regmap, CECB_RW_REG, reg, 384 !(reg & CECB_RW_BUS_BUSY), 385 5, 1000); 386 if (ret) 387 return ret; 388 389 ret = regmap_read(ao_cec->regmap, CECB_RW_REG, ®); 390 391 *data = FIELD_GET(CECB_RW_RD_DATA, reg); 392 393 return ret; 394} 395 396static int meson_ao_cec_g12a_write(void *context, unsigned int addr, 397 unsigned int data) 398{ 399 struct meson_ao_cec_g12a_device *ao_cec = context; 400 u32 reg = FIELD_PREP(CECB_RW_ADDR, addr) | 401 FIELD_PREP(CECB_RW_WR_DATA, data) | 402 CECB_RW_WRITE_EN; 403 404 return regmap_write(ao_cec->regmap, CECB_RW_REG, reg); 405} 406 407static const struct regmap_config meson_ao_cec_g12a_cec_regmap_conf = { 408 .reg_bits = 8, 409 .val_bits = 8, 410 .reg_read = meson_ao_cec_g12a_read, 411 .reg_write = meson_ao_cec_g12a_write, 412 .max_register = 0xffff, 413}; 414 415static inline void 416meson_ao_cec_g12a_irq_setup(struct meson_ao_cec_g12a_device *ao_cec, 417 bool enable) 418{ 419 u32 cfg = CECB_INTR_DONE | CECB_INTR_EOM | CECB_INTR_NACK | 420 CECB_INTR_ARB_LOSS | CECB_INTR_INITIATOR_ERR | 421 CECB_INTR_FOLLOWER_ERR; 422 423 regmap_write(ao_cec->regmap, CECB_INTR_MASKN_REG, 424 enable ? cfg : 0); 425} 426 427static void meson_ao_cec_g12a_irq_rx(struct meson_ao_cec_g12a_device *ao_cec) 428{ 429 int i, ret = 0; 430 u32 val; 431 432 ret = regmap_read(ao_cec->regmap_cec, CECB_RX_CNT, &val); 433 434 ao_cec->rx_msg.len = val; 435 if (ao_cec->rx_msg.len > CEC_MAX_MSG_SIZE) 436 ao_cec->rx_msg.len = CEC_MAX_MSG_SIZE; 437 438 for (i = 0; i < ao_cec->rx_msg.len; i++) { 439 ret |= regmap_read(ao_cec->regmap_cec, 440 CECB_RX_DATA00 + i, &val); 441 442 ao_cec->rx_msg.msg[i] = val & 0xff; 443 } 444 445 ret |= regmap_write(ao_cec->regmap_cec, CECB_LOCK_BUF, 0); 446 if (ret) 447 return; 448 449 cec_received_msg(ao_cec->adap, &ao_cec->rx_msg); 450} 451 452static irqreturn_t meson_ao_cec_g12a_irq(int irq, void *data) 453{ 454 struct meson_ao_cec_g12a_device *ao_cec = data; 455 u32 stat; 456 457 regmap_read(ao_cec->regmap, CECB_INTR_STAT_REG, &stat); 458 if (stat) 459 return IRQ_WAKE_THREAD; 460 461 return IRQ_NONE; 462} 463 464static irqreturn_t meson_ao_cec_g12a_irq_thread(int irq, void *data) 465{ 466 struct meson_ao_cec_g12a_device *ao_cec = data; 467 u32 stat; 468 469 regmap_read(ao_cec->regmap, CECB_INTR_STAT_REG, &stat); 470 regmap_write(ao_cec->regmap, CECB_INTR_CLR_REG, stat); 471 472 if (stat & CECB_INTR_DONE) 473 cec_transmit_attempt_done(ao_cec->adap, CEC_TX_STATUS_OK); 474 475 if (stat & CECB_INTR_EOM) 476 meson_ao_cec_g12a_irq_rx(ao_cec); 477 478 if (stat & CECB_INTR_NACK) 479 cec_transmit_attempt_done(ao_cec->adap, CEC_TX_STATUS_NACK); 480 481 if (stat & CECB_INTR_ARB_LOSS) { 482 regmap_write(ao_cec->regmap_cec, CECB_TX_CNT, 0); 483 regmap_update_bits(ao_cec->regmap_cec, CECB_CTRL, 484 CECB_CTRL_SEND | CECB_CTRL_TYPE, 0); 485 cec_transmit_attempt_done(ao_cec->adap, CEC_TX_STATUS_ARB_LOST); 486 } 487 488 /* Initiator reports an error on the CEC bus */ 489 if (stat & CECB_INTR_INITIATOR_ERR) 490 cec_transmit_attempt_done(ao_cec->adap, CEC_TX_STATUS_ERROR); 491 492 /* Follower reports a receive error, just reset RX buffer */ 493 if (stat & CECB_INTR_FOLLOWER_ERR) 494 regmap_write(ao_cec->regmap_cec, CECB_LOCK_BUF, 0); 495 496 return IRQ_HANDLED; 497} 498 499static int 500meson_ao_cec_g12a_set_log_addr(struct cec_adapter *adap, u8 logical_addr) 501{ 502 struct meson_ao_cec_g12a_device *ao_cec = adap->priv; 503 int ret = 0; 504 505 if (logical_addr == CEC_LOG_ADDR_INVALID) { 506 /* Assume this will allways succeed */ 507 regmap_write(ao_cec->regmap_cec, CECB_LADD_LOW, 0); 508 regmap_write(ao_cec->regmap_cec, CECB_LADD_HIGH, 0); 509 510 return 0; 511 } else if (logical_addr < 8) { 512 ret = regmap_update_bits(ao_cec->regmap_cec, CECB_LADD_LOW, 513 BIT(logical_addr), 514 BIT(logical_addr)); 515 } else { 516 ret = regmap_update_bits(ao_cec->regmap_cec, CECB_LADD_HIGH, 517 BIT(logical_addr - 8), 518 BIT(logical_addr - 8)); 519 } 520 521 /* Always set Broadcast/Unregistered 15 address */ 522 ret |= regmap_update_bits(ao_cec->regmap_cec, CECB_LADD_HIGH, 523 BIT(CEC_LOG_ADDR_UNREGISTERED - 8), 524 BIT(CEC_LOG_ADDR_UNREGISTERED - 8)); 525 526 return ret ? -EIO : 0; 527} 528 529static int meson_ao_cec_g12a_transmit(struct cec_adapter *adap, u8 attempts, 530 u32 signal_free_time, struct cec_msg *msg) 531{ 532 struct meson_ao_cec_g12a_device *ao_cec = adap->priv; 533 unsigned int type; 534 int ret = 0; 535 u32 val; 536 int i; 537 538 /* Check if RX is in progress */ 539 ret = regmap_read(ao_cec->regmap_cec, CECB_LOCK_BUF, &val); 540 if (ret) 541 return ret; 542 if (val & CECB_LOCK_BUF_EN) 543 return -EBUSY; 544 545 /* Check if TX Busy */ 546 ret = regmap_read(ao_cec->regmap_cec, CECB_CTRL, &val); 547 if (ret) 548 return ret; 549 if (val & CECB_CTRL_SEND) 550 return -EBUSY; 551 552 switch (signal_free_time) { 553 case CEC_SIGNAL_FREE_TIME_RETRY: 554 type = CECB_CTRL_TYPE_RETRY; 555 break; 556 case CEC_SIGNAL_FREE_TIME_NEXT_XFER: 557 type = CECB_CTRL_TYPE_NEXT; 558 break; 559 case CEC_SIGNAL_FREE_TIME_NEW_INITIATOR: 560 default: 561 type = CECB_CTRL_TYPE_NEW; 562 break; 563 } 564 565 for (i = 0; i < msg->len; i++) 566 ret |= regmap_write(ao_cec->regmap_cec, CECB_TX_DATA00 + i, 567 msg->msg[i]); 568 569 ret |= regmap_write(ao_cec->regmap_cec, CECB_TX_CNT, msg->len); 570 if (ret) 571 return -EIO; 572 573 ret = regmap_update_bits(ao_cec->regmap_cec, CECB_CTRL, 574 CECB_CTRL_SEND | 575 CECB_CTRL_TYPE, 576 CECB_CTRL_SEND | 577 FIELD_PREP(CECB_CTRL_TYPE, type)); 578 579 return ret; 580} 581 582static int meson_ao_cec_g12a_adap_enable(struct cec_adapter *adap, bool enable) 583{ 584 struct meson_ao_cec_g12a_device *ao_cec = adap->priv; 585 586 meson_ao_cec_g12a_irq_setup(ao_cec, false); 587 588 regmap_update_bits(ao_cec->regmap, CECB_GEN_CNTL_REG, 589 CECB_GEN_CNTL_RESET, CECB_GEN_CNTL_RESET); 590 591 if (!enable) 592 return 0; 593 594 /* Setup Filter */ 595 regmap_update_bits(ao_cec->regmap, CECB_GEN_CNTL_REG, 596 CECB_GEN_CNTL_FILTER_TICK_SEL | 597 CECB_GEN_CNTL_FILTER_DEL, 598 FIELD_PREP(CECB_GEN_CNTL_FILTER_TICK_SEL, 599 CECB_GEN_CNTL_FILTER_TICK_1US) | 600 FIELD_PREP(CECB_GEN_CNTL_FILTER_DEL, 7)); 601 602 /* Enable System Clock */ 603 regmap_update_bits(ao_cec->regmap, CECB_GEN_CNTL_REG, 604 CECB_GEN_CNTL_SYS_CLK_EN, 605 CECB_GEN_CNTL_SYS_CLK_EN); 606 607 /* Enable gated clock (Normal mode). */ 608 regmap_update_bits(ao_cec->regmap, CECB_GEN_CNTL_REG, 609 CECB_GEN_CNTL_CLK_CTRL_MASK, 610 FIELD_PREP(CECB_GEN_CNTL_CLK_CTRL_MASK, 611 CECB_GEN_CNTL_CLK_ENABLE)); 612 613 /* Release Reset */ 614 regmap_update_bits(ao_cec->regmap, CECB_GEN_CNTL_REG, 615 CECB_GEN_CNTL_RESET, 0); 616 617 if (ao_cec->data->ctrl2_setup) 618 regmap_write(ao_cec->regmap_cec, CECB_CTRL2, 619 FIELD_PREP(CECB_CTRL2_RISE_DEL_MAX, 2)); 620 621 meson_ao_cec_g12a_irq_setup(ao_cec, true); 622 623 return 0; 624} 625 626static const struct cec_adap_ops meson_ao_cec_g12a_ops = { 627 .adap_enable = meson_ao_cec_g12a_adap_enable, 628 .adap_log_addr = meson_ao_cec_g12a_set_log_addr, 629 .adap_transmit = meson_ao_cec_g12a_transmit, 630}; 631 632static int meson_ao_cec_g12a_probe(struct platform_device *pdev) 633{ 634 struct meson_ao_cec_g12a_device *ao_cec; 635 struct device *hdmi_dev; 636 void __iomem *base; 637 int ret, irq; 638 639 hdmi_dev = cec_notifier_parse_hdmi_phandle(&pdev->dev); 640 if (IS_ERR(hdmi_dev)) 641 return PTR_ERR(hdmi_dev); 642 643 ao_cec = devm_kzalloc(&pdev->dev, sizeof(*ao_cec), GFP_KERNEL); 644 if (!ao_cec) 645 return -ENOMEM; 646 647 ao_cec->data = of_device_get_match_data(&pdev->dev); 648 if (!ao_cec->data) { 649 dev_err(&pdev->dev, "failed to get match data\n"); 650 return -ENODEV; 651 } 652 653 spin_lock_init(&ao_cec->cec_reg_lock); 654 ao_cec->pdev = pdev; 655 656 ao_cec->adap = cec_allocate_adapter(&meson_ao_cec_g12a_ops, ao_cec, 657 "meson_g12a_ao_cec", 658 CEC_CAP_DEFAULTS | 659 CEC_CAP_CONNECTOR_INFO, 660 CEC_MAX_LOG_ADDRS); 661 if (IS_ERR(ao_cec->adap)) 662 return PTR_ERR(ao_cec->adap); 663 664 ao_cec->adap->owner = THIS_MODULE; 665 666 base = devm_platform_ioremap_resource(pdev, 0); 667 if (IS_ERR(base)) { 668 ret = PTR_ERR(base); 669 goto out_probe_adapter; 670 } 671 672 ao_cec->regmap = devm_regmap_init_mmio(&pdev->dev, base, 673 &meson_ao_cec_g12a_regmap_conf); 674 if (IS_ERR(ao_cec->regmap)) { 675 ret = PTR_ERR(ao_cec->regmap); 676 goto out_probe_adapter; 677 } 678 679 ao_cec->regmap_cec = devm_regmap_init(&pdev->dev, NULL, ao_cec, 680 &meson_ao_cec_g12a_cec_regmap_conf); 681 if (IS_ERR(ao_cec->regmap_cec)) { 682 ret = PTR_ERR(ao_cec->regmap_cec); 683 goto out_probe_adapter; 684 } 685 686 irq = platform_get_irq(pdev, 0); 687 ret = devm_request_threaded_irq(&pdev->dev, irq, 688 meson_ao_cec_g12a_irq, 689 meson_ao_cec_g12a_irq_thread, 690 0, NULL, ao_cec); 691 if (ret) { 692 dev_err(&pdev->dev, "irq request failed\n"); 693 goto out_probe_adapter; 694 } 695 696 ao_cec->oscin = devm_clk_get(&pdev->dev, "oscin"); 697 if (IS_ERR(ao_cec->oscin)) { 698 dev_err(&pdev->dev, "oscin clock request failed\n"); 699 ret = PTR_ERR(ao_cec->oscin); 700 goto out_probe_adapter; 701 } 702 703 ret = meson_ao_cec_g12a_setup_clk(ao_cec); 704 if (ret) 705 goto out_probe_adapter; 706 707 ret = clk_prepare_enable(ao_cec->core); 708 if (ret) { 709 dev_err(&pdev->dev, "core clock enable failed\n"); 710 goto out_probe_adapter; 711 } 712 713 device_reset_optional(&pdev->dev); 714 715 platform_set_drvdata(pdev, ao_cec); 716 717 ao_cec->notify = cec_notifier_cec_adap_register(hdmi_dev, NULL, 718 ao_cec->adap); 719 if (!ao_cec->notify) { 720 ret = -ENOMEM; 721 goto out_probe_core_clk; 722 } 723 724 ret = cec_register_adapter(ao_cec->adap, &pdev->dev); 725 if (ret < 0) 726 goto out_probe_notify; 727 728 /* Setup Hardware */ 729 regmap_write(ao_cec->regmap, CECB_GEN_CNTL_REG, CECB_GEN_CNTL_RESET); 730 731 return 0; 732 733out_probe_notify: 734 cec_notifier_cec_adap_unregister(ao_cec->notify, ao_cec->adap); 735 736out_probe_core_clk: 737 clk_disable_unprepare(ao_cec->core); 738 739out_probe_adapter: 740 cec_delete_adapter(ao_cec->adap); 741 742 dev_err(&pdev->dev, "CEC controller registration failed\n"); 743 744 return ret; 745} 746 747static int meson_ao_cec_g12a_remove(struct platform_device *pdev) 748{ 749 struct meson_ao_cec_g12a_device *ao_cec = platform_get_drvdata(pdev); 750 751 clk_disable_unprepare(ao_cec->core); 752 753 cec_notifier_cec_adap_unregister(ao_cec->notify, ao_cec->adap); 754 755 cec_unregister_adapter(ao_cec->adap); 756 757 return 0; 758} 759 760static const struct meson_ao_cec_g12a_data ao_cec_g12a_data = { 761 .ctrl2_setup = false, 762}; 763 764static const struct meson_ao_cec_g12a_data ao_cec_sm1_data = { 765 .ctrl2_setup = true, 766}; 767 768static const struct of_device_id meson_ao_cec_g12a_of_match[] = { 769 { 770 .compatible = "amlogic,meson-g12a-ao-cec", 771 .data = &ao_cec_g12a_data, 772 }, 773 { 774 .compatible = "amlogic,meson-sm1-ao-cec", 775 .data = &ao_cec_sm1_data, 776 }, 777 { /* sentinel */ } 778}; 779MODULE_DEVICE_TABLE(of, meson_ao_cec_g12a_of_match); 780 781static struct platform_driver meson_ao_cec_g12a_driver = { 782 .probe = meson_ao_cec_g12a_probe, 783 .remove = meson_ao_cec_g12a_remove, 784 .driver = { 785 .name = "meson-ao-cec-g12a", 786 .of_match_table = of_match_ptr(meson_ao_cec_g12a_of_match), 787 }, 788}; 789 790module_platform_driver(meson_ao_cec_g12a_driver); 791 792MODULE_DESCRIPTION("Meson AO CEC G12A Controller driver"); 793MODULE_AUTHOR("Neil Armstrong <narmstrong@baylibre.com>"); 794MODULE_LICENSE("GPL");