Home | History | Annotate | Line # | Download | only in dev
      1  1.5       jdc /* $NetBSD: fire_i2c.c,v 1.5 2026/09/25 07:16:27 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.5       jdc __KERNEL_RCSID(0, "$NetBSD: fire_i2c.c,v 1.5 2026/09/25 07:16:27 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.5       jdc #include <sys/kernel.h>
     40  1.1       jdc #include <sys/mutex.h>
     41  1.1       jdc 
     42  1.1       jdc #include <machine/autoconf.h>
     43  1.1       jdc #include <machine/openfirm.h>
     44  1.1       jdc 
     45  1.5       jdc #include <dev/pci/pcivar.h>
     46  1.5       jdc 
     47  1.1       jdc #include <dev/i2c/i2cvar.h>
     48  1.5       jdc #include <sparc64/dev/fire_i2creg.h>
     49  1.5       jdc #include <sparc64/dev/iommureg.h>
     50  1.5       jdc #include <sparc64/dev/iommuvar.h>
     51  1.5       jdc #include <sparc64/dev/pyrovar.h>
     52  1.5       jdc 
     53  1.5       jdc #include "ioconf.h"
     54  1.1       jdc 
     55  1.1       jdc #define FIREI2C_DEBUG 0
     56  1.1       jdc #if FIREI2C_DEBUG > 0
     57  1.5       jdc int dlvl = 1;		/* Set to 2 for verbose i2c ops output */
     58  1.5       jdc #define DPRINTF(n) if (dlvl >= n) printf
     59  1.1       jdc #else
     60  1.5       jdc #define DPRINTF(n) if (0) printf
     61  1.1       jdc #endif
     62  1.1       jdc 
     63  1.5       jdc #define FIREI2C_SCL_FREQ	100000	/* Target i2c clock frequency */
     64  1.5       jdc #define FIREI2C_OWN_ADDR	0x08	/* Our i2c slave address */
     65  1.1       jdc 
     66  1.5       jdc /* i2c clocks to match possible system clock frequencies (1/1, 1/2, 1/32) */
     67  1.1       jdc #define FIREI2C_CLK_FULL	0
     68  1.1       jdc #define FIREI2C_CLK_HALF	1
     69  1.1       jdc #define FIREI2C_CLK_TT		2
     70  1.1       jdc #define FIREI2C_CLK_LEN		3
     71  1.1       jdc 
     72  1.5       jdc /* i2c operations */
     73  1.5       jdc #define FIREI2C_OP_READ		0x01
     74  1.5       jdc #define FIREI2C_OP_WRITE	0x02
     75  1.5       jdc #define FIREI2C_OP_WR_RD	0x04
     76  1.5       jdc 
     77  1.5       jdc /* i2c stages */
     78  1.5       jdc #define FIREI2C_STAGE_IDLE	0x00
     79  1.5       jdc #define FIREI2C_STAGE_START	0x01
     80  1.5       jdc #define FIREI2C_STAGE_WR_ADDR	0x02
     81  1.5       jdc #define FIREI2C_STAGE_RE_ADDR	0x04
     82  1.5       jdc #define FIREI2C_STAGE_WRITE	0x08
     83  1.5       jdc #define FIREI2C_STAGE_REPSTART	0x10
     84  1.5       jdc #define FIREI2C_STAGE_READ	0x20
     85  1.5       jdc #define FIREI2C_STAGE_STOP	0x40
     86  1.5       jdc 
     87  1.5       jdc /* mainbus intr map/mask are only used for i2c interrupts, so put them here. */
     88  1.5       jdc struct mainbus_interrupt_map {
     89  1.5       jdc 	uint64_t paddr;		/* phys addr mask */
     90  1.5       jdc 	uint32_t intr;		/* interrupt mask */
     91  1.5       jdc 	int32_t cnode;		/* child node */
     92  1.5       jdc 	uint32_t cintr;		/* child interrupt */
     93  1.5       jdc } __packed;
     94  1.5       jdc 
     95  1.5       jdc struct mainbus_interrupt_map_mask {
     96  1.5       jdc 	uint64_t paddr;		/* phys addr mask */
     97  1.5       jdc 	uint32_t intr;		/* interrupt */
     98  1.5       jdc } __packed;
     99  1.5       jdc 
    100  1.1       jdc struct firei2c_softc {
    101  1.1       jdc 	device_t sc_dev;
    102  1.1       jdc 	bus_space_tag_t sc_bustag;
    103  1.1       jdc 	bus_space_handle_t sc_regh;
    104  1.1       jdc 	int sc_node;
    105  1.1       jdc 	void *sc_inth;
    106  1.5       jdc 
    107  1.5       jdc 	uint8_t sc_i2c_clks[FIREI2C_CLK_LEN];	/* Clocks for sys bus speeds */
    108  1.5       jdc 
    109  1.1       jdc 	struct i2c_controller sc_i2c;
    110  1.5       jdc 
    111  1.5       jdc 	kmutex_t sc_mutex;		/* Interrupt mutex ... */
    112  1.5       jdc 	kcondvar_t sc_cv;		/* ... and condvar */
    113  1.5       jdc 
    114  1.5       jdc 	int sc_op;			/* Operation to run */
    115  1.5       jdc 	int sc_stage;			/* Exec stage */
    116  1.5       jdc 	i2c_addr_t sc_target;		/* Saved exec args */
    117  1.5       jdc 	const u_int8_t *sc_cmdbuf;	/* ... */
    118  1.5       jdc 	size_t sc_cmdlen;		/* ... */
    119  1.5       jdc 	u_int8_t *sc_buf;		/* ... */
    120  1.5       jdc 	size_t sc_buflen;		/* ... */
    121  1.5       jdc 	int sc_i;			/* How far through buf */
    122  1.5       jdc 	int sc_err;			/* Error during transaction */
    123  1.5       jdc 
    124  1.1       jdc };
    125  1.1       jdc 
    126  1.1       jdc static int firei2c_match(device_t, cfdata_t, void *);
    127  1.1       jdc static void firei2c_attach(device_t, device_t, void *);
    128  1.5       jdc static void firei2c_intr_establish(struct firei2c_softc *,
    129  1.5       jdc     struct mainbus_attach_args *);
    130  1.1       jdc static uint8_t firei2c_clock(int);
    131  1.1       jdc static int firei2c_stop(struct firei2c_softc *);
    132  1.1       jdc static int firei2c_wait(struct firei2c_softc *, int);
    133  1.1       jdc int firei2c_exec(void *, i2c_op_t, i2c_addr_t, const void *,
    134  1.1       jdc     size_t, void *, size_t, int);
    135  1.1       jdc static int firei2c_write(struct firei2c_softc *, const uint8_t *, size_t,
    136  1.5       jdc     uint8_t *, size_t, int);
    137  1.5       jdc static int firei2c_read(struct firei2c_softc *, uint8_t *, size_t, int);
    138  1.1       jdc int firei2c_intr(void *);
    139  1.1       jdc static uint8_t firei2c_reg_read(struct firei2c_softc *, bus_size_t);
    140  1.1       jdc static void firei2c_reg_write(struct firei2c_softc *, bus_size_t, uint8_t);
    141  1.1       jdc 
    142  1.1       jdc CFATTACH_DECL_NEW(firei2c, sizeof(struct firei2c_softc),
    143  1.1       jdc 	firei2c_match, firei2c_attach, NULL, NULL);
    144  1.1       jdc 
    145  1.1       jdc static int
    146  1.1       jdc firei2c_match(device_t parent, cfdata_t cf, void *aux)
    147  1.1       jdc {
    148  1.1       jdc 	struct mainbus_attach_args *ma = aux;
    149  1.1       jdc 	char *compat;
    150  1.1       jdc 
    151  1.1       jdc 	if (strcmp(ma->ma_name, "i2c"))
    152  1.1       jdc 		return 0;
    153  1.1       jdc 
    154  1.1       jdc 	compat = prom_getpropstring(ma->ma_node, "compatible");
    155  1.1       jdc 	if (!strcmp(compat, "fire-i2c"))
    156  1.1       jdc 		return 1;
    157  1.1       jdc 
    158  1.1       jdc 	return 0;
    159  1.1       jdc }
    160  1.1       jdc 
    161  1.1       jdc static void
    162  1.1       jdc firei2c_attach(device_t parent, device_t self, void *aux)
    163  1.1       jdc {
    164  1.1       jdc 	struct firei2c_softc *sc = device_private(self);
    165  1.1       jdc 	struct mainbus_attach_args *ma = aux;
    166  1.1       jdc 	int  sysclk;
    167  1.1       jdc 
    168  1.1       jdc 	sc->sc_bustag = ma->ma_bustag;
    169  1.1       jdc 	sc->sc_node = ma->ma_node;
    170  1.1       jdc 	sc->sc_dev = self;
    171  1.1       jdc 
    172  1.1       jdc 	if (ma->ma_nreg != 1) {
    173  1.1       jdc 		aprint_error(": register count error (%d != 1)\n",
    174  1.1       jdc 		    ma->ma_nreg);
    175  1.1       jdc 		return;
    176  1.1       jdc 	}
    177  1.1       jdc 	if (ma->ma_reg[0].ur_len < FIREI2C_SRST) {
    178  1.4  nakayama 		aprint_error(": register length error (%" PRId64 " < %d\n",
    179  1.4  nakayama 		    ma->ma_reg[0].ur_len, FIREI2C_SRST);
    180  1.1       jdc 		return;
    181  1.1       jdc 	}
    182  1.1       jdc 
    183  1.1       jdc 	if (bus_space_map(sc->sc_bustag, ma->ma_reg[0].ur_paddr,
    184  1.1       jdc 	    ma->ma_reg[0].ur_len, 0, &sc->sc_regh)) {
    185  1.1       jdc 		aprint_error(": failed to map registers\n");
    186  1.1       jdc 		return;
    187  1.1       jdc 	}
    188  1.1       jdc 
    189  1.1       jdc 	aprint_normal(": addr %" PRIx64 ": Fire/MI2C i2c controller\n",
    190  1.1       jdc 	    ma->ma_reg[0].ur_paddr);
    191  1.1       jdc 
    192  1.5       jdc 	firei2c_intr_establish(sc, ma);
    193  1.5       jdc 
    194  1.5       jdc 	/* Calculate clock, software reset, set our address */
    195  1.1       jdc 	sysclk = prom_getpropint(findroot(), "clock-frequency", 0);
    196  1.1       jdc 	sc->sc_i2c_clks[FIREI2C_CLK_FULL] = firei2c_clock(sysclk);
    197  1.1       jdc 	sc->sc_i2c_clks[FIREI2C_CLK_HALF] = firei2c_clock(sysclk / 2);
    198  1.1       jdc 	sc->sc_i2c_clks[FIREI2C_CLK_TT] = firei2c_clock(sysclk / 32);
    199  1.1       jdc 	firei2c_reg_write(sc, FIREI2C_SRST, FIREI2C_SRST_RST);
    200  1.1       jdc 	delay(1000);
    201  1.1       jdc 	firei2c_reg_write(sc, FIREI2C_CCR, sc->sc_i2c_clks[FIREI2C_CLK_FULL]);
    202  1.1       jdc 	firei2c_reg_write(sc, FIREI2C_ADDR,
    203  1.1       jdc 	    FIREI2C_OWN_ADDR << FIREI2C_ADDR_SHIFT);
    204  1.1       jdc 
    205  1.1       jdc 	/* i2c setup */
    206  1.1       jdc 	iic_tag_init(&sc->sc_i2c);
    207  1.1       jdc 	sc->sc_i2c.ic_cookie = sc;
    208  1.1       jdc 	sc->sc_i2c.ic_exec = firei2c_exec;
    209  1.1       jdc 
    210  1.1       jdc 	/* Synchronisation between exec and intr */
    211  1.1       jdc 	mutex_init(&sc->sc_mutex, MUTEX_DEFAULT, IPL_VM);
    212  1.1       jdc 	cv_init(&sc->sc_cv, "firei2c");
    213  1.5       jdc 	sc->sc_stage = FIREI2C_STAGE_IDLE;
    214  1.1       jdc 
    215  1.1       jdc 	iicbus_attach(sc->sc_dev, &sc->sc_i2c);
    216  1.1       jdc 	return;
    217  1.1       jdc }
    218  1.1       jdc 
    219  1.1       jdc /*
    220  1.5       jdc  * Use the mainbus (root) interrupt map/mask to find our interrupt number
    221  1.5       jdc  * (ino 60 or 61) and pyro leaf.
    222  1.5       jdc  * Both i2c interrupts must go to the same pyro leaf, but we assume that
    223  1.5       jdc  * OFW has set up the ino and the leaf mapping for us.
    224  1.5       jdc  */
    225  1.5       jdc #define IMASK_LEN 3
    226  1.5       jdc #define IMAP_LEN 10
    227  1.5       jdc static void
    228  1.5       jdc firei2c_intr_establish(struct firei2c_softc *sc,
    229  1.5       jdc     struct mainbus_attach_args *ma)
    230  1.5       jdc {
    231  1.5       jdc 	struct mainbus_interrupt_map *mb_imap;
    232  1.5       jdc 	struct mainbus_interrupt_map_mask *mb_imask;
    233  1.5       jdc 	struct pyro_softc *psc = NULL;
    234  1.5       jdc 	int64_t paddr;
    235  1.5       jdc 	u_int intr;
    236  1.5       jdc 	int ihandle, root, size, i;
    237  1.5       jdc 
    238  1.5       jdc 	sc->sc_inth = NULL;	/* Default */
    239  1.5       jdc 	ihandle = 0;
    240  1.5       jdc 
    241  1.5       jdc 	/* Find our mapped interrupt number */
    242  1.5       jdc 	root = findroot();
    243  1.5       jdc 	mb_imask = NULL;
    244  1.5       jdc 	if (prom_getprop(root, "interrupt-map-mask",
    245  1.5       jdc 	    sizeof(int32_t), &size, (void **) &mb_imask) ||
    246  1.5       jdc 	    size != IMASK_LEN) {
    247  1.5       jdc 		aprint_error(": no interrupt-map-mask\n");
    248  1.5       jdc 		return;
    249  1.5       jdc 	}
    250  1.5       jdc 
    251  1.5       jdc 	mb_imap = NULL;
    252  1.5       jdc 	if (prom_getprop(root, "interrupt-map",
    253  1.5       jdc 	    sizeof(int32_t), &size, (void **) &mb_imap) ||
    254  1.5       jdc 	    size != IMAP_LEN) {
    255  1.5       jdc 		aprint_error(": no interrupt-map\n");
    256  1.5       jdc 		return;
    257  1.5       jdc 	}
    258  1.5       jdc 
    259  1.5       jdc 	intr = ma->ma_interrupts[0] && mb_imask->intr;
    260  1.5       jdc 	DPRINTF(1)("%s: intr %x masked to %x\n",
    261  1.5       jdc 	    device_xname(sc->sc_dev), ma->ma_interrupts[0], intr);
    262  1.5       jdc 	paddr = ma->ma_reg[0].ur_paddr & mb_imask->paddr;
    263  1.5       jdc 	DPRINTF(1)("%s: reg 0x%" PRIx64 " masked to 0x%" PRIx64 "\n",
    264  1.5       jdc 	    device_xname(sc->sc_dev), ma->ma_reg[0].ur_paddr, paddr);
    265  1.5       jdc 	for (i = 0; i < 2; i++) {
    266  1.5       jdc 		DPRINTF(1)("%s: checking paddr 0x%" PRIx64 ", intr %x\n",
    267  1.5       jdc 		    device_xname(sc->sc_dev), mb_imap->paddr, mb_imap->intr);
    268  1.5       jdc 		if (paddr == mb_imap->paddr && intr == mb_imap->intr) {
    269  1.5       jdc 			ihandle = mb_imap->cintr;
    270  1.5       jdc 			DPRINTF(1)("%s: found cintr %d, cnode 0x%x\n",
    271  1.5       jdc 			    device_xname(sc->sc_dev), ihandle, mb_imap->cnode);
    272  1.5       jdc 			break;
    273  1.5       jdc 		}
    274  1.5       jdc 		mb_imap++;
    275  1.5       jdc 	}
    276  1.5       jdc 	if (ihandle == 0) {
    277  1.5       jdc 		aprint_error(": failed to match interrupt\n");
    278  1.5       jdc 		return;
    279  1.5       jdc 	}
    280  1.5       jdc 
    281  1.5       jdc 	/* Find the pyro leaf with the matching cnode ) */
    282  1.5       jdc 	for (i = 0; i < pyro_cd.cd_ndevs; i++) {
    283  1.5       jdc 		device_t dt = device_lookup(&pyro_cd, i);
    284  1.5       jdc 		psc = device_private(dt);
    285  1.5       jdc 		if (psc && psc->sc_node == mb_imap->cnode) {
    286  1.5       jdc 			DPRINTF(1)("%s: matched pyro %d (0x%x)\n",
    287  1.5       jdc 			    device_xname(sc->sc_dev), i, psc->sc_node);
    288  1.5       jdc 			ihandle |= psc->sc_ign;
    289  1.5       jdc 			break;
    290  1.5       jdc 		}
    291  1.5       jdc 	}
    292  1.5       jdc 	if (psc == NULL) {
    293  1.5       jdc 		aprint_error(": failed to match pyro leaf\n");
    294  1.5       jdc 		return;
    295  1.5       jdc 	}
    296  1.5       jdc 
    297  1.5       jdc 	sc->sc_inth = psc->intr_establish_sc(psc,
    298  1.5       jdc 	    ihandle, IPL_BIO, firei2c_intr, sc, NULL);
    299  1.5       jdc 
    300  1.5       jdc 	if (sc->sc_inth != NULL) {
    301  1.5       jdc 		aprint_normal_dev(sc->sc_dev,
    302  1.5       jdc 		    "interrupting at ivec %x on pyro%d\n", ihandle, i);
    303  1.5       jdc 	}
    304  1.5       jdc 
    305  1.5       jdc 	return;
    306  1.5       jdc }
    307  1.5       jdc 
    308  1.5       jdc /*
    309  1.1       jdc  * Sampling frequency: input clock divided by 2^N (N is bits 0:2)
    310  1.1       jdc  * SCL frequency: sampling frequency divided by (M + 1) * 10 (bits 3:6)
    311  1.1       jdc  * i2c SCL is max 100kHz, so find the closest frequency at or below that.
    312  1.1       jdc  *
    313  1.1       jdc  * If the system (JBus) clock frequency changes, we must change our clock.
    314  1.1       jdc  * If increasing: after the JBus change, if decreasing: before the change.
    315  1.1       jdc  * This is to avoid running the i2c clock faster than the specification.
    316  1.1       jdc  */
    317  1.1       jdc static uint8_t
    318  1.1       jdc firei2c_clock(int sysclk)
    319  1.1       jdc {
    320  1.1       jdc 	int p, f, best_p, best_f;
    321  1.1       jdc 	uint32_t sample, scl;
    322  1.1       jdc 	uint32_t min = FIREI2C_SCL_FREQ;
    323  1.1       jdc 	uint8_t clkval;
    324  1.1       jdc 
    325  1.1       jdc 	best_p = 0;
    326  1.1       jdc 	best_f = 0;
    327  1.1       jdc 	for (p = 0; p <= FIREI2C_CCR_POW2_MAX; p++) {
    328  1.1       jdc 		if (p)
    329  1.1       jdc 			sample = sysclk / (2 << (p - 1));
    330  1.1       jdc 		else
    331  1.1       jdc 			sample = sysclk;
    332  1.1       jdc 		for (f = 0; f <= FIREI2C_CCR_FACT_MAX; f++) {
    333  1.1       jdc 			scl = sample / ((f + 1) * 10);
    334  1.1       jdc 			if (scl <= FIREI2C_SCL_FREQ) {
    335  1.1       jdc 				if (FIREI2C_SCL_FREQ - scl < min) {
    336  1.1       jdc 					best_p = p;
    337  1.1       jdc 					best_f = f;
    338  1.1       jdc 					min = FIREI2C_SCL_FREQ - scl;
    339  1.1       jdc 				}
    340  1.1       jdc 				break;	/* Already at or below SCL_FREQ */
    341  1.1       jdc 			}
    342  1.1       jdc 		}
    343  1.1       jdc 		if (!min)	/* Exactly SCL_FREQ */
    344  1.1       jdc 			break;
    345  1.1       jdc 	}
    346  1.1       jdc 	clkval = best_p + (best_f << FIREI2C_CCR_FACT_SHIFT);
    347  1.1       jdc 	return clkval;
    348  1.1       jdc }
    349  1.1       jdc 
    350  1.1       jdc /* No interrupts for stop, so wait for idle */
    351  1.1       jdc static int
    352  1.1       jdc firei2c_stop(struct firei2c_softc *sc)
    353  1.1       jdc {
    354  1.1       jdc 	int i;
    355  1.1       jdc 	uint8_t ctrl, val;
    356  1.1       jdc 
    357  1.1       jdc 	ctrl = FIREI2C_CTRL_ENAB | FIREI2C_CTRL_STP;
    358  1.1       jdc 	firei2c_reg_write(sc, FIREI2C_CTRL, ctrl);
    359  1.1       jdc 	for (i = 0; i < 500; i++) {
    360  1.1       jdc 		val = firei2c_reg_read(sc, FIREI2C_STAT);
    361  1.5       jdc 		if (val == FIREI2C_STAT_IDLE) {
    362  1.5       jdc 			mutex_enter(&sc->sc_mutex);
    363  1.5       jdc 			sc->sc_stage = FIREI2C_STAGE_IDLE;
    364  1.5       jdc 			mutex_exit(&sc->sc_mutex);
    365  1.1       jdc 			return 0;
    366  1.5       jdc 		}
    367  1.1       jdc 		delay(1000);
    368  1.1       jdc 	}
    369  1.1       jdc 	/* Clear the interrupt flag if we timed out */
    370  1.1       jdc 	ctrl = FIREI2C_CTRL_ENAB;
    371  1.1       jdc 	firei2c_reg_write(sc, FIREI2C_CTRL, ctrl);
    372  1.5       jdc 	/* Set the stage to idle, even for timeout */
    373  1.5       jdc 	mutex_enter(&sc->sc_mutex);
    374  1.5       jdc 	sc->sc_stage = FIREI2C_STAGE_IDLE;
    375  1.5       jdc 	mutex_exit(&sc->sc_mutex);
    376  1.1       jdc 	return 1;
    377  1.1       jdc }
    378  1.1       jdc 
    379  1.1       jdc 
    380  1.1       jdc static int
    381  1.1       jdc firei2c_wait(struct firei2c_softc *sc, int flags)
    382  1.1       jdc {
    383  1.1       jdc 	volatile uint8_t ctrl;
    384  1.1       jdc 	int i;
    385  1.1       jdc 
    386  1.5       jdc 	for (i = 0; i < 500; i++) {
    387  1.5       jdc 		ctrl = firei2c_reg_read(sc, FIREI2C_CTRL);
    388  1.5       jdc 		if (ctrl & FIREI2C_CTRL_IFLG)
    389  1.5       jdc 			return 0;
    390  1.5       jdc 		delay(1000);
    391  1.1       jdc 	}
    392  1.5       jdc 	return 1;
    393  1.1       jdc }
    394  1.1       jdc 
    395  1.1       jdc /*
    396  1.1       jdc  * Flow for a "simple" read/write:
    397  1.1       jdc  *   1.  Send start
    398  1.1       jdc  *   2.  Send addr + R or W
    399  1.1       jdc  *   3.  Receive ACK
    400  1.1       jdc  *   4.  (nothing)
    401  1.1       jdc  *   5.  (nothing)
    402  1.1       jdc  *   6R. Receive data			6W.  Send data
    403  1.1       jdc  *   7R. Send ACK or NAK		7W.  Receive ACK or NAK
    404  1.1       jdc  *       either receive more (6R) or	     either write more (6W) or
    405  1.1       jdc  *   8.  Send stop
    406  1.5       jdc  *
    407  1.1       jdc  * Flow for read/write following a "register" write:
    408  1.1       jdc  *   1.  Send start
    409  1.1       jdc  *   2.  Send addr + W
    410  1.1       jdc  *   3.  Receive ACK
    411  1.1       jdc  *   4.  Send register
    412  1.1       jdc  *   5R. Send repeat start + addr + R	5W.  (nothing to do)
    413  1.1       jdc  *   6R. Receive data			6W.  Send data
    414  1.1       jdc  *   7R. Send ACK or NAK		7W.  Receive ACK or NAK
    415  1.1       jdc  *       either receive more (6R) or	     either write more (6W) or
    416  1.1       jdc  *   8.  Send stop
    417  1.1       jdc  *
    418  1.1       jdc  * After each step, we receive an interrupt notifying us of the result.
    419  1.5       jdc  * We clear the interrupt flag, check the status, and set up the next step.
    420  1.5       jdc  * If we're polling, we check the flag in a loop instead.
    421  1.1       jdc  */
    422  1.1       jdc int
    423  1.1       jdc firei2c_exec(void *arg, i2c_op_t op, i2c_addr_t addr, const void *cmd,
    424  1.1       jdc     size_t cmdlen, void *vbuf, size_t buflen, int flags)
    425  1.1       jdc {
    426  1.1       jdc 	struct firei2c_softc *sc = arg;
    427  1.5       jdc 	const uint8_t *cmdbuf = cmd;
    428  1.1       jdc 	uint8_t *buf = vbuf;
    429  1.1       jdc 	uint8_t ctrl, val, ack, nack;
    430  1.5       jdc 	unsigned deadline, rem;
    431  1.1       jdc 	int err;
    432  1.1       jdc 
    433  1.5       jdc 	DPRINTF(1)("%s: exec op: %d addr: 0x%x "
    434  1.5       jdc 	    "cmdlen: %d buflen: %d flags 0x%x, intr %s, poll %s\n",
    435  1.1       jdc 	    device_xname(sc->sc_dev), op, addr,
    436  1.5       jdc 	    (int) cmdlen, (int) buflen, flags,
    437  1.5       jdc 	    sc->sc_inth == NULL ? "no" : "yes",
    438  1.5       jdc 	    flags & I2C_F_POLL ? "yes" : "no");
    439  1.1       jdc 	val = firei2c_reg_read(sc, FIREI2C_STAT);
    440  1.1       jdc 	if (val != FIREI2C_STAT_IDLE) {
    441  1.1       jdc 		/* Try sending stop */
    442  1.5       jdc 		DPRINTF(1)("%s: not idle, sending stop\n",
    443  1.1       jdc 		    device_xname(sc->sc_dev));
    444  1.1       jdc 		err = firei2c_stop(sc);
    445  1.1       jdc 		if (err) {
    446  1.1       jdc 			printf("%s: not idle (0x%02x)\n",
    447  1.1       jdc 			    device_xname(sc->sc_dev), val);
    448  1.1       jdc 			return 1;
    449  1.1       jdc 		}
    450  1.1       jdc 	}
    451  1.1       jdc 
    452  1.5       jdc 	/* Control defaults - bus enabled, interrupts enabled */
    453  1.5       jdc 	ctrl = FIREI2C_CTRL_ENAB;
    454  1.5       jdc 	if (sc->sc_inth != NULL && !(flags & I2C_F_POLL)) {
    455  1.5       jdc 		ctrl |= FIREI2C_CTRL_IEN;
    456  1.5       jdc 		sc->sc_target = addr;
    457  1.5       jdc 		sc->sc_cmdbuf = cmdbuf;
    458  1.5       jdc 		sc->sc_cmdlen = cmdlen;
    459  1.5       jdc 		sc->sc_buf = buf;
    460  1.5       jdc 		sc->sc_buflen = buflen;
    461  1.5       jdc 		sc->sc_i = 0;
    462  1.5       jdc 		sc->sc_err = 0;
    463  1.5       jdc 		if (I2C_OP_READ_P(op))
    464  1.5       jdc 			if (cmdlen > 0)
    465  1.5       jdc 				sc->sc_op = FIREI2C_OP_WR_RD;
    466  1.5       jdc 			else
    467  1.5       jdc 				sc->sc_op = FIREI2C_OP_READ;
    468  1.5       jdc 		else
    469  1.5       jdc 			sc->sc_op = FIREI2C_OP_WRITE;
    470  1.5       jdc 		mutex_enter(&sc->sc_mutex);
    471  1.5       jdc 		sc->sc_stage = FIREI2C_STAGE_START;
    472  1.5       jdc 		mutex_exit(&sc->sc_mutex);
    473  1.5       jdc 	}
    474  1.5       jdc 
    475  1.1       jdc 	/* Send start */
    476  1.5       jdc 	firei2c_reg_write(sc, FIREI2C_CTRL, ctrl | FIREI2C_CTRL_STA);
    477  1.5       jdc 
    478  1.5       jdc 	/* Interrupt-driven */
    479  1.5       jdc 	if (sc->sc_inth != NULL && !(flags & I2C_F_POLL)) {
    480  1.5       jdc 		/* Wait for the transfer to complete (stop). */
    481  1.5       jdc 		deadline = getticks() +
    482  1.5       jdc 		    /*timeout*/ hz / 10 + 10 * (cmdlen + buflen);
    483  1.5       jdc 		mutex_enter(&sc->sc_mutex);
    484  1.5       jdc 		while (sc->sc_stage != FIREI2C_STAGE_STOP) {
    485  1.5       jdc 			rem = deadline - getticks();
    486  1.5       jdc 			if (!rem || rem >= INT_MAX) {
    487  1.5       jdc 				printf("%s: intr timeout\n",
    488  1.5       jdc 				    device_xname(sc->sc_dev));
    489  1.5       jdc 				sc->sc_stage = FIREI2C_STAGE_STOP;
    490  1.5       jdc 				err = sc->sc_err | 1;
    491  1.5       jdc 				break;
    492  1.5       jdc 			}
    493  1.5       jdc 			cv_timedwait(&sc->sc_cv, &sc->sc_mutex, rem);
    494  1.5       jdc 		}
    495  1.5       jdc 		mutex_exit(&sc->sc_mutex);
    496  1.5       jdc 		err = sc->sc_err;
    497  1.5       jdc 		goto stop;
    498  1.5       jdc 	}
    499  1.5       jdc 
    500  1.5       jdc 	/*
    501  1.5       jdc 	 * If we are writing, write addr, cmd, buf.
    502  1.5       jdc 	 * If we are reading, either:
    503  1.5       jdc 	 *   write addr, cmd, repeat-start, then read addr to buf, or:
    504  1.5       jdc 	 *   read addr to buf.
    505  1.5       jdc 	 * Send stop
    506  1.5       jdc 	 */
    507  1.1       jdc 	err = firei2c_wait(sc, flags);
    508  1.1       jdc 	val = firei2c_reg_read(sc, FIREI2C_STAT);
    509  1.1       jdc 	if (err) {
    510  1.1       jdc 		printf("%s: start timeout 0x%x\n",
    511  1.1       jdc 		    device_xname(sc->sc_dev), val);
    512  1.1       jdc 		goto stop;
    513  1.1       jdc 	}
    514  1.1       jdc 	if (val != FIREI2C_STAT_STA) {
    515  1.1       jdc 		printf("%s: start error 0x%x\n",
    516  1.1       jdc 		    device_xname(sc->sc_dev), val);
    517  1.1       jdc 		err = 1;
    518  1.1       jdc 		goto stop;
    519  1.1       jdc 	}
    520  1.1       jdc 
    521  1.5       jdc 	/* Address + r/w in data, then send ctrl */
    522  1.5       jdc 	val = addr << FIREI2C_DATA_SHIFT;
    523  1.1       jdc 	if (I2C_OP_WRITE_P(op) || cmdlen > 0) {
    524  1.1       jdc 		ack = FIREI2C_STAT_AWR_ACK;
    525  1.1       jdc 		nack = FIREI2C_STAT_AWR_NAK;
    526  1.1       jdc 	} else {
    527  1.1       jdc 		val |= 0x01;
    528  1.1       jdc 		ack = FIREI2C_STAT_ARE_ACK;
    529  1.1       jdc 		nack = FIREI2C_STAT_ARE_NAK;
    530  1.1       jdc 	}
    531  1.1       jdc 	firei2c_reg_write(sc, FIREI2C_DATA, val);
    532  1.1       jdc 	firei2c_reg_write(sc, FIREI2C_CTRL, ctrl);
    533  1.1       jdc 	err = firei2c_wait(sc, flags);
    534  1.1       jdc 	val = firei2c_reg_read(sc, FIREI2C_STAT);
    535  1.1       jdc 	if (err) {
    536  1.1       jdc 		printf("%s: addr timeout 0x%x\n",
    537  1.1       jdc 		    device_xname(sc->sc_dev), val);
    538  1.1       jdc 		goto stop;
    539  1.1       jdc 	}
    540  1.1       jdc 	if (val != ack) {
    541  1.1       jdc 		if (val != nack)	/* Don't print for NACK */
    542  1.1       jdc 			printf("%s: addr error 0x%x\n",
    543  1.1       jdc 			    device_xname(sc->sc_dev), val);
    544  1.1       jdc 		err = 1;
    545  1.1       jdc 		goto stop;
    546  1.1       jdc 	}
    547  1.1       jdc 
    548  1.1       jdc 	err = 0;
    549  1.1       jdc 	if (I2C_OP_READ_P(op)) {
    550  1.1       jdc 		if (cmdlen > 0) {
    551  1.1       jdc 			/* Write register */
    552  1.1       jdc 			err = firei2c_write(sc, cmd, cmdlen,
    553  1.5       jdc 			    NULL, 0, flags);
    554  1.1       jdc 			if (err)
    555  1.1       jdc 				goto stop;
    556  1.1       jdc 
    557  1.1       jdc 			/* Send repeat start */
    558  1.5       jdc 			firei2c_reg_write(sc, FIREI2C_CTRL,
    559  1.5       jdc 			    ctrl | FIREI2C_CTRL_STA);
    560  1.1       jdc 			err = firei2c_wait(sc, flags);
    561  1.1       jdc 			val = firei2c_reg_read(sc, FIREI2C_STAT);
    562  1.1       jdc 			if (err) {
    563  1.1       jdc 				printf("%s: repeat start timeout 0x%x\n",
    564  1.1       jdc 				    device_xname(sc->sc_dev), val);
    565  1.1       jdc 				goto stop;
    566  1.1       jdc 			}
    567  1.1       jdc 			if (val != FIREI2C_STAT_REPSTA) {
    568  1.1       jdc 				printf("%s: repeat start error 0x%x\n",
    569  1.1       jdc 				    device_xname(sc->sc_dev), val);
    570  1.1       jdc 				err = 1;
    571  1.1       jdc 				goto stop;
    572  1.1       jdc 			}
    573  1.1       jdc 
    574  1.5       jdc 			/* Address + r in data, then send ctrl */
    575  1.5       jdc 			val = addr << FIREI2C_DATA_SHIFT;
    576  1.1       jdc 			val |= 0x01;
    577  1.1       jdc 			ack = FIREI2C_STAT_ARE_ACK;
    578  1.1       jdc 			nack = FIREI2C_STAT_ARE_NAK;
    579  1.1       jdc 			firei2c_reg_write(sc, FIREI2C_DATA, val);
    580  1.1       jdc 			firei2c_reg_write(sc, FIREI2C_CTRL, ctrl);
    581  1.1       jdc 			err = firei2c_wait(sc, flags);
    582  1.1       jdc 			val = firei2c_reg_read(sc, FIREI2C_STAT);
    583  1.1       jdc 			if (err) {
    584  1.1       jdc 				printf("%s: addr timeout 0x%x\n",
    585  1.1       jdc 				    device_xname(sc->sc_dev), val);
    586  1.1       jdc 				goto stop;
    587  1.1       jdc 			}
    588  1.1       jdc 			if (val != ack) {
    589  1.1       jdc 				if (val != nack)
    590  1.1       jdc 					printf("%s: addr error 0x%x\n",
    591  1.1       jdc 					    device_xname(sc->sc_dev), val);
    592  1.1       jdc 				err = 1;
    593  1.1       jdc 				goto stop;
    594  1.1       jdc 			}
    595  1.1       jdc 		}
    596  1.1       jdc 
    597  1.1       jdc 		/* Read data */
    598  1.5       jdc 		err = firei2c_read(sc, buf, buflen, flags);
    599  1.1       jdc 	} else
    600  1.1       jdc 		/* Write data or register + data */
    601  1.5       jdc 		err = firei2c_write(sc, cmd, cmdlen, buf, buflen, flags);
    602  1.1       jdc 
    603  1.1       jdc stop:
    604  1.1       jdc 	err |= firei2c_stop(sc);
    605  1.1       jdc 
    606  1.1       jdc 	return err;
    607  1.1       jdc }
    608  1.1       jdc 
    609  1.1       jdc static int
    610  1.1       jdc firei2c_write(struct firei2c_softc *sc, const uint8_t *cmd, size_t cmdlen,
    611  1.5       jdc     uint8_t *buf, size_t buflen, int flags)
    612  1.1       jdc {
    613  1.5       jdc 	uint8_t ctrl, val;
    614  1.1       jdc 	int i, err;
    615  1.1       jdc 
    616  1.5       jdc 	DPRINTF(2)("%s: write %ld\n",
    617  1.5       jdc 	    device_xname(sc->sc_dev), cmdlen + buflen);
    618  1.5       jdc 	ctrl = FIREI2C_CTRL_ENAB;
    619  1.1       jdc 	for (i = 0; i < cmdlen + buflen; i++) {
    620  1.5       jdc 		/* Bytes in data, then send ctrl */
    621  1.1       jdc 		if (i < cmdlen)
    622  1.1       jdc 			val = cmd[i];
    623  1.1       jdc 		else
    624  1.1       jdc 			val = buf[i - cmdlen];
    625  1.1       jdc 		firei2c_reg_write(sc, FIREI2C_DATA, val);
    626  1.1       jdc 		firei2c_reg_write(sc, FIREI2C_CTRL, ctrl);
    627  1.1       jdc 		err = firei2c_wait(sc, flags);
    628  1.1       jdc 		val = firei2c_reg_read(sc, FIREI2C_STAT);
    629  1.1       jdc 		if (err) {
    630  1.1       jdc 			printf("%s: write timeout 0x%x\n",
    631  1.1       jdc 			    device_xname(sc->sc_dev), val);
    632  1.1       jdc 			return 1;
    633  1.1       jdc 		}
    634  1.1       jdc 		if (val != FIREI2C_STAT_DAT_ACK) {
    635  1.1       jdc 			if (val != FIREI2C_STAT_DAT_NAK)
    636  1.1       jdc 				printf("%s: write error 0x%x\n",
    637  1.1       jdc 				    device_xname(sc->sc_dev), val);
    638  1.1       jdc 			return 1;
    639  1.1       jdc 		}
    640  1.1       jdc 
    641  1.1       jdc 	}
    642  1.1       jdc 	return 0;
    643  1.1       jdc }
    644  1.1       jdc 
    645  1.1       jdc static int
    646  1.5       jdc firei2c_read(struct firei2c_softc *sc, uint8_t *buf, size_t buflen, int flags)
    647  1.1       jdc {
    648  1.5       jdc 	uint8_t ctrl, val, ack;
    649  1.1       jdc 	int i, err;
    650  1.1       jdc 
    651  1.5       jdc 	DPRINTF(2)("%s: read %ld\n", device_xname(sc->sc_dev), buflen);
    652  1.1       jdc 	for (i = 0; i < buflen; i++) {
    653  1.1       jdc 		/* Send ACK on all but last byte */
    654  1.1       jdc 		if (i < buflen - 1) {
    655  1.5       jdc 			ctrl = FIREI2C_CTRL_ENAB | FIREI2C_CTRL_AAK;
    656  1.1       jdc 			ack = FIREI2C_STAT_MDAT_ACK;
    657  1.1       jdc 		} else {
    658  1.5       jdc 			ctrl = FIREI2C_CTRL_ENAB;
    659  1.1       jdc 			ack = FIREI2C_STAT_MDAT_NAK;
    660  1.1       jdc 		}
    661  1.5       jdc 		/* Send ctrl, then bytes in data */
    662  1.5       jdc 		firei2c_reg_write(sc, FIREI2C_CTRL, ctrl);
    663  1.1       jdc 		err = firei2c_wait(sc, flags);
    664  1.1       jdc 		val = firei2c_reg_read(sc, FIREI2C_STAT);
    665  1.1       jdc 		if (err) {
    666  1.1       jdc 			printf("%s: read timeout 0x%x\n",
    667  1.1       jdc 			    device_xname(sc->sc_dev), val);
    668  1.1       jdc 			return 1;
    669  1.1       jdc 		}
    670  1.1       jdc 		if (val != ack) {
    671  1.1       jdc 			printf("%s: read error 0x%x\n",
    672  1.1       jdc 			    device_xname(sc->sc_dev), val);
    673  1.1       jdc 			return 1;
    674  1.1       jdc 		}
    675  1.1       jdc 		buf[i] = firei2c_reg_read(sc, FIREI2C_DATA);
    676  1.1       jdc 	}
    677  1.1       jdc 	return 0;
    678  1.1       jdc }
    679  1.1       jdc 
    680  1.5       jdc /*
    681  1.5       jdc  * When we receive an interrupt, check the status versus the step
    682  1.5       jdc  * and set up the next stage.
    683  1.5       jdc  * See the comments before firei2c_exec() for the list of steps.
    684  1.5       jdc  */
    685  1.1       jdc int
    686  1.1       jdc firei2c_intr(void *arg)
    687  1.1       jdc {
    688  1.1       jdc 	struct firei2c_softc *sc = arg;
    689  1.5       jdc 	uint8_t ctrl, val;
    690  1.1       jdc 
    691  1.1       jdc 	mutex_enter(&sc->sc_mutex);
    692  1.1       jdc 	ctrl = firei2c_reg_read(sc, FIREI2C_CTRL);
    693  1.1       jdc 	if (ctrl & FIREI2C_CTRL_IFLG) {
    694  1.1       jdc 		/* Disable interrupts */
    695  1.1       jdc 		firei2c_reg_write(sc, FIREI2C_CTRL, ctrl & ~FIREI2C_CTRL_IEN);
    696  1.5       jdc 	}
    697  1.5       jdc 
    698  1.5       jdc 	if (sc->sc_stage == FIREI2C_STAGE_IDLE) {
    699  1.5       jdc 		DPRINTF(1)("%s: intr and idle\n", device_xname(sc->sc_dev));
    700  1.5       jdc 		mutex_exit(&sc->sc_mutex);
    701  1.5       jdc 		return 0;
    702  1.5       jdc 	}
    703  1.5       jdc 
    704  1.5       jdc 	ctrl = FIREI2C_CTRL_ENAB | FIREI2C_CTRL_IEN;
    705  1.5       jdc 	val = firei2c_reg_read(sc, FIREI2C_STAT);
    706  1.5       jdc 
    707  1.5       jdc 	switch (sc->sc_stage) {
    708  1.5       jdc 	case FIREI2C_STAGE_START:
    709  1.5       jdc 		DPRINTF(2)("%s: intr start, op %x\n",
    710  1.5       jdc 		    device_xname(sc->sc_dev), sc->sc_op);
    711  1.5       jdc 		if (val != FIREI2C_STAT_STA) {
    712  1.5       jdc 			printf("%s: intr start error 0x%02x\n",
    713  1.5       jdc 			    device_xname(sc->sc_dev), val);
    714  1.5       jdc 			sc->sc_err = 1;
    715  1.5       jdc 			sc->sc_stage = FIREI2C_STAGE_STOP;
    716  1.5       jdc 			break;
    717  1.5       jdc 		}
    718  1.5       jdc 
    719  1.5       jdc 		/* Address + r/w in data, then send ctrl */
    720  1.5       jdc 		val = sc->sc_target << FIREI2C_DATA_SHIFT;
    721  1.5       jdc 		if (sc->sc_op == FIREI2C_OP_READ) {
    722  1.5       jdc 			val |= 0x01;
    723  1.5       jdc 			sc->sc_stage = FIREI2C_STAGE_RE_ADDR;
    724  1.5       jdc 		} else
    725  1.5       jdc 			sc->sc_stage = FIREI2C_STAGE_WR_ADDR;
    726  1.5       jdc 		firei2c_reg_write(sc, FIREI2C_DATA, val);
    727  1.5       jdc 		firei2c_reg_write(sc, FIREI2C_CTRL, ctrl);
    728  1.5       jdc 		break;
    729  1.5       jdc 
    730  1.5       jdc 	case FIREI2C_STAGE_WR_ADDR:
    731  1.5       jdc 		DPRINTF(2)("%s: intr addr(w) 0x%02x = 0x%02x\n",
    732  1.5       jdc 		    device_xname(sc->sc_dev), sc->sc_target, val);
    733  1.5       jdc 		if (val != FIREI2C_STAT_AWR_ACK) {
    734  1.5       jdc 			if (val != FIREI2C_STAT_AWR_NAK)
    735  1.5       jdc 				printf("%s: intr addr(w) error 0x%02x\n",
    736  1.5       jdc 				    device_xname(sc->sc_dev), val);
    737  1.5       jdc 			sc->sc_err = 1;
    738  1.5       jdc 			sc->sc_stage = FIREI2C_STAGE_STOP;
    739  1.5       jdc 			break;
    740  1.5       jdc 		}
    741  1.5       jdc 
    742  1.5       jdc 		sc->sc_stage = FIREI2C_STAGE_WRITE;
    743  1.5       jdc 		val = FIREI2C_STAT_DAT_ACK;	/* For write */
    744  1.5       jdc 		/* Fallthrough */
    745  1.5       jdc 
    746  1.5       jdc 	case FIREI2C_STAGE_WRITE:
    747  1.5       jdc 		DPRINTF(2)("%s: intr write 0x%02x = 0x%02x\n",
    748  1.5       jdc 		    device_xname(sc->sc_dev), sc->sc_target, val);
    749  1.5       jdc 		if (val != FIREI2C_STAT_DAT_ACK) {
    750  1.5       jdc 			if (val != FIREI2C_STAT_DAT_NAK)
    751  1.5       jdc 				printf("%s: intr write error 0x%02x\n",
    752  1.5       jdc 				    device_xname(sc->sc_dev), val);
    753  1.5       jdc 			sc->sc_err = 1;
    754  1.5       jdc 			sc->sc_stage = FIREI2C_STAGE_STOP;
    755  1.5       jdc 			break;
    756  1.5       jdc 		}
    757  1.5       jdc 
    758  1.5       jdc 		/* Start the write from cmd */
    759  1.5       jdc 		if (sc->sc_i < sc->sc_cmdlen) {
    760  1.5       jdc 			firei2c_reg_write(sc, FIREI2C_DATA,
    761  1.5       jdc 			    sc->sc_cmdbuf[sc->sc_i]);
    762  1.5       jdc 			firei2c_reg_write(sc, FIREI2C_CTRL, ctrl);
    763  1.5       jdc 			sc->sc_i++;
    764  1.5       jdc 			break;
    765  1.5       jdc 		}
    766  1.5       jdc 
    767  1.5       jdc 		/* If a read OP, switch with repeat start after writing cmd */
    768  1.5       jdc 		if (sc->sc_op == FIREI2C_OP_WR_RD) {
    769  1.5       jdc 			sc->sc_i = 0;
    770  1.5       jdc 			sc->sc_stage = FIREI2C_STAGE_REPSTART;
    771  1.5       jdc 			ctrl |= FIREI2C_CTRL_STA;
    772  1.5       jdc 			firei2c_reg_write(sc, FIREI2C_CTRL, ctrl);
    773  1.5       jdc 			break;
    774  1.5       jdc 		}
    775  1.5       jdc 
    776  1.5       jdc 		/* If a write OP, continue the write, now from buf */
    777  1.5       jdc 		if (sc->sc_i < sc->sc_cmdlen + sc->sc_buflen) {
    778  1.5       jdc 			firei2c_reg_write(sc, FIREI2C_DATA,
    779  1.5       jdc 			    sc->sc_buf[sc->sc_i - sc->sc_cmdlen]);
    780  1.5       jdc 			firei2c_reg_write(sc, FIREI2C_CTRL, ctrl);
    781  1.5       jdc 			sc->sc_i++;
    782  1.5       jdc 		} else {
    783  1.5       jdc 			sc->sc_stage = FIREI2C_STAGE_STOP;
    784  1.5       jdc 		}
    785  1.5       jdc 		break;
    786  1.5       jdc 
    787  1.5       jdc 	case FIREI2C_STAGE_REPSTART:
    788  1.5       jdc 		DPRINTF(2)("%s: intr repstart 0x%02x = 0x%02x\n",
    789  1.5       jdc 		    device_xname(sc->sc_dev), sc->sc_target, val);
    790  1.5       jdc 		if (val != FIREI2C_STAT_REPSTA) {
    791  1.5       jdc 			printf("%s: intr repstart error 0x%02x\n",
    792  1.5       jdc 			    device_xname(sc->sc_dev), val);
    793  1.5       jdc 			sc->sc_err = 1;
    794  1.5       jdc 			sc->sc_stage = FIREI2C_STAGE_STOP;
    795  1.5       jdc 			break;
    796  1.5       jdc 		}
    797  1.5       jdc 
    798  1.5       jdc 		/* Address + r in data, then send ctrl */
    799  1.5       jdc 		val = (sc->sc_target << FIREI2C_DATA_SHIFT) | 0x01;
    800  1.5       jdc 		sc->sc_stage = FIREI2C_STAGE_RE_ADDR;
    801  1.5       jdc 		firei2c_reg_write(sc, FIREI2C_DATA, val);
    802  1.5       jdc 		firei2c_reg_write(sc, FIREI2C_CTRL, ctrl);
    803  1.5       jdc 		break;
    804  1.5       jdc 
    805  1.5       jdc 	case FIREI2C_STAGE_RE_ADDR:
    806  1.5       jdc 		DPRINTF(2)("%s: intr addr(r) 0x%02x = 0x%02x\n",
    807  1.5       jdc 		    device_xname(sc->sc_dev), sc->sc_target, val);
    808  1.5       jdc 		if (val != FIREI2C_STAT_ARE_ACK) {
    809  1.5       jdc 			if (val != FIREI2C_STAT_ARE_NAK)
    810  1.5       jdc 				printf("%s: intr addr(r) error 0x%02x\n",
    811  1.5       jdc 				    device_xname(sc->sc_dev), val);
    812  1.5       jdc 			sc->sc_err = 1;
    813  1.5       jdc 			sc->sc_stage = FIREI2C_STAGE_STOP;
    814  1.5       jdc 			break;
    815  1.5       jdc 		}
    816  1.5       jdc 
    817  1.5       jdc 		sc->sc_stage = FIREI2C_STAGE_READ;
    818  1.5       jdc 		val = FIREI2C_STAT_MDAT_NAK;	/* For read */
    819  1.5       jdc 		/* Fallthrough */
    820  1.5       jdc 
    821  1.5       jdc 	case FIREI2C_STAGE_READ:
    822  1.5       jdc 		DPRINTF(2)("%s: intr read 0x%02x = 0x%02x\n",
    823  1.5       jdc 		    device_xname(sc->sc_dev), sc->sc_target, val);
    824  1.5       jdc 		if (sc->sc_i > 0 && sc->sc_i < sc->sc_buflen) {
    825  1.5       jdc 			if (val != FIREI2C_STAT_MDAT_ACK) {
    826  1.5       jdc 				printf("%s: intr read error 0x%02x\n",
    827  1.5       jdc 				    device_xname(sc->sc_dev), val);
    828  1.5       jdc 				sc->sc_err = 1;
    829  1.5       jdc 				sc->sc_stage = FIREI2C_STAGE_STOP;
    830  1.5       jdc 				break;
    831  1.5       jdc 			}
    832  1.5       jdc 		} else {
    833  1.5       jdc 			if (val != FIREI2C_STAT_MDAT_NAK) {
    834  1.5       jdc 				printf("%s: intr read error 0x%02x\n",
    835  1.5       jdc 				    device_xname(sc->sc_dev), val);
    836  1.5       jdc 				sc->sc_err = 1;
    837  1.5       jdc 				sc->sc_stage = FIREI2C_STAGE_STOP;
    838  1.5       jdc 				break;
    839  1.5       jdc 			}
    840  1.5       jdc 		}
    841  1.5       jdc 
    842  1.5       jdc 		/* Data read is 1 cycle behind ctrl  */
    843  1.5       jdc 		if (sc->sc_i > 0 && sc->sc_i <= sc->sc_buflen) {
    844  1.5       jdc 			sc->sc_buf[sc->sc_i - 1] =
    845  1.5       jdc 			   firei2c_reg_read(sc, FIREI2C_DATA);
    846  1.5       jdc 		}
    847  1.5       jdc 
    848  1.5       jdc 		if (sc->sc_i == sc->sc_buflen) {
    849  1.5       jdc 			/* Last data was read */
    850  1.5       jdc 			sc->sc_stage = FIREI2C_STAGE_STOP;
    851  1.5       jdc 		} else {
    852  1.5       jdc 			/* Send ACK on all but last byte */
    853  1.5       jdc 			if (sc->sc_i < sc->sc_buflen - 1)
    854  1.5       jdc 				ctrl |= FIREI2C_CTRL_AAK;
    855  1.5       jdc 			firei2c_reg_write(sc, FIREI2C_CTRL, ctrl);
    856  1.5       jdc 			sc->sc_i++;
    857  1.5       jdc 		}
    858  1.5       jdc 		break;
    859  1.5       jdc 	}
    860  1.5       jdc 
    861  1.5       jdc 	if (sc->sc_stage == FIREI2C_STAGE_STOP) {
    862  1.5       jdc 		DPRINTF(2)("%s: intr stop (err=%d)\n",
    863  1.5       jdc 		    device_xname(sc->sc_dev), sc->sc_err);
    864  1.1       jdc 		cv_signal(&sc->sc_cv);
    865  1.1       jdc 	}
    866  1.5       jdc 
    867  1.1       jdc 	mutex_exit(&sc->sc_mutex);
    868  1.5       jdc 
    869  1.5       jdc 	return 1;
    870  1.5       jdc 
    871  1.1       jdc }
    872  1.1       jdc 
    873  1.1       jdc static uint8_t
    874  1.1       jdc firei2c_reg_read(struct firei2c_softc *sc, bus_size_t reg)
    875  1.1       jdc {
    876  1.1       jdc 	uint32_t val;
    877  1.1       jdc 	bus_space_barrier(sc->sc_bustag, sc->sc_regh, reg, 8,
    878  1.1       jdc 	    BUS_SPACE_BARRIER_READ);
    879  1.1       jdc 	val = bus_space_read_8(sc->sc_bustag, sc->sc_regh, reg);
    880  1.1       jdc 	return val & 0xff;
    881  1.1       jdc }
    882  1.1       jdc 
    883  1.1       jdc static void
    884  1.1       jdc firei2c_reg_write(struct firei2c_softc *sc, bus_size_t reg, uint8_t val)
    885  1.1       jdc {
    886  1.1       jdc 	bus_space_write_8(sc->sc_bustag, sc->sc_regh, reg, val);
    887  1.1       jdc 	bus_space_barrier(sc->sc_bustag, sc->sc_regh, reg, 8,
    888  1.1       jdc 	    BUS_SPACE_BARRIER_WRITE);
    889  1.1       jdc }
    890