Your NACK could be due to having the wrong slave address. The 7-bit slave address is shown many different ways. Sometimes it's shown left-aligned so that you can OR the R/W bit into the address. Other times it's right aligned. Also, the driver itself sometimes expects it one way or another! (Sorry, I forget off the top of my head which way around the Davinci driver wants it.) I recommend double-checking.
Brad ________________________________ From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] On Behalf Of Gabriele Filosofi Sent: Monday, September 29, 2008 1:10 PM To: [email protected] Subject: I2C NAK condition prevents device to be registered 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
