Ejemplo n.º 1
0
static int
ocpbus_config_intr(device_t dev, int irq, enum intr_trigger trig, 
    enum intr_polarity pol)
{

	return (powerpc_config_intr(irq, trig, pol));
}
Ejemplo n.º 2
0
static int 
aoagpio_attach(device_t gpio)
{
	struct aoagpio_softc	*sc;
	struct resource		*r;
	void			*cookie;
	int			 irq, rid = 0;

	sc = device_get_softc(gpio);

	if ((1 << sc->ctrl) & GPIO_CTRL_EXTINT_SET) {
		r = bus_alloc_resource_any(gpio, SYS_RES_IRQ, &rid, RF_ACTIVE);
		if (r == NULL)
			return (ENXIO);

		irq = rman_get_start(r);
		DPRINTF(("interrupting at irq %d\n", irq));

		if (powerpc_config_intr(irq, INTR_TRIGGER_EDGE, 
		    INTR_POLARITY_LOW) != 0) 
			return (ENXIO);

		bus_setup_intr(gpio, r, INTR_TYPE_MISC | INTR_MPSAFE |
		    INTR_ENTROPY, NULL, aoagpio_int, gpio, &cookie);
	}

	return (0);
}
Ejemplo n.º 3
0
/*
 * Add an interrupt to the dev's resource list if present
 */
