Exemplo n.º 1
0
static int
pcf2123_rtc_attach(device_t dev)
{
    struct pcf2123_rtc_softc *sc;
    struct spi_command cmd;
    unsigned char rxBuf[3];
    unsigned char txBuf[3];
    int err;

    sc = device_get_softc(dev);
    sc->dev = dev;

    clock_register(dev, 1000000);

    memset(&cmd, 0, sizeof(cmd));
    memset(rxBuf, 0, sizeof(rxBuf));
    memset(txBuf, 0, sizeof(txBuf));

    /* Make sure Ctrl1 and Ctrl2 are zeroes */
    txBuf[0] = PCF2123_WRITE(PCF2123_REG_CTRL1);
    cmd.rx_cmd = rxBuf;
    cmd.tx_cmd = txBuf;
    cmd.rx_cmd_sz = sizeof(rxBuf);
    cmd.tx_cmd_sz = sizeof(txBuf);
    err = SPIBUS_TRANSFER(device_get_parent(dev), dev, &cmd);
    DELAY(PCF2123_DELAY);

    return (0);
}
Exemplo n.º 2
0
static void
pcf8563_start(void *xdev)
{
	device_t dev;
	uint8_t reg = PCF8563_R_SECOND, val;
	struct iic_msg msgs[] = {
		{ 0, IIC_M_WR, sizeof(reg), &reg },
		{ 0, IIC_M_RD, sizeof(val), &val }
	};
	struct pcf8563_softc *sc;

	dev = (device_t)xdev;
	sc = device_get_softc(dev);
	config_intrhook_disestablish(&sc->enum_hook);

	/*
	 * NB: PCF8563_R_SECOND_VL doesn't automatically clear when VDD
	 * rises above Vlow again and needs to be cleared manually.
	 * However, apparently this needs all of the time registers to be
	 * set, i.e. pcf8563_settime(), and not just PCF8563_R_SECOND in
	 * order for PCF8563_R_SECOND_VL to stick.  Thus, we just issue a
	 * warning here rather than failing with ENXIO in case it is set.
	 * Note that pcf8563_settime() will also clear PCF8563_R_SECOND_VL
	 * as a side-effect.
	 */
	msgs[0].slave = msgs[1].slave = sc->sc_addr;
	if (iicbus_transfer(dev, msgs, nitems(msgs)) != 0) {
		device_printf(dev, "%s: cannot read RTC\n", __func__);
		return;
	}
	if ((val & PCF8563_R_SECOND_VL) != 0)
		device_printf(dev, "%s: battery low\n", __func__);

	clock_register(dev, 1000000);   /* 1 second resolution */
}
Exemplo n.º 3
0
static int
rtasdev_attach(device_t dev)
{
    if (rtas_token_lookup("get-time-of-day") != -1)
        clock_register(dev, 2000);

    EVENTHANDLER_REGISTER(shutdown_final, rtas_shutdown, NULL,
                          SHUTDOWN_PRI_LAST);

    return (0);
}
Exemplo n.º 4
0
static int
octeon_rtc_attach(device_t dev)
{
	cvmx_rtc_options_t supported;

	supported = cvmx_rtc_supported();
	if ((supported & CVMX_RTC_READ) == 0)
		return (ENXIO);

	clock_register(dev, 1000000);
	return (0);
}
Exemplo n.º 5
0
static int
opaldev_attach(device_t dev)
{
	phandle_t child;
	device_t cdev;
	uint64_t junk;
	int i, rv;
	struct ofw_bus_devinfo *dinfo;
	struct resource *irq;

	/* Test for RTC support and register clock if it works */
	rv = opal_call(OPAL_RTC_READ, vtophys(&junk), vtophys(&junk));
	do {
		rv = opal_call(OPAL_RTC_READ, vtophys(&junk), vtophys(&junk));
		if (rv == OPAL_BUSY_EVENT)
			rv = opal_call(OPAL_POLL_EVENTS, 0);
	} while (rv == OPAL_BUSY_EVENT);

	if (rv == OPAL_SUCCESS)
		clock_register(dev, 2000);
	
	EVENTHANDLER_REGISTER(shutdown_final, opal_shutdown, NULL,
	    SHUTDOWN_PRI_LAST);

	/* Bind to interrupts */
	for (i = 0; (irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &i,
	    RF_ACTIVE)) != NULL; i++)
		bus_setup_intr(dev, irq, INTR_TYPE_TTY | INTR_MPSAFE |
		    INTR_ENTROPY, NULL, opal_intr, (void *)rman_get_start(irq),
		    NULL);

	for (child = OF_child(ofw_bus_get_node(dev)); child != 0;
	    child = OF_peer(child)) {
		dinfo = malloc(sizeof(*dinfo), M_DEVBUF, M_WAITOK | M_ZERO);
		if (ofw_bus_gen_setup_devinfo(dinfo, child) != 0) {
			free(dinfo, M_DEVBUF);
			continue;
		}
		cdev = device_add_child(dev, NULL, -1);
		if (cdev == NULL) {
			device_printf(dev, "<%s>: device_add_child failed\n",
			    dinfo->obd_name);
			ofw_bus_gen_destroy_devinfo(dinfo);
			free(dinfo, M_DEVBUF);
			continue;
		}
		device_set_ivars(cdev, dinfo);
	}

	return (bus_generic_attach(dev));
}
Exemplo n.º 6
0
static int
at91_rtc_attach(device_t dev)
{
	struct at91_rtc_softc *sc = device_get_softc(dev);
	int err;

	sc->dev = dev;
	err = at91_rtc_activate(dev);
	if (err)
		goto out;

	AT91_RTC_LOCK_INIT(sc);

	/*
	 * Disable all interrupts in the hardware.
	 * Clear all bits in the status register.
	 * Set 24-hour-clock mode.
	 */
	WR4(sc, RTC_IDR, 0xffffffff);
	WR4(sc, RTC_SCCR, 0x1f);
	WR4(sc, RTC_MR, 0);

#ifdef AT91_RTC_USE_INTERRUPTS
	err = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_MISC,
	    at91_rtc_intr, NULL, sc, &sc->intrhand);
	if (err) {
		AT91_RTC_LOCK_DESTROY(sc);
		goto out;
	}
