Пример #1
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);
}
Пример #2
0
/*
 * BERI startup conforms to the spin-table start method defined in the
 * ePAPR 1.0 spec.  The initial spin waiting for an address is started
 * by the CPU firmware.
 */
int
platform_start_ap(int cpuid)
{
	phandle_t cpu;
	char prop[16];
	struct spin_entry *se;

	KASSERT(cpuid != 0, ("%s: can't start CPU 0!\n", __func__));
	KASSERT((cpuid > 0 && cpuid < MAXCPU),
	    ("%s: invalid CPU id %d", __func__, cpuid));

	cpu = cpu_of_nodes[cpuid];
	if (OF_getprop(cpu, "status", &prop, sizeof(prop)) <= 0) {
		if (bootverbose)
			printf("%s: CPU %d has no status property, "
			    "trying parent\n", __func__, cpuid);
		if (OF_getprop(OF_parent(cpu), "status", &prop,
		    sizeof(prop)) <= 0)
			panic("%s: CPU %d has no status property", __func__,
			    cpuid);
	}
	if (strcmp("disabled", prop) != 0)
		panic("%s: CPU %d status is '%s' not 'disabled'",
		    __func__, cpuid, prop);

	if (OF_getprop(cpu, "enable-method", &prop, sizeof(prop)) <= 0) {
		if (bootverbose)
			printf("%s: CPU %d has no enable-method, "
			    "trying parent\n", __func__, cpuid);
		if (OF_getprop(OF_parent(cpu), "enable-method", &prop,
		    sizeof(prop)) <= 0)
			panic("%s: CPU %d has no enable-method property",
			    __func__, cpuid);
	}
	if (strcmp("spin-table", prop) != 0)
		panic("%s: CPU %d enable-method is '%s' not "
		    "'spin-table'", __func__, cpuid, prop);

	if (OF_getprop(cpu, "cpu-release-addr", &se, sizeof(se)) <= 0)
		panic("%s: CPU %d has missing or invalid cpu-release-addr",
		    __func__, cpuid);
	se->pir = cpuid;
	if (bootverbose)
		printf("%s: writing %p to %p\n", __func__, mpentry,
		    &se->entry_addr);

	mips_sync();	/* Ordering. */
	se->entry_addr = (intptr_t)mpentry;
	mips_sync();	/* Liveness. */

	return (0);
}
Пример #3
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);
}
Пример #4
0
int
ofw_pci_nranges(phandle_t node, struct ofw_pci_cell_info *info)
{
	ssize_t nbase_ranges;

	if (info == NULL)
		return (-1);

	info->host_address_cells = 1;
	info->size_cells = 2;
	info->pci_address_cell = 3;

	OF_getencprop(OF_parent(node), "#address-cells",
	    &(info->host_address_cells), sizeof(info->host_address_cells));
	OF_getencprop(node, "#address-cells",
	    &(info->pci_address_cell), sizeof(info->pci_address_cell));
	OF_getencprop(node, "#size-cells", &(info->size_cells),
	    sizeof(info->size_cells));

	nbase_ranges = OF_getproplen(node, "ranges");
	if (nbase_ranges <= 0)
		return (-1);

	return (nbase_ranges / sizeof(cell_t) /
	    (info->pci_address_cell + info->host_address_cells +
	    info->size_cells));
}
Пример #5
0
int
fdt_get_reserved_regions(struct mem_region *mr, int *mrcnt)
{
	pcell_t reserve[FDT_REG_CELLS * FDT_MEM_REGIONS];
	pcell_t *reservep;
	phandle_t memory, root;
	uint32_t memory_size;
	int addr_cells, size_cells;
	int i, max_size, res_len, rv, tuple_size, tuples;

	max_size = sizeof(reserve);
	root = OF_finddevice("/");
	memory = OF_finddevice("/memory");
	if (memory == -1) {
		rv = ENXIO;
		goto out;
	}

	if ((rv = fdt_addrsize_cells(OF_parent(memory), &addr_cells,
	    &size_cells)) != 0)
		goto out;

	if (addr_cells > 2) {
		rv = ERANGE;
		goto out;
	}

	tuple_size = sizeof(pcell_t) * (addr_cells + size_cells);

	res_len = OF_getproplen(root, "memreserve");
	if (res_len <= 0 || res_len > sizeof(reserve)) {
		rv = ERANGE;
		goto out;
	}

	if (OF_getprop(root, "memreserve", reserve, res_len) <= 0) {
		rv = ENXIO;
		goto out;
	}

	memory_size = 0;
	tuples = res_len / tuple_size;
	reservep = (pcell_t *)&reserve;
	for (i = 0; i < tuples; i++) {

		rv = fdt_data_to_res(reservep, addr_cells, size_cells,
			(u_long *)&mr[i].mr_start, (u_long *)&mr[i].mr_size);

		if (rv != 0)
			goto out;

		reservep += addr_cells + size_cells;
	}

	*mrcnt = i;
	rv = 0;
out:
	return (rv);
}
Пример #6
0
int
vbus_intr_map(int node, int ino, uint64_t *sysino)
{
	int *imap = NULL, nimap;
	int *reg = NULL, nreg;
	int *imap_mask;
	int parent;
	int address_cells, interrupt_cells;
	uint64_t devhandle;
	uint64_t devino;
	int len;
	int err;

	parent = OF_parent(node);

	address_cells = getpropint(parent, "#address-cells", 2);
	interrupt_cells = getpropint(parent, "#interrupt-cells", 1);
	KASSERT(interrupt_cells == 1);

	len = OF_getproplen(parent, "interrupt-map-mask");
	if (len < (address_cells + interrupt_cells) * sizeof(int))
		return (-1);
	imap_mask = malloc(len, M_DEVBUF, M_NOWAIT);
	if (imap_mask == NULL)
		return (-1);
	if (OF_getprop(parent, "interrupt-map-mask", imap_mask, len) != len)
		return (-1);

	getprop(parent, "interrupt-map", sizeof(int), &nimap, (void **)&imap);
	getprop(node, "reg", sizeof(*reg), &nreg, (void **)&reg);
	if (nreg < address_cells)
		return (-1);

	while (nimap >= address_cells + interrupt_cells + 2) {
		if (vbus_cmp_cells(imap, reg, imap_mask, address_cells) &&
		    vbus_cmp_cells(&imap[address_cells], &ino,
		    &imap_mask[address_cells], interrupt_cells)) {
			node = imap[address_cells + interrupt_cells];
			devino = imap[address_cells + interrupt_cells + 1];

			free(reg, M_DEVBUF, 0);
			reg = NULL;

			getprop(node, "reg", sizeof(*reg), &nreg, (void **)&reg);
			devhandle = reg[0] & 0x0fffffff;

			err = hv_intr_devino_to_sysino(devhandle, devino, sysino);
			if (err != H_EOK)
				return (-1);

			KASSERT(*sysino == INTVEC(*sysino));
			return (0);
		}
		imap += address_cells + interrupt_cells + 2;
		nimap -= address_cells + interrupt_cells + 2;
	}

	return (-1);
}
Пример #7
0
int
fdt_get_range(phandle_t node, int range_id, u_long *base, u_long *size)
{
	pcell_t ranges[6], *rangesptr;
	pcell_t addr_cells, size_cells, par_addr_cells;
	u_long par_bus_addr, pbase, psize;
	int err, len, tuple_size, tuples;

	if ((fdt_addrsize_cells(node, &addr_cells, &size_cells)) != 0)
		return (ENXIO);
	/*
	 * Process 'ranges' property.
	 */
	par_addr_cells = fdt_parent_addr_cells(node);
	if (par_addr_cells > 2)
		return (ERANGE);

	len = OF_getproplen(node, "ranges");
	if (len > sizeof(ranges))
		return (ENOMEM);
	if (len == 0) {
		*base = 0;
		*size = ULONG_MAX;
		return (0);
	}

	if (!(range_id < len))
		return (ERANGE);

	if (OF_getprop(node, "ranges", ranges, sizeof(ranges)) <= 0)
		return (EINVAL);

	tuple_size = sizeof(pcell_t) * (addr_cells + par_addr_cells +
	    size_cells);
	tuples = len / tuple_size;

	if (par_addr_cells > 2 || addr_cells > 2 || size_cells > 2)
		return (ERANGE);

	*base = 0;
	*size = 0;
	rangesptr = &ranges[range_id];

	*base = fdt_data_get((void *)rangesptr, addr_cells);
	rangesptr += addr_cells;

	par_bus_addr = fdt_data_get((void *)rangesptr, par_addr_cells);
	rangesptr += par_addr_cells;

	err = fdt_get_range_by_busaddr(OF_parent(node), par_bus_addr,
	   &pbase, &psize);
	if (err == 0)
		*base += pbase;
	else
		*base += par_bus_addr;

	*size = fdt_data_get((void *)rangesptr, size_cells);
	return (0);
}
Пример #8
0
static int
fdt_lbc_reg_decode(phandle_t node, struct lbc_softc *sc,
    struct lbc_devinfo *di)
{
	rman_res_t start, end, count;
	pcell_t *reg, *regptr;
	pcell_t addr_cells, size_cells;
	int tuple_size, tuples;
	int i, j, rv, bank;

