aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMario Six2018-10-15 02:24:14 -0500
committerSimon Glass2018-11-14 11:16:27 -0600
commit9b77fe3b80b038af7114f7dae4934773bb026f8e (patch)
tree81d0fa83f731c7e56df5b93955e58a1bb0d7592f /drivers
parent45ef7f55c79f67be8bf0b4e6de549269c1fd4971 (diff)
downloadu-boot-9b77fe3b80b038af7114f7dae4934773bb026f8e.tar.gz
u-boot-9b77fe3b80b038af7114f7dae4934773bb026f8e.tar.xz
u-boot-9b77fe3b80b038af7114f7dae4934773bb026f8e.zip
regmap: Add endianness support
Add support for switching the endianness of regmap accesses via the "little-endian", "big-endian", and "native-endian" boolean properties in the device tree. The default endianness is native endianness. Signed-off-by: Mario Six <mario.six@gdsys.cc> Reviewed-by: Simon Glass <sjg@chromium.org> Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/core/regmap.c134
1 files changed, 124 insertions, 10 deletions
diff --git a/drivers/core/regmap.c b/drivers/core/regmap.c
index 9b2e02af2e..5ef0f71c8b 100644
--- a/drivers/core/regmap.c
+++ b/drivers/core/regmap.c
@@ -164,6 +164,15 @@ int regmap_init_mem(ofnode node, struct regmap **mapp)
164 return ret; 164 return ret;
165 } 165 }
166 166
167 if (ofnode_read_bool(node, "little-endian"))
168 map->endianness = REGMAP_LITTLE_ENDIAN;
169 else if (ofnode_read_bool(node, "big-endian"))
170 map->endianness = REGMAP_BIG_ENDIAN;
171 else if (ofnode_read_bool(node, "native-endian"))
172 map->endianness = REGMAP_NATIVE_ENDIAN;
173 else /* Default: native endianness */
174 map->endianness = REGMAP_NATIVE_ENDIAN;
175
167 *mapp = map; 176 *mapp = map;
168 177
169 return 0; 178 return 0;
@@ -188,6 +197,55 @@ int regmap_uninit(struct regmap *map)
188 return 0; 197 return 0;
189} 198}
190 199
200static inline u8 __read_8(u8 *addr, enum regmap_endianness_t endianness)
201{
202 return readb(addr);
203}
204
205static inline u16 __read_16(u16 *addr, enum regmap_endianness_t endianness)
206{
207 switch (endianness) {
208 case REGMAP_LITTLE_ENDIAN:
209 return in_le16(addr);
210 case REGMAP_BIG_ENDIAN:
211 return in_be16(addr);
212 case REGMAP_NATIVE_ENDIAN:
213 return readw(addr);
214 }
215
216 return readw(addr);
217}
218
219static inline u32 __read_32(u32 *addr, enum regmap_endianness_t endianness)
220{
221 switch (endianness) {
222 case REGMAP_LITTLE_ENDIAN:
223 return in_le32(addr);
224 case REGMAP_BIG_ENDIAN:
225 return in_be32(addr);
226 case REGMAP_NATIVE_ENDIAN:
227 return readl(addr);
228 }
229
230 return readl(addr);
231}
232
233#if defined(in_le64) && defined(in_be64) && defined(readq)
234static inline u64 __read_64(u64 *addr, enum regmap_endianness_t endianness)
235{
236 switch (endianness) {
237 case REGMAP_LITTLE_ENDIAN:
238 return in_le64(addr);
239 case REGMAP_BIG_ENDIAN:
240 return in_be64(addr);
241 case REGMAP_NATIVE_ENDIAN:
242 return readq(addr);
243 }
244
245 return readq(addr);
246}
247#endif
248
191int regmap_raw_read_range(struct regmap *map, uint range_num, uint offset, 249int regmap_raw_read_range(struct regmap *map, uint range_num, uint offset,
192 void *valp, size_t val_len) 250 void *valp, size_t val_len)
193{ 251{
@@ -210,17 +268,17 @@ int regmap_raw_read_range(struct regmap *map, uint range_num, uint offset,
210 268
211 switch (val_len) { 269 switch (val_len) {
212 case REGMAP_SIZE_8: 270 case REGMAP_SIZE_8:
213 *((u8 *)valp) = readb((u8 *)ptr); 271 *((u8 *)valp) = __read_8(ptr, map->endianness);
214 break; 272 break;
215 case REGMAP_SIZE_16: 273 case REGMAP_SIZE_16:
216 *((u16 *)valp) = readw((u16 *)ptr); 274 *((u16 *)valp) = __read_16(ptr, map->endianness);
217 break; 275 break;
218 case REGMAP_SIZE_32: 276 case REGMAP_SIZE_32:
219 *((u32 *)valp) = readl((u32 *)ptr); 277 *((u32 *)valp) = __read_32(ptr, map->endianness);
220 break; 278 break;
221#if defined(readq) 279#if defined(in_le64) && defined(in_be64) && defined(readq)
222 case REGMAP_SIZE_64: 280 case REGMAP_SIZE_64:
223 *((u64 *)valp) = readq((u64 *)ptr); 281 *((u64 *)valp) = __read_64(ptr, map->endianness);
224 break; 282 break;
225#endif 283#endif
226 default: 284 default:
@@ -241,6 +299,62 @@ int regmap_read(struct regmap *map, uint offset, uint *valp)
241 return regmap_raw_read(map, offset, valp, REGMAP_SIZE_32); 299 return regmap_raw_read(map, offset, valp, REGMAP_SIZE_32);
242} 300}
243 301
302static inline void __write_8(u8 *addr, const u8 *val,
303 enum regmap_endianness_t endianness)
304{
305 writeb(*val, addr);
306}
307
308static inline void __write_16(u16 *addr, const u16 *val,
309 enum regmap_endianness_t endianness)
310{
311 switch (endianness) {
312 case REGMAP_NATIVE_ENDIAN:
313 writew(*val, addr);
314 break;
315 case REGMAP_LITTLE_ENDIAN:
316 out_le16(addr, *val);
317 break;
318 case REGMAP_BIG_ENDIAN:
319 out_be16(addr, *val);
320 break;
321 }
322}
323
324static inline void __write_32(u32 *addr, const u32 *val,
325 enum regmap_endianness_t endianness)
326{
327 switch (endianness) {
328 case REGMAP_NATIVE_ENDIAN:
329 writel(*val, addr);
330 break;
331 case REGMAP_LITTLE_ENDIAN:
332 out_le32(addr, *val);
333 break;
334 case REGMAP_BIG_ENDIAN:
335 out_be32(addr, *val);
336 break;
337 }
338}
339
340#if defined(out_le64) && defined(out_be64) && defined(writeq)
341static inline void __write_64(u64 *addr, const u64 *val,
342 enum regmap_endianness_t endianness)
343{
344 switch (endianness) {
345 case REGMAP_NATIVE_ENDIAN:
346 writeq(*val, addr);
347 break;
348 case REGMAP_LITTLE_ENDIAN:
349 out_le64(addr, *val);
350 break;
351 case REGMAP_BIG_ENDIAN:
352 out_be64(addr, *val);
353 break;
354 }
355}
356#endif
357
244int regmap_raw_write_range(struct regmap *map, uint range_num, uint offset, 358int regmap_raw_write_range(struct regmap *map, uint range_num, uint offset,
245 const void *val, size_t val_len) 359 const void *val, size_t val_len)
246{ 360{
@@ -263,17 +377,17 @@ int regmap_raw_write_range(struct regmap *map, uint range_num, uint offset,
263 377
264 switch (val_len) { 378 switch (val_len) {
265 case REGMAP_SIZE_8: 379 case REGMAP_SIZE_8:
266 writeb(*((u8 *)val), (u8 *)ptr); 380 __write_8(ptr, val, map->endianness);
267 break; 381 break;
268 case REGMAP_SIZE_16: 382 case REGMAP_SIZE_16:
269 writew(*((u16 *)val), (u16 *)ptr); 383 __write_16(ptr, val, map->endianness);
270 break; 384 break;
271 case REGMAP_SIZE_32: 385 case REGMAP_SIZE_32:
272 writel(*((u32 *)val), (u32 *)ptr); 386 __write_32(ptr, val, map->endianness);
273 break; 387 break;
274#if defined(writeq) 388#if defined(out_le64) && defined(out_be64) && defined(writeq)
275 case REGMAP_SIZE_64: 389 case REGMAP_SIZE_64:
276 writeq(*((u64 *)val), (u64 *)ptr); 390 __write_64(ptr, val, map->endianness);
277 break; 391 break;
278#endif 392#endif
279 default: 393 default: