linux/drivers/media/platform/stm32/stm32-cec.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * STM32 CEC driver
   4 * Copyright (C) STMicroelectronics SA 2017
   5 *
   6 */
   7
   8#include <linux/clk.h>
   9#include <linux/interrupt.h>
  10#include <linux/kernel.h>
  11#include <linux/module.h>
  12#include <linux/of.h>
  13#include <linux/of_device.h>
  14#include <linux/platform_device.h>
  15#include <linux/regmap.h>
  16
  17#include <media/cec.h>
  18
  19#define CEC_NAME        "stm32-cec"
  20
  21/* CEC registers  */
  22#define CEC_CR          0x0000 /* Control Register */
  23#define CEC_CFGR        0x0004 /* ConFiGuration Register */
  24#define CEC_TXDR        0x0008 /* Rx data Register */
  25#define CEC_RXDR        0x000C /* Rx data Register */
  26#define CEC_ISR         0x0010 /* Interrupt and status Register */
  27#define CEC_IER         0x0014 /* Interrupt enable Register */
  28
  29#define TXEOM           BIT(2)
  30#define TXSOM           BIT(1)
  31#define CECEN           BIT(0)
  32
  33#define LSTN            BIT(31)
  34#define OAR             GENMASK(30, 16)
  35#define SFTOP           BIT(8)
  36#define BRDNOGEN        BIT(7)
  37#define LBPEGEN         BIT(6)
  38#define BREGEN          BIT(5)
  39#define BRESTP          BIT(4)
  40#define RXTOL           BIT(3)
  41#define SFT             GENMASK(2, 0)
  42#define FULL_CFG        (LSTN | SFTOP | BRDNOGEN | LBPEGEN | BREGEN | BRESTP \
  43                         | RXTOL)
  44
  45#define TXACKE          BIT(12)
  46#define TXERR           BIT(11)
  47#define TXUDR           BIT(10)
  48#define TXEND           BIT(9)
  49#define TXBR            BIT(8)
  50#define ARBLST          BIT(7)
  51#define RXACKE          BIT(6)
  52#define RXOVR           BIT(2)
  53#define RXEND           BIT(1)
  54#define RXBR            BIT(0)
  55
  56#define ALL_TX_IT       (TXEND | TXBR | TXACKE | TXERR | TXUDR | ARBLST)
  57#define ALL_RX_IT       (RXEND | RXBR | RXACKE | RXOVR)
  58
  59/*
  60 * 400 ms is the time it takes for one 16 byte message to be
  61 * transferred and 5 is the maximum number of retries. Add
  62 * another 100 ms as a margin.
  63 */
  64#define CEC_XFER_TIMEOUT_MS (5 * 400 + 100)
  65
  66struct stm32_cec {
  67        struct cec_adapter      *adap;
  68        struct device           *dev;
  69        struct clk              *clk_cec;
  70        struct clk              *clk_hdmi_cec;
  71        struct reset_control    *rstc;
  72        struct regmap           *regmap;
  73        int                     irq;
  74        u32                     irq_status;
  75        struct cec_msg          rx_msg;
  76        struct cec_msg          tx_msg;
  77        int                     tx_cnt;
  78};
  79
  80static void cec_hw_init(struct stm32_cec *cec)
  81{
  82        regmap_update_bits(cec->regmap, CEC_CR, TXEOM | TXSOM | CECEN, 0);
  83
  84        regmap_update_bits(cec->regmap, CEC_IER, ALL_TX_IT | ALL_RX_IT,
  85                           ALL_TX_IT | ALL_RX_IT);
  86
  87        regmap_update_bits(cec->regmap, CEC_CFGR, FULL_CFG, FULL_CFG);
  88}
  89
  90static void stm32_tx_done(struct stm32_cec *cec, u32 status)
  91{
  92        if (status & (TXERR | TXUDR)) {
  93                cec_transmit_done(cec->adap, CEC_TX_STATUS_ERROR,
  94                                  0, 0, 0, 1);
  95                return;
  96        }
  97
  98        if (status & ARBLST) {
  99                cec_transmit_done(cec->adap, CEC_TX_STATUS_ARB_LOST,
 100                                  1, 0, 0, 0);
 101                return;
 102        }
 103
 104        if (status & TXACKE) {
 105                cec_transmit_done(cec->adap, CEC_TX_STATUS_NACK,
 106                                  0, 1, 0, 0);
 107                return;
 108        }
 109
 110        if (cec->irq_status & TXBR) {
 111                /* send next byte */
 112                if (cec->tx_cnt < cec->tx_msg.len)
 113                        regmap_write(cec->regmap, CEC_TXDR,
 114                                     cec->tx_msg.msg[cec->tx_cnt++]);
 115
 116                /* TXEOM is set to command transmission of the last byte */
 117                if (cec->tx_cnt == cec->tx_msg.len)
 118                        regmap_update_bits(cec->regmap, CEC_CR, TXEOM, TXEOM);
 119        }
 120
 121        if (cec->irq_status & TXEND)
 122                cec_transmit_done(cec->adap, CEC_TX_STATUS_OK, 0, 0, 0, 0);
 123}
 124
 125static void stm32_rx_done(struct stm32_cec *cec, u32 status)
 126{
 127        if (cec->irq_status & (RXACKE | RXOVR)) {
 128                cec->rx_msg.len = 0;
 129                return;
 130        }
 131
 132        if (cec->irq_status & RXBR) {
 133                u32 val;
 134
 135                regmap_read(cec->regmap, CEC_RXDR, &val);
 136                cec->rx_msg.msg[cec->rx_msg.len++] = val & 0xFF;
 137        }
 138
 139        if (cec->irq_status & RXEND) {
 140                cec_received_msg(cec->adap, &cec->rx_msg);
 141                cec->rx_msg.len = 0;
 142        }
 143}
 144
 145static irqreturn_t stm32_cec_irq_thread(int irq, void *arg)
 146{
 147        struct stm32_cec *cec = arg;
 148
 149        if (cec->irq_status & ALL_TX_IT)
 150                stm32_tx_done(cec, cec->irq_status);
 151
 152        if (cec->irq_status & ALL_RX_IT)
 153                stm32_rx_done(cec, cec->irq_status);
 154
 155        cec->irq_status = 0;
 156
 157        return IRQ_HANDLED;
 158}
 159
 160static irqreturn_t stm32_cec_irq_handler(int irq, void *arg)
 161{
 162        struct stm32_cec *cec = arg;
 163
 164        regmap_read(cec->regmap, CEC_ISR, &cec->irq_status);
 165
 166        regmap_update_bits(cec->regmap, CEC_ISR,
 167                           ALL_TX_IT | ALL_RX_IT,
 168                           ALL_TX_IT | ALL_RX_IT);
 169
 170        return IRQ_WAKE_THREAD;
 171}
 172
 173static int stm32_cec_adap_enable(struct cec_adapter *adap, bool enable)
 174{
 175        struct stm32_cec *cec = adap->priv;
 176        int ret = 0;
 177
 178        if (enable) {
 179                ret = clk_enable(cec->clk_cec);
 180                if (ret)
 181                        dev_err(cec->dev, "fail to enable cec clock\n");
 182
 183                clk_enable(cec->clk_hdmi_cec);
 184                regmap_update_bits(cec->regmap, CEC_CR, CECEN, CECEN);
 185        } else {
 186                clk_disable(cec->clk_cec);
 187                clk_disable(cec->clk_hdmi_cec);
 188                regmap_update_bits(cec->regmap, CEC_CR, CECEN, 0);
 189        }
 190
 191        return ret;
 192}
 193
 194static int stm32_cec_adap_log_addr(struct cec_adapter *adap, u8 logical_addr)
 195{
 196        struct stm32_cec *cec = adap->priv;
 197        u32 oar = (1 << logical_addr) << 16;
 198        u32 val;
 199
 200        /* Poll every 100µs the register CEC_CR to wait end of transmission */
 201        regmap_read_poll_timeout(cec->regmap, CEC_CR, val, !(val & TXSOM),
 202                                 100, CEC_XFER_TIMEOUT_MS * 1000);
 203        regmap_update_bits(cec->regmap, CEC_CR, CECEN, 0);
 204
 205        if (logical_addr == CEC_LOG_ADDR_INVALID)
 206                regmap_update_bits(cec->regmap, CEC_CFGR, OAR, 0);
 207        else
 208                regmap_update_bits(cec->regmap, CEC_CFGR, oar, oar);
 209
 210        regmap_update_bits(cec->regmap, CEC_CR, CECEN, CECEN);
 211
 212        return 0;
 213}
 214
 215static int stm32_cec_adap_transmit(struct cec_adapter *adap, u8 attempts,
 216                                   u32 signal_free_time, struct cec_msg *msg)
 217{
 218        struct stm32_cec *cec = adap->priv;
 219
 220        /* Copy message */
 221        cec->tx_msg = *msg;
 222        cec->tx_cnt = 0;
 223
 224        /*
 225         * If the CEC message consists of only one byte,
 226         * TXEOM must be set before of TXSOM.
 227         */
 228        if (cec->tx_msg.len == 1)
 229                regmap_update_bits(cec->regmap, CEC_CR, TXEOM, TXEOM);
 230
 231        /* TXSOM is set to command transmission of the first byte */
 232        regmap_update_bits(cec->regmap, CEC_CR, TXSOM, TXSOM);
 233
 234        /* Write the header (first byte of message) */
 235        regmap_write(cec->regmap, CEC_TXDR, cec->tx_msg.msg[0]);
 236        cec->tx_cnt++;
 237
 238        return 0;
 239}
 240
 241static const struct cec_adap_ops stm32_cec_adap_ops = {
 242        .adap_enable = stm32_cec_adap_enable,
 243        .adap_log_addr = stm32_cec_adap_log_addr,
 244        .adap_transmit = stm32_cec_adap_transmit,
 245};
 246
 247static const struct regmap_config stm32_cec_regmap_cfg = {
 248        .reg_bits = 32,
 249        .val_bits = 32,
 250        .reg_stride = sizeof(u32),
 251        .max_register = 0x14,
 252        .fast_io = true,
 253};
 254
 255static int stm32_cec_probe(struct platform_device *pdev)
 256{
 257        u32 caps = CEC_CAP_DEFAULTS | CEC_CAP_PHYS_ADDR | CEC_MODE_MONITOR_ALL;
 258        struct resource *res;
 259        struct stm32_cec *cec;
 260        void __iomem *mmio;
 261        int ret;
 262
 263        cec = devm_kzalloc(&pdev->dev, sizeof(*cec), GFP_KERNEL);
 264        if (!cec)
 265                return -ENOMEM;
 266
 267        cec->dev = &pdev->dev;
 268
 269        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 270        mmio = devm_ioremap_resource(&pdev->dev, res);
 271        if (IS_ERR(mmio))
 272                return PTR_ERR(mmio);
 273
 274        cec->regmap = devm_regmap_init_mmio_clk(&pdev->dev, "cec", mmio,
 275                                                &stm32_cec_regmap_cfg);
 276
 277        if (IS_ERR(cec->regmap))
 278                return PTR_ERR(cec->regmap);
 279
 280        cec->irq = platform_get_irq(pdev, 0);
 281        if (cec->irq < 0)
 282                return cec->irq;
 283
 284        ret = devm_request_threaded_irq(&pdev->dev, cec->irq,
 285                                        stm32_cec_irq_handler,
 286                                        stm32_cec_irq_thread,
 287                                        0,
 288                                        pdev->name, cec);
 289        if (ret)
 290                return ret;
 291
 292        cec->clk_cec = devm_clk_get(&pdev->dev, "cec");
 293        if (IS_ERR(cec->clk_cec)) {
 294                dev_err(&pdev->dev, "Cannot get cec clock\n");
 295                return PTR_ERR(cec->clk_cec);
 296        }
 297
 298        ret = clk_prepare(cec->clk_cec);
 299        if (ret) {
 300                dev_err(&pdev->dev, "Unable to prepare cec clock\n");
 301                return ret;
 302        }
 303
 304        cec->clk_hdmi_cec = devm_clk_get(&pdev->dev, "hdmi-cec");
 305        if (!IS_ERR(cec->clk_hdmi_cec)) {
 306                ret = clk_prepare(cec->clk_hdmi_cec);
 307                if (ret) {
 308                        dev_err(&pdev->dev, "Unable to prepare hdmi-cec clock\n");
 309                        return ret;
 310                }
 311        }
 312
 313        /*
 314         * CEC_CAP_PHYS_ADDR caps should be removed when a cec notifier is
 315         * available for example when a drm driver can provide edid
 316         */
 317        cec->adap = cec_allocate_adapter(&stm32_cec_adap_ops, cec,
 318                        CEC_NAME, caps, CEC_MAX_LOG_ADDRS);
 319        ret = PTR_ERR_OR_ZERO(cec->adap);
 320        if (ret)
 321                return ret;
 322
 323        ret = cec_register_adapter(cec->adap, &pdev->dev);
 324        if (ret) {
 325                cec_delete_adapter(cec->adap);
 326                return ret;
 327        }
 328
 329        cec_hw_init(cec);
 330
 331        platform_set_drvdata(pdev, cec);
 332
 333        return 0;
 334}
 335
 336static int stm32_cec_remove(struct platform_device *pdev)
 337{
 338        struct stm32_cec *cec = platform_get_drvdata(pdev);
 339
 340        clk_unprepare(cec->clk_cec);
 341        clk_unprepare(cec->clk_hdmi_cec);
 342
 343        cec_unregister_adapter(cec->adap);
 344
 345        return 0;
 346}
 347
 348static const struct of_device_id stm32_cec_of_match[] = {
 349        { .compatible = "st,stm32-cec" },
 350        { /* end node */ }
 351};
 352MODULE_DEVICE_TABLE(of, stm32_cec_of_match);
 353
 354static struct platform_driver stm32_cec_driver = {
 355        .probe  = stm32_cec_probe,
 356        .remove = stm32_cec_remove,
 357        .driver = {
 358                .name           = CEC_NAME,
 359                .of_match_table = stm32_cec_of_match,
 360        },
 361};
 362
 363module_platform_driver(stm32_cec_driver);
 364
 365MODULE_AUTHOR("Benjamin Gaignard <benjamin.gaignard@st.com>");
 366MODULE_AUTHOR("Yannick Fertre <yannick.fertre@st.com>");
 367MODULE_DESCRIPTION("STMicroelectronics STM32 Consumer Electronics Control");
 368MODULE_LICENSE("GPL v2");
 369