]> git.sur5r.net Git - u-boot/blob - drivers/core/regmap.c
regmap: change regmap_init_mem() to take ofnode instead udevice
[u-boot] / drivers / core / regmap.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (c) 2015 Google, Inc
4  * Written by Simon Glass <sjg@chromium.org>
5  */
6
7 #include <common.h>
8 #include <dm.h>
9 #include <errno.h>
10 #include <linux/libfdt.h>
11 #include <malloc.h>
12 #include <mapmem.h>
13 #include <regmap.h>
14 #include <asm/io.h>
15 #include <dm/of_addr.h>
16 #include <linux/ioport.h>
17
18 DECLARE_GLOBAL_DATA_PTR;
19
20 static struct regmap *regmap_alloc(int count)
21 {
22         struct regmap *map;
23
24         map = malloc(sizeof(*map) + sizeof(map->ranges[0]) * count);
25         if (!map)
26                 return NULL;
27         map->range_count = count;
28
29         return map;
30 }
31
32 #if CONFIG_IS_ENABLED(OF_PLATDATA)
33 int regmap_init_mem_platdata(struct udevice *dev, fdt_val_t *reg, int count,
34                              struct regmap **mapp)
35 {
36         struct regmap_range *range;
37         struct regmap *map;
38
39         map = regmap_alloc(count);
40         if (!map)
41                 return -ENOMEM;
42
43         for (range = map->ranges; count > 0; reg += 2, range++, count--) {
44                 range->start = *reg;
45                 range->size = reg[1];
46         }
47
48         *mapp = map;
49
50         return 0;
51 }
52 #else
53 int regmap_init_mem(ofnode node, struct regmap **mapp)
54 {
55         struct regmap_range *range;
56         struct regmap *map;
57         int count;
58         int addr_len, size_len, both_len;
59         int len;
60         int index;
61         struct resource r;
62
63         addr_len = ofnode_read_simple_addr_cells(ofnode_get_parent(node));
64         size_len = ofnode_read_simple_size_cells(ofnode_get_parent(node));
65         both_len = addr_len + size_len;
66
67         len = ofnode_read_size(node, "reg");
68         if (len < 0)
69                 return len;
70         len /= sizeof(fdt32_t);
71         count = len / both_len;
72         if (!count)
73                 return -EINVAL;
74
75         map = regmap_alloc(count);
76         if (!map)
77                 return -ENOMEM;
78
79         for (range = map->ranges, index = 0; count > 0;
80              count--, range++, index++) {
81                 fdt_size_t sz;
82                 if (of_live_active()) {
83                         of_address_to_resource(ofnode_to_np(node), index, &r);
84                         range->start = r.start;
85                         range->size = r.end - r.start + 1;
86                 } else {
87                         range->start = fdtdec_get_addr_size_fixed(gd->fdt_blob,
88                                         ofnode_to_offset(node), "reg", index,
89                                         addr_len, size_len, &sz, true);
90                         range->size = sz;
91                 }
92         }
93
94         *mapp = map;
95
96         return 0;
97 }
98 #endif
99
100 void *regmap_get_range(struct regmap *map, unsigned int range_num)
101 {
102         struct regmap_range *range;
103
104         if (range_num >= map->range_count)
105                 return NULL;
106         range = &map->ranges[range_num];
107
108         return map_sysmem(range->start, range->size);
109 }
110
111 int regmap_uninit(struct regmap *map)
112 {
113         free(map);
114
115         return 0;
116 }
117
118 int regmap_read(struct regmap *map, uint offset, uint *valp)
119 {
120         u32 *ptr = map_physmem(map->ranges[0].start + offset, 4, MAP_NOCACHE);
121
122         *valp = le32_to_cpu(readl(ptr));
123
124         return 0;
125 }
126
127 int regmap_write(struct regmap *map, uint offset, uint val)
128 {
129         u32 *ptr = map_physmem(map->ranges[0].start + offset, 4, MAP_NOCACHE);
130
131         writel(cpu_to_le32(val), ptr);
132
133         return 0;
134 }