Пример #1
0
static int
bcm2835_cpufreq_set_voltage(struct bcm2835_cpufreq_softc *sc,
    uint32_t voltage_id, int32_t value)
{
	struct msg_set_voltage msg;
	int err;

	/*
	 * Set voltage
	 *   Tag: 0x00038003
	 *   Request:
	 *     Length: 4
	 *     Value:
	 *       u32: voltage id
	 *       u32: value (offset from 1.2V in units of 0.025V)
	 *   Response:
	 *     Length: 8
	 *     Value:
	 *       u32: voltage id
	 *       u32: value (offset from 1.2V in units of 0.025V)
	 */

	/*
	 * over_voltage:
	 * 0 (1.2 V). Values above 6 are only allowed when force_turbo or
	 * current_limit_override are specified (which set the warranty bit).
	 */
	if (value > MAX_OVER_VOLTAGE || value < MIN_OVER_VOLTAGE) {
		/* currently not supported */
		device_printf(sc->dev, "not supported voltage: %d\n", value);
		return (MSG_ERROR);
	}

	/* setup single tag buffer */
	memset(&msg, 0, sizeof(msg));
	msg.hdr.buf_size = sizeof(msg);
	msg.hdr.code = BCM2835_MBOX_CODE_REQ;
	msg.tag_hdr.tag = BCM2835_MBOX_TAG_SET_VOLTAGE;
	msg.tag_hdr.val_buf_size = sizeof(msg.body);
	msg.tag_hdr.val_len = sizeof(msg.body.req);
	msg.body.req.voltage_id = voltage_id;
	msg.body.req.value = (uint32_t)value;
	msg.end_tag = 0;

	/* call mailbox property */
	err = bcm2835_mbox_property(&msg, sizeof(msg));
	if (err) {
		device_printf(sc->dev, "can't set voltage\n");
		return (MSG_ERROR);
	}

	/* result (offset from 1.2V) */
	value = (int)msg.body.resp.value;
	DPRINTF("value = %d\n", value);
	return (value);
}
Пример #2
0
static int
bcm2835_cpufreq_set_turbo(struct bcm2835_cpufreq_softc *sc, uint32_t level)
{
	struct msg_set_turbo msg;
	int value;
	int err;

	/*
	 * Set turbo
	 *   Tag: 0x00038009
	 *   Request:
	 *     Length: 8
	 *     Value:
	 *       u32: id
	 *       u32: level
	 *   Response:
	 *     Length: 8
	 *     Value:
	 *       u32: id
	 *       u32: level
	 */

	/* replace unknown value to OFF */
	if (level != BCM2835_MBOX_TURBO_ON && level != BCM2835_MBOX_TURBO_OFF)
		level = BCM2835_MBOX_TURBO_OFF;

	/* setup single tag buffer */
	memset(&msg, 0, sizeof(msg));
	msg.hdr.buf_size = sizeof(msg);
	msg.hdr.code = BCM2835_MBOX_CODE_REQ;
	msg.tag_hdr.tag = BCM2835_MBOX_TAG_SET_TURBO;
	msg.tag_hdr.val_buf_size = sizeof(msg.body);
	msg.tag_hdr.val_len = sizeof(msg.body.req);
	msg.body.req.id = 0;
	msg.body.req.level = level;
	msg.end_tag = 0;

	/* call mailbox property */
	err = bcm2835_mbox_property(&msg, sizeof(msg));
	if (err) {
		device_printf(sc->dev, "can't set turbo\n");
		return (MSG_ERROR);
	}

	/* result 0=non-turbo, 1=turbo */
	value = (int)msg.body.resp.level;
	DPRINTF("level = %d\n", value);
	return (value);
}
Пример #3
0
static int
bcm2835_cpufreq_get_min_clock_rate(struct bcm2835_cpufreq_softc *sc,
    uint32_t clock_id)
{
	struct msg_get_min_clock_rate msg;
	int rate;
	int err;

	/*
	 * Get min clock rate
	 *   Tag: 0x00030007
	 *   Request:
	 *     Length: 4
	 *     Value:
	 *       u32: clock id
	 *   Response:
	 *     Length: 8
	 *     Value:
	 *       u32: clock id
	 *       u32: rate (in Hz)
	 */

	/* setup single tag buffer */
	memset(&msg, 0, sizeof(msg));
	msg.hdr.buf_size = sizeof(msg);
	msg.hdr.code = BCM2835_MBOX_CODE_REQ;
	msg.tag_hdr.tag = BCM2835_MBOX_TAG_GET_MIN_CLOCK_RATE;
	msg.tag_hdr.val_buf_size = sizeof(msg.body);
	msg.tag_hdr.val_len = sizeof(msg.body.req);
	msg.body.req.clock_id = clock_id;
	msg.end_tag = 0;

	/* call mailbox property */
	err = bcm2835_mbox_property(&msg, sizeof(msg));
	if (err) {
		device_printf(sc->dev, "can't get min clock rate (id=%u)\n",
		    clock_id);
		return (MSG_ERROR);
	}

	/* result (Hz) */
	rate = (int)msg.body.resp.rate_hz;
	DPRINTF("clock = %d(Hz)\n", rate);
	return (rate);
}
Пример #4
0
int
vcio_ioctl(struct cdev *dev, u_long cmd, caddr_t arg, int mode,
    struct thread *td)
{
    int error;
    void *ptr;
    uint32_t size;
    uint8_t *property;

