Home | History | Annotate | Line # | Download | only in ti
ti_iic.c revision 1.10
      1  1.10   thorpej /* $NetBSD: ti_iic.c,v 1.10 2021/01/18 02:35:49 thorpej Exp $ */
      2   1.1  jmcneill 
      3   1.1  jmcneill /*
      4   1.1  jmcneill  * Copyright (c) 2013 Manuel Bouyer.  All rights reserved.
      5   1.1  jmcneill  *
      6   1.1  jmcneill  * Redistribution and use in source and binary forms, with or without
      7   1.1  jmcneill  * modification, are permitted provided that the following conditions
      8   1.1  jmcneill  * are met:
      9   1.1  jmcneill  * 1. Redistributions of source code must retain the above copyright
     10   1.1  jmcneill  *    notice, this list of conditions and the following disclaimer.
     11   1.1  jmcneill  * 2. Redistributions in binary form must reproduce the above copyright
     12   1.1  jmcneill  *    notice, this list of conditions and the following disclaimer in the
     13   1.1  jmcneill  *    documentation and/or other materials provided with the distribution.
     14   1.1  jmcneill  *
     15   1.1  jmcneill  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     16   1.1  jmcneill  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     17   1.1  jmcneill  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     18   1.1  jmcneill  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     19   1.1  jmcneill  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     20   1.1  jmcneill  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     21   1.1  jmcneill  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     22   1.1  jmcneill  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     23   1.1  jmcneill  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     24   1.1  jmcneill  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     25   1.1  jmcneill  */
     26   1.1  jmcneill 
     27   1.1  jmcneill /*-
     28   1.1  jmcneill  * Copyright (c) 2012 Jared D. McNeill <jmcneill (at) invisible.ca>
     29   1.1  jmcneill  * All rights reserved.
     30   1.1  jmcneill  *
     31   1.1  jmcneill  * Redistribution and use in source and binary forms, with or without
     32   1.1  jmcneill  * modification, are permitted provided that the following conditions
     33   1.1  jmcneill  * are met:
     34   1.1  jmcneill  * 1. Redistributions of source code must retain the above copyright
     35   1.1  jmcneill  *    notice, this list of conditions and the following disclaimer.
     36   1.1  jmcneill  * 2. The name of the author may not be used to endorse or promote products
     37   1.1  jmcneill  *    derived from this software without specific prior written permission.
     38   1.1  jmcneill  *
     39   1.1  jmcneill  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     40   1.1  jmcneill  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     41   1.1  jmcneill  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     42   1.1  jmcneill  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     43   1.1  jmcneill  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
     44   1.1  jmcneill  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     45   1.1  jmcneill  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
     46   1.1  jmcneill  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
     47   1.1  jmcneill  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     48   1.1  jmcneill  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     49   1.1  jmcneill  * SUCH DAMAGE.
     50   1.1  jmcneill  */
     51   1.1  jmcneill 
     52   1.1  jmcneill #include <sys/cdefs.h>
     53  1.10   thorpej __KERNEL_RCSID(0, "$NetBSD: ti_iic.c,v 1.10 2021/01/18 02:35:49 thorpej Exp $");
     54   1.1  jmcneill 
     55   1.1  jmcneill #include <sys/param.h>
     56   1.1  jmcneill #include <sys/systm.h>
     57   1.1  jmcneill #include <sys/device.h>
     58   1.1  jmcneill #include <sys/conf.h>
     59   1.1  jmcneill #include <sys/bus.h>
     60   1.1  jmcneill #include <sys/proc.h>
     61   1.1  jmcneill #include <sys/kernel.h>
     62   1.1  jmcneill #include <sys/mutex.h>
     63   1.1  jmcneill #include <sys/condvar.h>
     64   1.1  jmcneill 
     65   1.1  jmcneill #include <dev/i2c/i2cvar.h>
     66   1.1  jmcneill 
     67   1.1  jmcneill #include <dev/fdt/fdtvar.h>
     68   1.1  jmcneill 
     69   1.1  jmcneill #include <arm/ti/ti_prcm.h>
     70   1.1  jmcneill #include <arm/ti/ti_iicreg.h>
     71   1.1  jmcneill 
     72   1.1  jmcneill #ifndef OMAP2_I2C_SLAVE_ADDR
     73   1.1  jmcneill #define OMAP2_I2C_SLAVE_ADDR	0x01
     74   1.1  jmcneill #endif
     75   1.1  jmcneill 
     76   1.1  jmcneill #define OMAP2_I2C_FIFOBYTES(fd)	(8 << (fd))
     77   1.1  jmcneill 
     78   1.1  jmcneill #ifdef I2CDEBUG
     79   1.1  jmcneill #define DPRINTF(args)	printf args
     80   1.1  jmcneill #else
     81   1.1  jmcneill #define DPRINTF(args)
     82   1.1  jmcneill #endif
     83   1.1  jmcneill 
     84   1.3  jmcneill enum ti_iic_type {
     85   1.3  jmcneill 	TI_IIC_OMAP3,
     86   1.3  jmcneill 	TI_IIC_OMAP4,
     87   1.3  jmcneill 	TI_NTYPES
     88   1.3  jmcneill };
     89   1.3  jmcneill 
     90   1.3  jmcneill enum {
     91   1.3  jmcneill 	I2C_SYSC,
     92   1.3  jmcneill 	I2C_IRQSTATUS_RAW,
     93   1.3  jmcneill 	I2C_IRQSTATUS,
     94   1.3  jmcneill 	I2C_IRQENABLE,		/* OMAP3 */
     95   1.3  jmcneill 	I2C_IRQENABLE_SET,	/* OMAP4 */
     96   1.3  jmcneill 	I2C_IRQENABLE_CLR,	/* OMAP4 */
     97   1.3  jmcneill 	I2C_SYSS,
     98   1.3  jmcneill 	I2C_BUF,
     99   1.3  jmcneill 	I2C_CNT,
    100   1.3  jmcneill 	I2C_DATA,
    101   1.3  jmcneill 	I2C_CON,
    102   1.3  jmcneill 	I2C_OA,
    103   1.3  jmcneill 	I2C_SA,
    104   1.3  jmcneill 	I2C_PSC,
    105   1.3  jmcneill 	I2C_SCLL,
    106   1.3  jmcneill 	I2C_SCLH,
    107   1.3  jmcneill 	I2C_BUFSTAT,
    108   1.3  jmcneill 	TI_NREGS
    109   1.3  jmcneill };
    110   1.3  jmcneill 
    111   1.3  jmcneill static const u_int ti_iic_regmap[TI_NTYPES][TI_NREGS] = {
    112   1.3  jmcneill 	[TI_IIC_OMAP3] = {
    113   1.3  jmcneill 		[I2C_SYSC] = 0x20,
    114   1.3  jmcneill 		[I2C_IRQSTATUS_RAW] = 0x08,
    115   1.3  jmcneill 		[I2C_IRQSTATUS] = 0x08,
    116   1.3  jmcneill 		[I2C_IRQENABLE] = 0x04,
    117   1.3  jmcneill 		[I2C_SYSS] = 0x10,
    118   1.3  jmcneill 		[I2C_BUF] = 0x14,
    119   1.3  jmcneill 		[I2C_CNT] = 0x18,
    120   1.3  jmcneill 		[I2C_DATA] = 0x1c,
    121   1.3  jmcneill 		[I2C_CON] = 0x24,
    122   1.3  jmcneill 		[I2C_OA] = 0x28,
    123   1.3  jmcneill 		[I2C_SA] = 0x2c,
    124   1.3  jmcneill 		[I2C_PSC] = 0x30,
    125   1.3  jmcneill 		[I2C_SCLL] = 0x34,
    126   1.3  jmcneill 		[I2C_SCLH] = 0x38,
    127   1.3  jmcneill 		[I2C_BUFSTAT] = 0x40,
    128   1.3  jmcneill 	},
    129   1.3  jmcneill 	[TI_IIC_OMAP4] = {
    130   1.3  jmcneill 		[I2C_SYSC] = 0x10,
    131   1.3  jmcneill 		[I2C_IRQSTATUS_RAW] = 0x24,
    132   1.3  jmcneill 		[I2C_IRQSTATUS] = 0x28,
    133   1.3  jmcneill 		[I2C_IRQENABLE_SET] = 0x2c,
    134   1.3  jmcneill 		[I2C_IRQENABLE_CLR] = 0x30,
    135   1.3  jmcneill 		[I2C_SYSS] = 0x90,
    136   1.3  jmcneill 		[I2C_BUF] = 0x94,
    137   1.3  jmcneill 		[I2C_CNT] = 0x98,
    138   1.3  jmcneill 		[I2C_DATA] = 0x9c,
    139   1.3  jmcneill 		[I2C_CON] = 0xa4,
    140   1.3  jmcneill 		[I2C_OA] = 0xa8,
    141   1.3  jmcneill 		[I2C_SA] = 0xac,
    142   1.3  jmcneill 		[I2C_PSC] = 0xb0,
    143   1.3  jmcneill 		[I2C_SCLL] = 0xb4,
    144   1.3  jmcneill 		[I2C_SCLH] = 0xb8,
    145   1.3  jmcneill 		[I2C_BUFSTAT] = 0xc0,
    146   1.3  jmcneill 	},
    147   1.3  jmcneill };
    148   1.3  jmcneill 
    149  1.10   thorpej static const struct device_compatible_entry compat_data[] = {
    150  1.10   thorpej 	/* compatible			type */
    151  1.10   thorpej 	{ .compat = "ti,omap3-i2c",	.value = TI_IIC_OMAP3 },
    152  1.10   thorpej 	{ .compat = "ti,omap4-i2c",	.value = TI_IIC_OMAP4 },
    153  1.10   thorpej 
    154  1.10   thorpej 	{ 0 }
    155   1.1  jmcneill };
    156   1.1  jmcneill 
    157   1.1  jmcneill /* operation in progress */
    158   1.1  jmcneill typedef enum {
    159   1.1  jmcneill 	TI_I2CREAD,
    160   1.1  jmcneill 	TI_I2CWRITE,
    161   1.1  jmcneill 	TI_I2CDONE,
    162   1.1  jmcneill 	TI_I2CERROR
    163   1.1  jmcneill } ti_i2cop_t;
    164   1.1  jmcneill 
    165   1.1  jmcneill struct ti_iic_softc {
    166   1.1  jmcneill 	device_t		sc_dev;
    167   1.1  jmcneill 	struct i2c_controller	sc_ic;
    168   1.1  jmcneill 	kmutex_t		sc_lock;
    169   1.1  jmcneill 	device_t		sc_i2cdev;
    170   1.1  jmcneill 
    171   1.1  jmcneill 	bus_space_tag_t		sc_iot;
    172   1.1  jmcneill 	bus_space_handle_t	sc_ioh;
    173   1.1  jmcneill 
    174   1.3  jmcneill 	enum ti_iic_type	sc_type;
    175   1.2  jmcneill 
    176   1.1  jmcneill 	void			*sc_ih;
    177   1.1  jmcneill 	kmutex_t		sc_mtx;
    178   1.1  jmcneill 	kcondvar_t		sc_cv;
    179   1.1  jmcneill 	ti_i2cop_t		sc_op;
    180   1.4  jmcneill 	int			sc_opflags;
    181   1.1  jmcneill 	int			sc_buflen;
    182   1.1  jmcneill 	int			sc_bufidx;
    183   1.1  jmcneill 	char			*sc_buf;
    184   1.1  jmcneill 
    185   1.1  jmcneill 	bool			sc_busy;
    186   1.1  jmcneill 
    187   1.1  jmcneill 	int			sc_rxthres;
    188   1.1  jmcneill 	int			sc_txthres;
    189   1.1  jmcneill };
    190   1.1  jmcneill 
    191   1.1  jmcneill #define I2C_READ_REG(sc, reg)		\
    192   1.3  jmcneill 	bus_space_read_2((sc)->sc_iot, (sc)->sc_ioh, ti_iic_regmap[(sc)->sc_type][(reg)])
    193   1.1  jmcneill #define I2C_READ_DATA(sc)		\
    194   1.3  jmcneill 	bus_space_read_1((sc)->sc_iot, (sc)->sc_ioh, ti_iic_regmap[(sc)->sc_type][I2C_DATA])
    195   1.1  jmcneill #define I2C_WRITE_REG(sc, reg, val)	\
    196   1.3  jmcneill 	bus_space_write_2((sc)->sc_iot, (sc)->sc_ioh, ti_iic_regmap[(sc)->sc_type][(reg)], (val))
    197   1.1  jmcneill #define I2C_WRITE_DATA(sc, val)		\
    198   1.3  jmcneill 	bus_space_write_1((sc)->sc_iot, (sc)->sc_ioh, ti_iic_regmap[(sc)->sc_type][I2C_DATA], (val))
    199   1.1  jmcneill 
    200   1.1  jmcneill static int	ti_iic_match(device_t, cfdata_t, void *);
    201   1.1  jmcneill static void	ti_iic_attach(device_t, device_t, void *);
    202   1.1  jmcneill 
    203   1.1  jmcneill static int	ti_iic_intr(void *);
    204   1.1  jmcneill 
    205   1.1  jmcneill static int	ti_iic_acquire_bus(void *, int);
    206   1.1  jmcneill static void	ti_iic_release_bus(void *, int);
    207   1.1  jmcneill static int	ti_iic_exec(void *, i2c_op_t, i2c_addr_t, const void *,
    208   1.1  jmcneill 			       size_t, void *, size_t, int);
    209   1.1  jmcneill 
    210   1.1  jmcneill static int	ti_iic_reset(struct ti_iic_softc *);
    211   1.1  jmcneill static int	ti_iic_op(struct ti_iic_softc *, i2c_addr_t, ti_i2cop_t,
    212   1.1  jmcneill 			       uint8_t *, size_t, int);
    213   1.1  jmcneill static void	ti_iic_handle_intr(struct ti_iic_softc *, uint32_t);
    214   1.1  jmcneill static void	ti_iic_do_read(struct ti_iic_softc *, uint32_t);
    215   1.1  jmcneill static void	ti_iic_do_write(struct ti_iic_softc *, uint32_t);
    216   1.1  jmcneill 
    217   1.1  jmcneill static int	ti_iic_wait(struct ti_iic_softc *, uint16_t, uint16_t, int);
    218   1.1  jmcneill static uint32_t	ti_iic_stat(struct ti_iic_softc *, uint32_t);
    219   1.1  jmcneill static int	ti_iic_flush(struct ti_iic_softc *);
    220   1.1  jmcneill 
    221   1.1  jmcneill CFATTACH_DECL_NEW(ti_iic, sizeof(struct ti_iic_softc),
    222   1.1  jmcneill     ti_iic_match, ti_iic_attach, NULL, NULL);
    223   1.1  jmcneill 
    224   1.1  jmcneill static int
    225   1.1  jmcneill ti_iic_match(device_t parent, cfdata_t match, void *opaque)
    226   1.1  jmcneill {
    227   1.1  jmcneill 	struct fdt_attach_args * const faa = opaque;
    228   1.1  jmcneill 
    229   1.2  jmcneill 	return of_match_compat_data(faa->faa_phandle, compat_data);
    230   1.1  jmcneill }
    231   1.1  jmcneill 
    232   1.1  jmcneill static void
    233   1.1  jmcneill ti_iic_attach(device_t parent, device_t self, void *opaque)
    234   1.1  jmcneill {
    235   1.1  jmcneill 	struct ti_iic_softc *sc = device_private(self);
    236   1.1  jmcneill 	struct fdt_attach_args * const faa = opaque;
    237   1.1  jmcneill 	const int phandle = faa->faa_phandle;
    238   1.3  jmcneill 	int fifodepth, fifo;
    239   1.3  jmcneill 	const char *modname;
    240   1.1  jmcneill 	char intrstr[128];
    241   1.1  jmcneill 	bus_addr_t addr;
    242   1.1  jmcneill 	bus_size_t size;
    243   1.1  jmcneill 
    244   1.1  jmcneill 	if (fdtbus_get_reg(phandle, 0, &addr, &size) != 0) {
    245   1.1  jmcneill 		aprint_error(": couldn't get registers\n");
    246   1.1  jmcneill 		return;
    247   1.1  jmcneill 	}
    248   1.1  jmcneill 	if (!fdtbus_intr_str(phandle, 0, intrstr, sizeof(intrstr))) {
    249   1.1  jmcneill 		aprint_error(": couldn't decode interrupt\n");
    250   1.1  jmcneill 		return;
    251   1.1  jmcneill 	}
    252   1.1  jmcneill 
    253   1.2  jmcneill 	if (ti_prcm_enable_hwmod(phandle, 0) != 0) {
    254   1.1  jmcneill 		aprint_error(": couldn't enable module\n");
    255   1.1  jmcneill 		return;
    256   1.1  jmcneill 	}
    257   1.1  jmcneill 
    258   1.1  jmcneill 	sc->sc_dev = self;
    259   1.1  jmcneill 	sc->sc_iot = faa->faa_bst;
    260   1.1  jmcneill 	mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE);
    261   1.1  jmcneill 	mutex_init(&sc->sc_mtx, MUTEX_DEFAULT, IPL_NET);
    262   1.1  jmcneill 	cv_init(&sc->sc_cv, "tiiic");
    263   1.7  riastrad 	iic_tag_init(&sc->sc_ic);
    264   1.1  jmcneill 	sc->sc_ic.ic_cookie = sc;
    265   1.1  jmcneill 	sc->sc_ic.ic_acquire_bus = ti_iic_acquire_bus;
    266   1.1  jmcneill 	sc->sc_ic.ic_release_bus = ti_iic_release_bus;
    267   1.1  jmcneill 	sc->sc_ic.ic_exec = ti_iic_exec;
    268   1.1  jmcneill 
    269   1.1  jmcneill 	if (bus_space_map(sc->sc_iot, addr, size, 0, &sc->sc_ioh) != 0) {
    270   1.1  jmcneill 		aprint_error(": couldn't map registers\n");
    271   1.1  jmcneill 		return;
    272   1.1  jmcneill 	}
    273  1.10   thorpej 	sc->sc_type = of_search_compatible(phandle, compat_data)->value;
    274   1.1  jmcneill 
    275   1.9  jmcneill 	sc->sc_ih = fdtbus_intr_establish_xname(phandle, 0, IPL_NET, 0,
    276   1.9  jmcneill 	    ti_iic_intr, sc, device_xname(self));
    277   1.1  jmcneill 	if (sc->sc_ih == NULL) {
    278   1.1  jmcneill 		aprint_error(": couldn't establish interrupt\n");
    279   1.1  jmcneill 		return;
    280   1.1  jmcneill 	}
    281   1.1  jmcneill 
    282   1.3  jmcneill 	modname = fdtbus_get_string(phandle, "ti,hwmods");
    283   1.3  jmcneill 	if (modname == NULL)
    284   1.3  jmcneill 		modname = fdtbus_get_string(OF_parent(phandle), "ti,hwmods");
    285   1.1  jmcneill 
    286   1.3  jmcneill 	fifodepth = I2C_BUFSTAT_FIFODEPTH(I2C_READ_REG(sc, I2C_BUFSTAT));
    287   1.1  jmcneill 	fifo = OMAP2_I2C_FIFOBYTES(fifodepth);
    288   1.1  jmcneill 	sc->sc_rxthres = sc->sc_txthres = fifo >> 1;
    289   1.1  jmcneill 
    290   1.3  jmcneill 	aprint_naive("\n");
    291   1.6  jmcneill 	if (modname != NULL)
    292   1.6  jmcneill 		aprint_normal(": I2C controller (%s), %d-bytes FIFO\n", modname, fifo);
    293   1.6  jmcneill 	else
    294   1.6  jmcneill 		aprint_normal(": I2C controller (i2c@%" PRIxBUSADDR "), %d-bytes FIFO\n",
    295   1.6  jmcneill 		    addr, fifo);
    296   1.3  jmcneill 
    297   1.1  jmcneill 	ti_iic_reset(sc);
    298   1.1  jmcneill 	ti_iic_flush(sc);
    299   1.1  jmcneill 
    300   1.8   thorpej 	fdtbus_register_i2c_controller(&sc->sc_ic, phandle);
    301   1.1  jmcneill 
    302   1.1  jmcneill 	fdtbus_attach_i2cbus(self, phandle, &sc->sc_ic, iicbus_print);
    303   1.1  jmcneill }
    304   1.1  jmcneill 
    305   1.1  jmcneill static int
    306   1.1  jmcneill ti_iic_intr(void *arg)
    307   1.1  jmcneill {
    308   1.1  jmcneill 	struct ti_iic_softc *sc = arg;
    309   1.1  jmcneill 	uint32_t stat;
    310   1.1  jmcneill 
    311   1.1  jmcneill 	mutex_enter(&sc->sc_mtx);
    312   1.4  jmcneill 	DPRINTF(("ti_iic_intr opflags=%#x\n", sc->sc_opflags));
    313   1.4  jmcneill 	if ((sc->sc_opflags & I2C_F_POLL) == 0) {
    314   1.4  jmcneill 		stat = I2C_READ_REG(sc, I2C_IRQSTATUS);
    315   1.4  jmcneill 		DPRINTF(("ti_iic_intr pre handle sc->sc_op eq %#x\n", sc->sc_op));
    316   1.4  jmcneill 		ti_iic_handle_intr(sc, stat);
    317   1.4  jmcneill 		I2C_WRITE_REG(sc, I2C_IRQSTATUS, stat);
    318   1.4  jmcneill 		if (sc->sc_op == TI_I2CERROR || sc->sc_op == TI_I2CDONE) {
    319   1.4  jmcneill 			DPRINTF(("ti_iic_intr post handle sc->sc_op %#x\n", sc->sc_op));
    320   1.4  jmcneill 			cv_broadcast(&sc->sc_cv);
    321   1.4  jmcneill 		}
    322   1.1  jmcneill 	}
    323   1.1  jmcneill 	mutex_exit(&sc->sc_mtx);
    324   1.1  jmcneill 	DPRINTF(("ti_iic_intr status 0x%x\n", stat));
    325   1.1  jmcneill 	return 1;
    326   1.1  jmcneill }
    327   1.1  jmcneill 
    328   1.1  jmcneill static int
    329   1.1  jmcneill ti_iic_acquire_bus(void *opaque, int flags)
    330   1.1  jmcneill {
    331   1.1  jmcneill 	struct ti_iic_softc *sc = opaque;
    332   1.1  jmcneill 
    333   1.1  jmcneill 	mutex_enter(&sc->sc_lock);
    334   1.1  jmcneill 	while (sc->sc_busy)
    335   1.1  jmcneill 		cv_wait(&sc->sc_cv, &sc->sc_lock);
    336   1.1  jmcneill 	sc->sc_busy = true;
    337   1.1  jmcneill 	mutex_exit(&sc->sc_lock);
    338   1.1  jmcneill 
    339   1.1  jmcneill 	return 0;
    340   1.1  jmcneill }
    341   1.1  jmcneill 
    342   1.1  jmcneill static void
    343   1.1  jmcneill ti_iic_release_bus(void *opaque, int flags)
    344   1.1  jmcneill {
    345   1.1  jmcneill 	struct ti_iic_softc *sc = opaque;
    346   1.1  jmcneill 
    347   1.1  jmcneill 	mutex_enter(&sc->sc_lock);
    348   1.1  jmcneill 	sc->sc_busy = false;
    349   1.1  jmcneill 	cv_broadcast(&sc->sc_cv);
    350   1.1  jmcneill 	mutex_exit(&sc->sc_lock);
    351   1.1  jmcneill }
    352   1.1  jmcneill 
    353   1.1  jmcneill static int
    354   1.1  jmcneill ti_iic_exec(void *opaque, i2c_op_t op, i2c_addr_t addr,
    355   1.1  jmcneill     const void *cmdbuf, size_t cmdlen, void *buf, size_t len, int flags)
    356   1.1  jmcneill {
    357   1.1  jmcneill 	struct ti_iic_softc *sc = opaque;
    358   1.1  jmcneill 	int err;
    359   1.1  jmcneill 
    360   1.1  jmcneill 	DPRINTF(("ti_iic_exec: op 0x%x cmdlen %zd len %zd flags 0x%x\n",
    361   1.1  jmcneill 	    op, cmdlen, len, flags));
    362   1.1  jmcneill 
    363   1.1  jmcneill 	if (cmdlen > 0) {
    364   1.1  jmcneill 		err = ti_iic_op(sc, addr, TI_I2CWRITE,
    365   1.1  jmcneill 		    __UNCONST(cmdbuf), cmdlen,
    366   1.1  jmcneill 		    (I2C_OP_READ_P(op) ? 0 : I2C_F_STOP) | flags);
    367   1.1  jmcneill 		if (err)
    368   1.1  jmcneill 			goto done;
    369   1.1  jmcneill 	}
    370   1.1  jmcneill 
    371   1.1  jmcneill 	if (I2C_OP_STOP_P(op))
    372   1.1  jmcneill 		flags |= I2C_F_STOP;
    373   1.1  jmcneill 
    374   1.1  jmcneill 	/*
    375   1.1  jmcneill 	 * I2C controller doesn't allow for zero-byte transfers.
    376   1.1  jmcneill 	 */
    377   1.1  jmcneill 	if (len == 0) {
    378   1.1  jmcneill 		err = EINVAL;
    379   1.1  jmcneill 		goto done;
    380   1.1  jmcneill 	}
    381   1.1  jmcneill 
    382   1.1  jmcneill 	if (I2C_OP_READ_P(op)) {
    383   1.1  jmcneill 		err = ti_iic_op(sc, addr, TI_I2CREAD, buf, len, flags);
    384   1.1  jmcneill 	} else {
    385   1.1  jmcneill 		err = ti_iic_op(sc, addr, TI_I2CWRITE, buf, len, flags);
    386   1.1  jmcneill 	}
    387   1.1  jmcneill 
    388   1.1  jmcneill done:
    389   1.1  jmcneill 	if (err)
    390   1.1  jmcneill 		ti_iic_reset(sc);
    391   1.1  jmcneill 
    392   1.1  jmcneill 	ti_iic_flush(sc);
    393   1.1  jmcneill 
    394   1.1  jmcneill 	DPRINTF(("ti_iic_exec: done %d\n", err));
    395   1.1  jmcneill 	return err;
    396   1.1  jmcneill }
    397   1.1  jmcneill 
    398   1.1  jmcneill static int
    399   1.1  jmcneill ti_iic_reset(struct ti_iic_softc *sc)
    400   1.1  jmcneill {
    401   1.1  jmcneill 	uint32_t psc, scll, sclh;
    402   1.1  jmcneill 	int i;
    403   1.1  jmcneill 
    404   1.1  jmcneill 	DPRINTF(("ti_iic_reset\n"));
    405   1.1  jmcneill 
    406   1.1  jmcneill 	/* Disable */
    407   1.3  jmcneill 	I2C_WRITE_REG(sc, I2C_CON, 0);
    408   1.1  jmcneill 	/* Soft reset */
    409   1.3  jmcneill 	I2C_WRITE_REG(sc, I2C_SYSC, I2C_SYSC_SRST);
    410   1.1  jmcneill 	delay(1000);
    411   1.1  jmcneill 	/* enable so that we can check for reset complete */
    412   1.3  jmcneill 	I2C_WRITE_REG(sc, I2C_CON, I2C_CON_EN);
    413   1.1  jmcneill 	delay(1000);
    414   1.1  jmcneill 	for (i = 0; i < 1000; i++) { /* 1s delay for reset */
    415   1.3  jmcneill 		if (I2C_READ_REG(sc, I2C_SYSS) & I2C_SYSS_RDONE)
    416   1.1  jmcneill 			break;
    417   1.1  jmcneill 	}
    418   1.1  jmcneill 	/* Disable again */
    419   1.3  jmcneill 	I2C_WRITE_REG(sc, I2C_CON, 0);
    420   1.1  jmcneill 	delay(50000);
    421   1.1  jmcneill 
    422   1.1  jmcneill 	if (i >= 1000) {
    423   1.1  jmcneill 		aprint_error_dev(sc->sc_dev, ": couldn't reset module\n");
    424   1.1  jmcneill 		return 1;
    425   1.1  jmcneill 	}
    426   1.1  jmcneill 
    427   1.1  jmcneill 
    428   1.1  jmcneill 	/* XXX standard speed only */
    429   1.4  jmcneill 	if (sc->sc_type == TI_IIC_OMAP3) {
    430   1.4  jmcneill 		psc = (96000000 / 19200000) - 1;
    431   1.4  jmcneill 		scll = sclh = (19200000 / (2 * 100000)) - 6;
    432   1.4  jmcneill 	} else {
    433   1.4  jmcneill 		psc = 3;
    434   1.4  jmcneill 		scll = 53;
    435   1.4  jmcneill 		sclh = 55;
    436   1.4  jmcneill 	}
    437   1.1  jmcneill 
    438   1.1  jmcneill 	/* Clocks */
    439   1.3  jmcneill 	I2C_WRITE_REG(sc, I2C_PSC, psc);
    440   1.3  jmcneill 	I2C_WRITE_REG(sc, I2C_SCLL, scll);
    441   1.3  jmcneill 	I2C_WRITE_REG(sc, I2C_SCLH, sclh);
    442   1.1  jmcneill 
    443   1.1  jmcneill 	/* Own I2C address */
    444   1.3  jmcneill 	I2C_WRITE_REG(sc, I2C_OA, OMAP2_I2C_SLAVE_ADDR);
    445   1.1  jmcneill 
    446   1.1  jmcneill 	/* 5 bytes fifo */
    447   1.3  jmcneill 	I2C_WRITE_REG(sc, I2C_BUF,
    448   1.1  jmcneill 	    I2C_BUF_RXTRSH(sc->sc_rxthres) | I2C_BUF_TXTRSH(sc->sc_txthres));
    449   1.1  jmcneill 
    450   1.1  jmcneill 	/* Enable */
    451   1.3  jmcneill 	I2C_WRITE_REG(sc, I2C_CON, I2C_CON_EN);
    452   1.1  jmcneill 
    453   1.1  jmcneill 	return 0;
    454   1.1  jmcneill }
    455   1.1  jmcneill 
    456   1.1  jmcneill static int
    457   1.1  jmcneill ti_iic_op(struct ti_iic_softc *sc, i2c_addr_t addr, ti_i2cop_t op,
    458   1.1  jmcneill     uint8_t *buf, size_t buflen, int flags)
    459   1.1  jmcneill {
    460   1.1  jmcneill 	uint16_t con, stat, mask;
    461   1.1  jmcneill 	int err, retry;
    462   1.1  jmcneill 
    463   1.1  jmcneill 	KASSERT(op == TI_I2CREAD || op == TI_I2CWRITE);
    464   1.1  jmcneill 	DPRINTF(("ti_iic_op: addr %#x op %#x buf %p buflen %#x flags %#x\n",
    465   1.1  jmcneill 	    addr, op, buf, (unsigned int) buflen, flags));
    466   1.1  jmcneill 
    467   1.1  jmcneill 	mask = I2C_IRQSTATUS_ARDY | I2C_IRQSTATUS_NACK | I2C_IRQSTATUS_AL;
    468   1.1  jmcneill 	if (op == TI_I2CREAD) {
    469   1.1  jmcneill 		mask |= I2C_IRQSTATUS_RDR | I2C_IRQSTATUS_RRDY;
    470   1.1  jmcneill 	} else {
    471   1.1  jmcneill 		mask |= I2C_IRQSTATUS_XDR | I2C_IRQSTATUS_XRDY;
    472   1.1  jmcneill 	}
    473   1.1  jmcneill 
    474   1.1  jmcneill 	err = ti_iic_wait(sc, I2C_IRQSTATUS_BB, 0, flags);
    475   1.1  jmcneill 	if (err) {
    476   1.1  jmcneill 		DPRINTF(("ti_iic_op: wait error %d\n", err));
    477   1.1  jmcneill 		return err;
    478   1.1  jmcneill 	}
    479   1.1  jmcneill 
    480   1.1  jmcneill 	con = I2C_CON_EN;
    481   1.1  jmcneill 	con |= I2C_CON_MST;
    482   1.5   msaitoh 	con |= I2C_CON_STT;
    483   1.1  jmcneill 	if (flags & I2C_F_STOP)
    484   1.1  jmcneill 		con |= I2C_CON_STP;
    485   1.1  jmcneill 	if (addr & ~0x7f)
    486   1.1  jmcneill 		con |= I2C_CON_XSA;
    487   1.1  jmcneill 	if (op == TI_I2CWRITE)
    488   1.1  jmcneill 		con |= I2C_CON_TRX;
    489   1.1  jmcneill 
    490   1.1  jmcneill 	mutex_enter(&sc->sc_mtx);
    491   1.1  jmcneill 	sc->sc_op = op;
    492   1.4  jmcneill 	sc->sc_opflags = flags;
    493   1.1  jmcneill 	sc->sc_buf = buf;
    494   1.1  jmcneill 	sc->sc_buflen = buflen;
    495   1.1  jmcneill 	sc->sc_bufidx = 0;
    496   1.1  jmcneill 
    497   1.3  jmcneill 	I2C_WRITE_REG(sc, I2C_CON, I2C_CON_EN | I2C_CON_MST | I2C_CON_STP);
    498   1.1  jmcneill 	DPRINTF(("ti_iic_op: op %d con 0x%x ", op, con));
    499   1.3  jmcneill 	I2C_WRITE_REG(sc, I2C_CNT, buflen);
    500   1.3  jmcneill 	I2C_WRITE_REG(sc, I2C_SA, (addr & I2C_SA_MASK));
    501   1.3  jmcneill 	DPRINTF(("SA 0x%x len %d\n", I2C_READ_REG(sc, I2C_SA), I2C_READ_REG(sc, I2C_CNT)));
    502   1.1  jmcneill 
    503   1.4  jmcneill 	if ((flags & I2C_F_POLL) == 0 || sc->sc_type == TI_IIC_OMAP3) {
    504   1.1  jmcneill 		/* clear any pending interrupt */
    505   1.3  jmcneill 		I2C_WRITE_REG(sc, I2C_IRQSTATUS,
    506   1.3  jmcneill 		    I2C_READ_REG(sc, I2C_IRQSTATUS));
    507   1.1  jmcneill 		/* and enable */
    508   1.3  jmcneill 		if (sc->sc_type == TI_IIC_OMAP4) {
    509   1.3  jmcneill 			I2C_WRITE_REG(sc, I2C_IRQENABLE_SET, mask);
    510   1.3  jmcneill 		} else {
    511   1.3  jmcneill 			I2C_WRITE_REG(sc, I2C_IRQENABLE, mask);
    512   1.3  jmcneill 		}
    513   1.1  jmcneill 	}
    514   1.1  jmcneill 	/* start transfer */
    515   1.3  jmcneill 	I2C_WRITE_REG(sc, I2C_CON, con);
    516   1.1  jmcneill 
    517   1.1  jmcneill 	if ((flags & I2C_F_POLL) == 0) {
    518   1.1  jmcneill 		/* and wait for completion */
    519   1.1  jmcneill 		DPRINTF(("ti_iic_op waiting, op %#x\n", sc->sc_op));
    520   1.1  jmcneill 		while (sc->sc_op == op) {
    521   1.1  jmcneill 			if (cv_timedwait(&sc->sc_cv, &sc->sc_mtx,
    522   1.1  jmcneill 			    mstohz(5000)) == EWOULDBLOCK) {
    523   1.1  jmcneill 				/* timeout */
    524   1.1  jmcneill 				op = TI_I2CERROR;
    525   1.1  jmcneill 			}
    526   1.1  jmcneill 		}
    527   1.1  jmcneill 		DPRINTF(("ti_iic_op waiting done, op %#x\n", sc->sc_op));
    528   1.1  jmcneill 
    529   1.1  jmcneill 		/* disable interrupts */
    530   1.3  jmcneill 		if (sc->sc_type == TI_IIC_OMAP4) {
    531   1.3  jmcneill 			I2C_WRITE_REG(sc, I2C_IRQENABLE_CLR, 0xffff);
    532   1.3  jmcneill 		} else {
    533   1.3  jmcneill 			I2C_WRITE_REG(sc, I2C_IRQENABLE, 0);
    534   1.3  jmcneill 		}
    535   1.1  jmcneill 	} else {
    536   1.1  jmcneill 		/* poll for completion */
    537   1.1  jmcneill 		DPRINTF(("ti_iic_op polling, op %x\n", sc->sc_op));
    538   1.1  jmcneill 		while (sc->sc_op == op) {
    539   1.1  jmcneill 			stat = ti_iic_stat(sc, mask);
    540   1.1  jmcneill 			DPRINTF(("ti_iic_op stat 0x%x\n", stat));
    541   1.1  jmcneill 			if (stat == 0) {
    542   1.1  jmcneill 				/* timeout */
    543   1.1  jmcneill 				sc->sc_op = TI_I2CERROR;
    544   1.1  jmcneill 			} else {
    545   1.1  jmcneill 				ti_iic_handle_intr(sc, stat);
    546   1.1  jmcneill 			}
    547   1.3  jmcneill 			I2C_WRITE_REG(sc, I2C_IRQSTATUS, stat);
    548   1.1  jmcneill 		}
    549   1.1  jmcneill 		DPRINTF(("ti_iic_op polling done, op now %x\n", sc->sc_op));
    550   1.1  jmcneill 	}
    551   1.1  jmcneill 	mutex_exit(&sc->sc_mtx);
    552   1.1  jmcneill 	retry = 10000;
    553   1.3  jmcneill 	I2C_WRITE_REG(sc, I2C_CON, 0);
    554   1.3  jmcneill 	while (I2C_READ_REG(sc, I2C_CON) & I2C_CON_MST) {
    555   1.1  jmcneill 		delay(100);
    556   1.1  jmcneill 		if (--retry == 0)
    557   1.1  jmcneill 			break;
    558   1.1  jmcneill 	}
    559   1.1  jmcneill 	return (sc->sc_op == TI_I2CDONE) ? 0 : EIO;
    560   1.1  jmcneill }
    561   1.1  jmcneill 
    562   1.1  jmcneill static void
    563   1.1  jmcneill ti_iic_handle_intr(struct ti_iic_softc *sc, uint32_t stat)
    564   1.1  jmcneill {
    565   1.1  jmcneill 	KASSERT(mutex_owned(&sc->sc_mtx));
    566   1.1  jmcneill 	KASSERT(stat != 0);
    567   1.1  jmcneill 	DPRINTF(("ti_iic_handle_intr stat %#x\n", stat));
    568   1.1  jmcneill 
    569   1.1  jmcneill 	if (stat &
    570   1.1  jmcneill 	    (I2C_IRQSTATUS_NACK|I2C_IRQSTATUS_AL)) {
    571   1.1  jmcneill 		sc->sc_op = TI_I2CERROR;
    572   1.1  jmcneill 		return;
    573   1.1  jmcneill 	}
    574   1.1  jmcneill 	if (stat & I2C_IRQSTATUS_ARDY) {
    575   1.1  jmcneill 		sc->sc_op = TI_I2CDONE;
    576   1.1  jmcneill 		return;
    577   1.1  jmcneill 	}
    578   1.1  jmcneill 	if (sc->sc_op == TI_I2CREAD)
    579   1.1  jmcneill 		ti_iic_do_read(sc, stat);
    580   1.1  jmcneill 	else if (sc->sc_op == TI_I2CWRITE)
    581   1.1  jmcneill 		ti_iic_do_write(sc, stat);
    582   1.1  jmcneill 	else
    583   1.1  jmcneill 		return;
    584   1.1  jmcneill }
    585   1.1  jmcneill void
    586   1.1  jmcneill ti_iic_do_read(struct ti_iic_softc *sc, uint32_t stat)
    587   1.1  jmcneill {
    588   1.1  jmcneill 	int len = 0;
    589   1.1  jmcneill 
    590   1.1  jmcneill 	KASSERT(mutex_owned(&sc->sc_mtx));
    591   1.1  jmcneill 	DPRINTF(("ti_iic_do_read stat %#x\n", stat));
    592   1.1  jmcneill 	if (stat & I2C_IRQSTATUS_RDR) {
    593   1.3  jmcneill 		len = I2C_READ_REG(sc, I2C_BUFSTAT);
    594   1.1  jmcneill 		len = I2C_BUFSTAT_RXSTAT(len);
    595   1.1  jmcneill 		DPRINTF(("ti_iic_do_read receive drain len %d left %d\n",
    596   1.3  jmcneill 		    len, I2C_READ_REG(sc, I2C_CNT)));
    597   1.1  jmcneill 	} else if (stat & I2C_IRQSTATUS_RRDY) {
    598   1.1  jmcneill 		len = sc->sc_rxthres + 1;
    599   1.1  jmcneill 		DPRINTF(("ti_iic_do_read receive len %d left %d\n",
    600   1.3  jmcneill 		    len, I2C_READ_REG(sc, I2C_CNT)));
    601   1.1  jmcneill 	}
    602   1.1  jmcneill 	for (;
    603   1.1  jmcneill 	    sc->sc_bufidx < sc->sc_buflen && len > 0;
    604   1.1  jmcneill 	    sc->sc_bufidx++, len--) {
    605   1.1  jmcneill 		sc->sc_buf[sc->sc_bufidx] = I2C_READ_DATA(sc);
    606   1.1  jmcneill 		DPRINTF(("ti_iic_do_read got b[%d]=0x%x\n", sc->sc_bufidx,
    607   1.1  jmcneill 		    sc->sc_buf[sc->sc_bufidx]));
    608   1.1  jmcneill 	}
    609   1.1  jmcneill 	DPRINTF(("ti_iic_do_read done\n"));
    610   1.1  jmcneill }
    611   1.1  jmcneill 
    612   1.1  jmcneill void
    613   1.1  jmcneill ti_iic_do_write(struct ti_iic_softc *sc, uint32_t stat)
    614   1.1  jmcneill {
    615   1.1  jmcneill 	int len = 0;
    616   1.1  jmcneill 
    617   1.1  jmcneill 	DPRINTF(("ti_iic_do_write stat %#x\n", stat));
    618   1.1  jmcneill 	KASSERT(mutex_owned(&sc->sc_mtx));
    619   1.1  jmcneill 	if (stat & I2C_IRQSTATUS_XDR) {
    620   1.3  jmcneill 		len = I2C_READ_REG(sc, I2C_BUFSTAT);
    621   1.1  jmcneill 		len = I2C_BUFSTAT_TXSTAT(len);
    622   1.1  jmcneill 		DPRINTF(("ti_iic_do_write xmit drain len %d left %d\n",
    623   1.3  jmcneill 		    len, I2C_READ_REG(sc, I2C_CNT)));
    624   1.1  jmcneill 	} else if (stat & I2C_IRQSTATUS_XRDY) {
    625   1.1  jmcneill 		len = sc->sc_txthres + 1;
    626   1.1  jmcneill 		DPRINTF(("ti_iic_do_write xmit len %d left %d\n",
    627   1.3  jmcneill 		    len, I2C_READ_REG(sc, I2C_CNT)));
    628   1.1  jmcneill 	}
    629   1.1  jmcneill 	for (;
    630   1.1  jmcneill 	    sc->sc_bufidx < sc->sc_buflen && len > 0;
    631   1.1  jmcneill 	    sc->sc_bufidx++, len--) {
    632   1.1  jmcneill 		DPRINTF(("ti_iic_do_write send b[%d]=0x%x\n",
    633   1.1  jmcneill 		    sc->sc_bufidx, sc->sc_buf[sc->sc_bufidx]));
    634   1.1  jmcneill 		I2C_WRITE_DATA(sc, sc->sc_buf[sc->sc_bufidx]);
    635   1.1  jmcneill 	}
    636   1.1  jmcneill 	DPRINTF(("ti_iic_do_write done\n"));
    637   1.1  jmcneill }
    638   1.1  jmcneill 
    639   1.1  jmcneill static int
    640   1.1  jmcneill ti_iic_wait(struct ti_iic_softc *sc, uint16_t mask, uint16_t val, int flags)
    641   1.1  jmcneill {
    642   1.1  jmcneill 	int retry = 10;
    643   1.1  jmcneill 	uint16_t v;
    644   1.1  jmcneill 	DPRINTF(("ti_iic_wait mask %#x val %#x flags %#x\n", mask, val, flags));
    645   1.1  jmcneill 
    646   1.3  jmcneill 	while (((v = I2C_READ_REG(sc, I2C_IRQSTATUS_RAW)) & mask) != val) {
    647   1.1  jmcneill 		--retry;
    648   1.1  jmcneill 		if (retry == 0) {
    649   1.1  jmcneill 			aprint_error_dev(sc->sc_dev, ": wait timeout, "
    650   1.1  jmcneill 			    "mask = %#x val = %#x stat = %#x\n",
    651   1.1  jmcneill 			    mask, val, v);
    652   1.1  jmcneill 			return EBUSY;
    653   1.1  jmcneill 		}
    654   1.1  jmcneill 		if (flags & I2C_F_POLL) {
    655   1.1  jmcneill 			delay(50000);
    656   1.1  jmcneill 		} else {
    657   1.1  jmcneill 			kpause("tiiic", false, mstohz(50), NULL);
    658   1.1  jmcneill 		}
    659   1.1  jmcneill 	}
    660   1.1  jmcneill 	DPRINTF(("ti_iic_wait done retry %#x\n", retry));
    661   1.1  jmcneill 
    662   1.1  jmcneill 	return 0;
    663   1.1  jmcneill }
    664   1.1  jmcneill 
    665   1.1  jmcneill static uint32_t
    666   1.1  jmcneill ti_iic_stat(struct ti_iic_softc *sc, uint32_t mask)
    667   1.1  jmcneill {
    668   1.1  jmcneill 	uint32_t v;
    669   1.1  jmcneill 	int retry = 500;
    670   1.1  jmcneill 	DPRINTF(("ti_iic_wait mask %#x\n", mask));
    671   1.1  jmcneill 	while (--retry > 0) {
    672   1.3  jmcneill 		v = I2C_READ_REG(sc, I2C_IRQSTATUS_RAW) & mask;
    673   1.1  jmcneill 		if (v != 0)
    674   1.1  jmcneill 			break;
    675   1.1  jmcneill 		delay(100);
    676   1.1  jmcneill 	}
    677   1.1  jmcneill 	DPRINTF(("ti_iic_wait done retry %#x\n", retry));
    678   1.1  jmcneill 	return v;
    679   1.1  jmcneill }
    680   1.1  jmcneill 
    681   1.1  jmcneill static int
    682   1.1  jmcneill ti_iic_flush(struct ti_iic_softc *sc)
    683   1.1  jmcneill {
    684   1.1  jmcneill 	DPRINTF(("ti_iic_flush\n"));
    685   1.1  jmcneill #if 0
    686   1.1  jmcneill 	int retry = 1000;
    687   1.1  jmcneill 	uint16_t v;
    688   1.1  jmcneill 
    689   1.3  jmcneill 	while ((v = I2C_READ_REG(sc, I2C_IRQSTATUS_RAW)) & I2C_IRQSTATUS_RRDY) {
    690   1.1  jmcneill 		if (--retry == 0) {
    691   1.1  jmcneill 			aprint_error_dev(sc->sc_dev,
    692   1.1  jmcneill 			    ": flush timeout, stat = %#x\n", v);
    693   1.1  jmcneill 			return EBUSY;
    694   1.1  jmcneill 		}
    695   1.1  jmcneill 		(void)I2C_READ_DATA(sc);
    696   1.1  jmcneill 		delay(1000);
    697   1.1  jmcneill 	}
    698   1.1  jmcneill #endif
    699   1.1  jmcneill 
    700   1.3  jmcneill 	I2C_WRITE_REG(sc, I2C_CNT, 0);
    701   1.1  jmcneill 	return 0;
    702   1.1  jmcneill }
    703