Exemple #1
0
/**
 * Populate platform configuration data.
 */
static int
bcm_init_platform_data(struct bcm_platform *bp)
{
	bus_addr_t		bus_addr, bus_size;
	bus_space_tag_t		erom_bst;
	bus_space_handle_t	erom_bsh;
	bool			aob, pmu;
	int			error;

	bus_addr = bcm_get_bus_addr();
	bus_size = bcm_get_bus_size();

#ifdef CFE
	/* Fetch CFE console handle (if any). Must be initialized before
	 * any calls to printf/early_putc. */
	if ((bp->cfe_console = cfe_getstdhandle(CFE_STDHANDLE_CONSOLE)) < 0)
		bp->cfe_console = -1;

	/* Probe CFE NVRAM sources */
	bp->nvram_io = &bcm_cfe_nvram.io;
	error = bcm_nvram_find_cfedev(&bcm_cfe_nvram, &bp->nvram_cls);
	if (error) {
		bp->nvram_io = NULL;
		bp->nvram_cls = NULL;
	}
#endif /* CFE */

	/* Probe and attach device table provider, populating our
	 * chip identification */
	erom_bst = mips_bus_space_generic;
	erom_bsh = BCM_SOC_BSH(bus_addr, 0);

	error = bhnd_erom_iobus_init(&bp->erom_io, bus_addr, bus_size, erom_bst,
	    erom_bsh);
	if (error) {
		BCM_ERR("failed to initialize erom I/O callbacks: %d\n", error);
		return (error);
	}

	error = bcm_erom_probe_and_attach(&bp->erom_impl, &bp->erom_ops,
	    &bp->erom.obj, sizeof(bp->erom), &bp->erom_io.eio, &bp->cid);
	if (error) {
		BCM_ERR("error attaching erom parser: %d\n", error);
		bhnd_erom_io_fini(&bp->erom_io.eio);
		return (error);
	}

	if (bootverbose)
		bhnd_erom_dump(&bp->erom.obj);

	/* Fetch chipcommon core info */
	error = bcm_find_core(bp, bcm_chipc_cores, nitems(bcm_chipc_cores),
	    &bp->cc_id, &bp->cc_addr);
	if (error) {
		BCM_ERR("error locating chipc core: %d\n", error);
		return (error);
	}

	/* Fetch chipc capability flags */
	bp->cc_caps = BCM_SOC_READ_4(bp->cc_addr, CHIPC_CAPABILITIES);
	bp->cc_caps_ext = 0x0;	

	if (CHIPC_HWREV_HAS_CAP_EXT(bp->cc_id.hwrev))
		bp->cc_caps_ext = BCM_CHIPC_READ_4(bp, CHIPC_CAPABILITIES_EXT);

	/* Fetch PMU info */
	pmu = CHIPC_GET_FLAG(bp->cc_caps, CHIPC_CAP_PMU);
	aob = CHIPC_GET_FLAG(bp->cc_caps_ext, CHIPC_CAP2_AOB);

	if (pmu && aob) {
		/* PMU block mapped to a PMU core on the Always-on-Bus (aob) */
		error = bcm_find_core(bp, bcm_pmu_cores, nitems(bcm_pmu_cores),
		    &bp->pmu_id,  &bp->pmu_addr);
		if (error) {
			BCM_ERR("error locating pmu core: %d\n", error);
			return (error);
		}
	} else if (pmu) {
		/* PMU block mapped to chipc */
		bp->pmu_addr = bp->cc_addr;
		bp->pmu_id = bp->cc_id;
	} else {
		/* No PMU */
		bp->pmu_addr = 0x0;
		memset(&bp->pmu_id, 0, sizeof(bp->pmu_id));
	}

	/* Initialize PMU query state */
	if (pmu) {
		error = bhnd_pmu_query_init(&bp->pmu, NULL, bp->cid,
		    &bcm_pmu_soc_io, bp);
		if (error) {
			BCM_ERR("bhnd_pmu_query_init() failed: %d\n", error);
			return (error);
		}
	}

	/* Find CPU core info */
	error = bcm_find_core(bp, bcm_cpu0_cores, nitems(bcm_cpu0_cores),
	    &bp->cpu_id,  &bp->cpu_addr);
	if (error) {
		BCM_ERR("error locating CPU core: %d\n", error);
		return (error);
	}

	/* Initialize our platform service registry */
	if ((error = bhnd_service_registry_init(&bp->services))) {
		BCM_ERR("error initializing service registry: %d\n", error);
		return (error);
	}

	bcm_platform_data_avail = true;
	return (0);
}
Exemple #2
0
/**
 * Default bhnd_pmu driver implementation of DEVICE_ATTACH().
 * 
 * @param dev PMU device.
 * @param res The PMU device registers. The driver will maintain a borrowed
 * reference to this resource for the lifetime of the device.
 */
