xref: /rk3399_rockchip-uboot/drivers/core/regmap.c (revision a951431e827cfd862a4c095e85e8650a6b8370f7)
16f98b750SSimon Glass /*
26f98b750SSimon Glass  * Copyright (c) 2015 Google, Inc
36f98b750SSimon Glass  * Written by Simon Glass <sjg@chromium.org>
46f98b750SSimon Glass  *
56f98b750SSimon Glass  * SPDX-License-Identifier:	GPL-2.0+
66f98b750SSimon Glass  */
76f98b750SSimon Glass 
86f98b750SSimon Glass #include <common.h>
96f98b750SSimon Glass #include <dm.h>
106f98b750SSimon Glass #include <errno.h>
116f98b750SSimon Glass #include <libfdt.h>
126f98b750SSimon Glass #include <malloc.h>
136f98b750SSimon Glass #include <mapmem.h>
146f98b750SSimon Glass #include <regmap.h>
156f98b750SSimon Glass 
166f98b750SSimon Glass DECLARE_GLOBAL_DATA_PTR;
176f98b750SSimon Glass 
18*a951431eSSimon Glass static struct regmap *regmap_alloc_count(int count)
19*a951431eSSimon Glass {
20*a951431eSSimon Glass 	struct regmap *map;
21*a951431eSSimon Glass 
22*a951431eSSimon Glass 	map = malloc(sizeof(struct regmap));
23*a951431eSSimon Glass 	if (!map)
24*a951431eSSimon Glass 		return NULL;
25*a951431eSSimon Glass 	if (count <= 1) {
26*a951431eSSimon Glass 		map->range = &map->base_range;
27*a951431eSSimon Glass 	} else {
28*a951431eSSimon Glass 		map->range = malloc(count * sizeof(struct regmap_range));
29*a951431eSSimon Glass 		if (!map->range) {
30*a951431eSSimon Glass 			free(map);
31*a951431eSSimon Glass 			return NULL;
32*a951431eSSimon Glass 		}
33*a951431eSSimon Glass 	}
34*a951431eSSimon Glass 	map->range_count = count;
35*a951431eSSimon Glass 
36*a951431eSSimon Glass 	return map;
37*a951431eSSimon Glass }
38*a951431eSSimon Glass 
393b2a29e0SSimon Glass #if CONFIG_IS_ENABLED(OF_PLATDATA)
403b2a29e0SSimon Glass int regmap_init_mem_platdata(struct udevice *dev, fdt32_t *reg, int size,
413b2a29e0SSimon Glass 			     struct regmap **mapp)
423b2a29e0SSimon Glass {
433b2a29e0SSimon Glass 	/* TODO(sjg@chromium.org): Implement this when needed */
443b2a29e0SSimon Glass 	return 0;
453b2a29e0SSimon Glass }
463b2a29e0SSimon Glass #else
476f98b750SSimon Glass int regmap_init_mem(struct udevice *dev, struct regmap **mapp)
486f98b750SSimon Glass {
496f98b750SSimon Glass 	const void *blob = gd->fdt_blob;
506f98b750SSimon Glass 	struct regmap_range *range;
516f98b750SSimon Glass 	const fdt32_t *cell;
526f98b750SSimon Glass 	struct regmap *map;
536f98b750SSimon Glass 	int count;
546f98b750SSimon Glass 	int addr_len, size_len, both_len;
556f98b750SSimon Glass 	int parent;
566f98b750SSimon Glass 	int len;
576f98b750SSimon Glass 
586f98b750SSimon Glass 	parent = dev->parent->of_offset;
596f98b750SSimon Glass 	addr_len = fdt_address_cells(blob, parent);
606f98b750SSimon Glass 	size_len = fdt_size_cells(blob, parent);
616f98b750SSimon Glass 	both_len = addr_len + size_len;
626f98b750SSimon Glass 
636f98b750SSimon Glass 	cell = fdt_getprop(blob, dev->of_offset, "reg", &len);
646f98b750SSimon Glass 	len /= sizeof(*cell);
656f98b750SSimon Glass 	count = len / both_len;
666f98b750SSimon Glass 	if (!cell || !count)
676f98b750SSimon Glass 		return -EINVAL;
686f98b750SSimon Glass 
69*a951431eSSimon Glass 	map = regmap_alloc_count(count);
706f98b750SSimon Glass 	if (!map)
716f98b750SSimon Glass 		return -ENOMEM;
726f98b750SSimon Glass 
736f98b750SSimon Glass 	map->base = fdtdec_get_number(cell, addr_len);
746f98b750SSimon Glass 
756f98b750SSimon Glass 	for (range = map->range; count > 0;
766f98b750SSimon Glass 	     count--, cell += both_len, range++) {
776f98b750SSimon Glass 		range->start = fdtdec_get_number(cell, addr_len);
786f98b750SSimon Glass 		range->size = fdtdec_get_number(cell + addr_len, size_len);
796f98b750SSimon Glass 	}
806f98b750SSimon Glass 
816f98b750SSimon Glass 	*mapp = map;
826f98b750SSimon Glass 
836f98b750SSimon Glass 	return 0;
846f98b750SSimon Glass }
853b2a29e0SSimon Glass #endif
866f98b750SSimon Glass 
876f98b750SSimon Glass void *regmap_get_range(struct regmap *map, unsigned int range_num)
886f98b750SSimon Glass {
896f98b750SSimon Glass 	struct regmap_range *range;
906f98b750SSimon Glass 
916f98b750SSimon Glass 	if (range_num >= map->range_count)
926f98b750SSimon Glass 		return NULL;
936f98b750SSimon Glass 	range = &map->range[range_num];
946f98b750SSimon Glass 
956f98b750SSimon Glass 	return map_sysmem(range->start, range->size);
966f98b750SSimon Glass }
976f98b750SSimon Glass 
986f98b750SSimon Glass int regmap_uninit(struct regmap *map)
996f98b750SSimon Glass {
1006f98b750SSimon Glass 	if (map->range_count > 1)
1016f98b750SSimon Glass 		free(map->range);
1026f98b750SSimon Glass 	free(map);
1036f98b750SSimon Glass 
1046f98b750SSimon Glass 	return 0;
1056f98b750SSimon Glass }
106