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