]> git.sur5r.net Git - u-boot/blob - drivers/core/regmap.c
dm: core: Move regmap allocation into a separate function
[u-boot] / drivers / core / regmap.c
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 static struct regmap *regmap_alloc_count(int count)
19 {
20         struct regmap *map;
21
22         map = malloc(sizeof(struct regmap));
23         if (!map)
24                 return NULL;
25         if (count <= 1) {
26                 map->range = &map->base_range;
27         } else {
28                 map->range = malloc(count * sizeof(struct regmap_range));
29                 if (!map->range) {
30                         free(map);
31                         return NULL;
32                 }
33         }
34         map->range_count = count;
35
36         return map;
37 }
38
39 #if CONFIG_IS_ENABLED(OF_PLATDATA)
40 int regmap_init_mem_platdata(struct udevice *dev, fdt32_t *reg, int size,
41                              struct regmap **mapp)
42 {
43         /* TODO(sjg@chromium.org): Implement this when needed */
44         return 0;
45 }
46 #else
47 int regmap_init_mem(struct udevice *dev, struct regmap **mapp)
48 {
49         const void *blob = gd->fdt_blob;
50         struct regmap_range *range;
51         const fdt32_t *cell;
52         struct regmap *map;
53         int count;
54         int addr_len, size_len, both_len;
55         int parent;
56         int len;
57
58         parent = dev->parent->of_offset;
59         addr_len = fdt_address_cells(blob, parent);
60         size_len = fdt_size_cells(blob, parent);
61         both_len = addr_len + size_len;
62
63         cell = fdt_getprop(blob, dev->of_offset, "reg", &len);
64         len /= sizeof(*cell);
65         count = len / both_len;
66         if (!cell || !count)
67                 return -EINVAL;
68
69         map = regmap_alloc_count(count);
70         if (!map)
71                 return -ENOMEM;
72
73         map->base = fdtdec_get_number(cell, addr_len);
74
75         for (range = map->range; count > 0;
76              count--, cell += both_len, range++) {
77                 range->start = fdtdec_get_number(cell, addr_len);
78                 range->size = fdtdec_get_number(cell + addr_len, size_len);
79         }
80
81         *mapp = map;
82
83         return 0;
84 }
85 #endif
86
87 void *regmap_get_range(struct regmap *map, unsigned int range_num)
88 {
89         struct regmap_range *range;
90
91         if (range_num >= map->range_count)
92                 return NULL;
93         range = &map->range[range_num];
94
95         return map_sysmem(range->start, range->size);
96 }
97
98 int regmap_uninit(struct regmap *map)
99 {
100         if (map->range_count > 1)
101                 free(map->range);
102         free(map);
103
104         return 0;
105 }