Home | History | Annotate | Line # | Download | only in i2c
motoi2c.c revision 1.3
      1 /* $NetBSD: motoi2c.c,v 1.3 2011/01/12 18:06:26 phx Exp $ */
      2 
      3 /*-
      4  * Copyright (c) 2007, 2010 The NetBSD Foundation, Inc.
      5  * All rights reserved.
      6  *
      7  * This code is derived from software contributed to The NetBSD Foundation
      8  * by Matt Thomas.
      9  *
     10  * Redistribution and use in source and binary forms, with or without
     11  * modification, are permitted provided that the following conditions
     12  * are met:
     13  * 1. Redistributions of source code must retain the above copyright
     14  *    notice, this list of conditions and the following disclaimer.
     15  * 2. Redistributions in binary form must reproduce the above copyright
     16  *    notice, this list of conditions and the following disclaimer in the
     17  *    documentation and/or other materials provided with the distribution.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29  * POSSIBILITY OF SUCH DAMAGE.
     30  */
     31 
     32 #include <sys/cdefs.h>
     33 __KERNEL_RCSID(0, "$NetBSD: motoi2c.c,v 1.3 2011/01/12 18:06:26 phx Exp $");
     34 
     35 #include <sys/param.h>
     36 #include <sys/device.h>
     37 #include <sys/systm.h>
     38 #include <sys/mutex.h>
     39 #include <sys/bus.h>
     40 #include <sys/intr.h>
     41 
     42 #include <dev/i2c/i2cvar.h>
     43 #include <dev/i2c/motoi2creg.h>
     44 #include <dev/i2c/motoi2cvar.h>
     45 
     46 #ifdef DEBUG
     47 int motoi2c_debug = 0;
     48 #define	DPRINTF(x)	if (motoi2c_debug) printf x
     49 #else
     50 #define	DPRINTF(x)
     51 #endif
     52 
     53 static int  motoi2c_acquire_bus(void *, int);
     54 static void motoi2c_release_bus(void *, int);
     55 static int  motoi2c_exec(void *, i2c_op_t, i2c_addr_t, const void *, size_t,
     56 		void *, size_t, int);
     57 static int  motoi2c_busy_wait(struct motoi2c_softc *, uint8_t);
     58 
     59 static const struct i2c_controller motoi2c = {
     60 	.ic_acquire_bus = motoi2c_acquire_bus,
     61 	.ic_release_bus = motoi2c_release_bus,
     62 	.ic_exec	= motoi2c_exec,
     63 };
     64 
     65 static const struct motoi2c_settings motoi2c_default_settings = {
     66 	.i2c_adr	= MOTOI2C_ADR_DEFAULT,
     67 	.i2c_fdr	= MOTOI2C_FDR_DEFAULT,
     68 	.i2c_dfsrr	= MOTOI2C_DFSRR_DEFAULT,
     69 };
     70 
     71 #define	I2C_READ(r)	((*sc->sc_iord)(sc, (r)))
     72 #define	I2C_WRITE(r,v)	((*sc->sc_iowr)(sc, (r), (v)))
     73 #define I2C_SETCLR(r, s, c) \
     74 	((*sc->sc_iowr)(sc, (r), ((*sc->sc_iord)(sc, (r)) | (s)) & ~(c)))
     75 
     76 static uint8_t
     77 motoi2c_iord1(struct motoi2c_softc *sc, bus_size_t off)
     78 {
     79 	return bus_space_read_1(sc->sc_iot, sc->sc_ioh, off);
     80 }
     81 
     82 static void
     83 motoi2c_iowr1(struct motoi2c_softc *sc, bus_size_t off, uint8_t data)
     84 {
     85 	bus_space_write_1(sc->sc_iot, sc->sc_ioh, off, data);
     86 }
     87 
     88 void
     89 motoi2c_attach_common(device_t self, struct motoi2c_softc *sc,
     90 	const struct motoi2c_settings *i2c)
     91 {
     92 	struct i2cbus_attach_args iba;
     93 
     94 	mutex_init(&sc->sc_buslock, MUTEX_DEFAULT, IPL_NONE);
     95 
     96 	if (i2c == NULL)
     97 		i2c = &motoi2c_default_settings;
     98 
     99 	sc->sc_i2c = motoi2c;
    100 	sc->sc_i2c.ic_cookie = sc;
    101 	sc->sc_start = false;
    102 	if (sc->sc_iord == NULL)
    103 		sc->sc_iord = motoi2c_iord1;
    104 	if (sc->sc_iowr == NULL)
    105 		sc->sc_iowr = motoi2c_iowr1;
    106 	memset(&iba, 0, sizeof(iba));
    107 	iba.iba_tag = &sc->sc_i2c;
    108 
    109 	I2C_WRITE(I2CCR, 0);		/* reset before changing anything */
    110 	I2C_WRITE(I2CDFSRR, i2c->i2c_dfsrr);	/* sampling units */
    111 	I2C_WRITE(I2CFDR, i2c->i2c_fdr);	/* divider 3072 (0x31) */
    112 	I2C_WRITE(I2CADR, i2c->i2c_adr);	/* our slave address is 0x7f */
    113 	I2C_WRITE(I2CSR, 0);		/* clear status flags */
    114 
    115 	config_found_ia(self, "i2cbus", &iba, iicbus_print);
    116 }
    117 
    118 static int
    119 motoi2c_acquire_bus(void *v, int flags)
    120 {
    121 	struct motoi2c_softc * const sc = v;
    122 
    123 	mutex_enter(&sc->sc_buslock);
    124 	I2C_WRITE(I2CCR, CR_MEN);	/* enable the I2C module */
    125 
    126 	return 0;
    127 }
    128 
    129 static void
    130 motoi2c_release_bus(void *v, int flags)
    131 {
    132 	struct motoi2c_softc * const sc = v;
    133 
    134 	sc->sc_start = false;
    135 	I2C_WRITE(I2CCR, 0);		/* reset before changing anything */
    136 	mutex_exit(&sc->sc_buslock);
    137 }
    138 
    139 /* busy waiting for byte data transfer completion */
    140 static int
    141 motoi2c_busy_wait(struct motoi2c_softc *sc, uint8_t cr)
    142 {
    143 	uint8_t sr;
    144 	u_int timo;
    145 	int error = 0;
    146 
    147 	timo = 1000;
    148 	while (((sr = I2C_READ(I2CSR)) & SR_MIF) == 0 && --timo)
    149 		DELAY(10);
    150 
    151 	if (timo == 0) {
    152 		DPRINTF(("%s: timeout (sr=%#x, cr=%#x)\n",
    153 		    __func__, sr, I2C_READ(I2CCR)));
    154 		error = ETIMEDOUT;
    155 	}
    156 	/*
    157 	 * RXAK is only valid when transmitting.
    158 	 */
    159 	if ((cr & CR_MTX) && (sr & SR_RXAK)) {
    160 		DPRINTF(("%s: missing rx ack (%#x): spin=%u\n",
    161 		    __func__, sr, 1000 - timo));
    162 		error = EIO;
    163 	}
    164 	I2C_WRITE(I2CSR, 0);
    165 	return error;
    166 }
    167 
    168 int
    169 motoi2c_intr(void *v)
    170 {
    171 	struct motoi2c_softc * const sc = v;
    172 
    173 	panic("%s(%p)", __func__, sc);
    174 
    175 	return 0;
    176 }
    177 
    178 int
    179 motoi2c_exec(void *v, i2c_op_t op, i2c_addr_t addr,
    180 	const void *cmdbuf, size_t cmdlen,
    181 	void *databuf, size_t datalen,
    182 	int flags)
    183 {
    184 	struct motoi2c_softc * const sc = v;
    185 	uint8_t sr;
    186 	uint8_t cr;
    187 	int error;
    188 
    189 	sr = I2C_READ(I2CSR);
    190 	cr = I2C_READ(I2CCR);
    191 
    192 #if 0
    193 	DPRINTF(("%s(%#x,%#x,%p,%zu,%p,%zu,%#x): sr=%#x cr=%#x\n",
    194 	    __func__, op, addr, cmdbuf, cmdlen, databuf, datalen, flags,
    195 	    sr, cr));
    196 #endif
    197 
    198 	if ((cr & CR_MSTA) == 0 && (sr & SR_MBB) != 0) {
    199 		/* wait for bus becoming available */
    200 		u_int timo = 100;
    201 		do {
    202 			DELAY(10);
    203 		} while (--timo > 0 && ((sr = I2C_READ(I2CSR)) & SR_MBB) != 0);
    204 
    205 		if (timo == 0) {
    206 			DPRINTF(("%s: bus is busy (%#x)\n", __func__, sr));
    207 			return ETIMEDOUT;
    208 		}
    209 	}
    210 
    211 	/* reset interrupt and arbitration-lost flags (all others are RO) */
    212 	I2C_WRITE(I2CSR, 0);
    213 	sr = I2C_READ(I2CSR);
    214 
    215 	/*
    216 	 * Generate start (or restart) condition
    217 	 */
    218 	/* CR_RTSA is write-only and transitory */
    219 	uint8_t rsta = (cr & CR_MSTA ? CR_RSTA : 0);
    220 	cr = CR_MEN | CR_MTX | CR_MSTA;
    221 	I2C_WRITE(I2CCR, cr | rsta);
    222 
    223 	DPRINTF(("%s: started: sr=%#x cr=%#x/%#x\n",
    224 	    __func__, I2C_READ(I2CSR), cr, I2C_READ(I2CCR)));
    225 
    226 	sr = I2C_READ(I2CSR);
    227 	if (sr & SR_MAL) {
    228 		DPRINTF(("%s: lost bus: sr=%#x cr=%#x/%#x\n",
    229 		    __func__, I2C_READ(I2CSR), cr, I2C_READ(I2CCR)));
    230 		I2C_WRITE(I2CCR, 0);
    231 		DELAY(10);
    232 		I2C_WRITE(I2CCR, CR_MEN | CR_MTX | CR_MSTA);
    233 		DELAY(10);
    234 		sr = I2C_READ(I2CSR);
    235 		if (sr & SR_MAL) {
    236 			error = EBUSY;
    237 			goto out;
    238 		}
    239 		DPRINTF(("%s: reacquired bus: sr=%#x cr=%#x/%#x\n",
    240 		    __func__, I2C_READ(I2CSR), cr, I2C_READ(I2CCR)));
    241 	}
    242 
    243 	/* send target address and transfer direction */
    244 	uint8_t addr_byte = (addr << 1)
    245 	    | (cmdlen == 0 && I2C_OP_READ_P(op) ? 1 : 0);
    246 	I2C_WRITE(I2CDR, addr_byte);
    247 
    248 	error = motoi2c_busy_wait(sc, cr);
    249 	if (error) {
    250 		DPRINTF(("%s: error sending address: %d\n", __func__, error));
    251 		if (error == EIO)
    252 			error = ENXIO;
    253 		goto out;
    254 	}
    255 
    256 	const uint8_t *cmdptr = cmdbuf;
    257 	for (size_t i = 0; i < cmdlen; i++) {
    258 		I2C_WRITE(I2CDR, *cmdptr++);
    259 
    260 		error = motoi2c_busy_wait(sc, cr);
    261 		if (error) {
    262 			DPRINTF(("%s: error sending cmd byte %zu (cr=%#x/%#x):"
    263 			    " %d\n", __func__, i, I2C_READ(I2CCR), cr, error));
    264 			goto out;
    265 		}
    266 	}
    267 
    268 	if (cmdlen > 0 && I2C_OP_READ_P(op)) {
    269 		KASSERT(cr & CR_MTX);
    270 		KASSERT((cr & CR_TXAK) == 0);
    271 		I2C_WRITE(I2CCR, cr | CR_RSTA);
    272 #if 0
    273 		DPRINTF(("%s: restarted(read): sr=%#x cr=%#x(%#x)\n",
    274 		    __func__, I2C_READ(I2CSR), cr | CR_RSTA, I2C_READ(I2CCR)));
    275 #endif
    276 
    277 		/* send target address and read transfer direction */
    278 		addr_byte |= 1;
    279 		I2C_WRITE(I2CDR, addr_byte);
    280 
    281 		error = motoi2c_busy_wait(sc, cr);
    282 		if (error) {
    283 			if (error == EIO)
    284 				error = ENXIO;
    285 			goto out;
    286 		}
    287 	}
    288 
    289 	if (I2C_OP_READ_P(op)) {
    290 		uint8_t *dataptr = databuf;
    291 		cr &= ~CR_MTX;		/* clear transmit flags */
    292 		if (datalen <= 1 && I2C_OP_STOP_P(op)) {
    293 			cr |= CR_TXAK;
    294 		}
    295 		I2C_WRITE(I2CCR, cr);
    296 		DELAY(10);
    297 		(void)I2C_READ(I2CDR);		/* dummy read */
    298 		for (size_t i = 0; i < datalen; i++) {
    299 			/*
    300 			 * If a master receiver wants to terminate a data
    301 			 * transfer, it must inform the slave transmitter by
    302 			 * not acknowledging the last byte of data (by setting
    303 			 * the transmit acknowledge bit (I2CCR[TXAK])) before
    304 			 * reading the next-to-last byte of data.
    305 			 */
    306 			error = motoi2c_busy_wait(sc, cr);
    307 			if (error) {
    308 				DPRINTF(("%s: error reading byte %zu: %d\n",
    309 				    __func__, i, error));
    310 				goto out;
    311 			}
    312 			if (I2C_OP_STOP_P(op)) {
    313 				if (i == datalen - 2) {
    314 					cr |= CR_TXAK;
    315 					I2C_WRITE(I2CCR, cr);
    316 				} else if (i == datalen - 1) {
    317 					cr = CR_MEN;
    318 					I2C_WRITE(I2CCR, cr);
    319 					sc->sc_start = false;
    320 				}
    321 			}
    322 			*dataptr++ = I2C_READ(I2CDR);
    323 		}
    324 		if (datalen == 0) {
    325 			(void)I2C_READ(I2CDR);	/* dummy read */
    326 			error = motoi2c_busy_wait(sc, cr);
    327 			if (error) {
    328 				DPRINTF(("%s: error reading dummy last byte:"
    329 				    "%d\n", __func__, error));
    330 				goto out;
    331 			}
    332 		}
    333 	} else {
    334 		const uint8_t *dataptr = databuf;
    335 		for (size_t i = 0; i < datalen; i++) {
    336 			I2C_WRITE(I2CDR, *dataptr++);
    337 			error = motoi2c_busy_wait(sc, cr);
    338 			if (error) {
    339 				DPRINTF(("%s: error sending data byte %zu:"
    340 				    " %d\n", __func__, i, error));
    341 				goto out;
    342 			}
    343 		}
    344 	}
    345 
    346  out:
    347 	/*
    348 	 * If we encountered an error condition or caller wants a STOP,
    349 	 * send a STOP.
    350 	 */
    351 	if (error || (cr & CR_TXAK) || ((cr & CR_MSTA) && I2C_OP_STOP_P(op))) {
    352 		cr = CR_MEN;
    353 		I2C_WRITE(I2CCR, cr);
    354 		DPRINTF(("%s: stopping: cr=%#x/%#x\n", __func__,
    355 		    cr, I2C_READ(I2CCR)));
    356 	}
    357 
    358 	DPRINTF(("%s: exit sr=%#x cr=%#x: %d\n", __func__,
    359 	    I2C_READ(I2CSR), I2C_READ(I2CCR), error));
    360 
    361 	return error;
    362 }
    363