static void
unin_chip_add_intr(phandle_t devnode, struct unin_chip_devinfo *dinfo)
{
	phandle_t iparent;
	int	*intr;
	int	i, nintr;
	int 	icells;

	if (dinfo->udi_ninterrupts >= 6) {
		printf("unin: device has more than 6 interrupts\n");
		return;
	}

	nintr = OF_getprop_alloc(devnode, "interrupts", sizeof(*intr), 
		(void **)&intr);
	if (nintr == -1) {
		nintr = OF_getprop_alloc(devnode, "AAPL,interrupts", 
			sizeof(*intr), (void **)&intr);
		if (nintr == -1)
			return;
	}

	if (intr[0] == -1)
		return;

	if (OF_getprop(devnode, "interrupt-parent", &iparent, sizeof(iparent))
	    <= 0)
		panic("Interrupt but no interrupt parent!\n");

	if (OF_searchprop(iparent, "#interrupt-cells", &icells, sizeof(icells))
	    <= 0)
		icells = 1;

	for (i = 0; i < nintr; i+=icells) {
		u_int irq = MAP_IRQ(iparent, intr[i]);

		resource_list_add(&dinfo->udi_resources, SYS_RES_IRQ,
		    dinfo->udi_ninterrupts, irq, irq, 1);

		if (icells > 1) {
			powerpc_config_intr(irq,
			    (intr[i+1] & 1) ? INTR_TRIGGER_LEVEL :
			    INTR_TRIGGER_EDGE, INTR_POLARITY_LOW);
		}

		dinfo->udi_interrupts[dinfo->udi_ninterrupts] = irq;
		dinfo->udi_ninterrupts++;
	}
}
Ejemplo n.º 4
0
static int
ocpbus_attach(device_t dev)
{
	struct ocpbus_softc *sc;
	int error, i, tgt, law_max;
	uint32_t sr;
	u_long start, end;

	sc = device_get_softc(dev);

	ocpbus_mk_child(dev, OCPBUS_DEVTYPE_I2C, 0);
	ocpbus_mk_child(dev, OCPBUS_DEVTYPE_I2C, 1);
	ocpbus_mk_child(dev, OCPBUS_DEVTYPE_UART, 0);
	ocpbus_mk_child(dev, OCPBUS_DEVTYPE_UART, 1);
	ocpbus_mk_child(dev, OCPBUS_DEVTYPE_LBC, 0);
	ocpbus_mk_child(dev, OCPBUS_DEVTYPE_PCIB, 0);
	ocpbus_mk_child(dev, OCPBUS_DEVTYPE_PCIB, 1);
	ocpbus_mk_child(dev, OCPBUS_DEVTYPE_PCIB, 2);
	ocpbus_mk_child(dev, OCPBUS_DEVTYPE_TSEC, 0);
	ocpbus_mk_child(dev, OCPBUS_DEVTYPE_TSEC, 1);
	ocpbus_mk_child(dev, OCPBUS_DEVTYPE_TSEC, 2);
	ocpbus_mk_child(dev, OCPBUS_DEVTYPE_TSEC, 3);
	ocpbus_mk_child(dev, OCPBUS_DEVTYPE_PIC, 0);
	ocpbus_mk_child(dev, OCPBUS_DEVTYPE_QUICC, 0);
	ocpbus_mk_child(dev, OCPBUS_DEVTYPE_SEC, 0);

	/* Set up IRQ rman */
	start = 0;
	end = INTR_VECTORS - 1;
	sc->sc_irq.rm_start = start;
	sc->sc_irq.rm_end = end;
	sc->sc_irq.rm_type = RMAN_ARRAY;
	sc->sc_irq.rm_descr = "Interrupt request lines";
	if (rman_init(&sc->sc_irq) ||
	    rman_manage_region(&sc->sc_irq, start, end))
		panic("ocpbus_attach IRQ rman");

	/* Set up I/O mem rman */
	sc->sc_mem.rm_type = RMAN_ARRAY;
	sc->sc_mem.rm_descr = "OCPBus Device Memory";
	error = rman_init(&sc->sc_mem);
	if (error) {
		device_printf(dev, "rman_init() failed. error = %d\n", error);
		return (error);
	}

	error = rman_manage_region(&sc->sc_mem, CCSRBAR_VA,
	    CCSRBAR_VA + CCSRBAR_SIZE - 1);
	if (error) {
		device_printf(dev, "rman_manage_region() failed. error = %d\n",
		    error);
		return (error);
	}

	/*
	 * Clear local access windows. Skip DRAM entries, so we don't shoot
	 * ourselves in the foot.
	 */
	law_max = law_getmax();
	for (i = 0; i < law_max; i++) {
		sr = ccsr_read4(OCP85XX_LAWSR(i));
		if ((sr & 0x80000000) == 0)
			continue;
		tgt = (sr & 0x01f00000) >> 20;
		if (tgt == OCP85XX_TGTIF_RAM1 || tgt == OCP85XX_TGTIF_RAM2 ||
		    tgt == OCP85XX_TGTIF_RAM_INTL)
			continue;

		ccsr_write4(OCP85XX_LAWSR(i), sr & 0x7fffffff);
	}

	if (bootverbose)
		device_printf(dev, "PORDEVSR=%08x, PORDEVSR2=%08x\n",
		    ccsr_read4(OCP85XX_PORDEVSR),
		    ccsr_read4(OCP85XX_PORDEVSR2));

	for (i = PIC_IRQ_START; i < PIC_IRQ_START + 4; i++)
		powerpc_config_intr(i, INTR_TRIGGER_LEVEL, INTR_POLARITY_LOW);

	return (bus_generic_attach(dev));
}
Ejemplo n.º 5
0
static int
i2s_attach(device_t self)
{
	struct i2s_softc 	*sc;
	struct resource 	*dbdma_irq;
	void			*dbdma_ih;
	int 			 rid, oirq, err;
	phandle_t 		 port;
	
	sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK | M_ZERO);

	sc->aoa.sc_dev = self;
	sc->node = ofw_bus_get_node(self);

	port = of_find_firstchild_byname(sc->node, "i2s-a");
	if (port == -1)
		return (ENXIO);
	sc->soundnode = of_find_firstchild_byname(port, "sound");
	if (sc->soundnode == -1)
		return (ENXIO);
 
	mtx_init(&sc->port_mtx, "port_mtx", NULL, MTX_DEF);

	/* Map the controller register space. */
	rid = 0;
	sc->reg = bus_alloc_resource_any(self, SYS_RES_MEMORY, &rid, RF_ACTIVE);
	if (sc->reg == NULL)
		return ENXIO;

	/* Map the DBDMA channel register space. */
	rid = 1;
	sc->aoa.sc_odma = bus_alloc_resource_any(self, SYS_RES_MEMORY, &rid, 
	    RF_ACTIVE);
	if (sc->aoa.sc_odma == NULL)
		return ENXIO;

	/* Establish the DBDMA channel edge-triggered interrupt. */
	rid = 1;
	dbdma_irq = bus_alloc_resource_any(self, SYS_RES_IRQ, 
	    &rid, RF_SHAREABLE | RF_ACTIVE);
	if (dbdma_irq == NULL)
		return (ENXIO);

	/* Now initialize the controller. */
	err = i2s_setup(sc, 44100, 16, 64);
	if (err != 0)
		return (err);

	snd_setup_intr(self, dbdma_irq, INTR_MPSAFE, aoa_interrupt,
	    sc, &dbdma_ih);

	oirq = rman_get_start(dbdma_irq);
	err = powerpc_config_intr(oirq, INTR_TRIGGER_EDGE, INTR_POLARITY_LOW);
	if (err != 0)
		return (err);

	/*
	 * Register a hook for delayed attach in order to allow
	 * the I2C controller to attach.
	 */
	if ((i2s_delayed_attach = malloc(sizeof(struct intr_config_hook), 
	    M_TEMP, M_WAITOK | M_ZERO)) == NULL)
		return (ENOMEM);

	i2s_delayed_attach->ich_func = i2s_postattach;
	i2s_delayed_attach->ich_arg = sc;

	if (config_intrhook_establish(i2s_delayed_attach) != 0)
		return (ENOMEM);

	return (aoa_attach(sc));
}
Ejemplo n.º 6
0
static struct nexus_devinfo *
nexus_setup_dinfo(device_t dev, phandle_t node)
{
	struct nexus_softc *sc;
	struct nexus_devinfo *ndi;
	uint32_t *reg, *intr, icells;
	uint64_t phys, size;
	phandle_t iparent;
	int i, j;
	int nintr;
	int nreg;

	sc = device_get_softc(dev);

	ndi = malloc(sizeof(*ndi), M_DEVBUF, M_WAITOK | M_ZERO);
	if (ofw_bus_gen_setup_devinfo(&ndi->ndi_obdinfo, node) != 0) {
		free(ndi, M_DEVBUF);
		return (NULL);
	}
	if (NEXUS_EXCLUDED(ndi->ndi_obdinfo.obd_name,
	    ndi->ndi_obdinfo.obd_type)) {
		ofw_bus_gen_destroy_devinfo(&ndi->ndi_obdinfo);
		free(ndi, M_DEVBUF);
		return (NULL);
	}

	resource_list_init(&ndi->ndi_rl);
	nreg = OF_getprop_alloc(node, "reg", sizeof(*reg), (void **)&reg);
	if (nreg == -1)
		nreg = 0;

	for (i = 0; i < nreg; i += sc->acells + sc->scells) {
		phys = size = 0;
		for (j = 0; j < sc->acells; j++) {
			phys <<= 32;
			phys |= reg[i + j];
		}
		for (j = 0; j < sc->scells; j++) {
			size <<= 32;
			size |= reg[i + sc->acells + j];
		}
		/* Skip the dummy reg property of glue devices like ssm(4). */
		if (size != 0)
			resource_list_add(&ndi->ndi_rl, SYS_RES_MEMORY, i,
			    phys, phys + size - 1, size);
	}
	free(reg, M_OFWPROP);

	nintr = OF_getprop_alloc(node, "interrupts",  sizeof(*intr),
	    (void **)&intr);
	if (nintr > 0) {
		iparent = 0;
		OF_searchprop(node, "interrupt-parent", &iparent,
		    sizeof(iparent));
		OF_searchprop(iparent, "#interrupt-cells", &icells,
		    sizeof(icells));
		for (i = 0; i < nintr; i+= icells) {
			intr[i] = MAP_IRQ(iparent, intr[i]);
			resource_list_add(&ndi->ndi_rl, SYS_RES_IRQ, i, intr[i],
			    intr[i], 1);
			if (icells > 1) {
				powerpc_config_intr(intr[i], (intr[i+1] & 1) ?
				    INTR_TRIGGER_LEVEL : INTR_TRIGGER_EDGE,
				    INTR_POLARITY_LOW);
			}
		}
		free(intr, M_OFWPROP);
	}

	return (ndi);
}
Ejemplo n.º 7
0
static int
smu_attach(device_t dev)
{
	struct smu_softc *sc;
	phandle_t	node, child;
	uint8_t		data[12];

	sc = device_get_softc(dev);

	mtx_init(&sc->sc_mtx, "smu", NULL, MTX_DEF);
	sc->sc_cur_cmd = NULL;
	sc->sc_doorbellirqid = -1;

	sc->sc_u3 = 0;
	if (OF_finddevice("/u3") != -1)
		sc->sc_u3 = 1;

	/*
	 * Map the mailbox area. This should be determined from firmware,
	 * but I have not found a simple way to do that.
	 */
	bus_dma_tag_create(NULL, 16, 0, BUS_SPACE_MAXADDR_32BIT,
	    BUS_SPACE_MAXADDR, NULL, NULL, PAGE_SIZE, 1, PAGE_SIZE, 0, NULL,
	    NULL, &(sc->sc_dmatag));
	sc->sc_bt = &bs_le_tag;
	bus_space_map(sc->sc_bt, SMU_MAILBOX, 4, 0, &sc->sc_mailbox);

	/*
	 * Allocate the command buffer. This can be anywhere in the low 4 GB
	 * of memory.
	 */
	bus_dmamem_alloc(sc->sc_dmatag, (void **)&sc->sc_cmd, BUS_DMA_WAITOK | 
	    BUS_DMA_ZERO, &sc->sc_cmd_dmamap);
	bus_dmamap_load(sc->sc_dmatag, sc->sc_cmd_dmamap,
	    sc->sc_cmd, PAGE_SIZE, smu_phys_callback, sc, 0);
	STAILQ_INIT(&sc->sc_cmdq);

	/*
	 * Set up handlers to change CPU voltage when CPU frequency is changed.
	 */
	EVENTHANDLER_REGISTER(cpufreq_pre_change, smu_cpufreq_pre_change, dev,
	    EVENTHANDLER_PRI_ANY);
	EVENTHANDLER_REGISTER(cpufreq_post_change, smu_cpufreq_post_change, dev,
	    EVENTHANDLER_PRI_ANY);

	/*
	 * Detect and attach child devices.
	 */
	node = ofw_bus_get_node(dev);
	for (child = OF_child(node); child != 0; child = OF_peer(child)) {
		char name[32];
		memset(name, 0, sizeof(name));
		OF_getprop(child, "name", name, sizeof(name));

		if (strncmp(name, "rpm-fans", 9) == 0 ||
		    strncmp(name, "fans", 5) == 0)
			smu_attach_fans(dev, child);

		if (strncmp(name, "sensors", 8) == 0)
			smu_attach_sensors(dev, child);

		if (strncmp(name, "smu-i2c-control", 15) == 0)
			smu_attach_i2c(dev, child);
	}

	/* Some SMUs have the I2C children directly under the bus. */
	smu_attach_i2c(dev, node);

	/*
	 * Collect calibration constants.
	 */
	smu_get_datablock(dev, SMU_CPUTEMP_CAL, data, sizeof(data));
	sc->sc_cpu_diode_scale = (data[4] << 8) + data[5];
	sc->sc_cpu_diode_offset = (data[6] << 8) + data[7];

	smu_get_datablock(dev, SMU_CPUVOLT_CAL, data, sizeof(data));
	sc->sc_cpu_volt_scale = (data[4] << 8) + data[5];
	sc->sc_cpu_volt_offset = (data[6] << 8) + data[7];
	sc->sc_cpu_curr_scale = (data[8] << 8) + data[9];
	sc->sc_cpu_curr_offset = (data[10] << 8) + data[11];

	smu_get_datablock(dev, SMU_SLOTPW_CAL, data, sizeof(data));
	sc->sc_slots_pow_scale = (data[4] << 8) + data[5];
	sc->sc_slots_pow_offset = (data[6] << 8) + data[7];

	/*
	 * Set up LED interface
	 */
	sc->sc_leddev = led_create(smu_set_sleepled, dev, "sleepled");

	/*
	 * Reset on power loss behavior
	 */

	SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
            SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
	    "server_mode", CTLTYPE_INT | CTLFLAG_RW, dev, 0,
	    smu_server_mode, "I", "Enable reboot after power failure");

	/*
	 * Set up doorbell interrupt.
	 */
	sc->sc_doorbellirqid = 0;
	sc->sc_doorbellirq = bus_alloc_resource_any(smu_doorbell, SYS_RES_IRQ,
	    &sc->sc_doorbellirqid, RF_ACTIVE);
	bus_setup_intr(smu_doorbell, sc->sc_doorbellirq,
	    INTR_TYPE_MISC | INTR_MPSAFE, NULL, smu_doorbell_intr, dev,
	    &sc->sc_doorbellirqcookie);
	powerpc_config_intr(rman_get_start(sc->sc_doorbellirq),
	    INTR_TRIGGER_EDGE, INTR_POLARITY_LOW);

	/*
	 * Connect RTC interface.
	 */
	clock_register(dev, 1000);

	/*
	 * Learn about shutdown events
	 */
	EVENTHANDLER_REGISTER(shutdown_final, smu_shutdown, dev,
	    SHUTDOWN_PRI_LAST);

	return (bus_generic_attach(dev));
}
Ejemplo n.º 8
0
static int
davbus_attach(device_t self)
{
	struct davbus_softc 	*sc;
	struct resource 	*dbdma_irq, *cintr;
	void 			*cookie;
	char			 compat[64];
	int 			 rid, oirq, err;

	sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK | M_ZERO);

	sc->aoa.sc_dev = self;
	sc->node = ofw_bus_get_node(self);
	sc->soundnode = OF_child(sc->node);

	/* Map the controller register space. */
	rid = 0;
	sc->reg = bus_alloc_resource_any(self, SYS_RES_MEMORY, &rid, RF_ACTIVE);
	if (sc->reg == NULL) 
		return (ENXIO);

	/* Map the DBDMA channel register space. */
	rid = 1;
	sc->aoa.sc_odma = bus_alloc_resource_any(self, SYS_RES_MEMORY, 
	    &rid, RF_ACTIVE);
	if (sc->aoa.sc_odma == NULL)
		return (ENXIO);

	/* Establish the DBDMA channel edge-triggered interrupt. */
	rid = 1;
	dbdma_irq = bus_alloc_resource_any(self, SYS_RES_IRQ, 
	    &rid, RF_SHAREABLE | RF_ACTIVE);
	if (dbdma_irq == NULL)
		return (ENXIO);

	oirq = rman_get_start(dbdma_irq);
	
	DPRINTF(("interrupting at irq %d\n", oirq));

	err = powerpc_config_intr(oirq, INTR_TRIGGER_EDGE, INTR_POLARITY_LOW);
	if (err != 0)
		return (err);
		
	snd_setup_intr(self, dbdma_irq, INTR_MPSAFE, aoa_interrupt,
	    sc, &cookie);

	/* Now initialize the controller. */

	bzero(compat, sizeof(compat));
	OF_getprop(sc->soundnode, "compatible", compat, sizeof(compat));
	OF_getprop(sc->soundnode, "device-id", &sc->device_id, sizeof(u_int));

	mtx_init(&sc->mutex, "DAVbus", NULL, MTX_DEF);

	device_printf(self, "codec: <%s>\n", compat);

	/* Setup the control interrupt. */
	rid = 0;
	cintr = bus_alloc_resource_any(self, SYS_RES_IRQ, 
	     &rid, RF_SHAREABLE | RF_ACTIVE);
	if (cintr != NULL) 
		bus_setup_intr(self, cintr, INTR_TYPE_MISC | INTR_MPSAFE,
		    NULL, davbus_cint, sc, &cookie);
	
	/* Initialize controller registers. */
        bus_write_4(sc->reg, DAVBUS_SOUND_CTRL, DAVBUS_INPUT_SUBFRAME0 | 
	    DAVBUS_OUTPUT_SUBFRAME0 | DAVBUS_RATE_44100 | DAVBUS_INTR_PORTCHG);

	/* Attach DBDMA engine and PCM layer */
	err = aoa_attach(sc);
	if (err)
		return (err);

	/* Install codec module */
	if (strcmp(compat, "screamer") == 0)
		mixer_init(self, &screamer_mixer_class, sc);
	else if (strcmp(compat, "burgundy") == 0)
		mixer_init(self, &burgundy_mixer_class, sc);

	return (0);
}