	if (fdt_addrsize_cells(OF_parent(node), &addr_cells, &size_cells) != 0)
		return (ENXIO);

	tuple_size = sizeof(pcell_t) * (addr_cells + size_cells);
	tuples = OF_getencprop_alloc_multi(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++) {

		bank = fdt_data_get((void *)reg, 1);
		di->di_bank = bank;
		reg += 1;

		/* Get address/size. */
		start = count = 0;
		for (j = 0; j < addr_cells; j++) {
			start <<= 32;
			start |= reg[j];
		}
		for (j = 0; j < size_cells; j++) {
			count <<= 32;
			count |= reg[addr_cells + j - 1];
		}
		reg += addr_cells - 1 + size_cells;

		/* Calculate address range relative to VA base. */
		start = sc->sc_banks[bank].kva + start;
		end = start + count - 1;

		debugf("reg addr bank = %d, start = %jx, end = %jx, "
		    "count = %jx\n", bank, start, end, count);

		/* Use bank (CS) cell as rid. */
		resource_list_add(&di->di_res, SYS_RES_MEMORY, bank, start,
		    end, count);
	}
	rv = 0;
	OF_prop_free(regptr);
	return (rv);
}
Пример #9
0
static int
rk30_gpio_init(void)
{
	phandle_t child, parent, root, ctrl;
	pcell_t gpios[MAX_PINS_PER_NODE * GPIOS_PROP_CELLS];
	struct gpio_ctrl_entry *e;
	int len, rv;

	root = OF_finddevice("/");
	len = 0;
	parent = root;

	/* Traverse through entire tree to find nodes with 'gpios' prop */
	for (child = OF_child(parent); child != 0; child = OF_peer(child)) {

		/* Find a 'leaf'. Start the search from this node. */
		while (OF_child(child)) {
			parent = child;
			child = OF_child(child);
		}
		if ((len = OF_getproplen(child, "gpios")) > 0) {

			if (len > sizeof(gpios))
				return (ENXIO);

			/* Get 'gpios' property. */
			OF_getprop(child, "gpios", &gpios, len);

			e = (struct gpio_ctrl_entry *)&gpio_controllers;

			/* Find and call a handler. */
			for (; e->compat; e++) {
				/*
				 * First cell of 'gpios' property should
				 * contain a ref. to a node defining GPIO
				 * controller.
				 */
				ctrl = OF_node_from_xref(fdt32_to_cpu(gpios[0]));

				if (fdt_is_compatible(ctrl, e->compat))
					/* Call a handler. */
					if ((rv = e->handler(ctrl,
					    (pcell_t *)&gpios, len)))
						return (rv);
			}
		}

		if (OF_peer(child) == 0) {
			/* No more siblings. */
			child = parent;
			parent = OF_parent(child);
		}
	}
	return (0);
}
Пример #10
0
void
fix_node_irq(int node, struct pcibus_attach_args *pba)
{
	struct { 
		u_int32_t phys_hi, phys_mid, phys_lo;
		u_int32_t size_hi, size_lo;
	} addr [8];
	u_int32_t map[144];
	int len;
	pcitag_t tag;
	u_int32_t irq;
	u_int32_t intr;
	int parent;

	pci_chipset_tag_t pc = pba->pba_pc;

	len = OF_getprop(node, "assigned-addresses", addr, sizeof(addr));
	if (len == -1 || len < sizeof(addr[0]))
		return;

	/* if this node has a AAPL,interrupts property, firmware
	 * has initialized the register correctly.
	 */
	len = OF_getprop(node, "AAPL,interrupts", &intr, 4);
	if (len != 4) {

		parent = OF_parent(node);

		irq = -1;

		/* we want the first interrupt, set size_hi to 1 */
		addr[0].size_hi = 1;
		if (find_node_intr(parent, &addr[0].phys_hi, &irq) == -1) {
			len = OF_getprop(node, "interrupts", map,
			    sizeof(map));
			if (len != -1 && len != 4) {
				irq = map[0];
			} else 
				return;
		}
	} else
		irq = intr;
	/* program the interrupt line register with the value
	 * found in openfirmware
	 */

	tag = pci_make_tag(pc, pcibus(addr[0].phys_hi),
	    pcidev(addr[0].phys_hi), pcifunc(addr[0].phys_hi));

	intr = pci_conf_read(pc, tag, PCI_INTERRUPT_REG);
	intr &= ~PCI_INTERRUPT_LINE_MASK;
	intr |= irq & PCI_INTERRUPT_LINE_MASK;
	pci_conf_write(pc, tag, PCI_INTERRUPT_REG, intr);
}
Пример #11
0
int
fdt_parent_addr_cells(phandle_t node)
{
	pcell_t addr_cells;

	/* Find out #address-cells of the superior bus. */
	if (OF_searchprop(OF_parent(node), "#address-cells", &addr_cells,
	    sizeof(addr_cells)) <= 0)
		return (2);

	return ((int)fdt32_to_cpu(addr_cells));
}
Пример #12
0
u_int
OF_getscsinitid(device_t dev)
{
	phandle_t node;
	uint32_t id;

	for (node = ofw_bus_get_node(dev); node != 0; node = OF_parent(node))
		if (OF_getprop(node, "scsi-initiator-id", &id,
		    sizeof(id)) > 0)
			return (id);
	return (7);
}
Пример #13
0
static int
fdt_lbc_reg_decode(phandle_t node, struct lbc_softc *sc,
    struct lbc_devinfo *di)
{
	u_long start, end, count;
	pcell_t *reg, *regptr;
	pcell_t addr_cells, size_cells;
	int tuple_size, tuples;
	int i, rv, bank;

