1*d6ffb00aSSimon Glass /* 2*d6ffb00aSSimon Glass * Device addresses 3*d6ffb00aSSimon Glass * 4*d6ffb00aSSimon Glass * Copyright (c) 2017 Google, Inc 5*d6ffb00aSSimon Glass * 6*d6ffb00aSSimon Glass * (C) Copyright 2012 7*d6ffb00aSSimon Glass * Pavel Herrmann <morpheus.ibis@gmail.com> 8*d6ffb00aSSimon Glass * 9*d6ffb00aSSimon Glass * SPDX-License-Identifier: GPL-2.0+ 10*d6ffb00aSSimon Glass */ 11*d6ffb00aSSimon Glass 12*d6ffb00aSSimon Glass #include <common.h> 13*d6ffb00aSSimon Glass #include <dm.h> 14*d6ffb00aSSimon Glass #include <fdt_support.h> 15*d6ffb00aSSimon Glass #include <asm/io.h> 16*d6ffb00aSSimon Glass #include <dm/device-internal.h> 17*d6ffb00aSSimon Glass 18*d6ffb00aSSimon Glass DECLARE_GLOBAL_DATA_PTR; 19*d6ffb00aSSimon Glass 20*d6ffb00aSSimon Glass fdt_addr_t dev_get_addr_index(struct udevice *dev, int index) 21*d6ffb00aSSimon Glass { 22*d6ffb00aSSimon Glass #if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA) 23*d6ffb00aSSimon Glass fdt_addr_t addr; 24*d6ffb00aSSimon Glass 25*d6ffb00aSSimon Glass if (CONFIG_IS_ENABLED(OF_TRANSLATE)) { 26*d6ffb00aSSimon Glass const fdt32_t *reg; 27*d6ffb00aSSimon Glass int len = 0; 28*d6ffb00aSSimon Glass int na, ns; 29*d6ffb00aSSimon Glass 30*d6ffb00aSSimon Glass na = fdt_address_cells(gd->fdt_blob, 31*d6ffb00aSSimon Glass dev_of_offset(dev->parent)); 32*d6ffb00aSSimon Glass if (na < 1) { 33*d6ffb00aSSimon Glass debug("bad #address-cells\n"); 34*d6ffb00aSSimon Glass return FDT_ADDR_T_NONE; 35*d6ffb00aSSimon Glass } 36*d6ffb00aSSimon Glass 37*d6ffb00aSSimon Glass ns = fdt_size_cells(gd->fdt_blob, dev_of_offset(dev->parent)); 38*d6ffb00aSSimon Glass if (ns < 0) { 39*d6ffb00aSSimon Glass debug("bad #size-cells\n"); 40*d6ffb00aSSimon Glass return FDT_ADDR_T_NONE; 41*d6ffb00aSSimon Glass } 42*d6ffb00aSSimon Glass 43*d6ffb00aSSimon Glass reg = fdt_getprop(gd->fdt_blob, dev_of_offset(dev), "reg", 44*d6ffb00aSSimon Glass &len); 45*d6ffb00aSSimon Glass if (!reg || (len <= (index * sizeof(fdt32_t) * (na + ns)))) { 46*d6ffb00aSSimon Glass debug("Req index out of range\n"); 47*d6ffb00aSSimon Glass return FDT_ADDR_T_NONE; 48*d6ffb00aSSimon Glass } 49*d6ffb00aSSimon Glass 50*d6ffb00aSSimon Glass reg += index * (na + ns); 51*d6ffb00aSSimon Glass 52*d6ffb00aSSimon Glass /* 53*d6ffb00aSSimon Glass * Use the full-fledged translate function for complex 54*d6ffb00aSSimon Glass * bus setups. 55*d6ffb00aSSimon Glass */ 56*d6ffb00aSSimon Glass addr = fdt_translate_address((void *)gd->fdt_blob, 57*d6ffb00aSSimon Glass dev_of_offset(dev), reg); 58*d6ffb00aSSimon Glass } else { 59*d6ffb00aSSimon Glass /* 60*d6ffb00aSSimon Glass * Use the "simple" translate function for less complex 61*d6ffb00aSSimon Glass * bus setups. 62*d6ffb00aSSimon Glass */ 63*d6ffb00aSSimon Glass addr = fdtdec_get_addr_size_auto_parent(gd->fdt_blob, 64*d6ffb00aSSimon Glass dev_of_offset(dev->parent), dev_of_offset(dev), 65*d6ffb00aSSimon Glass "reg", index, NULL, false); 66*d6ffb00aSSimon Glass if (CONFIG_IS_ENABLED(SIMPLE_BUS) && addr != FDT_ADDR_T_NONE) { 67*d6ffb00aSSimon Glass if (device_get_uclass_id(dev->parent) == 68*d6ffb00aSSimon Glass UCLASS_SIMPLE_BUS) 69*d6ffb00aSSimon Glass addr = simple_bus_translate(dev->parent, addr); 70*d6ffb00aSSimon Glass } 71*d6ffb00aSSimon Glass } 72*d6ffb00aSSimon Glass 73*d6ffb00aSSimon Glass /* 74*d6ffb00aSSimon Glass * Some platforms need a special address translation. Those 75*d6ffb00aSSimon Glass * platforms (e.g. mvebu in SPL) can configure a translation 76*d6ffb00aSSimon Glass * offset in the DM by calling dm_set_translation_offset() that 77*d6ffb00aSSimon Glass * will get added to all addresses returned by dev_get_addr(). 78*d6ffb00aSSimon Glass */ 79*d6ffb00aSSimon Glass addr += dm_get_translation_offset(); 80*d6ffb00aSSimon Glass 81*d6ffb00aSSimon Glass return addr; 82*d6ffb00aSSimon Glass #else 83*d6ffb00aSSimon Glass return FDT_ADDR_T_NONE; 84*d6ffb00aSSimon Glass #endif 85*d6ffb00aSSimon Glass } 86*d6ffb00aSSimon Glass 87*d6ffb00aSSimon Glass fdt_addr_t dev_get_addr_size_index(struct udevice *dev, int index, 88*d6ffb00aSSimon Glass fdt_size_t *size) 89*d6ffb00aSSimon Glass { 90*d6ffb00aSSimon Glass #if CONFIG_IS_ENABLED(OF_CONTROL) 91*d6ffb00aSSimon Glass /* 92*d6ffb00aSSimon Glass * Only get the size in this first call. We'll get the addr in the 93*d6ffb00aSSimon Glass * next call to the exisiting dev_get_xxx function which handles 94*d6ffb00aSSimon Glass * all config options. 95*d6ffb00aSSimon Glass */ 96*d6ffb00aSSimon Glass fdtdec_get_addr_size_auto_noparent(gd->fdt_blob, dev_of_offset(dev), 97*d6ffb00aSSimon Glass "reg", index, size, false); 98*d6ffb00aSSimon Glass 99*d6ffb00aSSimon Glass /* 100*d6ffb00aSSimon Glass * Get the base address via the existing function which handles 101*d6ffb00aSSimon Glass * all Kconfig cases 102*d6ffb00aSSimon Glass */ 103*d6ffb00aSSimon Glass return dev_get_addr_index(dev, index); 104*d6ffb00aSSimon Glass #else 105*d6ffb00aSSimon Glass return FDT_ADDR_T_NONE; 106*d6ffb00aSSimon Glass #endif 107*d6ffb00aSSimon Glass } 108*d6ffb00aSSimon Glass 109*d6ffb00aSSimon Glass fdt_addr_t dev_get_addr_name(struct udevice *dev, const char *name) 110*d6ffb00aSSimon Glass { 111*d6ffb00aSSimon Glass #if CONFIG_IS_ENABLED(OF_CONTROL) 112*d6ffb00aSSimon Glass int index; 113*d6ffb00aSSimon Glass 114*d6ffb00aSSimon Glass index = fdt_stringlist_search(gd->fdt_blob, dev_of_offset(dev), 115*d6ffb00aSSimon Glass "reg-names", name); 116*d6ffb00aSSimon Glass if (index < 0) 117*d6ffb00aSSimon Glass return index; 118*d6ffb00aSSimon Glass 119*d6ffb00aSSimon Glass return dev_get_addr_index(dev, index); 120*d6ffb00aSSimon Glass #else 121*d6ffb00aSSimon Glass return FDT_ADDR_T_NONE; 122*d6ffb00aSSimon Glass #endif 123*d6ffb00aSSimon Glass } 124*d6ffb00aSSimon Glass 125*d6ffb00aSSimon Glass fdt_addr_t dev_get_addr(struct udevice *dev) 126*d6ffb00aSSimon Glass { 127*d6ffb00aSSimon Glass return dev_get_addr_index(dev, 0); 128*d6ffb00aSSimon Glass } 129*d6ffb00aSSimon Glass 130*d6ffb00aSSimon Glass void *dev_get_addr_ptr(struct udevice *dev) 131*d6ffb00aSSimon Glass { 132*d6ffb00aSSimon Glass return (void *)(uintptr_t)dev_get_addr_index(dev, 0); 133*d6ffb00aSSimon Glass } 134*d6ffb00aSSimon Glass 135*d6ffb00aSSimon Glass void *dev_map_physmem(struct udevice *dev, unsigned long size) 136*d6ffb00aSSimon Glass { 137*d6ffb00aSSimon Glass fdt_addr_t addr = dev_get_addr(dev); 138*d6ffb00aSSimon Glass 139*d6ffb00aSSimon Glass if (addr == FDT_ADDR_T_NONE) 140*d6ffb00aSSimon Glass return NULL; 141*d6ffb00aSSimon Glass 142*d6ffb00aSSimon Glass return map_physmem(addr, size, MAP_NOCACHE); 143*d6ffb00aSSimon Glass } 144