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> 11*0e00a84cSMasahiro Yamada #include <linux/libfdt.h> 126f98b750SSimon Glass #include <malloc.h> 136f98b750SSimon Glass #include <mapmem.h> 146f98b750SSimon Glass #include <regmap.h> 153bfb8cb4SPaul Burton #include <asm/io.h> 1623d63267SSimon Glass #include <dm/of_addr.h> 1723d63267SSimon Glass #include <linux/ioport.h> 183bfb8cb4SPaul Burton 196f98b750SSimon Glass DECLARE_GLOBAL_DATA_PTR; 206f98b750SSimon Glass 21a951431eSSimon Glass static struct regmap *regmap_alloc_count(int count) 22a951431eSSimon Glass { 23a951431eSSimon Glass struct regmap *map; 24a951431eSSimon Glass 25a951431eSSimon Glass map = malloc(sizeof(struct regmap)); 26a951431eSSimon Glass if (!map) 27a951431eSSimon Glass return NULL; 28a951431eSSimon Glass if (count <= 1) { 29a951431eSSimon Glass map->range = &map->base_range; 30a951431eSSimon Glass } else { 31a951431eSSimon Glass map->range = malloc(count * sizeof(struct regmap_range)); 32a951431eSSimon Glass if (!map->range) { 33a951431eSSimon Glass free(map); 34a951431eSSimon Glass return NULL; 35a951431eSSimon Glass } 36a951431eSSimon Glass } 37a951431eSSimon Glass map->range_count = count; 38a951431eSSimon Glass 39a951431eSSimon Glass return map; 40a951431eSSimon Glass } 41a951431eSSimon Glass 423b2a29e0SSimon Glass #if CONFIG_IS_ENABLED(OF_PLATDATA) 43a28bfcc3SSimon Glass int regmap_init_mem_platdata(struct udevice *dev, fdt_val_t *reg, int count, 443b2a29e0SSimon Glass struct regmap **mapp) 453b2a29e0SSimon Glass { 461e6ca1a6SSimon Glass struct regmap_range *range; 471e6ca1a6SSimon Glass struct regmap *map; 481e6ca1a6SSimon Glass 491e6ca1a6SSimon Glass map = regmap_alloc_count(count); 501e6ca1a6SSimon Glass if (!map) 511e6ca1a6SSimon Glass return -ENOMEM; 521e6ca1a6SSimon Glass 531e6ca1a6SSimon Glass map->base = *reg; 541e6ca1a6SSimon Glass for (range = map->range; count > 0; reg += 2, range++, count--) { 551e6ca1a6SSimon Glass range->start = *reg; 561e6ca1a6SSimon Glass range->size = reg[1]; 571e6ca1a6SSimon Glass } 581e6ca1a6SSimon Glass 591e6ca1a6SSimon Glass *mapp = map; 601e6ca1a6SSimon Glass 613b2a29e0SSimon Glass return 0; 623b2a29e0SSimon Glass } 633b2a29e0SSimon Glass #else 646f98b750SSimon Glass int regmap_init_mem(struct udevice *dev, struct regmap **mapp) 656f98b750SSimon Glass { 666f98b750SSimon Glass struct regmap_range *range; 676f98b750SSimon Glass struct regmap *map; 686f98b750SSimon Glass int count; 696f98b750SSimon Glass int addr_len, size_len, both_len; 706f98b750SSimon Glass int len; 711804044fSJean-Jacques Hiblot int index; 7223d63267SSimon Glass ofnode node = dev_ofnode(dev); 7323d63267SSimon Glass struct resource r; 746f98b750SSimon Glass 75878d68c0SSimon Glass addr_len = dev_read_simple_addr_cells(dev->parent); 76878d68c0SSimon Glass size_len = dev_read_simple_size_cells(dev->parent); 776f98b750SSimon Glass both_len = addr_len + size_len; 786f98b750SSimon Glass 7923d63267SSimon Glass len = dev_read_size(dev, "reg"); 8023d63267SSimon Glass if (len < 0) 8123d63267SSimon Glass return len; 8223d63267SSimon Glass len /= sizeof(fdt32_t); 836f98b750SSimon Glass count = len / both_len; 8423d63267SSimon Glass if (!count) 856f98b750SSimon Glass return -EINVAL; 866f98b750SSimon Glass 87a951431eSSimon Glass map = regmap_alloc_count(count); 886f98b750SSimon Glass if (!map) 896f98b750SSimon Glass return -ENOMEM; 906f98b750SSimon Glass 911804044fSJean-Jacques Hiblot for (range = map->range, index = 0; count > 0; 9223d63267SSimon Glass count--, range++, index++) { 931804044fSJean-Jacques Hiblot fdt_size_t sz; 9423d63267SSimon Glass if (of_live_active()) { 9523d63267SSimon Glass of_address_to_resource(ofnode_to_np(node), index, &r); 9623d63267SSimon Glass range->start = r.start; 9723d63267SSimon Glass range->size = r.end - r.start + 1; 9823d63267SSimon Glass } else { 9945c78162SAndy Yan range->start = devfdt_get_addr_size_index(dev, index, &sz); 1001804044fSJean-Jacques Hiblot range->size = sz; 1016f98b750SSimon Glass } 10223d63267SSimon Glass } 1031804044fSJean-Jacques Hiblot map->base = map->range[0].start; 1046f98b750SSimon Glass 1056f98b750SSimon Glass *mapp = map; 1066f98b750SSimon Glass 1076f98b750SSimon Glass return 0; 1086f98b750SSimon Glass } 1093b2a29e0SSimon Glass #endif 1106f98b750SSimon Glass 1116f98b750SSimon Glass void *regmap_get_range(struct regmap *map, unsigned int range_num) 1126f98b750SSimon Glass { 1136f98b750SSimon Glass struct regmap_range *range; 1146f98b750SSimon Glass 1156f98b750SSimon Glass if (range_num >= map->range_count) 1166f98b750SSimon Glass return NULL; 1176f98b750SSimon Glass range = &map->range[range_num]; 1186f98b750SSimon Glass 1196f98b750SSimon Glass return map_sysmem(range->start, range->size); 1206f98b750SSimon Glass } 1216f98b750SSimon Glass 1226f98b750SSimon Glass int regmap_uninit(struct regmap *map) 1236f98b750SSimon Glass { 1246f98b750SSimon Glass if (map->range_count > 1) 1256f98b750SSimon Glass free(map->range); 1266f98b750SSimon Glass free(map); 1276f98b750SSimon Glass 1286f98b750SSimon Glass return 0; 1296f98b750SSimon Glass } 1303bfb8cb4SPaul Burton 1313bfb8cb4SPaul Burton int regmap_read(struct regmap *map, uint offset, uint *valp) 1323bfb8cb4SPaul Burton { 1333bfb8cb4SPaul Burton uint32_t *ptr = map_physmem(map->base + offset, 4, MAP_NOCACHE); 1343bfb8cb4SPaul Burton 1353bfb8cb4SPaul Burton *valp = le32_to_cpu(readl(ptr)); 1363bfb8cb4SPaul Burton 1373bfb8cb4SPaul Burton return 0; 1383bfb8cb4SPaul Burton } 1393bfb8cb4SPaul Burton 1403bfb8cb4SPaul Burton int regmap_write(struct regmap *map, uint offset, uint val) 1413bfb8cb4SPaul Burton { 1423bfb8cb4SPaul Burton uint32_t *ptr = map_physmem(map->base + offset, 4, MAP_NOCACHE); 1433bfb8cb4SPaul Burton 1443bfb8cb4SPaul Burton writel(cpu_to_le32(val), ptr); 1453bfb8cb4SPaul Burton 1463bfb8cb4SPaul Burton return 0; 1473bfb8cb4SPaul Burton } 148