]>
Commit | Line | Data |
---|---|---|
9943fa30 MB |
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, ®map_i2c, config); | |
113 | } | |
114 | EXPORT_SYMBOL_GPL(regmap_init_i2c); | |
115 | ||
b33f9cbd | 116 | MODULE_LICENSE("GPL"); |