	if (fdt_addrsize_cells(OF_parent(node), &addr_cells, &size_cells) != 0)
		return (ENXIO);

	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++) {

		bank = fdt_data_get((void *)reg, 1);
		di->di_bank = bank;
		reg += 1;

		/* Get address/size. */
		rv = fdt_data_to_res(reg, addr_cells - 1, size_cells, &start,
		    &count);
		if (rv != 0) {
			resource_list_free(&di->di_res);
			goto out;
		}
		reg += addr_cells - 1 + size_cells;

		/* Calculate address range relative to VA base. */
		start = sc->sc_banks[bank].kva + start;
		end = start + count - 1;

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

		/* Use bank (CS) cell as rid. */
		resource_list_add(&di->di_res, SYS_RES_MEMORY, bank, start,
		    end, count);
	}
	rv = 0;
out:
	free(regptr, M_OFWPROP);
	return (rv);
}
Пример #14
0
static int
pinmux_set(struct iomuxc_softc *sc)
{
	phandle_t child, parent, root;
	pcell_t iomux_config[MAX_MUX_LEN];
	int len;
	int values;
	int pin;
	int pin_cfg;
	int i;

	root = OF_finddevice("/");
	len = 0;
	parent = root;

	/* Find 'iomux_config' prop in the nodes */
	for (child = OF_child(parent); child != 0; child = OF_peer(child)) {

		/* Find a 'leaf'. Start the search from this node. */
		while (OF_child(child)) {
			parent = child;
			child = OF_child(child);
		}

		if (!fdt_is_enabled(child))
			continue;

		if ((len = OF_getproplen(child, "iomux_config")) > 0) {
			OF_getprop(child, "iomux_config", &iomux_config, len);

			values = len / (sizeof(uint32_t));
			for (i = 0; i < values; i += 2) {
				pin = fdt32_to_cpu(iomux_config[i]);
				pin_cfg = fdt32_to_cpu(iomux_config[i+1]);
#if 0
				device_printf(sc->dev, "Set pin %d to 0x%08x\n",
				    pin, pin_cfg);
#endif
				WRITE4(sc, IOMUXC(pin), pin_cfg);
			}
		}

		if (OF_peer(child) == 0) {
			/* No more siblings. */
			child = parent;
			parent = OF_parent(child);
		}
	}

	return (0);
}
Пример #15
0
static int
quicc_fdt_probe(device_t dev)
{
	phandle_t par;
	pcell_t clock;

	if (!ofw_bus_is_compatible(dev, "fsl,cpm2"))
		return (ENXIO);

	par = OF_parent(ofw_bus_get_node(dev));
	if (OF_getprop(par, "bus-frequency", &clock, sizeof(clock)) <= 0)
		clock = 0;

	return (quicc_bfe_probe(dev, (uintptr_t)clock));
}
Пример #16
0
static void
macio_add_reg(phandle_t devnode, struct macio_devinfo *dinfo)
{
	struct		macio_reg *reg, *regp;
	phandle_t 	child;
	char		buf[8];
	int		i, layout_id = 0, nreg, res;

	nreg = OF_getprop_alloc(devnode, "reg", sizeof(*reg), (void **)&reg);
	if (nreg == -1)
		return;

        /*
         *  Some G5's have broken properties in the i2s-a area. If so we try
         *  to fix it. Right now we know of two different cases, one for
         *  sound layout-id 36 and the other one for sound layout-id 76.
         *  What is missing is the base address for the memory addresses.
         *  We take them from the parent node (i2s) and use the size
         *  information from the child. 
         */

        if (reg[0].mr_base == 0) {
		child = OF_child(devnode);
		while (child != 0) {
			res = OF_getprop(child, "name", buf, sizeof(buf));
			if (res > 0 && strcmp(buf, "sound") == 0)
				break;
			child = OF_peer(child);
		}

                res = OF_getprop(child, "layout-id", &layout_id,
				sizeof(layout_id));

                if (res > 0 && (layout_id == 36 || layout_id == 76)) {
                        res = OF_getprop_alloc(OF_parent(devnode), "reg",
						sizeof(*regp), (void **)&regp);
                        reg[0] = regp[0];
                        reg[1].mr_base = regp[1].mr_base;
                        reg[2].mr_base = regp[1].mr_base + reg[1].mr_size;
                }
        } 

	for (i = 0; i < nreg; i++) {
		resource_list_add(&dinfo->mdi_resources, SYS_RES_MEMORY, i,
		    reg[i].mr_base, reg[i].mr_base + reg[i].mr_size,
		    reg[i].mr_size);
	}
}
Пример #17
0
static int
simplebus_fill_ranges(phandle_t node, struct simplebus_softc *sc)
{
	int host_address_cells;
	cell_t *base_ranges;
	ssize_t nbase_ranges;
	int err;
	int i, j, k;

	err = OF_searchencprop(OF_parent(node), "#address-cells",
	    &host_address_cells, sizeof(host_address_cells));
	if (err <= 0)
		return (-1);

	nbase_ranges = OF_getproplen(node, "ranges");
	if (nbase_ranges < 0)
		return (-1);
	sc->nranges = nbase_ranges / sizeof(cell_t) /
	    (sc->acells + host_address_cells + sc->scells);
	if (sc->nranges == 0)
		return (0);

	sc->ranges = malloc(sc->nranges * sizeof(sc->ranges[0]),
	    M_DEVBUF, M_WAITOK);
	base_ranges = malloc(nbase_ranges, M_DEVBUF, M_WAITOK);
	OF_getencprop(node, "ranges", base_ranges, nbase_ranges);

	for (i = 0, j = 0; i < sc->nranges; i++) {
		sc->ranges[i].bus = 0;
		for (k = 0; k < sc->acells; k++) {
			sc->ranges[i].bus <<= 32;
			sc->ranges[i].bus |= base_ranges[j++];
		}
		sc->ranges[i].host = 0;
		for (k = 0; k < host_address_cells; k++) {
			sc->ranges[i].host <<= 32;
			sc->ranges[i].host |= base_ranges[j++];
		}
		sc->ranges[i].size = 0;
		for (k = 0; k < sc->scells; k++) {
			sc->ranges[i].size <<= 32;
			sc->ranges[i].size |= base_ranges[j++];
		}
	}

	free(base_ranges, M_DEVBUF);
	return (sc->nranges);
}
Пример #18
0
/*
 * Get interrupt parent for given node.
 * Returns 0 if interrupt parent doesn't exist.
 */
