i2c driver develpment with diolan DLN-2 / ACPI?
Martin Kepplinger
martink at posteo.de
Sat Apr 30 11:10:30 EDT 2016
Am 2016-04-27 um 13:51 schrieb Daniel Baluta:
> 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?
>
Those patches don't apply anymore, also because of API changes. I save
them but I'll ignore the ACPI problem for now. Oh well, for development
only, I skip it and go ahead and try to write and read registers.
Different problem:
i2c_smbus_read_byte_data always returns with "Protocol Error".
DLN-2 jumpers are correct. Is there anything special to consider, using
the DLN-2, regardless of which chip you are talking to?
thanks
martin
>> 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.
>
> _______________________________________________
> Kernelnewbies mailing list
> Kernelnewbies at kernelnewbies.org
> http://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies
>
More information about the Kernelnewbies
mailing list