1 /* 2 * Copyright (c) 2013 Patrick Wildt <patrick@blueri.se> 3 * 4 * Permission to use, copy, modify, and distribute this software for any 5 * purpose with or without fee is hereby granted, provided that the above 6 * copyright notice and this permission notice appear in all copies. 7 * 8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 */ 16 17 #include <sys/param.h> 18 #include <sys/device.h> 19 #include <sys/kernel.h> 20 #include <sys/kthread.h> 21 #include <sys/malloc.h> 22 #include <sys/systm.h> 23 #include <machine/bus.h> 24 #if NFDT > 0 25 #include <machine/fdt.h> 26 #endif 27 28 #include <armv7/armv7/armv7var.h> 29 #include <armv7/exynos/exgpiovar.h> 30 #include <armv7/exynos/exiicvar.h> 31 #include <armv7/exynos/exclockvar.h> 32 33 /* registers */ 34 #define I2C_CON 0x00 /* control register */ 35 #define I2C_STAT 0x04 /* control/status register */ 36 #define I2C_ADD 0x08 /* address register */ 37 #define I2C_DS 0x0C /* transmit/receive data shift register */ 38 #define I2C_LC 0x10 /* multi-master line control register */ 39 40 /* bits and bytes */ 41 #define I2C_CON_TXCLKVAL_MASK (0xf << 0) /* tx clock = i2cclk / (i2ccon[3:0] + 1) */ 42 #define I2C_CON_INTPENDING (0x1 << 4) /* 0 = no interrupt pending/clear, 1 = pending */ 43 #define I2C_CON_TXRX_INT (0x1 << 5) /* enable/disable */ 44 #define I2C_CON_TXCLKSRC_16 (0x0 << 6) /* i2clk = fpclk/16 */ 45 #define I2C_CON_TXCLKSRC_512 (0x1 << 6) /* i2clk = fpclk/512 */ 46 #define I2C_CON_ACK (0x1 << 7) 47 #define I2C_STAT_LAST_RVCD_BIT (0x1 << 0) /* last received bit 0 => ack, 1 => no ack */ 48 #define I2C_STAT_ADDR_ZERO_FLAG (0x1 << 1) /* 0 => start/stop cond. detected, 1 => received slave addr 0xb */ 49 #define I2C_STAT_ADDR_SLAVE_ZERO_FLAG (0x1 << 2) /* 0 => start/stop cond. detected, 1 => received slave addr matches i2cadd */ 50 #define I2C_STAT_ARBITRATION (0x1 << 3) /* 0 => successul, 1 => failed */ 51 #define I2C_STAT_SERIAL_OUTPUT (0x1 << 4) /* 0 => disable tx/rx, 1 => enable tx/rx */ 52 #define I2C_STAT_BUSY_SIGNAL (0x1 << 5) /* 0 => not busy / stop signal generation, 1 => busy / start signal generation */ 53 #define I2C_STAT_MODE_SEL_SLAVE_RX (0x0 << 6) /* slave receive mode */ 54 #define I2C_STAT_MODE_SEL_SLAVE_TX (0x1 << 6) /* slave transmit mode */ 55 #define I2C_STAT_MODE_SEL_MASTER_RX (0x2 << 6) /* master receive mode */ 56 #define I2C_STAT_MODE_SEL_MASTER_TX (0x3 << 6) /* master transmit */ 57 #define I2C_ADD_SLAVE_ADDR(x) (((x) & 0x7f) << 1) 58 #define I2C_DS_DATA_SHIFT(x) (((x) & 0xff) << 0) 59 60 #define I2C_ACK 0 61 #define I2C_NACK 1 62 #define I2C_TIMEOUT 2 63 64 struct exiic_softc { 65 struct device sc_dev; 66 bus_space_tag_t sc_iot; 67 bus_space_handle_t sc_ioh; 68 bus_size_t sc_ios; 69 void *sc_ih; 70 int unit; 71 72 struct rwlock sc_buslock; 73 struct i2c_controller i2c_tag; 74 75 uint16_t frequency; 76 uint16_t intr_status; 77 }; 78 79 int exiic_match(struct device *parent, void *v, void *aux); 80 void exiic_attach(struct device *, struct device *, void *); 81 int exiic_detach(struct device *, int); 82 void exiic_bus_scan(struct device *, struct i2cbus_attach_args *, void *); 83 void exiic_setspeed(struct exiic_softc *, int); 84 int exiic_intr(void *); 85 int exiic_wait_intr(struct exiic_softc *, int, int); 86 int exiic_wait_state(struct exiic_softc *, uint32_t, uint32_t, uint32_t); 87 int exiic_start(struct exiic_softc *, int, int, void *, int); 88 89 void exiic_xfer_start(struct exiic_softc *); 90 int exiic_xfer_wait(struct exiic_softc *); 91 int exiic_i2c_acquire_bus(void *, int); 92 void exiic_i2c_release_bus(void *, int); 93 int exiic_i2c_exec(void *, i2c_op_t, i2c_addr_t, const void *, size_t, 94 void *, size_t, int); 95 96 #define HREAD4(sc, reg) \ 97 (bus_space_read_4((sc)->sc_iot, (sc)->sc_ioh, (reg))) 98 #define HWRITE4(sc, reg, val) \ 99 bus_space_write_4((sc)->sc_iot, (sc)->sc_ioh, (reg), (val)) 100 #define HSET4(sc, reg, bits) \ 101 HWRITE4((sc), (reg), HREAD4((sc), (reg)) | (bits)) 102 #define HCLR4(sc, reg, bits) \ 103 HWRITE4((sc), (reg), HREAD4((sc), (reg)) & ~(bits)) 104 105 106 struct cfattach exiic_ca = { 107 sizeof(struct exiic_softc), NULL, exiic_attach, exiic_detach 108 }; 109 struct cfattach exiic_fdt_ca = { 110 sizeof(struct exiic_softc), exiic_match, exiic_attach, exiic_detach 111 }; 112 113 struct cfdriver exiic_cd = { 114 NULL, "exiic", DV_DULL 115 }; 116 117 int 118 exiic_match(struct device *parent, void *v, void *aux) 119 { 120 #if NFDT > 0 121 struct armv7_attach_args *aa = aux; 122 123 if (fdt_node_compatible("samsung,s3c2440-i2c", aa->aa_node)) 124 return 1; 125 #endif 126 127 return 0; 128 } 129 130 void 131 exiic_attach(struct device *parent, struct device *self, void *args) 132 { 133 struct exiic_softc *sc = (struct exiic_softc *)self; 134 struct armv7_attach_args *aa = args; 135 struct armv7mem mem; 136 137 sc->sc_iot = aa->aa_iot; 138 #if NFDT > 0 139 if (aa->aa_node) { 140 struct fdt_reg reg; 141 static int unit = 0; 142 143 sc->unit = unit++; 144 if (fdt_get_reg(aa->aa_node, 0, ®)) 145 panic("%s: could not extract memory data from FDT", 146 __func__); 147 mem.addr = reg.addr; 148 mem.size = reg.size; 149 } else 150 #endif 151 { 152 mem.addr = aa->aa_dev->mem[0].addr; 153 mem.size = aa->aa_dev->mem[0].size; 154 sc->unit = aa->aa_dev->unit; 155 } 156 if (bus_space_map(sc->sc_iot, mem.addr, mem.size, 0, &sc->sc_ioh)) 157 panic("%s: bus_space_map failed!", __func__); 158 sc->sc_ios = mem.size; 159 160 #if 0 161 sc->sc_ih = arm_intr_establish(aa->aa_dev->irq[0], IPL_BIO, 162 exiic_intr, sc, sc->sc_dev.dv_xname); 163 #endif 164 165 printf("\n"); 166 167 rw_init(&sc->sc_buslock, sc->sc_dev.dv_xname); 168 169 struct i2cbus_attach_args iba; 170 171 sc->i2c_tag.ic_cookie = sc; 172 sc->i2c_tag.ic_acquire_bus = exiic_i2c_acquire_bus; 173 sc->i2c_tag.ic_release_bus = exiic_i2c_release_bus; 174 sc->i2c_tag.ic_exec = exiic_i2c_exec; 175 176 bzero(&iba, sizeof iba); 177 iba.iba_name = "iic"; 178 iba.iba_tag = &sc->i2c_tag; 179 iba.iba_bus_scan = exiic_bus_scan; 180 iba.iba_bus_scan_arg = sc; 181 config_found(&sc->sc_dev, &iba, NULL); 182 } 183 184 void 185 exiic_bus_scan(struct device *self, struct i2cbus_attach_args *iba, void *arg) 186 { 187 struct exiic_softc *sc = (struct exiic_softc *)arg; 188 struct i2c_attach_args ia; 189 190 /* XXX: We currently only attach cros-ec on I2C4. We'll use FDT later. */ 191 if (sc->unit != 4) 192 return; 193 194 char *name = "crosec"; 195 int addr = 0x1e; 196 197 memset(&ia, 0, sizeof(ia)); 198 ia.ia_tag = iba->iba_tag; 199 ia.ia_addr = addr; 200 ia.ia_size = 1; 201 ia.ia_name = name; 202 config_found(self, &ia, iicbus_print); 203 204 name = "tps65090"; 205 addr = 0x48; 206 207 memset(&ia, 0, sizeof(ia)); 208 ia.ia_tag = iba->iba_tag; 209 ia.ia_addr = addr; 210 ia.ia_size = 1; 211 ia.ia_name = name; 212 config_found(self, &ia, iicbus_print); 213 } 214 215 void 216 exiic_setspeed(struct exiic_softc *sc, int speed) 217 { 218 if (!sc->frequency) { 219 uint32_t freq, div = 0, pres = 16; 220 freq = exclock_get_i2cclk(); 221 222 /* calculate prescaler and divisor values */ 223 if ((freq / pres / (16 + 1)) > speed) 224 /* set prescaler to 512 */ 225 pres = 512; 226 227 while ((freq / pres / (div + 1)) > speed) 228 div++; 229 230 /* set prescaler, divisor according to freq, also set ACKGEN, IRQ */ 231 sc->frequency = (div & 0x0F) | 0xA0 | ((pres == 512) ? 0x40 : 0); 232 } 233 234 HWRITE4(sc, I2C_CON, sc->frequency); 235 } 236 237 #if 0 238 int 239 exiic_intr(void *arg) 240 { 241 struct exiic_softc *sc = arg; 242 u_int16_t status; 243 int rc = 0; 244 245 status = HREAD4(sc, I2C_CON); 246 247 if (ISSET(status, I2C_CON_INTPENDING)) { 248 /* we do not acknowledge the interrupt here */ 249 rc = 1; 250 251 sc->intr_status |= status; 252 wakeup(&sc->intr_status); 253 } 254 255 return (rc); 256 } 257 258 int 259 exiic_wait_intr(struct exiic_softc *sc, int mask, int timo) 260 { 261 int status; 262 int s; 263 264 s = splbio(); 265 266 status = sc->intr_status & mask; 267 while (status == 0) { 268 if (tsleep(&sc->intr_status, PWAIT, "hcintr", timo) 269 == EWOULDBLOCK) { 270 break; 271 } 272 status = sc->intr_status & mask; 273 } 274 status = sc->intr_status & mask; 275 sc->intr_status &= ~status; 276 277 splx(s); 278 return status; 279 } 280 #endif 281 282 int 283 exiic_wait_state(struct exiic_softc *sc, uint32_t reg, uint32_t mask, uint32_t value) 284 { 285 uint32_t state; 286 int timeout; 287 state = HREAD4(sc, reg); 288 for (timeout = 1000; timeout > 0; timeout--) { 289 if (((state = HREAD4(sc, reg)) & mask) == value) 290 return 0; 291 delay(1000); 292 } 293 return ETIMEDOUT; 294 } 295 296 int 297 exiic_i2c_acquire_bus(void *cookie, int flags) 298 { 299 struct exiic_softc *sc = cookie; 300 int ret = rw_enter(&sc->sc_buslock, RW_WRITE); 301 302 if (!ret) { 303 /* set speed to 100 Kbps */ 304 exiic_setspeed(sc, 100); 305 306 /* STOP */ 307 HWRITE4(sc, I2C_STAT, 0); 308 HWRITE4(sc, I2C_ADD, 0); 309 HWRITE4(sc, I2C_STAT, I2C_STAT_MODE_SEL_MASTER_TX 310 | I2C_STAT_SERIAL_OUTPUT); 311 } 312 313 return ret; 314 } 315 316 void 317 exiic_i2c_release_bus(void *cookie, int flags) 318 { 319 struct exiic_softc *sc = cookie; 320 321 (void) rw_exit(&sc->sc_buslock); 322 } 323 324 int 325 exiic_i2c_exec(void *cookie, i2c_op_t op, i2c_addr_t _addr, 326 const void *cmdbuf, size_t cmdlen, void *databuf, size_t datalen, int flags) 327 { 328 struct exiic_softc *sc = cookie; 329 uint32_t ret = 0; 330 u_int8_t addr = 0; 331 int i = 0; 332 333 addr = (_addr & 0x7f) << 1; 334 335 /* clock gating */ 336 //exccm_enable_i2c(sc->unit); 337 338 if (exiic_wait_state(sc, I2C_STAT, I2C_STAT_BUSY_SIGNAL, 0)) { 339 printf("%s: busy\n", __func__); 340 return (EIO); 341 } 342 343 /* acknowledge generation */ 344 HSET4(sc, I2C_CON, I2C_CON_ACK); 345 346 /* Send the slave-address */ 347 HWRITE4(sc, I2C_DS, addr); 348 if (!I2C_OP_READ_P(op) || (cmdbuf && cmdlen)) 349 HWRITE4(sc, I2C_STAT, I2C_STAT_MODE_SEL_MASTER_TX 350 | I2C_STAT_SERIAL_OUTPUT 351 | I2C_STAT_BUSY_SIGNAL); 352 else 353 HWRITE4(sc, I2C_STAT, I2C_STAT_MODE_SEL_MASTER_RX 354 | I2C_STAT_SERIAL_OUTPUT 355 | I2C_STAT_BUSY_SIGNAL); 356 357 ret = exiic_xfer_wait(sc); 358 if (ret != I2C_ACK) 359 goto fail; 360 361 /* transmit commands */ 362 if (cmdbuf && cmdlen) { 363 for (i = 0; i < cmdlen; i++) { 364 HWRITE4(sc, I2C_DS, ((uint8_t *)cmdbuf)[i]); 365 exiic_xfer_start(sc); 366 ret = exiic_xfer_wait(sc); 367 if (ret != I2C_ACK) 368 goto fail; 369 } 370 } 371 372 if (I2C_OP_READ_P(op)) { 373 if (cmdbuf && cmdlen) { 374 /* write slave chip address again for actual read */ 375 HWRITE4(sc, I2C_DS, addr); 376 377 /* restart */ 378 HWRITE4(sc, I2C_STAT, I2C_STAT_MODE_SEL_MASTER_RX 379 | I2C_STAT_SERIAL_OUTPUT 380 | I2C_STAT_BUSY_SIGNAL); 381 exiic_xfer_start(sc); 382 ret = exiic_xfer_wait(sc); 383 if (ret != I2C_ACK) 384 goto fail; 385 } 386 387 for (i = 0; i < datalen && ret == I2C_ACK; i++) { 388 /* disable ACK for final read */ 389 if (i == datalen - 1) 390 HCLR4(sc, I2C_CON, I2C_CON_ACK); 391 exiic_xfer_start(sc); 392 ret = exiic_xfer_wait(sc); 393 ((uint8_t *)databuf)[i] = HREAD4(sc, I2C_DS); 394 } 395 if (ret == I2C_NACK) 396 ret = I2C_ACK; /* Normal terminated read. */ 397 } else { 398 for (i = 0; i < datalen && ret == I2C_ACK; i++) { 399 HWRITE4(sc, I2C_DS, ((uint8_t *)databuf)[i]); 400 exiic_xfer_start(sc); 401 ret = exiic_xfer_wait(sc); 402 } 403 } 404 405 fail: 406 /* send STOP */ 407 if (op & I2C_OP_READ_WITH_STOP) { 408 HWRITE4(sc, I2C_STAT, I2C_STAT_MODE_SEL_MASTER_RX 409 | I2C_STAT_SERIAL_OUTPUT); 410 exiic_xfer_start(sc); 411 } 412 413 return ret; 414 } 415 416 void 417 exiic_xfer_start(struct exiic_softc *sc) 418 { 419 HCLR4(sc, I2C_CON, I2C_CON_INTPENDING); 420 } 421 422 int 423 exiic_xfer_wait(struct exiic_softc *sc) 424 { 425 if (!exiic_wait_state(sc, I2C_CON, I2C_CON_INTPENDING, 426 I2C_CON_INTPENDING)) 427 return (HREAD4(sc, I2C_STAT) & I2C_STAT_LAST_RVCD_BIT) ? 428 I2C_NACK : I2C_ACK; 429 else 430 return I2C_TIMEOUT; 431 } 432 433 int 434 exiic_detach(struct device *self, int flags) 435 { 436 struct exiic_softc *sc = (struct exiic_softc *)self; 437 438 bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_ios); 439 return 0; 440 } 441