phandle_t
ofw_bus_find_iparent(phandle_t node)
{
	phandle_t iparent;

	if (OF_searchencprop(node, "interrupt-parent", &iparent,
		    sizeof(iparent)) == -1) {
		for (iparent = node; iparent != 0;
		    iparent = OF_parent(iparent)) {
			if (OF_hasprop(iparent, "interrupt-controller"))
				break;
		}
		iparent = OF_xref_from_node(iparent);
	}
	return (iparent);
}
Пример #19
0
int
uart_fdt_get_clock(phandle_t node, pcell_t *cell)
{

	/* clock-frequency is a FreeBSD-only extention. */
	if ((OF_getencprop(node, "clock-frequency", cell,
	    sizeof(*cell))) <= 0) {
		/* Try to retrieve parent 'bus-frequency' */
		/* XXX this should go to simple-bus fixup or so */
		if ((OF_getencprop(OF_parent(node), "bus-frequency", cell,
		    sizeof(*cell))) <= 0)
			*cell = 0;
	}

	return (0);
}
Пример #20
0
static int
ofw_pci_fill_ranges(phandle_t node, struct ofw_pci_range *ranges)
{
	int host_address_cells = 1, pci_address_cells = 3, size_cells = 2;
	cell_t *base_ranges;
	ssize_t nbase_ranges;
	int nranges;
	int i, j, k;

	OF_getprop(OF_parent(node), "#address-cells", &host_address_cells,
	    sizeof(host_address_cells));
	OF_getprop(node, "#address-cells", &pci_address_cells,
	    sizeof(pci_address_cells));
	OF_getprop(node, "#size-cells", &size_cells, sizeof(size_cells));

	nbase_ranges = OF_getproplen(node, "ranges");
	if (nbase_ranges <= 0)
		return (-1);
	nranges = nbase_ranges / sizeof(cell_t) /
	    (pci_address_cells + host_address_cells + size_cells);

	base_ranges = malloc(nbase_ranges, M_DEVBUF, M_WAITOK);
	OF_getprop(node, "ranges", base_ranges, nbase_ranges);

	for (i = 0, j = 0; i < nranges; i++) {
		ranges[i].pci_hi = base_ranges[j++];
		ranges[i].pci = 0;
		for (k = 0; k < pci_address_cells - 1; k++) {
			ranges[i].pci <<= 32;
			ranges[i].pci |= base_ranges[j++];
		}
		ranges[i].host = 0;
		for (k = 0; k < host_address_cells; k++) {
			ranges[i].host <<= 32;
			ranges[i].host |= base_ranges[j++];
		}
		ranges[i].size = 0;
		for (k = 0; k < size_cells; k++) {
			ranges[i].size <<= 32;
			ranges[i].size |= base_ranges[j++];
		}
	}

	free(base_ranges, M_DEVBUF);
	return (nranges);
}
Пример #21
0
void
pccbb_attach_hook(struct device *parent, struct device *self,
    struct pci_attach_args *pa)
{
	pci_chipset_tag_t pc = pa->pa_pc;
	int node = PCITAG_NODE(pa->pa_tag);
	int bus, busrange[2];

