diff options
author | Stephen Warren <swarren@nvidia.com> | 2012-05-24 12:47:26 -0400 |
---|---|---|
committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2012-06-03 08:11:43 -0400 |
commit | 141eba2e006dd8145bed2e49fae3de5af65ab9b0 (patch) | |
tree | d8891499689971466ac978719c45c33d408fd5c5 /drivers/base/regmap | |
parent | f8f5701bdaf9134b1f90e5044a82c66324d2073f (diff) |
regmap: allow busses to request formatting with specific endianness
Add a field to struct regmap_bus that allows bus drivers to request that
register addresses and values be formatted with a specific endianness.
The default endianness is unchanged from current operation: Big.
Implement native endian formatting/parsing for 16- and 32-bit values.
This will be enough to support regmap-mmio.c.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'drivers/base/regmap')
-rw-r--r-- | drivers/base/regmap/regmap.c | 101 |
1 files changed, 90 insertions, 11 deletions
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c index 0bcda488f11c..1cf721421bec 100644 --- a/drivers/base/regmap/regmap.c +++ b/drivers/base/regmap/regmap.c | |||
@@ -119,13 +119,19 @@ static void regmap_format_8(void *buf, unsigned int val, unsigned int shift) | |||
119 | b[0] = val << shift; | 119 | b[0] = val << shift; |
120 | } | 120 | } |
121 | 121 | ||
122 | static void regmap_format_16(void *buf, unsigned int val, unsigned int shift) | 122 | static void regmap_format_16_be(void *buf, unsigned int val, unsigned int shift) |
123 | { | 123 | { |
124 | __be16 *b = buf; | 124 | __be16 *b = buf; |
125 | 125 | ||
126 | b[0] = cpu_to_be16(val << shift); | 126 | b[0] = cpu_to_be16(val << shift); |
127 | } | 127 | } |
128 | 128 | ||
129 | static void regmap_format_16_native(void *buf, unsigned int val, | ||
130 | unsigned int shift) | ||
131 | { | ||
132 | *(u16 *)buf = val << shift; | ||
133 | } | ||
134 | |||
129 | static void regmap_format_24(void *buf, unsigned int val, unsigned int shift) | 135 | static void regmap_format_24(void *buf, unsigned int val, unsigned int shift) |
130 | { | 136 | { |
131 | u8 *b = buf; | 137 | u8 *b = buf; |
@@ -137,13 +143,19 @@ static void regmap_format_24(void *buf, unsigned int val, unsigned int shift) | |||
137 | b[2] = val; | 143 | b[2] = val; |
138 | } | 144 | } |
139 | 145 | ||
140 | static void regmap_format_32(void *buf, unsigned int val, unsigned int shift) | 146 | static void regmap_format_32_be(void *buf, unsigned int val, unsigned int shift) |
141 | { | 147 | { |
142 | __be32 *b = buf; | 148 | __be32 *b = buf; |
143 | 149 | ||
144 | b[0] = cpu_to_be32(val << shift); | 150 | b[0] = cpu_to_be32(val << shift); |
145 | } | 151 | } |
146 | 152 | ||
153 | static void regmap_format_32_native(void *buf, unsigned int val, | ||
154 | unsigned int shift) | ||
155 | { | ||
156 | *(u32 *)buf = val << shift; | ||
157 | } | ||
158 | |||
147 | static unsigned int regmap_parse_8(void *buf) | 159 | static unsigned int regmap_parse_8(void *buf) |
148 | { | 160 | { |
149 | u8 *b = buf; | 161 | u8 *b = buf; |
@@ -151,7 +163,7 @@ static unsigned int regmap_parse_8(void *buf) | |||
151 | return b[0]; | 163 | return b[0]; |
152 | } | 164 | } |
153 | 165 | ||
154 | static unsigned int regmap_parse_16(void *buf) | 166 | static unsigned int regmap_parse_16_be(void *buf) |
155 | { | 167 | { |
156 | __be16 *b = buf; | 168 | __be16 *b = buf; |
157 | 169 | ||
@@ -160,6 +172,11 @@ static unsigned int regmap_parse_16(void *buf) | |||
160 | return b[0]; | 172 | return b[0]; |
161 | } | 173 | } |
162 | 174 | ||
175 | static unsigned int regmap_parse_16_native(void *buf) | ||
176 | { | ||
177 | return *(u16 *)buf; | ||
178 | } | ||
179 | |||
163 | static unsigned int regmap_parse_24(void *buf) | 180 | static unsigned int regmap_parse_24(void *buf) |
164 | { | 181 | { |
165 | u8 *b = buf; | 182 | u8 *b = buf; |
@@ -170,7 +187,7 @@ static unsigned int regmap_parse_24(void *buf) | |||
170 | return ret; | 187 | return ret; |
171 | } | 188 | } |
172 | 189 | ||
173 | static unsigned int regmap_parse_32(void *buf) | 190 | static unsigned int regmap_parse_32_be(void *buf) |
174 | { | 191 | { |
175 | __be32 *b = buf; | 192 | __be32 *b = buf; |
176 | 193 | ||
@@ -179,6 +196,11 @@ static unsigned int regmap_parse_32(void *buf) | |||
179 | return b[0]; | 196 | return b[0]; |
180 | } | 197 | } |
181 | 198 | ||
199 | static unsigned int regmap_parse_32_native(void *buf) | ||
200 | { | ||
201 | return *(u32 *)buf; | ||
202 | } | ||
203 | |||
182 | static void regmap_lock_mutex(struct regmap *map) | 204 | static void regmap_lock_mutex(struct regmap *map) |
183 | { | 205 | { |
184 | mutex_lock(&map->mutex); | 206 | mutex_lock(&map->mutex); |
@@ -227,6 +249,7 @@ struct regmap *regmap_init(struct device *dev, | |||
227 | { | 249 | { |
228 | struct regmap *map, **m; | 250 | struct regmap *map, **m; |
229 | int ret = -EINVAL; | 251 | int ret = -EINVAL; |
252 | enum regmap_endian reg_endian, val_endian; | ||
230 | 253 | ||
231 | if (!bus || !config) | 254 | if (!bus || !config) |
232 | goto err; | 255 | goto err; |
@@ -275,6 +298,18 @@ struct regmap *regmap_init(struct device *dev, | |||
275 | map->read_flag_mask = bus->read_flag_mask; | 298 | map->read_flag_mask = bus->read_flag_mask; |
276 | } | 299 | } |
277 | 300 | ||
301 | reg_endian = config->reg_format_endian; | ||
302 | if (reg_endian == REGMAP_ENDIAN_DEFAULT) | ||
303 | reg_endian = bus->reg_format_endian_default; | ||
304 | if (reg_endian == REGMAP_ENDIAN_DEFAULT) | ||
305 | reg_endian = REGMAP_ENDIAN_BIG; | ||
306 | |||
307 | val_endian = config->val_format_endian; | ||
308 | if (val_endian == REGMAP_ENDIAN_DEFAULT) | ||
309 | val_endian = bus->val_format_endian_default; | ||
310 | if (val_endian == REGMAP_ENDIAN_DEFAULT) | ||
311 | val_endian = REGMAP_ENDIAN_BIG; | ||
312 | |||
278 | switch (config->reg_bits + map->reg_shift) { | 313 | switch (config->reg_bits + map->reg_shift) { |
279 | case 2: | 314 | case 2: |
280 | switch (config->val_bits) { | 315 | switch (config->val_bits) { |
@@ -321,11 +356,29 @@ struct regmap *regmap_init(struct device *dev, | |||
321 | break; | 356 | break; |
322 | 357 | ||
323 | case 16: | 358 | case 16: |
324 | map->format.format_reg = regmap_format_16; | 359 | switch (reg_endian) { |
360 | case REGMAP_ENDIAN_BIG: | ||
361 | map->format.format_reg = regmap_format_16_be; | ||
362 | break; | ||
363 | case REGMAP_ENDIAN_NATIVE: | ||
364 | map->format.format_reg = regmap_format_16_native; | ||
365 | break; | ||
366 | default: | ||
367 | goto err_map; | ||
368 | } | ||
325 | break; | 369 | break; |
326 | 370 | ||
327 | case 32: | 371 | case 32: |
328 | map->format.format_reg = regmap_format_32; | 372 | switch (reg_endian) { |
373 | case REGMAP_ENDIAN_BIG: | ||
374 | map->format.format_reg = regmap_format_32_be; | ||
375 | break; | ||
376 | case REGMAP_ENDIAN_NATIVE: | ||
377 | map->format.format_reg = regmap_format_32_native; | ||
378 | break; | ||
379 | default: | ||
380 | goto err_map; | ||
381 | } | ||
329 | break; | 382 | break; |
330 | 383 | ||
331 | default: | 384 | default: |
@@ -338,21 +391,47 @@ struct regmap *regmap_init(struct device *dev, | |||
338 | map->format.parse_val = regmap_parse_8; | 391 | map->format.parse_val = regmap_parse_8; |
339 | break; | 392 | break; |
340 | case 16: | 393 | case 16: |
341 | map->format.format_val = regmap_format_16; | 394 | switch (val_endian) { |
342 | map->format.parse_val = regmap_parse_16; | 395 | case REGMAP_ENDIAN_BIG: |
396 | map->format.format_val = regmap_format_16_be; | ||
397 | map->format.parse_val = regmap_parse_16_be; | ||
398 | break; | ||
399 | case REGMAP_ENDIAN_NATIVE: | ||
400 | map->format.format_val = regmap_format_16_native; | ||
401 | map->format.parse_val = regmap_parse_16_native; | ||
402 | break; | ||
403 | default: | ||
404 | goto err_map; | ||
405 | } | ||
343 | break; | 406 | break; |
344 | case 24: | 407 | case 24: |
408 | if (val_endian != REGMAP_ENDIAN_BIG) | ||
409 | goto err_map; | ||
345 | map->format.format_val = regmap_format_24; | 410 | map->format.format_val = regmap_format_24; |
346 | map->format.parse_val = regmap_parse_24; | 411 | map->format.parse_val = regmap_parse_24; |
347 | break; | 412 | break; |
348 | case 32: | 413 | case 32: |
349 | map->format.format_val = regmap_format_32; | 414 | switch (val_endian) { |
350 | map->format.parse_val = regmap_parse_32; | 415 | case REGMAP_ENDIAN_BIG: |
416 | map->format.format_val = regmap_format_32_be; | ||
417 | map->format.parse_val = regmap_parse_32_be; | ||
418 | break; | ||
419 | case REGMAP_ENDIAN_NATIVE: | ||
420 | map->format.format_val = regmap_format_32_native; | ||
421 | map->format.parse_val = regmap_parse_32_native; | ||
422 | break; | ||
423 | default: | ||
424 | goto err_map; | ||
425 | } | ||
351 | break; | 426 | break; |
352 | } | 427 | } |
353 | 428 | ||
354 | if (map->format.format_write) | 429 | if (map->format.format_write) { |
430 | if ((reg_endian != REGMAP_ENDIAN_BIG) || | ||
431 | (val_endian != REGMAP_ENDIAN_BIG)) | ||
432 | goto err_map; | ||
355 | map->use_single_rw = true; | 433 | map->use_single_rw = true; |
434 | } | ||
356 | 435 | ||
357 | if (!map->format.format_write && | 436 | if (!map->format.format_write && |
358 | !(map->format.format_reg && map->format.format_val)) | 437 | !(map->format.format_reg && map->format.format_val)) |