Skip to content

Commit

Permalink
platform/x86: i2c-multi-instantiate: Count I2cSerialBus() resources
Browse files Browse the repository at this point in the history
Instead of relying on hard coded and thus expected number of I2C clients,
count the real amount provided by firmware.

This allows to support non-fixed amount of the slaves.

Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
  • Loading branch information
Andy Shevchenko committed Dec 3, 2018
1 parent 0d5102f commit a729656
Showing 1 changed file with 37 additions and 4 deletions.
41 changes: 37 additions & 4 deletions drivers/platform/x86/i2c-multi-instantiate.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/types.h>

struct i2c_inst_data {
const char *type;
Expand All @@ -23,6 +24,31 @@ struct i2c_multi_inst_data {
struct i2c_client *clients[0];
};

static int i2c_multi_inst_count(struct acpi_resource *ares, void *data)
{
struct acpi_resource_i2c_serialbus *sb;
int *count = data;

if (i2c_acpi_get_i2c_resource(ares, &sb))
*count = *count + 1;

return 1;
}

static int i2c_multi_inst_count_resources(struct acpi_device *adev)
{
LIST_HEAD(r);
int count = 0;
int ret;

ret = acpi_dev_get_resources(adev, &r, i2c_multi_inst_count, &count);
if (ret < 0)
return ret;

acpi_dev_free_resource_list(&r);
return count;
}

static int i2c_multi_inst_probe(struct platform_device *pdev)
{
struct i2c_multi_inst_data *multi;
Expand All @@ -44,17 +70,19 @@ static int i2c_multi_inst_probe(struct platform_device *pdev)
adev = ACPI_COMPANION(dev);

/* Count number of clients to instantiate */
for (i = 0; inst_data[i].type; i++) {}
ret = i2c_multi_inst_count_resources(adev);
if (ret < 0)
return ret;

multi = devm_kmalloc(dev,
offsetof(struct i2c_multi_inst_data, clients[i]),
offsetof(struct i2c_multi_inst_data, clients[ret]),
GFP_KERNEL);
if (!multi)
return -ENOMEM;

multi->num_clients = i;
multi->num_clients = ret;

for (i = 0; i < multi->num_clients; i++) {
for (i = 0; i < multi->num_clients && inst_data[i].type; i++) {
memset(&board_info, 0, sizeof(board_info));
strlcpy(board_info.type, inst_data[i].type, I2C_NAME_SIZE);
snprintf(name, sizeof(name), "%s-%s", match->id,
Expand All @@ -79,6 +107,11 @@ static int i2c_multi_inst_probe(struct platform_device *pdev)
goto error;
}
}
if (i < multi->num_clients) {
dev_err(dev, "Error finding driver, idx %d\n", i);
ret = -ENODEV;
goto error;
}

platform_set_drvdata(pdev, multi);
return 0;
Expand Down

0 comments on commit a729656

Please sign in to comment.