1 /* $NetBSD: bcm2835_bsc.c,v 1.2 2014/03/20 05:39:11 ozaki-r Exp $ */ 2 3 /* 4 * Copyright (c) 2012 Jonathan A. Kollasch 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 20 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 21 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 22 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 23 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 25 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 26 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #include <sys/cdefs.h> 30 __KERNEL_RCSID(0, "$NetBSD: bcm2835_bsc.c,v 1.2 2014/03/20 05:39:11 ozaki-r Exp $"); 31 32 #include <sys/param.h> 33 #include <sys/device.h> 34 #include <sys/systm.h> 35 #include <sys/mutex.h> 36 #include <sys/bus.h> 37 #include <sys/intr.h> 38 39 #include <dev/i2c/i2cvar.h> 40 41 #include <arm/broadcom/bcm_amba.h> 42 #include <arm/broadcom/bcm2835reg.h> 43 #include <arm/broadcom/bcm2835_bscreg.h> 44 #include <arm/broadcom/bcm2835_gpio_subr.h> 45 46 #if defined(_KERNEL_OPT) 47 #include "opt_kernhist.h" 48 #endif 49 #include <sys/kernhist.h> 50 51 KERNHIST_DECL(bsciichist); 52 KERNHIST_DEFINE(bsciichist); 53 54 struct bsciic_softc { 55 device_t sc_dev; 56 bus_space_tag_t sc_iot; 57 bus_space_handle_t sc_ioh; 58 bus_size_t sc_ios; 59 struct i2c_controller sc_i2c; 60 kmutex_t sc_buslock; 61 void *sc_inth; 62 }; 63 64 static int bsciic_match(device_t, cfdata_t, void *); 65 static void bsciic_attach(device_t, device_t, void *); 66 67 void bsciic_dump_regs(struct bsciic_softc * const); 68 69 static int bsciic_acquire_bus(void *, int); 70 static void bsciic_release_bus(void *, int); 71 static int bsciic_exec(void *, i2c_op_t, i2c_addr_t, const void *, size_t, 72 void *, size_t, int); 73 74 CFATTACH_DECL_NEW(bsciic, sizeof(struct bsciic_softc), 75 bsciic_match, bsciic_attach, NULL, NULL); 76 77 static int 78 bsciic_match(device_t parent, cfdata_t match, void *aux) 79 { 80 struct amba_attach_args * const aaa = aux; 81 82 if (strcmp(aaa->aaa_name, "bcmbsc") != 0) 83 return 0; 84 85 return 1; 86 } 87 88 static void 89 bsciic_attach(device_t parent, device_t self, void *aux) 90 { 91 struct bsciic_softc * const sc = device_private(self); 92 struct amba_attach_args * const aaa = aux; 93 struct i2cbus_attach_args iba; 94 u_int bscunit = ~0; 95 96 switch (aaa->aaa_addr) { 97 case BCM2835_BSC0_BASE: 98 bscunit = 0; 99 break; 100 case BCM2835_BSC1_BASE: 101 bscunit = 1; 102 break; 103 } 104 105 aprint_naive("\n"); 106 aprint_normal(": BSC%u\n", bscunit); 107 108 KERNHIST_INIT(bsciichist, 512); 109 110 sc->sc_dev = self; 111 112 mutex_init(&sc->sc_buslock, MUTEX_DEFAULT, IPL_NONE); 113 114 sc->sc_iot = aaa->aaa_iot; 115 if (bus_space_map(aaa->aaa_iot, aaa->aaa_addr, aaa->aaa_size, 0, 116 &sc->sc_ioh) != 0) { 117 aprint_error_dev(sc->sc_dev, "unable to map device\n"); 118 return; 119 } 120 sc->sc_ios = aaa->aaa_size; 121 122 switch (aaa->aaa_addr) { 123 case BCM2835_BSC0_BASE: 124 /* SDA0 on GPIO0, SCL0 on GPIO1 */ 125 bcm2835gpio_function_select(0, BCM2835_GPIO_ALT0); 126 bcm2835gpio_function_select(1, BCM2835_GPIO_ALT0); 127 break; 128 case BCM2835_BSC1_BASE: 129 /* SDA1 on GPIO2, SCL1 on GPIO3 */ 130 bcm2835gpio_function_select(2, BCM2835_GPIO_ALT0); 131 bcm2835gpio_function_select(3, BCM2835_GPIO_ALT0); 132 break; 133 } 134 135 /* clear FIFO, disable controller */ 136 bus_space_write_4(sc->sc_iot, sc->sc_ioh, BSC_C, BSC_C_CLEAR_CLEAR); 137 bus_space_write_4(sc->sc_iot, sc->sc_ioh, BSC_S, BSC_S_CLKT | 138 BSC_S_ERR | BSC_S_DONE); 139 bus_space_write_4(sc->sc_iot, sc->sc_ioh, BSC_DIV, 140 __SHIFTIN(250000000/100000, BSC_DIV_CDIV)); // XXX may not be this 141 142 sc->sc_i2c.ic_cookie = sc; 143 sc->sc_i2c.ic_acquire_bus = bsciic_acquire_bus; 144 sc->sc_i2c.ic_release_bus = bsciic_release_bus; 145 sc->sc_i2c.ic_exec = bsciic_exec; 146 147 memset(&iba, 0, sizeof(iba)); 148 149 iba.iba_tag = &sc->sc_i2c; 150 iba.iba_type = 0; 151 config_found_ia(self, "i2cbus", &iba, iicbus_print); 152 } 153 154 void 155 bsciic_dump_regs(struct bsciic_softc * const sc) 156 { 157 KERNHIST_FUNC(__func__); 158 KERNHIST_CALLED(bsciichist); 159 160 KERNHIST_LOG(bsciichist, "C %08x S %08x D %08x A %08x", 161 bus_space_read_4(sc->sc_iot, sc->sc_ioh, BSC_C), 162 bus_space_read_4(sc->sc_iot, sc->sc_ioh, BSC_S), 163 bus_space_read_4(sc->sc_iot, sc->sc_ioh, BSC_DLEN), 164 bus_space_read_4(sc->sc_iot, sc->sc_ioh, BSC_A) 165 ); 166 } 167 168 static int 169 bsciic_acquire_bus(void *v, int flags) 170 { 171 struct bsciic_softc * const sc = v; 172 uint32_t s __diagused; 173 174 mutex_enter(&sc->sc_buslock); 175 176 bus_space_write_4(sc->sc_iot, sc->sc_ioh, BSC_S, BSC_S_CLKT | 177 BSC_S_ERR | BSC_S_DONE); 178 bus_space_write_4(sc->sc_iot, sc->sc_ioh, BSC_C, BSC_C_I2CEN | 179 BSC_C_CLEAR_CLEAR); 180 s = bus_space_read_4(sc->sc_iot, sc->sc_ioh, BSC_S); 181 KASSERT((s & BSC_S_TA) == 0); 182 183 return 0; 184 } 185 186 static void 187 bsciic_release_bus(void *v, int flags) 188 { 189 struct bsciic_softc * const sc = v; 190 191 bus_space_write_4(sc->sc_iot, sc->sc_ioh, BSC_C, BSC_C_CLEAR_CLEAR); 192 193 mutex_exit(&sc->sc_buslock); 194 } 195 196 static int 197 bsciic_exec(void *v, i2c_op_t op, i2c_addr_t addr, const void *cmdbuf, 198 size_t cmdlen, void *databuf, size_t datalen, int flags) 199 { 200 KERNHIST_FUNC(__func__); KERNHIST_CALLED(bsciichist); 201 struct bsciic_softc * const sc = v; 202 uint32_t c, s, dlen, a; 203 uint32_t j; 204 uint8_t *buf; 205 size_t len; 206 size_t pos; 207 int error = 0; 208 const bool isread = I2C_OP_READ_P(op); 209 210 flags |= I2C_F_POLL; 211 212 #if 0 213 device_printf(sc->sc_dev, "exec: op %d, addr 0x%x, cmdbuf %p, " 214 "cmdlen %zu, databuf %p, datalen %zu, flags 0x%x\n", 215 op, addr, cmdbuf, cmdlen, databuf, datalen, flags); 216 #endif 217 218 a = __SHIFTIN(addr, BSC_A_ADDR); 219 c = BSC_C_I2CEN | BSC_C_CLEAR_CLEAR; 220 #if notyet 221 c |= BSC_C_INTR | BSC_C_INTT | BSC_C_INTD; 222 #endif 223 224 buf = __UNCONST(cmdbuf); 225 len = cmdlen; 226 227 if (isread) 228 dlen = cmdlen; 229 else 230 dlen = cmdlen + datalen; 231 dlen = __SHIFTIN(dlen, BSC_DLEN_DLEN); 232 233 s = bus_space_read_4(sc->sc_iot, sc->sc_ioh, BSC_S); 234 if ((s & BSC_S_TA) != 0) 235 bsciic_dump_regs(sc); 236 KASSERT((s & BSC_S_TA) == 0); 237 bus_space_write_4(sc->sc_iot, sc->sc_ioh, BSC_DLEN, dlen); 238 bus_space_write_4(sc->sc_iot, sc->sc_ioh, BSC_A, a); 239 bus_space_write_4(sc->sc_iot, sc->sc_ioh, BSC_C, c | BSC_C_ST); 240 241 do { 242 s = bus_space_read_4(sc->sc_iot, sc->sc_ioh, BSC_S); 243 } while ((s & BSC_S_TA) == 0); 244 245 flood_again: 246 KERNHIST_LOG(bsciichist, "flood top %p %zu", buf, len, 0, 0); 247 j = 10000000; 248 for (pos = 0; pos < len; ) { 249 if (--j == 0) 250 return -1; 251 s = bus_space_read_4(sc->sc_iot, sc->sc_ioh, BSC_S); 252 KERNHIST_LOG(bsciichist, "w s %08x", s, 0, 0, 0); 253 if ((s & BSC_S_CLKT) != 0) { 254 error = EIO; 255 goto done; 256 } 257 if ((s & BSC_S_ERR) != 0) { 258 error = EIO; 259 goto done; 260 } 261 if ((s & BSC_S_DONE) != 0) 262 break; 263 if ((s & BSC_S_TXD) == 0) 264 continue; 265 bus_space_write_4(sc->sc_iot, sc->sc_ioh, BSC_FIFO, buf[pos]); 266 KERNHIST_LOG(bsciichist, "w %p %p %02x", buf, &buf[pos], 267 buf[pos], 0); 268 pos++; 269 } 270 KERNHIST_LOG(bsciichist, "flood bot %p %zu", buf, len, 0, 0); 271 272 if (buf == cmdbuf && !isread) { 273 buf = databuf; 274 len = datalen; 275 goto flood_again; 276 } 277 278 do { 279 s = bus_space_read_4(sc->sc_iot, sc->sc_ioh, BSC_S); 280 } while ((s & BSC_S_TA) != 0); 281 282 s = bus_space_read_4(sc->sc_iot, sc->sc_ioh, BSC_S); 283 s &= BSC_S_CLKT|BSC_S_ERR|BSC_S_DONE; 284 KASSERT((s & BSC_S_DONE) != 0); 285 if (s != 0) 286 bus_space_write_4(sc->sc_iot, sc->sc_ioh, BSC_S, s); 287 288 if (!isread) 289 goto done; 290 291 c |= BSC_C_READ; 292 293 buf = databuf; 294 len = datalen; 295 dlen = datalen; 296 297 dlen = __SHIFTIN(dlen, BSC_DLEN_DLEN); 298 KASSERT(dlen >= 1); 299 bus_space_write_4(sc->sc_iot, sc->sc_ioh, BSC_DLEN, dlen); 300 bus_space_write_4(sc->sc_iot, sc->sc_ioh, BSC_A, a); 301 bus_space_write_4(sc->sc_iot, sc->sc_ioh, BSC_C, c | BSC_C_ST); 302 303 do { 304 s = bus_space_read_4(sc->sc_iot, sc->sc_ioh, BSC_S); 305 } while ((s & BSC_S_TA) == 0); 306 307 KERNHIST_LOG(bsciichist, "drain top %p %zu", buf, len, 0, 0); 308 j = 10000000; 309 for (pos = 0; pos < len; ) { 310 if (--j == 0) 311 return -1; 312 s = bus_space_read_4(sc->sc_iot, sc->sc_ioh, BSC_S); 313 KERNHIST_LOG(bsciichist, "r s %08x", s, 0, 0, 0); 314 if ((s & BSC_S_CLKT) != 0) { 315 error = EIO; 316 goto done; 317 } 318 if ((s & BSC_S_ERR) != 0) { 319 error = EIO; 320 goto done; 321 } 322 if ((s & BSC_S_DONE) != 0) 323 break; 324 if ((s & BSC_S_RXD) == 0) 325 continue; 326 j = 10000000; 327 buf[pos] = bus_space_read_4(sc->sc_iot, sc->sc_ioh, BSC_FIFO); 328 KERNHIST_LOG(bsciichist, "r %p %p %02x", buf, &buf[pos], 329 buf[pos], 0); 330 pos++; 331 } 332 KERNHIST_LOG(bsciichist, "drain bot %p %zu", buf, len, 0, 0); 333 334 do { 335 s = bus_space_read_4(sc->sc_iot, sc->sc_ioh, BSC_S); 336 } while ((s & BSC_S_TA) != 0); 337 338 s = bus_space_read_4(sc->sc_iot, sc->sc_ioh, BSC_S); 339 s &= BSC_S_CLKT|BSC_S_ERR|BSC_S_DONE; 340 KASSERT((s & BSC_S_DONE) != 0); 341 if (s != 0) 342 bus_space_write_4(sc->sc_iot, sc->sc_ioh, BSC_S, s); 343 344 done: 345 bsciic_dump_regs(sc); 346 347 bus_space_write_4(sc->sc_iot, sc->sc_ioh, BSC_DLEN, 0); 348 349 do { 350 s = bus_space_read_4(sc->sc_iot, sc->sc_ioh, BSC_S); 351 } while ((s & BSC_S_TA) != 0); 352 353 bsciic_dump_regs(sc); 354 355 s = bus_space_read_4(sc->sc_iot, sc->sc_ioh, BSC_S); 356 s &= BSC_S_CLKT|BSC_S_ERR|BSC_S_DONE; 357 if (s != 0) 358 bus_space_write_4(sc->sc_iot, sc->sc_ioh, BSC_S, s); 359 360 bsciic_dump_regs(sc); 361 362 return error; 363 } 364