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

exynos_hdmi_cecctrl.c (4792B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/* drivers/media/platform/s5p-cec/exynos_hdmi_cecctrl.c
      3 *
      4 * Copyright (c) 2009, 2014 Samsung Electronics
      5 *		http://www.samsung.com/
      6 *
      7 * cec ftn file for Samsung TVOUT driver
      8 */
      9
     10#include <linux/io.h>
     11#include <linux/device.h>
     12
     13#include "exynos_hdmi_cec.h"
     14#include "regs-cec.h"
     15
     16#define S5P_HDMI_FIN			24000000
     17#define CEC_DIV_RATIO			320000
     18
     19#define CEC_MESSAGE_BROADCAST_MASK	0x0F
     20#define CEC_MESSAGE_BROADCAST		0x0F
     21#define CEC_FILTER_THRESHOLD		0x15
     22
     23void s5p_cec_set_divider(struct s5p_cec_dev *cec)
     24{
     25	u32 div_ratio, div_val;
     26	unsigned int reg;
     27
     28	div_ratio  = S5P_HDMI_FIN / CEC_DIV_RATIO - 1;
     29
     30	if (regmap_read(cec->pmu, EXYNOS_HDMI_PHY_CONTROL, &reg)) {
     31		dev_err(cec->dev, "failed to read phy control\n");
     32		return;
     33	}
     34
     35	reg = (reg & ~(0x3FF << 16)) | (div_ratio << 16);
     36
     37	if (regmap_write(cec->pmu, EXYNOS_HDMI_PHY_CONTROL, reg)) {
     38		dev_err(cec->dev, "failed to write phy control\n");
     39		return;
     40	}
     41
     42	div_val = CEC_DIV_RATIO * 0.00005 - 1;
     43
     44	writeb(0x0, cec->reg + S5P_CEC_DIVISOR_3);
     45	writeb(0x0, cec->reg + S5P_CEC_DIVISOR_2);
     46	writeb(0x0, cec->reg + S5P_CEC_DIVISOR_1);
     47	writeb(div_val, cec->reg + S5P_CEC_DIVISOR_0);
     48}
     49
     50void s5p_cec_enable_rx(struct s5p_cec_dev *cec)
     51{
     52	u8 reg;
     53
     54	reg = readb(cec->reg + S5P_CEC_RX_CTRL);
     55	reg |= S5P_CEC_RX_CTRL_ENABLE;
     56	writeb(reg, cec->reg + S5P_CEC_RX_CTRL);
     57}
     58
     59void s5p_cec_mask_rx_interrupts(struct s5p_cec_dev *cec)
     60{
     61	u8 reg;
     62
     63	reg = readb(cec->reg + S5P_CEC_IRQ_MASK);
     64	reg |= S5P_CEC_IRQ_RX_DONE;
     65	reg |= S5P_CEC_IRQ_RX_ERROR;
     66	writeb(reg, cec->reg + S5P_CEC_IRQ_MASK);
     67}
     68
     69void s5p_cec_unmask_rx_interrupts(struct s5p_cec_dev *cec)
     70{
     71	u8 reg;
     72
     73	reg = readb(cec->reg + S5P_CEC_IRQ_MASK);
     74	reg &= ~S5P_CEC_IRQ_RX_DONE;
     75	reg &= ~S5P_CEC_IRQ_RX_ERROR;
     76	writeb(reg, cec->reg + S5P_CEC_IRQ_MASK);
     77}
     78
     79void s5p_cec_mask_tx_interrupts(struct s5p_cec_dev *cec)
     80{
     81	u8 reg;
     82
     83	reg = readb(cec->reg + S5P_CEC_IRQ_MASK);
     84	reg |= S5P_CEC_IRQ_TX_DONE;
     85	reg |= S5P_CEC_IRQ_TX_ERROR;
     86	writeb(reg, cec->reg + S5P_CEC_IRQ_MASK);
     87}
     88
     89void s5p_cec_unmask_tx_interrupts(struct s5p_cec_dev *cec)
     90{
     91	u8 reg;
     92
     93	reg = readb(cec->reg + S5P_CEC_IRQ_MASK);
     94	reg &= ~S5P_CEC_IRQ_TX_DONE;
     95	reg &= ~S5P_CEC_IRQ_TX_ERROR;
     96	writeb(reg, cec->reg + S5P_CEC_IRQ_MASK);
     97}
     98
     99void s5p_cec_reset(struct s5p_cec_dev *cec)
    100{
    101	u8 reg;
    102
    103	writeb(S5P_CEC_RX_CTRL_RESET, cec->reg + S5P_CEC_RX_CTRL);
    104	writeb(S5P_CEC_TX_CTRL_RESET, cec->reg + S5P_CEC_TX_CTRL);
    105
    106	reg = readb(cec->reg + 0xc4);
    107	reg &= ~0x1;
    108	writeb(reg, cec->reg + 0xc4);
    109}
    110
    111void s5p_cec_tx_reset(struct s5p_cec_dev *cec)
    112{
    113	writeb(S5P_CEC_TX_CTRL_RESET, cec->reg + S5P_CEC_TX_CTRL);
    114}
    115
    116void s5p_cec_rx_reset(struct s5p_cec_dev *cec)
    117{
    118	u8 reg;
    119
    120	writeb(S5P_CEC_RX_CTRL_RESET, cec->reg + S5P_CEC_RX_CTRL);
    121
    122	reg = readb(cec->reg + 0xc4);
    123	reg &= ~0x1;
    124	writeb(reg, cec->reg + 0xc4);
    125}
    126
    127void s5p_cec_threshold(struct s5p_cec_dev *cec)
    128{
    129	writeb(CEC_FILTER_THRESHOLD, cec->reg + S5P_CEC_RX_FILTER_TH);
    130	writeb(0, cec->reg + S5P_CEC_RX_FILTER_CTRL);
    131}
    132
    133void s5p_cec_copy_packet(struct s5p_cec_dev *cec, char *data,
    134			 size_t count, u8 retries)
    135{
    136	int i = 0;
    137	u8 reg;
    138
    139	while (i < count) {
    140		writeb(data[i], cec->reg + (S5P_CEC_TX_BUFF0 + (i * 4)));
    141		i++;
    142	}
    143
    144	writeb(count, cec->reg + S5P_CEC_TX_BYTES);
    145	reg = readb(cec->reg + S5P_CEC_TX_CTRL);
    146	reg |= S5P_CEC_TX_CTRL_START;
    147	reg &= ~0x70;
    148	reg |= retries << 4;
    149
    150	if ((data[0] & CEC_MESSAGE_BROADCAST_MASK) == CEC_MESSAGE_BROADCAST) {
    151		dev_dbg(cec->dev, "Broadcast");
    152		reg |= S5P_CEC_TX_CTRL_BCAST;
    153	} else {
    154		dev_dbg(cec->dev, "No Broadcast");
    155		reg &= ~S5P_CEC_TX_CTRL_BCAST;
    156	}
    157
    158	writeb(reg, cec->reg + S5P_CEC_TX_CTRL);
    159	dev_dbg(cec->dev, "cec-tx: cec count (%zu): %*ph", count,
    160		(int)count, data);
    161}
    162
    163void s5p_cec_set_addr(struct s5p_cec_dev *cec, u32 addr)
    164{
    165	writeb(addr & 0x0F, cec->reg + S5P_CEC_LOGIC_ADDR);
    166}
    167
    168u32 s5p_cec_get_status(struct s5p_cec_dev *cec)
    169{
    170	u32 status = 0;
    171
    172	status = readb(cec->reg + S5P_CEC_STATUS_0) & 0xf;
    173	status |= (readb(cec->reg + S5P_CEC_TX_STAT1) & 0xf) << 4;
    174	status |= readb(cec->reg + S5P_CEC_STATUS_1) << 8;
    175	status |= readb(cec->reg + S5P_CEC_STATUS_2) << 16;
    176	status |= readb(cec->reg + S5P_CEC_STATUS_3) << 24;
    177
    178	dev_dbg(cec->dev, "status = 0x%x!\n", status);
    179
    180	return status;
    181}
    182
    183void s5p_clr_pending_tx(struct s5p_cec_dev *cec)
    184{
    185	writeb(S5P_CEC_IRQ_TX_DONE | S5P_CEC_IRQ_TX_ERROR,
    186	       cec->reg + S5P_CEC_IRQ_CLEAR);
    187}
    188
    189void s5p_clr_pending_rx(struct s5p_cec_dev *cec)
    190{
    191	writeb(S5P_CEC_IRQ_RX_DONE | S5P_CEC_IRQ_RX_ERROR,
    192	       cec->reg + S5P_CEC_IRQ_CLEAR);
    193}
    194
    195void s5p_cec_get_rx_buf(struct s5p_cec_dev *cec, u32 size, u8 *buffer)
    196{
    197	u32 i = 0;
    198	char debug[40];
    199
    200	while (i < size) {
    201		buffer[i] = readb(cec->reg + S5P_CEC_RX_BUFF0 + (i * 4));
    202		sprintf(debug + i * 2, "%02x ", buffer[i]);
    203		i++;
    204	}
    205	dev_dbg(cec->dev, "cec-rx: cec size(%d): %s", size, debug);
    206}