brintos

brintos / linux-shallow public Read only

0
0
Text · 3.4 KiB · ac7f76d Raw
142 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * cx88-vp3054-i2c.c -- support for the secondary I2C bus of the4 *			DNTV Live! DVB-T Pro (VP-3054), wired as:5 *			GPIO[0] -> SCL, GPIO[1] -> SDA6 *7 * (c) 2005 Chris Pascoe <c.pascoe@itee.uq.edu.au>8 */9 10#include "cx88.h"11#include "cx88-vp3054-i2c.h"12 13#include <linux/module.h>14#include <linux/slab.h>15#include <linux/init.h>16#include <linux/io.h>17 18MODULE_DESCRIPTION("driver for cx2388x VP3054 design");19MODULE_AUTHOR("Chris Pascoe <c.pascoe@itee.uq.edu.au>");20MODULE_LICENSE("GPL");21 22/* ----------------------------------------------------------------------- */23 24static void vp3054_bit_setscl(void *data, int state)25{26	struct cx8802_dev *dev = data;27	struct cx88_core *core = dev->core;28	struct vp3054_i2c_state *vp3054_i2c = dev->vp3054;29 30	if (state) {31		vp3054_i2c->state |=  0x0001;	/* SCL high */32		vp3054_i2c->state &= ~0x0100;	/* external pullup */33	} else {34		vp3054_i2c->state &= ~0x0001;	/* SCL low */35		vp3054_i2c->state |=  0x0100;	/* drive pin */36	}37	cx_write(MO_GP0_IO, 0x010000 | vp3054_i2c->state);38	cx_read(MO_GP0_IO);39}40 41static void vp3054_bit_setsda(void *data, int state)42{43	struct cx8802_dev *dev = data;44	struct cx88_core *core = dev->core;45	struct vp3054_i2c_state *vp3054_i2c = dev->vp3054;46 47	if (state) {48		vp3054_i2c->state |=  0x0002;	/* SDA high */49		vp3054_i2c->state &= ~0x0200;	/* tristate pin */50	} else {51		vp3054_i2c->state &= ~0x0002;	/* SDA low */52		vp3054_i2c->state |=  0x0200;	/* drive pin */53	}54	cx_write(MO_GP0_IO, 0x020000 | vp3054_i2c->state);55	cx_read(MO_GP0_IO);56}57 58static int vp3054_bit_getscl(void *data)59{60	struct cx8802_dev *dev = data;61	struct cx88_core *core = dev->core;62	u32 state;63 64	state = cx_read(MO_GP0_IO);65	return (state & 0x01) ? 1 : 0;66}67 68static int vp3054_bit_getsda(void *data)69{70	struct cx8802_dev *dev = data;71	struct cx88_core *core = dev->core;72	u32 state;73 74	state = cx_read(MO_GP0_IO);75	return (state & 0x02) ? 1 : 0;76}77 78/* ----------------------------------------------------------------------- */79 80static const struct i2c_algo_bit_data vp3054_i2c_algo_template = {81	.setsda  = vp3054_bit_setsda,82	.setscl  = vp3054_bit_setscl,83	.getsda  = vp3054_bit_getsda,84	.getscl  = vp3054_bit_getscl,85	.udelay  = 16,86	.timeout = 200,87};88 89/* ----------------------------------------------------------------------- */90 91int vp3054_i2c_probe(struct cx8802_dev *dev)92{93	struct cx88_core *core = dev->core;94	struct vp3054_i2c_state *vp3054_i2c;95	int rc;96 97	if (core->boardnr != CX88_BOARD_DNTV_LIVE_DVB_T_PRO)98		return 0;99 100	vp3054_i2c = kzalloc(sizeof(*vp3054_i2c), GFP_KERNEL);101	if (!vp3054_i2c)102		return -ENOMEM;103	dev->vp3054 = vp3054_i2c;104 105	vp3054_i2c->algo = vp3054_i2c_algo_template;106 107	vp3054_i2c->adap.dev.parent = &dev->pci->dev;108	strscpy(vp3054_i2c->adap.name, core->name,109		sizeof(vp3054_i2c->adap.name));110	vp3054_i2c->adap.owner = THIS_MODULE;111	vp3054_i2c->algo.data = dev;112	i2c_set_adapdata(&vp3054_i2c->adap, dev);113	vp3054_i2c->adap.algo_data = &vp3054_i2c->algo;114 115	vp3054_bit_setscl(dev, 1);116	vp3054_bit_setsda(dev, 1);117 118	rc = i2c_bit_add_bus(&vp3054_i2c->adap);119	if (rc != 0) {120		pr_err("vp3054_i2c register FAILED\n");121 122		kfree(dev->vp3054);123		dev->vp3054 = NULL;124	}125 126	return rc;127}128EXPORT_SYMBOL(vp3054_i2c_probe);129 130void vp3054_i2c_remove(struct cx8802_dev *dev)131{132	struct vp3054_i2c_state *vp3054_i2c = dev->vp3054;133 134	if (!vp3054_i2c ||135	    dev->core->boardnr != CX88_BOARD_DNTV_LIVE_DVB_T_PRO)136		return;137 138	i2c_del_adapter(&vp3054_i2c->adap);139	kfree(vp3054_i2c);140}141EXPORT_SYMBOL(vp3054_i2c_remove);142