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

mantis_i2c.c (6037B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3	Mantis PCI bridge driver
      4
      5	Copyright (C) Manu Abraham (abraham.manu@gmail.com)
      6
      7*/
      8
      9#include <asm/io.h>
     10#include <linux/ioport.h>
     11#include <linux/pci.h>
     12#include <linux/i2c.h>
     13
     14#include <media/dmxdev.h>
     15#include <media/dvbdev.h>
     16#include <media/dvb_demux.h>
     17#include <media/dvb_frontend.h>
     18#include <media/dvb_net.h>
     19
     20#include "mantis_common.h"
     21#include "mantis_reg.h"
     22#include "mantis_i2c.h"
     23
     24#define TRIALS			10000
     25
     26static int mantis_i2c_read(struct mantis_pci *mantis, const struct i2c_msg *msg)
     27{
     28	u32 rxd, i, stat, trials;
     29
     30	dprintk(MANTIS_INFO, 0, "        %s:  Address=[0x%02x] <R>[ ",
     31		__func__, msg->addr);
     32
     33	for (i = 0; i < msg->len; i++) {
     34		rxd = (msg->addr << 25) | (1 << 24)
     35					| MANTIS_I2C_RATE_3
     36					| MANTIS_I2C_STOP
     37					| MANTIS_I2C_PGMODE;
     38
     39		if (i == (msg->len - 1))
     40			rxd &= ~MANTIS_I2C_STOP;
     41
     42		mmwrite(MANTIS_INT_I2CDONE, MANTIS_INT_STAT);
     43		mmwrite(rxd, MANTIS_I2CDATA_CTL);
     44
     45		/* wait for xfer completion */
     46		for (trials = 0; trials < TRIALS; trials++) {
     47			stat = mmread(MANTIS_INT_STAT);
     48			if (stat & MANTIS_INT_I2CDONE)
     49				break;
     50		}
     51
     52		dprintk(MANTIS_TMG, 0, "I2CDONE: trials=%d\n", trials);
     53
     54		/* wait for xfer completion */
     55		for (trials = 0; trials < TRIALS; trials++) {
     56			stat = mmread(MANTIS_INT_STAT);
     57			if (stat & MANTIS_INT_I2CRACK)
     58				break;
     59		}
     60
     61		dprintk(MANTIS_TMG, 0, "I2CRACK: trials=%d\n", trials);
     62
     63		rxd = mmread(MANTIS_I2CDATA_CTL);
     64		msg->buf[i] = (u8)((rxd >> 8) & 0xFF);
     65		dprintk(MANTIS_INFO, 0, "%02x ", msg->buf[i]);
     66	}
     67	dprintk(MANTIS_INFO, 0, "]\n");
     68
     69	return 0;
     70}
     71
     72static int mantis_i2c_write(struct mantis_pci *mantis, const struct i2c_msg *msg)
     73{
     74	int i;
     75	u32 txd = 0, stat, trials;
     76
     77	dprintk(MANTIS_INFO, 0, "        %s: Address=[0x%02x] <W>[ ",
     78		__func__, msg->addr);
     79
     80	for (i = 0; i < msg->len; i++) {
     81		dprintk(MANTIS_INFO, 0, "%02x ", msg->buf[i]);
     82		txd = (msg->addr << 25) | (msg->buf[i] << 8)
     83					| MANTIS_I2C_RATE_3
     84					| MANTIS_I2C_STOP
     85					| MANTIS_I2C_PGMODE;
     86
     87		if (i == (msg->len - 1))
     88			txd &= ~MANTIS_I2C_STOP;
     89
     90		mmwrite(MANTIS_INT_I2CDONE, MANTIS_INT_STAT);
     91		mmwrite(txd, MANTIS_I2CDATA_CTL);
     92
     93		/* wait for xfer completion */
     94		for (trials = 0; trials < TRIALS; trials++) {
     95			stat = mmread(MANTIS_INT_STAT);
     96			if (stat & MANTIS_INT_I2CDONE)
     97				break;
     98		}
     99
    100		dprintk(MANTIS_TMG, 0, "I2CDONE: trials=%d\n", trials);
    101
    102		/* wait for xfer completion */
    103		for (trials = 0; trials < TRIALS; trials++) {
    104			stat = mmread(MANTIS_INT_STAT);
    105			if (stat & MANTIS_INT_I2CRACK)
    106				break;
    107		}
    108
    109		dprintk(MANTIS_TMG, 0, "I2CRACK: trials=%d\n", trials);
    110	}
    111	dprintk(MANTIS_INFO, 0, "]\n");
    112
    113	return 0;
    114}
    115
    116static int mantis_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num)
    117{
    118	int ret = 0, i = 0, trials;
    119	u32 stat, data, txd;
    120	struct mantis_pci *mantis;
    121	struct mantis_hwconfig *config;
    122
    123	mantis = i2c_get_adapdata(adapter);
    124	BUG_ON(!mantis);
    125	config = mantis->hwconfig;
    126	BUG_ON(!config);
    127
    128	dprintk(MANTIS_DEBUG, 1, "Messages:%d", num);
    129	mutex_lock(&mantis->i2c_lock);
    130
    131	while (i < num) {
    132		/* Byte MODE */
    133		if ((config->i2c_mode & MANTIS_BYTE_MODE) &&
    134		    ((i + 1) < num)			&&
    135		    (msgs[i].len < 2)			&&
    136		    (msgs[i + 1].len < 2)		&&
    137		    (msgs[i + 1].flags & I2C_M_RD)) {
    138
    139			dprintk(MANTIS_DEBUG, 0, "        Byte MODE:\n");
    140
    141			/* Read operation */
    142			txd = msgs[i].addr << 25 | (0x1 << 24)
    143						 | (msgs[i].buf[0] << 16)
    144						 | MANTIS_I2C_RATE_3;
    145
    146			mmwrite(txd, MANTIS_I2CDATA_CTL);
    147			/* wait for xfer completion */
    148			for (trials = 0; trials < TRIALS; trials++) {
    149				stat = mmread(MANTIS_INT_STAT);
    150				if (stat & MANTIS_INT_I2CDONE)
    151					break;
    152			}
    153
    154			/* check for xfer completion */
    155			if (stat & MANTIS_INT_I2CDONE) {
    156				/* check xfer was acknowledged */
    157				if (stat & MANTIS_INT_I2CRACK) {
    158					data = mmread(MANTIS_I2CDATA_CTL);
    159					msgs[i + 1].buf[0] = (data >> 8) & 0xff;
    160					dprintk(MANTIS_DEBUG, 0, "        Byte <%d> RXD=0x%02x  [%02x]\n", 0x0, data, msgs[i + 1].buf[0]);
    161				} else {
    162					/* I/O error */
    163					dprintk(MANTIS_ERROR, 1, "        I/O error, LINE:%d", __LINE__);
    164					ret = -EIO;
    165					break;
    166				}
    167			} else {
    168				/* I/O error */
    169				dprintk(MANTIS_ERROR, 1, "        I/O error, LINE:%d", __LINE__);
    170				ret = -EIO;
    171				break;
    172			}
    173			i += 2; /* Write/Read operation in one go */
    174		}
    175
    176		if (i < num) {
    177			if (msgs[i].flags & I2C_M_RD)
    178				ret = mantis_i2c_read(mantis, &msgs[i]);
    179			else
    180				ret = mantis_i2c_write(mantis, &msgs[i]);
    181
    182			i++;
    183			if (ret < 0)
    184				goto bail_out;
    185		}
    186
    187	}
    188
    189	mutex_unlock(&mantis->i2c_lock);
    190
    191	return num;
    192
    193bail_out:
    194	mutex_unlock(&mantis->i2c_lock);
    195	return ret;
    196}
    197
    198static u32 mantis_i2c_func(struct i2c_adapter *adapter)
    199{
    200	return I2C_FUNC_SMBUS_EMUL;
    201}
    202
    203static const struct i2c_algorithm mantis_algo = {
    204	.master_xfer		= mantis_i2c_xfer,
    205	.functionality		= mantis_i2c_func,
    206};
    207
    208int mantis_i2c_init(struct mantis_pci *mantis)
    209{
    210	u32 intstat;
    211	struct i2c_adapter *i2c_adapter = &mantis->adapter;
    212	struct pci_dev *pdev		= mantis->pdev;
    213
    214	init_waitqueue_head(&mantis->i2c_wq);
    215	mutex_init(&mantis->i2c_lock);
    216	strscpy(i2c_adapter->name, "Mantis I2C", sizeof(i2c_adapter->name));
    217	i2c_set_adapdata(i2c_adapter, mantis);
    218
    219	i2c_adapter->owner	= THIS_MODULE;
    220	i2c_adapter->algo	= &mantis_algo;
    221	i2c_adapter->algo_data	= NULL;
    222	i2c_adapter->timeout	= 500;
    223	i2c_adapter->retries	= 3;
    224	i2c_adapter->dev.parent	= &pdev->dev;
    225
    226	mantis->i2c_rc		= i2c_add_adapter(i2c_adapter);
    227	if (mantis->i2c_rc < 0)
    228		return mantis->i2c_rc;
    229
    230	dprintk(MANTIS_DEBUG, 1, "Initializing I2C ..");
    231
    232	intstat = mmread(MANTIS_INT_STAT);
    233	mmread(MANTIS_INT_MASK);
    234	mmwrite(intstat, MANTIS_INT_STAT);
    235	dprintk(MANTIS_DEBUG, 1, "Disabling I2C interrupt");
    236	mantis_mask_ints(mantis, MANTIS_INT_I2CDONE);
    237
    238	return 0;
    239}
    240EXPORT_SYMBOL_GPL(mantis_i2c_init);
    241
    242int mantis_i2c_exit(struct mantis_pci *mantis)
    243{
    244	dprintk(MANTIS_DEBUG, 1, "Disabling I2C interrupt");
    245	mantis_mask_ints(mantis, MANTIS_INT_I2CDONE);
    246
    247	dprintk(MANTIS_DEBUG, 1, "Removing I2C adapter");
    248	i2c_del_adapter(&mantis->adapter);
    249
    250	return 0;
    251}
    252EXPORT_SYMBOL_GPL(mantis_i2c_exit);