1 1.15 thorpej /* $NetBSD: ti_iic.c,v 1.15 2025/09/16 11:55:17 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.15 thorpej __KERNEL_RCSID(0, "$NetBSD: ti_iic.c,v 1.15 2025/09/16 11:55:17 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.12 thorpej DEVICE_COMPAT_EOL 154 1.1 jmcneill }; 155 1.1 jmcneill 156 1.1 jmcneill /* operation in progress */ 157 1.1 jmcneill typedef enum { 158 1.1 jmcneill TI_I2CREAD, 159 1.1 jmcneill TI_I2CWRITE, 160 1.1 jmcneill TI_I2CDONE, 161 1.1 jmcneill TI_I2CERROR 162 1.1 jmcneill } ti_i2cop_t; 163 1.1 jmcneill 164 1.1 jmcneill struct ti_iic_softc { 165 1.1 jmcneill device_t sc_dev; 166 1.1 jmcneill struct i2c_controller sc_ic; 167 1.1 jmcneill kmutex_t sc_lock; 168 1.1 jmcneill device_t sc_i2cdev; 169 1.1 jmcneill 170 1.1 jmcneill bus_space_tag_t sc_iot; 171 1.1 jmcneill bus_space_handle_t sc_ioh; 172 1.1 jmcneill 173 1.3 jmcneill enum ti_iic_type sc_type; 174 1.2 jmcneill 175 1.1 jmcneill void *sc_ih; 176 1.1 jmcneill kmutex_t sc_mtx; 177 1.1 jmcneill kcondvar_t sc_cv; 178 1.1 jmcneill ti_i2cop_t sc_op; 179 1.4 jmcneill int sc_opflags; 180 1.1 jmcneill int sc_buflen; 181 1.1 jmcneill int sc_bufidx; 182 1.1 jmcneill char *sc_buf; 183 1.1 jmcneill 184 1.1 jmcneill bool sc_busy; 185 1.1 jmcneill 186 1.1 jmcneill int sc_rxthres; 187 1.1 jmcneill int sc_txthres; 188 1.1 jmcneill }; 189 1.1 jmcneill 190 1.1 jmcneill #define I2C_READ_REG(sc, reg) \ 191 1.3 jmcneill bus_space_read_2((sc)->sc_iot, (sc)->sc_ioh, ti_iic_regmap[(sc)->sc_type][(reg)]) 192 1.1 jmcneill #define I2C_READ_DATA(sc) \ 193 1.3 jmcneill bus_space_read_1((sc)->sc_iot, (sc)->sc_ioh, ti_iic_regmap[(sc)->sc_type][I2C_DATA]) 194 1.1 jmcneill #define I2C_WRITE_REG(sc, reg, val) \ 195 1.3 jmcneill bus_space_write_2((sc)->sc_iot, (sc)->sc_ioh, ti_iic_regmap[(sc)->sc_type][(reg)], (val)) 196 1.1 jmcneill #define I2C_WRITE_DATA(sc, val) \ 197 1.3 jmcneill bus_space_write_1((sc)->sc_iot, (sc)->sc_ioh, ti_iic_regmap[(sc)->sc_type][I2C_DATA], (val)) 198 1.1 jmcneill 199 1.1 jmcneill static int ti_iic_match(device_t, cfdata_t, void *); 200 1.1 jmcneill static void ti_iic_attach(device_t, device_t, void *); 201 1.1 jmcneill 202 1.1 jmcneill static int ti_iic_intr(void *); 203 1.1 jmcneill 204 1.1 jmcneill static int ti_iic_acquire_bus(void *, int); 205 1.1 jmcneill static void ti_iic_release_bus(void *, int); 206 1.1 jmcneill static int ti_iic_exec(void *, i2c_op_t, i2c_addr_t, const void *, 207 1.1 jmcneill size_t, void *, size_t, int); 208 1.1 jmcneill 209 1.1 jmcneill static int ti_iic_reset(struct ti_iic_softc *); 210 1.1 jmcneill static int ti_iic_op(struct ti_iic_softc *, i2c_addr_t, ti_i2cop_t, 211 1.1 jmcneill uint8_t *, size_t, int); 212 1.1 jmcneill static void ti_iic_handle_intr(struct ti_iic_softc *, uint32_t); 213 1.1 jmcneill static void ti_iic_do_read(struct ti_iic_softc *, uint32_t); 214 1.1 jmcneill static void ti_iic_do_write(struct ti_iic_softc *, uint32_t); 215 1.1 jmcneill 216 1.1 jmcneill static int ti_iic_wait(struct ti_iic_softc *, uint16_t, uint16_t, int); 217 1.1 jmcneill static uint32_t ti_iic_stat(struct ti_iic_softc *, uint32_t); 218 1.1 jmcneill static int ti_iic_flush(struct ti_iic_softc *); 219 1.1 jmcneill 220 1.1 jmcneill CFATTACH_DECL_NEW(ti_iic, sizeof(struct ti_iic_softc), 221 1.1 jmcneill ti_iic_match, ti_iic_attach, NULL, NULL); 222 1.1 jmcneill 223 1.1 jmcneill static int 224 1.1 jmcneill ti_iic_match(device_t parent, cfdata_t match, void *opaque) 225 1.1 jmcneill { 226 1.1 jmcneill struct fdt_attach_args * const faa = opaque; 227 1.1 jmcneill 228 1.13 thorpej return of_compatible_match(faa->faa_phandle, compat_data); 229 1.1 jmcneill } 230 1.1 jmcneill 231 1.1 jmcneill static void 232 1.1 jmcneill ti_iic_attach(device_t parent, device_t self, void *opaque) 233 1.1 jmcneill { 234 1.1 jmcneill struct ti_iic_softc *sc = device_private(self); 235 1.1 jmcneill struct fdt_attach_args * const faa = opaque; 236 1.1 jmcneill const int phandle = faa->faa_phandle; 237 1.3 jmcneill int fifodepth, fifo; 238 1.3 jmcneill const char *modname; 239 1.1 jmcneill char intrstr[128]; 240 1.1 jmcneill bus_addr_t addr; 241 1.1 jmcneill bus_size_t size; 242 1.1 jmcneill 243 1.1 jmcneill if (fdtbus_get_reg(phandle, 0, &addr, &size) != 0) { 244 1.1 jmcneill aprint_error(": couldn't get registers\n"); 245 1.1 jmcneill return; 246 1.1 jmcneill } 247 1.1 jmcneill if (!fdtbus_intr_str(phandle, 0, intrstr, sizeof(intrstr))) { 248 1.1 jmcneill aprint_error(": couldn't decode interrupt\n"); 249 1.1 jmcneill return; 250 1.1 jmcneill } 251 1.1 jmcneill 252 1.2 jmcneill if (ti_prcm_enable_hwmod(phandle, 0) != 0) { 253 1.1 jmcneill aprint_error(": couldn't enable module\n"); 254 1.1 jmcneill return; 255 1.1 jmcneill } 256 1.1 jmcneill 257 1.1 jmcneill sc->sc_dev = self; 258 1.1 jmcneill sc->sc_iot = faa->faa_bst; 259 1.1 jmcneill mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE); 260 1.1 jmcneill mutex_init(&sc->sc_mtx, MUTEX_DEFAULT, IPL_NET); 261 1.1 jmcneill cv_init(&sc->sc_cv, "tiiic"); 262 1.7 riastrad iic_tag_init(&sc->sc_ic); 263 1.1 jmcneill sc->sc_ic.ic_cookie = sc; 264 1.1 jmcneill sc->sc_ic.ic_acquire_bus = ti_iic_acquire_bus; 265 1.1 jmcneill sc->sc_ic.ic_release_bus = ti_iic_release_bus; 266 1.1 jmcneill sc->sc_ic.ic_exec = ti_iic_exec; 267 1.1 jmcneill 268 1.1 jmcneill if (bus_space_map(sc->sc_iot, addr, size, 0, &sc->sc_ioh) != 0) { 269 1.1 jmcneill aprint_error(": couldn't map registers\n"); 270 1.1 jmcneill return; 271 1.1 jmcneill } 272 1.13 thorpej sc->sc_type = of_compatible_lookup(phandle, compat_data)->value; 273 1.1 jmcneill 274 1.9 jmcneill sc->sc_ih = fdtbus_intr_establish_xname(phandle, 0, IPL_NET, 0, 275 1.9 jmcneill ti_iic_intr, sc, device_xname(self)); 276 1.1 jmcneill if (sc->sc_ih == NULL) { 277 1.1 jmcneill aprint_error(": couldn't establish interrupt\n"); 278 1.1 jmcneill return; 279 1.1 jmcneill } 280 1.1 jmcneill 281 1.3 jmcneill modname = fdtbus_get_string(phandle, "ti,hwmods"); 282 1.3 jmcneill if (modname == NULL) 283 1.3 jmcneill modname = fdtbus_get_string(OF_parent(phandle), "ti,hwmods"); 284 1.1 jmcneill 285 1.3 jmcneill fifodepth = I2C_BUFSTAT_FIFODEPTH(I2C_READ_REG(sc, I2C_BUFSTAT)); 286 1.1 jmcneill fifo = OMAP2_I2C_FIFOBYTES(fifodepth); 287 1.1 jmcneill sc->sc_rxthres = sc->sc_txthres = fifo >> 1; 288 1.1 jmcneill 289 1.3 jmcneill aprint_naive("\n"); 290 1.6 jmcneill if (modname != NULL) 291 1.6 jmcneill aprint_normal(": I2C controller (%s), %d-bytes FIFO\n", modname, fifo); 292 1.6 jmcneill else 293 1.6 jmcneill aprint_normal(": I2C controller (i2c@%" PRIxBUSADDR "), %d-bytes FIFO\n", 294 1.6 jmcneill addr, fifo); 295 1.3 jmcneill 296 1.1 jmcneill ti_iic_reset(sc); 297 1.1 jmcneill ti_iic_flush(sc); 298 1.1 jmcneill 299 1.14 thorpej iicbus_attach(self, &sc->sc_ic); 300 1.1 jmcneill } 301 1.1 jmcneill 302 1.1 jmcneill static int 303 1.1 jmcneill ti_iic_intr(void *arg) 304 1.1 jmcneill { 305 1.1 jmcneill struct ti_iic_softc *sc = arg; 306 1.1 jmcneill uint32_t stat; 307 1.1 jmcneill 308 1.1 jmcneill mutex_enter(&sc->sc_mtx); 309 1.4 jmcneill DPRINTF(("ti_iic_intr opflags=%#x\n", sc->sc_opflags)); 310 1.4 jmcneill if ((sc->sc_opflags & I2C_F_POLL) == 0) { 311 1.4 jmcneill stat = I2C_READ_REG(sc, I2C_IRQSTATUS); 312 1.4 jmcneill DPRINTF(("ti_iic_intr pre handle sc->sc_op eq %#x\n", sc->sc_op)); 313 1.4 jmcneill ti_iic_handle_intr(sc, stat); 314 1.4 jmcneill I2C_WRITE_REG(sc, I2C_IRQSTATUS, stat); 315 1.4 jmcneill if (sc->sc_op == TI_I2CERROR || sc->sc_op == TI_I2CDONE) { 316 1.4 jmcneill DPRINTF(("ti_iic_intr post handle sc->sc_op %#x\n", sc->sc_op)); 317 1.4 jmcneill cv_broadcast(&sc->sc_cv); 318 1.4 jmcneill } 319 1.1 jmcneill } 320 1.1 jmcneill mutex_exit(&sc->sc_mtx); 321 1.1 jmcneill DPRINTF(("ti_iic_intr status 0x%x\n", stat)); 322 1.1 jmcneill return 1; 323 1.1 jmcneill } 324 1.1 jmcneill 325 1.1 jmcneill static int 326 1.1 jmcneill ti_iic_acquire_bus(void *opaque, int flags) 327 1.1 jmcneill { 328 1.1 jmcneill struct ti_iic_softc *sc = opaque; 329 1.1 jmcneill 330 1.1 jmcneill mutex_enter(&sc->sc_lock); 331 1.1 jmcneill while (sc->sc_busy) 332 1.1 jmcneill cv_wait(&sc->sc_cv, &sc->sc_lock); 333 1.1 jmcneill sc->sc_busy = true; 334 1.1 jmcneill mutex_exit(&sc->sc_lock); 335 1.1 jmcneill 336 1.1 jmcneill return 0; 337 1.1 jmcneill } 338 1.1 jmcneill 339 1.1 jmcneill static void 340 1.1 jmcneill ti_iic_release_bus(void *opaque, int flags) 341 1.1 jmcneill { 342 1.1 jmcneill struct ti_iic_softc *sc = opaque; 343 1.1 jmcneill 344 1.1 jmcneill mutex_enter(&sc->sc_lock); 345 1.1 jmcneill sc->sc_busy = false; 346 1.1 jmcneill cv_broadcast(&sc->sc_cv); 347 1.1 jmcneill mutex_exit(&sc->sc_lock); 348 1.1 jmcneill } 349 1.1 jmcneill 350 1.1 jmcneill static int 351 1.1 jmcneill ti_iic_exec(void *opaque, i2c_op_t op, i2c_addr_t addr, 352 1.1 jmcneill const void *cmdbuf, size_t cmdlen, void *buf, size_t len, int flags) 353 1.1 jmcneill { 354 1.1 jmcneill struct ti_iic_softc *sc = opaque; 355 1.1 jmcneill int err; 356 1.1 jmcneill 357 1.1 jmcneill DPRINTF(("ti_iic_exec: op 0x%x cmdlen %zd len %zd flags 0x%x\n", 358 1.1 jmcneill op, cmdlen, len, flags)); 359 1.1 jmcneill 360 1.1 jmcneill if (cmdlen > 0) { 361 1.1 jmcneill err = ti_iic_op(sc, addr, TI_I2CWRITE, 362 1.1 jmcneill __UNCONST(cmdbuf), cmdlen, 363 1.1 jmcneill (I2C_OP_READ_P(op) ? 0 : I2C_F_STOP) | flags); 364 1.1 jmcneill if (err) 365 1.1 jmcneill goto done; 366 1.1 jmcneill } 367 1.1 jmcneill 368 1.1 jmcneill if (I2C_OP_STOP_P(op)) 369 1.1 jmcneill flags |= I2C_F_STOP; 370 1.1 jmcneill 371 1.1 jmcneill /* 372 1.1 jmcneill * I2C controller doesn't allow for zero-byte transfers. 373 1.1 jmcneill */ 374 1.1 jmcneill if (len == 0) { 375 1.1 jmcneill err = EINVAL; 376 1.1 jmcneill goto done; 377 1.1 jmcneill } 378 1.1 jmcneill 379 1.1 jmcneill if (I2C_OP_READ_P(op)) { 380 1.1 jmcneill err = ti_iic_op(sc, addr, TI_I2CREAD, buf, len, flags); 381 1.1 jmcneill } else { 382 1.1 jmcneill err = ti_iic_op(sc, addr, TI_I2CWRITE, buf, len, flags); 383 1.1 jmcneill } 384 1.1 jmcneill 385 1.1 jmcneill done: 386 1.1 jmcneill if (err) 387 1.1 jmcneill ti_iic_reset(sc); 388 1.1 jmcneill 389 1.1 jmcneill ti_iic_flush(sc); 390 1.1 jmcneill 391 1.1 jmcneill DPRINTF(("ti_iic_exec: done %d\n", err)); 392 1.1 jmcneill return err; 393 1.1 jmcneill } 394 1.1 jmcneill 395 1.1 jmcneill static int 396 1.1 jmcneill ti_iic_reset(struct ti_iic_softc *sc) 397 1.1 jmcneill { 398 1.1 jmcneill uint32_t psc, scll, sclh; 399 1.1 jmcneill int i; 400 1.1 jmcneill 401 1.1 jmcneill DPRINTF(("ti_iic_reset\n")); 402 1.1 jmcneill 403 1.1 jmcneill /* Disable */ 404 1.3 jmcneill I2C_WRITE_REG(sc, I2C_CON, 0); 405 1.1 jmcneill /* Soft reset */ 406 1.3 jmcneill I2C_WRITE_REG(sc, I2C_SYSC, I2C_SYSC_SRST); 407 1.1 jmcneill delay(1000); 408 1.1 jmcneill /* enable so that we can check for reset complete */ 409 1.3 jmcneill I2C_WRITE_REG(sc, I2C_CON, I2C_CON_EN); 410 1.1 jmcneill delay(1000); 411 1.1 jmcneill for (i = 0; i < 1000; i++) { /* 1s delay for reset */ 412 1.3 jmcneill if (I2C_READ_REG(sc, I2C_SYSS) & I2C_SYSS_RDONE) 413 1.1 jmcneill break; 414 1.1 jmcneill } 415 1.1 jmcneill /* Disable again */ 416 1.3 jmcneill I2C_WRITE_REG(sc, I2C_CON, 0); 417 1.1 jmcneill delay(50000); 418 1.1 jmcneill 419 1.1 jmcneill if (i >= 1000) { 420 1.1 jmcneill aprint_error_dev(sc->sc_dev, ": couldn't reset module\n"); 421 1.1 jmcneill return 1; 422 1.1 jmcneill } 423 1.1 jmcneill 424 1.1 jmcneill 425 1.1 jmcneill /* XXX standard speed only */ 426 1.4 jmcneill if (sc->sc_type == TI_IIC_OMAP3) { 427 1.4 jmcneill psc = (96000000 / 19200000) - 1; 428 1.4 jmcneill scll = sclh = (19200000 / (2 * 100000)) - 6; 429 1.4 jmcneill } else { 430 1.4 jmcneill psc = 3; 431 1.4 jmcneill scll = 53; 432 1.4 jmcneill sclh = 55; 433 1.4 jmcneill } 434 1.1 jmcneill 435 1.1 jmcneill /* Clocks */ 436 1.3 jmcneill I2C_WRITE_REG(sc, I2C_PSC, psc); 437 1.3 jmcneill I2C_WRITE_REG(sc, I2C_SCLL, scll); 438 1.3 jmcneill I2C_WRITE_REG(sc, I2C_SCLH, sclh); 439 1.1 jmcneill 440 1.1 jmcneill /* Own I2C address */ 441 1.3 jmcneill I2C_WRITE_REG(sc, I2C_OA, OMAP2_I2C_SLAVE_ADDR); 442 1.1 jmcneill 443 1.1 jmcneill /* 5 bytes fifo */ 444 1.3 jmcneill I2C_WRITE_REG(sc, I2C_BUF, 445 1.1 jmcneill I2C_BUF_RXTRSH(sc->sc_rxthres) | I2C_BUF_TXTRSH(sc->sc_txthres)); 446 1.1 jmcneill 447 1.1 jmcneill /* Enable */ 448 1.3 jmcneill I2C_WRITE_REG(sc, I2C_CON, I2C_CON_EN); 449 1.1 jmcneill 450 1.1 jmcneill return 0; 451 1.1 jmcneill } 452 1.1 jmcneill 453 1.1 jmcneill static int 454 1.1 jmcneill ti_iic_op(struct ti_iic_softc *sc, i2c_addr_t addr, ti_i2cop_t op, 455 1.1 jmcneill uint8_t *buf, size_t buflen, int flags) 456 1.1 jmcneill { 457 1.1 jmcneill uint16_t con, stat, mask; 458 1.1 jmcneill int err, retry; 459 1.1 jmcneill 460 1.1 jmcneill KASSERT(op == TI_I2CREAD || op == TI_I2CWRITE); 461 1.1 jmcneill DPRINTF(("ti_iic_op: addr %#x op %#x buf %p buflen %#x flags %#x\n", 462 1.1 jmcneill addr, op, buf, (unsigned int) buflen, flags)); 463 1.1 jmcneill 464 1.1 jmcneill mask = I2C_IRQSTATUS_ARDY | I2C_IRQSTATUS_NACK | I2C_IRQSTATUS_AL; 465 1.1 jmcneill if (op == TI_I2CREAD) { 466 1.1 jmcneill mask |= I2C_IRQSTATUS_RDR | I2C_IRQSTATUS_RRDY; 467 1.1 jmcneill } else { 468 1.1 jmcneill mask |= I2C_IRQSTATUS_XDR | I2C_IRQSTATUS_XRDY; 469 1.1 jmcneill } 470 1.1 jmcneill 471 1.1 jmcneill err = ti_iic_wait(sc, I2C_IRQSTATUS_BB, 0, flags); 472 1.1 jmcneill if (err) { 473 1.1 jmcneill DPRINTF(("ti_iic_op: wait error %d\n", err)); 474 1.1 jmcneill return err; 475 1.1 jmcneill } 476 1.1 jmcneill 477 1.1 jmcneill con = I2C_CON_EN; 478 1.1 jmcneill con |= I2C_CON_MST; 479 1.5 msaitoh con |= I2C_CON_STT; 480 1.1 jmcneill if (flags & I2C_F_STOP) 481 1.1 jmcneill con |= I2C_CON_STP; 482 1.1 jmcneill if (addr & ~0x7f) 483 1.1 jmcneill con |= I2C_CON_XSA; 484 1.1 jmcneill if (op == TI_I2CWRITE) 485 1.1 jmcneill con |= I2C_CON_TRX; 486 1.1 jmcneill 487 1.1 jmcneill mutex_enter(&sc->sc_mtx); 488 1.1 jmcneill sc->sc_op = op; 489 1.4 jmcneill sc->sc_opflags = flags; 490 1.1 jmcneill sc->sc_buf = buf; 491 1.1 jmcneill sc->sc_buflen = buflen; 492 1.1 jmcneill sc->sc_bufidx = 0; 493 1.1 jmcneill 494 1.3 jmcneill I2C_WRITE_REG(sc, I2C_CON, I2C_CON_EN | I2C_CON_MST | I2C_CON_STP); 495 1.1 jmcneill DPRINTF(("ti_iic_op: op %d con 0x%x ", op, con)); 496 1.3 jmcneill I2C_WRITE_REG(sc, I2C_CNT, buflen); 497 1.3 jmcneill I2C_WRITE_REG(sc, I2C_SA, (addr & I2C_SA_MASK)); 498 1.3 jmcneill DPRINTF(("SA 0x%x len %d\n", I2C_READ_REG(sc, I2C_SA), I2C_READ_REG(sc, I2C_CNT))); 499 1.1 jmcneill 500 1.4 jmcneill if ((flags & I2C_F_POLL) == 0 || sc->sc_type == TI_IIC_OMAP3) { 501 1.1 jmcneill /* clear any pending interrupt */ 502 1.3 jmcneill I2C_WRITE_REG(sc, I2C_IRQSTATUS, 503 1.3 jmcneill I2C_READ_REG(sc, I2C_IRQSTATUS)); 504 1.1 jmcneill /* and enable */ 505 1.3 jmcneill if (sc->sc_type == TI_IIC_OMAP4) { 506 1.3 jmcneill I2C_WRITE_REG(sc, I2C_IRQENABLE_SET, mask); 507 1.3 jmcneill } else { 508 1.3 jmcneill I2C_WRITE_REG(sc, I2C_IRQENABLE, mask); 509 1.3 jmcneill } 510 1.1 jmcneill } 511 1.1 jmcneill /* start transfer */ 512 1.3 jmcneill I2C_WRITE_REG(sc, I2C_CON, con); 513 1.1 jmcneill 514 1.1 jmcneill if ((flags & I2C_F_POLL) == 0) { 515 1.1 jmcneill /* and wait for completion */ 516 1.1 jmcneill DPRINTF(("ti_iic_op waiting, op %#x\n", sc->sc_op)); 517 1.1 jmcneill while (sc->sc_op == op) { 518 1.1 jmcneill if (cv_timedwait(&sc->sc_cv, &sc->sc_mtx, 519 1.1 jmcneill mstohz(5000)) == EWOULDBLOCK) { 520 1.1 jmcneill /* timeout */ 521 1.1 jmcneill op = TI_I2CERROR; 522 1.1 jmcneill } 523 1.1 jmcneill } 524 1.1 jmcneill DPRINTF(("ti_iic_op waiting done, op %#x\n", sc->sc_op)); 525 1.1 jmcneill 526 1.1 jmcneill /* disable interrupts */ 527 1.3 jmcneill if (sc->sc_type == TI_IIC_OMAP4) { 528 1.3 jmcneill I2C_WRITE_REG(sc, I2C_IRQENABLE_CLR, 0xffff); 529 1.3 jmcneill } else { 530 1.3 jmcneill I2C_WRITE_REG(sc, I2C_IRQENABLE, 0); 531 1.3 jmcneill } 532 1.1 jmcneill } else { 533 1.1 jmcneill /* poll for completion */ 534 1.1 jmcneill DPRINTF(("ti_iic_op polling, op %x\n", sc->sc_op)); 535 1.1 jmcneill while (sc->sc_op == op) { 536 1.1 jmcneill stat = ti_iic_stat(sc, mask); 537 1.1 jmcneill DPRINTF(("ti_iic_op stat 0x%x\n", stat)); 538 1.1 jmcneill if (stat == 0) { 539 1.1 jmcneill /* timeout */ 540 1.1 jmcneill sc->sc_op = TI_I2CERROR; 541 1.1 jmcneill } else { 542 1.1 jmcneill ti_iic_handle_intr(sc, stat); 543 1.1 jmcneill } 544 1.3 jmcneill I2C_WRITE_REG(sc, I2C_IRQSTATUS, stat); 545 1.1 jmcneill } 546 1.1 jmcneill DPRINTF(("ti_iic_op polling done, op now %x\n", sc->sc_op)); 547 1.1 jmcneill } 548 1.1 jmcneill mutex_exit(&sc->sc_mtx); 549 1.1 jmcneill retry = 10000; 550 1.3 jmcneill I2C_WRITE_REG(sc, I2C_CON, 0); 551 1.3 jmcneill while (I2C_READ_REG(sc, I2C_CON) & I2C_CON_MST) { 552 1.1 jmcneill delay(100); 553 1.1 jmcneill if (--retry == 0) 554 1.1 jmcneill break; 555 1.1 jmcneill } 556 1.1 jmcneill return (sc->sc_op == TI_I2CDONE) ? 0 : EIO; 557 1.1 jmcneill } 558 1.1 jmcneill 559 1.1 jmcneill static void 560 1.1 jmcneill ti_iic_handle_intr(struct ti_iic_softc *sc, uint32_t stat) 561 1.1 jmcneill { 562 1.1 jmcneill KASSERT(mutex_owned(&sc->sc_mtx)); 563 1.1 jmcneill KASSERT(stat != 0); 564 1.1 jmcneill DPRINTF(("ti_iic_handle_intr stat %#x\n", stat)); 565 1.1 jmcneill 566 1.1 jmcneill if (stat & 567 1.1 jmcneill (I2C_IRQSTATUS_NACK|I2C_IRQSTATUS_AL)) { 568 1.1 jmcneill sc->sc_op = TI_I2CERROR; 569 1.1 jmcneill return; 570 1.1 jmcneill } 571 1.1 jmcneill if (stat & I2C_IRQSTATUS_ARDY) { 572 1.1 jmcneill sc->sc_op = TI_I2CDONE; 573 1.1 jmcneill return; 574 1.1 jmcneill } 575 1.1 jmcneill if (sc->sc_op == TI_I2CREAD) 576 1.1 jmcneill ti_iic_do_read(sc, stat); 577 1.1 jmcneill else if (sc->sc_op == TI_I2CWRITE) 578 1.1 jmcneill ti_iic_do_write(sc, stat); 579 1.1 jmcneill else 580 1.1 jmcneill return; 581 1.1 jmcneill } 582 1.1 jmcneill void 583 1.1 jmcneill ti_iic_do_read(struct ti_iic_softc *sc, uint32_t stat) 584 1.1 jmcneill { 585 1.1 jmcneill int len = 0; 586 1.1 jmcneill 587 1.1 jmcneill KASSERT(mutex_owned(&sc->sc_mtx)); 588 1.1 jmcneill DPRINTF(("ti_iic_do_read stat %#x\n", stat)); 589 1.1 jmcneill if (stat & I2C_IRQSTATUS_RDR) { 590 1.3 jmcneill len = I2C_READ_REG(sc, I2C_BUFSTAT); 591 1.1 jmcneill len = I2C_BUFSTAT_RXSTAT(len); 592 1.1 jmcneill DPRINTF(("ti_iic_do_read receive drain len %d left %d\n", 593 1.3 jmcneill len, I2C_READ_REG(sc, I2C_CNT))); 594 1.1 jmcneill } else if (stat & I2C_IRQSTATUS_RRDY) { 595 1.1 jmcneill len = sc->sc_rxthres + 1; 596 1.1 jmcneill DPRINTF(("ti_iic_do_read receive len %d left %d\n", 597 1.3 jmcneill len, I2C_READ_REG(sc, I2C_CNT))); 598 1.1 jmcneill } 599 1.1 jmcneill for (; 600 1.1 jmcneill sc->sc_bufidx < sc->sc_buflen && len > 0; 601 1.1 jmcneill sc->sc_bufidx++, len--) { 602 1.1 jmcneill sc->sc_buf[sc->sc_bufidx] = I2C_READ_DATA(sc); 603 1.1 jmcneill DPRINTF(("ti_iic_do_read got b[%d]=0x%x\n", sc->sc_bufidx, 604 1.1 jmcneill sc->sc_buf[sc->sc_bufidx])); 605 1.1 jmcneill } 606 1.1 jmcneill DPRINTF(("ti_iic_do_read done\n")); 607 1.1 jmcneill } 608 1.1 jmcneill 609 1.1 jmcneill void 610 1.1 jmcneill ti_iic_do_write(struct ti_iic_softc *sc, uint32_t stat) 611 1.1 jmcneill { 612 1.1 jmcneill int len = 0; 613 1.1 jmcneill 614 1.1 jmcneill DPRINTF(("ti_iic_do_write stat %#x\n", stat)); 615 1.1 jmcneill KASSERT(mutex_owned(&sc->sc_mtx)); 616 1.1 jmcneill if (stat & I2C_IRQSTATUS_XDR) { 617 1.3 jmcneill len = I2C_READ_REG(sc, I2C_BUFSTAT); 618 1.1 jmcneill len = I2C_BUFSTAT_TXSTAT(len); 619 1.1 jmcneill DPRINTF(("ti_iic_do_write xmit drain len %d left %d\n", 620 1.3 jmcneill len, I2C_READ_REG(sc, I2C_CNT))); 621 1.1 jmcneill } else if (stat & I2C_IRQSTATUS_XRDY) { 622 1.1 jmcneill len = sc->sc_txthres + 1; 623 1.1 jmcneill DPRINTF(("ti_iic_do_write xmit len %d left %d\n", 624 1.3 jmcneill len, I2C_READ_REG(sc, I2C_CNT))); 625 1.1 jmcneill } 626 1.1 jmcneill for (; 627 1.1 jmcneill sc->sc_bufidx < sc->sc_buflen && len > 0; 628 1.1 jmcneill sc->sc_bufidx++, len--) { 629 1.1 jmcneill DPRINTF(("ti_iic_do_write send b[%d]=0x%x\n", 630 1.1 jmcneill sc->sc_bufidx, sc->sc_buf[sc->sc_bufidx])); 631 1.1 jmcneill I2C_WRITE_DATA(sc, sc->sc_buf[sc->sc_bufidx]); 632 1.1 jmcneill } 633 1.1 jmcneill DPRINTF(("ti_iic_do_write done\n")); 634 1.1 jmcneill } 635 1.1 jmcneill 636 1.1 jmcneill static int 637 1.1 jmcneill ti_iic_wait(struct ti_iic_softc *sc, uint16_t mask, uint16_t val, int flags) 638 1.1 jmcneill { 639 1.1 jmcneill int retry = 10; 640 1.1 jmcneill uint16_t v; 641 1.1 jmcneill DPRINTF(("ti_iic_wait mask %#x val %#x flags %#x\n", mask, val, flags)); 642 1.1 jmcneill 643 1.3 jmcneill while (((v = I2C_READ_REG(sc, I2C_IRQSTATUS_RAW)) & mask) != val) { 644 1.1 jmcneill --retry; 645 1.1 jmcneill if (retry == 0) { 646 1.1 jmcneill aprint_error_dev(sc->sc_dev, ": wait timeout, " 647 1.1 jmcneill "mask = %#x val = %#x stat = %#x\n", 648 1.1 jmcneill mask, val, v); 649 1.1 jmcneill return EBUSY; 650 1.1 jmcneill } 651 1.1 jmcneill if (flags & I2C_F_POLL) { 652 1.1 jmcneill delay(50000); 653 1.1 jmcneill } else { 654 1.1 jmcneill kpause("tiiic", false, mstohz(50), NULL); 655 1.1 jmcneill } 656 1.1 jmcneill } 657 1.1 jmcneill DPRINTF(("ti_iic_wait done retry %#x\n", retry)); 658 1.1 jmcneill 659 1.1 jmcneill return 0; 660 1.1 jmcneill } 661 1.1 jmcneill 662 1.1 jmcneill static uint32_t 663 1.1 jmcneill ti_iic_stat(struct ti_iic_softc *sc, uint32_t mask) 664 1.1 jmcneill { 665 1.1 jmcneill uint32_t v; 666 1.1 jmcneill int retry = 500; 667 1.1 jmcneill DPRINTF(("ti_iic_wait mask %#x\n", mask)); 668 1.1 jmcneill while (--retry > 0) { 669 1.3 jmcneill v = I2C_READ_REG(sc, I2C_IRQSTATUS_RAW) & mask; 670 1.1 jmcneill if (v != 0) 671 1.1 jmcneill break; 672 1.1 jmcneill delay(100); 673 1.1 jmcneill } 674 1.1 jmcneill DPRINTF(("ti_iic_wait done retry %#x\n", retry)); 675 1.1 jmcneill return v; 676 1.1 jmcneill } 677 1.1 jmcneill 678 1.1 jmcneill static int 679 1.1 jmcneill ti_iic_flush(struct ti_iic_softc *sc) 680 1.1 jmcneill { 681 1.1 jmcneill DPRINTF(("ti_iic_flush\n")); 682 1.1 jmcneill #if 0 683 1.1 jmcneill int retry = 1000; 684 1.1 jmcneill uint16_t v; 685 1.1 jmcneill 686 1.3 jmcneill while ((v = I2C_READ_REG(sc, I2C_IRQSTATUS_RAW)) & I2C_IRQSTATUS_RRDY) { 687 1.1 jmcneill if (--retry == 0) { 688 1.1 jmcneill aprint_error_dev(sc->sc_dev, 689 1.1 jmcneill ": flush timeout, stat = %#x\n", v); 690 1.1 jmcneill return EBUSY; 691 1.1 jmcneill } 692 1.1 jmcneill (void)I2C_READ_DATA(sc); 693 1.1 jmcneill delay(1000); 694 1.1 jmcneill } 695 1.1 jmcneill #endif 696 1.1 jmcneill 697 1.3 jmcneill I2C_WRITE_REG(sc, I2C_CNT, 0); 698 1.1 jmcneill return 0; 699 1.1 jmcneill } 700