1 // SPDX-License-Identifier: GPL-2.0+
3 * Copyright (c) 2015 Google, Inc
7 #define LOG_CATEGORY LOGC_DM
12 #include <asm/global_data.h>
13 #include <linux/libfdt.h>
18 #include <dm/of_addr.h>
19 #include <dm/devres.h>
20 #include <linux/ioport.h>
21 #include <linux/compat.h>
22 #include <linux/err.h>
23 #include <linux/bitops.h>
26 * Internal representation of a regmap field. Instead of storing the MSB and
27 * LSB, store the shift and mask. This makes the code a bit cleaner and faster
28 * because the shift and mask don't have to be calculated every time.
31 struct regmap *regmap;
38 DECLARE_GLOBAL_DATA_PTR;
41 * do_range_check() - Control whether range checks are done
43 * Returns: true to do range checks, false to skip
45 * This is used to reduce code size on SPL where range checks are known not to
48 * Add this to the top of the file to enable them: #define LOG_DEBUG
50 static inline bool do_range_check(void)
52 return _LOG_DEBUG || !IS_ENABLED(CONFIG_SPL);
57 * regmap_alloc() - Allocate a regmap with a given number of ranges.
59 * @count: Number of ranges to be allocated for the regmap.
61 * The default regmap width is set to REGMAP_SIZE_32. Callers can override it
64 * Return: A pointer to the newly allocated regmap, or NULL on error.
66 static struct regmap *regmap_alloc(int count)
69 size_t size = sizeof(*map) + sizeof(map->ranges[0]) * count;
71 map = calloc(1, size);
74 map->range_count = count;
75 map->width = REGMAP_SIZE_32;
80 #if CONFIG_IS_ENABLED(OF_PLATDATA)
81 int regmap_init_mem_plat(struct udevice *dev, void *reg, int size, int count,
84 struct regmap_range *range;
87 map = regmap_alloc(count);
91 if (size == sizeof(fdt32_t)) {
92 fdt32_t *ptr = (fdt32_t *)reg;
94 for (range = map->ranges; count > 0;
95 ptr += 2, range++, count--) {
99 } else if (size == sizeof(fdt64_t)) {
100 fdt64_t *ptr = (fdt64_t *)reg;
102 for (range = map->ranges; count > 0;
103 ptr += 2, range++, count--) {
105 range->size = ptr[1];
117 * init_range() - Initialize a single range of a regmap
118 * @node: Device node that will use the map in question
119 * @range: Pointer to a regmap_range structure that will be initialized
120 * @addr_len: The length of the addr parts of the reg property
121 * @size_len: The length of the size parts of the reg property
122 * @index: The index of the range to initialize
124 * This function will read the necessary 'reg' information from the device tree
125 * (the 'addr' part, and the 'length' part), and initialize the range in
128 * Return: 0 if OK, -ve on error
130 static int init_range(ofnode node, struct regmap_range *range, int addr_len,
131 int size_len, int index)
136 if (of_live_active()) {
139 ret = of_address_to_resource(ofnode_to_np(node),
142 debug("%s: Could not read resource of range %d (ret = %d)\n",
143 ofnode_get_name(node), index, ret);
147 range->start = r.start;
148 range->size = r.end - r.start + 1;
150 int offset = ofnode_to_offset(node);
152 range->start = fdtdec_get_addr_size_fixed(gd->fdt_blob, offset,
156 if (range->start == FDT_ADDR_T_NONE) {
157 debug("%s: Could not read start of range %d\n",
158 ofnode_get_name(node), index);
168 int regmap_init_mem_index(ofnode node, struct regmap **mapp, int index)
171 int addr_len, size_len;
174 addr_len = ofnode_read_simple_addr_cells(ofnode_get_parent(node));
176 debug("%s: Error while reading the addr length (ret = %d)\n",
177 ofnode_get_name(node), addr_len);
181 size_len = ofnode_read_simple_size_cells(ofnode_get_parent(node));
183 debug("%s: Error while reading the size length: (ret = %d)\n",
184 ofnode_get_name(node), size_len);
188 map = regmap_alloc(1);
192 ret = init_range(node, map->ranges, addr_len, size_len, index);
196 if (ofnode_read_bool(node, "little-endian"))
197 map->endianness = REGMAP_LITTLE_ENDIAN;
198 else if (ofnode_read_bool(node, "big-endian"))
199 map->endianness = REGMAP_BIG_ENDIAN;
200 else if (ofnode_read_bool(node, "native-endian"))
201 map->endianness = REGMAP_NATIVE_ENDIAN;
202 else /* Default: native endianness */
203 map->endianness = REGMAP_NATIVE_ENDIAN;
214 int regmap_init_mem_range(ofnode node, ulong r_start, ulong r_size,
215 struct regmap **mapp)
218 struct regmap_range *range;
220 map = regmap_alloc(1);
224 range = &map->ranges[0];
225 range->start = r_start;
226 range->size = r_size;
228 if (ofnode_read_bool(node, "little-endian"))
229 map->endianness = REGMAP_LITTLE_ENDIAN;
230 else if (ofnode_read_bool(node, "big-endian"))
231 map->endianness = REGMAP_BIG_ENDIAN;
232 else if (ofnode_read_bool(node, "native-endian"))
233 map->endianness = REGMAP_NATIVE_ENDIAN;
234 else /* Default: native endianness */
235 map->endianness = REGMAP_NATIVE_ENDIAN;
241 int regmap_init_mem(ofnode node, struct regmap **mapp)
243 struct regmap_range *range;
246 int addr_len, size_len, both_len;
251 addr_len = ofnode_read_simple_addr_cells(ofnode_get_parent(node));
253 debug("%s: Error while reading the addr length (ret = %d)\n",
254 ofnode_get_name(node), addr_len);
258 size_len = ofnode_read_simple_size_cells(ofnode_get_parent(node));
260 debug("%s: Error while reading the size length: (ret = %d)\n",
261 ofnode_get_name(node), size_len);
265 both_len = addr_len + size_len;
267 debug("%s: Both addr and size length are zero\n",
268 ofnode_get_name(node));
272 len = ofnode_read_size(node, "reg");
274 debug("%s: Error while reading reg size (ret = %d)\n",
275 ofnode_get_name(node), len);
278 len /= sizeof(fdt32_t);
279 count = len / both_len;
281 debug("%s: Not enough data in reg property\n",
282 ofnode_get_name(node));
286 map = regmap_alloc(count);
290 for (range = map->ranges, index = 0; count > 0;
291 count--, range++, index++) {
292 ret = init_range(node, range, addr_len, size_len, index);
297 if (ofnode_read_bool(node, "little-endian"))
298 map->endianness = REGMAP_LITTLE_ENDIAN;
299 else if (ofnode_read_bool(node, "big-endian"))
300 map->endianness = REGMAP_BIG_ENDIAN;
301 else if (ofnode_read_bool(node, "native-endian"))
302 map->endianness = REGMAP_NATIVE_ENDIAN;
303 else /* Default: native endianness */
304 map->endianness = REGMAP_NATIVE_ENDIAN;
315 static void devm_regmap_release(struct udevice *dev, void *res)
317 regmap_uninit(*(struct regmap **)res);
320 struct regmap *devm_regmap_init(struct udevice *dev,
321 const struct regmap_bus *bus,
323 const struct regmap_config *config)
326 struct regmap **mapp, *map;
328 /* this looks like a leak, but devres takes care of it */
329 mapp = devres_alloc(devm_regmap_release, sizeof(struct regmap *),
332 return ERR_PTR(-ENOMEM);
334 if (config && config->r_size != 0)
335 rc = regmap_init_mem_range(dev_ofnode(dev), config->r_start,
336 config->r_size, mapp);
338 rc = regmap_init_mem(dev_ofnode(dev), mapp);
344 map->width = config->width;
345 map->reg_offset_shift = config->reg_offset_shift;
348 devres_add(dev, mapp);
353 void *regmap_get_range(struct regmap *map, unsigned int range_num)
355 struct regmap_range *range;
357 if (range_num >= map->range_count)
359 range = &map->ranges[range_num];
361 return map_sysmem(range->start, range->size);
364 int regmap_uninit(struct regmap *map)
371 static inline u8 __read_8(u8 *addr, enum regmap_endianness_t endianness)
376 static inline u16 __read_16(u16 *addr, enum regmap_endianness_t endianness)
378 switch (endianness) {
379 case REGMAP_LITTLE_ENDIAN:
380 return in_le16(addr);
381 case REGMAP_BIG_ENDIAN:
382 return in_be16(addr);
383 case REGMAP_NATIVE_ENDIAN:
390 static inline u32 __read_32(u32 *addr, enum regmap_endianness_t endianness)
392 switch (endianness) {
393 case REGMAP_LITTLE_ENDIAN:
394 return in_le32(addr);
395 case REGMAP_BIG_ENDIAN:
396 return in_be32(addr);
397 case REGMAP_NATIVE_ENDIAN:
404 #if defined(in_le64) && defined(in_be64) && defined(readq)
405 static inline u64 __read_64(u64 *addr, enum regmap_endianness_t endianness)
407 switch (endianness) {
408 case REGMAP_LITTLE_ENDIAN:
409 return in_le64(addr);
410 case REGMAP_BIG_ENDIAN:
411 return in_be64(addr);
412 case REGMAP_NATIVE_ENDIAN:
420 int regmap_raw_read_range(struct regmap *map, uint range_num, uint offset,
421 void *valp, size_t val_len)
423 struct regmap_range *range;
426 if (do_range_check() && range_num >= map->range_count) {
427 debug("%s: range index %d larger than range count\n",
428 __func__, range_num);
431 range = &map->ranges[range_num];
433 offset <<= map->reg_offset_shift;
434 if (do_range_check() &&
435 (offset + val_len > range->size || offset + val_len < offset)) {
436 debug("%s: offset/size combination invalid\n", __func__);
440 ptr = map_physmem(range->start + offset, val_len, MAP_NOCACHE);
444 *((u8 *)valp) = __read_8(ptr, map->endianness);
447 *((u16 *)valp) = __read_16(ptr, map->endianness);
450 *((u32 *)valp) = __read_32(ptr, map->endianness);
452 #if defined(in_le64) && defined(in_be64) && defined(readq)
454 *((u64 *)valp) = __read_64(ptr, map->endianness);
458 debug("%s: regmap size %zu unknown\n", __func__, val_len);
465 int regmap_raw_read(struct regmap *map, uint offset, void *valp, size_t val_len)
467 return regmap_raw_read_range(map, 0, offset, valp, val_len);
470 int regmap_read(struct regmap *map, uint offset, uint *valp)
480 res = regmap_raw_read(map, offset, &u, map->width);
484 switch (map->width) {
504 static inline void __write_8(u8 *addr, const u8 *val,
505 enum regmap_endianness_t endianness)
510 static inline void __write_16(u16 *addr, const u16 *val,
511 enum regmap_endianness_t endianness)
513 switch (endianness) {
514 case REGMAP_NATIVE_ENDIAN:
517 case REGMAP_LITTLE_ENDIAN:
518 out_le16(addr, *val);
520 case REGMAP_BIG_ENDIAN:
521 out_be16(addr, *val);
526 static inline void __write_32(u32 *addr, const u32 *val,
527 enum regmap_endianness_t endianness)
529 switch (endianness) {
530 case REGMAP_NATIVE_ENDIAN:
533 case REGMAP_LITTLE_ENDIAN:
534 out_le32(addr, *val);
536 case REGMAP_BIG_ENDIAN:
537 out_be32(addr, *val);
542 #if defined(out_le64) && defined(out_be64) && defined(writeq)
543 static inline void __write_64(u64 *addr, const u64 *val,
544 enum regmap_endianness_t endianness)
546 switch (endianness) {
547 case REGMAP_NATIVE_ENDIAN:
550 case REGMAP_LITTLE_ENDIAN:
551 out_le64(addr, *val);
553 case REGMAP_BIG_ENDIAN:
554 out_be64(addr, *val);
560 int regmap_raw_write_range(struct regmap *map, uint range_num, uint offset,
561 const void *val, size_t val_len)
563 struct regmap_range *range;
566 if (range_num >= map->range_count) {
567 debug("%s: range index %d larger than range count\n",
568 __func__, range_num);
571 range = &map->ranges[range_num];
573 offset <<= map->reg_offset_shift;
574 if (offset + val_len > range->size || offset + val_len < offset) {
575 debug("%s: offset/size combination invalid\n", __func__);
579 ptr = map_physmem(range->start + offset, val_len, MAP_NOCACHE);
583 __write_8(ptr, val, map->endianness);
586 __write_16(ptr, val, map->endianness);
589 __write_32(ptr, val, map->endianness);
591 #if defined(out_le64) && defined(out_be64) && defined(writeq)
593 __write_64(ptr, val, map->endianness);
597 debug("%s: regmap size %zu unknown\n", __func__, val_len);
604 int regmap_raw_write(struct regmap *map, uint offset, const void *val,
607 return regmap_raw_write_range(map, 0, offset, val, val_len);
610 int regmap_write(struct regmap *map, uint offset, uint val)
619 switch (map->width) {
633 debug("%s: regmap size %zu unknown\n", __func__,
638 return regmap_raw_write(map, offset, &u, map->width);
641 int regmap_update_bits(struct regmap *map, uint offset, uint mask, uint val)
646 ret = regmap_read(map, offset, ®);
652 return regmap_write(map, offset, reg | (val & mask));
655 int regmap_field_read(struct regmap_field *field, unsigned int *val)
658 unsigned int reg_val;
660 ret = regmap_read(field->regmap, field->reg, ®_val);
664 reg_val &= field->mask;
665 reg_val >>= field->shift;
671 int regmap_field_write(struct regmap_field *field, unsigned int val)
673 return regmap_update_bits(field->regmap, field->reg, field->mask,
674 val << field->shift);
677 static void regmap_field_init(struct regmap_field *rm_field,
678 struct regmap *regmap,
679 struct reg_field reg_field)
681 rm_field->regmap = regmap;
682 rm_field->reg = reg_field.reg;
683 rm_field->shift = reg_field.lsb;
684 rm_field->mask = GENMASK(reg_field.msb, reg_field.lsb);
687 struct regmap_field *devm_regmap_field_alloc(struct udevice *dev,
688 struct regmap *regmap,
689 struct reg_field reg_field)
691 struct regmap_field *rm_field = devm_kzalloc(dev, sizeof(*rm_field),
694 return ERR_PTR(-ENOMEM);
696 regmap_field_init(rm_field, regmap, reg_field);
701 void devm_regmap_field_free(struct udevice *dev, struct regmap_field *field)
703 devm_kfree(dev, field);
706 struct regmap_field *regmap_field_alloc(struct regmap *regmap,
707 struct reg_field reg_field)
709 struct regmap_field *rm_field = kzalloc(sizeof(*rm_field), GFP_KERNEL);
712 return ERR_PTR(-ENOMEM);
714 regmap_field_init(rm_field, regmap, reg_field);
719 void regmap_field_free(struct regmap_field *field)