16f98b750SSimon Glass /* 26f98b750SSimon Glass * Copyright (c) 2015 Google, Inc 36f98b750SSimon Glass * Written by Simon Glass <sjg@chromium.org> 46f98b750SSimon Glass * 56f98b750SSimon Glass * SPDX-License-Identifier: GPL-2.0+ 66f98b750SSimon Glass */ 76f98b750SSimon Glass 86f98b750SSimon Glass #include <common.h> 96f98b750SSimon Glass #include <dm.h> 106f98b750SSimon Glass #include <errno.h> 116f98b750SSimon Glass #include <libfdt.h> 126f98b750SSimon Glass #include <malloc.h> 136f98b750SSimon Glass #include <mapmem.h> 146f98b750SSimon Glass #include <regmap.h> 156f98b750SSimon Glass 166f98b750SSimon Glass DECLARE_GLOBAL_DATA_PTR; 176f98b750SSimon Glass 18*a951431eSSimon Glass static struct regmap *regmap_alloc_count(int count) 19*a951431eSSimon Glass { 20*a951431eSSimon Glass struct regmap *map; 21*a951431eSSimon Glass 22*a951431eSSimon Glass map = malloc(sizeof(struct regmap)); 23*a951431eSSimon Glass if (!map) 24*a951431eSSimon Glass return NULL; 25*a951431eSSimon Glass if (count <= 1) { 26*a951431eSSimon Glass map->range = &map->base_range; 27*a951431eSSimon Glass } else { 28*a951431eSSimon Glass map->range = malloc(count * sizeof(struct regmap_range)); 29*a951431eSSimon Glass if (!map->range) { 30*a951431eSSimon Glass free(map); 31*a951431eSSimon Glass return NULL; 32*a951431eSSimon Glass } 33*a951431eSSimon Glass } 34*a951431eSSimon Glass map->range_count = count; 35*a951431eSSimon Glass 36*a951431eSSimon Glass return map; 37*a951431eSSimon Glass } 38*a951431eSSimon Glass 393b2a29e0SSimon Glass #if CONFIG_IS_ENABLED(OF_PLATDATA) 403b2a29e0SSimon Glass int regmap_init_mem_platdata(struct udevice *dev, fdt32_t *reg, int size, 413b2a29e0SSimon Glass struct regmap **mapp) 423b2a29e0SSimon Glass { 433b2a29e0SSimon Glass /* TODO(sjg@chromium.org): Implement this when needed */ 443b2a29e0SSimon Glass return 0; 453b2a29e0SSimon Glass } 463b2a29e0SSimon Glass #else 476f98b750SSimon Glass int regmap_init_mem(struct udevice *dev, struct regmap **mapp) 486f98b750SSimon Glass { 496f98b750SSimon Glass const void *blob = gd->fdt_blob; 506f98b750SSimon Glass struct regmap_range *range; 516f98b750SSimon Glass const fdt32_t *cell; 526f98b750SSimon Glass struct regmap *map; 536f98b750SSimon Glass int count; 546f98b750SSimon Glass int addr_len, size_len, both_len; 556f98b750SSimon Glass int parent; 566f98b750SSimon Glass int len; 576f98b750SSimon Glass 586f98b750SSimon Glass parent = dev->parent->of_offset; 596f98b750SSimon Glass addr_len = fdt_address_cells(blob, parent); 606f98b750SSimon Glass size_len = fdt_size_cells(blob, parent); 616f98b750SSimon Glass both_len = addr_len + size_len; 626f98b750SSimon Glass 636f98b750SSimon Glass cell = fdt_getprop(blob, dev->of_offset, "reg", &len); 646f98b750SSimon Glass len /= sizeof(*cell); 656f98b750SSimon Glass count = len / both_len; 666f98b750SSimon Glass if (!cell || !count) 676f98b750SSimon Glass return -EINVAL; 686f98b750SSimon Glass 69*a951431eSSimon Glass map = regmap_alloc_count(count); 706f98b750SSimon Glass if (!map) 716f98b750SSimon Glass return -ENOMEM; 726f98b750SSimon Glass 736f98b750SSimon Glass map->base = fdtdec_get_number(cell, addr_len); 746f98b750SSimon Glass 756f98b750SSimon Glass for (range = map->range; count > 0; 766f98b750SSimon Glass count--, cell += both_len, range++) { 776f98b750SSimon Glass range->start = fdtdec_get_number(cell, addr_len); 786f98b750SSimon Glass range->size = fdtdec_get_number(cell + addr_len, size_len); 796f98b750SSimon Glass } 806f98b750SSimon Glass 816f98b750SSimon Glass *mapp = map; 826f98b750SSimon Glass 836f98b750SSimon Glass return 0; 846f98b750SSimon Glass } 853b2a29e0SSimon Glass #endif 866f98b750SSimon Glass 876f98b750SSimon Glass void *regmap_get_range(struct regmap *map, unsigned int range_num) 886f98b750SSimon Glass { 896f98b750SSimon Glass struct regmap_range *range; 906f98b750SSimon Glass 916f98b750SSimon Glass if (range_num >= map->range_count) 926f98b750SSimon Glass return NULL; 936f98b750SSimon Glass range = &map->range[range_num]; 946f98b750SSimon Glass 956f98b750SSimon Glass return map_sysmem(range->start, range->size); 966f98b750SSimon Glass } 976f98b750SSimon Glass 986f98b750SSimon Glass int regmap_uninit(struct regmap *map) 996f98b750SSimon Glass { 1006f98b750SSimon Glass if (map->range_count > 1) 1016f98b750SSimon Glass free(map->range); 1026f98b750SSimon Glass free(map); 1036f98b750SSimon Glass 1046f98b750SSimon Glass return 0; 1056f98b750SSimon Glass } 106