    error = 0;
    switch(cmd) {
    case IOCTL_MBOX_PROPERTY:
    	memcpy (&ptr, arg, sizeof(ptr));
	error = copyin(ptr, &size, sizeof(size));

	if (error != 0)
		break;
	property = malloc(size, M_VCIO, M_WAITOK);
	if (property == NULL) {
		error = ENOMEM;
		break;
	}

	error = copyin(ptr, property, size);
	if (error) {
		free(property, M_VCIO);
		break;
	}

	error = bcm2835_mbox_property(property, size);
	if (error) {
		free(property, M_VCIO);
		break;
	}

	error = copyout(property, ptr, size);
	free(property, M_VCIO);

	break;
    default:
	error = EINVAL;
	break;
    }
    return (error);
}
Пример #5
0
static int
bcm2835_cpufreq_get_min_voltage(struct bcm2835_cpufreq_softc *sc,
    uint32_t voltage_id)
{
	struct msg_get_min_voltage msg;
	int value;
	int err;

	/*
	 * Get voltage
	 *   Tag: 0x00030008
	 *   Request:
	 *     Length: 4
	 *     Value:
	 *       u32: voltage id
	 *   Response:
	 *     Length: 8
	 *     Value:
	 *       u32: voltage id
	 *       u32: value (offset from 1.2V in units of 0.025V)
	 */

	/* setup single tag buffer */
	memset(&msg, 0, sizeof(msg));
	msg.hdr.buf_size = sizeof(msg);
	msg.hdr.code = BCM2835_MBOX_CODE_REQ;
	msg.tag_hdr.tag = BCM2835_MBOX_TAG_GET_MIN_VOLTAGE;
	msg.tag_hdr.val_buf_size = sizeof(msg.body);
	msg.tag_hdr.val_len = sizeof(msg.body.req);
	msg.body.req.voltage_id = voltage_id;
	msg.end_tag = 0;

	/* call mailbox property */
	err = bcm2835_mbox_property(&msg, sizeof(msg));
	if (err) {
		device_printf(sc->dev, "can't get min voltage\n");
		return (MSG_ERROR);
	}

	/* result (offset from 1.2V) */
	value = (int)msg.body.resp.value;
	DPRINTF("value = %d\n", value);
	return (value);
}
Пример #6
0
static int
bcm2835_cpufreq_get_temperature(struct bcm2835_cpufreq_softc *sc)
{
	struct msg_get_temperature msg;
	int value;
	int err;

	/*
	 * Get temperature
	 *   Tag: 0x00030006
	 *   Request:
	 *     Length: 4
	 *     Value:
	 *       u32: temperature id
	 *   Response:
	 *     Length: 8
	 *     Value:
	 *       u32: temperature id
	 *       u32: value
	 */

	/* setup single tag buffer */
	memset(&msg, 0, sizeof(msg));
	msg.hdr.buf_size = sizeof(msg);
	msg.hdr.code = BCM2835_MBOX_CODE_REQ;
	msg.tag_hdr.tag = BCM2835_MBOX_TAG_GET_TEMPERATURE;
	msg.tag_hdr.val_buf_size = sizeof(msg.body);
	msg.tag_hdr.val_len = sizeof(msg.body.req);
	msg.body.req.temperature_id = 0;
	msg.end_tag = 0;

	/* call mailbox property */
	err = bcm2835_mbox_property(&msg, sizeof(msg));
	if (err) {
		device_printf(sc->dev, "can't get temperature\n");
		return (MSG_ERROR);
	}

	/* result (temperature of degree C) */
	value = (int)msg.body.resp.value;
	DPRINTF("value = %d\n", value);
	return (value);
}
Пример #7
0
static int
bcm2835_cpufreq_get_turbo(struct bcm2835_cpufreq_softc *sc)
{
	struct msg_get_turbo msg;
	int level;
	int err;

	/*
	 * Get turbo
	 *   Tag: 0x00030009
	 *   Request:
	 *     Length: 4
	 *     Value:
	 *       u32: id
	 *   Response:
	 *     Length: 8
	 *     Value:
	 *       u32: id
	 *       u32: level
	 */

	/* setup single tag buffer */
	memset(&msg, 0, sizeof(msg));
	msg.hdr.buf_size = sizeof(msg);
	msg.hdr.code = BCM2835_MBOX_CODE_REQ;
	msg.tag_hdr.tag = BCM2835_MBOX_TAG_GET_TURBO;
	msg.tag_hdr.val_buf_size = sizeof(msg.body);
	msg.tag_hdr.val_len = sizeof(msg.body.req);
	msg.body.req.id = 0;
	msg.end_tag = 0;

	/* call mailbox property */
	err = bcm2835_mbox_property(&msg, sizeof(msg));
	if (err) {
		device_printf(sc->dev, "can't get turbo\n");
		return (MSG_ERROR);
	}

	/* result 0=non-turbo, 1=turbo */
	level = (int)msg.body.resp.level;
	DPRINTF("level = %d\n", level);
	return (level);
}
Пример #8
0
static int
bcm2835_cpufreq_set_clock_rate(struct bcm2835_cpufreq_softc *sc,
    uint32_t clock_id, uint32_t rate_hz)
{
	struct msg_set_clock_rate msg;
	int rate;
	int err;

	/*
	 * Set clock rate
	 *   Tag: 0x00038002
	 *   Request:
	 *     Length: 8
	 *     Value:
	 *       u32: clock id
	 *       u32: rate (in Hz)
	 *   Response:
	 *     Length: 8
	 *     Value:
	 *       u32: clock id
	 *       u32: rate (in Hz)
	 */

	/* setup single tag buffer */
	memset(&msg, 0, sizeof(msg));
	msg.hdr.buf_size = sizeof(msg);
	msg.hdr.code = BCM2835_MBOX_CODE_REQ;
	msg.tag_hdr.tag = BCM2835_MBOX_TAG_SET_CLOCK_RATE;
	msg.tag_hdr.val_buf_size = sizeof(msg.body);
	msg.tag_hdr.val_len = sizeof(msg.body.req);
	msg.body.req.clock_id = clock_id;
	msg.body.req.rate_hz = rate_hz;
	msg.end_tag = 0;

	/* call mailbox property */
	err = bcm2835_mbox_property(&msg, sizeof(msg));
	if (err) {
		device_printf(sc->dev, "can't set clock rate (id=%u)\n",
		    clock_id);
		return (MSG_ERROR);
	}

	/* workaround for core clock */
	if (clock_id == BCM2835_MBOX_CLOCK_ID_CORE) {
		/* for safety (may change voltage without changing clock) */
		DELAY(TRANSITION_LATENCY);

		/*
		 * XXX: the core clock is unable to change at once,
		 * to change certainly, write it twice now.
		 */

		/* setup single tag buffer */
		memset(&msg, 0, sizeof(msg));
		msg.hdr.buf_size = sizeof(msg);
		msg.hdr.code = BCM2835_MBOX_CODE_REQ;
		msg.tag_hdr.tag = BCM2835_MBOX_TAG_SET_CLOCK_RATE;
		msg.tag_hdr.val_buf_size = sizeof(msg.body);
		msg.tag_hdr.val_len = sizeof(msg.body.req);
		msg.body.req.clock_id = clock_id;
		msg.body.req.rate_hz = rate_hz;
		msg.end_tag = 0;

		/* call mailbox property */
		err = bcm2835_mbox_property(&msg, sizeof(msg));
		if (err) {
			device_printf(sc->dev,
			    "can't set clock rate (id=%u)\n", clock_id);
			return (MSG_ERROR);
		}
	}

	/* result (Hz) */
	rate = (int)msg.body.resp.rate_hz;
	DPRINTF("clock = %d(Hz)\n", rate);
	return (rate);
}