views:

242

answers:

0

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__ ) ;
        }
    }