Skip to content
Snippets Groups Projects
fdtdec.c 29.7 KiB
Newer Older
  • Learn to ignore specific revisions
  • 	mem = fdt_getprop(blob, config_node, prop_name, NULL);
    	if (!mem) {
    		debug("%s: No memory type for '%s', using /memory\n", __func__,
    		      prop_name);
    		mem = "/memory";
    	}
    
    	node = fdt_path_offset(blob, mem);
    	if (node < 0) {
    		debug("%s: Failed to find node '%s': %s\n", __func__, mem,
    		      fdt_strerror(node));
    		return -ENOENT;
    	}
    
    	/*
    	 * Not strictly correct - the memory may have multiple banks. We just
    	 * use the first
    	 */
    	if (fdtdec_decode_region(blob, node, "reg", &base, &size)) {
    		debug("%s: Failed to decode memory region %s\n", __func__,
    		      mem);
    		return -EINVAL;
    	}
    
    	snprintf(prop_name, sizeof(prop_name), "%s-offset%s", mem_type,
    		 suffix);
    	if (fdtdec_decode_region(blob, config_node, prop_name, &offset,
    				 &offset_size)) {
    		debug("%s: Failed to decode memory region '%s'\n", __func__,
    		      prop_name);
    		return -EINVAL;
    	}
    
    	*basep = base + offset;
    	*sizep = offset_size;
    
    	return 0;
    }
    
    static int decode_timing_property(const void *blob, int node, const char *name,
    				  struct timing_entry *result)
    {
    	int length, ret = 0;
    	const u32 *prop;
    
    	prop = fdt_getprop(blob, node, name, &length);
    	if (!prop) {
    		debug("%s: could not find property %s\n",
    		      fdt_get_name(blob, node, NULL), name);
    		return length;
    	}
    
    	if (length == sizeof(u32)) {
    		result->typ = fdtdec_get_int(blob, node, name, 0);
    		result->min = result->typ;
    		result->max = result->typ;
    	} else {
    		ret = fdtdec_get_int_array(blob, node, name, &result->min, 3);
    	}
    
    	return ret;
    }
    
    int fdtdec_decode_display_timing(const void *blob, int parent, int index,
    				 struct display_timing *dt)
    {
    	int i, node, timings_node;
    	u32 val = 0;
    	int ret = 0;
    
    	timings_node = fdt_subnode_offset(blob, parent, "display-timings");
    	if (timings_node < 0)
    		return timings_node;
    
    	for (i = 0, node = fdt_first_subnode(blob, timings_node);
    	     node > 0 && i != index;
    	     node = fdt_next_subnode(blob, node))
    		i++;
    
    	if (node < 0)
    		return node;
    
    	memset(dt, 0, sizeof(*dt));
    
    	ret |= decode_timing_property(blob, node, "hback-porch",
    				      &dt->hback_porch);
    	ret |= decode_timing_property(blob, node, "hfront-porch",
    				      &dt->hfront_porch);
    	ret |= decode_timing_property(blob, node, "hactive", &dt->hactive);
    	ret |= decode_timing_property(blob, node, "hsync-len", &dt->hsync_len);
    	ret |= decode_timing_property(blob, node, "vback-porch",
    				      &dt->vback_porch);
    	ret |= decode_timing_property(blob, node, "vfront-porch",
    				      &dt->vfront_porch);
    	ret |= decode_timing_property(blob, node, "vactive", &dt->vactive);
    	ret |= decode_timing_property(blob, node, "vsync-len", &dt->vsync_len);
    	ret |= decode_timing_property(blob, node, "clock-frequency",
    				      &dt->pixelclock);
    
    	dt->flags = 0;
    	val = fdtdec_get_int(blob, node, "vsync-active", -1);
    	if (val != -1) {
    		dt->flags |= val ? DISPLAY_FLAGS_VSYNC_HIGH :
    				DISPLAY_FLAGS_VSYNC_LOW;
    	}
    	val = fdtdec_get_int(blob, node, "hsync-active", -1);
    	if (val != -1) {
    		dt->flags |= val ? DISPLAY_FLAGS_HSYNC_HIGH :
    				DISPLAY_FLAGS_HSYNC_LOW;
    	}
    	val = fdtdec_get_int(blob, node, "de-active", -1);
    	if (val != -1) {
    		dt->flags |= val ? DISPLAY_FLAGS_DE_HIGH :
    				DISPLAY_FLAGS_DE_LOW;
    	}
    	val = fdtdec_get_int(blob, node, "pixelclk-active", -1);
    	if (val != -1) {
    		dt->flags |= val ? DISPLAY_FLAGS_PIXDATA_POSEDGE :
    				DISPLAY_FLAGS_PIXDATA_NEGEDGE;
    	}
    
    	if (fdtdec_get_bool(blob, node, "interlaced"))
    		dt->flags |= DISPLAY_FLAGS_INTERLACED;
    	if (fdtdec_get_bool(blob, node, "doublescan"))
    		dt->flags |= DISPLAY_FLAGS_DOUBLESCAN;
    	if (fdtdec_get_bool(blob, node, "doubleclk"))
    		dt->flags |= DISPLAY_FLAGS_DOUBLECLK;
    
    	return 0;
    }
    
    
    int fdtdec_setup(void)
    
    {
    #ifdef CONFIG_OF_CONTROL
    # ifdef CONFIG_OF_EMBED
    	/* Get a pointer to the FDT */
    	gd->fdt_blob = __dtb_dt_begin;
    # elif defined CONFIG_OF_SEPARATE
    #  ifdef CONFIG_SPL_BUILD
    	/* FDT is at end of BSS */
    	gd->fdt_blob = (ulong *)&__bss_end;
    #  else
    	/* FDT is at end of image */
    	gd->fdt_blob = (ulong *)&_end;
    #endif
    # elif defined(CONFIG_OF_HOSTFILE)
    	if (sandbox_read_fdt_from_file()) {
    		puts("Failed to read control FDT\n");
    		return -1;
    	}
    # endif
    # ifndef CONFIG_SPL_BUILD
    	/* Allow the early environment to override the fdt address */
    	gd->fdt_blob = (void *)getenv_ulong("fdtcontroladdr", 16,
    						(uintptr_t)gd->fdt_blob);
    # endif
    
    	return fdtdec_prepare_fdt();