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

saa7134-i2c.c (11303B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 *
      4 * device driver for philips saa7134 based TV cards
      5 * i2c interface support
      6 *
      7 * (c) 2001,02 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]
      8 */
      9
     10#include "saa7134.h"
     11#include "saa7134-reg.h"
     12
     13#include <linux/init.h>
     14#include <linux/list.h>
     15#include <linux/module.h>
     16#include <linux/kernel.h>
     17#include <linux/delay.h>
     18
     19#include <media/v4l2-common.h>
     20
     21/* ----------------------------------------------------------- */
     22
     23static unsigned int i2c_debug;
     24module_param(i2c_debug, int, 0644);
     25MODULE_PARM_DESC(i2c_debug,"enable debug messages [i2c]");
     26
     27static unsigned int i2c_scan;
     28module_param(i2c_scan, int, 0444);
     29MODULE_PARM_DESC(i2c_scan,"scan i2c bus at insmod time");
     30
     31#define i2c_dbg(level, fmt, arg...) do { \
     32	if (i2c_debug == level) \
     33		printk(KERN_DEBUG pr_fmt("i2c: " fmt), ## arg); \
     34	} while (0)
     35
     36#define i2c_cont(level, fmt, arg...) do { \
     37	if (i2c_debug == level) \
     38		pr_cont(fmt, ## arg); \
     39	} while (0)
     40
     41#define I2C_WAIT_DELAY  32
     42#define I2C_WAIT_RETRY  16
     43
     44/* ----------------------------------------------------------- */
     45
     46static char *str_i2c_status[] = {
     47	"IDLE", "DONE_STOP", "BUSY", "TO_SCL", "TO_ARB", "DONE_WRITE",
     48	"DONE_READ", "DONE_WRITE_TO", "DONE_READ_TO", "NO_DEVICE",
     49	"NO_ACKN", "BUS_ERR", "ARB_LOST", "SEQ_ERR", "ST_ERR", "SW_ERR"
     50};
     51
     52enum i2c_status {
     53	IDLE          = 0,  // no I2C command pending
     54	DONE_STOP     = 1,  // I2C command done and STOP executed
     55	BUSY          = 2,  // executing I2C command
     56	TO_SCL        = 3,  // executing I2C command, time out on clock stretching
     57	TO_ARB        = 4,  // time out on arbitration trial, still trying
     58	DONE_WRITE    = 5,  // I2C command done and awaiting next write command
     59	DONE_READ     = 6,  // I2C command done and awaiting next read command
     60	DONE_WRITE_TO = 7,  // see 5, and time out on status echo
     61	DONE_READ_TO  = 8,  // see 6, and time out on status echo
     62	NO_DEVICE     = 9,  // no acknowledge on device slave address
     63	NO_ACKN       = 10, // no acknowledge after data byte transfer
     64	BUS_ERR       = 11, // bus error
     65	ARB_LOST      = 12, // arbitration lost during transfer
     66	SEQ_ERR       = 13, // erroneous programming sequence
     67	ST_ERR        = 14, // wrong status echoing
     68	SW_ERR        = 15  // software error
     69};
     70
     71static char *str_i2c_attr[] = {
     72	"NOP", "STOP", "CONTINUE", "START"
     73};
     74
     75enum i2c_attr {
     76	NOP           = 0,  // no operation on I2C bus
     77	STOP          = 1,  // stop condition, no associated byte transfer
     78	CONTINUE      = 2,  // continue with byte transfer
     79	START         = 3   // start condition with byte transfer
     80};
     81
     82static inline enum i2c_status i2c_get_status(struct saa7134_dev *dev)
     83{
     84	enum i2c_status status;
     85
     86	status = saa_readb(SAA7134_I2C_ATTR_STATUS) & 0x0f;
     87	i2c_dbg(2, "i2c stat <= %s\n", str_i2c_status[status]);
     88	return status;
     89}
     90
     91static inline void i2c_set_status(struct saa7134_dev *dev,
     92				  enum i2c_status status)
     93{
     94	i2c_dbg(2, "i2c stat => %s\n", str_i2c_status[status]);
     95	saa_andorb(SAA7134_I2C_ATTR_STATUS,0x0f,status);
     96}
     97
     98static inline void i2c_set_attr(struct saa7134_dev *dev, enum i2c_attr attr)
     99{
    100	i2c_dbg(2, "i2c attr => %s\n", str_i2c_attr[attr]);
    101	saa_andorb(SAA7134_I2C_ATTR_STATUS,0xc0,attr << 6);
    102}
    103
    104static inline int i2c_is_error(enum i2c_status status)
    105{
    106	switch (status) {
    107	case NO_DEVICE:
    108	case NO_ACKN:
    109	case BUS_ERR:
    110	case ARB_LOST:
    111	case SEQ_ERR:
    112	case ST_ERR:
    113		return true;
    114	default:
    115		return false;
    116	}
    117}
    118
    119static inline int i2c_is_idle(enum i2c_status status)
    120{
    121	switch (status) {
    122	case IDLE:
    123	case DONE_STOP:
    124		return true;
    125	default:
    126		return false;
    127	}
    128}
    129
    130static inline int i2c_is_busy(enum i2c_status status)
    131{
    132	switch (status) {
    133	case BUSY:
    134	case TO_SCL:
    135	case TO_ARB:
    136		return true;
    137	default:
    138		return false;
    139	}
    140}
    141
    142static int i2c_is_busy_wait(struct saa7134_dev *dev)
    143{
    144	enum i2c_status status;
    145	int count;
    146
    147	for (count = 0; count < I2C_WAIT_RETRY; count++) {
    148		status = i2c_get_status(dev);
    149		if (!i2c_is_busy(status))
    150			break;
    151		saa_wait(I2C_WAIT_DELAY);
    152	}
    153	if (I2C_WAIT_RETRY == count)
    154		return false;
    155	return true;
    156}
    157
    158static int i2c_reset(struct saa7134_dev *dev)
    159{
    160	enum i2c_status status;
    161	int count;
    162
    163	i2c_dbg(2, "i2c reset\n");
    164	status = i2c_get_status(dev);
    165	if (!i2c_is_error(status))
    166		return true;
    167	i2c_set_status(dev,status);
    168
    169	for (count = 0; count < I2C_WAIT_RETRY; count++) {
    170		status = i2c_get_status(dev);
    171		if (!i2c_is_error(status))
    172			break;
    173		udelay(I2C_WAIT_DELAY);
    174	}
    175	if (I2C_WAIT_RETRY == count)
    176		return false;
    177
    178	if (!i2c_is_idle(status))
    179		return false;
    180
    181	i2c_set_attr(dev,NOP);
    182	return true;
    183}
    184
    185static inline int i2c_send_byte(struct saa7134_dev *dev,
    186				enum i2c_attr attr,
    187				unsigned char data)
    188{
    189	enum i2c_status status;
    190	__u32 dword;
    191
    192	/* have to write both attr + data in one 32bit word */
    193	dword  = saa_readl(SAA7134_I2C_ATTR_STATUS >> 2);
    194	dword &= 0x0f;
    195	dword |= (attr << 6);
    196	dword |= ((__u32)data << 8);
    197	dword |= 0x00 << 16;  /* 100 kHz */
    198//	dword |= 0x40 << 16;  /* 400 kHz */
    199	dword |= 0xf0 << 24;
    200	saa_writel(SAA7134_I2C_ATTR_STATUS >> 2, dword);
    201	i2c_dbg(2, "i2c data => 0x%x\n", data);
    202
    203	if (!i2c_is_busy_wait(dev))
    204		return -EIO;
    205	status = i2c_get_status(dev);
    206	if (i2c_is_error(status))
    207		return -EIO;
    208	return 0;
    209}
    210
    211static inline int i2c_recv_byte(struct saa7134_dev *dev)
    212{
    213	enum i2c_status status;
    214	unsigned char data;
    215
    216	i2c_set_attr(dev,CONTINUE);
    217	if (!i2c_is_busy_wait(dev))
    218		return -EIO;
    219	status = i2c_get_status(dev);
    220	if (i2c_is_error(status))
    221		return -EIO;
    222	data = saa_readb(SAA7134_I2C_DATA);
    223	i2c_dbg(2, "i2c data <= 0x%x\n", data);
    224	return data;
    225}
    226
    227static int saa7134_i2c_xfer(struct i2c_adapter *i2c_adap,
    228			    struct i2c_msg *msgs, int num)
    229{
    230	struct saa7134_dev *dev = i2c_adap->algo_data;
    231	enum i2c_status status;
    232	unsigned char data;
    233	int addr,rc,i,byte;
    234
    235	status = i2c_get_status(dev);
    236	if (!i2c_is_idle(status))
    237		if (!i2c_reset(dev))
    238			return -EIO;
    239
    240	i2c_dbg(2, "start xfer\n");
    241	i2c_dbg(1, "i2c xfer:");
    242	for (i = 0; i < num; i++) {
    243		if (!(msgs[i].flags & I2C_M_NOSTART) || 0 == i) {
    244			/* send address */
    245			i2c_dbg(2, "send address\n");
    246			addr  = msgs[i].addr << 1;
    247			if (msgs[i].flags & I2C_M_RD)
    248				addr |= 1;
    249			if (i > 0 && msgs[i].flags &
    250			    I2C_M_RD && msgs[i].addr != 0x40 &&
    251			    msgs[i].addr != 0x41 &&
    252			    msgs[i].addr != 0x19) {
    253				/* workaround for a saa7134 i2c bug
    254				 * needed to talk to the mt352 demux
    255				 * thanks to pinnacle for the hint */
    256				int quirk = 0xfe;
    257				i2c_cont(1, " [%02x quirk]", quirk);
    258				i2c_send_byte(dev,START,quirk);
    259				i2c_recv_byte(dev);
    260			}
    261			i2c_cont(1, " < %02x", addr);
    262			rc = i2c_send_byte(dev,START,addr);
    263			if (rc < 0)
    264				 goto err;
    265		}
    266		if (msgs[i].flags & I2C_M_RD) {
    267			/* read bytes */
    268			i2c_dbg(2, "read bytes\n");
    269			for (byte = 0; byte < msgs[i].len; byte++) {
    270				i2c_cont(1, " =");
    271				rc = i2c_recv_byte(dev);
    272				if (rc < 0)
    273					goto err;
    274				i2c_cont(1, "%02x", rc);
    275				msgs[i].buf[byte] = rc;
    276			}
    277			/* discard mysterious extra byte when reading
    278			   from Samsung S5H1411.  i2c bus gets error
    279			   if we do not. */
    280			if (0x19 == msgs[i].addr) {
    281				i2c_cont(1, " ?");
    282				rc = i2c_recv_byte(dev);
    283				if (rc < 0)
    284					goto err;
    285				i2c_cont(1, "%02x", rc);
    286			}
    287		} else {
    288			/* write bytes */
    289			i2c_dbg(2, "write bytes\n");
    290			for (byte = 0; byte < msgs[i].len; byte++) {
    291				data = msgs[i].buf[byte];
    292				i2c_cont(1, " %02x", data);
    293				rc = i2c_send_byte(dev,CONTINUE,data);
    294				if (rc < 0)
    295					goto err;
    296			}
    297		}
    298	}
    299	i2c_dbg(2, "xfer done\n");
    300	i2c_cont(1, " >");
    301	i2c_set_attr(dev,STOP);
    302	rc = -EIO;
    303	if (!i2c_is_busy_wait(dev))
    304		goto err;
    305	status = i2c_get_status(dev);
    306	if (i2c_is_error(status))
    307		goto err;
    308	/* ensure that the bus is idle for at least one bit slot */
    309	msleep(1);
    310
    311	i2c_cont(1, "\n");
    312	return num;
    313 err:
    314	if (1 == i2c_debug) {
    315		status = i2c_get_status(dev);
    316		i2c_cont(1, " ERROR: %s\n", str_i2c_status[status]);
    317	}
    318	return rc;
    319}
    320
    321/* ----------------------------------------------------------- */
    322
    323static u32 functionality(struct i2c_adapter *adap)
    324{
    325	return I2C_FUNC_SMBUS_EMUL;
    326}
    327
    328static const struct i2c_algorithm saa7134_algo = {
    329	.master_xfer   = saa7134_i2c_xfer,
    330	.functionality = functionality,
    331};
    332
    333static const struct i2c_adapter saa7134_adap_template = {
    334	.owner         = THIS_MODULE,
    335	.name          = "saa7134",
    336	.algo          = &saa7134_algo,
    337};
    338
    339static const struct i2c_client saa7134_client_template = {
    340	.name	= "saa7134 internal",
    341};
    342
    343/* ----------------------------------------------------------- */
    344
    345/*
    346 * On Medion 7134 reading the SAA7134 chip config EEPROM needs DVB-T
    347 * demod i2c gate closed due to an address clash between this EEPROM
    348 * and the demod one.
    349 */
    350static void saa7134_i2c_eeprom_md7134_gate(struct saa7134_dev *dev)
    351{
    352	u8 subaddr = 0x7, dmdregval;
    353	u8 data[2];
    354	int ret;
    355	struct i2c_msg i2cgatemsg_r[] = { {.addr = 0x08, .flags = 0,
    356					   .buf = &subaddr, .len = 1},
    357					  {.addr = 0x08,
    358					   .flags = I2C_M_RD,
    359					   .buf = &dmdregval, .len = 1}
    360					};
    361	struct i2c_msg i2cgatemsg_w[] = { {.addr = 0x08, .flags = 0,
    362					   .buf = data, .len = 2} };
    363
    364	ret = i2c_transfer(&dev->i2c_adap, i2cgatemsg_r, 2);
    365	if ((ret == 2) && (dmdregval & 0x2)) {
    366		pr_debug("%s: DVB-T demod i2c gate was left open\n",
    367			 dev->name);
    368
    369		data[0] = subaddr;
    370		data[1] = (dmdregval & ~0x2);
    371		if (i2c_transfer(&dev->i2c_adap, i2cgatemsg_w, 1) != 1)
    372			pr_err("%s: EEPROM i2c gate close failure\n",
    373			       dev->name);
    374	}
    375}
    376
    377static int
    378saa7134_i2c_eeprom(struct saa7134_dev *dev, unsigned char *eedata, int len)
    379{
    380	unsigned char buf;
    381	int i,err;
    382
    383	if (dev->board == SAA7134_BOARD_MD7134)
    384		saa7134_i2c_eeprom_md7134_gate(dev);
    385
    386	dev->i2c_client.addr = 0xa0 >> 1;
    387	buf = 0;
    388	if (1 != (err = i2c_master_send(&dev->i2c_client,&buf,1))) {
    389		pr_info("%s: Huh, no eeprom present (err=%d)?\n",
    390		       dev->name,err);
    391		return -1;
    392	}
    393	if (len != (err = i2c_master_recv(&dev->i2c_client,eedata,len))) {
    394		pr_warn("%s: i2c eeprom read error (err=%d)\n",
    395		       dev->name,err);
    396		return -1;
    397	}
    398
    399	for (i = 0; i < len; i += 16) {
    400		int size = (len - i) > 16 ? 16 : len - i;
    401
    402		pr_info("i2c eeprom %02x: %*ph\n", i, size, &eedata[i]);
    403	}
    404
    405	return 0;
    406}
    407
    408static char *i2c_devs[128] = {
    409	[ 0x20      ] = "mpeg encoder (saa6752hs)",
    410	[ 0xa0 >> 1 ] = "eeprom",
    411	[ 0xc0 >> 1 ] = "tuner (analog)",
    412	[ 0x86 >> 1 ] = "tda9887",
    413	[ 0x5a >> 1 ] = "remote control",
    414};
    415
    416static void do_i2c_scan(struct i2c_client *c)
    417{
    418	unsigned char buf;
    419	int i,rc;
    420
    421	for (i = 0; i < ARRAY_SIZE(i2c_devs); i++) {
    422		c->addr = i;
    423		rc = i2c_master_recv(c,&buf,0);
    424		if (rc < 0)
    425			continue;
    426		pr_info("i2c scan: found device @ 0x%x  [%s]\n",
    427			 i << 1, i2c_devs[i] ? i2c_devs[i] : "???");
    428	}
    429}
    430
    431int saa7134_i2c_register(struct saa7134_dev *dev)
    432{
    433	dev->i2c_adap = saa7134_adap_template;
    434	dev->i2c_adap.dev.parent = &dev->pci->dev;
    435	strscpy(dev->i2c_adap.name, dev->name, sizeof(dev->i2c_adap.name));
    436	dev->i2c_adap.algo_data = dev;
    437	i2c_set_adapdata(&dev->i2c_adap, &dev->v4l2_dev);
    438	i2c_add_adapter(&dev->i2c_adap);
    439
    440	dev->i2c_client = saa7134_client_template;
    441	dev->i2c_client.adapter = &dev->i2c_adap;
    442
    443	saa7134_i2c_eeprom(dev,dev->eedata,sizeof(dev->eedata));
    444	if (i2c_scan)
    445		do_i2c_scan(&dev->i2c_client);
    446
    447	/* Instantiate the IR receiver device, if present */
    448	saa7134_probe_i2c_ir(dev);
    449	return 0;
    450}
    451
    452int saa7134_i2c_unregister(struct saa7134_dev *dev)
    453{
    454	i2c_del_adapter(&dev->i2c_adap);
    455	return 0;
    456}