Esempio n. 1
0
static int
strtc_clock_read(struct strtc_softc *sc, struct clock_ymdhms *dt)
{
	u_int8_t bcd[M41ST84_REG_DATE_BYTES], cmdbuf[1];
	int i;

	if (iic_acquire_bus(sc->sc_tag, I2C_F_POLL)) {
		printf("%s: strtc_clock_read: failed to acquire I2C bus\n",
		    sc->sc_dev.dv_xname);
		return (0);
	}

	/* Read each RTC register in order. */
	for (i = M41ST84_REG_CSEC; i < M41ST84_REG_DATE_BYTES; i++) {
		cmdbuf[0] = i;

		if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
			     sc->sc_address, cmdbuf, 1,
			     &bcd[i], 1, I2C_F_POLL)) {
			iic_release_bus(sc->sc_tag, I2C_F_POLL);
			printf("%s: strtc_clock_read: failed to read rtc "
			    "at 0x%x\n", sc->sc_dev.dv_xname, i);
			return (0);
		}
	}

	/* Done with I2C */
	iic_release_bus(sc->sc_tag, I2C_F_POLL);

	/*
	 * Convert the M41ST84's register values into something useable
	 */
	dt->dt_sec = FROMBCD(bcd[M41ST84_REG_SEC] & M41ST84_SEC_MASK);
	dt->dt_min = FROMBCD(bcd[M41ST84_REG_MIN] & M41ST84_MIN_MASK);
	dt->dt_hour = FROMBCD(bcd[M41ST84_REG_CENHR] & M41ST84_HOUR_MASK);
	dt->dt_day = FROMBCD(bcd[M41ST84_REG_DATE] & M41ST84_DATE_MASK);
	dt->dt_mon = FROMBCD(bcd[M41ST84_REG_MONTH] & M41ST84_MONTH_MASK);

	/* XXX: Should be an MD way to specify EPOCH used by BIOS/Firmware */
	dt->dt_year = FROMBCD(bcd[M41ST84_REG_YEAR]) + POSIX_BASE_YEAR;

	return (1);
}
Esempio n. 2
0
int
pcaled_gpio_pin_read(void *arg, int pin)
{
	struct pcaled_softc *sc = arg;
	iic_acquire_bus(sc->sc_tag, I2C_F_POLL);
	uint8_t cmd, data;

	if (pin < 8)
		cmd = 0;
	else
		cmd = 1;
	if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_addr,
	    &cmd, 1, &data, 1, I2C_F_POLL))
		goto fail; /* XXX */

