Merge branch 'master' of git://git.infradead.org/users/linville/wireless-next into...
[pandora-kernel.git] / drivers / base / regmap / regmap-i2c.c
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
18 static 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
32 static 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
65 static 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
92 static 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  */
109 struct 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 }
114 EXPORT_SYMBOL_GPL(regmap_init_i2c);
115
116 MODULE_LICENSE("GPL");