cec_acts.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484
  1. /*
  2. * Copyright (c) 2020 Actions Semiconductor Co., Ltd
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. /**
  7. * @file
  8. * @brief HDMI CEC driver for Actions SoC
  9. */
  10. #include <errno.h>
  11. #include <kernel.h>
  12. #include <drivers/cec.h>
  13. #include <soc.h>
  14. #include <board_cfg.h>
  15. #include <logging/log.h>
  16. LOG_MODULE_REGISTER(cec0, CONFIG_LOG_DEFAULT_LEVEL);
  17. #ifndef BIT
  18. #define BIT(n) (1UL << (n))
  19. #endif
  20. #define CEC_TIMEOUT_MS (2000) /* transact timeout 2000ms */
  21. /* cec cr */
  22. #define CEC_MODE_SHIFT (30)
  23. #define CEC_MODE_MASK (0x3 << CEC_MODE_SHIFT)
  24. #define CEC_MODE_ENABLE (1 << CEC_MODE_SHIFT)
  25. #define CEC_ACKSTATUS BIT(29)
  26. #define CEC_LOGICAL_ADDR_SHIFT (24)
  27. #define CEC_LOGICAL_ADDR_MASK (0xF << CEC_LOGICAL_ADDR_SHIFT)
  28. #define CEC_LOGICAL_ADDR(x) ((x) << CEC_LOGICAL_ADDR_SHIFT)
  29. #define CEC_TIMER_DIV_SHIFT (16)
  30. #define CEC_TIMER_DIV_MASK (0xFF << CEC_TIMER_DIV_SHIFT)
  31. #define CEC_TIMER_DIV(x) ((x) << CEC_TIMER_DIV_SHIFT)
  32. #define CEC_PRE_DIV_SHIFT (8)
  33. #define CEC_PRE_DIV_MASK (0xFF << CEC_PRE_DIV_SHIFT)
  34. #define CEC_PRE_DIV(x) ((x) << CEC_PRE_DIV_SHIFT)
  35. #define CEC_ACK_MODE BIT(7)
  36. /* cec rtcr */
  37. #define CEC_PAD_IN BIT(31)
  38. #define CEC_WT_CNT_SHIFT (5)
  39. #define CEC_WT_CNT_MASK (0x3F << CEC_WT_CNT_SHIFT)
  40. #define CEC_LATTEST BIT(4)
  41. #define CEC_RETRY_NO_SHIFT (0)
  42. #define CEC_RETRY_NO_MASK (0xF << CEC_RETRY_NO_SHIFT)
  43. #define CEC_RETRY_NO(x) ((x) << CEC_RETRY_NO_SHIFT)
  44. /* cec rxcr */
  45. #define CEC_RX_MTYPE BIT(16)
  46. #define CEC_RX_EN BIT(15)
  47. #define CEC_RX_RST BIT(14)
  48. #define CEC_RX_CONTINUOUS BIT(13)
  49. #define CEC_RX_INT_EN BIT(12)
  50. #define CEC_INIT_ADDR_SHIFT (8)
  51. #define CEC_INIT_ADDR_MASK (0xF << CEC_INIT_ADDR_SHIFT)
  52. #define CEC_INIT_ADDR(x) ((x) << CEC_INIT_ADDR_SHIFT)
  53. #define CEC_RX_EOM BIT(7)
  54. #define CEC_RX_INT BIT(6)
  55. #define CEC_RX_FIFO_OV BIT(5)
  56. #define CEC_RX_FIFO_CNT_SHIFT (0)
  57. #define CEC_RX_FIFO_CNT_MASK (0x1F << CEC_RX_FIFO_CNT_SHIFT)
  58. /* cec txcr */
  59. #define CEC_TX_ADDR_EN BIT(20)
  60. #define CEC_TX_ADDR_SHIFT (16)
  61. #define CEC_TX_ADDR_MASK (0xF << CEC_TX_ADDR_SHIFT)
  62. #define CEC_TX_ADDR(x) ((x) << CEC_TX_ADDR_SHIFT)
  63. #define CEC_TX_EN BIT(15)
  64. #define CEC_TX_RST BIT(14)
  65. #define CEC_TX_CONTINUOUS BIT(13)
  66. #define CEC_TX_INT_EN BIT(12)
  67. #define CEC_DEST_ADDR_SHIFT (8)
  68. #define CEC_DEST_ADDR_MASK (0xF << CEC_DEST_ADDR_SHIFT)
  69. #define CEC_DEST_ADDR(x) ((x) << CEC_DEST_ADDR_SHIFT)
  70. #define CEC_TX_EOM BIT(7)
  71. #define CEC_TX_INT BIT(6)
  72. #define CEC_TX_FIFO_UD BIT(5)
  73. #define CEC_TX_FIFO_CNT_SHIFT (0)
  74. #define CEC_TX_FIFO_CNT_MASK (0x1F << CEC_TX_FIFO_CNT_SHIFT)
  75. /* cec rxtcr */
  76. #define CEC_RX_START_LOW_SHIFT (24)
  77. #define CEC_RX_START_LOW_MASK (0xFF << CEC_RX_START_LOW_SHIFT)
  78. #define CEC_RX_START_PERIOD_SHIFT (16)
  79. #define CEC_RX_START_PERIOD_MASK (0xFF << CEC_RX_START_PERIOD_SHIFT)
  80. #define CEC_RX_DATA_SAMPLE_SHIFT (8)
  81. #define CEC_RX_DATA_SAMPLE_MASK (0xFF << CEC_RX_DATA_SAMPLE_SHIFT)
  82. #define CEC_RX_DATA_PERIOD_SHIFT (0)
  83. #define CEC_RX_DATA_PERIOD_MASK (0xFF << CEC_RX_DATA_PERIOD_SHIFT)
  84. /* cec txtcr0 */
  85. #define CEC_TX_START_LOW_SHIFT (8)
  86. #define CEC_TX_START_LOW_MASK (0xFF << CEC_TX_START_LOW_SHIFT)
  87. #define CEC_TX_START_HIGH_SHIFT (0)
  88. #define CEC_TX_START_HIGH_MASK (0xFF << CEC_TX_START_HIGH_SHIFT)
  89. /* cec txtcr1 */
  90. #define CEC_TX_DATA_LOW_SHIFT (16)
  91. #define CEC_TX_DATA_LOW_MASK (0xFF << CEC_TX_DATA_LOW_SHIFT)
  92. #define CEC_TX_DATA_MID_SHIFT (8)
  93. #define CEC_TX_DATA_MID_MASK (0xFF << CEC_TX_DATA_01_SHIFT)
  94. #define CEC_TX_DATA_HIGH_SHIFT (0)
  95. #define CEC_TX_DATA_HIGH_MASK (0xFF << CEC_TX_DATA_HIGH_SHIFT)
  96. /* cec pad */
  97. #define CEC_REG_CEC_ENB BIT(0)
  98. #define CEC_RETRY_MAX_NUM (5)
  99. #define CEC_RXTCR_DEFAULT (0x8cbc2a51)
  100. #define CEC_TXTCR0_DEFAULT (0x9420)
  101. #define CEC_TXTCR1_DEFAULT (0x182424)
  102. /* CEC state enumration */
  103. enum cec_state {
  104. CEC_STATE_NORMAL = 0,
  105. CEC_STATE_ERROR
  106. };
  107. /* CEC controller */
  108. struct cec_acts_controller {
  109. volatile uint32_t cr; /* cec control register */
  110. volatile uint32_t rtcr; /* cec re-transmission control register */
  111. volatile uint32_t rxcr; /* cec rx control register */
  112. volatile uint32_t txcr; /* cec tx control register */
  113. volatile uint32_t txdr; /* cec tx data register */
  114. volatile uint32_t rxdr; /* cec rx data register */
  115. volatile uint32_t rxtcr; /* cec rx timing control register */
  116. volatile uint32_t txtcr0; /* cec tx timing control register 0 */
  117. volatile uint32_t txtcr1; /* cec tx timing control register 1 */
  118. volatile uint32_t pad; /* cec pad register */
  119. };
  120. /* cec device configration data */
  121. struct acts_cec_config {
  122. struct cec_acts_controller *base;
  123. void (*irq_config_func)(void);
  124. uint16_t clock_id;
  125. uint16_t reset_id;
  126. uint8_t local_address;
  127. };
  128. /* cec driver private data */
  129. struct acts_cec_data {
  130. struct k_mutex mutex;
  131. struct k_sem rx_done;
  132. struct k_sem tx_done;
  133. enum cec_state state;
  134. };
  135. static void cec_acts_dump_regs(struct cec_acts_controller *cec)
  136. {
  137. LOG_INF("CEC base 0x%x:\n"
  138. " cr: %08x rtcr: %08x rxcr: %08x\n"
  139. " txcr: %08x txdr: %08x rxdr: %08x\n"
  140. " rxtcr: %08x txtcr0: %08x txtcr1: %08x\n"
  141. " pad: %08x\n",
  142. (unsigned int)cec,
  143. cec->cr, cec->rtcr, cec->rxcr,
  144. cec->txcr, cec->txdr, cec->rxdr,
  145. cec->rxtcr, cec->txtcr0, cec->txtcr1,
  146. cec->pad);
  147. }
  148. static int cec_rx_reset(struct cec_acts_controller *cec)
  149. {
  150. /* Write 1 to clear rx state and its FIFO */
  151. cec->rxcr |= CEC_RX_RST;
  152. while (cec->rxcr & CEC_RX_RST)
  153. ;
  154. return 0;
  155. }
  156. static int cec_rx_disable(struct cec_acts_controller *cec)
  157. {
  158. /* Disable RX IRQ */
  159. cec->rxcr &= ~CEC_RX_INT_EN;
  160. /* Clear RX IRQ pending */
  161. cec->rxcr |= CEC_RX_INT;
  162. return cec_rx_reset(cec);
  163. }
  164. static int cec_tx_reset(struct cec_acts_controller *cec)
  165. {
  166. /* write 1 to clear tx state and its FIFO */
  167. cec->txcr |= CEC_TX_RST;
  168. while (cec->txcr & CEC_TX_RST)
  169. ;
  170. return 0;
  171. }
  172. static int cec_tx_disable(struct cec_acts_controller *cec)
  173. {
  174. /* Disable TX IRQ */
  175. cec->txcr &= ~CEC_TX_INT_EN;
  176. /* Clear TX IRQ pending */
  177. cec->txcr |= CEC_TX_INT;
  178. return cec_tx_reset(cec);
  179. }
  180. static int cec_rx_enable(struct cec_acts_controller *cec)
  181. {
  182. /* RX and IRQ enable */
  183. cec->rxcr |= (CEC_RX_EN | CEC_RX_INT_EN);
  184. /* Clear RX IRQ pending */
  185. cec->rxcr |= CEC_RX_INT;
  186. return 0;
  187. }
  188. static int cec_tx_enable(struct cec_acts_controller *cec)
  189. {
  190. /* TX and IRQ enable */
  191. cec->txcr |= (CEC_TX_EN | CEC_TX_INT_EN);
  192. /* Clear TX IRQ pending */
  193. cec->txcr |= CEC_TX_INT;
  194. return 0;
  195. }
  196. static int cec_set_local_address(const struct device *dev, uint8_t local_addr)
  197. {
  198. const struct acts_cec_config *config = dev->config;
  199. struct cec_acts_controller *cec = config->base;
  200. /* config initiator address */
  201. cec->cr &= ~CEC_LOGICAL_ADDR_MASK;
  202. cec->cr |= CEC_LOGICAL_ADDR(local_addr);
  203. return 0;
  204. }
  205. static void cec_update_state(const struct device *dev, enum cec_state state)
  206. {
  207. struct acts_cec_data *data = dev->data;
  208. data->state = state;
  209. }
  210. static int cec_control_init(const struct device *dev)
  211. {
  212. const struct acts_cec_config *config = dev->config;
  213. struct cec_acts_controller *cec = config->base;
  214. uint32_t reg;
  215. int ret;
  216. /* use default value #CEC_RETRY_MAX_NUM to set retry time */
  217. reg = cec->rtcr & ~CEC_RETRY_NO_MASK;
  218. cec->rtcr = reg | CEC_RETRY_NO(CEC_RETRY_MAX_NUM);
  219. cec->rxtcr = CEC_RXTCR_DEFAULT;
  220. cec->txtcr0 = CEC_TXTCR0_DEFAULT;
  221. cec->txtcr1 = CEC_TXTCR1_DEFAULT;
  222. cec->pad = 0;
  223. /* setup CEC clock 0.8Mhz */
  224. cec->cr = (cec->cr & ~CEC_PRE_DIV_MASK) | CEC_PRE_DIV(40);
  225. /* Enable CEC mode */
  226. cec->cr = (cec->cr & ~CEC_MODE_MASK) | CEC_MODE_ENABLE;
  227. cec_rx_disable(cec);
  228. cec_tx_disable(cec);
  229. /* By defalut to enable cec rx */
  230. ret = cec_rx_enable(cec);
  231. /* Setup local address */
  232. cec_set_local_address(dev, config->local_address);
  233. if (!ret)
  234. cec_update_state(dev, CEC_STATE_NORMAL);
  235. return ret;
  236. }
  237. static int acts_cec_write(const struct device *dev, const struct cec_msg *msg, uint32_t timeout_ms)
  238. {
  239. const struct acts_cec_config *config = dev->config;
  240. struct cec_acts_controller *cec = config->base;
  241. struct acts_cec_data *data = dev->data;
  242. uint8_t i;
  243. int ret;
  244. if ((!msg) || (msg->len > CEC_TRANSFER_MAX_SIZE)
  245. || (!msg->len)) {
  246. LOG_ERR("invalid msg");
  247. return -EINVAL;
  248. }
  249. k_mutex_lock(&data->mutex, K_FOREVER);
  250. cec_update_state(dev, CEC_STATE_NORMAL);
  251. /* disable rx mode */
  252. cec_rx_disable(cec);
  253. cec_tx_reset(cec);
  254. for (i = 0; i < msg->len; i++)
  255. cec->txdr = msg->buf[i];
  256. /* config destination address */
  257. cec->txcr &= ~CEC_DEST_ADDR_MASK;
  258. cec->txcr |= CEC_DEST_ADDR(msg->destination);
  259. /* config initiator address */
  260. cec_set_local_address(dev, msg->initiator);
  261. cec_tx_enable(cec);
  262. /* wait cec tx data transfer is done */
  263. ret = k_sem_take(&data->tx_done, K_MSEC(timeout_ms));
  264. if (ret) {
  265. LOG_ERR("wait tx timeout");
  266. ret = -EIO;
  267. goto out;
  268. }
  269. if (data->state == CEC_STATE_ERROR) {
  270. LOG_ERR("cec tx error");
  271. ret = -EFAULT;
  272. }
  273. out:
  274. if (ret)
  275. cec_acts_dump_regs(cec);
  276. /* disable cec tx */
  277. cec_tx_disable(cec);
  278. /* enable cec rx */
  279. cec_rx_enable(cec);
  280. k_mutex_unlock(&data->mutex);
  281. return ret;
  282. }
  283. static int acts_cec_read(const struct device *dev, struct cec_msg *msg, uint32_t timeout_ms)
  284. {
  285. const struct acts_cec_config *config = dev->config;
  286. struct cec_acts_controller *cec = config->base;
  287. struct acts_cec_data *data = dev->data;
  288. uint8_t i, rx_cnt;
  289. int ret;
  290. if (!msg) {
  291. LOG_ERR("invalid msg");
  292. return -EINVAL;
  293. }
  294. k_mutex_lock(&data->mutex, K_FOREVER);
  295. cec_update_state(dev, CEC_STATE_NORMAL);
  296. /* wait cec rx data transfer is done */
  297. ret = k_sem_take(&data->rx_done, K_MSEC(timeout_ms));
  298. if (ret) {
  299. LOG_ERR("wait rx timeout");
  300. ret = -EIO;
  301. goto out;
  302. }
  303. if (data->state == CEC_STATE_ERROR) {
  304. LOG_ERR("cec rx error");
  305. ret = -EFAULT;
  306. goto out;
  307. }
  308. msg->initiator = (cec->rxcr & CEC_INIT_ADDR_MASK) >> CEC_INIT_ADDR_SHIFT;
  309. /* check if a broadcast message */
  310. if (cec->rxcr & CEC_RX_MTYPE)
  311. msg->destination = 0xF;
  312. else
  313. msg->destination = (cec->cr & CEC_LOGICAL_ADDR_MASK) >> CEC_LOGICAL_ADDR_SHIFT;
  314. rx_cnt = cec->rxcr & CEC_RX_FIFO_CNT_MASK;
  315. for (i = 0; i < rx_cnt; i++) {
  316. if (i >= CEC_TRANSFER_MAX_SIZE) {
  317. LOG_ERR("invalid rx fifo count %d", rx_cnt);
  318. ret = -EINVAL;
  319. goto out;
  320. }
  321. msg->buf[i] = cec->rxdr;
  322. }
  323. msg->len = rx_cnt;
  324. out:
  325. if (ret)
  326. cec_acts_dump_regs(cec);
  327. /* rx reset */
  328. cec_rx_reset(cec);
  329. /* enable cec rx */
  330. cec_rx_enable(cec);
  331. k_mutex_unlock(&data->mutex);
  332. return ret;
  333. }
  334. int acts_cec_init(const struct device *dev)
  335. {
  336. const struct acts_cec_config *config = dev->config;
  337. struct acts_cec_data *data = dev->data;
  338. /* enable cec controller clock */
  339. acts_clock_peripheral_enable(config->clock_id);
  340. /* reset cec controller */
  341. acts_reset_peripheral(config->reset_id);
  342. k_mutex_init(&data->mutex);
  343. k_sem_init(&data->rx_done, 0, 1);
  344. k_sem_init(&data->tx_done, 0, 1);
  345. config->irq_config_func();
  346. cec_control_init(dev);
  347. printk("cec initialized\n");
  348. return 0;
  349. }
  350. const struct cec_driver_api cec_acts_driver_api = {
  351. .config = cec_set_local_address,
  352. .write = acts_cec_write,
  353. .read = acts_cec_read,
  354. };
  355. void acts_cec_isr(void *arg)
  356. {
  357. const struct device *dev = (const struct device *)arg;
  358. const struct acts_cec_config *config = dev->config;
  359. struct acts_cec_data *data = dev->data;
  360. struct cec_acts_controller *cec = config->base;
  361. LOG_DBG("cr:0x%x txcr:0x%x rxcr:0x%x", cec->cr, cec->txcr, cec->rxcr);
  362. if (cec->txcr & CEC_TX_INT) {
  363. /* check tx eom */
  364. if (!(cec->txcr & CEC_TX_EOM))
  365. data->state = CEC_STATE_ERROR;
  366. /* check ack status */
  367. if (!(cec->cr & CEC_ACKSTATUS))
  368. data->state = CEC_STATE_ERROR;
  369. cec->txcr |= CEC_TX_INT;
  370. k_sem_give(&data->tx_done);
  371. }
  372. if (cec->rxcr & CEC_RX_INT) {
  373. /* check rx fifo overflow */
  374. if (cec->rxcr & CEC_RX_FIFO_OV)
  375. data->state = CEC_STATE_ERROR;
  376. cec->rxcr |= CEC_RX_INT;
  377. k_sem_give(&data->rx_done);
  378. }
  379. }
  380. #if IS_ENABLED(CONFIG_CEC)
  381. static void cec_acts_config_func_0(void);
  382. static const struct acts_cec_config acts_cec_config_0 = {
  383. .base = (struct cec_acts_controller *)CEC_REG_BASE,
  384. .irq_config_func = cec_acts_config_func_0,
  385. .clock_id = CLOCK_ID_CEC,
  386. .reset_id = RESET_ID_CEC,
  387. .local_address = CONFIG_CEC_0_LOCAL_ADDRESS,
  388. };
  389. static struct acts_cec_data acts_cec_data_0;
  390. #if IS_ENABLED(CONFIG_CEC)
  391. DEVICE_DEFINE(cec0, CONFIG_CEC_DEV_NAME, &acts_cec_init, NULL,
  392. &acts_cec_data_0, &acts_cec_config_0,
  393. POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE,
  394. &cec_acts_driver_api);
  395. #endif
  396. static void cec_acts_config_func_0(void)
  397. {
  398. IRQ_CONNECT(IRQ_ID_CEC, CONFIG_CEC_0_IRQ_PRI,
  399. acts_cec_isr, DEVICE_GET(cec0), 0);
  400. irq_enable(IRQ_ID_CEC);
  401. }
  402. #endif