]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - drivers/core/regmap.c
tpm: Move the I2C TPM code into one file
[karo-tx-uboot.git] / 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 int regmap_init_mem(struct udevice *dev, struct regmap **mapp)
19 {
20         const void *blob = gd->fdt_blob;
21         struct regmap_range *range;
22         const fdt32_t *cell;
23         struct regmap *map;
24         int count;
25         int addr_len, size_len, both_len;
26         int parent;
27         int len;
28
29         parent = dev->parent->of_offset;
30         addr_len = fdt_address_cells(blob, parent);
31         size_len = fdt_size_cells(blob, parent);
32         both_len = addr_len + size_len;
33
34         cell = fdt_getprop(blob, dev->of_offset, "reg", &len);
35         len /= sizeof(*cell);
36         count = len / both_len;
37         if (!cell || !count)
38                 return -EINVAL;
39
40         map = malloc(sizeof(struct regmap));
41         if (!map)
42                 return -ENOMEM;
43
44         if (count <= 1) {
45                 map->range = &map->base_range;
46         } else {
47                 map->range = malloc(count * sizeof(struct regmap_range));
48                 if (!map->range) {
49                         free(map);
50                         return -ENOMEM;
51                 }
52         }
53
54         map->base = fdtdec_get_number(cell, addr_len);
55         map->range_count = count;
56
57         for (range = map->range; count > 0;
58              count--, cell += both_len, range++) {
59                 range->start = fdtdec_get_number(cell, addr_len);
60                 range->size = fdtdec_get_number(cell + addr_len, size_len);
61         }
62
63         *mapp = map;
64
65         return 0;
66 }
67
68 void *regmap_get_range(struct regmap *map, unsigned int range_num)
69 {
70         struct regmap_range *range;
71
72         if (range_num >= map->range_count)
73                 return NULL;
74         range = &map->range[range_num];
75
76         return map_sysmem(range->start, range->size);
77 }
78
79 int regmap_uninit(struct regmap *map)
80 {
81         if (map->range_count > 1)
82                 free(map->range);
83         free(map);
84
85         return 0;
86 }