Exemple #1
0
/**
 *	twl_scan - scans the i2c bus for sub modules
 *	@dev: the twl device
 *
 *	TWL devices don't just have one i2c slave address, rather they have up to
 *	5 other addresses, each is for separate modules within the device. This
 *	function scans the bus for 4 possible sub-devices and stores the info
 *	internally.
 *
 */
static void
twl_scan(void *dev)
{
	struct twl_softc *sc;
	unsigned i;
	uint8_t devs[TWL_MAX_SUBADDRS];
	uint8_t base = TWL_CHIP_ID0;

	sc = device_get_softc((device_t)dev);

	memset(devs, TWL_INVALID_CHIP_ID, TWL_MAX_SUBADDRS);

	/* Try each of the addresses (0x48, 0x49, 0x4a & 0x4b) to determine which
	 * sub modules we have.
	 */
	for (i = 0; i < TWL_MAX_SUBADDRS; i++) {
		if (twl_test_present(sc, (base + i)) == 0) {
			devs[i] = (base + i);
			device_printf(sc->sc_dev, "Found (sub)device at 0x%02x\n", (base + i));
		}
	}

	TWL_LOCK(sc);
	memcpy(sc->sc_subaddr_map, devs, TWL_MAX_SUBADDRS);
	TWL_UNLOCK(sc);

	/* Finished with the interrupt hook */
	config_intrhook_disestablish(&sc->sc_scan_hook);
}
Exemple #2
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);
}
Exemple #3
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);
}