	if (OF_getprop(OF_parent(node), "bus-range", &busrange,
	    sizeof(busrange)) != sizeof(busrange))
		return;

	bus = busrange[0] + 1;
	while (bus < 256 && pc->busnode[bus])
		bus++;
	if (bus == 256)
		return;
	pc->busnode[bus] = node;
}
Пример #22
0
static int
ofw_pci_nranges(phandle_t node)
{
	int host_address_cells = 1, pci_address_cells = 3, size_cells = 2;
	ssize_t nbase_ranges;

	OF_getprop(OF_parent(node), "#address-cells", &host_address_cells,
	    sizeof(host_address_cells));
	OF_getprop(node, "#address-cells", &pci_address_cells,
	    sizeof(pci_address_cells));
	OF_getprop(node, "#size-cells", &size_cells, sizeof(size_cells));

	nbase_ranges = OF_getproplen(node, "ranges");
	if (nbase_ranges <= 0)
		return (-1);

	return (nbase_ranges / sizeof(cell_t) /
	    (pci_address_cells + host_address_cells + size_cells));
}
Пример #23
0
static int
uart_fdt_get_clock(phandle_t node, pcell_t *cell)
{
	pcell_t clock;

	if ((OF_getprop(node, "clock-frequency", &clock,
	    sizeof(clock))) <= 0)
		return (ENXIO);

	if (clock == 0)
		/* Try to retrieve parent 'bus-frequency' */
		/* XXX this should go to simple-bus fixup or so */
		if ((OF_getprop(OF_parent(node), "bus-frequency", &clock,
		    sizeof(clock))) <= 0)
			clock = 0;

	*cell = fdt32_to_cpu(clock);
	return (0);
}
Пример #24
0
static int
openpicbus_mambo_attach(device_t dev)
{
	uint64_t picaddr;
	phandle_t nexus;
	struct openpicbus_softc *sc;

	sc = device_get_softc(dev);

	nexus = OF_parent(ofw_bus_get_node(dev));

	OF_getprop(nexus,"platform-open-pic",
	    &picaddr,sizeof(picaddr));

	sc->picaddr = picaddr;

	device_add_child(dev,"openpic",-1);

	return (bus_generic_attach(dev));
}
Пример #25
0
int
fdt_regsize(phandle_t node, u_long *base, u_long *size)
{
	pcell_t reg[4];
	int addr_cells, len, size_cells;

	if (fdt_addrsize_cells(OF_parent(node), &addr_cells, &size_cells))
		return (ENXIO);

	if ((sizeof(pcell_t) * (addr_cells + size_cells)) > sizeof(reg))
		return (ENOMEM);

	len = OF_getprop(node, "reg", &reg, sizeof(reg));
	if (len <= 0)
		return (EINVAL);

	*base = fdt_data_get(&reg[0], addr_cells);
	*size = fdt_data_get(&reg[addr_cells], size_cells);
	return (0);
}
Пример #26
0
static int
gpioled_probe(device_t dev)
{
#ifdef FDT
	int match;
	phandle_t node;
	char *compat;

	/*
	 * We can match against our own node compatible string and also against
	 * our parent node compatible string.  The first is normally used to
	 * describe leds on a gpiobus and the later when there is a common node
	 * compatible with 'gpio-leds' which is used to concentrate all the
	 * leds nodes on the dts.
	 */
	match = 0;
	if (ofw_bus_is_compatible(dev, "gpioled"))
		match = 1;

	if (match == 0) {
		if ((node = ofw_bus_get_node(dev)) == -1)
			return (ENXIO);
		if ((node = OF_parent(node)) == -1)
			return (ENXIO);
		if (OF_getprop_alloc(node, "compatible", 1,
		    (void **)&compat) == -1)
			return (ENXIO);

		if (strcasecmp(compat, "gpio-leds") == 0)
			match = 1;

		free(compat, M_OFWPROP);
	}

	if (match == 0)
		return (ENXIO);
#endif
	device_set_desc(dev, "GPIO led");

	return (0);
}
Пример #27
0
int
nvmem_write_cell_by_idx(phandle_t node, int idx, void *cell, size_t buflen)
{
	phandle_t cell_node, prov_node;
	device_t provider;
	uint32_t reg[2];
	int rv;

	rv = nvmem_get_cell_node(node, idx, &cell_node);
	if (rv != 0)
		return (rv);

	prov_node = OF_parent(cell_node);
	if (OF_hasprop(prov_node, "read-only"))
		return (ENXIO);

	/* Validate the reg property */
	if (OF_getencprop(cell_node, "reg", reg, sizeof(reg)) != sizeof(reg)) {
		if (bootverbose)
			printf("nvmem_get_cell_by_idx: Cannot parse reg property of cell %d\n",
			    idx);
		return (ENXIO);
	}

	if (buflen != reg[1])
		return (EINVAL);

	provider = OF_device_from_xref(OF_xref_from_node(prov_node));
	if (provider == NULL) {
		if (bootverbose)
			printf("nvmem_get_cell_by_idx: Cannot find the nvmem device\n");
		return (ENXIO);
	}

	rv = NVMEM_WRITE(provider, reg[0], reg[1], cell);
	if (rv != 0) {
		return (rv);
	}

	return (0);
}
Пример #28
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);
}
Пример #29
0
static int
uart_fdt_get_clock(phandle_t node, pcell_t *cell)
{
	pcell_t clock;

	/*
	 * clock-frequency is a FreeBSD-specific hack. Make its presence optional.
	 */
	if ((OF_getprop(node, "clock-frequency", &clock,
	    sizeof(clock))) <= 0)
		clock = 0;

	if (clock == 0)
		/* Try to retrieve parent 'bus-frequency' */
		/* XXX this should go to simple-bus fixup or so */
		if ((OF_getprop(OF_parent(node), "bus-frequency", &clock,
		    sizeof(clock))) <= 0)
			clock = 0;

	*cell = fdt32_to_cpu(clock);
	return (0);
}
Пример #30
0
void
macppc_pci_attach_hook(device_t parent, device_t self, struct pcibus_attach_args *pba)
{
	pci_chipset_tag_t pc = pba->pba_pc;
	int bus = pba->pba_bus;
	int node, nn, sz;
	int32_t busrange[2];

	for (node = pc->pc_node; node; node = nn) {
		sz = OF_getprop(node, "bus-range", busrange, 8);
		if (sz == 8 && busrange[0] == bus) {
			fixpci(node, pc);
			return;
		}
		if ((nn = OF_child(node)) != 0)
			continue;
		while ((nn = OF_peer(node)) == 0) {
			node = OF_parent(node);
			if (node == pc->pc_node)
				return;		/* not found */
		}
	}
}