xref: /linux/drivers/base/regmap/regmap-i2c.c (revision 60e13231561b3a4c5269bfa1ef6c0569ad6f28ec)
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");
117