Browse Source

fdt: allow fdtdec_get_addr_size_*() to translate addresses

Some code may want to read reg values from DT, but from nodes that aren't
associated with DM devices, so using dev_get_addr_index() isn't
appropriate. In this case, fdtdec_get_addr_size_*() are the functions to
use. However, "translation" (via the chain of ranges properties in parent
nodes) may still be desirable. Add a function parameter to request that,
and implement it. Update all call sites to default to the original
behaviour.

Signed-off-by: Stephen Warren <swarren@nvidia.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
Squashed in build fix from Stephen:
Signed-off-by: Simon Glass <sjg@chromium.org>
Stephen Warren 8 years ago
parent
commit
6e06acb732

+ 1 - 1
drivers/core/device.c

@@ -671,7 +671,7 @@ fdt_addr_t dev_get_addr_index(struct udevice *dev, int index)
 		addr = fdtdec_get_addr_size_auto_parent(gd->fdt_blob,
 							dev->parent->of_offset,
 							dev->of_offset, "reg",
-							index, NULL);
+							index, NULL, false);
 		if (CONFIG_IS_ENABLED(SIMPLE_BUS) && addr != FDT_ADDR_T_NONE) {
 			if (device_get_uclass_id(dev->parent) ==
 			    UCLASS_SIMPLE_BUS)

+ 1 - 1
drivers/gpio/mpc85xx_gpio.c

@@ -170,7 +170,7 @@ static int mpc85xx_gpio_ofdata_to_platdata(struct udevice *dev) {
 	fdt_size_t size;
 
 	addr = fdtdec_get_addr_size_auto_noparent(gd->fdt_blob, dev->of_offset,
-						  "reg", 0, &size);
+						  "reg", 0, &size, false);
 
 	plat->addr = addr;
 	plat->size = size;

+ 1 - 1
drivers/i2c/fsl_i2c.c

@@ -587,7 +587,7 @@ static int fsl_i2c_ofdata_to_platdata(struct udevice *bus)
 	fdt_size_t size;
 
 	addr = fdtdec_get_addr_size_auto_noparent(gd->fdt_blob, bus->of_offset,
-						  "reg", 0, &size);
+						  "reg", 0, &size, false);
 
 	dev->base = map_sysmem(CONFIG_SYS_IMMR + addr, size);
 

+ 2 - 1
drivers/mmc/msm_sdhci.c

@@ -178,7 +178,8 @@ static int msm_ofdata_to_platdata(struct udevice *dev)
 	priv->base = (void *)fdtdec_get_addr_size_auto_parent(gd->fdt_blob,
 							      parent->of_offset,
 							      dev->of_offset,
-							      "reg", 1, NULL);
+							      "reg", 1, NULL,
+							      false);
 	if (priv->base == (void *)FDT_ADDR_T_NONE ||
 	    host->ioaddr == (void *)FDT_ADDR_T_NONE)
 		return -EINVAL;

+ 2 - 1
drivers/net/cpsw.c

@@ -1146,7 +1146,8 @@ static const struct eth_ops cpsw_eth_ops = {
 
 static inline fdt_addr_t cpsw_get_addr_by_node(const void *fdt, int node)
 {
-	return fdtdec_get_addr_size_auto_noparent(fdt, node, "reg", 0, NULL);
+	return fdtdec_get_addr_size_auto_noparent(fdt, node, "reg", 0, NULL,
+						  false);
 }
 
 static int cpsw_eth_ofdata_to_platdata(struct udevice *dev)

+ 3 - 2
drivers/spmi/spmi-msm.c

@@ -153,11 +153,12 @@ static int msm_spmi_probe(struct udevice *dev)
 	priv->spmi_core = fdtdec_get_addr_size_auto_parent(gd->fdt_blob,
 							   parent->of_offset,
 							   dev->of_offset,
-							   "reg", 1, NULL);
+							   "reg", 1, NULL,
+							   false);
 	priv->spmi_obs = fdtdec_get_addr_size_auto_parent(gd->fdt_blob,
 							  parent->of_offset,
 							  dev->of_offset, "reg",
-							  2, NULL);
+							  2, NULL, false);
 	if (priv->arb_chnl == FDT_ADDR_T_NONE ||
 	    priv->spmi_core == FDT_ADDR_T_NONE ||
 	    priv->spmi_obs == FDT_ADDR_T_NONE)

+ 11 - 3
include/fdtdec.h

