xref: /rk3399_rockchip-uboot/drivers/core/regmap.c (revision dbbe2e6401fc8539f456cab7ef1dd38f9495591d)
1 /*
2  * Copyright (c) 2015 Google, Inc
3  * Written by Simon Glass <sjg@chromium.org>
4  *
5  * SPDX-License-Identifier:	GPL-2.0+
6  */
7 
8 #include <common.h>
9 #include <dm.h>
10 #include <errno.h>
11 #include <libfdt.h>
12 #include <malloc.h>
13 #include <mapmem.h>
14 #include <regmap.h>
15 
16 DECLARE_GLOBAL_DATA_PTR;
17 
18 #if CONFIG_IS_ENABLED(OF_PLATDATA)
19 int regmap_init_mem_platdata(struct udevice *dev, fdt32_t *reg, int size,
20 			     struct regmap **mapp)
21 {
22 	/* TODO(sjg@chromium.org): Implement this when needed */
23 	return 0;
24 }
25 #else
26 int regmap_init_mem(struct udevice *dev, struct regmap **mapp)
27 {
28 	const void *blob = gd->fdt_blob;
29 	struct regmap_range *range;
30 	const fdt32_t *cell;
31 	struct regmap *map;
32 	int count;
33 	int addr_len, size_len, both_len;
34 	int parent;
35 	int len;
36 
37 	parent = dev->parent->of_offset;
38 	addr_len = fdt_address_cells(blob, parent);
39 	size_len = fdt_size_cells(blob, parent);
40 	both_len = addr_len + size_len;
41 
42 	cell = fdt_getprop(blob, dev->of_offset, "reg", &len);
43 	len /= sizeof(*cell);
44 	count = len / both_len;
45 	if (!cell || !count)
46 		return -EINVAL;
47 
48 	map = malloc(sizeof(struct regmap));
49 	if (!map)
50 		return -ENOMEM;
51 
52 	if (count <= 1) {
53 		map->range = &map->base_range;
54 	} else {
55 		map->range = malloc(count * sizeof(struct regmap_range));
56 		if (!map->range) {
57 			free(map);
58 			return -ENOMEM;
59 		}
60 	}
61 
62 	map->base = fdtdec_get_number(cell, addr_len);
63 	map->range_count = count;
64 
65 	for (range = map->range; count > 0;
66 	     count--, cell += both_len, range++) {
67 		range->start = fdtdec_get_number(cell, addr_len);
68 		range->size = fdtdec_get_number(cell + addr_len, size_len);
69 	}
70 
71 	*mapp = map;
72 
73 	return 0;
74 }
75 #endif
76 
77 void *regmap_get_range(struct regmap *map, unsigned int range_num)
78 {
79 	struct regmap_range *range;
80 
81 	if (range_num >= map->range_count)
82 		return NULL;
83 	range = &map->range[range_num];
84 
85 	return map_sysmem(range->start, range->size);
86 }
87 
88 int regmap_uninit(struct regmap *map)
89 {
90 	if (map->range_count > 1)
91 		free(map->range);
92 	free(map);
93 
94 	return 0;
95 }
96