aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/base/regmap
diff options
context:
space:
mode:
authorStephen Warren <swarren@nvidia.com>2012-05-24 12:47:26 -0400
committerMark Brown <broonie@opensource.wolfsonmicro.com>2012-06-03 08:11:43 -0400
commit141eba2e006dd8145bed2e49fae3de5af65ab9b0 (patch)
treed8891499689971466ac978719c45c33d408fd5c5 /drivers/base/regmap
parentf8f5701bdaf9134b1f90e5044a82c66324d2073f (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.c101
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
122static void regmap_format_16(void *buf, unsigned int val, unsigned int shift) 122static 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
129static void regmap_format_16_native(void *buf, unsigned int val,
130 unsigned int shift)
131{
132 *(u16 *)buf = val << shift;
133}
134
129static void regmap_format_24(void *buf, unsigned int val, unsigned int shift) 135static 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
140static void regmap_format_32(void *buf, unsigned int val, unsigned int shift) 146static 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
153static void regmap_format_32_native(void *buf, unsigned int val,
154 unsigned int shift)
155{
156 *(u32 *)buf = val << shift;
157}
158
147static unsigned int regmap_parse_8(void *buf) 159static 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
154static unsigned int regmap_parse_16(void *buf) 166static 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
175static unsigned int regmap_parse_16_native(void *buf)
176{
177 return *(u16 *)buf;
178}
179
163static unsigned int regmap_parse_24(void *buf) 180static 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
173static unsigned int regmap_parse_32(void *buf) 190static 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
199static unsigned int regmap_parse_32_native(void *buf)
200{
201 return *(u32 *)buf;
202}
203
182static void regmap_lock_mutex(struct regmap *map) 204static 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))