#endif	

	/*
	 * Read the calendar register.  If the century is 19 then the clock has
	 * never been set.  Try to store an invalid value into the register,
	 * which will turn on the error bit in RTC_VER, and our getclock code
	 * knows to return EINVAL if any error bits are on.
	 */
	if (RTC_CALR_CEN(RD4(sc, RTC_CALR)) == 19)
		WR4(sc, RTC_CALR, 0);

	/*
	 * Register as a time of day clock with 1-second resolution.
	 */
	clock_register(dev, 1000000);
out:
	if (err)
		at91_rtc_deactivate(dev);
	return (err);
}
Exemplo n.º 7
0
int
mc146818_attach(device_t dev)
{
	struct mc146818_softc *sc;

	sc = device_get_softc(dev);

	if (mtx_initialized(&sc->sc_mtx) == 0) {
		device_printf(dev, "%s: mutex not initialized\n", __func__);
		return (ENXIO);
	}

	if (sc->sc_mcread == NULL)
		sc->sc_mcread = mc146818_def_read;
	if (sc->sc_mcwrite == NULL)
		sc->sc_mcwrite = mc146818_def_write;

	if (sc->sc_flag & MC146818_NO_CENT_ADJUST) {
		/*
		 * Note that setting MC146818_NO_CENT_ADJUST means that
		 * the century has to be stored in NVRAM somewhere.
		 */
		if (sc->sc_getcent == NULL)
			sc->sc_getcent = mc146818_def_getcent;
		if (sc->sc_setcent == NULL)
			sc->sc_setcent = mc146818_def_setcent;
	}

	mtx_lock_spin(&sc->sc_mtx);
	if (!(*sc->sc_mcread)(dev, MC_REGD) & MC_REGD_VRT) {
		mtx_unlock_spin(&sc->sc_mtx);
		device_printf(dev, "%s: battery low\n", __func__);
		return (ENXIO);
	}

	sc->sc_rega = MC_BASE_32_KHz;
	(*sc->sc_mcwrite)(dev, MC_REGA, sc->sc_rega);

	sc->sc_regb = 0;
	sc->sc_regb |= (sc->sc_flag & MC146818_BCD) ? 0 : MC_REGB_BINARY;
	sc->sc_regb |= (sc->sc_flag & MC146818_12HR) ? 0 : MC_REGB_24HR;
	(*sc->sc_mcwrite)(dev, MC_REGB, sc->sc_regb);
	mtx_unlock_spin(&sc->sc_mtx);

	clock_register(dev, 1000000);	/* 1 second resolution. */

	return (0);
}
Exemplo n.º 8
0
static int
nexus_attach(device_t dev)
{

	/*
	 * Mask the legacy PICs - we will use the I/O SAPIC for interrupt.
	 */
	outb(IO_ICU1+1, 0xff);
	outb(IO_ICU2+1, 0xff);

	if (acpi_identify() == 0)
		BUS_ADD_CHILD(dev, 10, "acpi", 0);
	clock_register(dev, 1000);
	bus_generic_attach(dev);
	return 0;
}
Exemplo n.º 9
0
static int
aw_rtc_attach(device_t dev)
{
	struct aw_rtc_softc *sc  = device_get_softc(dev);
	bus_size_t rtc_losc_sta;
	uint32_t val;
	int rid = 0;

	sc->res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE);
	if (!sc->res) {
		device_printf(dev, "could not allocate resources\n");
		return (ENXIO);
	}

	sc->type = ofw_bus_search_compatible(dev, compat_data)->ocd_data;
	switch (sc->type) {
	case A10_RTC:
	case A20_RTC:
		sc->rtc_date = A10_RTC_DATE_REG;
		sc->rtc_time = A10_RTC_TIME_REG;
		rtc_losc_sta = LOSC_CTRL_REG;
		break;
	case A31_RTC:
		sc->rtc_date = A31_RTC_DATE_REG;
		sc->rtc_time = A31_RTC_TIME_REG;
		rtc_losc_sta = A31_LOSC_AUTO_SWT_STA;
		break;
	}
	val = RTC_READ(sc, LOSC_CTRL_REG);
	val |= LOSC_AUTO_SW_EN;
	val |= LOSC_MAGIC | LOSC_GSM | LOSC_OSC_SRC;
	RTC_WRITE(sc, LOSC_CTRL_REG, val);

	DELAY(100);

	if (bootverbose) {
		val = RTC_READ(sc, rtc_losc_sta);
		if ((val & LOSC_OSC_SRC) == 0)
			device_printf(dev, "Using internal oscillator\n");
		else
			device_printf(dev, "Using external oscillator\n");
	}

	clock_register(dev, RTC_RES_US);
	
	return (0);
}
Exemplo n.º 10
0
int
as3722_rtc_attach(struct as3722_softc *sc, phandle_t node)
{
	int rv;

	/* Enable RTC, set 24 hours mode  and alarms */
	rv = RM1(sc, AS3722_RTC_CONTROL,
	    AS3722_RTC_ON | AS3722_RTC_ALARM_WAKEUP_EN | AS3722_RTC_AM_PM_MODE,
	    AS3722_RTC_ON | AS3722_RTC_ALARM_WAKEUP_EN);
	if (rv < 0) {
		device_printf(sc->dev, "Failed to initialize RTC controller\n");
		return (ENXIO);
	}
	clock_register(sc->dev, 1000000);

	return (0);
}
Exemplo n.º 11
0
static int
mv_rtc_attach(device_t dev)
{
	struct mv_rtc_softc *sc;

	sc = device_get_softc(dev);
	sc->dev = dev;

	clock_register(dev, 1000000);

	if (bus_alloc_resources(dev, res_spec, sc->res)) {
		device_printf(dev, "could not allocate resources\n");
		return (ENXIO);
	}

	return (0);
}
Exemplo n.º 12
0
static int
snvs_attach(device_t dev)
{
	struct snvs_softc *sc;
	int rid;

	sc = device_get_softc(dev);
	sc->dev = dev;

	rid = 0;
	sc->memres = bus_alloc_resource_any(sc->dev, SYS_RES_MEMORY, &rid,
	    RF_ACTIVE);
	if (sc->memres == NULL) {
		device_printf(sc->dev, "could not allocate registers\n");
		return (ENXIO);
	}

	clock_register(sc->dev, RTC_RESOLUTION_US);

	return (0);
}
Exemplo n.º 13
0
static int
rtc_attach(device_t dev)
{
    struct timespec ts;
    struct ds1553_softc *sc;
    int error;

    sc = device_get_softc(dev);
    bzero(sc, sizeof(struct ds1553_softc));

    mtx_init(&sc->sc_mtx, "rtc_mtx", NULL, MTX_SPIN);

    sc->res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->rid,
                                     RF_ACTIVE);
    if (sc->res == NULL) {
        device_printf(dev, "cannot allocate resources\n");
        mtx_destroy(&sc->sc_mtx);
        return (ENXIO);
    }

    sc->sc_bst = rman_get_bustag(sc->res);
    sc->sc_bsh = rman_get_bushandle(sc->res);

    if ((error = ds1553_attach(dev)) != 0) {
        device_printf(dev, "cannot attach time of day clock\n");
        bus_release_resource(dev, SYS_RES_MEMORY, sc->rid, sc->res);
        mtx_destroy(&sc->sc_mtx);
        return (error);
    }

    clock_register(dev, 1000000);

    if (bootverbose) {
        ds1553_gettime(dev, &ts);
        device_printf(dev, "current time: %ld.%09ld\n",
                      (long)ts.tv_sec, ts.tv_nsec);
    }

    return (0);
}
Exemplo n.º 14
0
static int
lpc_rtc_attach(device_t dev)
{
	struct lpc_rtc_softc *sc = device_get_softc(dev);
	int rid = 0;

	sc->lr_dev = dev;

	clock_register(dev, 1000000);

	sc->lr_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
	    RF_ACTIVE);
	if (!sc->lr_mem_res) {
		device_printf(dev, "cannot allocate memory window\n");
		return (ENXIO);
	}

	sc->lr_bst = rman_get_bustag(sc->lr_mem_res);
	sc->lr_bsh = rman_get_bushandle(sc->lr_mem_res);

	return (0);
}
Exemplo n.º 15
0
static void
ds1307_start(void *xdev)
{
	device_t dev;
	struct ds1307_softc *sc;
	struct sysctl_ctx_list *ctx;
	struct sysctl_oid *tree_node;
	struct sysctl_oid_list *tree;

	dev = (device_t)xdev;
	sc = device_get_softc(dev);
	ctx = device_get_sysctl_ctx(dev);
	tree_node = device_get_sysctl_tree(dev);
	tree = SYSCTL_CHILDREN(tree_node);

	config_intrhook_disestablish(&sc->enum_hook);
	/* Set the 24 hours mode. */
	if (ds1307_set_24hrs_mode(sc) != 0)
		return;
	/* Enable the oscillator if halted. */
	if (ds1307_osc_enable(sc) != 0)
		return;

	/* Configuration parameters. */
	SYSCTL_ADD_PROC(ctx, tree, OID_AUTO, "sqwe",
	    CTLFLAG_RW | CTLTYPE_UINT | CTLFLAG_MPSAFE, sc, 0,
	    ds1307_sqwe_sysctl, "IU", "DS1307 square-wave enable");
	SYSCTL_ADD_PROC(ctx, tree, OID_AUTO, "sqw_freq",
	    CTLFLAG_RW | CTLTYPE_UINT | CTLFLAG_MPSAFE, sc, 0,
	    ds1307_sqw_freq_sysctl, "IU",
	    "DS1307 square-wave output frequency");
	SYSCTL_ADD_PROC(ctx, tree, OID_AUTO, "sqw_out",
	    CTLFLAG_RW | CTLTYPE_UINT | CTLFLAG_MPSAFE, sc, 0,
	    ds1307_sqw_out_sysctl, "IU", "DS1307 square-wave output state");

	/* 1 second resolution. */
	clock_register(dev, 1000000);
}
Exemplo n.º 16
0
static int
s3c2xx0_rtc_attach(device_t dev)
{
	struct s3c2xx0_rtc_softc *sc;
	int error, rid;

	sc = device_get_softc(dev);
 	error = 0;

	rid = 0;
	sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid,
	    RF_ACTIVE);
	if (sc->mem_res == NULL) {
		error = ENOMEM;
		goto out;
	}

	bus_write_1(sc->mem_res, RTC_RTCCON, RTCCON_RTCEN);
	clock_register(dev, 1000000);

