Example #1
0
void ft_fixup_enet_phy_connect_type(void *fdt)
{
	struct eth_device *dev;
	struct tsec_private *priv;
	const char *enet_path, *phy_path;
	char enet[16];
	char phy[16];
	int phy_node;
	int i = 0;
	uint32_t ph;
	char *name[3] = { "eTSEC1", "eTSEC2", "eTSEC3" };

	for (; i < ARRAY_SIZE(name); i++) {
		dev = eth_get_dev_by_name(name[i]);
		if (dev) {
			sprintf(enet, "ethernet%d", i);
			sprintf(phy, "enet%d_rgmii_phy", i);
		} else {
			continue;
		}

		priv = dev->priv;
		if (priv->flags & TSEC_SGMII)
			continue;

		enet_path = fdt_get_alias(fdt, enet);
		if (!enet_path)
			continue;

		phy_path = fdt_get_alias(fdt, phy);
		if (!phy_path)
			continue;

		phy_node = fdt_path_offset(fdt, phy_path);
		if (phy_node < 0)
			continue;

		ph = fdt_create_phandle(fdt, phy_node);
		if (ph)
			do_fixup_by_path_u32(fdt, enet_path,
					     "phy-handle", ph, 1);

		do_fixup_by_path(fdt, enet_path, "phy-connection-type",
				 phy_string_for_interface(
				 PHY_INTERFACE_MODE_RGMII_ID),
				 sizeof(phy_string_for_interface(
				 PHY_INTERFACE_MODE_RGMII_ID)),
				 1);
	}
}
Example #2
0
static int ti_musb_get_usb_index(int node)
{
	const void *fdt = gd->fdt_blob;
	int i = 0;
	char path[64];
	const char *alias_path;
	char alias[16];

	fdt_get_path(fdt, node, path, sizeof(path));

	do {
		snprintf(alias, sizeof(alias), "usb%d", i);
		alias_path = fdt_get_alias(fdt, alias);
		if (alias_path == NULL) {
			debug("USB index not found\n");
			return -ENOENT;
		}

		if (!strcmp(path, alias_path))
			return i;

		i++;
	} while (alias_path);

	return -ENOENT;
}
Example #3
0
/*
 * Given the following ...
 *
 * 1) A pointer to an Fman Ethernet node (as identified by the 'compat'
 * compatible string and 'addr' physical address)
 *
 * 2) The name of an alias that points to the ethernet-phy node (usually inside
 * a virtual MDIO node)
 *
 * ... update that Ethernet node's phy-handle property to point to the
 * ethernet-phy node.  This is how we link an Ethernet node to its PHY, so each
 * PHY in a virtual MDIO node must have an alias.
 *
 * Returns 0 on success, or a negative FDT error code on error.
 */
int fdt_set_phy_handle(void *fdt, char *compat, phys_addr_t addr,
			const char *alias)
{
	int offset;
	unsigned int ph;
	const char *path;

	/* Get a path to the node that 'alias' points to */
	path = fdt_get_alias(fdt, alias);
	if (!path)
		return -FDT_ERR_BADPATH;

	/* Get the offset of that node */
	offset = fdt_path_offset(fdt, path);
	if (offset < 0)
		return offset;

	ph = fdt_create_phandle(fdt, offset);
	if (!ph)
		return -FDT_ERR_BADPHANDLE;

	offset = fdt_node_offset_by_compat_reg(fdt, compat, addr);
	if (offset < 0)
		return offset;

	return fdt_setprop(fdt, offset, "phy-handle", &ph, sizeof(ph));
}
Example #4
0
int
of_finddevice(const char *device)
{
    const char *name = device;
    int node;

    if (device == NULL)
        return OF_FAILED;

    if (device[0] != '/' && fdt_get_alias(gFDT, device))
        name = fdt_get_alias(gFDT, device);

    node = fdt_path_offset(gFDT, name);
    TRACE(("of_finddevice('%s') name='%s' node=%d ret=%d\n", device, name, node,
           fdt2of(node)));
    return fdt2of(node);
}
Example #5
0
int fdtparse_alias_offset(const void *fdt, const char *name) {
    const char *path;

    path = fdt_get_alias(fdt, name);
    if (!path) {
        return -FDT_ERR_NOTFOUND;
    }

    return fdt_path_offset(fdt, path);
}
Example #6
0
/*
 * Given an alias or a path for a node, set the mux value of that node.
 *
 * If 'alias' is not a valid alias, then it is treated as a full path to the
 * node.  No error checking is performed.
 *
 * This function is normally called to set the fsl,hydra-mdio-muxval property
 * of a virtual MDIO node.
 */