int
bhnd_pmu_attach(device_t dev, struct bhnd_resource *res)
{
	struct bhnd_pmu_softc	*sc;
	struct sysctl_ctx_list	*ctx;
	struct sysctl_oid	*tree;
	devclass_t		 bhnd_class;
	device_t		 core, bus;
	int			 error;

	sc = device_get_softc(dev);
	sc->dev = dev;
	sc->quirks = 0;
	sc->res = res;

	/* Fetch capability flags */
	sc->caps = bhnd_bus_read_4(sc->res, BHND_PMU_CAP);

	/* Find the bus-attached core */
	bhnd_class = devclass_find("bhnd");
	core = sc->dev;
	while ((bus = device_get_parent(core)) != NULL) {
		if (device_get_devclass(bus) == bhnd_class)
			break;

		core = bus;
	}

	if (core == NULL) {
		device_printf(sc->dev, "bhnd bus not found\n");
		return (ENXIO);
	}

	/* Fetch chip and board info */
	sc->cid = *bhnd_get_chipid(core);

	if ((error = bhnd_read_board_info(core, &sc->board))) {
		device_printf(sc->dev, "error fetching board info: %d\n",
		    error);
		return (ENXIO);
	}

	/* Locate ChipCommon device */
	sc->chipc_dev = bhnd_find_child(bus, BHND_DEVCLASS_CC, 0);
	if (sc->chipc_dev == NULL) {
		device_printf(sc->dev, "chipcommon device not found\n");
		return (ENXIO);
	}

	/* Initialize query state */
	error = bhnd_pmu_query_init(&sc->query, dev, sc->cid, &bhnd_pmu_res_io,
	    sc);
	if (error)
		return (error);
	sc->io = sc->query.io; 
	sc->io_ctx = sc->query.io_ctx;

	BPMU_LOCK_INIT(sc);

	/* Set quirk flags */
	switch (sc->cid.chip_id) {
	case BHND_CHIPID_BCM4328:
	case BHND_CHIPID_BCM5354:
		/* HTAVAIL/ALPAVAIL are bitswapped in CLKCTL */
		sc->quirks |= BPMU_QUIRK_CLKCTL_CCS0;
		break;
	default:
		break;
	}

	/* Initialize PMU */
	if ((error = bhnd_pmu_init(sc))) {
		device_printf(sc->dev, "PMU init failed: %d\n", error);
		goto failed;
	}

	/* Set up sysctl nodes */
	ctx = device_get_sysctl_ctx(dev);
	tree = device_get_sysctl_tree(dev);

	SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
	    "bus_freq", CTLTYPE_UINT | CTLFLAG_RD, sc, 0,
	    bhnd_pmu_sysctl_bus_freq, "IU", "Bus clock frequency");

	SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
	    "cpu_freq", CTLTYPE_UINT | CTLFLAG_RD, sc, 0,
	    bhnd_pmu_sysctl_cpu_freq, "IU", "CPU clock frequency");
	
	SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
	    "mem_freq", CTLTYPE_UINT | CTLFLAG_RD, sc, 0,
	    bhnd_pmu_sysctl_mem_freq, "IU", "Memory clock frequency");

	return (0);

failed:
	BPMU_LOCK_DESTROY(sc);
	bhnd_pmu_query_fini(&sc->query);
	return (error);
}