示例#1
0
int
fdt_immr_addr(vm_offset_t immr_va)
{
	phandle_t node;
	u_long base, size;
	int r;

	/*
	 * Try to access the SOC node directly i.e. through /aliases/.
	 */
	if ((node = OF_finddevice("soc")) != 0)
		if (fdt_is_compatible(node, "simple-bus"))
			goto moveon;
	/*
	 * Find the node the long way.
	 */
	if ((node = OF_finddevice("/")) == 0)
		return (ENXIO);

	if ((node = fdt_find_compatible(node, "simple-bus", 0)) == 0)
		return (ENXIO);

moveon:
	if ((r = fdt_get_range(node, 0, &base, &size)) == 0) {
		fdt_immr_pa = base;
		fdt_immr_va = immr_va;
		fdt_immr_size = size;
	}

	return (r);
}
示例#2
0
int
mv_msi_data(int irq, uint64_t *addr, uint32_t *data)
{
	u_long phys, base, size;
	phandle_t node;
	int error;

	node = ofw_bus_get_node(mv_mpic_sc->sc_dev);

	/* Get physical addres of register space */
	error = fdt_get_range(OF_parent(node), 0, &phys, &size);
	if (error) {
		printf("%s: Cannot get register physical address, err:%d",
		    __func__, error);
		return (error);
	}

	/* Get offset of MPIC register space */
	error = fdt_regsize(node, &base, &size);
	if (error) {
		printf("%s: Cannot get MPIC register offset, err:%d",
		    __func__, error);
		return (error);
	}

	*addr = phys + base + MPIC_SOFT_INT;
	*data = MPIC_SOFT_INT_DRBL1 | irq;

	return (0);
}
示例#3
0
int
fdt_reg_to_rl(phandle_t node, struct resource_list *rl)
{
	u_long end, count, start;
	pcell_t *reg, *regptr;
	pcell_t addr_cells, size_cells;
	int tuple_size, tuples;
	int i, rv;
	long busaddr, bussize;

	if (fdt_addrsize_cells(OF_parent(node), &addr_cells, &size_cells) != 0)
		return (ENXIO);
	if (fdt_get_range(OF_parent(node), 0, &busaddr, &bussize)) {
		busaddr = 0;
		bussize = 0;
	}

	tuple_size = sizeof(pcell_t) * (addr_cells + size_cells);
	tuples = OF_getprop_alloc(node, "reg", tuple_size, (void **)&reg);
	debugf("addr_cells = %d, size_cells = %d\n", addr_cells, size_cells);
	debugf("tuples = %d, tuple size = %d\n", tuples, tuple_size);
	if (tuples <= 0)
		/* No 'reg' property in this node. */
		return (0);

	regptr = reg;
	for (i = 0; i < tuples; i++) {

		rv = fdt_data_to_res(reg, addr_cells, size_cells, &start,
		    &count);
		if (rv != 0) {
			resource_list_free(rl);
			goto out;
		}
		reg += addr_cells + size_cells;

		/* Calculate address range relative to base. */
		start += busaddr;
		end = start + count - 1;

		debugf("reg addr start = %lx, end = %lx, count = %lx\n", start,
		    end, count);

		resource_list_add(rl, SYS_RES_MEMORY, i, start, end,
		    count);
	}
	rv = 0;

out:
	free(regptr, M_OFWPROP);
	return (rv);
}
示例#4
0
static int
alloc_resource_for_node(phandle_t node, struct resource *res, u_long *size)
{
	int err;
	u_long pbase, psize;
	u_long start;

	if ((err = fdt_get_range(OF_parent(node), 0, &pbase, &psize)) != 0 ||
	    (err = fdt_regsize(node, &start, size)) != 0)
		return (err);

	start += pbase;

	memset(res, 0, sizeof(*res));

	res->r_bustag = fdtbus_bs_tag;

	err = bus_space_map(res->r_bustag, start, *size, 0, &res->r_bushandle);

	return (err);
}
示例#5
0
int
uart_cpu_getdev(int devtype, struct uart_devinfo *di)
{
	char buf[64];
	struct uart_class *class;
	phandle_t node, chosen;
	pcell_t shift, br, rclk;
	u_long start, size, pbase, psize;
	int err;

	uart_bus_space_mem = fdtbus_bs_tag;
	uart_bus_space_io = NULL;

	/* Allow overriding the FDT uning the environment. */
	class = &uart_ns8250_class;
	err = uart_getenv(devtype, di, class);
	if (!err)
		return (0);

	if (devtype != UART_DEV_CONSOLE)
		return (ENXIO);

	/*
	 * Retrieve /chosen/std{in,out}.
	 */
	if ((chosen = OF_finddevice("/chosen")) == -1)
		return (ENXIO);
	if (OF_getprop(chosen, "stdin", buf, sizeof(buf)) <= 0)
		return (ENXIO);
	if ((node = OF_finddevice(buf)) == -1)
		return (ENXIO);
	if (OF_getprop(chosen, "stdout", buf, sizeof(buf)) <= 0)
		return (ENXIO);
	if (OF_finddevice(buf) != node)
		/* Only stdin == stdout is supported. */
		return (ENXIO);
	/*
	 * Retrieve serial attributes.
	 */
	uart_fdt_get_shift(node, &shift);

	if (OF_getprop(node, "current-speed", &br, sizeof(br)) <= 0)
		br = 0;
	br = fdt32_to_cpu(br);

	if ((err = uart_fdt_get_clock(node, &rclk)) != 0)
		return (err);
	/*
	 * Finalize configuration.
	 */
	if (fdt_is_compatible(node, "quicc"))
		class = &uart_quicc_class;
	if (fdt_is_compatible(node, "lpc"))
		class = &uart_lpc_class;
	if (fdt_is_compatible(node, "ns16550"))
		class = &uart_ns8250_class;
	if (fdt_is_compatible(node, "arm,pl011"))
		class = &uart_pl011_class;

	di->bas.chan = 0;
	di->bas.regshft = (u_int)shift;
	di->baudrate = br;
	di->bas.rclk = (u_int)rclk;
	di->ops = uart_getops(class);
	di->databits = 8;
	di->stopbits = 1;
	di->parity = UART_PARITY_NONE;
	di->bas.bst = uart_bus_space_mem;

	err = fdt_regsize(node, &start, &size);
	if (err)
		return (ENXIO);
	err = fdt_get_range(OF_parent(node), 0, &pbase, &psize);
	if (err)
		pbase = 0;

	start += pbase;

	return (bus_space_map(di->bas.bst, start, size, 0, &di->bas.bsh));
}