aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Brown <broonie@opensource.wolfsonmicro.com>2011-06-20 14:02:29 -0400
committerMark Brown <broonie@opensource.wolfsonmicro.com>2011-07-23 02:56:39 -0400
commit9943fa300a5dcd4536e9a4aa5c09cf94e5e7b28c (patch)
treed846756bbc3feb9ffd8d3d2b6aa7ff876c39d367
parentb83a313bf2520183641cf485d68cc273323597d2 (diff)
regmap: Add I2C bus support
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> Acked-by: Liam Girdwood <lrg@ti.com> Acked-by: Wolfram Sang <w.sang@pengutronix.de> Acked-by: Grant Likely <grant.likely@secretlab.ca>
-rw-r--r--drivers/base/regmap/Kconfig4
-rw-r--r--drivers/base/regmap/Makefile1
-rw-r--r--drivers/base/regmap/regmap-i2c.c115
-rw-r--r--include/linux/regmap.h4
4 files changed, 124 insertions, 0 deletions
diff --git a/drivers/base/regmap/Kconfig b/drivers/base/regmap/Kconfig
index fc0eb1d484dd..03cf1abed401 100644
--- a/drivers/base/regmap/Kconfig
+++ b/drivers/base/regmap/Kconfig
@@ -3,4 +3,8 @@
3# subsystems should select the appropriate symbols. 3# subsystems should select the appropriate symbols.
4 4
5config REGMAP 5config REGMAP
6 default y if REGMAP_I2C
6 bool 7 bool
8
9config REGMAP_I2C
10 tristate
diff --git a/drivers/base/regmap/Makefile b/drivers/base/regmap/Makefile
index 7532e13e0f00..ee5109d20f4e 100644
--- a/drivers/base/regmap/Makefile
+++ b/drivers/base/regmap/Makefile
@@ -1 +1,2 @@
1obj-$(CONFIG_REGMAP) += regmap.o 1obj-$(CONFIG_REGMAP) += regmap.o
2obj-$(CONFIG_REGMAP_I2C) += regmap-i2c.o
diff --git a/drivers/base/regmap/regmap-i2c.c b/drivers/base/regmap/regmap-i2c.c
new file mode 100644
index 000000000000..c2231ff06cbc
--- /dev/null
+++ b/drivers/base/regmap/regmap-i2c.c
@@ -0,0 +1,115 @@
1/*
2 * Register map access API - I2C support
3 *
4 * Copyright 2011 Wolfson Microelectronics plc
5 *
6 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13#include <linux/regmap.h>
14#include <linux/i2c.h>
15#include <linux/module.h>
16#include <linux/init.h>
17
18static int regmap_i2c_write(struct device *dev, const void *data, size_t count)
19{
20 struct i2c_client *i2c = to_i2c_client(dev);
21 int ret;
22
23 ret = i2c_master_send(i2c, data, count);
24 if (ret == count)
25 return 0;
26 else if (ret < 0)
27 return ret;
28 else
29 return -EIO;
30}
31
32static int regmap_i2c_gather_write(struct device *dev,
33 const void *reg, size_t reg_size,
34 const void *val, size_t val_size)
35{
36 struct i2c_client *i2c = to_i2c_client(dev);
37 struct i2c_msg xfer[2];
38 int ret;
39
40 /* If the I2C controller can't do a gather tell the core, it
41 * will substitute in a linear write for us.
42 */
43 if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_PROTOCOL_MANGLING))
44 return -ENOTSUPP;
45
46 xfer[0].addr = i2c->addr;
47 xfer[0].flags = 0;
48 xfer[0].len = reg_size;
49 xfer[0].buf = (void *)reg;
50
51 xfer[1].addr = i2c->addr;
52 xfer[1].flags = I2C_M_NOSTART;
53 xfer[1].len = val_size;
54 xfer[1].buf = (void *)val;
55
56 ret = i2c_transfer(i2c->adapter, xfer, 2);
57 if (ret == 2)
58 return 0;
59 if (ret < 0)
60 return ret;
61 else
62 return -EIO;
63}
64
65static int regmap_i2c_read(struct device *dev,
66 const void *reg, size_t reg_size,
67 void *val, size_t val_size)
68{
69 struct i2c_client *i2c = to_i2c_client(dev);
70 struct i2c_msg xfer[2];
71 int ret;
72
73 xfer[0].addr = i2c->addr;
74 xfer[0].flags = 0;
75 xfer[0].len = reg_size;
76 xfer[0].buf = (void *)reg;
77
78 xfer[1].addr = i2c->addr;
79 xfer[1].flags = I2C_M_RD;
80 xfer[1].len = val_size;
81 xfer[1].buf = val;
82
83 ret = i2c_transfer(i2c->adapter, xfer, 2);
84 if (ret == 2)
85 return 0;
86 else if (ret < 0)
87 return ret;
88 else
89 return -EIO;
90}
91
92static struct regmap_bus regmap_i2c = {
93 .type = &i2c_bus_type,
94 .write = regmap_i2c_write,
95 .gather_write = regmap_i2c_gather_write,
96 .read = regmap_i2c_read,
97 .owner = THIS_MODULE,
98};
99
100/**
101 * regmap_init_i2c(): Initialise register map
102 *
103 * @i2c: Device that will be interacted with
104 * @config: Configuration for register map
105 *
106 * The return value will be an ERR_PTR() on error or a valid pointer to
107 * a struct regmap.
108 */
109struct regmap *regmap_init_i2c(struct i2c_client *i2c,
110 const struct regmap_config *config)
111{
112 return regmap_init(&i2c->dev, &regmap_i2c, config);
113}
114EXPORT_SYMBOL_GPL(regmap_init_i2c);
115
diff --git a/include/linux/regmap.h b/include/linux/regmap.h
index a26c1d001401..5ba61f22c703 100644
--- a/include/linux/regmap.h
+++ b/include/linux/regmap.h
@@ -17,6 +17,8 @@
17#include <linux/list.h> 17#include <linux/list.h>
18#include <linux/module.h> 18#include <linux/module.h>
19 19
20struct i2c_client;
21
20struct regmap_config { 22struct regmap_config {
21 int reg_bits; 23 int reg_bits;
22 int val_bits; 24 int val_bits;
@@ -59,6 +61,8 @@ struct regmap_bus {
59struct regmap *regmap_init(struct device *dev, 61struct regmap *regmap_init(struct device *dev,
60 const struct regmap_bus *bus, 62 const struct regmap_bus *bus,
61 const struct regmap_config *config); 63 const struct regmap_config *config);
64struct regmap *regmap_init_i2c(struct i2c_client *i2c,
65 const struct regmap_config *config);
62void regmap_exit(struct regmap *map); 66void regmap_exit(struct regmap *map);
63int regmap_write(struct regmap *map, unsigned int reg, unsigned int val); 67int regmap_write(struct regmap *map, unsigned int reg, unsigned int val);
64int regmap_raw_write(struct regmap *map, unsigned int reg, 68int regmap_raw_write(struct regmap *map, unsigned int reg,