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

netup_unidvb_i2c.c (9807B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * netup_unidvb_i2c.c
      4 *
      5 * Internal I2C bus driver for NetUP Universal Dual DVB-CI
      6 *
      7 * Copyright (C) 2014 NetUP Inc.
      8 * Copyright (C) 2014 Sergey Kozlov <serjk@netup.ru>
      9 * Copyright (C) 2014 Abylay Ospan <aospan@netup.ru>
     10 */
     11
     12#include <linux/module.h>
     13#include <linux/moduleparam.h>
     14#include <linux/init.h>
     15#include <linux/delay.h>
     16#include "netup_unidvb.h"
     17
     18#define NETUP_I2C_BUS0_ADDR		0x4800
     19#define NETUP_I2C_BUS1_ADDR		0x4840
     20#define NETUP_I2C_TIMEOUT		1000
     21
     22/* twi_ctrl0_stat reg bits */
     23#define TWI_IRQEN_COMPL	0x1
     24#define TWI_IRQEN_ANACK 0x2
     25#define TWI_IRQEN_DNACK 0x4
     26#define TWI_IRQ_COMPL	(TWI_IRQEN_COMPL << 8)
     27#define TWI_IRQ_ANACK	(TWI_IRQEN_ANACK << 8)
     28#define TWI_IRQ_DNACK	(TWI_IRQEN_DNACK << 8)
     29#define TWI_IRQ_TX	0x800
     30#define TWI_IRQ_RX	0x1000
     31#define TWI_IRQEN	(TWI_IRQEN_COMPL | TWI_IRQEN_ANACK | TWI_IRQEN_DNACK)
     32/* twi_addr_ctrl1 reg bits*/
     33#define TWI_TRANSFER	0x100
     34#define TWI_NOSTOP	0x200
     35#define TWI_SOFT_RESET	0x2000
     36/* twi_clkdiv reg value */
     37#define TWI_CLKDIV	156
     38/* fifo_stat_ctrl reg bits */
     39#define FIFO_IRQEN	0x8000
     40#define FIFO_RESET	0x4000
     41/* FIFO size */
     42#define FIFO_SIZE	16
     43
     44struct netup_i2c_fifo_regs {
     45	union {
     46		__u8	data8;
     47		__le16	data16;
     48		__le32	data32;
     49	};
     50	__u8		padding[4];
     51	__le16		stat_ctrl;
     52} __packed __aligned(1);
     53
     54struct netup_i2c_regs {
     55	__le16				clkdiv;
     56	__le16				twi_ctrl0_stat;
     57	__le16				twi_addr_ctrl1;
     58	__le16				length;
     59	__u8				padding1[8];
     60	struct netup_i2c_fifo_regs	tx_fifo;
     61	__u8				padding2[6];
     62	struct netup_i2c_fifo_regs	rx_fifo;
     63} __packed __aligned(1);
     64
     65irqreturn_t netup_i2c_interrupt(struct netup_i2c *i2c)
     66{
     67	u16 reg, tmp;
     68	unsigned long flags;
     69	irqreturn_t iret = IRQ_HANDLED;
     70
     71	spin_lock_irqsave(&i2c->lock, flags);
     72	reg = readw(&i2c->regs->twi_ctrl0_stat);
     73	writew(reg & ~TWI_IRQEN, &i2c->regs->twi_ctrl0_stat);
     74	dev_dbg(i2c->adap.dev.parent,
     75		"%s(): twi_ctrl0_state 0x%x\n", __func__, reg);
     76	if ((reg & TWI_IRQEN_COMPL) != 0 && (reg & TWI_IRQ_COMPL)) {
     77		dev_dbg(i2c->adap.dev.parent,
     78			"%s(): TWI_IRQEN_COMPL\n", __func__);
     79		i2c->state = STATE_DONE;
     80		goto irq_ok;
     81	}
     82	if ((reg & TWI_IRQEN_ANACK) != 0 && (reg & TWI_IRQ_ANACK)) {
     83		dev_dbg(i2c->adap.dev.parent,
     84			"%s(): TWI_IRQEN_ANACK\n", __func__);
     85		i2c->state = STATE_ERROR;
     86		goto irq_ok;
     87	}
     88	if ((reg & TWI_IRQEN_DNACK) != 0 && (reg & TWI_IRQ_DNACK)) {
     89		dev_dbg(i2c->adap.dev.parent,
     90			"%s(): TWI_IRQEN_DNACK\n", __func__);
     91		i2c->state = STATE_ERROR;
     92		goto irq_ok;
     93	}
     94	if ((reg & TWI_IRQ_RX) != 0) {
     95		tmp = readw(&i2c->regs->rx_fifo.stat_ctrl);
     96		writew(tmp & ~FIFO_IRQEN, &i2c->regs->rx_fifo.stat_ctrl);
     97		i2c->state = STATE_WANT_READ;
     98		dev_dbg(i2c->adap.dev.parent,
     99			"%s(): want read\n", __func__);
    100		goto irq_ok;
    101	}
    102	if ((reg & TWI_IRQ_TX) != 0) {
    103		tmp = readw(&i2c->regs->tx_fifo.stat_ctrl);
    104		writew(tmp & ~FIFO_IRQEN, &i2c->regs->tx_fifo.stat_ctrl);
    105		i2c->state = STATE_WANT_WRITE;
    106		dev_dbg(i2c->adap.dev.parent,
    107			"%s(): want write\n", __func__);
    108		goto irq_ok;
    109	}
    110	dev_warn(&i2c->adap.dev, "%s(): not mine interrupt\n", __func__);
    111	iret = IRQ_NONE;
    112irq_ok:
    113	spin_unlock_irqrestore(&i2c->lock, flags);
    114	if (iret == IRQ_HANDLED)
    115		wake_up(&i2c->wq);
    116	return iret;
    117}
    118
    119static void netup_i2c_reset(struct netup_i2c *i2c)
    120{
    121	dev_dbg(i2c->adap.dev.parent, "%s()\n", __func__);
    122	i2c->state = STATE_DONE;
    123	writew(TWI_SOFT_RESET, &i2c->regs->twi_addr_ctrl1);
    124	writew(TWI_CLKDIV, &i2c->regs->clkdiv);
    125	writew(FIFO_RESET, &i2c->regs->tx_fifo.stat_ctrl);
    126	writew(FIFO_RESET, &i2c->regs->rx_fifo.stat_ctrl);
    127	writew(0x800, &i2c->regs->tx_fifo.stat_ctrl);
    128	writew(0x800, &i2c->regs->rx_fifo.stat_ctrl);
    129}
    130
    131static void netup_i2c_fifo_tx(struct netup_i2c *i2c)
    132{
    133	u8 data;
    134	u32 fifo_space = FIFO_SIZE -
    135		(readw(&i2c->regs->tx_fifo.stat_ctrl) & 0x3f);
    136	u32 msg_length = i2c->msg->len - i2c->xmit_size;
    137
    138	msg_length = (msg_length < fifo_space ? msg_length : fifo_space);
    139	while (msg_length--) {
    140		data = i2c->msg->buf[i2c->xmit_size++];
    141		writeb(data, &i2c->regs->tx_fifo.data8);
    142		dev_dbg(i2c->adap.dev.parent,
    143			"%s(): write 0x%02x\n", __func__, data);
    144	}
    145	if (i2c->xmit_size < i2c->msg->len) {
    146		dev_dbg(i2c->adap.dev.parent,
    147			"%s(): TX IRQ enabled\n", __func__);
    148		writew(readw(&i2c->regs->tx_fifo.stat_ctrl) | FIFO_IRQEN,
    149			&i2c->regs->tx_fifo.stat_ctrl);
    150	}
    151}
    152
    153static void netup_i2c_fifo_rx(struct netup_i2c *i2c)
    154{
    155	u8 data;
    156	u32 fifo_size = readw(&i2c->regs->rx_fifo.stat_ctrl) & 0x3f;
    157
    158	dev_dbg(i2c->adap.dev.parent,
    159		"%s(): RX fifo size %d\n", __func__, fifo_size);
    160	while (fifo_size--) {
    161		data = readb(&i2c->regs->rx_fifo.data8);
    162		if ((i2c->msg->flags & I2C_M_RD) != 0 &&
    163					i2c->xmit_size < i2c->msg->len) {
    164			i2c->msg->buf[i2c->xmit_size++] = data;
    165			dev_dbg(i2c->adap.dev.parent,
    166				"%s(): read 0x%02x\n", __func__, data);
    167		}
    168	}
    169	if (i2c->xmit_size < i2c->msg->len) {
    170		dev_dbg(i2c->adap.dev.parent,
    171			"%s(): RX IRQ enabled\n", __func__);
    172		writew(readw(&i2c->regs->rx_fifo.stat_ctrl) | FIFO_IRQEN,
    173			&i2c->regs->rx_fifo.stat_ctrl);
    174	}
    175}
    176
    177static void netup_i2c_start_xfer(struct netup_i2c *i2c)
    178{
    179	u16 rdflag = ((i2c->msg->flags & I2C_M_RD) ? 1 : 0);
    180	u16 reg = readw(&i2c->regs->twi_ctrl0_stat);
    181
    182	writew(TWI_IRQEN | reg, &i2c->regs->twi_ctrl0_stat);
    183	writew(i2c->msg->len, &i2c->regs->length);
    184	writew(TWI_TRANSFER | (i2c->msg->addr << 1) | rdflag,
    185		&i2c->regs->twi_addr_ctrl1);
    186	dev_dbg(i2c->adap.dev.parent,
    187		"%s(): length %d twi_addr_ctrl1 0x%x twi_ctrl0_stat 0x%x\n",
    188		__func__, readw(&i2c->regs->length),
    189		readw(&i2c->regs->twi_addr_ctrl1),
    190		readw(&i2c->regs->twi_ctrl0_stat));
    191	i2c->state = STATE_WAIT;
    192	i2c->xmit_size = 0;
    193	if (!rdflag)
    194		netup_i2c_fifo_tx(i2c);
    195	else
    196		writew(FIFO_IRQEN | readw(&i2c->regs->rx_fifo.stat_ctrl),
    197			&i2c->regs->rx_fifo.stat_ctrl);
    198}
    199
    200static int netup_i2c_xfer(struct i2c_adapter *adap,
    201			  struct i2c_msg *msgs, int num)
    202{
    203	unsigned long flags;
    204	int i, trans_done, res = num;
    205	struct netup_i2c *i2c = i2c_get_adapdata(adap);
    206	u16 reg;
    207
    208	spin_lock_irqsave(&i2c->lock, flags);
    209	if (i2c->state != STATE_DONE) {
    210		dev_dbg(i2c->adap.dev.parent,
    211			"%s(): i2c->state == %d, resetting I2C\n",
    212			__func__, i2c->state);
    213		netup_i2c_reset(i2c);
    214	}
    215	dev_dbg(i2c->adap.dev.parent, "%s() num %d\n", __func__, num);
    216	for (i = 0; i < num; i++) {
    217		i2c->msg = &msgs[i];
    218		netup_i2c_start_xfer(i2c);
    219		trans_done = 0;
    220		while (!trans_done) {
    221			spin_unlock_irqrestore(&i2c->lock, flags);
    222			if (wait_event_timeout(i2c->wq,
    223					i2c->state != STATE_WAIT,
    224					msecs_to_jiffies(NETUP_I2C_TIMEOUT))) {
    225				spin_lock_irqsave(&i2c->lock, flags);
    226				switch (i2c->state) {
    227				case STATE_WANT_READ:
    228					netup_i2c_fifo_rx(i2c);
    229					break;
    230				case STATE_WANT_WRITE:
    231					netup_i2c_fifo_tx(i2c);
    232					break;
    233				case STATE_DONE:
    234					if ((i2c->msg->flags & I2C_M_RD) != 0 &&
    235						i2c->xmit_size != i2c->msg->len)
    236						netup_i2c_fifo_rx(i2c);
    237					dev_dbg(i2c->adap.dev.parent,
    238						"%s(): msg %d OK\n",
    239						__func__, i);
    240					trans_done = 1;
    241					break;
    242				case STATE_ERROR:
    243					res = -EIO;
    244					dev_dbg(i2c->adap.dev.parent,
    245						"%s(): error state\n",
    246						__func__);
    247					goto done;
    248				default:
    249					dev_dbg(i2c->adap.dev.parent,
    250						"%s(): invalid state %d\n",
    251						__func__, i2c->state);
    252					res = -EINVAL;
    253					goto done;
    254				}
    255				if (!trans_done) {
    256					i2c->state = STATE_WAIT;
    257					reg = readw(
    258						&i2c->regs->twi_ctrl0_stat);
    259					writew(TWI_IRQEN | reg,
    260						&i2c->regs->twi_ctrl0_stat);
    261				}
    262				spin_unlock_irqrestore(&i2c->lock, flags);
    263			} else {
    264				spin_lock_irqsave(&i2c->lock, flags);
    265				dev_dbg(i2c->adap.dev.parent,
    266					"%s(): wait timeout\n", __func__);
    267				res = -ETIMEDOUT;
    268				goto done;
    269			}
    270			spin_lock_irqsave(&i2c->lock, flags);
    271		}
    272	}
    273done:
    274	spin_unlock_irqrestore(&i2c->lock, flags);
    275	dev_dbg(i2c->adap.dev.parent, "%s(): result %d\n", __func__, res);
    276	return res;
    277}
    278
    279static u32 netup_i2c_func(struct i2c_adapter *adap)
    280{
    281	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
    282}
    283
    284static const struct i2c_algorithm netup_i2c_algorithm = {
    285	.master_xfer	= netup_i2c_xfer,
    286	.functionality	= netup_i2c_func,
    287};
    288
    289static const struct i2c_adapter netup_i2c_adapter = {
    290	.owner		= THIS_MODULE,
    291	.name		= NETUP_UNIDVB_NAME,
    292	.class		= I2C_CLASS_HWMON | I2C_CLASS_SPD,
    293	.algo		= &netup_i2c_algorithm,
    294};
    295
    296static int netup_i2c_init(struct netup_unidvb_dev *ndev, int bus_num)
    297{
    298	int ret;
    299	struct netup_i2c *i2c;
    300
    301	if (bus_num < 0 || bus_num > 1) {
    302		dev_err(&ndev->pci_dev->dev,
    303			"%s(): invalid bus_num %d\n", __func__, bus_num);
    304		return -EINVAL;
    305	}
    306	i2c = &ndev->i2c[bus_num];
    307	spin_lock_init(&i2c->lock);
    308	init_waitqueue_head(&i2c->wq);
    309	i2c->regs = (struct netup_i2c_regs __iomem *)(ndev->bmmio0 +
    310		(bus_num == 0 ? NETUP_I2C_BUS0_ADDR : NETUP_I2C_BUS1_ADDR));
    311	netup_i2c_reset(i2c);
    312	i2c->adap = netup_i2c_adapter;
    313	i2c->adap.dev.parent = &ndev->pci_dev->dev;
    314	i2c_set_adapdata(&i2c->adap, i2c);
    315	ret = i2c_add_adapter(&i2c->adap);
    316	if (ret)
    317		return ret;
    318	dev_info(&ndev->pci_dev->dev,
    319		"%s(): registered I2C bus %d at 0x%x\n",
    320		__func__,
    321		bus_num, (bus_num == 0 ?
    322			NETUP_I2C_BUS0_ADDR :
    323			NETUP_I2C_BUS1_ADDR));
    324	return 0;
    325}
    326
    327static void netup_i2c_remove(struct netup_unidvb_dev *ndev, int bus_num)
    328{
    329	struct netup_i2c *i2c;
    330
    331	if (bus_num < 0 || bus_num > 1) {
    332		dev_err(&ndev->pci_dev->dev,
    333			"%s(): invalid bus number %d\n", __func__, bus_num);
    334		return;
    335	}
    336	i2c = &ndev->i2c[bus_num];
    337	netup_i2c_reset(i2c);
    338	/* remove adapter */
    339	i2c_del_adapter(&i2c->adap);
    340	dev_info(&ndev->pci_dev->dev,
    341		"netup_i2c_remove: unregistered I2C bus %d\n", bus_num);
    342}
    343
    344int netup_i2c_register(struct netup_unidvb_dev *ndev)
    345{
    346	int ret;
    347
    348	ret = netup_i2c_init(ndev, 0);
    349	if (ret)
    350		return ret;
    351	ret = netup_i2c_init(ndev, 1);
    352	if (ret) {
    353		netup_i2c_remove(ndev, 0);
    354		return ret;
    355	}
    356	return 0;
    357}
    358
    359void netup_i2c_unregister(struct netup_unidvb_dev *ndev)
    360{
    361	netup_i2c_remove(ndev, 0);
    362	netup_i2c_remove(ndev, 1);
    363}
    364