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

dibx000_common.c (13129B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
      3
      4#include <linux/i2c.h>
      5#include <linux/mutex.h>
      6#include <linux/module.h>
      7
      8#include "dibx000_common.h"
      9
     10static int debug;
     11module_param(debug, int, 0644);
     12MODULE_PARM_DESC(debug, "turn on debugging (default: 0)");
     13
     14#define dprintk(fmt, arg...) do {					\
     15	if (debug)							\
     16		printk(KERN_DEBUG pr_fmt("%s: " fmt),			\
     17		       __func__, ##arg);				\
     18} while (0)
     19
     20static int dibx000_write_word(struct dibx000_i2c_master *mst, u16 reg, u16 val)
     21{
     22	int ret;
     23
     24	if (mutex_lock_interruptible(&mst->i2c_buffer_lock) < 0) {
     25		dprintk("could not acquire lock\n");
     26		return -EINVAL;
     27	}
     28
     29	mst->i2c_write_buffer[0] = (reg >> 8) & 0xff;
     30	mst->i2c_write_buffer[1] = reg & 0xff;
     31	mst->i2c_write_buffer[2] = (val >> 8) & 0xff;
     32	mst->i2c_write_buffer[3] = val & 0xff;
     33
     34	memset(mst->msg, 0, sizeof(struct i2c_msg));
     35	mst->msg[0].addr = mst->i2c_addr;
     36	mst->msg[0].flags = 0;
     37	mst->msg[0].buf = mst->i2c_write_buffer;
     38	mst->msg[0].len = 4;
     39
     40	ret = i2c_transfer(mst->i2c_adap, mst->msg, 1) != 1 ? -EREMOTEIO : 0;
     41	mutex_unlock(&mst->i2c_buffer_lock);
     42
     43	return ret;
     44}
     45
     46static u16 dibx000_read_word(struct dibx000_i2c_master *mst, u16 reg)
     47{
     48	u16 ret;
     49
     50	if (mutex_lock_interruptible(&mst->i2c_buffer_lock) < 0) {
     51		dprintk("could not acquire lock\n");
     52		return 0;
     53	}
     54
     55	mst->i2c_write_buffer[0] = reg >> 8;
     56	mst->i2c_write_buffer[1] = reg & 0xff;
     57
     58	memset(mst->msg, 0, 2 * sizeof(struct i2c_msg));
     59	mst->msg[0].addr = mst->i2c_addr;
     60	mst->msg[0].flags = 0;
     61	mst->msg[0].buf = mst->i2c_write_buffer;
     62	mst->msg[0].len = 2;
     63	mst->msg[1].addr = mst->i2c_addr;
     64	mst->msg[1].flags = I2C_M_RD;
     65	mst->msg[1].buf = mst->i2c_read_buffer;
     66	mst->msg[1].len = 2;
     67
     68	if (i2c_transfer(mst->i2c_adap, mst->msg, 2) != 2)
     69		dprintk("i2c read error on %d\n", reg);
     70
     71	ret = (mst->i2c_read_buffer[0] << 8) | mst->i2c_read_buffer[1];
     72	mutex_unlock(&mst->i2c_buffer_lock);
     73
     74	return ret;
     75}
     76
     77static int dibx000_is_i2c_done(struct dibx000_i2c_master *mst)
     78{
     79	int i = 100;
     80	u16 status;
     81
     82	while (((status = dibx000_read_word(mst, mst->base_reg + 2)) & 0x0100) == 0 && --i > 0)
     83		;
     84
     85	/* i2c timed out */
     86	if (i == 0)
     87		return -EREMOTEIO;
     88
     89	/* no acknowledge */
     90	if ((status & 0x0080) == 0)
     91		return -EREMOTEIO;
     92
     93	return 0;
     94}
     95
     96static int dibx000_master_i2c_write(struct dibx000_i2c_master *mst, struct i2c_msg *msg, u8 stop)
     97{
     98	u16 data;
     99	u16 da;
    100	u16 i;
    101	u16 txlen = msg->len, len;
    102	const u8 *b = msg->buf;
    103
    104	while (txlen) {
    105		dibx000_read_word(mst, mst->base_reg + 2);
    106
    107		len = txlen > 8 ? 8 : txlen;
    108		for (i = 0; i < len; i += 2) {
    109			data = *b++ << 8;
    110			if (i+1 < len)
    111				data |= *b++;
    112			dibx000_write_word(mst, mst->base_reg, data);
    113		}
    114		da = (((u8) (msg->addr))  << 9) |
    115			(1           << 8) |
    116			(1           << 7) |
    117			(0           << 6) |
    118			(0           << 5) |
    119			((len & 0x7) << 2) |
    120			(0           << 1) |
    121			(0           << 0);
    122
    123		if (txlen == msg->len)
    124			da |= 1 << 5; /* start */
    125
    126		if (txlen-len == 0 && stop)
    127			da |= 1 << 6; /* stop */
    128
    129		dibx000_write_word(mst, mst->base_reg+1, da);
    130
    131		if (dibx000_is_i2c_done(mst) != 0)
    132			return -EREMOTEIO;
    133		txlen -= len;
    134	}
    135
    136	return 0;
    137}
    138
    139static int dibx000_master_i2c_read(struct dibx000_i2c_master *mst, struct i2c_msg *msg)
    140{
    141	u16 da;
    142	u8 *b = msg->buf;
    143	u16 rxlen = msg->len, len;
    144
    145	while (rxlen) {
    146		len = rxlen > 8 ? 8 : rxlen;
    147		da = (((u8) (msg->addr)) << 9) |
    148			(1           << 8) |
    149			(1           << 7) |
    150			(0           << 6) |
    151			(0           << 5) |
    152			((len & 0x7) << 2) |
    153			(1           << 1) |
    154			(0           << 0);
    155
    156		if (rxlen == msg->len)
    157			da |= 1 << 5; /* start */
    158
    159		if (rxlen-len == 0)
    160			da |= 1 << 6; /* stop */
    161		dibx000_write_word(mst, mst->base_reg+1, da);
    162
    163		if (dibx000_is_i2c_done(mst) != 0)
    164			return -EREMOTEIO;
    165
    166		rxlen -= len;
    167
    168		while (len) {
    169			da = dibx000_read_word(mst, mst->base_reg);
    170			*b++ = (da >> 8) & 0xff;
    171			len--;
    172			if (len >= 1) {
    173				*b++ =  da   & 0xff;
    174				len--;
    175			}
    176		}
    177	}
    178
    179	return 0;
    180}
    181
    182int dibx000_i2c_set_speed(struct i2c_adapter *i2c_adap, u16 speed)
    183{
    184	struct dibx000_i2c_master *mst = i2c_get_adapdata(i2c_adap);
    185
    186	if (mst->device_rev < DIB7000MC && speed < 235)
    187		speed = 235;
    188	return dibx000_write_word(mst, mst->base_reg + 3, (u16)(60000 / speed));
    189
    190}
    191EXPORT_SYMBOL(dibx000_i2c_set_speed);
    192
    193static u32 dibx000_i2c_func(struct i2c_adapter *adapter)
    194{
    195	return I2C_FUNC_I2C;
    196}
    197
    198static int dibx000_i2c_select_interface(struct dibx000_i2c_master *mst,
    199					enum dibx000_i2c_interface intf)
    200{
    201	if (mst->device_rev > DIB3000MC && mst->selected_interface != intf) {
    202		dprintk("selecting interface: %d\n", intf);
    203		mst->selected_interface = intf;
    204		return dibx000_write_word(mst, mst->base_reg + 4, intf);
    205	}
    206	return 0;
    207}
    208
    209static int dibx000_i2c_master_xfer_gpio12(struct i2c_adapter *i2c_adap, struct i2c_msg msg[], int num)
    210{
    211	struct dibx000_i2c_master *mst = i2c_get_adapdata(i2c_adap);
    212	int msg_index;
    213	int ret = 0;
    214
    215	dibx000_i2c_select_interface(mst, DIBX000_I2C_INTERFACE_GPIO_1_2);
    216	for (msg_index = 0; msg_index < num; msg_index++) {
    217		if (msg[msg_index].flags & I2C_M_RD) {
    218			ret = dibx000_master_i2c_read(mst, &msg[msg_index]);
    219			if (ret != 0)
    220				return 0;
    221		} else {
    222			ret = dibx000_master_i2c_write(mst, &msg[msg_index], 1);
    223			if (ret != 0)
    224				return 0;
    225		}
    226	}
    227
    228	return num;
    229}
    230
    231static int dibx000_i2c_master_xfer_gpio34(struct i2c_adapter *i2c_adap, struct i2c_msg msg[], int num)
    232{
    233	struct dibx000_i2c_master *mst = i2c_get_adapdata(i2c_adap);
    234	int msg_index;
    235	int ret = 0;
    236
    237	dibx000_i2c_select_interface(mst, DIBX000_I2C_INTERFACE_GPIO_3_4);
    238	for (msg_index = 0; msg_index < num; msg_index++) {
    239		if (msg[msg_index].flags & I2C_M_RD) {
    240			ret = dibx000_master_i2c_read(mst, &msg[msg_index]);
    241			if (ret != 0)
    242				return 0;
    243		} else {
    244			ret = dibx000_master_i2c_write(mst, &msg[msg_index], 1);
    245			if (ret != 0)
    246				return 0;
    247		}
    248	}
    249
    250	return num;
    251}
    252
    253static struct i2c_algorithm dibx000_i2c_master_gpio12_xfer_algo = {
    254	.master_xfer = dibx000_i2c_master_xfer_gpio12,
    255	.functionality = dibx000_i2c_func,
    256};
    257
    258static struct i2c_algorithm dibx000_i2c_master_gpio34_xfer_algo = {
    259	.master_xfer = dibx000_i2c_master_xfer_gpio34,
    260	.functionality = dibx000_i2c_func,
    261};
    262
    263static int dibx000_i2c_gate_ctrl(struct dibx000_i2c_master *mst, u8 tx[4],
    264				 u8 addr, int onoff)
    265{
    266	u16 val;
    267
    268
    269	if (onoff)
    270		val = addr << 8;	// bit 7 = use master or not, if 0, the gate is open
    271	else
    272		val = 1 << 7;
    273
    274	if (mst->device_rev > DIB7000)
    275		val <<= 1;
    276
    277	tx[0] = (((mst->base_reg + 1) >> 8) & 0xff);
    278	tx[1] = ((mst->base_reg + 1) & 0xff);
    279	tx[2] = val >> 8;
    280	tx[3] = val & 0xff;
    281
    282	return 0;
    283}
    284
    285static int dibx000_i2c_gated_gpio67_xfer(struct i2c_adapter *i2c_adap,
    286					struct i2c_msg msg[], int num)
    287{
    288	struct dibx000_i2c_master *mst = i2c_get_adapdata(i2c_adap);
    289	int ret;
    290
    291	if (num > 32) {
    292		dprintk("%s: too much I2C message to be transmitted (%i). Maximum is 32",
    293			__func__, num);
    294		return -ENOMEM;
    295	}
    296
    297	dibx000_i2c_select_interface(mst, DIBX000_I2C_INTERFACE_GPIO_6_7);
    298
    299	if (mutex_lock_interruptible(&mst->i2c_buffer_lock) < 0) {
    300		dprintk("could not acquire lock\n");
    301		return -EINVAL;
    302	}
    303
    304	memset(mst->msg, 0, sizeof(struct i2c_msg) * (2 + num));
    305
    306	/* open the gate */
    307	dibx000_i2c_gate_ctrl(mst, &mst->i2c_write_buffer[0], msg[0].addr, 1);
    308	mst->msg[0].addr = mst->i2c_addr;
    309	mst->msg[0].buf = &mst->i2c_write_buffer[0];
    310	mst->msg[0].len = 4;
    311
    312	memcpy(&mst->msg[1], msg, sizeof(struct i2c_msg) * num);
    313
    314	/* close the gate */
    315	dibx000_i2c_gate_ctrl(mst, &mst->i2c_write_buffer[4], 0, 0);
    316	mst->msg[num + 1].addr = mst->i2c_addr;
    317	mst->msg[num + 1].buf = &mst->i2c_write_buffer[4];
    318	mst->msg[num + 1].len = 4;
    319
    320	ret = (i2c_transfer(mst->i2c_adap, mst->msg, 2 + num) == 2 + num ?
    321			num : -EIO);
    322
    323	mutex_unlock(&mst->i2c_buffer_lock);
    324	return ret;
    325}
    326
    327static struct i2c_algorithm dibx000_i2c_gated_gpio67_algo = {
    328	.master_xfer = dibx000_i2c_gated_gpio67_xfer,
    329	.functionality = dibx000_i2c_func,
    330};
    331
    332static int dibx000_i2c_gated_tuner_xfer(struct i2c_adapter *i2c_adap,
    333					struct i2c_msg msg[], int num)
    334{
    335	struct dibx000_i2c_master *mst = i2c_get_adapdata(i2c_adap);
    336	int ret;
    337
    338	if (num > 32) {
    339		dprintk("%s: too much I2C message to be transmitted (%i). Maximum is 32",
    340			__func__, num);
    341		return -ENOMEM;
    342	}
    343
    344	dibx000_i2c_select_interface(mst, DIBX000_I2C_INTERFACE_TUNER);
    345
    346	if (mutex_lock_interruptible(&mst->i2c_buffer_lock) < 0) {
    347		dprintk("could not acquire lock\n");
    348		return -EINVAL;
    349	}
    350	memset(mst->msg, 0, sizeof(struct i2c_msg) * (2 + num));
    351
    352	/* open the gate */
    353	dibx000_i2c_gate_ctrl(mst, &mst->i2c_write_buffer[0], msg[0].addr, 1);
    354	mst->msg[0].addr = mst->i2c_addr;
    355	mst->msg[0].buf = &mst->i2c_write_buffer[0];
    356	mst->msg[0].len = 4;
    357
    358	memcpy(&mst->msg[1], msg, sizeof(struct i2c_msg) * num);
    359
    360	/* close the gate */
    361	dibx000_i2c_gate_ctrl(mst, &mst->i2c_write_buffer[4], 0, 0);
    362	mst->msg[num + 1].addr = mst->i2c_addr;
    363	mst->msg[num + 1].buf = &mst->i2c_write_buffer[4];
    364	mst->msg[num + 1].len = 4;
    365
    366	ret = (i2c_transfer(mst->i2c_adap, mst->msg, 2 + num) == 2 + num ?
    367			num : -EIO);
    368	mutex_unlock(&mst->i2c_buffer_lock);
    369	return ret;
    370}
    371
    372static struct i2c_algorithm dibx000_i2c_gated_tuner_algo = {
    373	.master_xfer = dibx000_i2c_gated_tuner_xfer,
    374	.functionality = dibx000_i2c_func,
    375};
    376
    377struct i2c_adapter *dibx000_get_i2c_adapter(struct dibx000_i2c_master *mst,
    378						enum dibx000_i2c_interface intf,
    379						int gating)
    380{
    381	struct i2c_adapter *i2c = NULL;
    382
    383	switch (intf) {
    384	case DIBX000_I2C_INTERFACE_TUNER:
    385		if (gating)
    386			i2c = &mst->gated_tuner_i2c_adap;
    387		break;
    388	case DIBX000_I2C_INTERFACE_GPIO_1_2:
    389		if (!gating)
    390			i2c = &mst->master_i2c_adap_gpio12;
    391		break;
    392	case DIBX000_I2C_INTERFACE_GPIO_3_4:
    393		if (!gating)
    394			i2c = &mst->master_i2c_adap_gpio34;
    395		break;
    396	case DIBX000_I2C_INTERFACE_GPIO_6_7:
    397		if (gating)
    398			i2c = &mst->master_i2c_adap_gpio67;
    399		break;
    400	default:
    401		pr_err("incorrect I2C interface selected\n");
    402		break;
    403	}
    404
    405	return i2c;
    406}
    407
    408EXPORT_SYMBOL(dibx000_get_i2c_adapter);
    409
    410void dibx000_reset_i2c_master(struct dibx000_i2c_master *mst)
    411{
    412	/* initialize the i2c-master by closing the gate */
    413	u8 tx[4];
    414	struct i2c_msg m = {.addr = mst->i2c_addr,.buf = tx,.len = 4 };
    415
    416	dibx000_i2c_gate_ctrl(mst, tx, 0, 0);
    417	i2c_transfer(mst->i2c_adap, &m, 1);
    418	mst->selected_interface = 0xff;	// the first time force a select of the I2C
    419	dibx000_i2c_select_interface(mst, DIBX000_I2C_INTERFACE_TUNER);
    420}
    421
    422EXPORT_SYMBOL(dibx000_reset_i2c_master);
    423
    424static int i2c_adapter_init(struct i2c_adapter *i2c_adap,
    425				struct i2c_algorithm *algo, const char *name,
    426				struct dibx000_i2c_master *mst)
    427{
    428	strscpy(i2c_adap->name, name, sizeof(i2c_adap->name));
    429	i2c_adap->algo = algo;
    430	i2c_adap->algo_data = NULL;
    431	i2c_set_adapdata(i2c_adap, mst);
    432	if (i2c_add_adapter(i2c_adap) < 0)
    433		return -ENODEV;
    434	return 0;
    435}
    436
    437int dibx000_init_i2c_master(struct dibx000_i2c_master *mst, u16 device_rev,
    438				struct i2c_adapter *i2c_adap, u8 i2c_addr)
    439{
    440	int ret;
    441
    442	mutex_init(&mst->i2c_buffer_lock);
    443	if (mutex_lock_interruptible(&mst->i2c_buffer_lock) < 0) {
    444		dprintk("could not acquire lock\n");
    445		return -EINVAL;
    446	}
    447	memset(mst->msg, 0, sizeof(struct i2c_msg));
    448	mst->msg[0].addr = i2c_addr >> 1;
    449	mst->msg[0].flags = 0;
    450	mst->msg[0].buf = mst->i2c_write_buffer;
    451	mst->msg[0].len = 4;
    452
    453	mst->device_rev = device_rev;
    454	mst->i2c_adap = i2c_adap;
    455	mst->i2c_addr = i2c_addr >> 1;
    456
    457	if (device_rev == DIB7000P || device_rev == DIB8000)
    458		mst->base_reg = 1024;
    459	else
    460		mst->base_reg = 768;
    461
    462	mst->gated_tuner_i2c_adap.dev.parent = mst->i2c_adap->dev.parent;
    463	if (i2c_adapter_init
    464			(&mst->gated_tuner_i2c_adap, &dibx000_i2c_gated_tuner_algo,
    465			 "DiBX000 tuner I2C bus", mst) != 0)
    466		pr_err("could not initialize the tuner i2c_adapter\n");
    467
    468	mst->master_i2c_adap_gpio12.dev.parent = mst->i2c_adap->dev.parent;
    469	if (i2c_adapter_init
    470			(&mst->master_i2c_adap_gpio12, &dibx000_i2c_master_gpio12_xfer_algo,
    471			 "DiBX000 master GPIO12 I2C bus", mst) != 0)
    472		pr_err("could not initialize the master i2c_adapter\n");
    473
    474	mst->master_i2c_adap_gpio34.dev.parent = mst->i2c_adap->dev.parent;
    475	if (i2c_adapter_init
    476			(&mst->master_i2c_adap_gpio34, &dibx000_i2c_master_gpio34_xfer_algo,
    477			 "DiBX000 master GPIO34 I2C bus", mst) != 0)
    478		pr_err("could not initialize the master i2c_adapter\n");
    479
    480	mst->master_i2c_adap_gpio67.dev.parent = mst->i2c_adap->dev.parent;
    481	if (i2c_adapter_init
    482			(&mst->master_i2c_adap_gpio67, &dibx000_i2c_gated_gpio67_algo,
    483			 "DiBX000 master GPIO67 I2C bus", mst) != 0)
    484		pr_err("could not initialize the master i2c_adapter\n");
    485
    486	/* initialize the i2c-master by closing the gate */
    487	dibx000_i2c_gate_ctrl(mst, mst->i2c_write_buffer, 0, 0);
    488
    489	ret = (i2c_transfer(i2c_adap, mst->msg, 1) == 1);
    490	mutex_unlock(&mst->i2c_buffer_lock);
    491
    492	return ret;
    493}
    494
    495EXPORT_SYMBOL(dibx000_init_i2c_master);
    496
    497void dibx000_exit_i2c_master(struct dibx000_i2c_master *mst)
    498{
    499	i2c_del_adapter(&mst->gated_tuner_i2c_adap);
    500	i2c_del_adapter(&mst->master_i2c_adap_gpio12);
    501	i2c_del_adapter(&mst->master_i2c_adap_gpio34);
    502	i2c_del_adapter(&mst->master_i2c_adap_gpio67);
    503}
    504EXPORT_SYMBOL(dibx000_exit_i2c_master);
    505
    506MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@posteo.de>");
    507MODULE_DESCRIPTION("Common function the DiBcom demodulator family");
    508MODULE_LICENSE("GPL");