@@ -297,11 +297,13 @@ int fdtdec_next_compatible_subnode(const void *blob, int node,
  * @param na	the number of cells used to represent an address
  * @param ns	the number of cells used to represent a size
  * @param sizep	a pointer to store the size into. Use NULL if not required
+ * @param translate	Indicates whether to translate the returned value
+ *			using the parent node's ranges property.
  * @return address, if found, or FDT_ADDR_T_NONE if not
  */
 fdt_addr_t fdtdec_get_addr_size_fixed(const void *blob, int node,
 		const char *prop_name, int index, int na, int ns,
-		fdt_size_t *sizep);
+		fdt_size_t *sizep, bool translate);
 
 /*
  * Look up an address property in a node and return the parsed address, and
@@ -317,10 +319,13 @@ fdt_addr_t fdtdec_get_addr_size_fixed(const void *blob, int node,
  * @param prop_name	name of property to find
  * @param index	which address to retrieve from a list of addresses. Often 0.
  * @param sizep	a pointer to store the size into. Use NULL if not required
+ * @param translate	Indicates whether to translate the returned value
+ *			using the parent node's ranges property.
  * @return address, if found, or FDT_ADDR_T_NONE if not
  */
 fdt_addr_t fdtdec_get_addr_size_auto_parent(const void *blob, int parent,
-		int node, const char *prop_name, int index, fdt_size_t *sizep);
+		int node, const char *prop_name, int index, fdt_size_t *sizep,
+		bool translate);
 
 /*
  * Look up an address property in a node and return the parsed address, and
@@ -340,10 +345,13 @@ fdt_addr_t fdtdec_get_addr_size_auto_parent(const void *blob, int parent,
  * @param prop_name	name of property to find
  * @param index	which address to retrieve from a list of addresses. Often 0.
  * @param sizep	a pointer to store the size into. Use NULL if not required
+ * @param translate	Indicates whether to translate the returned value
+ *			using the parent node's ranges property.
  * @return address, if found, or FDT_ADDR_T_NONE if not
  */
 fdt_addr_t fdtdec_get_addr_size_auto_noparent(const void *blob, int node,
-		const char *prop_name, int index, fdt_size_t *sizep);
+		const char *prop_name, int index, fdt_size_t *sizep,
+		bool translate);
 
 /*
  * Look up an address property in a node and return the parsed address.

+ 15 - 7
lib/fdtdec.c

@@ -9,6 +9,7 @@
 #include <errno.h>
 #include <serial.h>
 #include <libfdt.h>
+#include <fdt_support.h>
 #include <fdtdec.h>
 #include <asm/sections.h>
 #include <linux/ctype.h>
@@ -77,7 +78,7 @@ const char *fdtdec_get_compatible(enum fdt_compat_id id)
 
 fdt_addr_t fdtdec_get_addr_size_fixed(const void *blob, int node,
 		const char *prop_name, int index, int na, int ns,
-		fdt_size_t *sizep)
+		fdt_size_t *sizep, bool translate)
 {
 	const fdt32_t *prop, *prop_end;
 	const fdt32_t *prop_addr, *prop_size, *prop_after_size;
@@ -112,7 +113,12 @@ fdt_addr_t fdtdec_get_addr_size_fixed(const void *blob, int node,
 		return FDT_ADDR_T_NONE;
 	}
 
-	addr = fdtdec_get_number(prop_addr, na);
+#if !defined(CONFIG_SPL_BUILD) && defined(CONFIG_OF_LIBFDT)
+	if (translate)
+		addr = fdt_translate_address(blob, node, prop_addr);
+	else
+#endif
+		addr = fdtdec_get_number(prop_addr, na);
 
 	if (sizep) {
 		*sizep = fdtdec_get_number(prop_size, ns);
@@ -126,7 +132,8 @@ fdt_addr_t fdtdec_get_addr_size_fixed(const void *blob, int node,
 }
 
 fdt_addr_t fdtdec_get_addr_size_auto_parent(const void *blob, int parent,
-		int node, const char *prop_name, int index, fdt_size_t *sizep)
+		int node, const char *prop_name, int index, fdt_size_t *sizep,
+		bool translate)
 {
 	int na, ns;
 
@@ -147,11 +154,12 @@ fdt_addr_t fdtdec_get_addr_size_auto_parent(const void *blob, int parent,
 	debug("na=%d, ns=%d, ", na, ns);
 
 	return fdtdec_get_addr_size_fixed(blob, node, prop_name, index, na,
-					  ns, sizep);
+					  ns, sizep, translate);
 }
 
 fdt_addr_t fdtdec_get_addr_size_auto_noparent(const void *blob, int node,
-		const char *prop_name, int index, fdt_size_t *sizep)
+		const char *prop_name, int index, fdt_size_t *sizep,
+		bool translate)
 {
 	int parent;
 
@@ -164,7 +172,7 @@ fdt_addr_t fdtdec_get_addr_size_auto_noparent(const void *blob, int node,
 	}
 
 	return fdtdec_get_addr_size_auto_parent(blob, parent, node, prop_name,
-						index, sizep);
+						index, sizep, translate);
 }
 
 fdt_addr_t fdtdec_get_addr_size(const void *blob, int node,
@@ -174,7 +182,7 @@ fdt_addr_t fdtdec_get_addr_size(const void *blob, int node,
 
 	return fdtdec_get_addr_size_fixed(blob, node, prop_name, 0,
 					  sizeof(fdt_addr_t) / sizeof(fdt32_t),
-					  ns, sizep);
+					  ns, sizep, false);
 }
 
 fdt_addr_t fdtdec_get_addr(const void *blob, int node,