Esempio n. 1
0
/*
 * Retrieve the raw value from OPAL.  This will be cooked by the sysctl handler.
 */
static int
opal_sensor_get_val(uint32_t key, uint64_t *val)
{
	struct opal_msg msg;
	uint32_t val32;
	int i, rv;

	rv = opal_call(OPAL_SENSOR_READ, key, key, vtophys(&val32));

	if (rv == OPAL_ASYNC_COMPLETION) {
		/* Sleep a little to let things settle. */
		DELAY(100);
		bzero(&msg, sizeof(msg));
		i = 0;
		do {
			rv = opal_call(OPAL_CHECK_ASYNC_COMPLETION,
			    vtophys(&msg), sizeof(msg), key);
			/* Sleep for ~100us if necessary. */
			if (rv == OPAL_BUSY)
				DELAY(100);
		} while (rv == OPAL_BUSY && ++i < 10);
		if (rv != OPAL_SUCCESS)
			return (EIO);
		val32 = msg.params[0];
	}

	if (rv != OPAL_SUCCESS)
		return (EIO);

	*val = val32;
	
	return (0);
}
Esempio n. 2
0
static int
opal_settime(device_t dev, struct timespec *ts)
{
	int rv;
	struct clocktime ct;
	uint32_t ymd = 0;
	uint64_t hmsm = 0;

	clock_ts_to_ct(ts, &ct);

	ymd |= (uint32_t)bin2bcd(ct.day);
	ymd |= ((uint32_t)bin2bcd(ct.mon) << 8);
	ymd |= ((uint32_t)bin2bcd32(ct.year) << 16);

	hmsm |= ((uint64_t)bin2bcd32(ct.nsec/1000) << 16);
	hmsm |= ((uint64_t)bin2bcd(ct.sec) << 40);
	hmsm |= ((uint64_t)bin2bcd(ct.min) << 48);
	hmsm |= ((uint64_t)bin2bcd(ct.hour) << 56);

	hmsm = htobe64(hmsm);
	ymd = htobe32(ymd);

	do {
		rv = opal_call(OPAL_RTC_WRITE, vtophys(&ymd), vtophys(&hmsm));
		if (rv == OPAL_BUSY_EVENT) {
			rv = opal_call(OPAL_POLL_EVENTS, 0);
			pause("opalrtc", 1);
		}
	} while (rv == OPAL_BUSY_EVENT);

	if (rv != OPAL_SUCCESS)
		return (ENXIO);

	return (0);
}
Esempio n. 3
0
static int
opal_gettime(device_t dev, struct timespec *ts)
{
	int rv;
	struct clocktime ct;
	uint32_t ymd;
	uint64_t hmsm;

	do {
		rv = opal_call(OPAL_RTC_READ, vtophys(&ymd), vtophys(&hmsm));
		if (rv == OPAL_BUSY_EVENT) {
			rv = opal_call(OPAL_POLL_EVENTS, 0);
			pause("opalrtc", 1);
		}
	} while (rv == OPAL_BUSY_EVENT);

	if (rv != OPAL_SUCCESS)
		return (ENXIO);

	hmsm = be64toh(hmsm);
	ymd = be32toh(ymd);

	ct.nsec	= bcd2bin32((hmsm & 0x000000ffffff0000) >> 16) * 1000;
	ct.sec	= bcd2bin((hmsm & 0x0000ff0000000000) >> 40);
	ct.min	= bcd2bin((hmsm & 0x00ff000000000000) >> 48);
	ct.hour	= bcd2bin((hmsm & 0xff00000000000000) >> 56);

	ct.day	= bcd2bin((ymd & 0x000000ff) >> 0);
	ct.mon	= bcd2bin((ymd & 0x0000ff00) >> 8);
	ct.year	= bcd2bin32((ymd & 0xffff0000) >> 16);

	return (clock_ct_to_ts(&ct, ts));
}
Esempio n. 4
0
static void
opal_shutdown(void *arg, int howto)
{

	if (howto & RB_HALT)
		opal_call(OPAL_CEC_POWER_DOWN, 0 /* Normal power off */);
	else
		opal_call(OPAL_CEC_REBOOT);

	opal_call(OPAL_RETURN_CPU);
}
Esempio 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));
}
Esempio n. 6
0
static int
opalflash_erase(struct opalflash_softc *sc, off_t off, off_t count)
{
	struct opal_msg msg;
	int rv, token;

	/* Ensure we write aligned to a full block size. */
	if (off % sc->sc_disk->d_stripesize != 0 ||
	    count % sc->sc_disk->d_stripesize != 0)
		return (EIO);

	token = opal_alloc_async_token();

	rv = opal_call(OPAL_FLASH_ERASE, sc->sc_opal_id, off, count, token);
	if (rv == OPAL_ASYNC_COMPLETION) {
		rv = opal_wait_completion(&msg, sizeof(msg), token);
		if (rv == OPAL_SUCCESS)
			rv = msg.params[1];
	}
	opal_free_async_token(token);

	if (rv == OPAL_SUCCESS)
		rv = 0;
	else
		rv = EIO;

	return (rv);
}
Esempio n. 7
0
static void
opal_intr(void *xintr)
{
	uint64_t events = 0;

	opal_call(OPAL_HANDLE_INTERRUPT, (uint32_t)(uint64_t)xintr,
	    vtophys(&events));
	/* XXX: do something useful with this information */

}
Esempio n. 8
0
static int
opalflash_write(struct opalflash_softc *sc, off_t off,
    caddr_t data, off_t count)
{
	struct opal_msg msg;
	int rv, size, token;

	/* Ensure we write aligned to a full block size. */
	if (off % sc->sc_disk->d_sectorsize != 0 ||
	    count % sc->sc_disk->d_sectorsize != 0)
		return (EIO);

	if (sc->sc_erase) {
	    /* Erase the full block first, then write in page chunks. */
	    rv = opalflash_erase(sc, off, count);
	    if (rv != 0)
		    return (rv);
	}

	token = opal_alloc_async_token();

	/*
	 * Write one page at a time.  It's not guaranteed that the buffer is
	 * physically contiguous.
	 */
	while (count > 0) {
		size = MIN(count, PAGE_SIZE);
		size = MIN(size, PAGE_SIZE - ((u_long)data & PAGE_MASK));
		rv = opal_call(OPAL_FLASH_WRITE, sc->sc_opal_id, off,
		    vtophys(data), size, token);
		if (rv == OPAL_ASYNC_COMPLETION) {
			rv = opal_wait_completion(&msg, sizeof(msg), token);
			if (rv == OPAL_SUCCESS)
				rv = msg.params[1];
		}
		if (rv != OPAL_SUCCESS)
			break;
		count -= size;
		off += size;
		data += size;
	}
	opal_free_async_token(token);

	if (rv == OPAL_SUCCESS)
		rv = 0;
	else
		rv = EIO;

	return (rv);
}