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

cx231xx-i2c.c (14065B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3   cx231xx-i2c.c - driver for Conexant Cx23100/101/102 USB video capture devices
      4
      5   Copyright (C) 2008 <srinivasa.deevi at conexant dot com>
      6		Based on em28xx driver
      7		Based on Cx23885 driver
      8
      9 */
     10
     11#include "cx231xx.h"
     12#include <linux/module.h>
     13#include <linux/kernel.h>
     14#include <linux/i2c.h>
     15#include <linux/i2c-mux.h>
     16#include <media/v4l2-common.h>
     17#include <media/tuner.h>
     18
     19
     20/* ----------------------------------------------------------- */
     21
     22static unsigned int i2c_scan;
     23module_param(i2c_scan, int, 0444);
     24MODULE_PARM_DESC(i2c_scan, "scan i2c bus at insmod time");
     25
     26static unsigned int i2c_debug;
     27module_param(i2c_debug, int, 0644);
     28MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]");
     29
     30#define dprintk1(lvl, fmt, args...)			\
     31do {							\
     32	if (i2c_debug >= lvl) {				\
     33		printk(fmt, ##args);			\
     34		}					\
     35} while (0)
     36
     37#define dprintk2(lvl, fmt, args...)			\
     38do {							\
     39	if (i2c_debug >= lvl) {				\
     40		printk(KERN_DEBUG "%s at %s: " fmt,	\
     41		       dev->name, __func__ , ##args);	\
     42      }							\
     43} while (0)
     44
     45static inline int get_real_i2c_port(struct cx231xx *dev, int bus_nr)
     46{
     47	if (bus_nr == 1)
     48		return dev->port_3_switch_enabled ? I2C_1_MUX_3 : I2C_1_MUX_1;
     49	return bus_nr;
     50}
     51
     52static inline bool is_tuner(struct cx231xx *dev, struct cx231xx_i2c *bus,
     53			const struct i2c_msg *msg, int tuner_type)
     54{
     55	int i2c_port = get_real_i2c_port(dev, bus->nr);
     56
     57	if (i2c_port != dev->board.tuner_i2c_master)
     58		return false;
     59
     60	if (msg->addr != dev->board.tuner_addr)
     61		return false;
     62
     63	if (dev->tuner_type != tuner_type)
     64		return false;
     65
     66	return true;
     67}
     68
     69/*
     70 * cx231xx_i2c_send_bytes()
     71 */
     72static int cx231xx_i2c_send_bytes(struct i2c_adapter *i2c_adap,
     73				  const struct i2c_msg *msg)
     74{
     75	struct cx231xx_i2c *bus = i2c_adap->algo_data;
     76	struct cx231xx *dev = bus->dev;
     77	struct cx231xx_i2c_xfer_data req_data;
     78	int status = 0;
     79	u16 size = 0;
     80	u8 loop = 0;
     81	u8 saddr_len = 1;
     82	u8 *buf_ptr = NULL;
     83	u16 saddr = 0;
     84	u8 need_gpio = 0;
     85
     86	if (is_tuner(dev, bus, msg, TUNER_XC5000)) {
     87		size = msg->len;
     88
     89		if (size == 2) {	/* register write sub addr */
     90			/* Just writing sub address will cause problem
     91			* to XC5000. So ignore the request */
     92			return 0;
     93		} else if (size == 4) {	/* register write with sub addr */
     94			if (msg->len >= 2)
     95				saddr = msg->buf[0] << 8 | msg->buf[1];
     96			else if (msg->len == 1)
     97				saddr = msg->buf[0];
     98
     99			switch (saddr) {
    100			case 0x0000:	/* start tuner calibration mode */
    101				need_gpio = 1;
    102				/* FW Loading is done */
    103				dev->xc_fw_load_done = 1;
    104				break;
    105			case 0x000D:	/* Set signal source */
    106			case 0x0001:	/* Set TV standard - Video */
    107			case 0x0002:	/* Set TV standard - Audio */
    108			case 0x0003:	/* Set RF Frequency */
    109				need_gpio = 1;
    110				break;
    111			default:
    112				if (dev->xc_fw_load_done)
    113					need_gpio = 1;
    114				break;
    115			}
    116
    117			if (need_gpio) {
    118				dprintk1(1,
    119				"GPIO WRITE: addr 0x%x, len %d, saddr 0x%x\n",
    120				msg->addr, msg->len, saddr);
    121
    122				return dev->cx231xx_gpio_i2c_write(dev,
    123								   msg->addr,
    124								   msg->buf,
    125								   msg->len);
    126			}
    127		}
    128
    129		/* special case for Xc5000 tuner case */
    130		saddr_len = 1;
    131
    132		/* adjust the length to correct length */
    133		size -= saddr_len;
    134		buf_ptr = (u8 *) (msg->buf + 1);
    135
    136		do {
    137			/* prepare xfer_data struct */
    138			req_data.dev_addr = msg->addr;
    139			req_data.direction = msg->flags;
    140			req_data.saddr_len = saddr_len;
    141			req_data.saddr_dat = msg->buf[0];
    142			req_data.buf_size = size > 16 ? 16 : size;
    143			req_data.p_buffer = (u8 *) (buf_ptr + loop * 16);
    144
    145			bus->i2c_nostop = (size > 16) ? 1 : 0;
    146			bus->i2c_reserve = (loop == 0) ? 0 : 1;
    147
    148			/* usb send command */
    149			status = dev->cx231xx_send_usb_command(bus, &req_data);
    150			loop++;
    151
    152			if (size >= 16)
    153				size -= 16;
    154			else
    155				size = 0;
    156
    157		} while (size > 0);
    158
    159		bus->i2c_nostop = 0;
    160		bus->i2c_reserve = 0;
    161
    162	} else {		/* regular case */
    163
    164		/* prepare xfer_data struct */
    165		req_data.dev_addr = msg->addr;
    166		req_data.direction = msg->flags;
    167		req_data.saddr_len = 0;
    168		req_data.saddr_dat = 0;
    169		req_data.buf_size = msg->len;
    170		req_data.p_buffer = msg->buf;
    171
    172		/* usb send command */
    173		status = dev->cx231xx_send_usb_command(bus, &req_data);
    174	}
    175
    176	return status < 0 ? status : 0;
    177}
    178
    179/*
    180 * cx231xx_i2c_recv_bytes()
    181 * read a byte from the i2c device
    182 */
    183static int cx231xx_i2c_recv_bytes(struct i2c_adapter *i2c_adap,
    184				  const struct i2c_msg *msg)
    185{
    186	struct cx231xx_i2c *bus = i2c_adap->algo_data;
    187	struct cx231xx *dev = bus->dev;
    188	struct cx231xx_i2c_xfer_data req_data;
    189	int status = 0;
    190	u16 saddr = 0;
    191	u8 need_gpio = 0;
    192
    193	if (is_tuner(dev, bus, msg, TUNER_XC5000)) {
    194		if (msg->len == 2)
    195			saddr = msg->buf[0] << 8 | msg->buf[1];
    196		else if (msg->len == 1)
    197			saddr = msg->buf[0];
    198
    199		if (dev->xc_fw_load_done) {
    200
    201			switch (saddr) {
    202			case 0x0009:	/* BUSY check */
    203				dprintk1(1,
    204				"GPIO R E A D: Special case BUSY check \n");
    205				/*Try read BUSY register, just set it to zero*/
    206				msg->buf[0] = 0;
    207				if (msg->len == 2)
    208					msg->buf[1] = 0;
    209				return 0;
    210			case 0x0004:	/* read Lock status */
    211				need_gpio = 1;
    212				break;
    213
    214			}
    215
    216			if (need_gpio) {
    217				/* this is a special case to handle Xceive tuner
    218				clock stretch issue with gpio based I2C */
    219
    220				dprintk1(1,
    221				"GPIO R E A D: addr 0x%x, len %d, saddr 0x%x\n",
    222				msg->addr, msg->len,
    223				msg->buf[0] << 8 | msg->buf[1]);
    224
    225				status =
    226				    dev->cx231xx_gpio_i2c_write(dev, msg->addr,
    227								msg->buf,
    228								msg->len);
    229				status =
    230				    dev->cx231xx_gpio_i2c_read(dev, msg->addr,
    231							       msg->buf,
    232							       msg->len);
    233				return status;
    234			}
    235		}
    236
    237		/* prepare xfer_data struct */
    238		req_data.dev_addr = msg->addr;
    239		req_data.direction = msg->flags;
    240		req_data.saddr_len = msg->len;
    241		req_data.saddr_dat = msg->buf[0] << 8 | msg->buf[1];
    242		req_data.buf_size = msg->len;
    243		req_data.p_buffer = msg->buf;
    244
    245		/* usb send command */
    246		status = dev->cx231xx_send_usb_command(bus, &req_data);
    247
    248	} else {
    249
    250		/* prepare xfer_data struct */
    251		req_data.dev_addr = msg->addr;
    252		req_data.direction = msg->flags;
    253		req_data.saddr_len = 0;
    254		req_data.saddr_dat = 0;
    255		req_data.buf_size = msg->len;
    256		req_data.p_buffer = msg->buf;
    257
    258		/* usb send command */
    259		status = dev->cx231xx_send_usb_command(bus, &req_data);
    260	}
    261
    262	return status < 0 ? status : 0;
    263}
    264
    265/*
    266 * cx231xx_i2c_recv_bytes_with_saddr()
    267 * read a byte from the i2c device
    268 */
    269static int cx231xx_i2c_recv_bytes_with_saddr(struct i2c_adapter *i2c_adap,
    270					     const struct i2c_msg *msg1,
    271					     const struct i2c_msg *msg2)
    272{
    273	struct cx231xx_i2c *bus = i2c_adap->algo_data;
    274	struct cx231xx *dev = bus->dev;
    275	struct cx231xx_i2c_xfer_data req_data;
    276	int status = 0;
    277	u16 saddr = 0;
    278	u8 need_gpio = 0;
    279
    280	if (msg1->len == 2)
    281		saddr = msg1->buf[0] << 8 | msg1->buf[1];
    282	else if (msg1->len == 1)
    283		saddr = msg1->buf[0];
    284
    285	if (is_tuner(dev, bus, msg2, TUNER_XC5000)) {
    286		if ((msg2->len < 16)) {
    287
    288			dprintk1(1,
    289			"i2c_read: addr 0x%x, len %d, saddr 0x%x, len %d\n",
    290			msg2->addr, msg2->len, saddr, msg1->len);
    291
    292			switch (saddr) {
    293			case 0x0008:	/* read FW load status */
    294				need_gpio = 1;
    295				break;
    296			case 0x0004:	/* read Lock status */
    297				need_gpio = 1;
    298				break;
    299			}
    300
    301			if (need_gpio) {
    302				status =
    303				    dev->cx231xx_gpio_i2c_write(dev, msg1->addr,
    304								msg1->buf,
    305								msg1->len);
    306				status =
    307				    dev->cx231xx_gpio_i2c_read(dev, msg2->addr,
    308							       msg2->buf,
    309							       msg2->len);
    310				return status;
    311			}
    312		}
    313	}
    314
    315	/* prepare xfer_data struct */
    316	req_data.dev_addr = msg2->addr;
    317	req_data.direction = msg2->flags;
    318	req_data.saddr_len = msg1->len;
    319	req_data.saddr_dat = saddr;
    320	req_data.buf_size = msg2->len;
    321	req_data.p_buffer = msg2->buf;
    322
    323	/* usb send command */
    324	status = dev->cx231xx_send_usb_command(bus, &req_data);
    325
    326	return status < 0 ? status : 0;
    327}
    328
    329/*
    330 * cx231xx_i2c_check_for_device()
    331 * check if there is a i2c_device at the supplied address
    332 */
    333static int cx231xx_i2c_check_for_device(struct i2c_adapter *i2c_adap,
    334					const struct i2c_msg *msg)
    335{
    336	struct cx231xx_i2c *bus = i2c_adap->algo_data;
    337	struct cx231xx *dev = bus->dev;
    338	struct cx231xx_i2c_xfer_data req_data;
    339	int status = 0;
    340	u8 buf[1];
    341
    342	/* prepare xfer_data struct */
    343	req_data.dev_addr = msg->addr;
    344	req_data.direction = I2C_M_RD;
    345	req_data.saddr_len = 0;
    346	req_data.saddr_dat = 0;
    347	req_data.buf_size = 1;
    348	req_data.p_buffer = buf;
    349
    350	/* usb send command */
    351	status = dev->cx231xx_send_usb_command(bus, &req_data);
    352
    353	return status < 0 ? status : 0;
    354}
    355
    356/*
    357 * cx231xx_i2c_xfer()
    358 * the main i2c transfer function
    359 */
    360static int cx231xx_i2c_xfer(struct i2c_adapter *i2c_adap,
    361			    struct i2c_msg msgs[], int num)
    362{
    363	struct cx231xx_i2c *bus = i2c_adap->algo_data;
    364	struct cx231xx *dev = bus->dev;
    365	int addr, rc, i, byte;
    366
    367	mutex_lock(&dev->i2c_lock);
    368	for (i = 0; i < num; i++) {
    369
    370		addr = msgs[i].addr;
    371
    372		dprintk2(2, "%s %s addr=0x%x len=%d:",
    373			 (msgs[i].flags & I2C_M_RD) ? "read" : "write",
    374			 i == num - 1 ? "stop" : "nonstop", addr, msgs[i].len);
    375		if (!msgs[i].len) {
    376			/* no len: check only for device presence */
    377			rc = cx231xx_i2c_check_for_device(i2c_adap, &msgs[i]);
    378			if (rc < 0) {
    379				dprintk2(2, " no device\n");
    380				mutex_unlock(&dev->i2c_lock);
    381				return rc;
    382			}
    383
    384		} else if (msgs[i].flags & I2C_M_RD) {
    385			/* read bytes */
    386			rc = cx231xx_i2c_recv_bytes(i2c_adap, &msgs[i]);
    387			if (i2c_debug >= 2) {
    388				for (byte = 0; byte < msgs[i].len; byte++)
    389					printk(KERN_CONT " %02x", msgs[i].buf[byte]);
    390			}
    391		} else if (i + 1 < num && (msgs[i + 1].flags & I2C_M_RD) &&
    392			   msgs[i].addr == msgs[i + 1].addr
    393			   && (msgs[i].len <= 2) && (bus->nr < 3)) {
    394			/* write bytes */
    395			if (i2c_debug >= 2) {
    396				for (byte = 0; byte < msgs[i].len; byte++)
    397					printk(KERN_CONT " %02x", msgs[i].buf[byte]);
    398				printk(KERN_CONT "\n");
    399			}
    400			/* read bytes */
    401			dprintk2(2, "plus %s %s addr=0x%x len=%d:",
    402				(msgs[i+1].flags & I2C_M_RD) ? "read" : "write",
    403				i+1 == num - 1 ? "stop" : "nonstop", addr, msgs[i+1].len);
    404			rc = cx231xx_i2c_recv_bytes_with_saddr(i2c_adap,
    405							       &msgs[i],
    406							       &msgs[i + 1]);
    407			if (i2c_debug >= 2) {
    408				for (byte = 0; byte < msgs[i+1].len; byte++)
    409					printk(KERN_CONT " %02x", msgs[i+1].buf[byte]);
    410			}
    411			i++;
    412		} else {
    413			/* write bytes */
    414			if (i2c_debug >= 2) {
    415				for (byte = 0; byte < msgs[i].len; byte++)
    416					printk(KERN_CONT " %02x", msgs[i].buf[byte]);
    417			}
    418			rc = cx231xx_i2c_send_bytes(i2c_adap, &msgs[i]);
    419		}
    420		if (rc < 0)
    421			goto err;
    422		if (i2c_debug >= 2)
    423			printk(KERN_CONT "\n");
    424	}
    425	mutex_unlock(&dev->i2c_lock);
    426	return num;
    427err:
    428	dprintk2(2, " ERROR: %i\n", rc);
    429	mutex_unlock(&dev->i2c_lock);
    430	return rc;
    431}
    432
    433/* ----------------------------------------------------------- */
    434
    435/*
    436 * functionality()
    437 */
    438static u32 functionality(struct i2c_adapter *adap)
    439{
    440	return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_I2C;
    441}
    442
    443static const struct i2c_algorithm cx231xx_algo = {
    444	.master_xfer = cx231xx_i2c_xfer,
    445	.functionality = functionality,
    446};
    447
    448static const struct i2c_adapter cx231xx_adap_template = {
    449	.owner = THIS_MODULE,
    450	.name = "cx231xx",
    451	.algo = &cx231xx_algo,
    452};
    453
    454/* ----------------------------------------------------------- */
    455
    456/*
    457 * i2c_devs
    458 * incomplete list of known devices
    459 */
    460static const char *i2c_devs[128] = {
    461	[0x20 >> 1] = "demod",
    462	[0x60 >> 1] = "colibri",
    463	[0x88 >> 1] = "hammerhead",
    464	[0x8e >> 1] = "CIR",
    465	[0x32 >> 1] = "GeminiIII",
    466	[0x02 >> 1] = "Aquarius",
    467	[0xa0 >> 1] = "eeprom",
    468	[0xc0 >> 1] = "tuner",
    469	[0xc2 >> 1] = "tuner",
    470};
    471
    472/*
    473 * cx231xx_do_i2c_scan()
    474 * check i2c address range for devices
    475 */
    476void cx231xx_do_i2c_scan(struct cx231xx *dev, int i2c_port)
    477{
    478	unsigned char buf;
    479	int i, rc;
    480	struct i2c_adapter *adap;
    481	struct i2c_msg msg = {
    482		.flags = I2C_M_RD,
    483		.len = 1,
    484		.buf = &buf,
    485	};
    486
    487	if (!i2c_scan)
    488		return;
    489
    490	/* Don't generate I2C errors during scan */
    491	dev->i2c_scan_running = true;
    492	adap = cx231xx_get_i2c_adap(dev, i2c_port);
    493
    494	for (i = 0; i < 128; i++) {
    495		msg.addr = i;
    496		rc = i2c_transfer(adap, &msg, 1);
    497
    498		if (rc < 0)
    499			continue;
    500		dev_info(dev->dev,
    501			 "i2c scan: found device @ port %d addr 0x%x  [%s]\n",
    502			 i2c_port,
    503			 i << 1,
    504			 i2c_devs[i] ? i2c_devs[i] : "???");
    505	}
    506
    507	dev->i2c_scan_running = false;
    508}
    509
    510/*
    511 * cx231xx_i2c_register()
    512 * register i2c bus
    513 */
    514int cx231xx_i2c_register(struct cx231xx_i2c *bus)
    515{
    516	struct cx231xx *dev = bus->dev;
    517
    518	if (!dev->cx231xx_send_usb_command)
    519		return -EINVAL;
    520
    521	bus->i2c_adap = cx231xx_adap_template;
    522	bus->i2c_adap.dev.parent = dev->dev;
    523
    524	snprintf(bus->i2c_adap.name, sizeof(bus->i2c_adap.name), "%s-%d", bus->dev->name, bus->nr);
    525
    526	bus->i2c_adap.algo_data = bus;
    527	i2c_set_adapdata(&bus->i2c_adap, &dev->v4l2_dev);
    528	bus->i2c_rc = i2c_add_adapter(&bus->i2c_adap);
    529
    530	if (0 != bus->i2c_rc)
    531		dev_warn(dev->dev,
    532			 "i2c bus %d register FAILED\n", bus->nr);
    533
    534	return bus->i2c_rc;
    535}
    536
    537/*
    538 * cx231xx_i2c_unregister()
    539 * unregister i2c_bus
    540 */
    541void cx231xx_i2c_unregister(struct cx231xx_i2c *bus)
    542{
    543	if (!bus->i2c_rc)
    544		i2c_del_adapter(&bus->i2c_adap);
    545}
    546
    547/*
    548 * cx231xx_i2c_mux_select()
    549 * switch i2c master number 1 between port1 and port3
    550 */
    551static int cx231xx_i2c_mux_select(struct i2c_mux_core *muxc, u32 chan_id)
    552{
    553	struct cx231xx *dev = i2c_mux_priv(muxc);
    554
    555	return cx231xx_enable_i2c_port_3(dev, chan_id);
    556}
    557
    558int cx231xx_i2c_mux_create(struct cx231xx *dev)
    559{
    560	dev->muxc = i2c_mux_alloc(&dev->i2c_bus[1].i2c_adap, dev->dev, 2, 0, 0,
    561				  cx231xx_i2c_mux_select, NULL);
    562	if (!dev->muxc)
    563		return -ENOMEM;
    564	dev->muxc->priv = dev;
    565	return 0;
    566}
    567
    568int cx231xx_i2c_mux_register(struct cx231xx *dev, int mux_no)
    569{
    570	return i2c_mux_add_adapter(dev->muxc,
    571				   0,
    572				   mux_no /* chan_id */,
    573				   0 /* class */);
    574}
    575
    576void cx231xx_i2c_mux_unregister(struct cx231xx *dev)
    577{
    578	i2c_mux_del_adapters(dev->muxc);
    579}
    580
    581struct i2c_adapter *cx231xx_get_i2c_adap(struct cx231xx *dev, int i2c_port)
    582{
    583	switch (i2c_port) {
    584	case I2C_0:
    585		return &dev->i2c_bus[0].i2c_adap;
    586	case I2C_1:
    587		return &dev->i2c_bus[1].i2c_adap;
    588	case I2C_2:
    589		return &dev->i2c_bus[2].i2c_adap;
    590	case I2C_1_MUX_1:
    591		return dev->muxc->adapter[0];
    592	case I2C_1_MUX_3:
    593		return dev->muxc->adapter[1];
    594	default:
    595		BUG();
    596	}
    597}
    598EXPORT_SYMBOL_GPL(cx231xx_get_i2c_adap);