Example #1
0
static void
kiic_intr(void *xsc)
{
	struct kiic_softc *sc = xsc;
	u_int isr;
	uint32_t x;

	mtx_lock(&sc->sc_mutex);
	isr = kiic_readreg(sc, ISR);

	if (isr & I2C_INT_ADDR) {
		sc->sc_flags |= I2C_SELECTED;

		if (sc->sc_flags & I2C_READING) {
			if (sc->sc_resid > 1) {
				x = kiic_readreg(sc, CONTROL);
				x |= I2C_CT_AAK;
				kiic_writereg(sc, CONTROL, x);
			}
		} else {
			kiic_writereg(sc, DATA, *sc->sc_data++);
			sc->sc_resid--;
		}
	}

	if (isr & I2C_INT_DATA) {
		if (sc->sc_flags & I2C_READING) {
			if (sc->sc_resid > 0) {
				*sc->sc_data++ = kiic_readreg(sc, DATA);
				sc->sc_resid--;
			}
			if (sc->sc_resid == 0)  /* done */
				kiic_writereg(sc, CONTROL, 0);
		} else {
			if (sc->sc_resid == 0) {
				x = kiic_readreg(sc, CONTROL);
				x |= I2C_CT_STOP;
				kiic_writereg(sc, CONTROL, x);
			} else {
				kiic_writereg(sc, DATA, *sc->sc_data++);
				sc->sc_resid--;
			}
		}
	}

	if (isr & I2C_INT_STOP) {
		kiic_writereg(sc, CONTROL, 0);
		sc->sc_flags &= ~I2C_SELECTED;
		wakeup(sc->sc_dev);
	}

	kiic_writereg(sc, ISR, isr);
	mtx_unlock(&sc->sc_mutex);
}
Example #2
0
int
kiic_start(struct kiic_softc *sc, int addr, int subaddr, void *data, int len)
{
	int rw = (sc->sc_flags & I2C_READING) ? 1 : 0;
	int timo, x;

	KASSERT((addr & 1) == 0);

	sc->sc_data = data;
	sc->sc_resid = len;
	sc->sc_flags |= I2C_BUSY;

	timo = 1000 + len * 200;

	/* XXX TAS3001 sometimes takes 50ms to finish writing registers. */
	/* if (addr == 0x68) */
		timo += 100000;

	kiic_writereg(sc, ADDR, addr | rw);
	kiic_writereg(sc, SUBADDR, subaddr);

	x = kiic_readreg(sc, CONTROL) | I2C_CT_ADDR;
	kiic_writereg(sc, CONTROL, x);

	if (kiic_poll(sc, timo))
		return (-1);
	if (sc->sc_flags & I2C_ERROR) {
		printf("I2C_ERROR\n");
		return (-1);
	}
	if (sc->sc_resid != 0)
		return (-1);
	return (0);
}
Example #3
0
static void
kiic_setspeed(struct kiic_softc *sc, u_int speed)
{
	u_int x;

	KASSERT((speed & ~I2C_SPEED) == 0, ("bad speed"));
	x = kiic_readreg(sc, MODE);
	x &= ~I2C_SPEED;
	x |= speed;
	kiic_writereg(sc, MODE, x);
}
Example #4
0
static void
kiic_setport(struct kiic_softc *sc, u_int port)
{
	u_int x;

	KASSERT(port == 1 || port == 0, ("bad port"));
	x = kiic_readreg(sc, MODE);
	x &= ~I2C_PORT;
	x |= (port << 4);
	kiic_writereg(sc, MODE, x);
}
Example #5
0
static void
kiic_setmode(struct kiic_softc *sc, u_int mode)
{
	u_int x;

	KASSERT((mode & ~I2C_MODE) == 0, ("bad mode"));
	x = kiic_readreg(sc, MODE);
	x &= ~I2C_MODE;
	x |= mode;
	kiic_writereg(sc, MODE, x);
}
Example #6
0
int
kiic_poll(struct kiic_softc *sc, int timo)
{
	while (sc->sc_flags & I2C_BUSY) {
		if (kiic_readreg(sc, ISR))
			kiic_intr(sc);
		timo -= 100;
		if (timo < 0) {
			printf("i2c_poll: timeout\n");
			return (-1);
		}
		delay(100);
	}
	return (0);
}
Example #7
0
void
kiic_setmode(struct kiic_softc *sc, u_int mode, u_int bus)
{
	u_int x;

	KASSERT((mode & ~I2C_MODE) == 0);
	x = kiic_readreg(sc, MODE);
	x &= ~(I2C_MODE);
	if (bus)
		x |= I2C_BUS1;
	else
		x &= ~I2C_BUS1;
	x |= mode;
	kiic_writereg(sc, MODE, x);
}
Example #8
0
static int
kiic_transfer(device_t dev, struct iic_msg *msgs, uint32_t nmsgs)
{
	struct kiic_softc *sc;
	int i, x, timo, err;
	uint16_t addr;
	uint8_t subaddr;

	sc = device_get_softc(dev);
	timo = 100;
	subaddr = 0;

	mtx_lock(&sc->sc_mutex);

	if (sc->sc_flags & I2C_BUSY)
		mtx_sleep(dev, &sc->sc_mutex, 0, "kiic", timo);

	if (sc->sc_flags & I2C_BUSY) {
		mtx_unlock(&sc->sc_mutex);
		return (ETIMEDOUT);
	}
		
	sc->sc_flags = I2C_BUSY;

	/* Clear pending interrupts, and reset controller */
	kiic_writereg(sc, ISR, kiic_readreg(sc, ISR));
	kiic_writereg(sc, STATUS, 0);

	for (i = 0; i < nmsgs; i++) {
		if (msgs[i].flags & IIC_M_NOSTOP) {
			if (msgs[i+1].flags & IIC_M_RD)
				kiic_setmode(sc, I2C_COMBMODE);
			else
				kiic_setmode(sc, I2C_STDSUBMODE);
			KASSERT(msgs[i].len == 1, ("oversize I2C message"));
			subaddr = msgs[i].buf[0];
			i++;
		} else {
			kiic_setmode(sc, I2C_STDMODE);
		}

		sc->sc_data = msgs[i].buf;
		sc->sc_resid = msgs[i].len;
		sc->sc_flags = I2C_BUSY;
		addr = msgs[i].slave;
		timo = 1000 + sc->sc_resid * 200;
		timo += 100000;

		if (msgs[i].flags & IIC_M_RD) {
			sc->sc_flags |= I2C_READING;
			addr |= 1;
		}

		addr |= sc->sc_i2c_base;

		kiic_setport(sc, (addr & 0x100) >> 8);
		kiic_writereg(sc, ADDR, addr & 0xff);
		kiic_writereg(sc, SUBADDR, subaddr);

		x = kiic_readreg(sc, CONTROL) | I2C_CT_ADDR;
		kiic_writereg(sc, CONTROL, x);

		err = mtx_sleep(dev, &sc->sc_mutex, 0, "kiic", timo);
		
		msgs[i].len -= sc->sc_resid;

		if ((sc->sc_flags & I2C_ERROR) || err == EWOULDBLOCK) {
			device_printf(sc->sc_dev, "I2C error\n");
			sc->sc_flags = 0;
			mtx_unlock(&sc->sc_mutex);
			return (EIO);
		}
	}

	sc->sc_flags = 0;

	mtx_unlock(&sc->sc_mutex);

	return (0);
}
Example #9
0
static int
kiic_attach(device_t self)
{
	struct kiic_softc *sc = device_get_softc(self);
	int rid, rate;
	phandle_t node;
	char name[64];

	bzero(sc, sizeof(*sc));
	sc->sc_dev = self;
	
	node = ofw_bus_get_node(self);
	if (node == 0 || node == -1) {
		return (EINVAL);
	}

	rid = 0;
	sc->sc_reg = bus_alloc_resource_any(self, SYS_RES_MEMORY,
			&rid, RF_ACTIVE);
	if (sc->sc_reg == NULL) {
		return (ENOMEM);
	}

	if (OF_getencprop(node, "AAPL,i2c-rate", &rate, 4) != 4) {
		device_printf(self, "cannot get i2c-rate\n");
		return (ENXIO);
	}
	if (OF_getencprop(node, "AAPL,address-step", &sc->sc_regstep, 4) != 4) {
		device_printf(self, "unable to find i2c address step\n");
		return (ENXIO);
	}

	/*
	 * Some Keywest I2C devices have their children attached directly
	 * underneath them.  Some have a single 'iicbus' child with the
	 * devices underneath that.  Sort this out, and make sure that the
	 * OFW I2C layer has the correct node.
	 *
	 * Note: the I2C children of the Uninorth bridges have two ports.
	 *  In general, the port is designated in the 9th bit of the I2C
	 *  address. However, for kiic devices with children attached below
	 *  an i2c-bus node, the port is indicated in the 'reg' property
	 *  of the i2c-bus node.
	 */

	sc->sc_node = node;

	node = OF_child(node);
	if (OF_getprop(node, "name", name, sizeof(name)) > 0) {
		if (strcmp(name,"i2c-bus") == 0) {
			phandle_t reg;
			if (OF_getprop(node, "reg", &reg, sizeof(reg)) > 0)
				sc->sc_i2c_base = reg << 8;

			sc->sc_node = node;
		}
	}

	mtx_init(&sc->sc_mutex, "kiic", NULL, MTX_DEF);

	sc->sc_irq = bus_alloc_resource_any(self, SYS_RES_IRQ, &sc->sc_irqrid, 
	    RF_ACTIVE);
	bus_setup_intr(self, sc->sc_irq, INTR_TYPE_MISC | INTR_MPSAFE, NULL,
	    kiic_intr, sc, &sc->sc_ih);

	kiic_writereg(sc, ISR, kiic_readreg(sc, ISR));
	kiic_writereg(sc, STATUS, 0);
	kiic_writereg(sc, IER, 0);

	kiic_setmode(sc, I2C_STDMODE);
	kiic_setspeed(sc, I2C_100kHz);		/* XXX rate */
	
	kiic_writereg(sc, IER, I2C_INT_DATA | I2C_INT_ADDR | I2C_INT_STOP);

	if (bootverbose)
		device_printf(self, "Revision: %02X\n", kiic_readreg(sc, REV));

	/* Add the IIC bus layer */
	sc->sc_iicbus = device_add_child(self, "iicbus", -1);

	return (bus_generic_attach(self));
}
Example #10
0
int
kiic_intr(struct kiic_softc *sc)
{
	u_int isr, x;

	isr = kiic_readreg(sc, ISR);
	if (isr & I2C_INT_ADDR) {
#if 0
		if ((kiic_readreg(sc, STATUS) & I2C_ST_LASTAAK) == 0) {
			/* No slave responded. */
			sc->sc_flags |= I2C_ERROR;
			goto out;
		}
#endif

		if (sc->sc_flags & I2C_READING) {
			if (sc->sc_resid > 1) {
				x = kiic_readreg(sc, CONTROL);
				x |= I2C_CT_AAK;
				kiic_writereg(sc, CONTROL, x);
			}
		} else {
			kiic_writereg(sc, DATA, *sc->sc_data++);
			sc->sc_resid--;
		}
	}

	if (isr & I2C_INT_DATA) {
		if (sc->sc_flags & I2C_READING) {
			*sc->sc_data++ = kiic_readreg(sc, DATA);
			sc->sc_resid--;

			if (sc->sc_resid == 0) {	/* Completed */
				kiic_writereg(sc, CONTROL, 0);
				goto out;
			}
		} else {
#if 0
			if ((kiic_readreg(sc, STATUS) & I2C_ST_LASTAAK) == 0) {
				/* No slave responded. */
				sc->sc_flags |= I2C_ERROR;
				goto out;
			}
#endif

			if (sc->sc_resid == 0) {
				x = kiic_readreg(sc, CONTROL) | I2C_CT_STOP;
				kiic_writereg(sc, CONTROL, x);
			} else {
				kiic_writereg(sc, DATA, *sc->sc_data++);
				sc->sc_resid--;
			}
		}
	}

out:
	if (isr & I2C_INT_STOP) {
		kiic_writereg(sc, CONTROL, 0);
		sc->sc_flags &= ~I2C_BUSY;
	}

	kiic_writereg(sc, ISR, isr);

	return (1);
}
Example #11
0
u_int
kiic_getspeed(struct kiic_softc *sc)
{
	return kiic_readreg(sc, MODE) & I2C_SPEED;
}
Example #12
0
u_int
kiic_getmode(struct kiic_softc *sc)
{
	return kiic_readreg(sc, MODE) & I2C_MODE;
}