out:
	return (error);
}
Exemplo n.º 17
0
static int
atrtc_attach(device_t dev)
{
	struct atrtc_softc *sc;
	int i;

	/*
	 * Not that we need them or anything, but grab our resources
	 * so they show up, correctly attributed, in the big picture.
	 */
	
	sc = device_get_softc(dev);
	if (!(sc->port_res = bus_alloc_resource(dev, SYS_RES_IOPORT,
	    &sc->port_rid, IO_RTC, IO_RTC + 1, 2, RF_ACTIVE)))
		device_printf(dev,"Warning: Couldn't map I/O.\n");
	if (!(sc->intr_res = bus_alloc_resource(dev, SYS_RES_IRQ,
	    &sc->intr_rid, 8, 8, 1, RF_ACTIVE)))
		device_printf(dev,"Warning: Couldn't map Interrupt.\n");
	clock_register(dev, 1000000);
	if (resource_int_value("atrtc", 0, "clock", &i) == 0 && i == 0)
		atrtcclock_disable = 1;
	return(0);
}
Exemplo n.º 18
0
static int
cuda_attach(device_t dev)
{
	struct cuda_softc *sc;

	volatile int i;
	uint8_t reg;
	phandle_t node,child;
	
	sc = device_get_softc(dev);
	sc->sc_dev = dev;
	
	sc->sc_memrid = 0;
	sc->sc_memr = bus_alloc_resource_any(dev, SYS_RES_MEMORY, 
	    &sc->sc_memrid, RF_ACTIVE);

	if (sc->sc_memr == NULL) {
		device_printf(dev, "Could not alloc mem resource!\n");
		return (ENXIO);
	}

	sc->sc_irqrid = 0;
	sc->sc_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->sc_irqrid,
            	RF_ACTIVE);
        if (sc->sc_irq == NULL) {
                device_printf(dev, "could not allocate interrupt\n");
                return (ENXIO);
        }

	if (bus_setup_intr(dev, sc->sc_irq, INTR_TYPE_MISC | INTR_MPSAFE 
	    | INTR_ENTROPY, NULL, cuda_intr, dev, &sc->sc_ih) != 0) {
                device_printf(dev, "could not setup interrupt\n");
                bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irqrid,
                    sc->sc_irq);
                return (ENXIO);
        }

	mtx_init(&sc->sc_mutex,"cuda",NULL,MTX_DEF | MTX_RECURSE);

	sc->sc_sent = 0;
	sc->sc_received = 0;
	sc->sc_waiting = 0;
	sc->sc_polling = 0;
	sc->sc_state = CUDA_NOTREADY;
	sc->sc_autopoll = 0;
	sc->sc_rtc = -1;

	STAILQ_INIT(&sc->sc_inq);
	STAILQ_INIT(&sc->sc_outq);
	STAILQ_INIT(&sc->sc_freeq);

	for (i = 0; i < CUDA_MAXPACKETS; i++)
		STAILQ_INSERT_TAIL(&sc->sc_freeq, &sc->sc_pkts[i], pkt_q);

	/* Init CUDA */

	reg = cuda_read_reg(sc, vDirB);
	reg |= 0x30;	/* register B bits 4 and 5: outputs */
	cuda_write_reg(sc, vDirB, reg);

	reg = cuda_read_reg(sc, vDirB);
	reg &= 0xf7;	/* register B bit 3: input */
	cuda_write_reg(sc, vDirB, reg);

	reg = cuda_read_reg(sc, vACR);
	reg &= ~vSR_OUT;	/* make sure SR is set to IN */
	cuda_write_reg(sc, vACR, reg);

	cuda_write_reg(sc, vACR, (cuda_read_reg(sc, vACR) | 0x0c) & ~0x10);

	sc->sc_state = CUDA_IDLE;	/* used by all types of hardware */

	cuda_write_reg(sc, vIER, 0x84); /* make sure VIA interrupts are on */

	cuda_idle(sc);	/* reset ADB */

	/* Reset CUDA */

	i = cuda_read_reg(sc, vSR);	/* clear interrupt */
	cuda_write_reg(sc, vIER, 0x04); /* no interrupts while clearing */
	cuda_idle(sc);	/* reset state to idle */
	DELAY(150);
	cuda_tip(sc);	/* signal start of frame */
	DELAY(150);
	cuda_toggle_ack(sc);
	DELAY(150);
	cuda_clear_tip(sc);
	DELAY(150);
	cuda_idle(sc);	/* back to idle state */
	i = cuda_read_reg(sc, vSR);	/* clear interrupt */
	cuda_write_reg(sc, vIER, 0x84);	/* ints ok now */

	/* Initialize child buses (ADB) */
	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 (bootverbose)
			device_printf(dev, "CUDA child <%s>\n",name);

		if (strncmp(name, "adb", 4) == 0) {
			sc->adb_bus = device_add_child(dev,"adb",-1);
		}
	}

	clock_register(dev, 1000);
	EVENTHANDLER_REGISTER(shutdown_final, cuda_shutdown, sc,
	    SHUTDOWN_PRI_LAST);

	return (bus_generic_attach(dev));
}
Exemplo n.º 19
0
int
mk48txx_attach(device_t dev)
{
	struct mk48txx_softc *sc;
	int i;
	uint8_t wday;

	sc = device_get_softc(dev);

	if (mtx_initialized(&sc->sc_mtx) == 0) {
		device_printf(dev, "%s: mutex not initialized\n", __func__);
		return (ENXIO);
	}

	device_printf(dev, "model %s", sc->sc_model);
	i = sizeof(mk48txx_models) / sizeof(mk48txx_models[0]);
	while (--i >= 0) {
		if (strcmp(sc->sc_model, mk48txx_models[i].name) == 0) {
			break;
		}
	}
	if (i < 0) {
		device_printf(dev, " (unsupported)\n");
		return (ENXIO);
	}
	printf("\n");
	sc->sc_nvramsz = mk48txx_models[i].nvramsz;
	sc->sc_clkoffset = mk48txx_models[i].clkoff;

	if (sc->sc_nvrd == NULL)
		sc->sc_nvrd = mk48txx_def_nvrd;
	if (sc->sc_nvwr == NULL)
		sc->sc_nvwr = mk48txx_def_nvwr;

	if (mk48txx_models[i].flags & MK48TXX_EXT_REGISTERS) {
		mtx_lock(&sc->sc_mtx);
		if ((*sc->sc_nvrd)(dev, sc->sc_clkoffset + MK48TXX_FLAGS) &
		    MK48TXX_FLAGS_BL) {
			mtx_unlock(&sc->sc_mtx);
			device_printf(dev, "%s: battery low\n", __func__);
			return (ENXIO);
		}
		mtx_unlock(&sc->sc_mtx);
	}

	if (sc->sc_flag & MK48TXX_NO_CENT_ADJUST) {
		/*
		 * Use MK48TXX_WDAY_CB instead of manually adjusting the
		 * century.
		 */
		if (!(mk48txx_models[i].flags & MK48TXX_EXT_REGISTERS)) {
			device_printf(dev, "%s: no century bit\n", __func__);
			return (ENXIO);
		} else {
			mtx_lock(&sc->sc_mtx);
			wday = (*sc->sc_nvrd)
			    (dev, sc->sc_clkoffset + MK48TXX_IWDAY);
			wday |= MK48TXX_WDAY_CEB;
			(*sc->sc_nvwr)
			    (dev, sc->sc_clkoffset + MK48TXX_IWDAY, wday);
			mtx_unlock(&sc->sc_mtx);
		}
	}

	clock_register(dev, 1000000);	/* 1 second resolution */

	if ((sc->sc_flag & MK48TXX_WDOG_REGISTER) &&
	    (mk48txx_models[i].flags & MK48TXX_EXT_REGISTERS)) {
		sc->sc_wet = EVENTHANDLER_REGISTER(watchdog_list,
		    mk48txx_watchdog, dev, 0);
		device_printf(dev,
		    "watchdog registered, timeout interval max. 128 sec\n");
	}

	return (0);
}
Exemplo n.º 20
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));
}
Exemplo n.º 21
0
static int 
ps3bus_attach(device_t self) 
{
	struct ps3bus_softc *sc;
	struct ps3bus_devinfo *dinfo;
	int bus_index, dev_index, result;
	uint64_t bustype, bus, devs;
	uint64_t dev, devtype;
	uint64_t junk;
	device_t cdev;

	sc = device_get_softc(self);
	sc->sc_mem_rman.rm_type = RMAN_ARRAY;
	sc->sc_mem_rman.rm_descr = "PS3Bus Memory Mapped I/O";
	sc->sc_intr_rman.rm_type = RMAN_ARRAY;
	sc->sc_intr_rman.rm_descr = "PS3Bus Interrupts";
	rman_init(&sc->sc_mem_rman);
	rman_init(&sc->sc_intr_rman);
	rman_manage_region(&sc->sc_intr_rman, 0, ~0);

	/* Get memory regions for DMA */
	mem_regions(&sc->regions, &sc->rcount, &sc->regions, &sc->rcount);

	/*
	 * Probe all the PS3's buses.
	 */

	for (bus_index = 0; bus_index < 5; bus_index++) {
		result = lv1_get_repository_node_value(PS3_LPAR_ID_PME,
		    (lv1_repository_string("bus") >> 32) | bus_index,
		    lv1_repository_string("type"), 0, 0, &bustype, &junk);

		if (result != 0)
			continue;

		result = lv1_get_repository_node_value(PS3_LPAR_ID_PME,
		    (lv1_repository_string("bus") >> 32) | bus_index,
		    lv1_repository_string("id"), 0, 0, &bus, &junk);

		if (result != 0)
			continue;

		result = lv1_get_repository_node_value(PS3_LPAR_ID_PME,
		    (lv1_repository_string("bus") >> 32) | bus_index,
		    lv1_repository_string("num_dev"), 0, 0, &devs, &junk);

		for (dev_index = 0; dev_index < devs; dev_index++) {
			result = lv1_get_repository_node_value(PS3_LPAR_ID_PME,
			    (lv1_repository_string("bus") >> 32) | bus_index,
			    lv1_repository_string("dev") | dev_index,
			    lv1_repository_string("type"), 0, &devtype, &junk);

			if (result != 0)
				continue;

			result = lv1_get_repository_node_value(PS3_LPAR_ID_PME,
			    (lv1_repository_string("bus") >> 32) | bus_index,
			    lv1_repository_string("dev") | dev_index,
			    lv1_repository_string("id"), 0, &dev, &junk);

			if (result != 0)
				continue;
			
			switch (devtype) {
			case PS3_DEVTYPE_USB:
				/* USB device has OHCI and EHCI USB host controllers */

				lv1_open_device(bus, dev, 0);

				/* OHCI host controller */

				dinfo = malloc(sizeof(*dinfo), M_PS3BUS,
				    M_WAITOK | M_ZERO);

				dinfo->bus = bus;
				dinfo->dev = dev;
				dinfo->bustype = bustype;
				dinfo->devtype = devtype;
				dinfo->busidx = bus_index;
				dinfo->devidx = dev_index;

				ps3bus_resources_init_by_type(&sc->sc_mem_rman, bus_index,
				    dev_index, OHCI_IRQ, OHCI_REG, dinfo);

				cdev = device_add_child(self, "ohci", -1);
				if (cdev == NULL) {
					device_printf(self,
					    "device_add_child failed\n");
					free(dinfo, M_PS3BUS);
					continue;
				}

				mtx_init(&dinfo->iommu_mtx, "iommu", NULL, MTX_DEF);
				device_set_ivars(cdev, dinfo);

				/* EHCI host controller */

				dinfo = malloc(sizeof(*dinfo), M_PS3BUS,
				    M_WAITOK | M_ZERO);

				dinfo->bus = bus;
				dinfo->dev = dev;
				dinfo->bustype = bustype;
				dinfo->devtype = devtype;
				dinfo->busidx = bus_index;
				dinfo->devidx = dev_index;

				ps3bus_resources_init_by_type(&sc->sc_mem_rman, bus_index,
				    dev_index, EHCI_IRQ, EHCI_REG, dinfo);

				cdev = device_add_child(self, "ehci", -1);
				if (cdev == NULL) {
					device_printf(self,
					    "device_add_child failed\n");
					free(dinfo, M_PS3BUS);
					continue;
				}

				mtx_init(&dinfo->iommu_mtx, "iommu", NULL, MTX_DEF);
				device_set_ivars(cdev, dinfo);
				break;
			default:
				dinfo = malloc(sizeof(*dinfo), M_PS3BUS,
				    M_WAITOK | M_ZERO);

				dinfo->bus = bus;
				dinfo->dev = dev;
				dinfo->bustype = bustype;
				dinfo->devtype = devtype;
				dinfo->busidx = bus_index;
				dinfo->devidx = dev_index;

				if (dinfo->bustype == PS3_BUSTYPE_SYSBUS ||
				    dinfo->bustype == PS3_BUSTYPE_STORAGE)
					lv1_open_device(bus, dev, 0);

				ps3bus_resources_init(&sc->sc_mem_rman, bus_index,
				    dev_index, dinfo);

				cdev = device_add_child(self, NULL, -1);
				if (cdev == NULL) {
					device_printf(self,
					    "device_add_child failed\n");
					free(dinfo, M_PS3BUS);
					continue;
				}

				mtx_init(&dinfo->iommu_mtx, "iommu", NULL, MTX_DEF);
				device_set_ivars(cdev, dinfo);
			}
		}
	}
	
	clock_register(self, 1000);

	return (bus_generic_attach(self));
}