xref: /rk3399_rockchip-uboot/drivers/core/regmap.c (revision 3b2a29e0971397085c616c89a3a09f2609f50ca4)
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*3b2a29e0SSimon Glass #if CONFIG_IS_ENABLED(OF_PLATDATA)
19*3b2a29e0SSimon Glass int regmap_init_mem_platdata(struct udevice *dev, fdt32_t *reg, int size,
20*3b2a29e0SSimon Glass 			     struct regmap **mapp)
21*3b2a29e0SSimon Glass {
22*3b2a29e0SSimon Glass 	/* TODO(sjg@chromium.org): Implement this when needed */
23*3b2a29e0SSimon Glass 	return 0;
24*3b2a29e0SSimon Glass }
25*3b2a29e0SSimon Glass #else
266f98b750SSimon Glass int regmap_init_mem(struct udevice *dev, struct regmap **mapp)
276f98b750SSimon Glass {
286f98b750SSimon Glass 	const void *blob = gd->fdt_blob;
296f98b750SSimon Glass 	struct regmap_range *range;
306f98b750SSimon Glass 	const fdt32_t *cell;
316f98b750SSimon Glass 	struct regmap *map;
326f98b750SSimon Glass 	int count;
336f98b750SSimon Glass 	int addr_len, size_len, both_len;
346f98b750SSimon Glass 	int parent;
356f98b750SSimon Glass 	int len;
366f98b750SSimon Glass 
376f98b750SSimon Glass 	parent = dev->parent->of_offset;
386f98b750SSimon Glass 	addr_len = fdt_address_cells(blob, parent);
396f98b750SSimon Glass 	size_len = fdt_size_cells(blob, parent);
406f98b750SSimon Glass 	both_len = addr_len + size_len;
416f98b750SSimon Glass 
426f98b750SSimon Glass 	cell = fdt_getprop(blob, dev->of_offset, "reg", &len);
436f98b750SSimon Glass 	len /= sizeof(*cell);
446f98b750SSimon Glass 	count = len / both_len;
456f98b750SSimon Glass 	if (!cell || !count)
466f98b750SSimon Glass 		return -EINVAL;
476f98b750SSimon Glass 
486f98b750SSimon Glass 	map = malloc(sizeof(struct regmap));
496f98b750SSimon Glass 	if (!map)
506f98b750SSimon Glass 		return -ENOMEM;
516f98b750SSimon Glass 
526f98b750SSimon Glass 	if (count <= 1) {
536f98b750SSimon Glass 		map->range = &map->base_range;
546f98b750SSimon Glass 	} else {
556f98b750SSimon Glass 		map->range = malloc(count * sizeof(struct regmap_range));
566f98b750SSimon Glass 		if (!map->range) {
576f98b750SSimon Glass 			free(map);
586f98b750SSimon Glass 			return -ENOMEM;
596f98b750SSimon Glass 		}
606f98b750SSimon Glass 	}
616f98b750SSimon Glass 
626f98b750SSimon Glass 	map->base = fdtdec_get_number(cell, addr_len);
636f98b750SSimon Glass 	map->range_count = count;
646f98b750SSimon Glass 
656f98b750SSimon Glass 	for (range = map->range; count > 0;
666f98b750SSimon Glass 	     count--, cell += both_len, range++) {
676f98b750SSimon Glass 		range->start = fdtdec_get_number(cell, addr_len);
686f98b750SSimon Glass 		range->size = fdtdec_get_number(cell + addr_len, size_len);
696f98b750SSimon Glass 	}
706f98b750SSimon Glass 
716f98b750SSimon Glass 	*mapp = map;
726f98b750SSimon Glass 
736f98b750SSimon Glass 	return 0;
746f98b750SSimon Glass }
75*3b2a29e0SSimon Glass #endif
766f98b750SSimon Glass 
776f98b750SSimon Glass void *regmap_get_range(struct regmap *map, unsigned int range_num)
786f98b750SSimon Glass {
796f98b750SSimon Glass 	struct regmap_range *range;
806f98b750SSimon Glass 
816f98b750SSimon Glass 	if (range_num >= map->range_count)
826f98b750SSimon Glass 		return NULL;
836f98b750SSimon Glass 	range = &map->range[range_num];
846f98b750SSimon Glass 
856f98b750SSimon Glass 	return map_sysmem(range->start, range->size);
866f98b750SSimon Glass }
876f98b750SSimon Glass 
886f98b750SSimon Glass int regmap_uninit(struct regmap *map)
896f98b750SSimon Glass {
906f98b750SSimon Glass 	if (map->range_count > 1)
916f98b750SSimon Glass 		free(map->range);
926f98b750SSimon Glass 	free(map);
936f98b750SSimon Glass 
946f98b750SSimon Glass 	return 0;
956f98b750SSimon Glass }
96