lkml.org 
[lkml]   [2011]   [Jun]   [20]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 2/8] regmap: Add I2C bus support
    Date
    We initialise at postcore_initcall() so that we are available before users
    - some users such as PMICs initialise very early. We won't actually try to
    use any of the bus until a device initialises a register map.

    Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
    ---
    drivers/regmap/Makefile | 2 +-
    drivers/regmap/regmap-i2c.c | 112 +++++++++++++++++++++++++++++++++++++++++++
    drivers/regmap/regmap.c | 4 +-
    3 files changed, 115 insertions(+), 3 deletions(-)
    create mode 100644 drivers/regmap/regmap-i2c.c

    diff --git a/drivers/regmap/Makefile b/drivers/regmap/Makefile
    index 1e5037e..641c20a 100644
    --- a/drivers/regmap/Makefile
    +++ b/drivers/regmap/Makefile
    @@ -1,2 +1,2 @@
    obj-$(CONFIG_REGMAP) += regmap.o
    -
    +obj-$(CONFIG_I2C) += regmap-i2c.o
    diff --git a/drivers/regmap/regmap-i2c.c b/drivers/regmap/regmap-i2c.c
    new file mode 100644
    index 0000000..4a61560
    --- /dev/null
    +++ b/drivers/regmap/regmap-i2c.c
    @@ -0,0 +1,112 @@
    +/*
    + * Register map access API - I2C support
    + *
    + * Copyright 2011 Wolfson Microelectronics plc
    + *
    + * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
    + *
    + * This program is free software; you can redistribute it and/or modify
    + * it under the terms of the GNU General Public License version 2 as
    + * published by the Free Software Foundation.
    + */
    +
    +#include <linux/regmap.h>
    +#include <linux/i2c.h>
    +
    +static int regmap_i2c_write(struct device *dev, const void *data, size_t count)
    +{
    + struct i2c_client *i2c = to_i2c_client(dev);
    + int ret;
    +
    + ret = i2c_master_send(i2c, data, count);
    + if (ret == count)
    + return 0;
    + else if (ret < 0)
    + return ret;
    + else
    + return -EIO;
    +}
    +
    +static int regmap_i2c_gather_write(struct device *dev,
    + const void *reg, size_t reg_size,
    + const void *val, size_t val_size)
    +{
    + struct i2c_client *i2c = to_i2c_client(dev);
    + struct i2c_msg xfer[2];
    + int ret;
    +
    + /* If the I2C controller can't do a gather tell the core, it
    + * will substitute in a linear write for us.
    + */
    + if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_PROTOCOL_MANGLING))
    + return -ENOTSUPP;
    +
    + xfer[0].addr = i2c->addr;
    + xfer[0].flags = 0;
    + xfer[0].len = reg_size;
    + xfer[0].buf = (void *)reg;
    +
    + xfer[1].addr = i2c->addr;
    + xfer[1].flags = I2C_M_NOSTART;
    + xfer[1].len = val_size;
    + xfer[1].buf = (void *)val;
    +
    + ret = i2c_transfer(i2c->adapter, xfer, 2);
    + if (ret == 2)
    + return 0;
    + if (ret < 0)
    + return ret;
    + else
    + return -EIO;
    +}
    +
    +static int regmap_i2c_read(struct device *dev,
    + const void *reg, size_t reg_size,
    + void *val, size_t val_size)
    +{
    + struct i2c_client *i2c = to_i2c_client(dev);
    + struct i2c_msg xfer[2];
    + int ret;
    +
    + if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_PROTOCOL_MANGLING))
    + return -ENOTSUPP;
    +
    + xfer[0].addr = i2c->addr;
    + xfer[0].flags = 0;
    + xfer[0].len = reg_size;
    + xfer[0].buf = (void *)reg;
    +
    + xfer[1].addr = i2c->addr;
    + xfer[1].flags = I2C_M_RD;
    + xfer[1].len = val_size;
    + xfer[1].buf = val;
    +
    + ret = i2c_transfer(i2c->adapter, xfer, 2);
    + if (ret == 2)
    + return 0;
    + else if (ret < 0)
    + return ret;
    + else
    + return -EIO;
    +}
    +
    +static struct regmap_bus regmap_i2c = {
    + .type = &i2c_bus_type,
    + .write = regmap_i2c_write,
    + .gather_write = regmap_i2c_gather_write,
    + .read = regmap_i2c_read,
    + .owner = THIS_MODULE,
    +};
    +
    +static int __init regmap_i2c_init(void)
    +{
    + regmap_add_bus(&regmap_i2c);
    + return 0;
    +}
    +postcore_initcall(regmap_i2c_init);
    +
    +static void __exit regmap_i2c_exit(void)
    +{
    + regmap_del_bus(&regmap_i2c);
    +}
    +module_exit(regmap_i2c_exit);
    diff --git a/drivers/regmap/regmap.c b/drivers/regmap/regmap.c
    index a8610c7..896b710 100644
    --- a/drivers/regmap/regmap.c
    +++ b/drivers/regmap/regmap.c
    @@ -461,7 +461,7 @@ out:
    }
    EXPORT_SYMBOL_GPL(regmap_update_bits);

    -int regmap_add_bus(struct regmap_bus *bus)
    +void regmap_add_bus(struct regmap_bus *bus)
    {
    mutex_lock(&regmap_bus_lock);
    list_add(&bus->list, &regmap_bus_list);
    @@ -469,7 +469,7 @@ int regmap_add_bus(struct regmap_bus *bus)
    }
    EXPORT_SYMBOL_GPL(regmap_add_bus);

    -int regmap_del_bus(struct regmap_bus *bus)
    +void regmap_del_bus(struct regmap_bus *bus)
    {
    mutex_lock(&regmap_bus_lock);
    list_del(&bus->list);
    --
    1.7.5.4


    \
     
     \ /
      Last update: 2011-06-20 14:57    [W:0.027 / U:30.280 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site