fail:
	iic_release_bus(sc->sc_tag, I2C_F_POLL);
	return (data >> (pin & 3)) & 1;
}
Esempio n. 3
0
int
lmtemp_temp_read(struct lmtemp_softc *sc, uint8_t which, int *valp)
{
	u_int8_t cmd, buf[2];
	int error;

	cmd = which;
	error = iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
	    sc->sc_addr, &cmd, 1, buf, 2, 0);
	if (error)
		return (error);

	/* Some chips return transient 0's.. we try next time */
	if (buf[0] == 0x00 && buf[1] == 0x00)
		return (1);

	/* convert to half-degrees C */
	*valp = ((buf[0] << 8) | buf[1]) / (1 << (16 - sc->sc_bits));
	return (0);
}
Esempio n. 4
0
int
max7301_match(struct device *parent, void *v, void *arg)
{
	struct i2c_attach_args *ia = arg;
	int ok = 0;
	uint8_t cmd, data;

	if (ia->ia_addr != MAX7301_ADDR)
		return (0);
	/* attempt to read input register 0 */
	iic_acquire_bus(ia->ia_tag, I2C_F_POLL);
	cmd = 0;
	if (iic_exec(ia->ia_tag, I2C_OP_READ_WITH_STOP, ia->ia_addr,
	    &cmd, sizeof cmd, &data, sizeof data, I2C_F_POLL))
		goto fail;
	ok = 1;
fail:
	iic_release_bus(ia->ia_tag, I2C_F_POLL);
	return (ok);
}
Esempio n. 5
0
void
maxds_refresh(void *arg)
{
	struct maxds_softc *sc = arg;
	u_int8_t cmd;
	u_int16_t data;

	iic_acquire_bus(sc->sc_tag, 0);

	cmd = DS1631_TEMP;
	if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
	    sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0) {
		sc->sc_sensor[MAXDS_TEMP].value = 273150000 +
		    (int)(betoh16(data)) / 8 * 31250;
		sc->sc_sensor[MAXDS_TEMP].flags &= ~SENSOR_FINVALID;
	} else
		sc->sc_sensor[MAXDS_TEMP].flags |= SENSOR_FINVALID;

	iic_release_bus(sc->sc_tag, 0);
}
Esempio n. 6
0
int
lmtemp_temp_read(struct lmtemp_softc *sc, uint8_t which, int *valp)
{
	u_int8_t cmd;
	u_int16_t data = 0x0000;
	int error;

	cmd = which;
	error = iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
	    sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0);
	if (error)
		return (error);

	/* Some chips return transient 0's.. we try next time */
	if (data == 0x0000)
		return (1);

	/* convert to half-degrees C */
	*valp = betoh16(data) / (1 << (16 - sc->sc_bits));
	return (0);
}
Esempio n. 7
0
static int
as3722_match(device_t parent, cfdata_t match, void *aux)
{
	struct i2c_attach_args *ia = aux;
	uint8_t reg, id1;
	int error;

	if (ia->ia_name == NULL) {
		iic_acquire_bus(ia->ia_tag, I2C_F_POLL);
		reg = AS3722_ASIC_ID1_REG;
		error = iic_exec(ia->ia_tag, I2C_OP_READ_WITH_STOP, ia->ia_addr,
		    &reg, 1, &id1, 1, I2C_F_POLL);
		iic_release_bus(ia->ia_tag, I2C_F_POLL);

		if (error == 0 && id1 == 0x0c)
			return 1;

		return 0;
	} else {
		return iic_compat_match(ia, as3722_compats);
	}
}
Esempio n. 8
0
static int
awin_hdmi_read_edid_block(struct awin_hdmi_softc *sc, uint8_t *data,
    uint8_t block)
{
	i2c_tag_t tag = &sc->sc_ic;
	uint8_t wbuf[2];
	int error;

	if ((error = iic_acquire_bus(tag, I2C_F_POLL)) != 0)
		return error;

	wbuf[0] = block;	/* start address */

	if ((error = iic_exec(tag, I2C_OP_READ_WITH_STOP, DDC_ADDR, wbuf, 1,
	    data, 128, I2C_F_POLL)) != 0) {
		iic_release_bus(tag, I2C_F_POLL);
		return error;
	}
	iic_release_bus(tag, I2C_F_POLL);

	return 0;
}
Esempio n. 9
0
static uint8_t
tps65217pmic_reg_read(struct tps65217pmic_softc *sc, uint8_t reg)
{
	uint8_t wbuf[2];
	uint8_t rv;

	if (iic_acquire_bus(sc->sc_tag, I2C_F_POLL) != 0) {
		aprint_error_dev(sc->sc_dev, "cannot acquire bus for read\n");
		return 0;
	}

	wbuf[0] = reg;

	if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_addr, wbuf,
	    1, &rv, 1, I2C_F_POLL)) {
		aprint_error_dev(sc->sc_dev, "cannot execute operation\n");
		iic_release_bus(sc->sc_tag, I2C_F_POLL);
		return 0;
	}
	iic_release_bus(sc->sc_tag, I2C_F_POLL);

	return rv;
}
Esempio n. 10
0
static int
rs5c372rtc_clock_write(struct rs5c372rtc_softc *sc, struct clock_ymdhms *dt)
{
	uint8_t bcd[RS5C372_NRTC_REGS];
	uint8_t cmdbuf[1];

	/*
	 * Convert our time representation into something the RS5C372
	 * can understand.
	 */
	bcd[RS5C372_SECONDS] = TOBCD(dt->dt_sec);
	bcd[RS5C372_MINUTES] = TOBCD(dt->dt_min);
	bcd[RS5C372_HOURS] = TOBCD(dt->dt_hour);
	bcd[RS5C372_DATE] = TOBCD(dt->dt_day);
	bcd[RS5C372_DAY] = TOBCD(dt->dt_wday);
	bcd[RS5C372_MONTH] = TOBCD(dt->dt_mon);
	bcd[RS5C372_YEAR] = TOBCD(dt->dt_year % 100);

	if (iic_acquire_bus(sc->sc_tag, I2C_F_POLL)) {
		aprint_error_dev(sc->sc_dev, "rs5c372rtc_clock_write: failed to "
		    "acquire I2C bus\n");
		return (0);
	}

	cmdbuf[0] = (RS5C372_SECONDS << 4);
	if (iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP, sc->sc_address,
	             cmdbuf, 1, bcd, RS5C372_NRTC_REGS, I2C_F_POLL)) {
		iic_release_bus(sc->sc_tag, I2C_F_POLL);
		aprint_error_dev(sc->sc_dev,
		    "rs5c372rtc_clock_write: failed to write rtc\n");
		return (0);
	}

	iic_release_bus(sc->sc_tag, I2C_F_POLL);

	return (1);
}
Esempio n. 11
0
/*ARGSUSED*/
int
pcfrtc_read(dev_t dev, struct uio *uio, int flags)
{
	struct pcfrtc_softc *sc;
	u_int8_t ch, cmdbuf[1];
	int a, error;

	if ((sc = device_lookup(&pcfrtc_cd, minor(dev))) == NULL)
		return (ENXIO);

	if (uio->uio_offset >= PCF8583_NVRAM_SIZE)
		return (EINVAL);

	if ((error = iic_acquire_bus(sc->sc_tag, 0)) != 0)
		return (error);

	while (uio->uio_resid && uio->uio_offset < PCF8583_NVRAM_SIZE) {
		a = (int)uio->uio_offset;
		cmdbuf[0] = a + PCF8583_NVRAM_START;
		if ((error = iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
				      sc->sc_address, cmdbuf, 1,
				      &ch, 1, 0)) != 0) {
			iic_release_bus(sc->sc_tag, 0);
			printf("%s: pcfrtc_read: read failed at 0x%x\n",
			    sc->sc_dev.dv_xname, a);
			return (error);
		}
		if ((error = uiomove(&ch, 1, uio)) != 0) {
			iic_release_bus(sc->sc_tag, 0);
			return (error);
		}
	}

	iic_release_bus(sc->sc_tag, 0);

	return (0);
}
Esempio n. 12
0
/*ARGSUSED*/
int
m41t00_read(dev_t dev, struct uio *uio, int flags)
{
	struct m41t00_softc *sc;
	u_int8_t ch, cmdbuf[1];
	int a, error;

	if ((sc = device_lookup_private(&m41trtc_cd, minor(dev))) == NULL)
		return ENXIO;

	if (uio->uio_offset >= M41T00_NBYTES)
		return EINVAL;

	if ((error = iic_acquire_bus(sc->sc_tag, 0)) != 0)
		return error;

	while (uio->uio_resid && uio->uio_offset < M41T00_NBYTES) {
		a = (int)uio->uio_offset;
		cmdbuf[0] = a;
		if ((error = iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
				      sc->sc_address, cmdbuf, 1,
				      &ch, 1, 0)) != 0) {
			iic_release_bus(sc->sc_tag, 0);
			aprint_error_dev(sc->sc_dev,
			    "m41t00_read: read failed at 0x%x\n", a);
			return error;
		}
		if ((error = uiomove(&ch, 1, uio)) != 0) {
			iic_release_bus(sc->sc_tag, 0);
			return error;
		}
	}

	iic_release_bus(sc->sc_tag, 0);

	return 0;
}
Esempio n. 13
0
static int
pcf8563rtc_clock_read(struct pcf8563rtc_softc *sc, struct clock_ymdhms *dt)
{
	uint8_t bcd[PCF8563_NREGS];
	uint8_t reg = PCF8563_R_SECOND;
	const int flags = cold ? I2C_F_POLL : 0;

	if (iic_acquire_bus(sc->sc_tag, flags)) {
		device_printf(sc->sc_dev, "acquire bus for read failed\n");
		return 0;
	}

	if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_addr, &reg, 1,
		     &bcd[reg], PCF8563_R_YEAR - reg + 1, flags)) {
		iic_release_bus(sc->sc_tag, flags);
		device_printf(sc->sc_dev, "read failed\n");
		return 0;
	}

	iic_release_bus(sc->sc_tag, flags);

	if (bcd[PCF8563_R_SECOND] & PCF8563_M_VL)
		return 0;

	dt->dt_sec = bcdtobin(bcd[PCF8563_R_SECOND] & PCF8563_M_SECOND);
	dt->dt_min = bcdtobin(bcd[PCF8563_R_MINUTE] & PCF8563_M_MINUTE);
	dt->dt_hour = bcdtobin(bcd[PCF8563_R_HOUR] & PCF8563_M_HOUR);
	dt->dt_day = bcdtobin(bcd[PCF8563_R_DAY] & PCF8563_M_DAY);
	dt->dt_wday = bcdtobin(bcd[PCF8563_R_WEEKDAY] & PCF8563_M_WEEKDAY);
	dt->dt_mon = bcdtobin(bcd[PCF8563_R_MONTH] & PCF8563_M_MONTH);
	dt->dt_year = 1900 +
	    (bcdtobin(bcd[PCF8563_R_YEAR] & PCF8563_M_YEAR) % 100);
	if ((bcd[PCF8563_R_MONTH] & PCF8563_M_CENTURY) == 0)
		dt->dt_year += 100;

	return 1;
}
Esempio n. 14
0
/*ARGSUSED*/
int
strtc_read(dev_t dev, struct uio *uio, int flags)
{
	struct strtc_softc *sc;
	u_int8_t ch, cmdbuf[1];
	int a, error;

	if ((sc = device_lookup_private(&strtc_cd, minor(dev))) == NULL)
		return (ENXIO);

	if (uio->uio_offset >= M41ST84_USER_RAM_SIZE)
		return (EINVAL);

	if ((error = iic_acquire_bus(sc->sc_tag, 0)) != 0)
		return (error);

	while (uio->uio_resid && uio->uio_offset < M41ST84_USER_RAM_SIZE) {
		a = (int)uio->uio_offset;
		cmdbuf[0] = a + M41ST84_USER_RAM;
		if ((error = iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
				      sc->sc_address, cmdbuf, 1,
				      &ch, 1, 0)) != 0) {
			iic_release_bus(sc->sc_tag, 0);
			aprint_error_dev(sc->sc_dev,
			    "strtc_read: read failed at 0x%x\n", a);
			return (error);
		}
		if ((error = uiomove(&ch, 1, uio)) != 0) {
			iic_release_bus(sc->sc_tag, 0);
			return (error);
		}
	}

	iic_release_bus(sc->sc_tag, 0);

	return (0);
}
Esempio n. 15
0
static void
rs5c372rtc_reg_write(struct rs5c372rtc_softc *sc, int reg, uint8_t val)
{
	uint8_t cmdbuf[2];

	if (iic_acquire_bus(sc->sc_tag, I2C_F_POLL)) {
		aprint_error_dev(sc->sc_dev,
		    "rs5c372rtc_reg_write: failed to acquire I2C bus\n");
		return;
	}

	reg &= 0xf;
	cmdbuf[0] = (reg << 4);
	cmdbuf[1] = val;
	if (iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP, sc->sc_address,
	             cmdbuf, 1, &cmdbuf[1], 1, I2C_F_POLL)) {
		iic_release_bus(sc->sc_tag, I2C_F_POLL);
		aprint_error_dev(sc->sc_dev,
		    "rs5c372rtc_reg_write: failed to write reg%d\n", reg);
		return;
	}

	iic_release_bus(sc->sc_tag, I2C_F_POLL);
}
Esempio n. 16
0
static int
strtc_clock_write(struct strtc_softc *sc, struct clock_ymdhms *dt)
{
	uint8_t bcd[M41ST84_REG_DATE_BYTES], cmdbuf[2];
	int i;

	/*
	 * Convert our time representation into something the M41ST84
	 * can understand.
	 */
	bcd[M41ST84_REG_CSEC] = TOBCD(0);	/* must always write as 0 */
	bcd[M41ST84_REG_SEC] = TOBCD(dt->dt_sec);
	bcd[M41ST84_REG_MIN] = TOBCD(dt->dt_min);
	bcd[M41ST84_REG_CENHR] = TOBCD(dt->dt_hour);
	bcd[M41ST84_REG_DATE] = TOBCD(dt->dt_day);
	bcd[M41ST84_REG_DAY] = TOBCD(dt->dt_wday);
	bcd[M41ST84_REG_MONTH] = TOBCD(dt->dt_mon);
	bcd[M41ST84_REG_YEAR] = TOBCD((dt->dt_year - POSIX_BASE_YEAR) % 100);

	if (iic_acquire_bus(sc->sc_tag, I2C_F_POLL)) {
		aprint_error_dev(sc->sc_dev,
		    "strtc_clock_write: failed to acquire I2C bus\n");
		return (0);
	}

	/* Stop the clock */
	cmdbuf[0] = M41ST84_REG_SEC;
	cmdbuf[1] = M41ST84_SEC_ST;

	if (iic_exec(sc->sc_tag, I2C_OP_WRITE, sc->sc_address,
		     cmdbuf, 1, &cmdbuf[1], 1, I2C_F_POLL)) {
		iic_release_bus(sc->sc_tag, I2C_F_POLL);
		aprint_error_dev(sc->sc_dev,
		    "strtc_clock_write: failed to Hold Clock\n");
		return (0);
	}

	/*
	 * Check for the HT bit -- if set, then clock lost power & stopped
	 * If that happened, then clear the bit so that the clock will have
	 * a chance to run again.
	 */
	cmdbuf[0] = M41ST84_REG_AL_HOUR;
	if (iic_exec(sc->sc_tag, I2C_OP_READ, sc->sc_address,
		     cmdbuf, 1, &cmdbuf[1], 1, I2C_F_POLL)) {
		iic_release_bus(sc->sc_tag, I2C_F_POLL);
		aprint_error_dev(sc->sc_dev,
		    "strtc_clock_write: failed to read HT\n");
		return (0);
	}
	if (cmdbuf[1] & M41ST84_AL_HOUR_HT) {
		cmdbuf[1] &= ~M41ST84_AL_HOUR_HT;
		if (iic_exec(sc->sc_tag, I2C_OP_WRITE, sc->sc_address,
			     cmdbuf, 1, &cmdbuf[1], 1, I2C_F_POLL)) {
			iic_release_bus(sc->sc_tag, I2C_F_POLL);
			aprint_error_dev(sc->sc_dev,
			    "strtc_clock_write: failed to reset HT\n");
			return (0);
		}
	}

	/*
	 * Write registers in reverse order. The last write (to the Seconds
	 * register) will undo the Clock Hold, above.
	 */
	for (i = M41ST84_REG_DATE_BYTES - 1; i >= 0; i--) {
		cmdbuf[0] = i;
		if (iic_exec(sc->sc_tag,
			     i ? I2C_OP_WRITE : I2C_OP_WRITE_WITH_STOP,
			     sc->sc_address, cmdbuf, 1, &bcd[i], 1,
			     I2C_F_POLL)) {
			iic_release_bus(sc->sc_tag, I2C_F_POLL);
			aprint_error_dev(sc->sc_dev,
			    "strtc_clock_write: failed to write rtc "
			    " at 0x%x\n", i);
			/* XXX: Clock Hold is likely still asserted! */
			return (0);
		}
	}

	iic_release_bus(sc->sc_tag, I2C_F_POLL);

	return (1);
}
Esempio n. 17
0
void
maxds_attach(struct device *parent, struct device *self, void *aux)
{
	struct maxds_softc *sc = (struct maxds_softc *)self;
	struct i2c_attach_args *ia = aux;
	u_int8_t cmd, data;
	int i;

	printf(": %s", ia->ia_name);

	sc->sc_tag = ia->ia_tag;
	sc->sc_addr = ia->ia_addr;

	iic_acquire_bus(sc->sc_tag, 0);

	cmd = DS1631_CONTROL;
	if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
	    sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0) {
		if (data & DS1631_CONTROL_1SHOT) {
			/*
			 * 1-Shot mode would require us to write every refresh
			 * which is stupid.  Put us into continuous mode.
			 */
			data &= ~DS1631_CONTROL_1SHOT;

			(void) iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP,
			    sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0);
			//delay(10 * 1000);
			printf(", continuous");
			goto dostart;
		}
		if (data & DS1631_CONTROL_DONE) {
dostart:
			cmd = DS1631_START;
			if (strcmp(ia->ia_name, "ds1624") == 0)
				cmd = DS1624_START;
			(void) iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP,
			    sc->sc_addr, &cmd, sizeof cmd, NULL, 0, 0);
			printf(", starting");
		}
	}

	iic_release_bus(sc->sc_tag, 0);

	/* Initialize sensor data. */
	strlcpy(sc->sc_sensordev.xname, sc->sc_dev.dv_xname,
	    sizeof(sc->sc_sensordev.xname));

	sc->sc_sensor[MAXDS_TEMP].type = SENSOR_TEMP;
	strlcpy(sc->sc_sensor[MAXDS_TEMP].desc, "Internal",
	    sizeof(sc->sc_sensor[MAXDS_TEMP].desc));

	if (sensor_task_register(sc, maxds_refresh, 5) == NULL) {
		printf(", unable to register update task\n");
		return;
	}

	for (i = 0; i < MAXDS_NUM_SENSORS; i++)
		sensor_attach(&sc->sc_sensordev, &sc->sc_sensor[i]);
	sensordev_install(&sc->sc_sensordev);

	printf("\n");
}
Esempio n. 18
0
static void
pic16lc_read_1(struct pic16lc_softc *sc, uint8_t cmd, uint8_t *valp)
{
	iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
	    sc->sc_addr, &cmd, 1, valp, 1, 0);
}
Esempio n. 19
0
static int
strtc_clock_read(struct strtc_softc *sc, struct clock_ymdhms *dt)
{
	u_int8_t bcd[M41ST84_REG_DATE_BYTES], cmdbuf[1];
	int i;

	if (iic_acquire_bus(sc->sc_tag, I2C_F_POLL)) {
		aprint_error_dev(sc->sc_dev,
		    "strtc_clock_read: failed to acquire I2C bus\n");
		return (0);
	}

	/*
	 * Check for the HT bit -- if set, then clock lost power & stopped
	 * If that happened, then clear the bit so that the clock will have
	 * a chance to run again.
	 */
	cmdbuf[0] = M41ST84_REG_AL_HOUR;
	if (iic_exec(sc->sc_tag, I2C_OP_READ, sc->sc_address,
		     cmdbuf, 1, &cmdbuf[1], 1, I2C_F_POLL)) {
		iic_release_bus(sc->sc_tag, I2C_F_POLL);
		aprint_error_dev(sc->sc_dev,
		    "strtc_clock_read: failed to read HT\n");
		return (0);
	}
	if (cmdbuf[1] & M41ST84_AL_HOUR_HT) {
		cmdbuf[1] &= ~M41ST84_AL_HOUR_HT;
		if (iic_exec(sc->sc_tag, I2C_OP_WRITE, sc->sc_address,
			     cmdbuf, 1, &cmdbuf[1], 1, I2C_F_POLL)) {
			iic_release_bus(sc->sc_tag, I2C_F_POLL);
			aprint_error_dev(sc->sc_dev,
			    "strtc_clock_read: failed to reset HT\n");
			return (0);
		}
	}

	/* Read each RTC register in order. */
	for (i = M41ST84_REG_CSEC; i < M41ST84_REG_DATE_BYTES; i++) {
		cmdbuf[0] = i;

		if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
			     sc->sc_address, cmdbuf, 1,
			     &bcd[i], 1, I2C_F_POLL)) {
			iic_release_bus(sc->sc_tag, I2C_F_POLL);
			aprint_error_dev(sc->sc_dev,
			    "strtc_clock_read: failed to read rtc "
			    "at 0x%x\n", i);
			return (0);
		}
	}

	/* Done with I2C */
	iic_release_bus(sc->sc_tag, I2C_F_POLL);

	/*
	 * Convert the M41ST84's register values into something useable
	 */
	dt->dt_sec = FROMBCD(bcd[M41ST84_REG_SEC] & M41ST84_SEC_MASK);
	dt->dt_min = FROMBCD(bcd[M41ST84_REG_MIN] & M41ST84_MIN_MASK);
	dt->dt_hour = FROMBCD(bcd[M41ST84_REG_CENHR] & M41ST84_HOUR_MASK);
	dt->dt_day = FROMBCD(bcd[M41ST84_REG_DATE] & M41ST84_DATE_MASK);
	dt->dt_mon = FROMBCD(bcd[M41ST84_REG_MONTH] & M41ST84_MONTH_MASK);

	/* XXX: Should be an MD way to specify EPOCH used by BIOS/Firmware */
	dt->dt_year = FROMBCD(bcd[M41ST84_REG_YEAR]) + POSIX_BASE_YEAR;

	return (1);
}
Esempio n. 20
0
static void
coram_attach(device_t parent, device_t self, void *aux)
{
	struct coram_softc *sc = device_private(self);
	const struct pci_attach_args *pa = aux;
	pci_intr_handle_t ih;
	pcireg_t reg;
	const char *intrstr;
	struct coram_iic_softc *cic;
	uint32_t value;
	int i;
#ifdef CORAM_ATTACH_I2C
	struct i2cbus_attach_args iba;
#endif

	sc->sc_dev = self;

	pci_aprint_devinfo(pa, NULL);

	reg = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_SUBSYS_ID_REG);
	sc->sc_board = coram_board_lookup(PCI_VENDOR(reg), PCI_PRODUCT(reg));
	KASSERT(sc->sc_board != NULL);

	if (pci_mapreg_map(pa, CX23885_MMBASE, PCI_MAPREG_TYPE_MEM, 0,
			   &sc->sc_memt, &sc->sc_memh, NULL, &sc->sc_mems)) {
		aprint_error_dev(self, "couldn't map memory space\n");
		return;
	}

	sc->sc_dmat = pa->pa_dmat;
	sc->sc_pc = pa->pa_pc;

	if (pci_intr_map(pa, &ih)) {
		aprint_error_dev(self, "couldn't map interrupt\n");
		return;
	}
	intrstr = pci_intr_string(pa->pa_pc, ih);
	sc->sc_ih = pci_intr_establish(pa->pa_pc, ih, IPL_VM, coram_intr, self);
	if (sc->sc_ih == NULL) {
		aprint_error_dev(self, "couldn't establish interrupt");
		if (intrstr != NULL)
			aprint_error(" at %s", intrstr);
		aprint_error("\n");
		return;
	}
	aprint_normal_dev(self, "interrupting at %s\n", intrstr);

	/* set master */
	reg = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG);
	reg |= PCI_COMMAND_MASTER_ENABLE;
	pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, reg);

	/* I2C */
	for(i = 0; i < I2C_NUM; i++) {
		cic = &sc->sc_iic[i];

		cic->cic_sc = sc;
		if (bus_space_subregion(sc->sc_memt, sc->sc_memh,
		    I2C_BASE + (I2C_SIZE * i), I2C_SIZE, &cic->cic_regh))
			panic("failed to subregion i2c");

		mutex_init(&cic->cic_busmutex, MUTEX_DRIVER, IPL_NONE);
		cic->cic_i2c.ic_cookie = cic;
		cic->cic_i2c.ic_acquire_bus = coram_iic_acquire_bus;
		cic->cic_i2c.ic_release_bus = coram_iic_release_bus;
		cic->cic_i2c.ic_exec = coram_iic_exec;

#ifdef CORAM_ATTACH_I2C
		/* attach iic(4) */
		memset(&iba, 0, sizeof(iba));
		iba.iba_tag = &cic->cic_i2c;
		iba.iba_type = I2C_TYPE_SMBUS;
		cic->cic_i2cdev = config_found_ia(self, "i2cbus", &iba,
		    iicbus_print);
#endif
	}

	/* HVR1250 GPIO */
	value = bus_space_read_4(sc->sc_memt, sc->sc_memh, 0x110010);
