cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

stm32-cec.c (9110B)


      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 stm32_cec *cec;
    259	void __iomem *mmio;
    260	int ret;
    261
    262	cec = devm_kzalloc(&pdev->dev, sizeof(*cec), GFP_KERNEL);
    263	if (!cec)
    264		return -ENOMEM;
    265
    266	cec->dev = &pdev->dev;
    267
    268	mmio = devm_platform_ioremap_resource(pdev, 0);
    269	if (IS_ERR(mmio))
    270		return PTR_ERR(mmio);
    271
    272	cec->regmap = devm_regmap_init_mmio_clk(&pdev->dev, "cec", mmio,
    273						&stm32_cec_regmap_cfg);
    274
    275	if (IS_ERR(cec->regmap))
    276		return PTR_ERR(cec->regmap);
    277
    278	cec->irq = platform_get_irq(pdev, 0);
    279	if (cec->irq < 0)
    280		return cec->irq;
    281
    282	ret = devm_request_threaded_irq(&pdev->dev, cec->irq,
    283					stm32_cec_irq_handler,
    284					stm32_cec_irq_thread,
    285					0,
    286					pdev->name, cec);
    287	if (ret)
    288		return ret;
    289
    290	cec->clk_cec = devm_clk_get(&pdev->dev, "cec");
    291	if (IS_ERR(cec->clk_cec)) {
    292		if (PTR_ERR(cec->clk_cec) != -EPROBE_DEFER)
    293			dev_err(&pdev->dev, "Cannot get cec clock\n");
    294
    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	    PTR_ERR(cec->clk_hdmi_cec) == -EPROBE_DEFER) {
    307		ret = -EPROBE_DEFER;
    308		goto err_unprepare_cec_clk;
    309	}
    310
    311	if (!IS_ERR(cec->clk_hdmi_cec)) {
    312		ret = clk_prepare(cec->clk_hdmi_cec);
    313		if (ret) {
    314			dev_err(&pdev->dev, "Can't prepare hdmi-cec clock\n");
    315			goto err_unprepare_cec_clk;
    316		}
    317	}
    318
    319	/*
    320	 * CEC_CAP_PHYS_ADDR caps should be removed when a cec notifier is
    321	 * available for example when a drm driver can provide edid
    322	 */
    323	cec->adap = cec_allocate_adapter(&stm32_cec_adap_ops, cec,
    324			CEC_NAME, caps,	CEC_MAX_LOG_ADDRS);
    325	ret = PTR_ERR_OR_ZERO(cec->adap);
    326	if (ret)
    327		goto err_unprepare_hdmi_cec_clk;
    328
    329	ret = cec_register_adapter(cec->adap, &pdev->dev);
    330	if (ret)
    331		goto err_delete_adapter;
    332
    333	cec_hw_init(cec);
    334
    335	platform_set_drvdata(pdev, cec);
    336
    337	return 0;
    338
    339err_delete_adapter:
    340	cec_delete_adapter(cec->adap);
    341
    342err_unprepare_hdmi_cec_clk:
    343	clk_unprepare(cec->clk_hdmi_cec);
    344
    345err_unprepare_cec_clk:
    346	clk_unprepare(cec->clk_cec);
    347	return ret;
    348}
    349
    350static int stm32_cec_remove(struct platform_device *pdev)
    351{
    352	struct stm32_cec *cec = platform_get_drvdata(pdev);
    353
    354	clk_unprepare(cec->clk_cec);
    355	clk_unprepare(cec->clk_hdmi_cec);
    356
    357	cec_unregister_adapter(cec->adap);
    358
    359	return 0;
    360}
    361
    362static const struct of_device_id stm32_cec_of_match[] = {
    363	{ .compatible = "st,stm32-cec" },
    364	{ /* end node */ }
    365};
    366MODULE_DEVICE_TABLE(of, stm32_cec_of_match);
    367
    368static struct platform_driver stm32_cec_driver = {
    369	.probe  = stm32_cec_probe,
    370	.remove = stm32_cec_remove,
    371	.driver = {
    372		.name		= CEC_NAME,
    373		.of_match_table = stm32_cec_of_match,
    374	},
    375};
    376
    377module_platform_driver(stm32_cec_driver);
    378
    379MODULE_AUTHOR("Benjamin Gaignard <benjamin.gaignard@st.com>");
    380MODULE_AUTHOR("Yannick Fertre <yannick.fertre@st.com>");
    381MODULE_DESCRIPTION("STMicroelectronics STM32 Consumer Electronics Control");
    382MODULE_LICENSE("GPL v2");