2 * tw68 code to handle the i2c interface.
4 * Much of this code is derived from the bt87x driver. The original
5 * work was by Gerd Knorr; more recently the code was enhanced by Mauro
6 * Carvalho Chehab. Their work is gratefully acknowledged. Full credit
7 * goes to them - any problems within this code are mine.
9 * Copyright (C) 2009 William M. Brack <wbrack@mmm.com.hk>
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License along
22 * with this program; if not, write to the Free Software Foundation, Inc.,
23 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26 #include <linux/init.h>
27 #include <linux/list.h>
28 #include <linux/module.h>
29 #include <linux/kernel.h>
30 #include <linux/slab.h>
31 #include <linux/delay.h>
34 #include <media/v4l2-common.h>
35 #include <linux/i2c-algo-bit.h>
37 /*----------------------------------------------------------------*/
39 static unsigned int i2c_debug
;
40 module_param(i2c_debug
, int, 0644);
41 MODULE_PARM_DESC(i2c_debug
, "enable debug messages [i2c]");
44 static unsigned int i2c_scan
;
45 module_param(i2c_scan
, int, 0444);
46 MODULE_PARM_DESC(i2c_scan
, "scan i2c bus at insmod time");
49 #define d1printk if (1 == i2c_debug) printk
51 #define I2C_CLOCK 0xa6 /* 99.4 kHz */
53 /*----------------------------------------------------------------------*/
54 /* Although the TW68xx i2c controller has a "hardware" mode, where all of
55 * the low-level i2c/smbbus is handled by the chip, it appears that mode
56 * is not suitable for linux i2c handling routines because extended "bursts"
57 * of data (sequences of bytes without intervening START/STOP bits) are
58 * not possible. Instead, we put the chip into "software" mode, and handle
59 * the i2c bus at a low level. To accomplish this, we use the routines
60 * from the i2c modules.
62 * Because the particular boards which I had for testing did not have any
63 * devices attached to the i2c bus, I have been unable to test these
67 /*----------------------------------------------------------------------*/
68 /* I2C functions - "bit-banging" adapter (software i2c) */
71 * Handles "toggling" the i2c clock bit
73 static void tw68_bit_setscl(void *data
, int state
)
75 struct tw68_dev
*dev
= data
;
77 tw_andorb(TW68_SBUSC
, (state
? 1 : 0) << TW68_SSCLK
, TW68_SSCLK_B
);
81 * Handles "toggling" the i2c data bit
83 static void tw68_bit_setsda(void *data
, int state
)
85 struct tw68_dev
*dev
= data
;
87 tw_andorb(TW68_SBUSC
, (state
? 1 : 0) << TW68_SSDAT
, TW68_SSDAT_B
);
92 * Returns the current state of the clock bit
94 static int tw68_bit_getscl(void *data
)
96 struct tw68_dev
*dev
= data
;
98 return (tw_readb(TW68_SBUSC
) & TW68_SSCLK_B
) ? 1 : 0;
103 * Returns the current state of the data bit
105 static int tw68_bit_getsda(void *data
)
107 struct tw68_dev
*dev
= data
;
109 return (tw_readb(TW68_SBUSC
) & TW68_SSDAT_B
) ? 1 : 0;
112 static struct i2c_algo_bit_data __devinitdata tw68_i2c_algo_bit_template
= {
113 .setsda
= tw68_bit_setsda
,
114 .setscl
= tw68_bit_setscl
,
115 .getsda
= tw68_bit_getsda
,
116 .getscl
= tw68_bit_getscl
,
121 static struct i2c_client tw68_client_template
= {
122 .name
= "tw68 internal",
125 /*----------------------------------------------------------------*/
127 static int attach_inform(struct i2c_client
*client
)
129 /* struct tw68_dev *dev = client->adapter->algo_data; */
131 d1printk("%s i2c attach [addr=0x%x,client=%s]\n",
132 client
->driver
->driver
.name
, client
->addr
, client
->name
);
134 switch (client
->addr
) {
135 /* No info yet on what addresses to expect */
141 static struct i2c_adapter tw68_adap_sw_template
= {
142 .owner
= THIS_MODULE
,
144 .client_register
= attach_inform
,
147 static int tw68_i2c_eeprom(struct tw68_dev
*dev
, unsigned char *eedata
,
153 dev
->i2c_client
.addr
= 0xa0 >> 1;
156 err
= i2c_master_send(&dev
->i2c_client
, &buf
, 1);
158 printk(KERN_INFO
"%s: Huh, no eeprom present (err = %d)?\n",
162 err
= i2c_master_recv(&dev
->i2c_client
, eedata
, len
);
164 printk(KERN_WARNING
"%s: i2c eeprom read error (err=%d)\n",
169 for (i
= 0; i
< len
; i
++) {
171 printk(KERN_INFO
"%s: i2c eeprom %02x:",
173 printk(KERN_INFO
" %02x", eedata
[i
]);
181 static char *i2c_devs
[128] = {
182 [0xa0 >> 1] = "eeprom",
185 static void do_i2c_scan(char *name
, struct i2c_client
*c
)
190 for (i
= 0; i
< ARRAY_SIZE(i2c_devs
); i
++) {
192 rc
= i2c_master_recv(c
, &buf
, 1);
195 printk(KERN_INFO
"%s: i2c scan: found device "
196 "@ 0x%x [%s]\n", name
, i
<< 1,
197 i2c_devs
[i
] ? i2c_devs
[i
] : "???");
202 int __devinit
tw68_i2c_register(struct tw68_dev
*dev
)
206 printk(KERN_DEBUG
"%s: Registering i2c module\n", __func__
);
207 tw_writeb(TW68_I2C_RST
, 1); /* reset the i2c module */
209 memcpy(&dev
->i2c_client
, &tw68_client_template
,
210 sizeof(tw68_client_template
));
212 memcpy(&dev
->i2c_adap
, &tw68_adap_sw_template
,
213 sizeof(tw68_adap_sw_template
));
214 dev
->i2c_adap
.algo_data
= &dev
->i2c_algo
;
215 dev
->i2c_adap
.dev
.parent
= &dev
->pci
->dev
;
217 memcpy(&dev
->i2c_algo
, &tw68_i2c_algo_bit_template
,
218 sizeof(tw68_i2c_algo_bit_template
));
219 dev
->i2c_algo
.data
= dev
;
220 /* TODO - may want to set better name (see bttv code) */
222 i2c_set_adapdata(&dev
->i2c_adap
, &dev
->v4l2_dev
);
223 dev
->i2c_client
.adapter
= &dev
->i2c_adap
;
225 /* Assure chip is in "software" mode */
226 tw_writel(TW68_SBUSC
, TW68_SSDAT
| TW68_SSCLK
);
227 tw68_bit_setscl(dev
, 1);
228 tw68_bit_setsda(dev
, 1);
230 rc
= i2c_bit_add_bus(&dev
->i2c_adap
);
232 tw68_i2c_eeprom(dev
, dev
->eedata
, sizeof(dev
->eedata
));
235 do_i2c_scan(dev
->name
, &dev
->i2c_client
);
241 int tw68_i2c_unregister(struct tw68_dev
*dev
)
243 i2c_del_adapter(&dev
->i2c_adap
);