uboot/drivers/core/regmap.c
<<
>>
Prefs
   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#include <asm/io.h>
  17
  18DECLARE_GLOBAL_DATA_PTR;
  19
  20static struct regmap *regmap_alloc_count(int count)
  21{
  22        struct regmap *map;
  23
  24        map = malloc(sizeof(struct regmap));
  25        if (!map)
  26                return NULL;
  27        if (count <= 1) {
  28                map->range = &map->base_range;
  29        } else {
  30                map->range = malloc(count * sizeof(struct regmap_range));
  31                if (!map->range) {
  32                        free(map);
  33                        return NULL;
  34                }
  35        }
  36        map->range_count = count;
  37
  38        return map;
  39}
  40
  41#if CONFIG_IS_ENABLED(OF_PLATDATA)
  42int regmap_init_mem_platdata(struct udevice *dev, u32 *reg, int count,
  43                             struct regmap **mapp)
  44{
  45        struct regmap_range *range;
  46        struct regmap *map;
  47
  48        map = regmap_alloc_count(count);
  49        if (!map)
  50                return -ENOMEM;
  51
  52        map->base = *reg;
  53        for (range = map->range; count > 0; reg += 2, range++, count--) {
  54                range->start = *reg;
  55                range->size = reg[1];
  56        }
  57
  58        *mapp = map;
  59
  60        return 0;
  61}
  62#else
  63int regmap_init_mem(struct udevice *dev, struct regmap **mapp)
  64{
  65        const void *blob = gd->fdt_blob;
  66        struct regmap_range *range;
  67        const fdt32_t *cell;
  68        struct regmap *map;
  69        int count;
  70        int addr_len, size_len, both_len;
  71        int parent;
  72        int len;
  73
  74        parent = dev->parent->of_offset;
  75        addr_len = fdt_address_cells(blob, parent);
  76        size_len = fdt_size_cells(blob, parent);
  77        both_len = addr_len + size_len;
  78
  79        cell = fdt_getprop(blob, dev->of_offset, "reg", &len);
  80        len /= sizeof(*cell);
  81        count = len / both_len;
  82        if (!cell || !count)
  83                return -EINVAL;
  84
  85        map = regmap_alloc_count(count);
  86        if (!map)
  87                return -ENOMEM;
  88
  89        map->base = fdtdec_get_number(cell, addr_len);
  90
  91        for (range = map->range; count > 0;
  92             count--, cell += both_len, range++) {
  93                range->start = fdtdec_get_number(cell, addr_len);
  94                range->size = fdtdec_get_number(cell + addr_len, size_len);
  95        }
  96
  97        *mapp = map;
  98
  99        return 0;
 100}
 101#endif
 102
 103void *regmap_get_range(struct regmap *map, unsigned int range_num)
 104{
 105        struct regmap_range *range;
 106
 107        if (range_num >= map->range_count)
 108                return NULL;
 109        range = &map->range[range_num];
 110
 111        return map_sysmem(range->start, range->size);
 112}
 113
 114int regmap_uninit(struct regmap *map)
 115{
 116        if (map->range_count > 1)
 117                free(map->range);
 118        free(map);
 119
 120        return 0;
 121}
 122
 123int regmap_read(struct regmap *map, uint offset, uint *valp)
 124{
 125        uint32_t *ptr = map_physmem(map->base + offset, 4, MAP_NOCACHE);
 126
 127        *valp = le32_to_cpu(readl(ptr));
 128
 129        return 0;
 130}
 131
 132int regmap_write(struct regmap *map, uint offset, uint val)
 133{
 134        uint32_t *ptr = map_physmem(map->base + offset, 4, MAP_NOCACHE);
 135
 136        writel(cpu_to_le32(val), ptr);
 137
 138        return 0;
 139}
 140