I am working on an embedded linux kernel project for a 83xx powerpc using a 2.6.24 kernel and having some issues extracting information out of the open firmware DTS file for a i2c device driver.
For a memory mapped device I would add normally add entry in the DTS file that specified the address / IRQ parameters etc. Then in the associated kernel probe function I would call irq_of_parse_and_map ( ofdev->node, 0 ) to access these details as the probe call is passed struct of_device *ofdev and then pass the parameter returned to request_irq ().
However in the i2c equivalent the function I am (possibly incorrectly) calling the request_irq() function from device_detect() which is not passed the ofdev pointer.
By hard coding the IRQ number and flags I can register and uses the IRQ but I think that I should be able to pull this information in directly from the DTS file. Anybody got any pointers as to what I am missing?
Thanks
DTS file snipit
i2c@3000 {
#address-cells = <1>;
#size-cells = <0>;
device_type = "i2c";
compatible = "fsl-i2c";
reg = <3000 100>;
interrupts = <e 8>;
interrupt-parent = < &ipic >;
dfsrr;
io_0@20 {
device_type = "io_expander";
compatible = "pca9534";
reg = <20>;
interrupts = <13 8>;
interrupt-parent = < &ipic >;
};
io_1@21 {
device_type = "io_expander";
compatible = "pca9534";
reg = <21>;
};
Below is a snipit of my code which was based on kernel/drivers/i2c/chips/pca9539.c
static struct i2c_driver pca9534_driver = {
.driver = {
.name = "pca9534",
},
.attach_adapter = pca9534_attach_adapter,
.detach_client = pca9534_detach_client,
};
static int pca9534_attach_adapter(struct i2c_adapter *adapter)
{
return i2c_probe(adapter, &addr_data, pca9534_detect);
}
static irqreturn_t io_0_irq ( int irq, void * reg )
{
printk(KERN_ERR "[io_0_irq]\n");
return IRQ_HANDLED;
}
static int pca9534_detect(struct i2c_adapter *adapter, int address, int kind)
{
struct i2c_client *new_client;
struct pca9534_data *data;
int err = 0;
int irq;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
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 pca9534_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 = &pca9534_driver;
new_client->flags = 0;
if (kind < 0) {
/* Detection: the pca9534 only has 4 registers (0-3).
A read of 3 should succeed, but a read of 4 should fail. */
if ((i2c_smbus_read_byte_data(new_client, 3) < 0) ||
(i2c_smbus_read_byte_data(new_client, 4) >= 0))
goto exit_kfree;
}
strlcpy(new_client->name, "pca9534", I2C_NAME_SIZE);
/* Tell the I2C layer a new client has arrived */
if ((err = i2c_attach_client(new_client)))
goto exit_kfree;
/* Register sysfs hooks */
err = sysfs_create_group(&new_client->dev.kobj,
&pca9534_defattr_group);
/* If i2c address matches IQ_0 install IRQ (several other IO expanders that don't have IRQs */
if (0x20 == address) {
/*
This is what I would like to use but don't know how to get to ofdev from here
irq = irq_of_parse_and_map ( ofdev->node, 0 ) ;
*/
/* Hard coded request for IRQ 0x13, 2=falling edge triggered */
irq = request_irq ( 0x13, io_0_irq, 2, "io_0_irq", NULL ) ;
if ( irq ) {
printk(KERN_ERR "[%s] ERROR %d Installing IRQ\n", __func__ , irq ) ;
} else {
printk(KERN_ERR "[%s] : IO_0 irq installed\n", __func__ ) ;
}
}