#if 1
	value &= ~0x00010001;
	bus_space_write_4(sc->sc_memt, sc->sc_memh, 0x110010, value);
	delay(5000);
#endif
	value |= 0x00010001;
	bus_space_write_4(sc->sc_memt, sc->sc_memh, 0x110010, value);

#if 0
	int i;
	uint8_t foo[256];
	uint8_t bar;
	bar = 0;
//	seeprom_bootstrap_read(&sc->sc_i2c, 0x50, 0, 256, foo, 256);

	iic_acquire_bus(&sc->sc_i2c, I2C_F_POLL);
	iic_exec(&sc->sc_i2c, I2C_OP_READ_WITH_STOP, 0x50, &bar, 1, foo, 256,
	    I2C_F_POLL);
	iic_release_bus(&sc->sc_i2c, I2C_F_POLL);

	printf("\n");
	for ( i = 0; i < 256; i++) {
		if ( (i % 8) == 0 )
			printf("%02x: ", i);

		printf("%02x", foo[i]);

		if ( (i % 8) == 7 )
			printf("\n");
		else
			printf(" ");
	}
	printf("\n");
#endif

	sc->sc_demod = cx24227_open(sc->sc_dev, &sc->sc_iic[0].cic_i2c, 0x19);
	if (sc->sc_demod == NULL)
		aprint_error_dev(self, "couldn't open cx24227\n");
	sc->sc_tuner = mt2131_open(sc->sc_dev, &sc->sc_iic[0].cic_i2c, 0x61);
	if (sc->sc_tuner == NULL)
		aprint_error_dev(self, "couldn't open mt2131\n");

	coram_mpeg_attach(sc);

	if (!pmf_device_register(self, NULL, coram_resume))
		aprint_error_dev(self, "couldn't establish power handler\n");

	return;
}
Esempio n. 21
0
void
tsl_attach(struct device *parent, struct device *self, void *aux)
{
	struct tsl_softc *sc = (struct tsl_softc *)self;
	struct i2c_attach_args *ia = aux;
	u_int8_t cmd, data;

	sc->sc_tag = ia->ia_tag;
	sc->sc_addr = ia->ia_addr;

	iic_acquire_bus(sc->sc_tag, 0);
	cmd = TSL2560_REG_CONTROL; data = TSL2560_CONTROL_POWER;
	if (iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP,
	    sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) {
		iic_release_bus(sc->sc_tag, 0);
		printf(": power up failed\n");
		return;
	}
	cmd = TSL2560_REG_TIMING;
	data = TSL2560_TIMING_GAIN | TSL2560_TIMING_INTEG2;
	if (iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP,
	    sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) {
		iic_release_bus(sc->sc_tag, 0);
		printf(": cannot write timing register\n");
		return;
	}
	cmd = TSL2560_REG_ID;
	if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
	    sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) {
		iic_release_bus(sc->sc_tag, 0);
		printf(": cannot read ID register\n");
		return;
	}
	iic_release_bus(sc->sc_tag, 0);

	switch (data >> 4) {
	case 0:
		printf(": TSL2560 rev %x", data & 0x0f);
		break;
	case 1:
		printf(": TSL2561 rev %x", data & 0x0f);
		break;
	default:
		printf(": unknown part number %x", data >> 4);
		break;
	}

	/* Initialize sensor data. */
	strlcpy(sc->sc_sensordev.xname, sc->sc_dev.dv_xname,
	    sizeof(sc->sc_sensordev.xname));
	sc->sc_sensor.type = SENSOR_LUX;

	if (sensor_task_register(sc, tsl_refresh, 5) == NULL) {
		printf(": unable to register update task\n");
		return;
	}

	sensor_attach(&sc->sc_sensordev, &sc->sc_sensor);
	sensordev_install(&sc->sc_sensordev);

	printf("\n");
}
Esempio n. 22
0
int
cros_ec_i2c_command(struct cros_ec_softc *sc, uint8_t cmd, int cmd_version,
		const uint8_t *out, int out_len, uint8_t **in, int in_len)
{
	int out_bytes, in_bytes, ret;
	uint8_t *ptr = sc->out;
	uint8_t *inptr = sc->in;

	inptr += sizeof(uint64_t); /* returned data should be 64-bit aligned */
	if (!sc->cmd_version_is_supported) {
		/* old-style */
		*ptr++ = cmd;
		out_bytes = out_len + 1;
		in_bytes = in_len + 2;
		inptr--; /* status byte */
	} else {
		/* new-style */
		*ptr++ = EC_CMD_VERSION0 + cmd_version;
		*ptr++ = cmd;
		*ptr++ = out_len;
		out_bytes = out_len + 4;
		in_bytes = in_len + 3;
		inptr -= 2; /* status byte, length */
	}
	memcpy(ptr, out, out_len);
	ptr += out_len;

	if (sc->cmd_version_is_supported)
		*ptr++ = (uint8_t)
			 cros_ec_calc_checksum(sc->out, out_len + 3);

	iic_acquire_bus(sc->sc_tag, 0);
	ret = iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP,
	    sc->sc_addr, NULL, 0, &sc->out, out_bytes, 0);
	if (ret) {
		DPRINTF(("%s: I2C write failed\n", __func__));
		iic_release_bus(sc->sc_tag, 0);
		return -1;
	}

	ret = iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
	    sc->sc_addr, NULL, 0, inptr, in_bytes, 0);
	if (ret) {
		DPRINTF(("%s: I2C read failed\n", __func__));
		iic_release_bus(sc->sc_tag, 0);
		return -1;
	}

	iic_release_bus(sc->sc_tag, 0);

	if (*inptr != EC_RES_SUCCESS) {
		DPRINTF(("%s: bad result\n", __func__));
		return -(int)*inptr;
	}

	if (sc->cmd_version_is_supported) {
		int len, csum;

		len = inptr[1];
		if (len > sizeof(sc->in)) {
			DPRINTF(("%s: Received length too large\n", __func__));
			return -1;
		}
		csum = cros_ec_calc_checksum(inptr, 2 + len);
		if (csum != inptr[2 + len]) {
			DPRINTF(("%s: Invalid checksum\n", __func__));
			return -1;
		}
		in_len = min(in_len, len);
	}

	*in = sc->in + sizeof(uint64_t);

	return in_len;
}
Esempio n. 23
0
static int
m41t00_clock_write(struct m41t00_softc *sc, struct clock_ymdhms *dt)
{
	uint8_t bcd[M41T00_DATE_BYTES], cmdbuf[2];
	uint8_t init_seconds, final_seconds;
	int i;

	/*
	 * Convert our time representation into something the MAX6900
	 * can understand.
	 */
	bcd[M41T00_SEC] = TOBCD(dt->dt_sec);
	bcd[M41T00_MIN] = TOBCD(dt->dt_min);
	bcd[M41T00_CENHR] = TOBCD(dt->dt_hour);
	bcd[M41T00_DATE] = TOBCD(dt->dt_day);
	bcd[M41T00_DAY] = TOBCD(dt->dt_wday);
	bcd[M41T00_MONTH] = TOBCD(dt->dt_mon);
	bcd[M41T00_YEAR] = TOBCD(dt->dt_year % 100);

	if (iic_acquire_bus(sc->sc_tag, I2C_F_POLL)) {
		aprint_error_dev(sc->sc_dev,
		    "m41t00_clock_write: failed to acquire I2C bus\n");
		return 0;
	}

	/*
	 * The MAX6900 RTC manual recommends ensuring "atomicity" of
	 * a non-burst write by:
	 *
	 *	- writing SECONDS
	 *	- reading back SECONDS, remembering it as "initial seconds"
	 *	- write the remaing RTC registers
	 *	- read back SECONDS as "final seconds"
	 *	- if "initial seconds" == 59, ensure "final seconds" == 59
	 *	- else, ensure "final seconds" is no more than one second
	 *	  beyond "initial seconds".
	 *
	 * This sounds reasonable for the M41T00, too.
	 */
 again:
	cmdbuf[0] = M41T00_SEC;
	if (iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP, sc->sc_address,
		     cmdbuf, 1, &bcd[M41T00_SEC], 1, I2C_F_POLL)) {
		iic_release_bus(sc->sc_tag, I2C_F_POLL);
		aprint_error_dev(sc->sc_dev,
		    "m41t00_clock_write: failed to write SECONDS\n");
		return 0;
	}

	cmdbuf[0] = M41T00_SEC;
	if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_address,
		     cmdbuf, 1, &init_seconds, 1, I2C_F_POLL)) {
		iic_release_bus(sc->sc_tag, I2C_F_POLL);
		aprint_error_dev(sc->sc_dev,
		    "m41t00_clock_write: failed to read "
		    "INITIAL SECONDS\n");
		return 0;
	}
	init_seconds = FROMBCD(init_seconds & M41T00_SEC_MASK);

	for (i = 1; i < M41T00_DATE_BYTES; i++) {
		cmdbuf[0] = m41t00_rtc_offset[i];
		if (iic_exec(sc->sc_tag,
			     I2C_OP_WRITE_WITH_STOP, sc->sc_address,
			     cmdbuf, 1, &bcd[i], 1, I2C_F_POLL)) {
			iic_release_bus(sc->sc_tag, I2C_F_POLL);
			aprint_error_dev(sc->sc_dev,
			    "m41t00_clock_write: failed to write rtc "
			    " at 0x%x\n",
			    m41t00_rtc_offset[i]);
			return 0;
		}
	}

	cmdbuf[0] = M41T00_SEC;
	if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_address,
		     cmdbuf, 1, &final_seconds, 1, I2C_F_POLL)) {
		iic_release_bus(sc->sc_tag, I2C_F_POLL);
		aprint_error_dev(sc->sc_dev,
		    "m41t00_clock_write: failed to read "
		    "FINAL SECONDS\n");
		return 0;
	}
	final_seconds = FROMBCD(final_seconds & M41T00_SEC_MASK);

	if ((init_seconds != final_seconds) &&
	    (((init_seconds + 1) % 60) != final_seconds)) {
#if 1
		printf("%s: m41t00_clock_write: init %d, final %d, try again\n",
		    device_xname(sc->sc_dev), init_seconds, final_seconds);
#endif
		goto again;
	}

	iic_release_bus(sc->sc_tag, I2C_F_POLL);

	return 1;
}
Esempio n. 24
0
void
adc_attach(struct device *parent, struct device *self, void *aux)
{
	struct adc_softc *sc = (struct adc_softc *)self;
	struct i2c_attach_args *ia = aux;
	u_int8_t cmd, data;
	int nsens = 0, i;

	sc->sc_tag = ia->ia_tag;
	sc->sc_addr = ia->ia_addr;

	printf(": %s", ia->ia_name);

	sc->sc_chip = 0;
	if (strcmp(ia->ia_name, "ad7417") == 0)
		sc->sc_chip = 7417;
	if (strcmp(ia->ia_name, "ad7418") == 0)
		sc->sc_chip = 7418;

	if (sc->sc_chip != 0) {
		cmd = AD741X_CONFIG2;
		data = 0;
		if (iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP,
		    sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) {
			printf(", config2 reset failed\n");
			return;
		}
	}

	cmd = AD741X_CONFIG;
	if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
	    sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) {
		printf(", config reset failed\n");
		return;
	}
	data &= 0xfe;
	if (iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP,
	    sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) {
		printf(", config reset failed\n");
		return;
	}
	sc->sc_config = data;

	/* Initialize sensor data. */
	strlcpy(sc->sc_sensordev.xname, sc->sc_dev.dv_xname,
	    sizeof(sc->sc_sensordev.xname));

	sc->sc_sensor[ADC_TEMP].type = SENSOR_TEMP;
	strlcpy(sc->sc_sensor[ADC_TEMP].desc, "Internal",
	    sizeof(sc->sc_sensor[ADC_TEMP].desc));
	nsens = 1;

	if (sc->sc_chip == 7417 || sc->sc_chip == 7418) {
		sc->sc_sensor[ADC_ADC0].type = SENSOR_INTEGER;
		nsens++;
	}
	if (sc->sc_chip == 7417 || sc->sc_chip == 7418) {
		sc->sc_sensor[ADC_ADC1].type = SENSOR_INTEGER;
		sc->sc_sensor[ADC_ADC2].type = SENSOR_INTEGER;
		sc->sc_sensor[ADC_ADC3].type = SENSOR_INTEGER;
		nsens += 3;
	}

	if (sensor_task_register(sc, adc_refresh, 5) == NULL) {
		printf(", unable to register update task\n");
		return;
	}

	sensor_attach(&sc->sc_sensordev, &sc->sc_sensor[0]);
	if (sc->sc_chip == 7417 || sc->sc_chip == 7418)
		sensor_attach(&sc->sc_sensordev, &sc->sc_sensor[1]);
	if (sc->sc_chip == 7417)
		for (i = 2; i < nsens; i++)
			sensor_attach(&sc->sc_sensordev, &sc->sc_sensor[i]);
	sensordev_install(&sc->sc_sensordev);

	printf("\n");
}
Esempio n. 25
0
static int
pcfrtc_clock_read(struct pcfrtc_softc *sc, struct clock_ymdhms *dt,
    uint8_t *centi)
{
	u_int8_t bcd[10], cmdbuf[1];
	int i, err;

	if ((err = iic_acquire_bus(sc->sc_tag, I2C_F_POLL))) {
		aprint_error_dev(sc->sc_dev,
		    "pcfrtc_clock_read: failed to acquire I2C bus\n");
		return err;
	}

	/* Read each timekeeping register in order. */
	for (i = 0; i < 10; i++) {
		cmdbuf[0] = pcf8583_rtc_offset[i];

		if ((err = iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
			     sc->sc_address, cmdbuf, 1,
			     &bcd[i], 1, I2C_F_POLL))) {
			iic_release_bus(sc->sc_tag, I2C_F_POLL);
			aprint_error_dev(sc->sc_dev,
			    "pcfrtc_clock_read: failed to read rtc "
			    "at 0x%x\n",
			    pcf8583_rtc_offset[i]);
			return err;
		}
	}

	/* Done with I2C */
	iic_release_bus(sc->sc_tag, I2C_F_POLL);

	/*
	 * Convert the PCF8583's register values into something useable
	 */
	*centi      = FROMBCD(bcd[PCF8583_REG_CENTI]);
	dt->dt_sec  = FROMBCD(bcd[PCF8583_REG_SEC]);
	dt->dt_min  = FROMBCD(bcd[PCF8583_REG_MIN]);
	dt->dt_hour = FROMBCD(bcd[PCF8583_REG_HOUR] & PCF8583_HOUR_MASK);
	if (bcd[PCF8583_REG_HOUR] & PCF8583_HOUR_12H) {
		dt->dt_hour %= 12;	/* 12AM -> 0, 12PM -> 12 */
		if (bcd[PCF8583_REG_HOUR] & PCF8583_HOUR_PM)
			dt->dt_hour += 12;
	}

	dt->dt_day = FROMBCD(bcd[PCF8583_REG_YEARDATE] & PCF8583_DATE_MASK);
	dt->dt_mon = FROMBCD(bcd[PCF8583_REG_WKDYMON] & PCF8583_MON_MASK);

	dt->dt_year = bcd[8] + (bcd[9] * 100);
	/* Try to notice if the year's rolled over. */
	if (bcd[PCF8583_REG_CSR] & PCF8583_CSR_MASK)
		aprint_error_dev(sc->sc_dev,
		    "cannot check year in mask mode\n");
	else {
		while (dt->dt_year % 4 !=
		       (bcd[PCF8583_REG_YEARDATE] &
			PCF8583_YEAR_MASK) >> PCF8583_YEAR_SHIFT)
			dt->dt_year++;
	}

	return 0;
}
Esempio n. 26
0
void
admtemp_attach(struct device *parent, struct device *self, void *aux)
{
	struct admtemp_softc *sc = (struct admtemp_softc *)self;
	struct i2c_attach_args *ia = aux;
	u_int8_t cmd, data, stat;
	int xeon = 0, i;

	sc->sc_tag = ia->ia_tag;
	sc->sc_addr = ia->ia_addr;

	if (strcmp(ia->ia_name, "xeontemp") == 0) {
		printf(": Xeon");
		xeon = 1;
	} else
		printf(": %s", ia->ia_name);

	iic_acquire_bus(sc->sc_tag, 0);
	cmd = ADM1021_CONFIG_READ;
	if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
	    sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) {
		iic_release_bus(sc->sc_tag, 0);
		printf(", cannot get control register\n");
		return;
	}
	if (data & ADM1021_CONFIG_RUN) {
		cmd = ADM1021_STATUS;
		if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
		    sc->sc_addr, &cmd, sizeof cmd, &stat, sizeof stat, 0)) {
			iic_release_bus(sc->sc_tag, 0);
			printf(", cannot read status register\n");
			return;
		}
		if ((stat & ADM1021_STATUS_INVAL) == ADM1021_STATUS_INVAL) {
			if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
			    sc->sc_addr, &cmd, sizeof cmd, &stat, sizeof stat, 0)) {
				iic_release_bus(sc->sc_tag, 0);
				printf(", cannot read status register\n");
				return;
			}
		}

		/* means external is dead */
		if ((stat & ADM1021_STATUS_INVAL) != ADM1021_STATUS_INVAL &&
		    (stat & ADM1021_STATUS_NOEXT))
			sc->sc_noexternal = 1;

		data &= ~ADM1021_CONFIG_RUN;
		cmd = ADM1021_CONFIG_WRITE;
		if (iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP,
		    sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) {
			iic_release_bus(sc->sc_tag, 0);
			printf(", cannot set control register\n");
			return;
		}
	}
	iic_release_bus(sc->sc_tag, 0);

	/* Initialize sensor data. */
	strlcpy(sc->sc_sensordev.xname, sc->sc_dev.dv_xname,
	    sizeof(sc->sc_sensordev.xname));

	sc->sc_sensor[ADMTEMP_EXT].type = SENSOR_TEMP;
	strlcpy(sc->sc_sensor[ADMTEMP_EXT].desc,
	    xeon ? "Xeon" : "External",
	    sizeof(sc->sc_sensor[ADMTEMP_EXT].desc));

	sc->sc_sensor[ADMTEMP_INT].type = SENSOR_TEMP;
	strlcpy(sc->sc_sensor[ADMTEMP_INT].desc,
	    xeon ? "Xeon" : "Internal",
	    sizeof(sc->sc_sensor[ADMTEMP_INT].desc));

	if (sensor_task_register(sc, admtemp_refresh, 5) == NULL) {
		printf(", unable to register update task\n");
		return;
	}

	for (i = 0; i < (sc->sc_noexternal ? 1 : ADMTEMP_NUM_SENSORS); i++)
		sensor_attach(&sc->sc_sensordev, &sc->sc_sensor[i]);
	sensordev_install(&sc->sc_sensordev);

	printf("\n");
}
Esempio n. 27
0
void
pcfadc_attach(struct device *parent, struct device *self, void *aux)
{
	struct pcfadc_softc *sc = (struct pcfadc_softc *)self;
	u_char chanuse[PCF8591_CHANNELS * 4], desc[PCF8591_CHANNELS * 32];
	u_char *cp;
	u_int8_t junk[PCF8591_CHANNELS + 1];
	u_int32_t transinfo[PCF8591_CHANNELS * 4];
	struct i2c_attach_args *ia = aux;
	int dlen, clen, tlen, node = *(int *)ia->ia_cookie;
	u_int i;

	if ((dlen = OF_getprop(node, "channels-description", desc,
	    sizeof(desc))) < 0) {
		printf(": couldn't find \"channels-description\" property\n");
		return;
	}
	if (dlen > sizeof(desc) || desc[dlen - 1] != '\0') {
		printf(": bad \"channels-description\" property\n");
		return;
	}
	if ((clen = OF_getprop(node, "channels-in-use", chanuse,
	    sizeof(chanuse))) < 0) {
		printf(": couldn't find \"channels-in-use\" property\n");
		return;
	}
	if ((clen % 4) != 0) {
		printf(": invalid \"channels-in-use\" length %d\n", clen);
		return;
	}
	sc->sc_nchan = clen / 4;
	if (sc->sc_nchan > PCF8591_CHANNELS) {
		printf(": invalid number of channels (%d)\n", sc->sc_nchan);
		return;
	}

	if ((tlen = OF_getprop(node, "tables", sc->sc_xlate,
	    sizeof(sc->sc_xlate))) < 0) {
		printf(": couldn't find \"tables\" property\n");
		return;
	}
	/* We only support complete, single width tables */
	if (tlen != 256) {
		printf(": invalid \"tables\" length %d\n", tlen);
		return;
	}

	if ((tlen = OF_getprop(node, "translation", transinfo,
	    sizeof(transinfo))) < 0) {
		printf(": couldn't find \"translation\" property\n");
		return;
	}
	if (tlen != (sc->sc_nchan * 4 * 4)) {
		printf(": invalid \"translation\" length %d\n", tlen);
		return;
	}

	cp = desc;
	for (i = 0; i < sc->sc_nchan; i++) {
		struct pcfadc_channel *chp = &sc->sc_channels[i];

		chp->chan_sensor.type = SENSOR_TEMP;

		if (cp >= desc + dlen) {
			printf(": invalid \"channels-description\"\n");
			return;
		}
		strlcpy(chp->chan_sensor.desc, cp,
		    sizeof(chp->chan_sensor.desc));
		cp += strlen(cp) + 1;

		/*
		 * We only support input temperature channels, with
		 * valid channel numbers, and basic (unscaled) translation
		 * 
		 * XXX TODO: support voltage (type 2) channels and type 4
		 * (scaled) translation tables
		 */
		if (chanuse[(i * 4)] > PCF8591_CHANNELS || /* channel # */
		    chanuse[(i * 4) + 1] != 0 ||	/* dir == input */
		    chanuse[(i * 4) + 2] != 1 ||	/* type == temp */
		    transinfo[(i * 4)] != 3 ||		/* xlate == table */
		    transinfo[(i * 4) + 2] != 0 ||	/* no xlate offset */
		    transinfo[(i * 4) + 3] != 0x100) {	/* xlate tbl length */
			printf(": unsupported sensor %d\n", i);
			return;
		}
		chp->chan_num = chanuse[(i * 4)];
	}

	sc->sc_tag = ia->ia_tag;
	sc->sc_addr = ia->ia_addr;

	iic_acquire_bus(sc->sc_tag, 0);

	/* Try a read now, so we can fail if it doesn't work */
	if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_addr,
	    NULL, 0, junk, sc->sc_nchan + 1, 0)) {
		printf(": read failed\n");
		iic_release_bus(sc->sc_tag, 0);
		return;
	}

	iic_release_bus(sc->sc_tag, 0);

	/* Initialize sensor data. */
	strlcpy(sc->sc_sensordev.xname, sc->sc_dev.dv_xname,
	    sizeof(sc->sc_sensordev.xname));

	for (i = 0; i < sc->sc_nchan; i++)
		if (!(sc->sc_channels[i].chan_sensor.flags & SENSOR_FINVALID))
			sensor_attach(&sc->sc_sensordev, 
			    &sc->sc_channels[i].chan_sensor);

	if (sensor_task_register(sc, pcfadc_refresh, 5)) {
		printf(": unable to register update task\n");
		return;
	}

	sensordev_install(&sc->sc_sensordev);

	printf("\n");
}
Esempio n. 28
0
static int
maxrtc_clock_write(struct maxrtc_softc *sc, struct clock_ymdhms *dt)
{
	uint8_t bcd[MAX6900_BURST_LEN], cmdbuf[2];
	uint8_t init_seconds, final_seconds;
	int i;

	/*
	 * Convert our time representation into something the MAX6900
	 * can understand.
	 */
	bcd[MAX6900_BURST_SECOND] = TOBCD(dt->dt_sec);
	bcd[MAX6900_BURST_MINUTE] = TOBCD(dt->dt_min);
	bcd[MAX6900_BURST_HOUR] = TOBCD(dt->dt_hour) & MAX6900_HOUR_24MASK;
	bcd[MAX6900_BURST_DATE] = TOBCD(dt->dt_day);
	bcd[MAX6900_BURST_WDAY] = TOBCD(dt->dt_wday);
	bcd[MAX6900_BURST_MONTH] = TOBCD(dt->dt_mon);
	bcd[MAX6900_BURST_YEAR] = TOBCD(dt->dt_year % 100);
		/* century in control slot */
	bcd[MAX6900_BURST_CONTROL] = TOBCD(dt->dt_year / 100);

	if (iic_acquire_bus(sc->sc_tag, I2C_F_POLL)) {
		aprint_error_dev(sc->sc_dev,
		    "maxrtc_clock_write: failed to acquire I2C bus\n");
		return (0);
	}

	/* Start by clearing the control register's write-protect bit. */
	cmdbuf[0] = MAX6900_REG_CONTROL | MAX6900_CMD_WRITE;
	cmdbuf[1] = 0;

	if (iic_exec(sc->sc_tag, I2C_OP_WRITE, sc->sc_address,
		     cmdbuf, 1, &cmdbuf[1], 1, I2C_F_POLL)) {
		iic_release_bus(sc->sc_tag, I2C_F_POLL);
		aprint_error_dev(sc->sc_dev,
		    "maxrtc_clock_write: failed to clear WP bit\n");
		return (0);
	}

	/*
	 * The MAX6900 RTC manual recommends ensuring "atomicity" of
	 * a non-burst write by:
	 *
	 *	- writing SECONDS
	 *	- reading back SECONDS, remembering it as "initial seconds"
	 *	- write the remaing RTC registers
	 *	- read back SECONDS as "final seconds"
	 *	- if "initial seconds" == 59, ensure "final seconds" == 59
	 *	- else, ensure "final seconds" is no more than one second
	 *	  beyond "initial seconds".
	 */
 again:
	cmdbuf[0] = MAX6900_REG_SECOND | MAX6900_CMD_WRITE;
	if (iic_exec(sc->sc_tag, I2C_OP_WRITE, sc->sc_address,
		     cmdbuf, 1, &bcd[MAX6900_BURST_SECOND], 1, I2C_F_POLL)) {
		iic_release_bus(sc->sc_tag, I2C_F_POLL);
		aprint_error_dev(sc->sc_dev,
		    "maxrtc_clock_write: failed to write SECONDS\n");
		return (0);
	}

	cmdbuf[0] = MAX6900_REG_SECOND | MAX6900_CMD_READ;
	if (iic_exec(sc->sc_tag, I2C_OP_READ, sc->sc_address,
		     cmdbuf, 1, &init_seconds, 1, I2C_F_POLL)) {
		iic_release_bus(sc->sc_tag, I2C_F_POLL);
		aprint_error_dev(sc->sc_dev,
		    "maxrtc_clock_write: failed to read "
		    "INITIAL SECONDS\n");
		return (0);
	}

	for (i = 1; i < MAX6900_BURST_LEN; i++) {
		cmdbuf[0] = max6900_rtc_offset[i] | MAX6900_CMD_WRITE;
		if (iic_exec(sc->sc_tag,
			     i != MAX6900_BURST_LEN - 1 ? I2C_OP_WRITE :
			     I2C_OP_WRITE_WITH_STOP, sc->sc_address,
			     cmdbuf, 1, &bcd[i], 1, I2C_F_POLL)) {
			iic_release_bus(sc->sc_tag, I2C_F_POLL);
			aprint_error_dev(sc->sc_dev,
			    "maxrtc_clock_write: failed to write rtc "
			    " at 0x%x\n",
			    max6900_rtc_offset[i]);
			return (0);
		}
	}

	cmdbuf[0] = MAX6900_REG_SECOND | MAX6900_CMD_READ;
	if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_address,
		     cmdbuf, 1, &final_seconds, 1, I2C_F_POLL)) {
		iic_release_bus(sc->sc_tag, I2C_F_POLL);
		aprint_error_dev(sc->sc_dev,
		    "maxrtc_clock_write: failed to read "
		    "FINAL SECONDS\n");
		return (0);
	}

	if ((init_seconds == 59 && final_seconds != 59) ||
	    (init_seconds != 59 && final_seconds != init_seconds + 1)) {
#if 1
		printf("%s: maxrtc_clock_write: init %d, final %d, try again\n",
		    device_xname(sc->sc_dev), init_seconds, final_seconds);
#endif
		goto again;
	}

	/* Finish by setting the control register's write-protect bit. */
	cmdbuf[0] = MAX6900_REG_CONTROL | MAX6900_CMD_WRITE;
	cmdbuf[1] = MAX6900_CONTROL_WP;

	if (iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP, sc->sc_address,
		     cmdbuf, 1, &cmdbuf[1], 1, I2C_F_POLL)) {
		iic_release_bus(sc->sc_tag, I2C_F_POLL);
		aprint_error_dev(sc->sc_dev,
		    "maxrtc_clock_write: failed to set WP bit\n");
		return (0);
	}

	iic_release_bus(sc->sc_tag, I2C_F_POLL);

	return (1);
}
Esempio n. 29
0
/*ARGSUSED*/
int
maxrtc_write(dev_t dev, struct uio *uio, int flags)
{
	struct maxrtc_softc *sc;
	u_int8_t cmdbuf[2];
	int a, error, sverror;

	if ((sc = device_lookup_private(&maxrtc_cd, minor(dev))) == NULL)
		return (ENXIO);

	if (uio->uio_offset >= MAX6900_RAM_BYTES)
		return (EINVAL);

	if ((error = iic_acquire_bus(sc->sc_tag, 0)) != 0)
		return (error);

	/* Start by clearing the control register's write-protect bit. */
	cmdbuf[0] = MAX6900_REG_CONTROL | MAX6900_CMD_WRITE;
	cmdbuf[1] = 0;

	if ((error = iic_exec(sc->sc_tag, I2C_OP_WRITE, sc->sc_address,
			      cmdbuf, 1, &cmdbuf[1], 1, 0)) != 0) {
		iic_release_bus(sc->sc_tag, 0);
		aprint_error_dev(sc->sc_dev,
		    "maxrtc_write: failed to clear WP bit\n");
		return (error);
	}

	while (uio->uio_resid && uio->uio_offset < MAX6900_RAM_BYTES) {
		a = (int)uio->uio_offset;

		cmdbuf[0] = MAX6900_REG_RAM(a) | MAX6900_CMD_WRITE;
		if ((error = uiomove(&cmdbuf[1], 1, uio)) != 0)
			break;

		if ((error = iic_exec(sc->sc_tag, I2C_OP_WRITE, sc->sc_address,
				      cmdbuf, 1, &cmdbuf[1], 1, 0)) != 0) {
			aprint_error_dev(sc->sc_dev,
			    "maxrtc_write: write failed at 0x%x\n", a);
			break;
		}
	}

	/* Set the write-protect bit again. */
	cmdbuf[0] = MAX6900_REG_CONTROL | MAX6900_CMD_WRITE;
	cmdbuf[1] = MAX6900_CONTROL_WP;

	sverror = error;
	if ((error = iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP,
			      sc->sc_address, cmdbuf, 1,
			      &cmdbuf[1], 1, 0)) != 0) {
		if (sverror != 0)
			error = sverror;
		aprint_error_dev(sc->sc_dev,
		    "maxrtc_write: failed to set WP bit\n");
	}

	iic_release_bus(sc->sc_tag, 0);

	return (error);
}
Esempio n. 30
0
void
lmtemp_attach(struct device *parent, struct device *self, void *aux)
{
	struct lmtemp_softc *sc = (struct lmtemp_softc *)self;
	struct i2c_attach_args *ia = aux;
	u_int8_t cmd, data;

	sc->sc_tag = ia->ia_tag;
	sc->sc_addr = ia->ia_addr;

	printf(": %s", ia->ia_name);

	/* If in SHUTDOWN mode, wake it up */
	iic_acquire_bus(sc->sc_tag, 0);
	cmd = LM75_REG_CONFIG;
	if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
	    sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) {
		iic_release_bus(sc->sc_tag, 0);
		printf(", fails to respond\n");
		return;
	}
	if (data & LM75_CONFIG_SHUTDOWN) {
		data &= ~LM75_CONFIG_SHUTDOWN;
		if (iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP,
		    sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) {
			printf(", cannot wake up\n");
			iic_release_bus(sc->sc_tag, 0);
			return;
		}
		printf(", woken up");
	}
	iic_release_bus(sc->sc_tag, 0);

	sc->sc_model = LM_MODEL_LM75;
	sc->sc_bits = 9;
	sc->sc_ratio = 500000;		/* 0.5 degC for LSB */
	if (strcmp(ia->ia_name, "lm77") == 0) {
		sc->sc_model = LM_MODEL_LM77;
		sc->sc_bits = 13;
	} else if (strcmp(ia->ia_name, "lm76") == 0) {
		sc->sc_model = LM_MODEL_LM76;
		sc->sc_bits = 13;
		sc->sc_ratio = 62500;	/* 0.0625 degC for LSB */
	} else if (strcmp(ia->ia_name, "ds1775") == 0) {
		sc->sc_model = LM_MODEL_DS1775;
		//sc->sc_bits = DS1755_CONFIG_RESOLUTION(data);
	} else if (strcmp(ia->ia_name, "lm75a") == 0) {
		/* For simplicity's sake, treat the LM75A as an LM75 */
		sc->sc_model = LM_MODEL_LM75A;
	}

	printf("\n");

	/* Initialize sensor data */
	strlcpy(sc->sc_sensordev.xname, sc->sc_dev.dv_xname,
	    sizeof(sc->sc_sensordev.xname));
	sc->sc_sensor.type = SENSOR_TEMP;

	/* Hook into the hw.sensors sysctl */
	sensor_attach(&sc->sc_sensordev, &sc->sc_sensor);
	sensordev_install(&sc->sc_sensordev);

	sensor_task_register(sc, lmtemp_refresh_sensor_data, LM_POLLTIME);
}