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

Reply via email to