static void fdt_set_mdio_mux(void *fdt, const char *alias, u32 mux)
{
	const char *path = fdt_get_alias(fdt, alias);

	if (!path)
		path = alias;

	do_fixup_by_path(fdt, path, "fsl,hydra-mdio-muxval",
			 &mux, sizeof(mux), 1);
}
Example #7
0
phys_addr_t
fdt_get_device_reg_byalias(const void* fdt, const char* alias)
{
	const char* name = fdt_get_alias(fdt, alias);

	if (name == NULL) {
		dprintf("%s: No alias found for %s!\n", __func__, alias);
		return 0;
	}

	phys_addr_t deviceReg = fdt_get_device_reg_byname(fdt, name);
	return deviceReg; 
}
Example #8
0
int i2c_bus_register_imx(const char *bus_path, const char *alias_or_path)
{
  const void *fdt;
  const char *path;
  int node;
  imx_i2c_bus *bus;
  int eno;

  fdt = bsp_fdt_get();
  path = fdt_get_alias(fdt, alias_or_path);

  if (path == NULL) {
    path = alias_or_path;
  }

  node = fdt_path_offset(fdt, path);
  if (node < 0) {
    rtems_set_errno_and_return_minus_one(ENXIO);
  }

  bus = (imx_i2c_bus *) i2c_bus_alloc_and_init(sizeof(*bus));
  if (bus == NULL){
    return -1;
  }

  bus->regs = imx_get_reg_of_node(fdt, node);
  bus->irq = imx_get_irq_of_node(fdt, node, 0);

  eno = imx_i2c_init(bus);
  if (eno != 0) {
    (*bus->base.destroy)(&bus->base);
    rtems_set_errno_and_return_minus_one(eno);
  }

  bus->base.transfer = imx_i2c_transfer;
  bus->base.set_clock = imx_i2c_set_clock;
  bus->base.destroy = imx_i2c_destroy;

  return i2c_bus_register(&bus->base, bus_path);
}
Example #9
0
void ft_cpu_setup(void *blob, bd_t *bd)
{
	int off;
	int val;
	const char *sysclk_path;
	struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
	unsigned int svr;
	svr = in_be32(&gur->svr);

	unsigned long busclk = get_bus_freq(0);

	/* delete crypto node if not on an E-processor */
	if (!IS_E_PROCESSOR(svr))
		fdt_fixup_crypto_node(blob, 0);
#if CONFIG_SYS_FSL_SEC_COMPAT >= 4
	else {
		ccsr_sec_t __iomem *sec;

		sec = (void __iomem *)CONFIG_SYS_FSL_SEC_ADDR;
		fdt_fixup_crypto_node(blob, sec_in32(&sec->secvid_ms));
	}
#endif

	off = fdt_node_offset_by_prop_value(blob, -1, "device_type", "cpu", 4);
	while (off != -FDT_ERR_NOTFOUND) {
		val = gd->cpu_clk;
		fdt_setprop(blob, off, "clock-frequency", &val, 4);
		off = fdt_node_offset_by_prop_value(blob, off,
						    "device_type", "cpu", 4);
	}

	do_fixup_by_prop_u32(blob, "device_type", "soc",
			     4, "bus-frequency", busclk, 1);

	ft_fixup_enet_phy_connect_type(blob);

#ifdef CONFIG_SYS_NS16550
	do_fixup_by_compat_u32(blob, "fsl,16550-FIFO64",
			       "clock-frequency", CONFIG_SYS_NS16550_CLK, 1);
#endif

	sysclk_path = fdt_get_alias(blob, "sysclk");
	if (sysclk_path)
		do_fixup_by_path_u32(blob, sysclk_path, "clock-frequency",
				     CONFIG_SYS_CLK_FREQ, 1);
	do_fixup_by_compat_u32(blob, "fsl,qoriq-sysclk-2.0",
			       "clock-frequency", CONFIG_SYS_CLK_FREQ, 1);

#if defined(CONFIG_DEEP_SLEEP) && defined(CONFIG_SD_BOOT)
#define UBOOT_HEAD_LEN	0x1000
	/*
	 * Reserved memory in SD boot deep sleep case.
	 * Second stage uboot binary and malloc space should be reserved.
	 * If the memory they occupied has not been reserved, then this
	 * space would be used by kernel and overwritten in uboot when
	 * deep sleep resume, which cause deep sleep failed.
	 * Since second uboot binary has a head, that space need to be
	 * reserved either(assuming its size is less than 0x1000).
	 */
	off = fdt_add_mem_rsv(blob, CONFIG_SYS_TEXT_BASE - UBOOT_HEAD_LEN,
			CONFIG_SYS_MONITOR_LEN + CONFIG_SYS_SPL_MALLOC_SIZE +
			UBOOT_HEAD_LEN);
	if (off < 0)
		printf("Failed to reserve memory for SD boot deep sleep: %s\n",
		       fdt_strerror(off));
#endif

#if defined(CONFIG_FSL_ESDHC)
	fdt_fixup_esdhc(blob, bd);
#endif

	/*
	 * platform bus clock = system bus clock/2
	 * Here busclk = system bus clock
	 * We are using the platform bus clock as 1588 Timer reference
	 * clock source select
	 */
	do_fixup_by_compat_u32(blob, "fsl, gianfar-ptp-timer",
			       "timer-frequency", busclk / 2, 1);

	/*
	 * clock-freq should change to clock-frequency and
	 * flexcan-v1.0 should change to p1010-flexcan respectively
	 * in the future.
	 */
	do_fixup_by_compat_u32(blob, "fsl, flexcan-v1.0",
			       "clock_freq", busclk / 2, 1);

	do_fixup_by_compat_u32(blob, "fsl, flexcan-v1.0",
			       "clock-frequency", busclk / 2, 1);

	do_fixup_by_compat_u32(blob, "fsl, ls1021a-flexcan",
			       "clock-frequency", busclk / 2, 1);

#if defined(CONFIG_QSPI_BOOT) || defined(CONFIG_SD_BOOT_QSPI)
	off = fdt_node_offset_by_compat_reg(blob, FSL_IFC_COMPAT,
					    CONFIG_SYS_IFC_ADDR);
	fdt_set_node_status(blob, off, FDT_STATUS_DISABLED, 0);
#else
	off = fdt_node_offset_by_compat_reg(blob, FSL_QSPI_COMPAT,
					    QSPI0_BASE_ADDR);
	fdt_set_node_status(blob, off, FDT_STATUS_DISABLED, 0);
	off = fdt_node_offset_by_compat_reg(blob, FSL_DSPI_COMPAT,
					    DSPI1_BASE_ADDR);
	fdt_set_node_status(blob, off, FDT_STATUS_DISABLED, 0);
#endif
}
Example #10
0
/*
 * Check if the /secure-chosen node in the DT contains an stdout-path value
 * for which we have a compatible driver. If so, switch the console to
 * this device.
 */
