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 stih_cec *cec;
 303        struct device *hdmi_dev;
 304        int ret;
 305
 306        hdmi_dev = cec_notifier_parse_hdmi_phandle(dev);
 307
 308        if (IS_ERR(hdmi_dev))
 309                return PTR_ERR(hdmi_dev);
 310
 311        cec = devm_kzalloc(dev, sizeof(*cec), GFP_KERNEL);
 312        if (!cec)
 313                return -ENOMEM;
 314
 315        cec->dev = dev;
 316
 317        cec->regs = devm_platform_ioremap_resource(pdev, 0);
 318        if (IS_ERR(cec->regs))
 319                return PTR_ERR(cec->regs);
 320
 321        cec->irq = platform_get_irq(pdev, 0);
 322        if (cec->irq < 0)
 323                return cec->irq;
 324
 325        ret = devm_request_threaded_irq(dev, cec->irq, stih_cec_irq_handler,
 326                                        stih_cec_irq_handler_thread, 0,
 327                                        pdev->name, cec);
 328        if (ret)
 329                return ret;
 330
 331        cec->clk = devm_clk_get(dev, "cec-clk");
 332        if (IS_ERR(cec->clk)) {
 333                dev_err(dev, "Cannot get cec clock\n");
 334                return PTR_ERR(cec->clk);
 335        }
 336
 337        cec->adap = cec_allocate_adapter(&sti_cec_adap_ops, cec, CEC_NAME,
 338                                         CEC_CAP_DEFAULTS |
 339                                         CEC_CAP_CONNECTOR_INFO,
 340                                         CEC_MAX_LOG_ADDRS);
 341        ret = PTR_ERR_OR_ZERO(cec->adap);
 342        if (ret)
 343                return ret;
 344
 345        cec->notifier = cec_notifier_cec_adap_register(hdmi_dev, NULL,
 346                                                       cec->adap);
 347        if (!cec->notifier) {
 348                ret = -ENOMEM;
 349                goto err_delete_adapter;
 350        }
 351
 352        ret = cec_register_adapter(cec->adap, &pdev->dev);
 353        if (ret)
 354                goto err_notifier;
 355
 356        platform_set_drvdata(pdev, cec);
 357        return 0;
 358
 359err_notifier:
 360        cec_notifier_cec_adap_unregister(cec->notifier, cec->adap);
 361
 362err_delete_adapter:
 363        cec_delete_adapter(cec->adap);
 364        return ret;
 365}
 366
 367static int stih_cec_remove(struct platform_device *pdev)
 368{
 369        struct stih_cec *cec = platform_get_drvdata(pdev);
 370
 371        cec_notifier_cec_adap_unregister(cec->notifier, cec->adap);
 372        cec_unregister_adapter(cec->adap);
 373
 374        return 0;
 375}
 376
 377static const struct of_device_id stih_cec_match[] = {
 378        {
 379                .compatible     = "st,stih-cec",
 380        },
 381        {},
 382};
 383MODULE_DEVICE_TABLE(of, stih_cec_match);
 384
 385static struct platform_driver stih_cec_pdrv = {
 386        .probe  = stih_cec_probe,
 387        .remove = stih_cec_remove,
 388        .driver = {
 389                .name           = CEC_NAME,
 390                .of_match_table = stih_cec_match,
 391        },
 392};
 393
 394module_platform_driver(stih_cec_pdrv);
 395
 396MODULE_AUTHOR("Benjamin Gaignard <benjamin.gaignard@linaro.org>");
 397MODULE_LICENSE("GPL");
 398MODULE_DESCRIPTION("STIH4xx CEC driver");
 399