Пример #1
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 */
}
Пример #2
0
static int
ds1307_write(device_t dev, uint16_t addr, uint8_t *data, size_t len)
{
	struct iic_msg msg[1] = {
	    { addr, IIC_M_WR, len, data },
	};

	return (iicbus_transfer(dev, msg, nitems(msg)));
}
Пример #3
0
static int
iicrdwr(struct iic_cdevpriv *priv, struct iic_rdwr_data *d, int flags)
{
	struct iic_msg *buf, *m;
	void **usrbufs;
	device_t iicdev, parent;
	int error, i;

	iicdev = priv->sc->sc_dev;
	parent = device_get_parent(iicdev);
	error = 0;

	buf = malloc(sizeof(*d->msgs) * d->nmsgs, M_IIC, M_WAITOK);

	error = copyin(d->msgs, buf, sizeof(*d->msgs) * d->nmsgs);

	/* Alloc kernel buffers for userland data, copyin write data */
	usrbufs = malloc(sizeof(void *) * d->nmsgs, M_IIC, M_WAITOK | M_ZERO);

	for (i = 0; i < d->nmsgs; i++) {
		m = &(buf[i]);
		usrbufs[i] = m->buf;

		/*
		 * At least init the buffer to NULL so we can safely free() it later.
		 * If the copyin() to buf failed, don't try to malloc bogus m->len.
		 */
		m->buf = NULL;
		if (error != 0)
			continue;
		m->buf = malloc(m->len, M_IIC, M_WAITOK);
		if (!(m->flags & IIC_M_RD))
			error = copyin(usrbufs[i], m->buf, m->len);
	}

	if (error == 0)
		error = iicbus_request_bus(parent, iicdev,
		    (flags & O_NONBLOCK) ? IIC_DONTWAIT : (IIC_WAIT | IIC_INTR));

	if (error == 0) {
		error = iicbus_transfer(iicdev, buf, d->nmsgs);
		iicbus_release_bus(parent, iicdev);
	}

	/* Copyout all read segments, free up kernel buffers */
	for (i = 0; i < d->nmsgs; i++) {
		m = &(buf[i]);
		if ((error == 0) && (m->flags & IIC_M_RD))
			error = copyout(m->buf, usrbufs[i], m->len);
		free(m->buf, M_IIC);
	}

	free(usrbufs, M_IIC);
	free(buf, M_IIC);
	return (error);
}
Пример #4
0
static int
ds1307_read(device_t dev, uint16_t addr, uint8_t reg, uint8_t *data, size_t len)
{
	struct iic_msg msg[2] = {
	    { addr, IIC_M_WR | IIC_M_NOSTOP, 1, &reg },
	    { addr, IIC_M_RD, len, data },
	};

	return (iicbus_transfer(dev, msg, nitems(msg)));
}
Пример #5
0
static int
am335x_pmic_read(device_t dev, uint8_t addr, uint8_t *data, uint8_t size)
{
	struct am335x_pmic_softc *sc = device_get_softc(dev);
	struct iic_msg msg[] = {
		{ sc->sc_addr, IIC_M_WR, 1, &addr },
		{ sc->sc_addr, IIC_M_RD, size, data },
	};
	return (iicbus_transfer(dev, msg, 2));
}
Пример #6
0
static void
at24co2n_read_mac(struct at24co2n_softc *sc)
{
	uint8_t addr = AT24CO_EEPROM_ETH_MACADDR;
	struct iic_msg msgs[2] = {
	     { sc->sc_addr, IIC_M_WR, 1, &addr },
	     { sc->sc_addr, IIC_M_RD, 6, sc->sc_mac_addr},
	};

	iicbus_transfer(sc->sc_dev, msgs, 2);
}
Пример #7
0
static int
max6657_read(device_t dev, uint32_t slave_addr, int reg) 
{
	uint8_t addr = reg;
	uint8_t data[1];
	struct iic_msg msgs[2] = {
	     { slave_addr, IIC_M_WR, 1, &addr },
	     { slave_addr, IIC_M_RD, 1, data },
	};

	return iicbus_transfer(dev, msgs, 2) != 0 ? -1 : data[0];
}
static void
fled_cb(void *arg, int onoff)
{
    uint8_t data[1];
    struct iic_msg msgs[1] = {
        { LED_ADDR, IIC_M_WR, 1, data },
    };
    device_t dev = arg;

    data[0] = (onoff == 0);		/* NB: low true */
    (void) iicbus_transfer(dev, msgs, 1);
}
Пример #9
0
/**
 *	twl_test_present - checks if a device with given address is present
 *	@sc: device soft context
 *	@addr: the address of the device to scan for
 *
 *	Sends just the address byte and checks for an ACK. If no ACK then device
 *	is assumed to not be present.
 *
 *	RETURNS:
 *	EIO if device is not present, otherwise 0 is returned.
 */
