linux/drivers/media/cec/platform/sti/stih-cec.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * STIH4xx CEC driver
   4 * Copyright (C) STMicroelectronics SA 2016
   5 *
   6 */
   7#include <linux/clk.h>
   8#include <linux/interrupt.h>
   9#include <linux/kernel.h>
  10#include <linux/mfd/syscon.h>
  11#include <linux/module.h>
  12#include <linux/of.h>
  13#include <linux/of_platform.h>
  14#include <linux/platform_device.h>
  15
  16#include <media/cec.h>
  17#include <media/cec-notifier.h>
  18
  19#define CEC_NAME        "stih-cec"
  20
  21/* CEC registers  */
  22#define CEC_CLK_DIV           0x0
  23#define CEC_CTRL              0x4
  24#define CEC_IRQ_CTRL          0x8
  25#define CEC_STATUS            0xC
  26#define CEC_EXT_STATUS        0x10
  27#define CEC_TX_CTRL           0x14
  28#define CEC_FREE_TIME_THRESH  0x18
  29#define CEC_BIT_TOUT_THRESH   0x1C
  30#define CEC_BIT_PULSE_THRESH  0x20
  31#define CEC_DATA              0x24
  32#define CEC_TX_ARRAY_CTRL     0x28
  33#define CEC_CTRL2             0x2C
  34#define CEC_TX_ERROR_STS      0x30
  35#define CEC_ADDR_TABLE        0x34
  36#define CEC_DATA_ARRAY_CTRL   0x38
  37#define CEC_DATA_ARRAY_STATUS 0x3C
  38#define CEC_TX_DATA_BASE      0x40
  39#define CEC_TX_DATA_TOP       0x50
  40#define CEC_TX_DATA_SIZE      0x1
  41#define CEC_RX_DATA_BASE      0x54
  42#define CEC_RX_DATA_TOP       0x64
  43#define CEC_RX_DATA_SIZE      0x1
  44
  45/* CEC_CTRL2 */
  46#define CEC_LINE_INACTIVE_EN   BIT(0)
  47#define CEC_AUTO_BUS_ERR_EN    BIT(1)
  48#define CEC_STOP_ON_ARB_ERR_EN BIT(2)
  49#define CEC_TX_REQ_WAIT_EN     BIT(3)
  50
  51/* CEC_DATA_ARRAY_CTRL */
  52#define CEC_TX_ARRAY_EN          BIT(0)
  53#define CEC_RX_ARRAY_EN          BIT(1)
  54#define CEC_TX_ARRAY_RESET       BIT(2)
  55#define CEC_RX_ARRAY_RESET       BIT(3)
  56#define CEC_TX_N_OF_BYTES_IRQ_EN BIT(4)
  57#define CEC_TX_STOP_ON_NACK      BIT(7)
  58
  59/* CEC_TX_ARRAY_CTRL */
  60#define CEC_TX_N_OF_BYTES  0x1F
  61#define CEC_TX_START       BIT(5)
  62#define CEC_TX_AUTO_SOM_EN BIT(6)
  63#define CEC_TX_AUTO_EOM_EN BIT(7)
  64
  65/* CEC_IRQ_CTRL */
  66#define CEC_TX_DONE_IRQ_EN   BIT(0)
  67#define CEC_ERROR_IRQ_EN     BIT(2)
  68#define CEC_RX_DONE_IRQ_EN   BIT(3)
  69#define CEC_RX_SOM_IRQ_EN    BIT(4)
  70#define CEC_RX_EOM_IRQ_EN    BIT(5)
  71#define CEC_FREE_TIME_IRQ_EN BIT(6)
  72#define CEC_PIN_STS_IRQ_EN   BIT(7)
  73
  74/* CEC_CTRL */
  75#define CEC_IN_FILTER_EN    BIT(0)
  76#define CEC_PWR_SAVE_EN     BIT(1)
  77#define CEC_EN              BIT(4)
  78#define CEC_ACK_CTRL        BIT(5)
  79#define CEC_RX_RESET_EN     BIT(6)
  80#define CEC_IGNORE_RX_ERROR BIT(7)
  81
  82/* CEC_STATUS */
  83#define CEC_TX_DONE_STS       BIT(0)
  84#define CEC_TX_ACK_GET_STS    BIT(1)
  85#define CEC_ERROR_STS         BIT(2)
  86#define CEC_RX_DONE_STS       BIT(3)
  87#define CEC_RX_SOM_STS        BIT(4)
  88#define CEC_RX_EOM_STS        BIT(5)
  89#define CEC_FREE_TIME_IRQ_STS BIT(6)
  90#define CEC_PIN_STS           BIT(7)
  91#define CEC_SBIT_TOUT_STS     BIT(8)
  92#define CEC_DBIT_TOUT_STS     BIT(9)
  93#define CEC_LPULSE_ERROR_STS  BIT(10)
  94#define CEC_HPULSE_ERROR_STS  BIT(11)
  95#define CEC_TX_ERROR          BIT(12)
  96#define CEC_TX_ARB_ERROR      BIT(13)
  97#define CEC_RX_ERROR_MIN      BIT(14)
  98#define CEC_RX_ERROR_MAX      BIT(15)
  99
 100/* Signal free time in bit periods (2.4ms) */
 101#define CEC_PRESENT_INIT_SFT 7
 102#define CEC_NEW_INIT_SFT     5
 103#define CEC_RETRANSMIT_SFT   3
 104
 105/* Constants for CEC_BIT_TOUT_THRESH register */
 106#define CEC_SBIT_TOUT_47MS BIT(1)
 107#define CEC_SBIT_TOUT_48MS (BIT(0) | BIT(1))
 108#define CEC_SBIT_TOUT_50MS BIT(2)
 109#define CEC_DBIT_TOUT_27MS BIT(0)
 110#define CEC_DBIT_TOUT_28MS BIT(1)
 111#define CEC_DBIT_TOUT_29MS (BIT(0) | BIT(1))
 112
 113/* Constants for CEC_BIT_PULSE_THRESH register */
 114#define CEC_BIT_LPULSE_03MS BIT(1)
 115#define CEC_BIT_HPULSE_03MS BIT(3)
 116
 117/* Constants for CEC_DATA_ARRAY_STATUS register */
 118#define CEC_RX_N_OF_BYTES                     0x1F
 119#define CEC_TX_N_OF_BYTES_SENT                BIT(5)
 120#define CEC_RX_OVERRUN                        BIT(6)
 121
 122struct stih_cec {
 123        struct cec_adapter      *adap;
 124        struct device           *dev;
 125        struct clk              *clk;
 126        void __iomem            *regs;
 127        int                     irq;
 128        u32                     irq_status;
 129        struct cec_notifier     *notifier;
 130};
 131
 132static int stih_cec_adap_enable(struct cec_adapter *adap, bool enable)
 133{
 134        struct stih_cec *cec = cec_get_drvdata(adap);
 135
 136        if (enable) {
 137                /* The doc says (input TCLK_PERIOD * CEC_CLK_DIV) = 0.1ms */
 138                unsigned long clk_freq = clk_get_rate(cec->clk);
 139                u32 cec_clk_div = clk_freq / 10000;
 140
 141                writel(cec_clk_div, cec->regs + CEC_CLK_DIV);
 142
 143                /* Configuration of the durations activating a timeout */
 144                writel(CEC_SBIT_TOUT_47MS | (CEC_DBIT_TOUT_28MS << 4),
 145                       cec->regs + CEC_BIT_TOUT_THRESH);
 146
 147                /* Configuration of the smallest allowed duration for pulses */
 148                writel(CEC_BIT_LPULSE_03MS | CEC_BIT_HPULSE_03MS,
 149                       cec->regs + CEC_BIT_PULSE_THRESH);
 150
 151                /* Minimum received bit period threshold */
 152                writel(BIT(5) | BIT(7), cec->regs + CEC_TX_CTRL);
 153
 154                /* Configuration of transceiver data arrays */
 155                writel(CEC_TX_ARRAY_EN | CEC_RX_ARRAY_EN | CEC_TX_STOP_ON_NACK,
 156                       cec->regs + CEC_DATA_ARRAY_CTRL);
 157
 158                /* Configuration of the control bits for CEC Transceiver */
 159                writel(CEC_IN_FILTER_EN | CEC_EN | CEC_RX_RESET_EN,
 160                       cec->regs + CEC_CTRL);
 161
 162                /* Clear logical addresses */
 163                writel(0, cec->regs + CEC_ADDR_TABLE);
 164
 165                /* Clear the status register */
 166                writel(0x0, cec->regs + CEC_STATUS);
 167
 168                /* Enable the interrupts */
 169                writel(CEC_TX_DONE_IRQ_EN | CEC_RX_DONE_IRQ_EN |
 170                       CEC_RX_SOM_IRQ_EN | CEC_RX_EOM_IRQ_EN |
 171                       CEC_ERROR_IRQ_EN,
 172                       cec->regs + CEC_IRQ_CTRL);
 173
 174        } else {
 175                /* Clear logical addresses */
 176                writel(0, cec->regs + CEC_ADDR_TABLE);
 177
 178                /* Clear the status register */
 179                writel(0x0, cec->regs + CEC_STATUS);
 180
 181                /* Disable the interrupts */
 182                writel(0, cec->regs + CEC_IRQ_CTRL);
 183        }
 184
 185        return 0;
 186}
 187
 188static int stih_cec_adap_log_addr(struct cec_adapter *adap, u8 logical_addr)
 189{
 190        struct stih_cec *cec = cec_get_drvdata(adap);
 191        u32 reg = readl(cec->regs + CEC_ADDR_TABLE);
 192
 193        reg |= 1 << logical_addr;
 194
 195        if (logical_addr == CEC_LOG_ADDR_INVALID)
 196                reg = 0;
 197
 198        writel(reg, cec->regs + CEC_ADDR_TABLE);
 199
 200        return 0;
 201}
 202
 203static int stih_cec_adap_transmit(struct cec_adapter *adap, u8 attempts,
 204                                  u32 signal_free_time, struct cec_msg *msg)
 205{
 206        struct stih_cec *cec = cec_get_drvdata(adap);
 207        int i;
 208
 209        /* Copy message into registers */
 210        for (i = 0; i < msg->len; i++)
 211                writeb(msg->msg[i], cec->regs + CEC_TX_DATA_BASE + i);
 212
 213        /*
 214         * Start transmission, configure hardware to add start and stop bits
 215         * Signal free time is handled by the hardware
 216         */
 217        writel(CEC_TX_AUTO_SOM_EN | CEC_TX_AUTO_EOM_EN | CEC_TX_START |
 218               msg->len, cec->regs + CEC_TX_ARRAY_CTRL);
 219
 220        return 0;
 221}
 222
 223static void stih_tx_done(struct stih_cec *cec, u32 status)
 224{
 225        if (status & CEC_TX_ERROR) {
 226                cec_transmit_attempt_done(cec->adap, CEC_TX_STATUS_ERROR);
 227                return;
 228        }
 229
 230        if (status & CEC_TX_ARB_ERROR) {
 231                cec_transmit_attempt_done(cec->adap, CEC_TX_STATUS_ARB_LOST);
 232                return;
 233        }
 234
 235        if (!(status & CEC_TX_ACK_GET_STS)) {
 236                cec_transmit_attempt_done(cec->adap, CEC_TX_STATUS_NACK);
 237                return;
 238        }
 239
 240        cec_transmit_attempt_done(cec->adap, CEC_TX_STATUS_OK);
 241}
 242
 243static void stih_rx_done(struct stih_cec *cec, u32 status)
 244{
 245        struct cec_msg msg = {};
 246        u8 i;
 247
 248        if (status & CEC_RX_ERROR_MIN)
 249                return;
 250
 251        if (status & CEC_RX_ERROR_MAX)
 252                return;
 253
 254        msg.len = readl(cec->regs + CEC_DATA_ARRAY_STATUS) & 0x1f;
 255
 256        if (!msg.len)
 257                return;
 258
 259        if (msg.len > 16)
 260                msg.len = 16;
 261
 262        for (i = 0; i < msg.len; i++)
 263                msg.msg[i] = readl(cec->regs + CEC_RX_DATA_BASE + i);
 264
 265        cec_received_msg(cec->adap, &msg);
 266}
 267
 268static irqreturn_t stih_cec_irq_handler_thread(int irq, void *priv)
 269{
 270        struct stih_cec *cec = priv;
 271
 272        if (cec->irq_status & CEC_TX_DONE_STS)
 273                stih_tx_done(cec, cec->irq_status);
 274
 275        if (cec->irq_status & CEC_RX_DONE_STS)
 276                stih_rx_done(cec, cec->irq_status);
 277
 278        cec->irq_status = 0;
 279
 280        return IRQ_HANDLED;
 281}
 282
 283static irqreturn_t stih_cec_irq_handler(int irq, void *priv)
 284{
 285        struct stih_cec *cec = priv;
 286
 287        cec->irq_status = readl(cec->regs + CEC_STATUS);
 288        writel(cec->irq_status, cec->regs + CEC_STATUS);
 289
 290        return IRQ_WAKE_THREAD;
 291}
 292
 293static const struct cec_adap_ops sti_cec_adap_ops = {
 294        .adap_enable = stih_cec_adap_enable,
 295        .adap_log_addr = stih_cec_adap_log_addr,
 296        .adap_transmit = stih_cec_adap_transmit,
 297};
 298
 299static int stih_cec_probe(struct platform_device *pdev)
 300{
 301        struct device *dev = &pdev->dev;
 302        struct resource *res;
 303        struct stih_cec *cec;
 304        struct device *hdmi_dev;
 305        int ret;
 306
 307        hdmi_dev = cec_notifier_parse_hdmi_phandle(dev);
 308
 309        if (IS_ERR(hdmi_dev))
 310                return PTR_ERR(hdmi_dev);
 311
 312        cec = devm_kzalloc(dev, sizeof(*cec), GFP_KERNEL);
 313        if (!cec)
 314                return -ENOMEM;
 315
 316        cec->dev = dev;
 317
 318        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 319        cec->regs = devm_ioremap_resource(dev, res);
 320        if (IS_ERR(cec->regs))
 321                return PTR_ERR(cec->regs);
 322
 323        cec->irq = platform_get_irq(pdev, 0);
 324        if (cec->irq < 0)
 325                return cec->irq;
 326
 327        ret = devm_request_threaded_irq(dev, cec->irq, stih_cec_irq_handler,
 328                                        stih_cec_irq_handler_thread, 0,
 329                                        pdev->name, cec);
 330        if (ret)
 331                return ret;
 332
 333        cec->clk = devm_clk_get(dev, "cec-clk");
 334        if (IS_ERR(cec->clk)) {
 335                dev_err(dev, "Cannot get cec clock\n");
 336                return PTR_ERR(cec->clk);
 337        }
 338
 339        cec->adap = cec_allocate_adapter(&sti_cec_adap_ops, cec, CEC_NAME,
 340                                         CEC_CAP_DEFAULTS |
 341                                         CEC_CAP_CONNECTOR_INFO,
 342                                         CEC_MAX_LOG_ADDRS);
 343        ret = PTR_ERR_OR_ZERO(cec->adap);
 344        if (ret)
 345                return ret;
 346
 347        cec->notifier = cec_notifier_cec_adap_register(hdmi_dev, NULL,
 348                                                       cec->adap);
 349        if (!cec->notifier) {
 350                ret = -ENOMEM;
 351                goto err_delete_adapter;
 352        }
 353
 354        ret = cec_register_adapter(cec->adap, &pdev->dev);
 355        if (ret)
 356                goto err_notifier;
 357
 358        platform_set_drvdata(pdev, cec);
 359        return 0;
 360
 361err_notifier:
 362        cec_notifier_cec_adap_unregister(cec->notifier, cec->adap);
 363
 364err_delete_adapter:
 365        cec_delete_adapter(cec->adap);
 366        return ret;
 367}
 368
 369static int stih_cec_remove(struct platform_device *pdev)
 370{
 371        struct stih_cec *cec = platform_get_drvdata(pdev);
 372
 373        cec_notifier_cec_adap_unregister(cec->notifier, cec->adap);
 374        cec_unregister_adapter(cec->adap);
 375
 376        return 0;
 377}
 378
 379static const struct of_device_id stih_cec_match[] = {
 380        {
 381                .compatible     = "st,stih-cec",
 382        },
 383        {},
 384};
 385MODULE_DEVICE_TABLE(of, stih_cec_match);
 386
 387static struct platform_driver stih_cec_pdrv = {
 388        .probe  = stih_cec_probe,
 389        .remove = stih_cec_remove,
 390        .driver = {
 391                .name           = CEC_NAME,
 392                .of_match_table = stih_cec_match,
 393        },
 394};
 395
 396module_platform_driver(stih_cec_pdrv);
 397
 398MODULE_AUTHOR("Benjamin Gaignard <benjamin.gaignard@linaro.org>");
 399MODULE_LICENSE("GPL");
 400MODULE_DESCRIPTION("STIH4xx CEC driver");
 401