diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-04-01 19:13:21 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-04-01 19:13:21 -0400 |
commit | 675c354a95d5375153b8bb80a0448cab916c7991 (patch) | |
tree | 88cbc5a5a31dd1c1016271006a8d56cfe0abf7bd /drivers/base | |
parent | c70929147a10fa4538886cb23b934b509c4c0e49 (diff) | |
parent | 1b3fa22e0234d613df967445cd34807e10fa54fa (diff) |
Merge tag 'char-misc-3.15-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc
Pull char/misc driver patches from Greg KH:
"Here's the big char/misc driver updates for 3.15-rc1.
Lots of various things here, including the new mcb driver subsystem.
All of these have been in linux-next for a while"
* tag 'char-misc-3.15-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc: (118 commits)
extcon: Move OF helper function to extcon core and change function name
extcon: of: Remove unnecessary function call by using the name of device_node
extcon: gpio: Use SIMPLE_DEV_PM_OPS macro
extcon: palmas: Use SIMPLE_DEV_PM_OPS macro
mei: don't use deprecated DEFINE_PCI_DEVICE_TABLE macro
mei: amthif: fix checkpatch error
mei: client.h fix checkpatch errors
mei: use cl_dbg where appropriate
mei: fix Unnecessary space after function pointer name
mei: report consistently copy_from/to_user failures
mei: drop pr_fmt macros
mei: make me hw headers private to me hw.
mei: fix memory leak of pending write cb objects
mei: me: do not reset when less than expected data is received
drivers: mcb: Fix build error discovered by 0-day bot
cs5535-mfgpt: Simplify dependencies
spmi: pm: drop bus-level PM suspend/resume routines
spmi: pmic_arb: make selectable on ARCH_QCOM
Drivers: hv: vmbus: Increase the limit on the number of pfns we can handle
pch_phub: Report error writing MAC back to user
...
Diffstat (limited to 'drivers/base')
-rw-r--r-- | drivers/base/regmap/regmap-spmi.c | 228 |
1 files changed, 197 insertions, 31 deletions
diff --git a/drivers/base/regmap/regmap-spmi.c b/drivers/base/regmap/regmap-spmi.c index ac2391013db1..d7026dc33388 100644 --- a/drivers/base/regmap/regmap-spmi.c +++ b/drivers/base/regmap/regmap-spmi.c | |||
@@ -22,69 +22,235 @@ | |||
22 | #include <linux/module.h> | 22 | #include <linux/module.h> |
23 | #include <linux/init.h> | 23 | #include <linux/init.h> |
24 | 24 | ||
25 | static int regmap_spmi_read(void *context, | 25 | static int regmap_spmi_base_read(void *context, |
26 | const void *reg, size_t reg_size, | 26 | const void *reg, size_t reg_size, |
27 | void *val, size_t val_size) | 27 | void *val, size_t val_size) |
28 | { | 28 | { |
29 | u8 addr = *(u8 *)reg; | ||
30 | int err = 0; | ||
31 | |||
32 | BUG_ON(reg_size != 1); | ||
33 | |||
34 | while (val_size-- && !err) | ||
35 | err = spmi_register_read(context, addr++, val++); | ||
36 | |||
37 | return err; | ||
38 | } | ||
39 | |||
40 | static int regmap_spmi_base_gather_write(void *context, | ||
41 | const void *reg, size_t reg_size, | ||
42 | const void *val, size_t val_size) | ||
43 | { | ||
44 | const u8 *data = val; | ||
45 | u8 addr = *(u8 *)reg; | ||
46 | int err = 0; | ||
47 | |||
48 | BUG_ON(reg_size != 1); | ||
49 | |||
50 | /* | ||
51 | * SPMI defines a more bandwidth-efficient 'Register 0 Write' sequence, | ||
52 | * use it when possible. | ||
53 | */ | ||
54 | if (addr == 0 && val_size) { | ||
55 | err = spmi_register_zero_write(context, *data); | ||
56 | if (err) | ||
57 | goto err_out; | ||
58 | |||
59 | data++; | ||
60 | addr++; | ||
61 | val_size--; | ||
62 | } | ||
63 | |||
64 | while (val_size) { | ||
65 | err = spmi_register_write(context, addr, *data); | ||
66 | if (err) | ||
67 | goto err_out; | ||
68 | |||
69 | data++; | ||
70 | addr++; | ||
71 | val_size--; | ||
72 | } | ||
73 | |||
74 | err_out: | ||
75 | return err; | ||
76 | } | ||
77 | |||
78 | static int regmap_spmi_base_write(void *context, const void *data, | ||
79 | size_t count) | ||
80 | { | ||
81 | BUG_ON(count < 1); | ||
82 | return regmap_spmi_base_gather_write(context, data, 1, data + 1, | ||
83 | count - 1); | ||
84 | } | ||
85 | |||
86 | static struct regmap_bus regmap_spmi_base = { | ||
87 | .read = regmap_spmi_base_read, | ||
88 | .write = regmap_spmi_base_write, | ||
89 | .gather_write = regmap_spmi_base_gather_write, | ||
90 | .reg_format_endian_default = REGMAP_ENDIAN_NATIVE, | ||
91 | .val_format_endian_default = REGMAP_ENDIAN_NATIVE, | ||
92 | }; | ||
93 | |||
94 | /** | ||
95 | * regmap_init_spmi_base(): Create regmap for the Base register space | ||
96 | * @sdev: SPMI device that will be interacted with | ||
97 | * @config: Configuration for register map | ||
98 | * | ||
99 | * The return value will be an ERR_PTR() on error or a valid pointer to | ||
100 | * a struct regmap. | ||
101 | */ | ||
102 | struct regmap *regmap_init_spmi_base(struct spmi_device *sdev, | ||
103 | const struct regmap_config *config) | ||
104 | { | ||
105 | return regmap_init(&sdev->dev, ®map_spmi_base, sdev, config); | ||
106 | } | ||
107 | EXPORT_SYMBOL_GPL(regmap_init_spmi_base); | ||
108 | |||
109 | /** | ||
110 | * devm_regmap_init_spmi_base(): Create managed regmap for Base register space | ||
111 | * @sdev: SPMI device that will be interacted with | ||
112 | * @config: Configuration for register map | ||
113 | * | ||
114 | * The return value will be an ERR_PTR() on error or a valid pointer | ||
115 | * to a struct regmap. The regmap will be automatically freed by the | ||
116 | * device management code. | ||
117 | */ | ||
118 | struct regmap *devm_regmap_init_spmi_base(struct spmi_device *sdev, | ||
119 | const struct regmap_config *config) | ||
120 | { | ||
121 | return devm_regmap_init(&sdev->dev, ®map_spmi_base, sdev, config); | ||
122 | } | ||
123 | EXPORT_SYMBOL_GPL(devm_regmap_init_spmi_base); | ||
124 | |||
125 | static int regmap_spmi_ext_read(void *context, | ||
126 | const void *reg, size_t reg_size, | ||
127 | void *val, size_t val_size) | ||
128 | { | ||
129 | int err = 0; | ||
130 | size_t len; | ||
131 | u16 addr; | ||
132 | |||
29 | BUG_ON(reg_size != 2); | 133 | BUG_ON(reg_size != 2); |
30 | return spmi_ext_register_readl(context, *(u16 *)reg, | 134 | |
31 | val, val_size); | 135 | addr = *(u16 *)reg; |
136 | |||
137 | /* | ||
138 | * Split accesses into two to take advantage of the more | ||
139 | * bandwidth-efficient 'Extended Register Read' command when possible | ||
140 | */ | ||
141 | while (addr <= 0xFF && val_size) { | ||
142 | len = min_t(size_t, val_size, 16); | ||
143 | |||
144 | err = spmi_ext_register_read(context, addr, val, len); | ||
145 | if (err) | ||
146 | goto err_out; | ||
147 | |||
148 | addr += len; | ||
149 | val += len; | ||
150 | val_size -= len; | ||
151 | } | ||
152 | |||
153 | while (val_size) { | ||
154 | len = min_t(size_t, val_size, 8); | ||
155 | |||
156 | err = spmi_ext_register_readl(context, addr, val, val_size); | ||
157 | if (err) | ||
158 | goto err_out; | ||
159 | |||
160 | addr += len; | ||
161 | val += len; | ||
162 | val_size -= len; | ||
163 | } | ||
164 | |||
165 | err_out: | ||
166 | return err; | ||
32 | } | 167 | } |
33 | 168 | ||
34 | static int regmap_spmi_gather_write(void *context, | 169 | static int regmap_spmi_ext_gather_write(void *context, |
35 | const void *reg, size_t reg_size, | 170 | const void *reg, size_t reg_size, |
36 | const void *val, size_t val_size) | 171 | const void *val, size_t val_size) |
37 | { | 172 | { |
173 | int err = 0; | ||
174 | size_t len; | ||
175 | u16 addr; | ||
176 | |||
38 | BUG_ON(reg_size != 2); | 177 | BUG_ON(reg_size != 2); |
39 | return spmi_ext_register_writel(context, *(u16 *)reg, val, val_size); | 178 | |
179 | addr = *(u16 *)reg; | ||
180 | |||
181 | while (addr <= 0xFF && val_size) { | ||
182 | len = min_t(size_t, val_size, 16); | ||
183 | |||
184 | err = spmi_ext_register_write(context, addr, val, len); | ||
185 | if (err) | ||
186 | goto err_out; | ||
187 | |||
188 | addr += len; | ||
189 | val += len; | ||
190 | val_size -= len; | ||
191 | } | ||
192 | |||
193 | while (val_size) { | ||
194 | len = min_t(size_t, val_size, 8); | ||
195 | |||
196 | err = spmi_ext_register_writel(context, addr, val, len); | ||
197 | if (err) | ||
198 | goto err_out; | ||
199 | |||
200 | addr += len; | ||
201 | val += len; | ||
202 | val_size -= len; | ||
203 | } | ||
204 | |||
205 | err_out: | ||
206 | return err; | ||
40 | } | 207 | } |
41 | 208 | ||
42 | static int regmap_spmi_write(void *context, const void *data, | 209 | static int regmap_spmi_ext_write(void *context, const void *data, |
43 | size_t count) | 210 | size_t count) |
44 | { | 211 | { |
45 | BUG_ON(count < 2); | 212 | BUG_ON(count < 2); |
46 | return regmap_spmi_gather_write(context, data, 2, data + 2, count - 2); | 213 | return regmap_spmi_ext_gather_write(context, data, 2, data + 2, |
214 | count - 2); | ||
47 | } | 215 | } |
48 | 216 | ||
49 | static struct regmap_bus regmap_spmi = { | 217 | static struct regmap_bus regmap_spmi_ext = { |
50 | .read = regmap_spmi_read, | 218 | .read = regmap_spmi_ext_read, |
51 | .write = regmap_spmi_write, | 219 | .write = regmap_spmi_ext_write, |
52 | .gather_write = regmap_spmi_gather_write, | 220 | .gather_write = regmap_spmi_ext_gather_write, |
53 | .reg_format_endian_default = REGMAP_ENDIAN_NATIVE, | 221 | .reg_format_endian_default = REGMAP_ENDIAN_NATIVE, |
54 | .val_format_endian_default = REGMAP_ENDIAN_NATIVE, | 222 | .val_format_endian_default = REGMAP_ENDIAN_NATIVE, |
55 | }; | 223 | }; |
56 | 224 | ||
57 | /** | 225 | /** |
58 | * regmap_init_spmi(): Initialize register map | 226 | * regmap_init_spmi_ext(): Create regmap for Ext register space |
59 | * | 227 | * @sdev: Device that will be interacted with |
60 | * @sdev: Device that will be interacted with | 228 | * @config: Configuration for register map |
61 | * @config: Configuration for register map | ||
62 | * | 229 | * |
63 | * The return value will be an ERR_PTR() on error or a valid pointer to | 230 | * The return value will be an ERR_PTR() on error or a valid pointer to |
64 | * a struct regmap. | 231 | * a struct regmap. |
65 | */ | 232 | */ |
66 | struct regmap *regmap_init_spmi(struct spmi_device *sdev, | 233 | struct regmap *regmap_init_spmi_ext(struct spmi_device *sdev, |
67 | const struct regmap_config *config) | 234 | const struct regmap_config *config) |
68 | { | 235 | { |
69 | return regmap_init(&sdev->dev, ®map_spmi, sdev, config); | 236 | return regmap_init(&sdev->dev, ®map_spmi_ext, sdev, config); |
70 | } | 237 | } |
71 | EXPORT_SYMBOL_GPL(regmap_init_spmi); | 238 | EXPORT_SYMBOL_GPL(regmap_init_spmi_ext); |
72 | 239 | ||
73 | /** | 240 | /** |
74 | * devm_regmap_init_spmi(): Initialise managed register map | 241 | * devm_regmap_init_spmi_ext(): Create managed regmap for Ext register space |
75 | * | 242 | * @sdev: SPMI device that will be interacted with |
76 | * @sdev: Device that will be interacted with | 243 | * @config: Configuration for register map |
77 | * @config: Configuration for register map | ||
78 | * | 244 | * |
79 | * The return value will be an ERR_PTR() on error or a valid pointer | 245 | * The return value will be an ERR_PTR() on error or a valid pointer |
80 | * to a struct regmap. The regmap will be automatically freed by the | 246 | * to a struct regmap. The regmap will be automatically freed by the |
81 | * device management code. | 247 | * device management code. |
82 | */ | 248 | */ |
83 | struct regmap *devm_regmap_init_spmi(struct spmi_device *sdev, | 249 | struct regmap *devm_regmap_init_spmi_ext(struct spmi_device *sdev, |
84 | const struct regmap_config *config) | 250 | const struct regmap_config *config) |
85 | { | 251 | { |
86 | return devm_regmap_init(&sdev->dev, ®map_spmi, sdev, config); | 252 | return devm_regmap_init(&sdev->dev, ®map_spmi_ext, sdev, config); |
87 | } | 253 | } |
88 | EXPORT_SYMBOL_GPL(devm_regmap_init_spmi); | 254 | EXPORT_SYMBOL_GPL(devm_regmap_init_spmi_ext); |
89 | 255 | ||
90 | MODULE_LICENSE("GPL"); | 256 | MODULE_LICENSE("GPL"); |