static int
twl_test_present(struct twl_softc *sc, uint8_t addr)
{
	struct iic_msg msg;
	uint8_t tmp;

	/* Set the address to read from */
	msg.slave = addr;
	msg.flags = IIC_M_RD;
	msg.len = 1;
	msg.buf = &tmp;

	if (iicbus_transfer(sc->sc_dev, &msg, 1) != 0)
		return (EIO);

	return (0);
}
Пример #10
0
static int
am335x_pmic_write(device_t dev, uint8_t address, uint8_t *data, uint8_t size)
{
	uint8_t buffer[MAX_IIC_DATA_SIZE + 1];
	struct am335x_pmic_softc *sc = device_get_softc(dev);
	struct iic_msg msg[] = {
		{ sc->sc_addr, IIC_M_WR, size + 1, buffer },
	};

	if (size > MAX_IIC_DATA_SIZE)
		return (ENOMEM);

	buffer[0] = address;
	memcpy(buffer + 1, data, size);

	return (iicbus_transfer(dev, msg, 1));
}
Пример #11
0
/**
 *	twl_write - writes one or more registers to the TWL device
 *	@sc: device soft context
 *	@nsub: the sub-module to read from
 *	@reg: the register offset within the module to read
 *	@buf: data to write
 *	@cnt: the number of bytes to write
 *
 *	Writes one or more registers.
 *
 *	LOCKING:
 *	Expects the TWL lock to be held.
 *
 *	RETURNS:
 *	Zero on success or a negative error code on failure.
 */
int
twl_write(device_t dev, uint8_t nsub, uint8_t reg, uint8_t *buf, uint16_t cnt)
{
	struct twl_softc *sc;
	struct iic_msg msg;
	uint8_t addr;
	uint8_t tmp_buf[TWL_MAX_IIC_DATA_SIZE + 1];
	int rc;

	if (cnt > TWL_MAX_IIC_DATA_SIZE)
		return (ENOMEM);

	/* Set the register address as the first byte */
	tmp_buf[0] = reg;
	memcpy(&tmp_buf[1], buf, cnt);

	sc = device_get_softc(dev);

	TWL_LOCK(sc);

	addr = sc->sc_subaddr_map[nsub];
	if (addr == TWL_INVALID_CHIP_ID) {
		TWL_UNLOCK(sc);
		return (EIO);
	}

	/* Setup the transfer and execute it */
	msg.slave = addr;
	msg.flags = IIC_M_WR;
	msg.len = cnt + 1;
	msg.buf = tmp_buf;
	TWL_UNLOCK(sc);

	rc = iicbus_transfer(dev, &msg, 1);


	if (rc != 0) {
		device_printf(sc->sc_dev, "iicbus write failed (adr:0x%02x, reg:0x%02x)\n",
		              addr, reg);
		return (EIO);
	}

	return (0);
}
Пример #12
0
static int
onyx_write(struct onyx_softc *sc, uint8_t reg, const uint8_t value)
{
	u_int size;
	uint8_t buf[16];

	struct iic_msg msg[] = {
		{ sc->sc_addr, IIC_M_WR, 0, buf }
	};

	size = 1;
	msg[0].len = size + 1;
	buf[0] = reg;
	buf[1] = value;

	iicbus_transfer(sc->sc_dev, msg, 1);

	return (0);
}
Пример #13
0
static int
tumbler_write(struct tumbler_softc *sc, uint8_t reg, const void *data)
{
    u_int size;
    uint8_t buf[16];

    struct iic_msg msg[] = {
        { sc->sc_addr, IIC_M_WR, 0, buf }
    };

    KASSERT(reg < sizeof(tumbler_regsize), ("bad reg"));
    size = tumbler_regsize[reg];
    msg[0].len = size + 1;
    buf[0] = reg;
    memcpy(&buf[1], data, size);

    iicbus_transfer(sc->sc_dev, msg, 1);

    return (0);
}
Пример #14
0
/**
 *	twl_read - read one or more registers from the TWL device
 *	@sc: device soft context
 *	@nsub: the sub-module to read from
 *	@reg: the register offset within the module to read
 *	@buf: buffer to store the bytes in
 *	@cnt: the number of bytes to read
 *
 *	Reads one or registers and stores the result in the suppled buffer.
 *
 *	LOCKING:
 *	Expects the TWL lock to be held.
 *
 *	RETURNS:
 *	Zero on success or a negative error code on failure.
 */
