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*3b2a29e0SSimon Glass #if CONFIG_IS_ENABLED(OF_PLATDATA) 19*3b2a29e0SSimon Glass int regmap_init_mem_platdata(struct udevice *dev, fdt32_t *reg, int size, 20*3b2a29e0SSimon Glass struct regmap **mapp) 21*3b2a29e0SSimon Glass { 22*3b2a29e0SSimon Glass /* TODO(sjg@chromium.org): Implement this when needed */ 23*3b2a29e0SSimon Glass return 0; 24*3b2a29e0SSimon Glass } 25*3b2a29e0SSimon Glass #else 266f98b750SSimon Glass int regmap_init_mem(struct udevice *dev, struct regmap **mapp) 276f98b750SSimon Glass { 286f98b750SSimon Glass const void *blob = gd->fdt_blob; 296f98b750SSimon Glass struct regmap_range *range; 306f98b750SSimon Glass const fdt32_t *cell; 316f98b750SSimon Glass struct regmap *map; 326f98b750SSimon Glass int count; 336f98b750SSimon Glass int addr_len, size_len, both_len; 346f98b750SSimon Glass int parent; 356f98b750SSimon Glass int len; 366f98b750SSimon Glass 376f98b750SSimon Glass parent = dev->parent->of_offset; 386f98b750SSimon Glass addr_len = fdt_address_cells(blob, parent); 396f98b750SSimon Glass size_len = fdt_size_cells(blob, parent); 406f98b750SSimon Glass both_len = addr_len + size_len; 416f98b750SSimon Glass 426f98b750SSimon Glass cell = fdt_getprop(blob, dev->of_offset, "reg", &len); 436f98b750SSimon Glass len /= sizeof(*cell); 446f98b750SSimon Glass count = len / both_len; 456f98b750SSimon Glass if (!cell || !count) 466f98b750SSimon Glass return -EINVAL; 476f98b750SSimon Glass 486f98b750SSimon Glass map = malloc(sizeof(struct regmap)); 496f98b750SSimon Glass if (!map) 506f98b750SSimon Glass return -ENOMEM; 516f98b750SSimon Glass 526f98b750SSimon Glass if (count <= 1) { 536f98b750SSimon Glass map->range = &map->base_range; 546f98b750SSimon Glass } else { 556f98b750SSimon Glass map->range = malloc(count * sizeof(struct regmap_range)); 566f98b750SSimon Glass if (!map->range) { 576f98b750SSimon Glass free(map); 586f98b750SSimon Glass return -ENOMEM; 596f98b750SSimon Glass } 606f98b750SSimon Glass } 616f98b750SSimon Glass 626f98b750SSimon Glass map->base = fdtdec_get_number(cell, addr_len); 636f98b750SSimon Glass map->range_count = count; 646f98b750SSimon Glass 656f98b750SSimon Glass for (range = map->range; count > 0; 666f98b750SSimon Glass count--, cell += both_len, range++) { 676f98b750SSimon Glass range->start = fdtdec_get_number(cell, addr_len); 686f98b750SSimon Glass range->size = fdtdec_get_number(cell + addr_len, size_len); 696f98b750SSimon Glass } 706f98b750SSimon Glass 716f98b750SSimon Glass *mapp = map; 726f98b750SSimon Glass 736f98b750SSimon Glass return 0; 746f98b750SSimon Glass } 75*3b2a29e0SSimon Glass #endif 766f98b750SSimon Glass 776f98b750SSimon Glass void *regmap_get_range(struct regmap *map, unsigned int range_num) 786f98b750SSimon Glass { 796f98b750SSimon Glass struct regmap_range *range; 806f98b750SSimon Glass 816f98b750SSimon Glass if (range_num >= map->range_count) 826f98b750SSimon Glass return NULL; 836f98b750SSimon Glass range = &map->range[range_num]; 846f98b750SSimon Glass 856f98b750SSimon Glass return map_sysmem(range->start, range->size); 866f98b750SSimon Glass } 876f98b750SSimon Glass 886f98b750SSimon Glass int regmap_uninit(struct regmap *map) 896f98b750SSimon Glass { 906f98b750SSimon Glass if (map->range_count > 1) 916f98b750SSimon Glass free(map->range); 926f98b750SSimon Glass free(map); 936f98b750SSimon Glass 946f98b750SSimon Glass return 0; 956f98b750SSimon Glass } 96