Hi,
I've written a loadable module to drive a CCDC device (ov7670) on the I2C bus.
But when I "insmod" it:
[EMAIL PROTECTED]:~# insmod
/lib/modules/2.6.25-rc1-davinci1/kernel/drivers/i2c/chips/ov7670.ko
<7>i2c-core: driver [ov7670] registered
<7>i2c-adapter i2c-1: found normal entry for adapter 1, addr 0x21
<7>i2c-adapter i2c-1: master_xfer[0] W, addr=0x21, len=0
<7>i2c_davinci i2c_davinci.1: i2c_davinci_xfer: msgs: 1
<7>i2c_davinci i2c_davinci.1: i2c_davinci_isr: stat=0x5
<3>i2c_davinci i2c_davinci.1: TDR IRQ while no data to send
i2c_davinci i2c_davinci.1: TDR IRQ while no data to send
<7>i2c_davinci i2c_davinci.1: i2c_davinci_isr: stat=0x2
<7>i2c_davinci i2c_davinci.1: i2c_davinci_isr: stat=0x6
<7>i2c_davinci i2c_davinci.1: i2c_davinci_xfer ret: -121
This prevents the device from being properly registered, infact I don't find
the device file in /sys/bus/i2c/devices.
I've found the I2C bus transaction fails for a NAK condition in function
(drivers/i2c/busses/i2c-davinci.c)
static int i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg,
int stop)
{
...
if (dev->cmd_err & DAVINCI_I2C_STR_NACK) {
if (msg->flags & I2C_M_IGNORE_NAK)
return msg->len;
return -EREMOTEIO; //exit point (EREMOTEIO
= 121)
}
return -EIO;
}
Looking the code above it seems that having set the I2C_M_IGNORE_NAK flag could
solve the problem.
How can I do it?
My driver is:
static int ov7670_attach_adapter(struct i2c_adapter *adapter)
{
return i2c_probe(adapter, &addr_data, ov7670_detect);
}
/* This function is called by i2c_probe */
static int ov7670_detect(struct i2c_adapter *adapter, int address, int kind)
{
//struct i2c_client *new_client;
struct ov7670_data *data;
int err = 0;
const char *client_name = "ov7670";
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE))
goto exit;
/* OK. For now, we presume we have a valid client. We now create the
client structure, even though we cannot fill it completely yet. */
if (!(data = kzalloc(sizeof(struct ov7670_data), GFP_KERNEL))) {
err = -ENOMEM;
goto exit;
}
new_client = &data->client;
i2c_set_clientdata(new_client, data);
new_client->addr = address;
new_client->adapter = adapter;
new_client->driver = &ov7670_driver;
new_client->flags = 0;
/*
Note: I've tryed with
new_client->flags = I2C_M_IGNORE_NAK;
without any results.
*/
/* Fill in the remaining client fields and put it into the global list
*/
strlcpy(new_client->name, client_name, I2C_NAME_SIZE);
/* Tell the I2C layer a new client has arrived */
if ((err = i2c_attach_client(new_client)))
goto exit_free;
/* Initialize the OV7670 chip */
ov7670_init_client(new_client);
/* Register sysfs hooks */
err = sysfs_create_group(&new_client->dev.kobj, &ov7670_attr_group);
if (err)
goto exit_detach;
return 0;
exit_detach:
i2c_detach_client(new_client);
exit_free:
kfree(data);
exit:
return err;
}
static int ov7670_detach_client(struct i2c_client *client)
{
int err;
sysfs_remove_group(&client->dev.kobj, &ov7670_attr_group);
if ((err = i2c_detach_client(client)))
return err;
kfree(i2c_get_clientdata(client));
return 0;
}
/* Called when we have found a new OV7670 */
static void ov7670_init_client(struct i2c_client *client)
{
struct ov7670_data *data = i2c_get_clientdata(client);
data->fmt = &ov7670_formats[0];
data->sat = 128;
data->write = -EAGAIN;
}
static int __init ov7670_init(void)
{
int ret = 0;
if (i2c_add_driver(&ov7670_driver)) {
printk("ov7670 i2c: Driver registration failed, \
module not inserted.\n");
ret = -ENODEV;
return ret;
}
printk("OV7670 I2C version %s (%s)\n",
OV7670_VERSION, OV7670_DATE);
return ret;
}
static void __exit ov7670_exit(void)
{
i2c_del_driver(&ov7670_driver);
}
module_init(ov7670_init);
module_exit(ov7670_exit);
Thanks a lot,
Gabriele
_______________________________________________
Davinci-linux-open-source mailing list
[email protected]
http://linux.davincidsp.com/mailman/listinfo/davinci-linux-open-source