1c942fddfSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
252b1eaf4SKozlov Sergey /*
352b1eaf4SKozlov Sergey  * netup_unidvb_i2c.c
452b1eaf4SKozlov Sergey  *
552b1eaf4SKozlov Sergey  * Internal I2C bus driver for NetUP Universal Dual DVB-CI
652b1eaf4SKozlov Sergey  *
752b1eaf4SKozlov Sergey  * Copyright (C) 2014 NetUP Inc.
852b1eaf4SKozlov Sergey  * Copyright (C) 2014 Sergey Kozlov <serjk@netup.ru>
952b1eaf4SKozlov Sergey  * Copyright (C) 2014 Abylay Ospan <aospan@netup.ru>
1052b1eaf4SKozlov Sergey  */
1152b1eaf4SKozlov Sergey 
1252b1eaf4SKozlov Sergey #include <linux/module.h>
1352b1eaf4SKozlov Sergey #include <linux/moduleparam.h>
1452b1eaf4SKozlov Sergey #include <linux/init.h>
1552b1eaf4SKozlov Sergey #include <linux/delay.h>
1652b1eaf4SKozlov Sergey #include "netup_unidvb.h"
1752b1eaf4SKozlov Sergey 
1852b1eaf4SKozlov Sergey #define NETUP_I2C_BUS0_ADDR		0x4800
1952b1eaf4SKozlov Sergey #define NETUP_I2C_BUS1_ADDR		0x4840
2052b1eaf4SKozlov Sergey #define NETUP_I2C_TIMEOUT		1000
2152b1eaf4SKozlov Sergey 
2252b1eaf4SKozlov Sergey /* twi_ctrl0_stat reg bits */
2352b1eaf4SKozlov Sergey #define TWI_IRQEN_COMPL	0x1
2452b1eaf4SKozlov Sergey #define TWI_IRQEN_ANACK 0x2
2552b1eaf4SKozlov Sergey #define TWI_IRQEN_DNACK 0x4
2652b1eaf4SKozlov Sergey #define TWI_IRQ_COMPL	(TWI_IRQEN_COMPL << 8)
2752b1eaf4SKozlov Sergey #define TWI_IRQ_ANACK	(TWI_IRQEN_ANACK << 8)
2852b1eaf4SKozlov Sergey #define TWI_IRQ_DNACK	(TWI_IRQEN_DNACK << 8)
2952b1eaf4SKozlov Sergey #define TWI_IRQ_TX	0x800
3052b1eaf4SKozlov Sergey #define TWI_IRQ_RX	0x1000
3152b1eaf4SKozlov Sergey #define TWI_IRQEN	(TWI_IRQEN_COMPL | TWI_IRQEN_ANACK | TWI_IRQEN_DNACK)
3252b1eaf4SKozlov Sergey /* twi_addr_ctrl1 reg bits*/
3352b1eaf4SKozlov Sergey #define TWI_TRANSFER	0x100
3452b1eaf4SKozlov Sergey #define TWI_NOSTOP	0x200
3552b1eaf4SKozlov Sergey #define TWI_SOFT_RESET	0x2000
3652b1eaf4SKozlov Sergey /* twi_clkdiv reg value */
3752b1eaf4SKozlov Sergey #define TWI_CLKDIV	156
3852b1eaf4SKozlov Sergey /* fifo_stat_ctrl reg bits */
3952b1eaf4SKozlov Sergey #define FIFO_IRQEN	0x8000
4052b1eaf4SKozlov Sergey #define FIFO_RESET	0x4000
4152b1eaf4SKozlov Sergey /* FIFO size */
4252b1eaf4SKozlov Sergey #define FIFO_SIZE	16
4352b1eaf4SKozlov Sergey 
4452b1eaf4SKozlov Sergey struct netup_i2c_fifo_regs {
4552b1eaf4SKozlov Sergey 	union {
4652b1eaf4SKozlov Sergey 		__u8	data8;
4752b1eaf4SKozlov Sergey 		__le16	data16;
4852b1eaf4SKozlov Sergey 		__le32	data32;
4952b1eaf4SKozlov Sergey 	};
5052b1eaf4SKozlov Sergey 	__u8		padding[4];
5152b1eaf4SKozlov Sergey 	__le16		stat_ctrl;
5252b1eaf4SKozlov Sergey } __packed __aligned(1);
5352b1eaf4SKozlov Sergey 
5452b1eaf4SKozlov Sergey struct netup_i2c_regs {
5552b1eaf4SKozlov Sergey 	__le16				clkdiv;
5652b1eaf4SKozlov Sergey 	__le16				twi_ctrl0_stat;
5752b1eaf4SKozlov Sergey 	__le16				twi_addr_ctrl1;
5852b1eaf4SKozlov Sergey 	__le16				length;
5952b1eaf4SKozlov Sergey 	__u8				padding1[8];
6052b1eaf4SKozlov Sergey 	struct netup_i2c_fifo_regs	tx_fifo;
6152b1eaf4SKozlov Sergey 	__u8				padding2[6];
6252b1eaf4SKozlov Sergey 	struct netup_i2c_fifo_regs	rx_fifo;
6352b1eaf4SKozlov Sergey } __packed __aligned(1);
6452b1eaf4SKozlov Sergey 
netup_i2c_interrupt(struct netup_i2c * i2c)6552b1eaf4SKozlov Sergey irqreturn_t netup_i2c_interrupt(struct netup_i2c *i2c)
6652b1eaf4SKozlov Sergey {
6752b1eaf4SKozlov Sergey 	u16 reg, tmp;
6852b1eaf4SKozlov Sergey 	unsigned long flags;
6952b1eaf4SKozlov Sergey 	irqreturn_t iret = IRQ_HANDLED;
7052b1eaf4SKozlov Sergey 
7152b1eaf4SKozlov Sergey 	spin_lock_irqsave(&i2c->lock, flags);
7252b1eaf4SKozlov Sergey 	reg = readw(&i2c->regs->twi_ctrl0_stat);
7352b1eaf4SKozlov Sergey 	writew(reg & ~TWI_IRQEN, &i2c->regs->twi_ctrl0_stat);
7452b1eaf4SKozlov Sergey 	dev_dbg(i2c->adap.dev.parent,
7552b1eaf4SKozlov Sergey 		"%s(): twi_ctrl0_state 0x%x\n", __func__, reg);
7652b1eaf4SKozlov Sergey 	if ((reg & TWI_IRQEN_COMPL) != 0 && (reg & TWI_IRQ_COMPL)) {
7752b1eaf4SKozlov Sergey 		dev_dbg(i2c->adap.dev.parent,
7852b1eaf4SKozlov Sergey 			"%s(): TWI_IRQEN_COMPL\n", __func__);
7952b1eaf4SKozlov Sergey 		i2c->state = STATE_DONE;
8052b1eaf4SKozlov Sergey 		goto irq_ok;
8152b1eaf4SKozlov Sergey 	}
8252b1eaf4SKozlov Sergey 	if ((reg & TWI_IRQEN_ANACK) != 0 && (reg & TWI_IRQ_ANACK)) {
8352b1eaf4SKozlov Sergey 		dev_dbg(i2c->adap.dev.parent,
8452b1eaf4SKozlov Sergey 			"%s(): TWI_IRQEN_ANACK\n", __func__);
8552b1eaf4SKozlov Sergey 		i2c->state = STATE_ERROR;
8652b1eaf4SKozlov Sergey 		goto irq_ok;
8752b1eaf4SKozlov Sergey 	}
8852b1eaf4SKozlov Sergey 	if ((reg & TWI_IRQEN_DNACK) != 0 && (reg & TWI_IRQ_DNACK)) {
8952b1eaf4SKozlov Sergey 		dev_dbg(i2c->adap.dev.parent,
9052b1eaf4SKozlov Sergey 			"%s(): TWI_IRQEN_DNACK\n", __func__);
9152b1eaf4SKozlov Sergey 		i2c->state = STATE_ERROR;
9252b1eaf4SKozlov Sergey 		goto irq_ok;
9352b1eaf4SKozlov Sergey 	}
9452b1eaf4SKozlov Sergey 	if ((reg & TWI_IRQ_RX) != 0) {
9552b1eaf4SKozlov Sergey 		tmp = readw(&i2c->regs->rx_fifo.stat_ctrl);
9652b1eaf4SKozlov Sergey 		writew(tmp & ~FIFO_IRQEN, &i2c->regs->rx_fifo.stat_ctrl);
9752b1eaf4SKozlov Sergey 		i2c->state = STATE_WANT_READ;
9852b1eaf4SKozlov Sergey 		dev_dbg(i2c->adap.dev.parent,
9952b1eaf4SKozlov Sergey 			"%s(): want read\n", __func__);
10052b1eaf4SKozlov Sergey 		goto irq_ok;
10152b1eaf4SKozlov Sergey 	}
10252b1eaf4SKozlov Sergey 	if ((reg & TWI_IRQ_TX) != 0) {
10352b1eaf4SKozlov Sergey 		tmp = readw(&i2c->regs->tx_fifo.stat_ctrl);
10452b1eaf4SKozlov Sergey 		writew(tmp & ~FIFO_IRQEN, &i2c->regs->tx_fifo.stat_ctrl);
10552b1eaf4SKozlov Sergey 		i2c->state = STATE_WANT_WRITE;
10652b1eaf4SKozlov Sergey 		dev_dbg(i2c->adap.dev.parent,
10752b1eaf4SKozlov Sergey 			"%s(): want write\n", __func__);
10852b1eaf4SKozlov Sergey 		goto irq_ok;
10952b1eaf4SKozlov Sergey 	}
11052b1eaf4SKozlov Sergey 	dev_warn(&i2c->adap.dev, "%s(): not mine interrupt\n", __func__);
11152b1eaf4SKozlov Sergey 	iret = IRQ_NONE;
11252b1eaf4SKozlov Sergey irq_ok:
11352b1eaf4SKozlov Sergey 	spin_unlock_irqrestore(&i2c->lock, flags);
11452b1eaf4SKozlov Sergey 	if (iret == IRQ_HANDLED)
11552b1eaf4SKozlov Sergey 		wake_up(&i2c->wq);
11652b1eaf4SKozlov Sergey 	return iret;
11752b1eaf4SKozlov Sergey }
11852b1eaf4SKozlov Sergey 
netup_i2c_reset(struct netup_i2c * i2c)11952b1eaf4SKozlov Sergey static void netup_i2c_reset(struct netup_i2c *i2c)
12052b1eaf4SKozlov Sergey {
12152b1eaf4SKozlov Sergey 	dev_dbg(i2c->adap.dev.parent, "%s()\n", __func__);
12252b1eaf4SKozlov Sergey 	i2c->state = STATE_DONE;
12352b1eaf4SKozlov Sergey 	writew(TWI_SOFT_RESET, &i2c->regs->twi_addr_ctrl1);
12452b1eaf4SKozlov Sergey 	writew(TWI_CLKDIV, &i2c->regs->clkdiv);
12552b1eaf4SKozlov Sergey 	writew(FIFO_RESET, &i2c->regs->tx_fifo.stat_ctrl);
12652b1eaf4SKozlov Sergey 	writew(FIFO_RESET, &i2c->regs->rx_fifo.stat_ctrl);
12752b1eaf4SKozlov Sergey 	writew(0x800, &i2c->regs->tx_fifo.stat_ctrl);
12852b1eaf4SKozlov Sergey 	writew(0x800, &i2c->regs->rx_fifo.stat_ctrl);
12952b1eaf4SKozlov Sergey }
13052b1eaf4SKozlov Sergey 
netup_i2c_fifo_tx(struct netup_i2c * i2c)13152b1eaf4SKozlov Sergey static void netup_i2c_fifo_tx(struct netup_i2c *i2c)
13252b1eaf4SKozlov Sergey {
13352b1eaf4SKozlov Sergey 	u8 data;
13452b1eaf4SKozlov Sergey 	u32 fifo_space = FIFO_SIZE -
13552b1eaf4SKozlov Sergey 		(readw(&i2c->regs->tx_fifo.stat_ctrl) & 0x3f);
13652b1eaf4SKozlov Sergey 	u32 msg_length = i2c->msg->len - i2c->xmit_size;
13752b1eaf4SKozlov Sergey 
13852b1eaf4SKozlov Sergey 	msg_length = (msg_length < fifo_space ? msg_length : fifo_space);
13952b1eaf4SKozlov Sergey 	while (msg_length--) {
14052b1eaf4SKozlov Sergey 		data = i2c->msg->buf[i2c->xmit_size++];
14152b1eaf4SKozlov Sergey 		writeb(data, &i2c->regs->tx_fifo.data8);
14252b1eaf4SKozlov Sergey 		dev_dbg(i2c->adap.dev.parent,
14352b1eaf4SKozlov Sergey 			"%s(): write 0x%02x\n", __func__, data);
14452b1eaf4SKozlov Sergey 	}
14552b1eaf4SKozlov Sergey 	if (i2c->xmit_size < i2c->msg->len) {
14652b1eaf4SKozlov Sergey 		dev_dbg(i2c->adap.dev.parent,
14752b1eaf4SKozlov Sergey 			"%s(): TX IRQ enabled\n", __func__);
14852b1eaf4SKozlov Sergey 		writew(readw(&i2c->regs->tx_fifo.stat_ctrl) | FIFO_IRQEN,
14952b1eaf4SKozlov Sergey 			&i2c->regs->tx_fifo.stat_ctrl);
15052b1eaf4SKozlov Sergey 	}
15152b1eaf4SKozlov Sergey }
15252b1eaf4SKozlov Sergey 
netup_i2c_fifo_rx(struct netup_i2c * i2c)15352b1eaf4SKozlov Sergey static void netup_i2c_fifo_rx(struct netup_i2c *i2c)
15452b1eaf4SKozlov Sergey {
15552b1eaf4SKozlov Sergey 	u8 data;
15652b1eaf4SKozlov Sergey 	u32 fifo_size = readw(&i2c->regs->rx_fifo.stat_ctrl) & 0x3f;
15752b1eaf4SKozlov Sergey 
15852b1eaf4SKozlov Sergey 	dev_dbg(i2c->adap.dev.parent,
15952b1eaf4SKozlov Sergey 		"%s(): RX fifo size %d\n", __func__, fifo_size);
16052b1eaf4SKozlov Sergey 	while (fifo_size--) {
16152b1eaf4SKozlov Sergey 		data = readb(&i2c->regs->rx_fifo.data8);
16252b1eaf4SKozlov Sergey 		if ((i2c->msg->flags & I2C_M_RD) != 0 &&
16352b1eaf4SKozlov Sergey 					i2c->xmit_size < i2c->msg->len) {
16452b1eaf4SKozlov Sergey 			i2c->msg->buf[i2c->xmit_size++] = data;
16552b1eaf4SKozlov Sergey 			dev_dbg(i2c->adap.dev.parent,
16652b1eaf4SKozlov Sergey 				"%s(): read 0x%02x\n", __func__, data);
16752b1eaf4SKozlov Sergey 		}
16852b1eaf4SKozlov Sergey 	}
16952b1eaf4SKozlov Sergey 	if (i2c->xmit_size < i2c->msg->len) {
17052b1eaf4SKozlov Sergey 		dev_dbg(i2c->adap.dev.parent,
17152b1eaf4SKozlov Sergey 			"%s(): RX IRQ enabled\n", __func__);
17252b1eaf4SKozlov Sergey 		writew(readw(&i2c->regs->rx_fifo.stat_ctrl) | FIFO_IRQEN,
17352b1eaf4SKozlov Sergey 			&i2c->regs->rx_fifo.stat_ctrl);
17452b1eaf4SKozlov Sergey 	}
17552b1eaf4SKozlov Sergey }
17652b1eaf4SKozlov Sergey 
netup_i2c_start_xfer(struct netup_i2c * i2c)17752b1eaf4SKozlov Sergey static void netup_i2c_start_xfer(struct netup_i2c *i2c)
17852b1eaf4SKozlov Sergey {
17952b1eaf4SKozlov Sergey 	u16 rdflag = ((i2c->msg->flags & I2C_M_RD) ? 1 : 0);
18052b1eaf4SKozlov Sergey 	u16 reg = readw(&i2c->regs->twi_ctrl0_stat);
18152b1eaf4SKozlov Sergey 
18252b1eaf4SKozlov Sergey 	writew(TWI_IRQEN | reg, &i2c->regs->twi_ctrl0_stat);
18352b1eaf4SKozlov Sergey 	writew(i2c->msg->len, &i2c->regs->length);
18452b1eaf4SKozlov Sergey 	writew(TWI_TRANSFER | (i2c->msg->addr << 1) | rdflag,
18552b1eaf4SKozlov Sergey 		&i2c->regs->twi_addr_ctrl1);
18652b1eaf4SKozlov Sergey 	dev_dbg(i2c->adap.dev.parent,
18752b1eaf4SKozlov Sergey 		"%s(): length %d twi_addr_ctrl1 0x%x twi_ctrl0_stat 0x%x\n",
18852b1eaf4SKozlov Sergey 		__func__, readw(&i2c->regs->length),
18952b1eaf4SKozlov Sergey 		readw(&i2c->regs->twi_addr_ctrl1),
19052b1eaf4SKozlov Sergey 		readw(&i2c->regs->twi_ctrl0_stat));
19152b1eaf4SKozlov Sergey 	i2c->state = STATE_WAIT;
19252b1eaf4SKozlov Sergey 	i2c->xmit_size = 0;
19352b1eaf4SKozlov Sergey 	if (!rdflag)
19452b1eaf4SKozlov Sergey 		netup_i2c_fifo_tx(i2c);
19552b1eaf4SKozlov Sergey 	else
19652b1eaf4SKozlov Sergey 		writew(FIFO_IRQEN | readw(&i2c->regs->rx_fifo.stat_ctrl),
19752b1eaf4SKozlov Sergey 			&i2c->regs->rx_fifo.stat_ctrl);
19852b1eaf4SKozlov Sergey }
19952b1eaf4SKozlov Sergey 
netup_i2c_xfer(struct i2c_adapter * adap,struct i2c_msg * msgs,int num)20052b1eaf4SKozlov Sergey static int netup_i2c_xfer(struct i2c_adapter *adap,
20152b1eaf4SKozlov Sergey 			  struct i2c_msg *msgs, int num)
20252b1eaf4SKozlov Sergey {
20352b1eaf4SKozlov Sergey 	unsigned long flags;
20452b1eaf4SKozlov Sergey 	int i, trans_done, res = num;
20552b1eaf4SKozlov Sergey 	struct netup_i2c *i2c = i2c_get_adapdata(adap);
20652b1eaf4SKozlov Sergey 	u16 reg;
20752b1eaf4SKozlov Sergey 
20852b1eaf4SKozlov Sergey 	spin_lock_irqsave(&i2c->lock, flags);
20952b1eaf4SKozlov Sergey 	if (i2c->state != STATE_DONE) {
21052b1eaf4SKozlov Sergey 		dev_dbg(i2c->adap.dev.parent,
21152b1eaf4SKozlov Sergey 			"%s(): i2c->state == %d, resetting I2C\n",
21252b1eaf4SKozlov Sergey 			__func__, i2c->state);
21352b1eaf4SKozlov Sergey 		netup_i2c_reset(i2c);
21452b1eaf4SKozlov Sergey 	}
21552b1eaf4SKozlov Sergey 	dev_dbg(i2c->adap.dev.parent, "%s() num %d\n", __func__, num);
21652b1eaf4SKozlov Sergey 	for (i = 0; i < num; i++) {
21752b1eaf4SKozlov Sergey 		i2c->msg = &msgs[i];
21852b1eaf4SKozlov Sergey 		netup_i2c_start_xfer(i2c);
21952b1eaf4SKozlov Sergey 		trans_done = 0;
22052b1eaf4SKozlov Sergey 		while (!trans_done) {
22152b1eaf4SKozlov Sergey 			spin_unlock_irqrestore(&i2c->lock, flags);
22252b1eaf4SKozlov Sergey 			if (wait_event_timeout(i2c->wq,
22352b1eaf4SKozlov Sergey 					i2c->state != STATE_WAIT,
22452b1eaf4SKozlov Sergey 					msecs_to_jiffies(NETUP_I2C_TIMEOUT))) {
22552b1eaf4SKozlov Sergey 				spin_lock_irqsave(&i2c->lock, flags);
22652b1eaf4SKozlov Sergey 				switch (i2c->state) {
22752b1eaf4SKozlov Sergey 				case STATE_WANT_READ:
22852b1eaf4SKozlov Sergey 					netup_i2c_fifo_rx(i2c);
22952b1eaf4SKozlov Sergey 					break;
23052b1eaf4SKozlov Sergey 				case STATE_WANT_WRITE:
23152b1eaf4SKozlov Sergey 					netup_i2c_fifo_tx(i2c);
23252b1eaf4SKozlov Sergey 					break;
23352b1eaf4SKozlov Sergey 				case STATE_DONE:
23452b1eaf4SKozlov Sergey 					if ((i2c->msg->flags & I2C_M_RD) != 0 &&
23552b1eaf4SKozlov Sergey 						i2c->xmit_size != i2c->msg->len)
23652b1eaf4SKozlov Sergey 						netup_i2c_fifo_rx(i2c);
23752b1eaf4SKozlov Sergey 					dev_dbg(i2c->adap.dev.parent,
23852b1eaf4SKozlov Sergey 						"%s(): msg %d OK\n",
23952b1eaf4SKozlov Sergey 						__func__, i);
24052b1eaf4SKozlov Sergey 					trans_done = 1;
24152b1eaf4SKozlov Sergey 					break;
24252b1eaf4SKozlov Sergey 				case STATE_ERROR:
24352b1eaf4SKozlov Sergey 					res = -EIO;
24452b1eaf4SKozlov Sergey 					dev_dbg(i2c->adap.dev.parent,
24552b1eaf4SKozlov Sergey 						"%s(): error state\n",
24652b1eaf4SKozlov Sergey 						__func__);
24752b1eaf4SKozlov Sergey 					goto done;
24852b1eaf4SKozlov Sergey 				default:
24952b1eaf4SKozlov Sergey 					dev_dbg(i2c->adap.dev.parent,
25052b1eaf4SKozlov Sergey 						"%s(): invalid state %d\n",
25152b1eaf4SKozlov Sergey 						__func__, i2c->state);
25252b1eaf4SKozlov Sergey 					res = -EINVAL;
25352b1eaf4SKozlov Sergey 					goto done;
25452b1eaf4SKozlov Sergey 				}
25552b1eaf4SKozlov Sergey 				if (!trans_done) {
25652b1eaf4SKozlov Sergey 					i2c->state = STATE_WAIT;
25752b1eaf4SKozlov Sergey 					reg = readw(
25852b1eaf4SKozlov Sergey 						&i2c->regs->twi_ctrl0_stat);
25952b1eaf4SKozlov Sergey 					writew(TWI_IRQEN | reg,
26052b1eaf4SKozlov Sergey 						&i2c->regs->twi_ctrl0_stat);
26152b1eaf4SKozlov Sergey 				}
26252b1eaf4SKozlov Sergey 				spin_unlock_irqrestore(&i2c->lock, flags);
26352b1eaf4SKozlov Sergey 			} else {
26452b1eaf4SKozlov Sergey 				spin_lock_irqsave(&i2c->lock, flags);
26552b1eaf4SKozlov Sergey 				dev_dbg(i2c->adap.dev.parent,
26652b1eaf4SKozlov Sergey 					"%s(): wait timeout\n", __func__);
26752b1eaf4SKozlov Sergey 				res = -ETIMEDOUT;
26852b1eaf4SKozlov Sergey 				goto done;
26952b1eaf4SKozlov Sergey 			}
27052b1eaf4SKozlov Sergey 			spin_lock_irqsave(&i2c->lock, flags);
27152b1eaf4SKozlov Sergey 		}
27252b1eaf4SKozlov Sergey 	}
27352b1eaf4SKozlov Sergey done:
27452b1eaf4SKozlov Sergey 	spin_unlock_irqrestore(&i2c->lock, flags);
27552b1eaf4SKozlov Sergey 	dev_dbg(i2c->adap.dev.parent, "%s(): result %d\n", __func__, res);
27652b1eaf4SKozlov Sergey 	return res;
27752b1eaf4SKozlov Sergey }
27852b1eaf4SKozlov Sergey 
netup_i2c_func(struct i2c_adapter * adap)27952b1eaf4SKozlov Sergey static u32 netup_i2c_func(struct i2c_adapter *adap)
28052b1eaf4SKozlov Sergey {
28152b1eaf4SKozlov Sergey 	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
28252b1eaf4SKozlov Sergey }
28352b1eaf4SKozlov Sergey 
28452b1eaf4SKozlov Sergey static const struct i2c_algorithm netup_i2c_algorithm = {
28552b1eaf4SKozlov Sergey 	.master_xfer	= netup_i2c_xfer,
28652b1eaf4SKozlov Sergey 	.functionality	= netup_i2c_func,
28752b1eaf4SKozlov Sergey };
28852b1eaf4SKozlov Sergey 
289e5fffebeSBhumika Goyal static const struct i2c_adapter netup_i2c_adapter = {
29052b1eaf4SKozlov Sergey 	.owner		= THIS_MODULE,
29152b1eaf4SKozlov Sergey 	.name		= NETUP_UNIDVB_NAME,
29252b1eaf4SKozlov Sergey 	.class		= I2C_CLASS_HWMON | I2C_CLASS_SPD,
29352b1eaf4SKozlov Sergey 	.algo		= &netup_i2c_algorithm,
29452b1eaf4SKozlov Sergey };
29552b1eaf4SKozlov Sergey 
netup_i2c_init(struct netup_unidvb_dev * ndev,int bus_num)29652b1eaf4SKozlov Sergey static int netup_i2c_init(struct netup_unidvb_dev *ndev, int bus_num)
29752b1eaf4SKozlov Sergey {
29852b1eaf4SKozlov Sergey 	int ret;
29952b1eaf4SKozlov Sergey 	struct netup_i2c *i2c;
30052b1eaf4SKozlov Sergey 
30152b1eaf4SKozlov Sergey 	if (bus_num < 0 || bus_num > 1) {
30252b1eaf4SKozlov Sergey 		dev_err(&ndev->pci_dev->dev,
30352b1eaf4SKozlov Sergey 			"%s(): invalid bus_num %d\n", __func__, bus_num);
30452b1eaf4SKozlov Sergey 		return -EINVAL;
30552b1eaf4SKozlov Sergey 	}
30652b1eaf4SKozlov Sergey 	i2c = &ndev->i2c[bus_num];
30752b1eaf4SKozlov Sergey 	spin_lock_init(&i2c->lock);
30852b1eaf4SKozlov Sergey 	init_waitqueue_head(&i2c->wq);
309d91b1d91SMauro Carvalho Chehab 	i2c->regs = (struct netup_i2c_regs __iomem *)(ndev->bmmio0 +
31052b1eaf4SKozlov Sergey 		(bus_num == 0 ? NETUP_I2C_BUS0_ADDR : NETUP_I2C_BUS1_ADDR));
31152b1eaf4SKozlov Sergey 	netup_i2c_reset(i2c);
31252b1eaf4SKozlov Sergey 	i2c->adap = netup_i2c_adapter;
31352b1eaf4SKozlov Sergey 	i2c->adap.dev.parent = &ndev->pci_dev->dev;
31452b1eaf4SKozlov Sergey 	i2c_set_adapdata(&i2c->adap, i2c);
31552b1eaf4SKozlov Sergey 	ret = i2c_add_adapter(&i2c->adap);
31638e699bcSWolfram Sang 	if (ret)
31752b1eaf4SKozlov Sergey 		return ret;
31852b1eaf4SKozlov Sergey 	dev_info(&ndev->pci_dev->dev,
31952b1eaf4SKozlov Sergey 		"%s(): registered I2C bus %d at 0x%x\n",
32052b1eaf4SKozlov Sergey 		__func__,
32152b1eaf4SKozlov Sergey 		bus_num, (bus_num == 0 ?
32252b1eaf4SKozlov Sergey 			NETUP_I2C_BUS0_ADDR :
32352b1eaf4SKozlov Sergey 			NETUP_I2C_BUS1_ADDR));
32452b1eaf4SKozlov Sergey 	return 0;
32552b1eaf4SKozlov Sergey }
32652b1eaf4SKozlov Sergey 
netup_i2c_remove(struct netup_unidvb_dev * ndev,int bus_num)32752b1eaf4SKozlov Sergey static void netup_i2c_remove(struct netup_unidvb_dev *ndev, int bus_num)
32852b1eaf4SKozlov Sergey {
32952b1eaf4SKozlov Sergey 	struct netup_i2c *i2c;
33052b1eaf4SKozlov Sergey 
33152b1eaf4SKozlov Sergey 	if (bus_num < 0 || bus_num > 1) {
33252b1eaf4SKozlov Sergey 		dev_err(&ndev->pci_dev->dev,
33352b1eaf4SKozlov Sergey 			"%s(): invalid bus number %d\n", __func__, bus_num);
33452b1eaf4SKozlov Sergey 		return;
33552b1eaf4SKozlov Sergey 	}
33652b1eaf4SKozlov Sergey 	i2c = &ndev->i2c[bus_num];
33752b1eaf4SKozlov Sergey 	netup_i2c_reset(i2c);
33852b1eaf4SKozlov Sergey 	/* remove adapter */
33952b1eaf4SKozlov Sergey 	i2c_del_adapter(&i2c->adap);
34052b1eaf4SKozlov Sergey 	dev_info(&ndev->pci_dev->dev,
34152b1eaf4SKozlov Sergey 		"netup_i2c_remove: unregistered I2C bus %d\n", bus_num);
34252b1eaf4SKozlov Sergey }
34352b1eaf4SKozlov Sergey 
netup_i2c_register(struct netup_unidvb_dev * ndev)34452b1eaf4SKozlov Sergey int netup_i2c_register(struct netup_unidvb_dev *ndev)
34552b1eaf4SKozlov Sergey {
34652b1eaf4SKozlov Sergey 	int ret;
34752b1eaf4SKozlov Sergey 
34852b1eaf4SKozlov Sergey 	ret = netup_i2c_init(ndev, 0);
34952b1eaf4SKozlov Sergey 	if (ret)
35052b1eaf4SKozlov Sergey 		return ret;
35152b1eaf4SKozlov Sergey 	ret = netup_i2c_init(ndev, 1);
35252b1eaf4SKozlov Sergey 	if (ret) {
35352b1eaf4SKozlov Sergey 		netup_i2c_remove(ndev, 0);
35452b1eaf4SKozlov Sergey 		return ret;
35552b1eaf4SKozlov Sergey 	}
35652b1eaf4SKozlov Sergey 	return 0;
35752b1eaf4SKozlov Sergey }
35852b1eaf4SKozlov Sergey 
netup_i2c_unregister(struct netup_unidvb_dev * ndev)35952b1eaf4SKozlov Sergey void netup_i2c_unregister(struct netup_unidvb_dev *ndev)
36052b1eaf4SKozlov Sergey {
36152b1eaf4SKozlov Sergey 	netup_i2c_remove(ndev, 0);
36252b1eaf4SKozlov Sergey 	netup_i2c_remove(ndev, 1);
36352b1eaf4SKozlov Sergey }
36452b1eaf4SKozlov Sergey 
365