]> git.sur5r.net Git - u-boot/blob - drivers/core/regmap.c
dm: core: Replace of_offset with accessor (part 2)
[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 #include <asm/io.h>
17
18 DECLARE_GLOBAL_DATA_PTR;
19
20 static struct regmap *regmap_alloc_count(int count)
21 {
22         struct regmap *map;
23
24         map = malloc(sizeof(struct regmap));
25         if (!map)
26                 return NULL;
27         if (count <= 1) {
28                 map->range = &map->base_range;
29         } else {
30                 map->range = malloc(count * sizeof(struct regmap_range));
31                 if (!map->range) {
32                         free(map);
33                         return NULL;
34                 }
35         }
36         map->range_count = count;
37
38         return map;
39 }
40
41 #if CONFIG_IS_ENABLED(OF_PLATDATA)
42 int regmap_init_mem_platdata(struct udevice *dev, u32 *reg, int count,
43                              struct regmap **mapp)
44 {
45         struct regmap_range *range;
46         struct regmap *map;
47
48         map = regmap_alloc_count(count);
49         if (!map)
50                 return -ENOMEM;
51
52         map->base = *reg;
53         for (range = map->range; count > 0; reg += 2, range++, count--) {
54                 range->start = *reg;
55                 range->size = reg[1];
56         }
57
58         *mapp = map;
59
60         return 0;
61 }
62 #else
63 int regmap_init_mem(struct udevice *dev, struct regmap **mapp)
64 {
65         const void *blob = gd->fdt_blob;
66         struct regmap_range *range;
67         const fdt32_t *cell;
68         struct regmap *map;
69         int count;
70         int addr_len, size_len, both_len;
71         int parent;
72         int len;
73         int index;
74
75         parent = dev_of_offset(dev->parent);
76         addr_len = fdt_address_cells(blob, parent);
77         size_len = fdt_size_cells(blob, parent);
78         both_len = addr_len + size_len;
79
80         cell = fdt_getprop(blob, dev_of_offset(dev), "reg", &len);
81         len /= sizeof(*cell);
82         count = len / both_len;
83         if (!cell || !count)
84                 return -EINVAL;
85
86         map = regmap_alloc_count(count);
87         if (!map)
88                 return -ENOMEM;
89
90         for (range = map->range, index = 0; count > 0;
91              count--, cell += both_len, range++, index++) {
92                 fdt_size_t sz;
93                 range->start = fdtdec_get_addr_size_fixed(blob,
94                                 dev_of_offset(dev), "reg", index, addr_len,
95                                 size_len, &sz, true);
96                 range->size = sz;
97         }
98         map->base = map->range[0].start;
99
100         *mapp = map;
101
102         return 0;
103 }
104 #endif
105
106 void *regmap_get_range(struct regmap *map, unsigned int range_num)
107 {
108         struct regmap_range *range;
109
110         if (range_num >= map->range_count)
111                 return NULL;
112         range = &map->range[range_num];
113
114         return map_sysmem(range->start, range->size);
115 }
116
117 int regmap_uninit(struct regmap *map)
118 {
119         if (map->range_count > 1)
120                 free(map->range);
121         free(map);
122
123         return 0;
124 }
125
126 int regmap_read(struct regmap *map, uint offset, uint *valp)
127 {
128         uint32_t *ptr = map_physmem(map->base + offset, 4, MAP_NOCACHE);
129
130         *valp = le32_to_cpu(readl(ptr));
131
132         return 0;
133 }
134
135 int regmap_write(struct regmap *map, uint offset, uint val)
136 {
137         uint32_t *ptr = map_physmem(map->base + offset, 4, MAP_NOCACHE);
138
139         writel(cpu_to_le32(val), ptr);
140
141         return 0;
142 }