i2c driver develpment with diolan DLN-2 / ACPI?

Daniel Baluta daniel.baluta at gmail.com
Wed Apr 27 07:51:47 EDT 2016


On Wed, Apr 27, 2016 at 2:36 PM, Martin Kepplinger <martink at posteo.de> wrote:
> Hi roberta or anyone who uses a diolan i2c/spi bridge device,
>
> I try to do get the kernel driver for the connected chip loaded, but I'm
> having some trouble getting it right.
>
> Cables are connected to the device (i2c), and the (mainline) kernel
> driver for the diolan DLN-2 device is compiled and loaded on plugin.
>
> I don't use any of their (userspace) software.
>
> Now I get a new i2c bus and can manually instanciate my driver
>
> root at laptop:/sys/bus/i2c/devices/i2c-7# echo mma8452 0x1c > new_device
>
> and the driver loads. (Now for development, later maybe for merging) I
> added acpi support, I guess I'd need it, but ACPI_HANDLE(&client->dev)
> isn't true (during probe) hence we don't continue. I append my
> adding-acpi-patch below.
>
> How do you do it?
>
> Do *you* manually instantiate your i2c-driver during development with
> your diolan device or should it somehow even get loaded automatically?
>

Hi Martin,

Please also use the following two patches:

https://lkml.org/lkml/2014/12/16/290
https://lkml.org/lkml/2014/12/16/289

How does your setup looks like?

> thanks so much for any help,
>
>                      martin
>
>
> --- a/drivers/iio/accel/mma8452.c
> +++ b/drivers/iio/accel/mma8452.c
> @@ -33,6 +33,7 @@
>  #include <linux/of_device.h>
>  #include <linux/of_irq.h>
>  #include <linux/pm_runtime.h>
> +#include <linux/acpi.h>
>
>  #define MMA8452_STATUS                         0x00
>  #define  MMA8452_STATUS_DRDY                   (BIT(2) | BIT(1) | BIT(0))
> @@ -1434,6 +1435,19 @@ static const struct of_device_id mma8452_dt_ids[] = {
>  };
>  MODULE_DEVICE_TABLE(of, mma8452_dt_ids);
>
> +static const char *mma8452_match_acpi_device(struct device *dev, int *data)
> +{
> +        const struct acpi_device_id *id;
> +
> +        id = acpi_match_device(dev->driver->acpi_match_table, dev);
> +        if (!id)
> +                return NULL;
> +
> +        *data = (int)id->driver_data;
> +
> +        return dev_name(dev);
> +}
> +
>  static int mma8452_probe(struct i2c_client *client,
>                          const struct i2c_device_id *id)
>  {
> @@ -1441,21 +1455,35 @@ static int mma8452_probe(struct i2c_client *client,
>         struct iio_dev *indio_dev;
>         int ret;
>         const struct of_device_id *match;
> +       const char *name = NULL;
> +       int dev_id = 0;
>
> -       match = of_match_device(mma8452_dt_ids, &client->dev);
> -       if (!match) {
> -               dev_err(&client->dev, "unknown device model\n");
> -               return -ENODEV;
> -       }
> +pr_info("mma probe running!!\n");
>
>         indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
>         if (!indio_dev)
>                 return -ENOMEM;
>
>         data = iio_priv(indio_dev);
> +       i2c_set_clientdata(client, indio_dev);
>         data->client = client;
> +
> +       match = of_match_device(mma8452_dt_ids, &client->dev);
> +       if (match) {
> +               if (id)
> +                       name = id->name;
> +               data->chip_info = match->data;
> +       } else if (ACPI_HANDLE(&client->dev)) {
> +               name = mma8452_match_acpi_device(&client->dev, &dev_id);
> +               pr_info("mma acpi ok. found id %d\n", dev_id);
> +               /* TODO chip_info setting*/
> +               data->chip_info = &mma_chip_info_table[dev_id];
> +       } else {
> +               dev_err(&client->dev, "unknown device model\n");
> +               return -ENODEV;
> +       }
> +
>         mutex_init(&data->lock);
> -       data->chip_info = match->data;
>
>         ret = i2c_smbus_read_byte_data(client, MMA8452_WHO_AM_I);
>         if (ret < 0)
> @@ -1475,11 +1503,10 @@ static int mma8452_probe(struct i2c_client *client,
>         }
>
>         dev_info(&client->dev, "registering %s accelerometer; ID 0x%x\n",
> -                match->compatible, data->chip_info->chip_id);
> +                name, data->chip_info->chip_id);
>
> -       i2c_set_clientdata(client, indio_dev);
>         indio_dev->info = &mma8452_info;
> -       indio_dev->name = id->name;
> +       indio_dev->name = name;
>         indio_dev->dev.parent = &client->dev;
>         indio_dev->modes = INDIO_DIRECT_MODE;
>         indio_dev->channels = data->chip_info->channels;
> @@ -1669,6 +1696,17 @@ static const struct dev_pm_ops mma8452_pm_ops = {
>                            mma8452_runtime_resume, NULL)
>  };
>
> +static const struct acpi_device_id mma8452_acpi_match[] = {
> +       { "MMA8451", mma8451 },
> +       { "MMA8452", mma8452 },
> +       { "MMA8453", mma8453 },
> +       { "MMA8652", mma8652 },
> +       { "MMA8653", mma8653 },
> +       { "FXLS8471", fxls8471 },
> +       { },
> +};
> +MODULE_DEVICE_TABLE(acpi, mma8452_acpi_match);
> +
>  static const struct i2c_device_id mma8452_id[] = {
>         { "mma8451", mma8451 },
>         { "mma8452", mma8452 },
> @@ -1684,6 +1722,7 @@ static struct i2c_driver mma8452_driver = {
>         .driver = {
>                 .name   = "mma8452",
>                 .of_match_table = of_match_ptr(mma8452_dt_ids),
> +               .acpi_match_table = ACPI_PTR(mma8452_acpi_match),
>                 .pm     = &mma8452_pm_ops,
>         },
>         .probe = mma8452_probe,

This looks fine to me.

Daniel.



More information about the Kernelnewbies mailing list