Home | History | Annotate | Line # | Download | only in dev
fire_i2c.c revision 1.1
      1  1.1  jdc /* $NetBSD: fire_i2c.c,v 1.1 2026/06/04 13:43:24 jdc Exp $ */
      2  1.1  jdc 
      3  1.1  jdc /*-
      4  1.1  jdc  * Copyright (c) 2026 The NetBSD Foundation, Inc.
      5  1.1  jdc  * All rights reserved.
      6  1.1  jdc  *
      7  1.1  jdc  * This code is derived from software contributed to The NetBSD Foundation
      8  1.1  jdc  * by Julian Coleman.
      9  1.1  jdc  *
     10  1.1  jdc  * Redistribution and use in source and binary forms, with or without
     11  1.1  jdc  * modification, are permitted provided that the following conditions
     12  1.1  jdc  * are met:
     13  1.1  jdc  * 1. Redistributions of source code must retain the above copyright
     14  1.1  jdc  *    notice, this list of conditions and the following disclaimer.
     15  1.1  jdc  * 2. Redistributions in binary form must reproduce the above copyright
     16  1.1  jdc  *    notice, this list of conditions and the following disclaimer in the
     17  1.1  jdc  *    documentation and/or other materials provided with the distribution.
     18  1.1  jdc  *
     19  1.1  jdc  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20  1.1  jdc  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21  1.1  jdc  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22  1.1  jdc  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23  1.1  jdc  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24  1.1  jdc  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25  1.1  jdc  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26  1.1  jdc  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27  1.1  jdc  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28  1.1  jdc  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29  1.1  jdc  * POSSIBILITY OF SUCH DAMAGE.
     30  1.1  jdc  */
     31  1.1  jdc 
     32  1.1  jdc #include <sys/cdefs.h>
     33  1.1  jdc __KERNEL_RCSID(0, "$NetBSD: fire_i2c.c,v 1.1 2026/06/04 13:43:24 jdc Exp $");
     34  1.1  jdc 
     35  1.1  jdc #include <sys/param.h>
     36  1.1  jdc #include <sys/condvar.h>
     37  1.1  jdc #include <sys/device.h>
     38  1.1  jdc #include <sys/intr.h>
     39  1.1  jdc #include <sys/mutex.h>
     40  1.1  jdc 
     41  1.1  jdc #include <machine/autoconf.h>
     42  1.1  jdc #include <machine/openfirm.h>
     43  1.1  jdc 
     44  1.1  jdc #include <dev/i2c/i2cvar.h>
     45  1.1  jdc #include <arch/sparc64/dev/fire_i2creg.h>
     46  1.1  jdc 
     47  1.1  jdc #define FIREI2C_DEBUG 0
     48  1.1  jdc #if FIREI2C_DEBUG > 0
     49  1.1  jdc #define DPRINTF printf
     50  1.1  jdc #else
     51  1.1  jdc #define DPRINTF if (0) printf
     52  1.1  jdc #endif
     53  1.1  jdc 
     54  1.1  jdc #define FIREI2C_SCL_FREQ	100000
     55  1.1  jdc #define FIREI2C_OWN_ADDR	0x08
     56  1.1  jdc 
     57  1.1  jdc #define FIREI2C_CLK_FULL	0
     58  1.1  jdc #define FIREI2C_CLK_HALF	1
     59  1.1  jdc #define FIREI2C_CLK_TT		2
     60  1.1  jdc #define FIREI2C_CLK_LEN		3
     61  1.1  jdc 
     62  1.1  jdc struct firei2c_softc {
     63  1.1  jdc 	device_t sc_dev;
     64  1.1  jdc 	bus_space_tag_t sc_bustag;
     65  1.1  jdc 	bus_space_handle_t sc_regh;
     66  1.1  jdc 	int sc_node;
     67  1.1  jdc 	void *sc_inth;
     68  1.1  jdc 	uint8_t sc_i2c_clks[FIREI2C_CLK_LEN];
     69  1.1  jdc 	struct i2c_controller sc_i2c;
     70  1.1  jdc 	kmutex_t sc_mutex;
     71  1.1  jdc 	kcondvar_t sc_cv;
     72  1.1  jdc };
     73  1.1  jdc 
     74  1.1  jdc static int firei2c_match(device_t, cfdata_t, void *);
     75  1.1  jdc static void firei2c_attach(device_t, device_t, void *);
     76  1.1  jdc static uint8_t firei2c_clock(int);
     77  1.1  jdc static int firei2c_stop(struct firei2c_softc *);
     78  1.1  jdc static int firei2c_wait(struct firei2c_softc *, int);
     79  1.1  jdc int firei2c_exec(void *, i2c_op_t, i2c_addr_t, const void *,
     80  1.1  jdc     size_t, void *, size_t, int);
     81  1.1  jdc static int firei2c_write(struct firei2c_softc *, const uint8_t *, size_t,
     82  1.1  jdc     uint8_t *, size_t, int, int);
     83  1.1  jdc static int firei2c_read(struct firei2c_softc *, uint8_t *, size_t, int, int);
     84  1.1  jdc int firei2c_intr(void *);
     85  1.1  jdc static uint8_t firei2c_reg_read(struct firei2c_softc *, bus_size_t);
     86  1.1  jdc static void firei2c_reg_write(struct firei2c_softc *, bus_size_t, uint8_t);
     87  1.1  jdc 
     88  1.1  jdc CFATTACH_DECL_NEW(firei2c, sizeof(struct firei2c_softc),
     89  1.1  jdc 	firei2c_match, firei2c_attach, NULL, NULL);
     90  1.1  jdc 
     91  1.1  jdc static int
     92  1.1  jdc firei2c_match(device_t parent, cfdata_t cf, void *aux)
     93  1.1  jdc {
     94  1.1  jdc 	struct mainbus_attach_args *ma = aux;
     95  1.1  jdc 	char *compat;
     96  1.1  jdc 
     97  1.1  jdc 	if (strcmp(ma->ma_name, "i2c"))
     98  1.1  jdc 		return 0;
     99  1.1  jdc 
    100  1.1  jdc 	compat = prom_getpropstring(ma->ma_node, "compatible");
    101  1.1  jdc 	if (!strcmp(compat, "fire-i2c"))
    102  1.1  jdc 		return 1;
    103  1.1  jdc 
    104  1.1  jdc 	return 0;
    105  1.1  jdc }
    106  1.1  jdc 
    107  1.1  jdc static void
    108  1.1  jdc firei2c_attach(device_t parent, device_t self, void *aux)
    109  1.1  jdc {
    110  1.1  jdc 	struct firei2c_softc *sc = device_private(self);
    111  1.1  jdc 	struct mainbus_attach_args *ma = aux;
    112  1.1  jdc 	int  sysclk;
    113  1.1  jdc 
    114  1.1  jdc 	sc->sc_bustag = ma->ma_bustag;
    115  1.1  jdc 	sc->sc_node = ma->ma_node;
    116  1.1  jdc 	sc->sc_dev = self;
    117  1.1  jdc 
    118  1.1  jdc 	if (ma->ma_nreg != 1) {
    119  1.1  jdc 		aprint_error(": register count error (%d != 1)\n",
    120  1.1  jdc 		    ma->ma_nreg);
    121  1.1  jdc 		return;
    122  1.1  jdc 	}
    123  1.1  jdc 	if (ma->ma_reg[0].ur_len < FIREI2C_SRST) {
    124  1.1  jdc 		aprint_error(": register length error (%ld < %d\n",
    125  1.1  jdc 		    ma->ma_reg[0].ur_len, FIREI2C_SRST);
    126  1.1  jdc 		return;
    127  1.1  jdc 	}
    128  1.1  jdc 
    129  1.1  jdc 	if (bus_space_map(sc->sc_bustag, ma->ma_reg[0].ur_paddr,
    130  1.1  jdc 	    ma->ma_reg[0].ur_len, 0, &sc->sc_regh)) {
    131  1.1  jdc 		aprint_error(": failed to map registers\n");
    132  1.1  jdc 		return;
    133  1.1  jdc 	}
    134  1.1  jdc 
    135  1.1  jdc 	sc->sc_inth = NULL;
    136  1.1  jdc /* XXX need to set up interrupt mapping before we can enable them here
    137  1.1  jdc    Both i2c interrupts must go to the same Pyro leaf.
    138  1.1  jdc 
    139  1.1  jdc 	sc->sc_inth = bus_intr_establish(sc->sc_bustag, *ma->ma_interrupts,
    140  1.1  jdc 	    IPL_VM, firei2c_intr, sc);
    141  1.1  jdc 
    142  1.1  jdc 	if (sc->sc_inth == NULL) {
    143  1.1  jdc 		aprint_error(": failed to establish interrupt\n");
    144  1.1  jdc 		return;
    145  1.1  jdc 	}
    146  1.1  jdc */
    147  1.1  jdc 
    148  1.1  jdc 	aprint_normal(": addr %" PRIx64 ": Fire/MI2C i2c controller\n",
    149  1.1  jdc 	    ma->ma_reg[0].ur_paddr);
    150  1.1  jdc /* XXX interrupts
    151  1.1  jdc 	aprint_normal_dev(self, "interrupting at %x\n", *ma->ma_interrupts);
    152  1.1  jdc */
    153  1.1  jdc 
    154  1.1  jdc 	/* Calculate clock, software reset, set our addr, enable interrupts */
    155  1.1  jdc 	sysclk = prom_getpropint(findroot(), "clock-frequency", 0);
    156  1.1  jdc 	sc->sc_i2c_clks[FIREI2C_CLK_FULL] = firei2c_clock(sysclk);
    157  1.1  jdc 	sc->sc_i2c_clks[FIREI2C_CLK_HALF] = firei2c_clock(sysclk / 2);
    158  1.1  jdc 	sc->sc_i2c_clks[FIREI2C_CLK_TT] = firei2c_clock(sysclk / 32);
    159  1.1  jdc 	firei2c_reg_write(sc, FIREI2C_SRST, FIREI2C_SRST_RST);
    160  1.1  jdc 	delay(1000);
    161  1.1  jdc 	firei2c_reg_write(sc, FIREI2C_CCR, sc->sc_i2c_clks[FIREI2C_CLK_FULL]);
    162  1.1  jdc 	firei2c_reg_write(sc, FIREI2C_ADDR,
    163  1.1  jdc 	    FIREI2C_OWN_ADDR << FIREI2C_ADDR_SHIFT);
    164  1.1  jdc 
    165  1.1  jdc 	/* i2c setup */
    166  1.1  jdc 	iic_tag_init(&sc->sc_i2c);
    167  1.1  jdc 	sc->sc_i2c.ic_cookie = sc;
    168  1.1  jdc 	sc->sc_i2c.ic_exec = firei2c_exec;
    169  1.1  jdc 
    170  1.1  jdc 	/* Synchronisation between exec and intr */
    171  1.1  jdc 	mutex_init(&sc->sc_mutex, MUTEX_DEFAULT, IPL_VM);
    172  1.1  jdc 	cv_init(&sc->sc_cv, "firei2c");
    173  1.1  jdc 
    174  1.1  jdc 	iicbus_attach(sc->sc_dev, &sc->sc_i2c);
    175  1.1  jdc 	return;
    176  1.1  jdc }
    177  1.1  jdc 
    178  1.1  jdc /*
    179  1.1  jdc  * Sampling frequency: input clock divided by 2^N (N is bits 0:2)
    180  1.1  jdc  * SCL frequency: sampling frequency divided by (M + 1) * 10 (bits 3:6)
    181  1.1  jdc  * i2c SCL is max 100kHz, so find the closest frequency at or below that.
    182  1.1  jdc  *
    183  1.1  jdc  * If the system (JBus) clock frequency changes, we must change our clock.
    184  1.1  jdc  * If increasing: after the JBus change, if decreasing: before the change.
    185  1.1  jdc  * This is to avoid running the i2c clock faster than the specification.
    186  1.1  jdc  */
    187  1.1  jdc static uint8_t
    188  1.1  jdc firei2c_clock(int sysclk)
    189  1.1  jdc {
    190  1.1  jdc 	int p, f, best_p, best_f;
    191  1.1  jdc 	uint32_t sample, scl;
    192  1.1  jdc 	uint32_t min = FIREI2C_SCL_FREQ;
    193  1.1  jdc 	uint8_t clkval;
    194  1.1  jdc 
    195  1.1  jdc 	best_p = 0;
    196  1.1  jdc 	best_f = 0;
    197  1.1  jdc 	for (p = 0; p <= FIREI2C_CCR_POW2_MAX; p++) {
    198  1.1  jdc 		if (p)
    199  1.1  jdc 			sample = sysclk / (2 << (p - 1));
    200  1.1  jdc 		else
    201  1.1  jdc 			sample = sysclk;
    202  1.1  jdc 		for (f = 0; f <= FIREI2C_CCR_FACT_MAX; f++) {
    203  1.1  jdc 			scl = sample / ((f + 1) * 10);
    204  1.1  jdc 			if (scl <= FIREI2C_SCL_FREQ) {
    205  1.1  jdc 				if (FIREI2C_SCL_FREQ - scl < min) {
    206  1.1  jdc 					best_p = p;
    207  1.1  jdc 					best_f = f;
    208  1.1  jdc 					min = FIREI2C_SCL_FREQ - scl;
    209  1.1  jdc 				}
    210  1.1  jdc 				break;	/* Already at or below SCL_FREQ */
    211  1.1  jdc 			}
    212  1.1  jdc 		}
    213  1.1  jdc 		if (!min)	/* Exactly SCL_FREQ */
    214  1.1  jdc 			break;
    215  1.1  jdc 	}
    216  1.1  jdc 	clkval = best_p + (best_f << FIREI2C_CCR_FACT_SHIFT);
    217  1.1  jdc 	return clkval;
    218  1.1  jdc }
    219  1.1  jdc 
    220  1.1  jdc /* No interrupts for stop, so wait for idle */
    221  1.1  jdc static int
    222  1.1  jdc firei2c_stop(struct firei2c_softc *sc)
    223  1.1  jdc {
    224  1.1  jdc 	int i;
    225  1.1  jdc 	uint8_t ctrl, val;
    226  1.1  jdc 
    227  1.1  jdc 	ctrl = FIREI2C_CTRL_ENAB | FIREI2C_CTRL_STP;
    228  1.1  jdc 	firei2c_reg_write(sc, FIREI2C_CTRL, ctrl);
    229  1.1  jdc 	for (i = 0; i < 500; i++) {
    230  1.1  jdc 		val = firei2c_reg_read(sc, FIREI2C_STAT);
    231  1.1  jdc 		if (val == FIREI2C_STAT_IDLE)
    232  1.1  jdc 			return 0;
    233  1.1  jdc 		delay(1000);
    234  1.1  jdc 	}
    235  1.1  jdc 	/* Clear the interrupt flag if we timed out */
    236  1.1  jdc 	ctrl = FIREI2C_CTRL_ENAB;
    237  1.1  jdc 	firei2c_reg_write(sc, FIREI2C_CTRL, ctrl);
    238  1.1  jdc 	return 1;
    239  1.1  jdc }
    240  1.1  jdc 
    241  1.1  jdc 
    242  1.1  jdc static int
    243  1.1  jdc firei2c_wait(struct firei2c_softc *sc, int flags)
    244  1.1  jdc {
    245  1.1  jdc 	volatile uint8_t ctrl;
    246  1.1  jdc 	int i;
    247  1.1  jdc 
    248  1.1  jdc 	if (sc->sc_inth == NULL || flags & I2C_F_POLL) {
    249  1.1  jdc 		for (i = 0; i < 500; i++) {
    250  1.1  jdc 			ctrl = firei2c_reg_read(sc, FIREI2C_CTRL);
    251  1.1  jdc 			if (ctrl & FIREI2C_CTRL_IFLG)
    252  1.1  jdc 				return 0;
    253  1.1  jdc 			delay(1000);
    254  1.1  jdc 		}
    255  1.1  jdc 		return 1;
    256  1.1  jdc 	} else {
    257  1.1  jdc 		mutex_enter(&sc->sc_mutex);
    258  1.1  jdc 		if (cv_timedwait(&sc->sc_cv, &sc->sc_mutex, hz / 2)) {
    259  1.1  jdc 			mutex_exit(&sc->sc_mutex);
    260  1.1  jdc 			return 1;
    261  1.1  jdc 		}
    262  1.1  jdc 		mutex_exit(&sc->sc_mutex);
    263  1.1  jdc 		return 0;
    264  1.1  jdc 	}
    265  1.1  jdc }
    266  1.1  jdc 
    267  1.1  jdc /*
    268  1.1  jdc  * Flow for a "simple" read/write:
    269  1.1  jdc  *   1.  Send start
    270  1.1  jdc  *   2.  Send addr + R or W
    271  1.1  jdc  *   3.  Receive ACK
    272  1.1  jdc  *   4.  (nothing)
    273  1.1  jdc  *   5.  (nothing)
    274  1.1  jdc  *   6R. Receive data			6W.  Send data
    275  1.1  jdc  *   7R. Send ACK or NAK		7W.  Receive ACK or NAK
    276  1.1  jdc  *       either receive more (6R) or	     either write more (6W) or
    277  1.1  jdc  *   8.  Send stop
    278  1.1  jdc  *
    279  1.1  jdc  * Flow for read/write following a "register" write:
    280  1.1  jdc  *   1.  Send start
    281  1.1  jdc  *   2.  Send addr + W
    282  1.1  jdc  *   3.  Receive ACK
    283  1.1  jdc  *   4.  Send register
    284  1.1  jdc  *   5R. Send repeat start + addr + R	5W.  (nothing to do)
    285  1.1  jdc  *   6R. Receive data			6W.  Send data
    286  1.1  jdc  *   7R. Send ACK or NAK		7W.  Receive ACK or NAK
    287  1.1  jdc  *       either receive more (6R) or	     either write more (6W) or
    288  1.1  jdc  *   8.  Send stop
    289  1.1  jdc  *
    290  1.1  jdc  * After each step, we receive an interrupt notifying us of the result.
    291  1.1  jdc  * We check the status, set up the next step, then clear the interrupt flag.
    292  1.1  jdc  */
    293  1.1  jdc int
    294  1.1  jdc firei2c_exec(void *arg, i2c_op_t op, i2c_addr_t addr, const void *cmd,
    295  1.1  jdc     size_t cmdlen, void *vbuf, size_t buflen, int flags)
    296  1.1  jdc {
    297  1.1  jdc 	struct firei2c_softc *sc = arg;
    298  1.1  jdc 	uint8_t *buf = vbuf;
    299  1.1  jdc 	uint8_t ctrl, val, ack, nack;
    300  1.1  jdc 	int err;
    301  1.1  jdc 
    302  1.1  jdc 	DPRINTF("%s: exec op: %d addr: 0x%x cmdlen: %d buflen: %d flags 0x%x\n",
    303  1.1  jdc 	    device_xname(sc->sc_dev), op, addr,
    304  1.1  jdc 	    (int) cmdlen, (int) buflen, flags);
    305  1.1  jdc 
    306  1.1  jdc 	/*
    307  1.1  jdc 	 * Send start
    308  1.1  jdc  	 * If we are writing, write addr, cmd, buf.
    309  1.1  jdc  	 * If we are reading, either:
    310  1.1  jdc  	 *   write addr, cmd, repeat-start, then read addr to buf, or:
    311  1.1  jdc  	 *   read addr to buf.
    312  1.1  jdc 	 * Send stop
    313  1.1  jdc  	 */
    314  1.1  jdc 
    315  1.1  jdc 	/* Control defaults - bus enabled, interrupts enabled */
    316  1.1  jdc 	ctrl = FIREI2C_CTRL_ENAB;
    317  1.1  jdc 	if (sc->sc_inth != NULL && !(flags & I2C_F_POLL))
    318  1.1  jdc 		ctrl |= FIREI2C_CTRL_IEN;
    319  1.1  jdc 
    320  1.1  jdc 	val = firei2c_reg_read(sc, FIREI2C_STAT);
    321  1.1  jdc 	if (val != FIREI2C_STAT_IDLE) {
    322  1.1  jdc 		/* Try sending stop */
    323  1.1  jdc 		DPRINTF("%s: not idle, sending stop\n",
    324  1.1  jdc 		    device_xname(sc->sc_dev));
    325  1.1  jdc 		err = firei2c_stop(sc);
    326  1.1  jdc 		if (err) {
    327  1.1  jdc 			printf("%s: not idle (0x%02x)\n",
    328  1.1  jdc 			    device_xname(sc->sc_dev), val);
    329  1.1  jdc 			return 1;
    330  1.1  jdc 		}
    331  1.1  jdc 	}
    332  1.1  jdc 
    333  1.1  jdc 	/* Send start */
    334  1.1  jdc 	val = ctrl | FIREI2C_CTRL_STA;
    335  1.1  jdc 	firei2c_reg_write(sc, FIREI2C_CTRL, val);
    336  1.1  jdc 	err = firei2c_wait(sc, flags);
    337  1.1  jdc 	val = firei2c_reg_read(sc, FIREI2C_STAT);
    338  1.1  jdc 	if (err) {
    339  1.1  jdc 		printf("%s: start timeout 0x%x\n",
    340  1.1  jdc 		    device_xname(sc->sc_dev), val);
    341  1.1  jdc 		goto stop;
    342  1.1  jdc 	}
    343  1.1  jdc 	if (val != FIREI2C_STAT_STA) {
    344  1.1  jdc 		printf("%s: start error 0x%x\n",
    345  1.1  jdc 		    device_xname(sc->sc_dev), val);
    346  1.1  jdc 		err = 1;
    347  1.1  jdc 		goto stop;
    348  1.1  jdc 	}
    349  1.1  jdc 
    350  1.1  jdc 	/* Address + r/w in data, then clear interrupt flag in ctrl */
    351  1.1  jdc 	val = (addr & 0x7f) << FIREI2C_DATA_SHIFT;
    352  1.1  jdc 	if (I2C_OP_WRITE_P(op) || cmdlen > 0) {
    353  1.1  jdc 		ack = FIREI2C_STAT_AWR_ACK;
    354  1.1  jdc 		nack = FIREI2C_STAT_AWR_NAK;
    355  1.1  jdc 	} else {
    356  1.1  jdc 		val |= 0x01;
    357  1.1  jdc 		ack = FIREI2C_STAT_ARE_ACK;
    358  1.1  jdc 		nack = FIREI2C_STAT_ARE_NAK;
    359  1.1  jdc 	}
    360  1.1  jdc 	firei2c_reg_write(sc, FIREI2C_DATA, val);
    361  1.1  jdc 	firei2c_reg_write(sc, FIREI2C_CTRL, ctrl);
    362  1.1  jdc 	err = firei2c_wait(sc, flags);
    363  1.1  jdc 	val = firei2c_reg_read(sc, FIREI2C_STAT);
    364  1.1  jdc 	if (err) {
    365  1.1  jdc 		printf("%s: addr timeout 0x%x\n",
    366  1.1  jdc 		    device_xname(sc->sc_dev), val);
    367  1.1  jdc 		goto stop;
    368  1.1  jdc 	}
    369  1.1  jdc 	if (val != ack) {
    370  1.1  jdc 		if (val != nack)	/* Don't print for NACK */
    371  1.1  jdc 			printf("%s: addr error 0x%x\n",
    372  1.1  jdc 			    device_xname(sc->sc_dev), val);
    373  1.1  jdc 		err = 1;
    374  1.1  jdc 		goto stop;
    375  1.1  jdc 	}
    376  1.1  jdc 
    377  1.1  jdc 	err = 0;
    378  1.1  jdc 	if (I2C_OP_READ_P(op)) {
    379  1.1  jdc 		if (cmdlen > 0) {
    380  1.1  jdc 			/* Write register */
    381  1.1  jdc 			err = firei2c_write(sc, cmd, cmdlen,
    382  1.1  jdc 			    NULL, 0, ctrl, flags);
    383  1.1  jdc 			if (err)
    384  1.1  jdc 				goto stop;
    385  1.1  jdc 
    386  1.1  jdc 			/* Send repeat start */
    387  1.1  jdc 			val = ctrl | FIREI2C_CTRL_STA;
    388  1.1  jdc 			firei2c_reg_write(sc, FIREI2C_CTRL, val);
    389  1.1  jdc 			err = firei2c_wait(sc, flags);
    390  1.1  jdc 			val = firei2c_reg_read(sc, FIREI2C_STAT);
    391  1.1  jdc 			if (err) {
    392  1.1  jdc 				printf("%s: repeat start timeout 0x%x\n",
    393  1.1  jdc 				    device_xname(sc->sc_dev), val);
    394  1.1  jdc 				goto stop;
    395  1.1  jdc 			}
    396  1.1  jdc 			if (val != FIREI2C_STAT_REPSTA) {
    397  1.1  jdc 				printf("%s: repeat start error 0x%x\n",
    398  1.1  jdc 				    device_xname(sc->sc_dev), val);
    399  1.1  jdc 				err = 1;
    400  1.1  jdc 				goto stop;
    401  1.1  jdc 			}
    402  1.1  jdc 
    403  1.1  jdc 			/* Address + r in data, then clear intr flag in ctrl */
    404  1.1  jdc 			val = (addr & 0x7f) << FIREI2C_DATA_SHIFT;
    405  1.1  jdc 			val |= 0x01;
    406  1.1  jdc 			ack = FIREI2C_STAT_ARE_ACK;
    407  1.1  jdc 			nack = FIREI2C_STAT_ARE_NAK;
    408  1.1  jdc 			firei2c_reg_write(sc, FIREI2C_DATA, val);
    409  1.1  jdc 			firei2c_reg_write(sc, FIREI2C_CTRL, ctrl);
    410  1.1  jdc 			err = firei2c_wait(sc, flags);
    411  1.1  jdc 			val = firei2c_reg_read(sc, FIREI2C_STAT);
    412  1.1  jdc 			if (err) {
    413  1.1  jdc 				printf("%s: addr timeout 0x%x\n",
    414  1.1  jdc 				    device_xname(sc->sc_dev), val);
    415  1.1  jdc 				goto stop;
    416  1.1  jdc 			}
    417  1.1  jdc 			if (val != ack) {
    418  1.1  jdc 				if (val != nack)
    419  1.1  jdc 					printf("%s: addr error 0x%x\n",
    420  1.1  jdc 					    device_xname(sc->sc_dev), val);
    421  1.1  jdc 				err = 1;
    422  1.1  jdc 				goto stop;
    423  1.1  jdc 			}
    424  1.1  jdc 		}
    425  1.1  jdc 
    426  1.1  jdc 		/* Read data */
    427  1.1  jdc 		err = firei2c_read(sc, buf, buflen, ctrl, flags);
    428  1.1  jdc 	} else
    429  1.1  jdc 		/* Write data or register + data */
    430  1.1  jdc 		err = firei2c_write(sc, cmd, cmdlen, buf, buflen, ctrl, flags);
    431  1.1  jdc 
    432  1.1  jdc stop:
    433  1.1  jdc 	err |= firei2c_stop(sc);
    434  1.1  jdc 
    435  1.1  jdc 	return err;
    436  1.1  jdc }
    437  1.1  jdc 
    438  1.1  jdc static int
    439  1.1  jdc firei2c_write(struct firei2c_softc *sc, const uint8_t *cmd, size_t cmdlen,
    440  1.1  jdc     uint8_t *buf, size_t buflen, int ctrl, int flags)
    441  1.1  jdc {
    442  1.1  jdc 	uint8_t val;
    443  1.1  jdc 	int i, err;
    444  1.1  jdc 
    445  1.1  jdc 	for (i = 0; i < cmdlen + buflen; i++) {
    446  1.1  jdc 		/* Bytes in data, then clear interrupt flag in ctrl */
    447  1.1  jdc 		if (i < cmdlen)
    448  1.1  jdc 			val = cmd[i];
    449  1.1  jdc 		else
    450  1.1  jdc 			val = buf[i - cmdlen];
    451  1.1  jdc 		firei2c_reg_write(sc, FIREI2C_DATA, val);
    452  1.1  jdc 		firei2c_reg_write(sc, FIREI2C_CTRL, ctrl);
    453  1.1  jdc 		err = firei2c_wait(sc, flags);
    454  1.1  jdc 		val = firei2c_reg_read(sc, FIREI2C_STAT);
    455  1.1  jdc 		if (err) {
    456  1.1  jdc 			printf("%s: write timeout 0x%x\n",
    457  1.1  jdc 			    device_xname(sc->sc_dev), val);
    458  1.1  jdc 			return 1;
    459  1.1  jdc 		}
    460  1.1  jdc 		if (val != FIREI2C_STAT_DAT_ACK) {
    461  1.1  jdc 			if (val != FIREI2C_STAT_DAT_NAK)
    462  1.1  jdc 				printf("%s: write error 0x%x\n",
    463  1.1  jdc 				    device_xname(sc->sc_dev), val);
    464  1.1  jdc 			return 1;
    465  1.1  jdc 		}
    466  1.1  jdc 
    467  1.1  jdc 	}
    468  1.1  jdc 	return 0;
    469  1.1  jdc }
    470  1.1  jdc 
    471  1.1  jdc static int
    472  1.1  jdc firei2c_read(struct firei2c_softc *sc, uint8_t *buf, size_t buflen,
    473  1.1  jdc     int ctrl, int flags)
    474  1.1  jdc {
    475  1.1  jdc 	uint8_t val, ack;
    476  1.1  jdc 	int i, err;
    477  1.1  jdc 
    478  1.1  jdc 	for (i = 0; i < buflen; i++) {
    479  1.1  jdc 		/* Send ACK on all but last byte */
    480  1.1  jdc 		if (i < buflen - 1) {
    481  1.1  jdc 			val = ctrl | FIREI2C_CTRL_AAK;
    482  1.1  jdc 			ack = FIREI2C_STAT_MDAT_ACK;
    483  1.1  jdc 		} else {
    484  1.1  jdc 			val = ctrl;
    485  1.1  jdc 			ack = FIREI2C_STAT_MDAT_NAK;
    486  1.1  jdc 		}
    487  1.1  jdc 		/* Clear interrupt flag in ctrl, bytes in data */
    488  1.1  jdc 		firei2c_reg_write(sc, FIREI2C_CTRL, val);
    489  1.1  jdc 		err = firei2c_wait(sc, flags);
    490  1.1  jdc 		val = firei2c_reg_read(sc, FIREI2C_STAT);
    491  1.1  jdc 		if (err) {
    492  1.1  jdc 			printf("%s: read timeout 0x%x\n",
    493  1.1  jdc 			    device_xname(sc->sc_dev), val);
    494  1.1  jdc 			return 1;
    495  1.1  jdc 		}
    496  1.1  jdc 		if (val != ack) {
    497  1.1  jdc 			printf("%s: read error 0x%x\n",
    498  1.1  jdc 			    device_xname(sc->sc_dev), val);
    499  1.1  jdc 			return 1;
    500  1.1  jdc 		}
    501  1.1  jdc 		buf[i] = firei2c_reg_read(sc, FIREI2C_DATA);
    502  1.1  jdc 	}
    503  1.1  jdc 	return 0;
    504  1.1  jdc }
    505  1.1  jdc 
    506  1.1  jdc int
    507  1.1  jdc firei2c_intr(void *arg)
    508  1.1  jdc {
    509  1.1  jdc 	struct firei2c_softc *sc = arg;
    510  1.1  jdc 	uint8_t ctrl;
    511  1.1  jdc 
    512  1.1  jdc 	mutex_enter(&sc->sc_mutex);
    513  1.1  jdc 	ctrl = firei2c_reg_read(sc, FIREI2C_CTRL);
    514  1.1  jdc 	if (ctrl & FIREI2C_CTRL_IFLG) {
    515  1.1  jdc 		/* Disable interrupts */
    516  1.1  jdc 		firei2c_reg_write(sc, FIREI2C_CTRL, ctrl & ~FIREI2C_CTRL_IEN);
    517  1.1  jdc 		cv_signal(&sc->sc_cv);
    518  1.1  jdc 		mutex_exit(&sc->sc_mutex);
    519  1.1  jdc 		return 1;	/* Handled */
    520  1.1  jdc 	}
    521  1.1  jdc 	mutex_exit(&sc->sc_mutex);
    522  1.1  jdc 	return 0;
    523  1.1  jdc }
    524  1.1  jdc 
    525  1.1  jdc static uint8_t
    526  1.1  jdc firei2c_reg_read(struct firei2c_softc *sc, bus_size_t reg)
    527  1.1  jdc {
    528  1.1  jdc 	uint32_t val;
    529  1.1  jdc 	bus_space_barrier(sc->sc_bustag, sc->sc_regh, reg, 8,
    530  1.1  jdc 	    BUS_SPACE_BARRIER_READ);
    531  1.1  jdc 	val = bus_space_read_8(sc->sc_bustag, sc->sc_regh, reg);
    532  1.1  jdc 	return val & 0xff;
    533  1.1  jdc }
    534  1.1  jdc 
    535  1.1  jdc static void
    536  1.1  jdc firei2c_reg_write(struct firei2c_softc *sc, bus_size_t reg, uint8_t val)
    537  1.1  jdc {
    538  1.1  jdc 	bus_space_write_8(sc->sc_bustag, sc->sc_regh, reg, val);
    539  1.1  jdc 	bus_space_barrier(sc->sc_bustag, sc->sc_regh, reg, 8,
    540  1.1  jdc 	    BUS_SPACE_BARRIER_WRITE);
    541  1.1  jdc }
    542