[PATCH 19 0/5] Version 18, series to add device tree naming to i2c - Kernel

This is a discussion on [PATCH 19 0/5] Version 18, series to add device tree naming to i2c - Kernel ; Updated to reflect comments in: http://lkml.org/lkml/2008/1/11/272 Since copying i2c-mpc.c to maintain support for the ppc architecture seems to be an issue; instead rework i2c-mpc.c to use CONFIG_PPC_MERGE #ifdefs to support both the ppc and powerpc architecture. When ppc is deleted ...

+ Reply to Thread
Results 1 to 11 of 11

Thread: [PATCH 19 0/5] Version 18, series to add device tree naming to i2c

  1. [PATCH 19 0/5] Version 18, series to add device tree naming to i2c

    Updated to reflect comments in:
    http://lkml.org/lkml/2008/1/11/272

    Since copying i2c-mpc.c to maintain support for the ppc architecture seems to be an issue; instead rework i2c-mpc.c to use CONFIG_PPC_MERGE #ifdefs to support both the ppc and powerpc architecture. When ppc is deleted in six months these #ifdefs will need to be removed.

    Another rework of the i2c for powerpc device tree patch. This version implements standard alias naming only on the powerpc platform and only for the device tree names. The old naming mechanism of i2c_client.name,driver_name is left in place and not changed for non-powerpc platforms. This patch is fully capable of dynamically loading the i2c modules. You can modprobe in the i2c-mpc driver and the i2c modules described in the device tree will be automatically loaded. Modules also work if compiled in.

    The follow on patch to module-init-tools is also needed since the i2c subsystem has never implemented dynamic loading.
    http://lkml.org/lkml/2007/12/17/493

    The following series implements standard linux module aliasing for i2c modules on arch=powerpc. It then converts the mpc i2c driver from being a platform driver to an open firmware one. I2C device names are picked up from the device tree. Module aliasing is used to translate from device tree names into to linux kernel names. Several i2c drivers are updated to use the new aliasing.

    --
    Jon Smirl
    jonsmirl@gmail.com
    --
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/

  2. [PATCH 19 1/5] Implement module aliasing for i2c to translate from device tree names

    This patch allows new style i2c chip drivers to have alias names using
    the official kernel aliasing system and MODULE_DEVICE_TABLE(). I've
    tested it on PowerPC and x86. This change is required for PowerPC
    device tree support.

    Signed-off-by: Jon Smirl
    ---

    drivers/hwmon/f75375s.c | 4 ++--
    drivers/i2c/chips/ds1682.c | 2 +-
    drivers/i2c/chips/menelaus.c | 2 +-
    drivers/i2c/chips/tps65010.c | 2 +-
    drivers/i2c/chips/tsl2550.c | 2 +-
    drivers/i2c/i2c-core.c | 24 +++++++++++++++++++++++-
    drivers/rtc/rtc-ds1307.c | 2 +-
    drivers/rtc/rtc-ds1374.c | 2 +-
    drivers/rtc/rtc-m41t80.c | 2 +-
    drivers/rtc/rtc-rs5c372.c | 2 +-
    include/linux/i2c.h | 5 ++---
    include/linux/mod_devicetable.h | 19 +++++++++++++++++++
    scripts/mod/file2alias.c | 14 ++++++++++++++
    13 files changed, 68 insertions(+), 14 deletions(-)


    diff --git a/drivers/hwmon/f75375s.c b/drivers/hwmon/f75375s.c
    index 6892f76..2247de6 100644
    --- a/drivers/hwmon/f75375s.c
    +++ b/drivers/hwmon/f75375s.c
    @@ -117,7 +117,7 @@ struct f75375_data {
    static int f75375_attach_adapter(struct i2c_adapter *adapter);
    static int f75375_detect(struct i2c_adapter *adapter, int address, int kind);
    static int f75375_detach_client(struct i2c_client *client);
    -static int f75375_probe(struct i2c_client *client);
    +static int f75375_probe(struct i2c_client *client, const struct i2c_device_id *id);
    static int f75375_remove(struct i2c_client *client);

    static struct i2c_driver f75375_legacy_driver = {
    @@ -628,7 +628,7 @@ static void f75375_init(struct i2c_client *client, struct f75375_data *data,

    }

    -static int f75375_probe(struct i2c_client *client)
    +static int f75375_probe(struct i2c_client *client, const struct i2c_device_id *id)
    {
    struct f75375_data *data = i2c_get_clientdata(client);
    struct f75375s_platform_data *f75375s_pdata = client->dev.platform_data;
    diff --git a/drivers/i2c/chips/ds1682.c b/drivers/i2c/chips/ds1682.c
    index 9e94542..93c0441 100644
    --- a/drivers/i2c/chips/ds1682.c
    +++ b/drivers/i2c/chips/ds1682.c
    @@ -200,7 +200,7 @@ static struct bin_attribute ds1682_eeprom_attr = {
    /*
    * Called when a ds1682 device is matched with this driver
    */
    -static int ds1682_probe(struct i2c_client *client)
    +static int ds1682_probe(struct i2c_client *client, const struct i2c_device_id *id)
    {
    int rc;

    diff --git a/drivers/i2c/chips/menelaus.c b/drivers/i2c/chips/menelaus.c
    index 2dea012..89ef9b6 100644
    --- a/drivers/i2c/chips/menelaus.c
    +++ b/drivers/i2c/chips/menelaus.c
    @@ -1149,7 +1149,7 @@ static inline void menelaus_rtc_init(struct menelaus_chip *m)

    static struct i2c_driver menelaus_i2c_driver;

    -static int menelaus_probe(struct i2c_client *client)
    +static int menelaus_probe(struct i2c_client *client, const struct i2c_device_id *id)
    {
    struct menelaus_chip *menelaus;
    int rev = 0, val;
    diff --git a/drivers/i2c/chips/tps65010.c b/drivers/i2c/chips/tps65010.c
    index e320994..6b13642 100644
    --- a/drivers/i2c/chips/tps65010.c
    +++ b/drivers/i2c/chips/tps65010.c
    @@ -465,7 +465,7 @@ static int __exit tps65010_remove(struct i2c_client *client)
    return 0;
    }

    -static int tps65010_probe(struct i2c_client *client)
    +static int tps65010_probe(struct i2c_client *client, const struct i2c_device_id *id)
    {
    struct tps65010 *tps;
    int status;
    diff --git a/drivers/i2c/chips/tsl2550.c b/drivers/i2c/chips/tsl2550.c
    index 3de4b19..27c553d 100644
    --- a/drivers/i2c/chips/tsl2550.c
    +++ b/drivers/i2c/chips/tsl2550.c
    @@ -364,7 +364,7 @@ static int tsl2550_init_client(struct i2c_client *client)
    */

    static struct i2c_driver tsl2550_driver;
    -static int __devinit tsl2550_probe(struct i2c_client *client)
    +static int __devinit tsl2550_probe(struct i2c_client *client, const struct i2c_device_id *id)
    {
    struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
    struct tsl2550_data *data;
    diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
    index b5e13e4..5f62230 100644
    --- a/drivers/i2c/i2c-core.c
    +++ b/drivers/i2c/i2c-core.c
    @@ -47,6 +47,19 @@ static DEFINE_IDR(i2c_adapter_idr);

    /* ------------------------------------------------------------------------- */

    +static const struct i2c_device_id *i2c_match_id(
    + const struct i2c_device_id *id, struct i2c_client *client)
    +{
    + /* only powerpc drivers implement the id_table,
    + * it is empty on other platforms */
    + while (id->name[0]) {
    + if (strcmp(client->name, id->name) == 0)
    + return id;
    + id++;
    + }
    + return NULL;
    +}
    +
    static int i2c_device_match(struct device *dev, struct device_driver *drv)
    {
    struct i2c_client *client = to_i2c_client(dev);
    @@ -58,6 +71,10 @@ static int i2c_device_match(struct device *dev, struct device_driver *drv)
    if (!is_newstyle_driver(driver))
    return 0;

    + /* match on an id table if there is one */
    + if (driver->id_table)
    + return i2c_match_id(driver->id_table, client) != NULL;
    +
    /* new style drivers use the same kind of driver matching policy
    * as platform devices or SPI: compare device and driver IDs.
    */
    @@ -89,12 +106,17 @@ static int i2c_device_probe(struct device *dev)
    {
    struct i2c_client *client = to_i2c_client(dev);
    struct i2c_driver *driver = to_i2c_driver(dev->driver);
    + const struct i2c_device_id *id = NULL;

    if (!driver->probe)
    return -ENODEV;
    client->driver = driver;
    dev_dbg(dev, "probe\n");
    - return driver->probe(client);
    +
    + if (driver->id_table)
    + id = i2c_match_id(driver->id_table, client);
    +
    + return driver->probe(client, id);
    }

    static int i2c_device_remove(struct device *dev)
    diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c
    index bc1c7fe..9b0eab9 100644
    --- a/drivers/rtc/rtc-ds1307.c
    +++ b/drivers/rtc/rtc-ds1307.c
    @@ -326,7 +326,7 @@ static struct bin_attribute nvram = {

    static struct i2c_driver ds1307_driver;

    -static int __devinit ds1307_probe(struct i2c_client *client)
    +static int __devinit ds1307_probe(struct i2c_client *client, const struct i2c_device_id *id)
    {
    struct ds1307 *ds1307;
    int err = -ENODEV;
    diff --git a/drivers/rtc/rtc-ds1374.c b/drivers/rtc/rtc-ds1374.c
    index 45bda18..dab6008 100644
    --- a/drivers/rtc/rtc-ds1374.c
    +++ b/drivers/rtc/rtc-ds1374.c
    @@ -355,7 +355,7 @@ static const struct rtc_class_ops ds1374_rtc_ops = {
    .ioctl = ds1374_ioctl,
    };

    -static int ds1374_probe(struct i2c_client *client)
    +static int ds1374_probe(struct i2c_client *client, const struct i2c_device_id *id)
    {
    struct ds1374 *ds1374;
    int ret;
    diff --git a/drivers/rtc/rtc-m41t80.c b/drivers/rtc/rtc-m41t80.c
    index 1cb33ca..457f2ca 100644
    --- a/drivers/rtc/rtc-m41t80.c
    +++ b/drivers/rtc/rtc-m41t80.c
    @@ -756,7 +756,7 @@ static struct notifier_block wdt_notifier = {
    *
    ************************************************** ***************************
    */
    -static int m41t80_probe(struct i2c_client *client)
    +static int m41t80_probe(struct i2c_client *client, const struct i2c_device_id *id)
    {
    int i, rc = 0;
    struct rtc_device *rtc = NULL;
    diff --git a/drivers/rtc/rtc-rs5c372.c b/drivers/rtc/rtc-rs5c372.c
    index 6b67b50..25de13b 100644
    --- a/drivers/rtc/rtc-rs5c372.c
    +++ b/drivers/rtc/rtc-rs5c372.c
    @@ -494,7 +494,7 @@ static void rs5c_sysfs_unregister(struct device *dev)

    static struct i2c_driver rs5c372_driver;

    -static int rs5c372_probe(struct i2c_client *client)
    +static int rs5c372_probe(struct i2c_client *client, const struct i2c_device_id *id)
    {
    int err = 0;
    struct rs5c372 *rs5c372;
    diff --git a/include/linux/i2c.h b/include/linux/i2c.h
    index a100c9f..0ca1a59 100644
    --- a/include/linux/i2c.h
    +++ b/include/linux/i2c.h
    @@ -126,7 +126,7 @@ struct i2c_driver {
    * With the driver model, device enumeration is NEVER done by drivers;
    * it's done by infrastructure. (NEW STYLE DRIVERS ONLY)
    */
    - int (*probe)(struct i2c_client *);
    + int (*probe)(struct i2c_client *, const struct i2c_device_id *id);
    int (*remove)(struct i2c_client *);

    /* driver model interfaces that don't relate to enumeration */
    @@ -141,11 +141,10 @@ struct i2c_driver {

    struct device_driver driver;
    struct list_head list;
    + struct i2c_device_id *id_table;
    };
    #define to_i2c_driver(d) container_of(d, struct i2c_driver, driver)

    -#define I2C_NAME_SIZE 20
    -
    /**
    * struct i2c_client - represent an I2C slave device
    * @flags: I2C_CLIENT_TEN indicates the device uses a ten bit chip address;
    diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h
    index e9fddb4..f3aef9f 100644
    --- a/include/linux/mod_devicetable.h
    +++ b/include/linux/mod_devicetable.h
    @@ -367,4 +367,23 @@ struct virtio_device_id {
    };
    #define VIRTIO_DEV_ANY_ID 0xffffffff

    +/* i2c */
    +
    +/* These defines are used to separate PowerPC open firmware
    + * drivers into their own namespace */
    +#define I2C_NAME_SIZE (16*3) /* Needs to be large enough to hold device tree style names */
    +#define I2C_MODULE_PREFIX "i2c:"
    +#ifdef CONFIG_OF
    +#define OF_I2C_PREFIX "OF,"
    +#define OF_I2C_ID(s,d) { OF_I2C_PREFIX s, (d) },
    +#else
    +#define OF_I2C_ID(s,d)
    +#endif
    +
    +struct i2c_device_id {
    + char name[I2C_NAME_SIZE];
    + kernel_ulong_t driver_data; /* Data private to the driver */
    +};
    +
    +
    #endif /* LINUX_MOD_DEVICETABLE_H */
    diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c
    index d802b5a..90a8d2c 100644
    --- a/scripts/mod/file2alias.c
    +++ b/scripts/mod/file2alias.c
    @@ -539,6 +539,16 @@ static int do_virtio_entry(const char *filename, struct virtio_device_id *id,
    return 1;
    }

    +/* Looks like: i2c:s */
    +static int do_i2c_entry(const char *filename, struct i2c_device_id *id,
    + char *alias)
    +{
    + char *tmp;
    + sprintf(alias, I2C_MODULE_PREFIX "%s", id->name);
    +
    + return 1;
    +}
    +
    /* Ignore any prefix, eg. v850 prepends _ */
    static inline int sym_is(const char *symbol, const char *name)
    {
    @@ -669,6 +679,10 @@ void handle_moddevtable(struct module *mod, struct elf_info *info,
    do_table(symval, sym->st_size,
    sizeof(struct virtio_device_id), "virtio",
    do_virtio_entry, mod);
    + else if (sym_is(symname, "__mod_i2c_device_table"))
    + do_table(symval, sym->st_size,
    + sizeof(struct i2c_device_id), "i2c",
    + do_i2c_entry, mod);
    free(zeros);
    }


    --
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/

  3. Re: [i2c] [PATCH 19 1/5] Implement module aliasing for i2c to translate from device tree names

    Comment was wrong, I2C_OF_MODULE_PREFIX was needed. Add it back.

    Implement module aliasing for i2c to translate from device tree names

    This patch allows new style i2c chip drivers to have alias names using
    the official kernel aliasing system and MODULE_DEVICE_TABLE(). I've
    tested it on PowerPC and x86. This change is required for PowerPC
    device tree support.

    Signed-off-by: Jon Smirl
    ---

    drivers/hwmon/f75375s.c | 4 ++--
    drivers/i2c/chips/ds1682.c | 2 +-
    drivers/i2c/chips/menelaus.c | 2 +-
    drivers/i2c/chips/tps65010.c | 2 +-
    drivers/i2c/chips/tsl2550.c | 2 +-
    drivers/i2c/i2c-core.c | 24 +++++++++++++++++++++++-
    drivers/rtc/rtc-ds1307.c | 2 +-
    drivers/rtc/rtc-ds1374.c | 2 +-
    drivers/rtc/rtc-m41t80.c | 2 +-
    drivers/rtc/rtc-rs5c372.c | 2 +-
    include/linux/i2c.h | 5 ++---
    include/linux/mod_devicetable.h | 20 ++++++++++++++++++++
    scripts/mod/file2alias.c | 12 ++++++++++++
    13 files changed, 67 insertions(+), 14 deletions(-)


    diff --git a/drivers/hwmon/f75375s.c b/drivers/hwmon/f75375s.c
    index 6892f76..2247de6 100644
    --- a/drivers/hwmon/f75375s.c
    +++ b/drivers/hwmon/f75375s.c
    @@ -117,7 +117,7 @@ struct f75375_data {
    static int f75375_attach_adapter(struct i2c_adapter *adapter);
    static int f75375_detect(struct i2c_adapter *adapter, int address, int kind);
    static int f75375_detach_client(struct i2c_client *client);
    -static int f75375_probe(struct i2c_client *client);
    +static int f75375_probe(struct i2c_client *client, const struct
    i2c_device_id *id);
    static int f75375_remove(struct i2c_client *client);

    static struct i2c_driver f75375_legacy_driver = {
    @@ -628,7 +628,7 @@ static void f75375_init(struct i2c_client *client,
    struct f75375_data *data,

    }

    -static int f75375_probe(struct i2c_client *client)
    +static int f75375_probe(struct i2c_client *client, const struct
    i2c_device_id *id)
    {
    struct f75375_data *data = i2c_get_clientdata(client);
    struct f75375s_platform_data *f75375s_pdata = client->dev.platform_data;
    diff --git a/drivers/i2c/chips/ds1682.c b/drivers/i2c/chips/ds1682.c
    index 9e94542..93c0441 100644
    --- a/drivers/i2c/chips/ds1682.c
    +++ b/drivers/i2c/chips/ds1682.c
    @@ -200,7 +200,7 @@ static struct bin_attribute ds1682_eeprom_attr = {
    /*
    * Called when a ds1682 device is matched with this driver
    */
    -static int ds1682_probe(struct i2c_client *client)
    +static int ds1682_probe(struct i2c_client *client, const struct
    i2c_device_id *id)
    {
    int rc;

    diff --git a/drivers/i2c/chips/menelaus.c b/drivers/i2c/chips/menelaus.c
    index 2dea012..89ef9b6 100644
    --- a/drivers/i2c/chips/menelaus.c
    +++ b/drivers/i2c/chips/menelaus.c
    @@ -1149,7 +1149,7 @@ static inline void menelaus_rtc_init(struct
    menelaus_chip *m)

    static struct i2c_driver menelaus_i2c_driver;

    -static int menelaus_probe(struct i2c_client *client)
    +static int menelaus_probe(struct i2c_client *client, const struct
    i2c_device_id *id)
    {
    struct menelaus_chip *menelaus;
    int rev = 0, val;
    diff --git a/drivers/i2c/chips/tps65010.c b/drivers/i2c/chips/tps65010.c
    index e320994..6b13642 100644
    --- a/drivers/i2c/chips/tps65010.c
    +++ b/drivers/i2c/chips/tps65010.c
    @@ -465,7 +465,7 @@ static int __exit tps65010_remove(struct i2c_client *client)
    return 0;
    }

    -static int tps65010_probe(struct i2c_client *client)
    +static int tps65010_probe(struct i2c_client *client, const struct
    i2c_device_id *id)
    {
    struct tps65010 *tps;
    int status;
    diff --git a/drivers/i2c/chips/tsl2550.c b/drivers/i2c/chips/tsl2550.c
    index 3de4b19..27c553d 100644
    --- a/drivers/i2c/chips/tsl2550.c
    +++ b/drivers/i2c/chips/tsl2550.c
    @@ -364,7 +364,7 @@ static int tsl2550_init_client(struct i2c_client *client)
    */

    static struct i2c_driver tsl2550_driver;
    -static int __devinit tsl2550_probe(struct i2c_client *client)
    +static int __devinit tsl2550_probe(struct i2c_client *client, const
    struct i2c_device_id *id)
    {
    struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
    struct tsl2550_data *data;
    diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
    index b5e13e4..5f62230 100644
    --- a/drivers/i2c/i2c-core.c
    +++ b/drivers/i2c/i2c-core.c
    @@ -47,6 +47,19 @@ static DEFINE_IDR(i2c_adapter_idr);

    /* ------------------------------------------------------------------------- */

    +static const struct i2c_device_id *i2c_match_id(
    + const struct i2c_device_id *id, struct i2c_client *client)
    +{
    + /* only powerpc drivers implement the id_table,
    + * it is empty on other platforms */
    + while (id->name[0]) {
    + if (strcmp(client->name, id->name) == 0)
    + return id;
    + id++;
    + }
    + return NULL;
    +}
    +
    static int i2c_device_match(struct device *dev, struct device_driver *drv)
    {
    struct i2c_client *client = to_i2c_client(dev);
    @@ -58,6 +71,10 @@ static int i2c_device_match(struct device *dev,
    struct device_driver *drv)
    if (!is_newstyle_driver(driver))
    return 0;

    + /* match on an id table if there is one */
    + if (driver->id_table)
    + return i2c_match_id(driver->id_table, client) != NULL;
    +
    /* new style drivers use the same kind of driver matching policy
    * as platform devices or SPI: compare device and driver IDs.
    */
    @@ -89,12 +106,17 @@ static int i2c_device_probe(struct device *dev)
    {
    struct i2c_client *client = to_i2c_client(dev);
    struct i2c_driver *driver = to_i2c_driver(dev->driver);
    + const struct i2c_device_id *id = NULL;

    if (!driver->probe)
    return -ENODEV;
    client->driver = driver;
    dev_dbg(dev, "probe\n");
    - return driver->probe(client);
    +
    + if (driver->id_table)
    + id = i2c_match_id(driver->id_table, client);
    +
    + return driver->probe(client, id);
    }

    static int i2c_device_remove(struct device *dev)
    diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c
    index bc1c7fe..9b0eab9 100644
    --- a/drivers/rtc/rtc-ds1307.c
    +++ b/drivers/rtc/rtc-ds1307.c
    @@ -326,7 +326,7 @@ static struct bin_attribute nvram = {

    static struct i2c_driver ds1307_driver;

    -static int __devinit ds1307_probe(struct i2c_client *client)
    +static int __devinit ds1307_probe(struct i2c_client *client, const
    struct i2c_device_id *id)
    {
    struct ds1307 *ds1307;
    int err = -ENODEV;
    diff --git a/drivers/rtc/rtc-ds1374.c b/drivers/rtc/rtc-ds1374.c
    index 45bda18..dab6008 100644
    --- a/drivers/rtc/rtc-ds1374.c
    +++ b/drivers/rtc/rtc-ds1374.c
    @@ -355,7 +355,7 @@ static const struct rtc_class_ops ds1374_rtc_ops = {
    .ioctl = ds1374_ioctl,
    };

    -static int ds1374_probe(struct i2c_client *client)
    +static int ds1374_probe(struct i2c_client *client, const struct
    i2c_device_id *id)
    {
    struct ds1374 *ds1374;
    int ret;
    diff --git a/drivers/rtc/rtc-m41t80.c b/drivers/rtc/rtc-m41t80.c
    index 1cb33ca..457f2ca 100644
    --- a/drivers/rtc/rtc-m41t80.c
    +++ b/drivers/rtc/rtc-m41t80.c
    @@ -756,7 +756,7 @@ static struct notifier_block wdt_notifier = {
    *
    ************************************************** ***************************
    */
    -static int m41t80_probe(struct i2c_client *client)
    +static int m41t80_probe(struct i2c_client *client, const struct
    i2c_device_id *id)
    {
    int i, rc = 0;
    struct rtc_device *rtc = NULL;
    diff --git a/drivers/rtc/rtc-rs5c372.c b/drivers/rtc/rtc-rs5c372.c
    index 6b67b50..25de13b 100644
    --- a/drivers/rtc/rtc-rs5c372.c
    +++ b/drivers/rtc/rtc-rs5c372.c
    @@ -494,7 +494,7 @@ static void rs5c_sysfs_unregister(struct device *dev)

    static struct i2c_driver rs5c372_driver;

    -static int rs5c372_probe(struct i2c_client *client)
    +static int rs5c372_probe(struct i2c_client *client, const struct
    i2c_device_id *id)
    {
    int err = 0;
    struct rs5c372 *rs5c372;
    diff --git a/include/linux/i2c.h b/include/linux/i2c.h
    index a100c9f..0ca1a59 100644
    --- a/include/linux/i2c.h
    +++ b/include/linux/i2c.h
    @@ -126,7 +126,7 @@ struct i2c_driver {
    * With the driver model, device enumeration is NEVER done by drivers;
    * it's done by infrastructure. (NEW STYLE DRIVERS ONLY)
    */
    - int (*probe)(struct i2c_client *);
    + int (*probe)(struct i2c_client *, const struct i2c_device_id *id);
    int (*remove)(struct i2c_client *);

    /* driver model interfaces that don't relate to enumeration */
    @@ -141,11 +141,10 @@ struct i2c_driver {

    struct device_driver driver;
    struct list_head list;
    + struct i2c_device_id *id_table;
    };
    #define to_i2c_driver(d) container_of(d, struct i2c_driver, driver)

    -#define I2C_NAME_SIZE 20
    -
    /**
    * struct i2c_client - represent an I2C slave device
    * @flags: I2C_CLIENT_TEN indicates the device uses a ten bit chip address;
    diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h
    index e9fddb4..612d416 100644
    --- a/include/linux/mod_devicetable.h
    +++ b/include/linux/mod_devicetable.h
    @@ -367,4 +367,24 @@ struct virtio_device_id {
    };
    #define VIRTIO_DEV_ANY_ID 0xffffffff

    +/* i2c */
    +
    +/* These defines are used to separate PowerPC open firmware
    + * drivers into their own namespace */
    +#define I2C_NAME_SIZE (16*3) /* Needs to be large enough to hold
    device tree style names */
    +#define I2C_MODULE_PREFIX "i2c:"
    +#ifdef CONFIG_OF
    +#define OF_I2C_PREFIX "OF,"
    +#define I2C_OF_MODULE_PREFIX I2C_MODULE_PREFIX OF_I2C_PREFIX
    +#define OF_I2C_ID(s,d) { OF_I2C_PREFIX s, (d) },
    +#else
    +#define OF_I2C_ID(s,d)
    +#endif
    +
    +struct i2c_device_id {
    + char name[I2C_NAME_SIZE];
    + kernel_ulong_t driver_data; /* Data private to the driver */
    +};
    +
    +
    #endif /* LINUX_MOD_DEVICETABLE_H */
    diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c
    index d802b5a..ac05b04 100644
    --- a/scripts/mod/file2alias.c
    +++ b/scripts/mod/file2alias.c
    @@ -539,6 +539,14 @@ static int do_virtio_entry(const char *filename,
    struct virtio_device_id *id,
    return 1;
    }

    +/* Looks like: i2c:s */
    +static int do_i2c_entry(const char *filename, struct i2c_device_id *id,
    + char *alias)
    +{
    + sprintf(alias, I2C_MODULE_PREFIX "%s", id->name);
    + return 1;
    +}
    +
    /* Ignore any prefix, eg. v850 prepends _ */
    static inline int sym_is(const char *symbol, const char *name)
    {
    @@ -669,6 +677,10 @@ void handle_moddevtable(struct module *mod,
    struct elf_info *info,
    do_table(symval, sym->st_size,
    sizeof(struct virtio_device_id), "virtio",
    do_virtio_entry, mod);
    + else if (sym_is(symname, "__mod_i2c_device_table"))
    + do_table(symval, sym->st_size,
    + sizeof(struct i2c_device_id), "i2c",
    + do_i2c_entry, mod);
    free(zeros);
    }

    --
    Jon Smirl
    jonsmirl@gmail.com
    --
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/

  4. Re: [i2c] [PATCH 19 1/5] Implement module aliasing for i2c to translate from device tree names

    Hi Jon,

    On Fri, 11 Jan 2008 22:00:42 -0500 "Jon Smirl" wrote:
    >
    > +++ b/drivers/hwmon/f75375s.c
    > @@ -117,7 +117,7 @@ struct f75375_data {
    > static int f75375_attach_adapter(struct i2c_adapter *adapter);
    > static int f75375_detect(struct i2c_adapter *adapter, int address, int kind);
    > static int f75375_detach_client(struct i2c_client *client);
    > -static int f75375_probe(struct i2c_client *client);
    > +static int f75375_probe(struct i2c_client *client, const struct
    > i2c_device_id *id);


    Looks like your mail client has wrapped this. Also in various later
    spots.

    > +++ b/drivers/i2c/i2c-core.c
    > @@ -47,6 +47,19 @@ static DEFINE_IDR(i2c_adapter_idr);
    >
    > /* ------------------------------------------------------------------------- */
    >
    > +static const struct i2c_device_id *i2c_match_id(
    > + const struct i2c_device_id *id, struct i2c_client *client)


    Any reason that the "client" argument is not const as well?

    > +++ b/include/linux/i2c.h
    > @@ -141,11 +141,10 @@ struct i2c_driver {
    >
    > struct device_driver driver;
    > struct list_head list;
    > + struct i2c_device_id *id_table;


    Any reason that this is not const? Making it const would allow divers to
    make their tables const.

    These are just small things (apart from the wrapping) that can be fixed
    up with followup patches.

    --
    Cheers,
    Stephen Rothwell sfr@canb.auug.org.au
    http://www.canb.auug.org.au/~sfr/

    -----BEGIN PGP SIGNATURE-----
    Version: GnuPG v1.4.6 (GNU/Linux)

    iD8DBQFHiDhQTgG2atn1QN8RAkvzAJ4r8DaBYRyq1PBhTN8IXW//3fZGSwCfYu1M
    IFzVy4mah4t9+8O/vqQ2z28=
    =3njn
    -----END PGP SIGNATURE-----


  5. Re: [PATCH 19 4/5] Convert PowerPC MPC i2c to of_platform_driver from platform_driver

    Hi Jon,

    On Fri, 11 Jan 2008 21:47:46 -0500 Jon Smirl wrote:
    >
    > +++ b/drivers/i2c/busses/i2c-mpc.c


    > +static void of_register_i2c_devices(struct i2c_adapter *adap, struct device_node *adap_node)
    > +{
    > + struct device_node *node = NULL;
    > +
    > + while ((node = of_get_next_child(adap_node, node))) {


    We have for_each_child_of_node(adap_node, node) now for this (and it
    means you don't need to initialize the "node" above).

    > + struct i2c_board_info info;
    > + const u32 *addr;
    > + const char *compatible;
    > + int len;
    > +
    > + addr = of_get_property(node, "reg", &len);
    > + if (!addr || len < sizeof(int) || *addr > (1 << 10) - 1) {
    > + printk(KERN_ERR "i2c-mpc.c: invalid entry, missing reg attribute\n");
    > + continue;
    > + }
    > +
    > + info.irq = irq_of_parse_and_map(node, 0);
    > + if (info.irq == NO_IRQ)
    > + info.irq = -1;
    > +
    > + compatible = of_get_property(node, "compatible", &len);
    > + if (!compatible) {
    > + printk(KERN_ERR "i2c-mpc.c: invalid entry, missing compatible attribute\n");
    > + continue;


    You may need to clean up from the irq_of_pase_and_map().

    > + }
    > +
    > + /* need full alias i2c:NOF,vendor,device */
    > + strcpy(info.type, I2C_OF_MODULE_PREFIX);
    > + strncat(info.type, compatible, sizeof(info.type));
    > + request_module(info.type);
    > +
    > + /* need module alias OF,vendor,device */
    > + strcpy(info.type, OF_I2C_PREFIX);
    > + strncat(info.type, compatible, sizeof(info.type));
    > +
    > + info.driver_name[0] = '\0';
    > + info.platform_data = NULL;
    > + info.addr = *addr;
    > +
    > + if (!i2c_new_device(adap, &info)) {
    > + printk(KERN_ERR "i2c-mpc.c: Failed to load driver for %s\n", info.type);
    > + continue;


    And again.

    > + }
    > + }
    > +}
    > +
    > +static int mpc_i2c_probe(struct of_device *op, const struct of_device_id*match)
    > +{


    > + dev_set_drvdata(&op->dev, i2c);
    > +
    > + i2c->adap = mpc_ops;
    > + i2c_set_adapdata(&i2c->adap, i2c);
    > + i2c->adap.dev.parent = &op->dev;
    > +
    > + result = i2c_add_adapter(&i2c->adap);
    > + if (result < 0) {
    > + printk(KERN_ERR "i2c-mpc - failed to add adapter\n");
    > + goto fail_add;
    > + }
    > +
    > + of_register_i2c_devices(&i2c->adap, op->node);
    > +
    > + return result;
    > +
    > +fail_add:


    dev_set_dvdata(&op->dev, NULL);

    > + free_irq(i2c->irq, i2c);
    > +fail_request:
    > + irq_dispose_mapping(i2c->irq);
    > +fail_irq:
    > + iounmap(i2c->base);
    > +fail_map:
    > + kfree(i2c);
    > + return result;
    > +};


    > +static struct of_device_id mpc_i2c_of_match[] = {


    const, please.

    --
    Cheers,
    Stephen Rothwell sfr@canb.auug.org.au
    http://www.canb.auug.org.au/~sfr/

    -----BEGIN PGP SIGNATURE-----
    Version: GnuPG v1.4.6 (GNU/Linux)

    iD8DBQFHiDz4TgG2atn1QN8RAjUxAJ9EKsqJwr8ROLgJ7AxjWD QGbSVaSgCeK860
    NqKJFy9Qaslyhi+B8zY7s0s=
    =R6J4
    -----END PGP SIGNATURE-----


  6. Re: [i2c] [PATCH 19 3/5] Clean up error returns

    Hi Jon,

    On Fri, 11 Jan 2008 21:47:43 -0500, Jon Smirl wrote:
    > Return errors that were being ignored in the mpc-i2c driver


    This wording is a bit excessive. The errors were not being ignored,
    only the error code was replaced with a less informative -1. Still,
    that's a good fix, although totally unrelated with the patch set it was
    hiding into. The only question I have is:

    >
    > Signed-off-by: Jon Smirl
    > ---
    >
    > drivers/i2c/busses/i2c-mpc.c | 30 +++++++++++++++++-------------
    > 1 files changed, 17 insertions(+), 13 deletions(-)
    >
    >
    > diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c
    > index d8de4ac..7c35a8f 100644
    > --- a/drivers/i2c/busses/i2c-mpc.c
    > +++ b/drivers/i2c/busses/i2c-mpc.c
    > @@ -180,7 +180,7 @@ static void mpc_i2c_stop(struct mpc_i2c *i2c)
    > static int mpc_write(struct mpc_i2c *i2c, int target,
    > const u8 * data, int length, int restart)
    > {
    > - int i;
    > + int i, result;
    > unsigned timeout = i2c->adap.timeout;
    > u32 flags = restart ? CCR_RSTA : 0;
    >
    > @@ -192,15 +192,17 @@ static int mpc_write(struct mpc_i2c *i2c, int target,
    > /* Write target byte */
    > writeb((target << 1), i2c->base + MPC_I2C_DR);
    >
    > - if (i2c_wait(i2c, timeout, 1) < 0)
    > - return -1;
    > + result = i2c_wait(i2c, timeout, 1);
    > + if (result < 0)
    > + return result;
    >
    > for (i = 0; i < length; i++) {
    > /* Write data byte */
    > writeb(data[i], i2c->base + MPC_I2C_DR);
    >
    > - if (i2c_wait(i2c, timeout, 1) < 0)
    > - return -1;
    > + result = i2c_wait(i2c, timeout, 1);
    > + if (result < 0)
    > + return result;
    > }
    >
    > return 0;
    > @@ -210,7 +212,7 @@ static int mpc_read(struct mpc_i2c *i2c, int target,
    > u8 * data, int length, int restart)
    > {
    > unsigned timeout = i2c->adap.timeout;
    > - int i;
    > + int i, result;
    > u32 flags = restart ? CCR_RSTA : 0;
    >
    > /* Start with MEN */
    > @@ -221,8 +223,9 @@ static int mpc_read(struct mpc_i2c *i2c, int target,
    > /* Write target address byte - this time with the read flag set */
    > writeb((target << 1) | 1, i2c->base + MPC_I2C_DR);
    >
    > - if (i2c_wait(i2c, timeout, 1) < 0)
    > - return -1;
    > + result = i2c_wait(i2c, timeout, 1);
    > + if (result < 0)
    > + return result;
    >
    > if (length) {
    > if (length == 1)
    > @@ -234,8 +237,9 @@ static int mpc_read(struct mpc_i2c *i2c, int target,
    > }
    >
    > for (i = 0; i < length; i++) {
    > - if (i2c_wait(i2c, timeout, 0) < 0)
    > - return -1;
    > + result = i2c_wait(i2c, timeout, 0);
    > + if (result < 0)
    > + return result;
    >
    > /* Generate txack on next to last byte */
    > if (i == length - 2)
    > @@ -321,9 +325,9 @@ static int fsl_i2c_probe(struct platform_device *pdev)
    >
    > pdata = (struct fsl_i2c_platform_data *) pdev->dev.platform_data;
    >
    > - if (!(i2c = kzalloc(sizeof(*i2c), GFP_KERNEL))) {
    > + i2c = kzalloc(sizeof(*i2c), GFP_KERNEL);
    > + if (!i2c)
    > return -ENOMEM;
    > - }
    >
    > i2c->irq = platform_get_irq(pdev, 0);
    > if (i2c->irq < 0) {
    > @@ -381,7 +385,7 @@ static int fsl_i2c_remove(struct platform_device *pdev)
    > i2c_del_adapter(&i2c->adap);
    > platform_set_drvdata(pdev, NULL);
    >
    > - if (i2c->irq != 0)
    > + if (i2c->irq != NO_IRQ)
    > free_irq(i2c->irq, i2c);
    >
    > iounmap(i2c->base);
    >
    >


    Is this last chunk a cleanup or a bugfix? It seems that NO_IRQ can have
    value 0 or -1 depending on the architecture, so your change is real on
    some architectures.

    I have to admit that I'm a bit confused by the way IRQs are handled by
    this driver. On the one hand, there is code to handle polled-mode:

    static int i2c_wait(struct mpc_i2c *i2c, unsigned timeout, int writing)
    {
    (...)
    if (i2c->irq == 0)
    {
    (...)
    } else {
    /* Interrupt mode */

    But on the other hand the initialization code bails out if the platform
    device doesn't provide an IRQ:

    static int fsl_i2c_probe(struct platform_device *pdev)
    {
    (...)
    i2c->irq = platform_get_irq(pdev, 0);
    if (i2c->irq < 0) {
    result = -ENXIO;
    goto fail_get_irq;
    }

    So it seems to me like the polling mode code is never actually used?
    Unless some platforms include an "empty" IRQ in their device
    definition. Which indeed seems to be the case... but then they set the
    IRQ to 0, NOT to NO_IRQ, so I'm wondering if the change you propose is
    really correct.

    Either way, there are more places in the driver where the IRQ is
    compared to 0, so if your change is correct, it should be applied
    consistently. Thus I will revert this part for the time being, if any
    change is really needed with regards to interrupts in this driver,
    please send a separate patch. But please double-check first, as I said
    above it's trickier than it looks.

    --
    Jean Delvare
    --
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/

  7. Re: [i2c] [PATCH 19 3/5] Clean up error returns

    On 1/20/08, Jean Delvare wrote:
    > > @@ -381,7 +385,7 @@ static int fsl_i2c_remove(struct platform_device *pdev)
    > > i2c_del_adapter(&i2c->adap);
    > > platform_set_drvdata(pdev, NULL);
    > >
    > > - if (i2c->irq != 0)
    > > + if (i2c->irq != NO_IRQ)
    > > free_irq(i2c->irq, i2c);
    > >
    > > iounmap(i2c->base);
    > >
    > >

    >
    > Is this last chunk a cleanup or a bugfix? It seems that NO_IRQ can have
    > value 0 or -1 depending on the architecture, so your change is real on
    > some architectures.


    I was confused by this too. Search the ppc list archives and there is
    a thread about it where BenH tries to explain the correct way of
    fixing it to me.

    This is part of the ppc to powerpc conversion that has not been
    completely cleaned up in this driver. NO_IRQ = -1 is ppc and NO_IRQ =
    0 is powerpc. Since this driver didn't originally use the NO_IRQ
    define it didn't get automatically converted. We need to identify the
    right places where NO_IRQ should have been used.

    >
    > I have to admit that I'm a bit confused by the way IRQs are handled by
    > this driver. On the one hand, there is code to handle polled-mode:
    >
    > static int i2c_wait(struct mpc_i2c *i2c, unsigned timeout, int writing)
    > {
    > (...)
    > if (i2c->irq == 0)


    I missed this one, it should have been NO_IRQ.

    > {
    > (...)
    > } else {
    > /* Interrupt mode */
    >
    > But on the other hand the initialization code bails out if the platform
    > device doesn't provide an IRQ:


    >
    > static int fsl_i2c_probe(struct platform_device *pdev)
    > {
    > (...)
    > i2c->irq = platform_get_irq(pdev, 0);
    > if (i2c->irq < 0) {
    > result = -ENXIO;
    > goto fail_get_irq;


    It is only bailing out on an error, not the NO_IRQ case. But maybe the
    comparison needs to be with NO_IRQ instead of zero.



    > }
    >
    > So it seems to me like the polling mode code is never actually used?
    > Unless some platforms include an "empty" IRQ in their device
    > definition. Which indeed seems to be the case... but then they set the
    > IRQ to 0, NOT to NO_IRQ, so I'm wondering if the change you propose is
    > really correct.


    All of this is very confusing to me, There are physical IRQs and
    virtual IRQs. Apparently zero is a legal physical IRQ but it is not a
    legal virtual IRQ. We only get virtual IRQs in this code. We need to
    get BenH to give us the right answer on these two cases.


    >
    > Either way, there are more places in the driver where the IRQ is
    > compared to 0, so if your change is correct, it should be applied
    > consistently. Thus I will revert this part for the time being, if any
    > change is really needed with regards to interrupts in this driver,
    > please send a separate patch. But please double-check first, as I said
    > above it's trickier than it looks.
    >
    > --
    > Jean Delvare
    >



    --
    Jon Smirl
    jonsmirl@gmail.com
    --
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/

  8. Re: [i2c] [PATCH 19 3/5] Clean up error returns

    Hi Jon,

    On Sun, 20 Jan 2008 10:39:43 -0500, Jon Smirl wrote:
    > Here' s a version with the compares to zero switched to NO_IRQ. If I
    > understand how NO_IRQ works it is the correct change. My understanding
    > is that under ppc IRQ zero was legal and NO_IRQ was -1. But then the
    > whole kernel switched to NO_IRQ = zero. Powerpc updated to NO_IRQ=0
    > and used virtual IRQs to move a physical IRQ 0 to another IRQ number.
    > ppc was not changed. This driver does not appear to have been updated
    > to track this global change since it didn't initially use the NO_IRQ
    > define everywhere.


    As I have already applied the part of this patch that preserves error
    values in error paths, can you please send an incremental patch that
    only fixes the IRQ issues? These are separate issues so it's better to
    have separate patches anyway.

    Thanks,
    --
    Jean Delvare
    --
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/

  9. Re: [i2c] [PATCH 19 3/5] Clean up error returns


    On Mon, 2008-01-21 at 17:10 +0100, Jean Delvare wrote:
    > Hi Jon,
    >
    > On Sun, 20 Jan 2008 10:39:43 -0500, Jon Smirl wrote:
    > > Here' s a version with the compares to zero switched to NO_IRQ. If I
    > > understand how NO_IRQ works it is the correct change. My understanding
    > > is that under ppc IRQ zero was legal and NO_IRQ was -1. But then the
    > > whole kernel switched to NO_IRQ = zero. Powerpc updated to NO_IRQ=0
    > > and used virtual IRQs to move a physical IRQ 0 to another IRQ number.
    > > ppc was not changed. This driver does not appear to have been updated
    > > to track this global change since it didn't initially use the NO_IRQ
    > > define everywhere.

    >
    > As I have already applied the part of this patch that preserves error
    > values in error paths, can you please send an incremental patch that
    > only fixes the IRQ issues? These are separate issues so it's better to
    > have separate patches anyway.


    To be clear, nowadays, checking against 0 is correct unless you intend
    the driver to work with arch/ppc (which we'll deprecate soon).

    Ben.


    --
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/

  10. Re: [i2c] [PATCH 19 3/5] Clean up error returns


    On Sun, 2008-01-20 at 10:18 -0500, Jon Smirl wrote:
    > > So it seems to me like the polling mode code is never actually used?
    > > Unless some platforms include an "empty" IRQ in their device
    > > definition. Which indeed seems to be the case... but then they set

    > the
    > > IRQ to 0, NOT to NO_IRQ, so I'm wondering if the change you propose

    > is
    > > really correct.

    >
    > All of this is very confusing to me, There are physical IRQs and
    > virtual IRQs. Apparently zero is a legal physical IRQ but it is not a
    > legal virtual IRQ. We only get virtual IRQs in this code. We need to
    > get BenH to give us the right answer on these two cases.


    Testing against NO_IRQ for a linux IRQ number should always be correct.

    Physical IRQ numbers are remapped and shouldn't be visible to drivers,
    NO_IRQ is a value that never exist for a valid logical interrupt number,
    that is 0 for arch/powerpc and -1 for arch/ppc.

    Ben.


    --
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/

  11. Re: [PATCH 19 5/5] Convert pfc8563 i2c driver from old style to new style

    Hi Jon,

    On Saturday 12 January 2008 03:47, Jon Smirl wrote:
    > Convert pfc8563 i2c driver from old style to new style. The
    > driver is also modified to support device tree names via the
    > i2c mod alias mechanism.


    The patch breaks the pfc8563 driver.

    The old style driver allocated memory for a pcf8563 structure that
    encapsulated an i2c_client instance. Various functions use container_of
    on an i2c_client instance to get a pointer to the pcf8563 structure.

    The new style driver gets rid of the pcf8563 structure allocation, as the
    i2c_client structure is now allocated by I2C code.

    Here is an incremental patch that fixes the issue.

    From 1eac5a8e10e085c3a77c6ba7ed9dac9a39024915 Mon Sep 17 00:00:00 2001
    From: Laurent Pinchart
    Date: Thu, 10 Apr 2008 11:12:25 +0200
    Subject: [PATCH] Fix pcf8563 breakage introduced by the conversion from oldstyle to new style

    The old style I2C driver used to allocate a pcf8563 instance that encapsulated
    an i2c_client instance. The i2c_client instance is now allocated by I2C core.

    This patch fixes the driver by storing the pcf8563 instance in the I2C client
    data field.

    Signed-off-by: Laurent Pinchart
    ---
    drivers/rtc/rtc-pcf8563.c | 29 ++++++++++++++++++-----------
    1 files changed, 18 insertions(+), 11 deletions(-)

    diff --git a/drivers/rtc/rtc-pcf8563.c b/drivers/rtc/rtc-pcf8563.c
    index e1ea2a0..7aab24e 100644
    --- a/drivers/rtc/rtc-pcf8563.c
    +++ b/drivers/rtc/rtc-pcf8563.c
    @@ -50,7 +50,7 @@
    #define PCF8563_MO_C 0x80 /* century */

    struct pcf8563 {
    - struct i2c_client client;
    + struct rtc_device *rtc;
    /*
    * The meaning of MO_C bit varies by the chip type.
    * From PCF8563 datasheet: this bit is toggled when the years
    @@ -74,7 +74,7 @@ struct pcf8563 {
    */
    static int pcf8563_get_datetime(struct i2c_client *client, struct rtc_time*tm)
    {
    - struct pcf8563 *pcf8563 = container_of(client, struct pcf8563, client);
    + struct pcf8563 *pcf8563 = i2c_get_clientdata(client);
    unsigned char buf[13] = { PCF8563_REG_ST1 };

    struct i2c_msg msgs[] = {
    @@ -131,7 +131,7 @@ static int pcf8563_get_datetime(struct i2c_client *client, struct rtc_time *tm)

    static int pcf8563_set_datetime(struct i2c_client *client, struct rtc_time*tm)
    {
    - struct pcf8563 *pcf8563 = container_of(client, struct pcf8563, client);
    + struct pcf8563 *pcf8563 = i2c_get_clientdata(client);
    int i, err;
    unsigned char buf[9];

    @@ -252,10 +252,10 @@ static const struct rtc_class_ops pcf8563_rtc_ops ={

    static int pcf8563_remove(struct i2c_client *client)
    {
    - struct rtc_device *rtc = i2c_get_clientdata(client);
    + struct pcf8563 *pcf8563 = i2c_get_clientdata(client);

    - if (rtc)
    - rtc_device_unregister(rtc);
    + if (pcf8563->rtc)
    + rtc_device_unregister(pcf8563->rtc);

    return 0;
    }
    @@ -274,26 +274,33 @@ static struct i2c_driver pcf8563_driver = {
    .name = "rtc-pcf8563",
    },
    .id = I2C_DRIVERID_PCF8563,
    - .probe = &pcf8563_probe,
    - .remove = &pcf8563_remove,
    + .probe = &pcf8563_probe,
    + .remove = &pcf8563_remove,
    .id_table = pcf8563_id,
    };

    static int pcf8563_probe(struct i2c_client *client, const struct i2c_device_id *id)
    {
    - int result;
    + struct pcf8563 *pcf8563;
    struct rtc_device *rtc;
    + int result;

    result = pcf8563_validate_client(client);
    if (result)
    return result;

    + if ((pcf8563 = kzalloc(sizeof(*pcf8563), GFP_KERNEL)) == NULL)
    + return -ENOMEM;
    +
    rtc = rtc_device_register(pcf8563_driver.driver.name, &client->dev,
    &pcf8563_rtc_ops, THIS_MODULE);
    - if (IS_ERR(rtc))
    + if (IS_ERR(rtc)) {
    + kfree(pcf8563);
    return PTR_ERR(rtc);
    + }

    - i2c_set_clientdata(client, rtc);
    + pcf8563->rtc = rtc;
    + i2c_set_clientdata(client, pcf8563);

    return 0;
    }
    --
    1.5.0

    --
    Laurent Pinchart
    CSE Semaphore Belgium

    Chaussee de Bruxelles, 732A
    B-1410 Waterloo
    Belgium

    T +32 (2) 387 42 59
    F +32 (2) 387 42 75

    -----BEGIN PGP SIGNATURE-----
    Version: GnuPG v1.4.5 (GNU/Linux)

    iD8DBQBH/dpq8y9gWxC9vpcRAmsjAJ4g3CJ/+8xY/kocuw2EWrHYen902gCgti3Y
    EtYl7MvLc8nWqd8PskVQlTw=
    =7XiV
    -----END PGP SIGNATURE-----


+ Reply to Thread