brintos

brintos / linux-shallow public Read only

0
0
Text · 5.9 KiB · 4ff6022 Raw
253 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3	Mantis PCI bridge driver4 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			1000025 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_336					| MANTIS_I2C_STOP37					| 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_384					| MANTIS_I2C_STOP85					| 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			else180				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);253