int
twl_read(device_t dev, uint8_t nsub, uint8_t reg, uint8_t *buf, uint16_t cnt)
{
	struct twl_softc *sc;
	struct iic_msg msg[2];
	uint8_t addr;
	int rc;

	sc = device_get_softc(dev);

	TWL_LOCK(sc);

	addr = sc->sc_subaddr_map[nsub];
	if (addr == TWL_INVALID_CHIP_ID) {
		TWL_UNLOCK(sc);
		return (EIO);
	}

	/* Set the address to read from */
	msg[0].slave = addr;
	msg[0].flags = IIC_M_WR | IIC_M_NOSTOP;
	msg[0].len = 1;
	msg[0].buf = &reg;
	/* Read the data back */
	msg[1].slave = addr;
	msg[1].flags = IIC_M_RD;
	msg[1].len = cnt;
	msg[1].buf = buf;
	TWL_UNLOCK(sc);

	rc = iicbus_transfer(dev, msg, 2);


	if (rc != 0) {
		device_printf(dev, "iicbus read failed (adr:0x%02x, reg:0x%02x)\n",
		              addr, reg);
		return (EIO);
	}

	return (0);
}
Пример #15
0
static int
pcf8563_gettime(device_t dev, struct timespec *ts)
{
	struct clocktime ct;
	uint8_t reg = PCF8563_R_SECOND, val[PCF8563_NCLOCKREGS];
	struct iic_msg msgs[] = {
		{ 0, IIC_M_WR, sizeof(reg), &reg },
		{ 0, IIC_M_RD, PCF8563_NCLOCKREGS, &val[PCF8563_R_SECOND] }
	};
	struct pcf8563_softc *sc;
	int error;

	sc = device_get_softc(dev);
	msgs[0].slave = msgs[1].slave = sc->sc_addr;
	error = iicbus_transfer(dev, msgs, nitems(msgs));
	if (error != 0) {
		device_printf(dev, "%s: cannot read RTC\n", __func__);
		return (error);
	}

	ct.nsec = 0;
	ct.sec = FROMBCD(val[PCF8563_R_SECOND] & PCF8563_M_SECOND);
	ct.min = FROMBCD(val[PCF8563_R_MINUTE] & PCF8563_M_MINUTE);
	ct.hour = FROMBCD(val[PCF8563_R_HOUR] & PCF8563_M_HOUR);
	ct.day = FROMBCD(val[PCF8563_R_DAY] & PCF8563_M_DAY);
	ct.dow = val[PCF8563_R_WEEKDAY] & PCF8563_M_WEEKDAY;
	ct.mon = FROMBCD(val[PCF8563_R_MONTH] & PCF8563_M_MONTH);
	ct.year = FROMBCD(val[PCF8563_R_YEAR] & PCF8563_M_YEAR);
	ct.year += sc->sc_year0;
	if (ct.year < POSIX_BASE_YEAR)
		ct.year += 100;	/* assume [1970, 2069] */
	if ((val[PCF8563_R_MONTH] & PCF8563_R_MONTH_C) != 0) {
		if (ct.year >= 100 + sc->sc_year0)
			sc->sc_flags |= PCF8563_CPOL;
	} else if (ct.year < 100 + sc->sc_year0)
			sc->sc_flags |= PCF8563_CPOL;

	return (clock_ct_to_ts(&ct, ts));
}
Пример #16
0
static int
pcf8563_settime(device_t dev, struct timespec *ts)
{
	struct clocktime ct;
	uint8_t val[PCF8563_NCLOCKREGS];
	struct iic_msg msgs[] = {
		{ 0, IIC_M_WR, PCF8563_NCLOCKREGS - 1, &val[PCF8563_R_CS2] }
	};
	struct pcf8563_softc *sc;
	int error;

	sc = device_get_softc(dev);
	val[PCF8563_R_CS2] = PCF8563_R_SECOND;	/* abuse */
	/* Accuracy is only one second. */
	if (ts->tv_nsec >= 500000000)
		ts->tv_sec++;
	ts->tv_nsec = 0;
	clock_ts_to_ct(ts, &ct);
	val[PCF8563_R_SECOND] = TOBCD(ct.sec);
	val[PCF8563_R_MINUTE] = TOBCD(ct.min);
	val[PCF8563_R_HOUR] = TOBCD(ct.hour);
	val[PCF8563_R_DAY] = TOBCD(ct.day);
	val[PCF8563_R_WEEKDAY] = ct.dow;
	val[PCF8563_R_MONTH] = TOBCD(ct.mon);
	val[PCF8563_R_YEAR] = TOBCD(ct.year % 100);
	if ((sc->sc_flags & PCF8563_CPOL) != 0) {
		if (ct.year >= 100 + sc->sc_year0)
			val[PCF8563_R_MONTH] |= PCF8563_R_MONTH_C;
	} else if (ct.year < 100 + sc->sc_year0)
			val[PCF8563_R_MONTH] |= PCF8563_R_MONTH_C;

	msgs[0].slave = sc->sc_addr;
	error = iicbus_transfer(dev, msgs, nitems(msgs));
	if (error != 0)
		device_printf(dev, "%s: cannot write RTC\n", __func__);

	return (error);
}
Пример #17
0
				.flags	= IIC_M_WR,
				.len	= 1,
				.buf	= &start,
			}, {
				.slave	= DDC_ADDR << 1,
				.flags	= IIC_M_RD,
				.len	= len,
				.buf	= buf,
			}
		};

	/*
	 * Avoid sending the segment addr to not upset non-compliant ddc
	 * monitors.
	 */
		ret = iicbus_transfer(adapter, &msgs[3 - xfers], xfers);

		if (ret != 0)
			DRM_DEBUG_KMS("iicbus_transfer countdown %d error %d\n",
			    retries, ret);
	} while (ret != 0 && --retries);

	return (ret == 0 ? 0 : -1);
}

static bool drm_edid_is_zero(u8 *in_edid, int length)
{
	int i;
	u32 *raw_edid = (u32 *)in_edid;

	for (i = 0; i < length / 4; i++)