void configure_console_from_dt(unsigned long phys_fdt)
{
	const struct dt_driver *dt_drv;
	const struct serial_driver *sdrv;
	const struct fdt_property *prop;
	struct serial_chip *dev;
	char *stdout_data;
	const char *uart;
	const char *parms = NULL;
	void *fdt;
	int offs;
	char *p;

	if (!phys_fdt)
		return;
	fdt = phys_to_virt(phys_fdt, MEM_AREA_IO_NSEC);
	if (!fdt)
		panic();

	offs = fdt_path_offset(fdt, "/secure-chosen");
	if (offs < 0)
		return;
	prop = fdt_get_property(fdt, offs, "stdout-path", NULL);
	if (!prop) {
		/*
		 * /secure-chosen node present but no stdout-path property
		 * means we don't want any console output
		 */
		IMSG("Switching off console");
		register_serial_console(NULL);
		return;
	}

	stdout_data = strdup(prop->data);
	if (!stdout_data)
		return;
	p = strchr(stdout_data, ':');
	if (p) {
		*p = '\0';
		parms = p + 1;
	}

	/* stdout-path may refer to an alias */
	uart = fdt_get_alias(fdt, stdout_data);
	if (!uart) {
		/* Not an alias, assume we have a node path */
		uart = stdout_data;
	}
	offs = fdt_path_offset(fdt, uart);
	if (offs < 0)
		goto out;

	dt_drv = dt_find_compatible_driver(fdt, offs);
	if (!dt_drv)
		goto out;

	sdrv = (const struct serial_driver *)dt_drv->driver;
	if (!sdrv)
		goto out;
	dev = sdrv->dev_alloc();
	if (!dev)
		goto out;
	/*
	 * If the console is the same as the early console, dev_init() might
	 * clear pending data. Flush to avoid that.
	 */
	console_flush();
	if (sdrv->dev_init(dev, fdt, offs, parms) < 0) {
		sdrv->dev_free(dev);
		goto out;
	}

	IMSG("Switching console to device: %s", uart);
	register_serial_console(dev);
out:
	free(stdout_data);
}
Example #11
0
DebugUART *
debug_uart_from_fdt(const void *fdt)
{
	const char *name;
	const char *type;
	int node;
	int len;
	phys_addr_t regs;
	int32 clock = 0;
	int32 speed = 0;
	const void *prop;
	DebugUART *uart = NULL;

	if (fdt == NULL)
		return NULL;

	name = fdt_get_alias(fdt, "serial");
	if (name == NULL)
		name = fdt_get_alias(fdt, "serial0");
	if (name == NULL)
		name = fdt_get_alias(fdt, "serial1");
	// TODO: else use /chosen linux,stdout-path
	if (name == NULL)
		return NULL;

	node = fdt_path_offset(fdt, name);
	//dprintf("serial: using '%s', node %d\n", name, node);
	if (node < 0)
		return NULL;

	type = (const char *)fdt_getprop(fdt, node, "device_type", &len);
	//dprintf("serial: type: '%s'\n", type);
	if (type == NULL || strcmp(type, "serial"))
		return NULL;

	// determine the MMIO address
	// TODO: ppc460 use 64bit addressing, but U-Boot seems to map it below 4G,
	// and the FDT is not very clear. libfdt is also getting 64bit addr support.
	// so FIXME someday.
	prop = fdt_getprop(fdt, node, "virtual-reg", &len);
	if (prop && len == 4) {
		regs = fdt32_to_cpu(*(uint32_t *)prop);
		//dprintf("serial: virtual-reg 0x%08llx\n", (int64)regs);
	} else {
		prop = fdt_getprop(fdt, node, "reg", &len);
		if (prop && len >= 4) {
			regs = fdt32_to_cpu(*(uint32_t *)prop);
			//dprintf("serial: reg 0x%08llx\n", (int64)regs);
		} else
			return NULL;
	}

	// get the UART clock rate
	prop = fdt_getprop(fdt, node, "clock-frequency", &len);
	if (prop && len == 4) {
		clock = fdt32_to_cpu(*(uint32_t *)prop);
		//dprintf("serial: clock %ld\n", clock);
	}

	// get current speed (XXX: not yet passed over)
	prop = fdt_getprop(fdt, node, "current-speed", &len);
	if (prop && len == 4) {
		speed = fdt32_to_cpu(*(uint32_t *)prop);
		//dprintf("serial: speed %ld\n", speed);
	}

	if (fdt_node_check_compatible(fdt, node, "ns16550a") == 1
		|| fdt_node_check_compatible(fdt, node, "ns16550") == 1) {
		uart = arch_get_uart_8250(regs, clock);
		//dprintf("serial: using 8250\n");
		// XXX:assume speed is already set
		(void)speed;
	} else {
		// TODO: handle more UART types
		// for when we can use U-Boot's console
		panic("Unknown UART type %s", type);
	}

	return uart;
}
static void process_boot_dtb(void *boot_dtb)
{
	const u32 *na, *ns, *reg, *val32;
	const char *path;
	u64 memsize64;
	int node, size, i;

	/* Make sure FDT blob is sane */
	if (fdt_check_header(boot_dtb) != 0)
		fatal("Invalid device tree blob\n");

	/* Find the #address-cells and #size-cells properties */
	node = fdt_path_offset(boot_dtb, "/");
	if (node < 0)
		fatal("Cannot find root node\n");
	na = fdt_getprop(boot_dtb, node, "#address-cells", &size);
	if (!na || (size != 4))
		fatal("Cannot find #address-cells property");

	ns = fdt_getprop(boot_dtb, node, "#size-cells", &size);
	if (!ns || (size != 4))
		fatal("Cannot find #size-cells property");

	/* Find the memory range */
	node = fdt_node_offset_by_prop_value(boot_dtb, -1, "device_type",
					     "memory", sizeof("memory"));
	if (node < 0)
		fatal("Cannot find memory node\n");
	reg = fdt_getprop(boot_dtb, node, "reg", &size);
	if (size < (*na+*ns) * sizeof(u32))
		fatal("cannot get memory range\n");

	/* Only interested in memory based at 0 */
	for (i = 0; i < *na; i++)
		if (*reg++ != 0)
			fatal("Memory range is not based at address 0\n");

	/* get the memsize and trucate it to under 4G on 32 bit machines */
	memsize64 = 0;
	for (i = 0; i < *ns; i++)
		memsize64 = (memsize64 << 32) | *reg++;
	if (sizeof(void *) == 4 && memsize64 >= 0x100000000ULL)
		memsize64 = 0xffffffff;

	mem_size = memsize64;

	/* get clock frequencies */
	node = fdt_node_offset_by_prop_value(boot_dtb, -1, "device_type",
					     "cpu", sizeof("cpu"));
	if (!node)
		fatal("Cannot find cpu node\n");

	val32 = fdt_getprop(boot_dtb, node, "clock-frequency", &size);
	if (!val32 || (size != 4))
		fatal("Cannot get clock frequency");

	int_freq = *val32;

	val32 = fdt_getprop(boot_dtb, node, "bus-frequency", &size);
	if (!val32 || (size != 4))
		fatal("Cannot get bus frequency");

	bus_freq = *val32;

	path = fdt_get_alias(boot_dtb, "ethernet0");
	if (path) {
		const void *p;

		node = fdt_path_offset(boot_dtb, path);
		if (node < 0)
			fatal("Cannot find ethernet0 node");

		p = fdt_getprop(boot_dtb, node, "mac-address", &size);
		if (!p || (size < 6)) {
			printf("no mac-address property, finding local\n\r");
			p = fdt_getprop(boot_dtb, node, "local-mac-address", &size);
		}

		if (!p || (size < 6))
			fatal("cannot get MAC addres");

		memcpy(enetaddr, p, sizeof(enetaddr));
	}
}