1/*- 2 * Copyright (c) 1998 Nicolas Souchu 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27#include <sys/cdefs.h> 28__FBSDID("$FreeBSD: stable/11/sys/dev/iicbus/iiconf.c 350031 2019-07-16 15:02:28Z avg $"); 29 30#include <sys/param.h> 31#include <sys/systm.h> 32#include <sys/lock.h> 33#include <sys/malloc.h> 34#include <sys/module.h> 35#include <sys/mutex.h> 36#include <sys/bus.h> 37 38#include <dev/iicbus/iiconf.h> 39#include <dev/iicbus/iicbus.h> 40#include "iicbus_if.h" 41 42/* 43 * Translate IIC_Exxxxx status values to vaguely-equivelent errno values. 44 */ 45int 46iic2errno(int iic_status) 47{ 48 switch (iic_status) { 49 case IIC_NOERR: return (0); 50 case IIC_EBUSERR: return (EALREADY); 51 case IIC_ENOACK: return (EIO); 52 case IIC_ETIMEOUT: return (ETIMEDOUT); 53 case IIC_EBUSBSY: return (EWOULDBLOCK); 54 case IIC_ESTATUS: return (EPROTO); 55 case IIC_EUNDERFLOW: return (EIO); 56 case IIC_EOVERFLOW: return (EOVERFLOW); 57 case IIC_ENOTSUPP: return (EOPNOTSUPP); 58 case IIC_ENOADDR: return (EADDRNOTAVAIL); 59 case IIC_ERESOURCE: return (ENOMEM); 60 default: return (EIO); 61 } 62} 63 64/* 65 * iicbus_intr() 66 */ 67void 68iicbus_intr(device_t bus, int event, char *buf) 69{ 70 struct iicbus_softc *sc = (struct iicbus_softc *)device_get_softc(bus); 71 72 /* call owner's intr routine */ 73 if (sc->owner) 74 IICBUS_INTR(sc->owner, event, buf); 75 76 return; 77} 78 79static int 80iicbus_poll(struct iicbus_softc *sc, int how) 81{ 82 int error; 83 84 IICBUS_ASSERT_LOCKED(sc); 85 switch (how & IIC_INTRWAIT) { 86 case IIC_WAIT | IIC_INTR: 87 error = mtx_sleep(sc, &sc->lock, IICPRI|PCATCH, "iicreq", 0); 88 break; 89 90 case IIC_WAIT | IIC_NOINTR: 91 error = mtx_sleep(sc, &sc->lock, IICPRI, "iicreq", 0); 92 break; 93 94 default: 95 return (IIC_EBUSBSY); 96 } 97 98 return (error); 99} 100 101/* 102 * iicbus_request_bus() 103 * 104 * Allocate the device to perform transfers. 105 * 106 * how : IIC_WAIT or IIC_DONTWAIT 107 */ 108int 109iicbus_request_bus(device_t bus, device_t dev, int how) 110{ 111 struct iicbus_softc *sc = (struct iicbus_softc *)device_get_softc(bus); 112 int error = 0; 113 114 IICBUS_LOCK(sc); 115 116 for (;;) { 117 if (sc->owner == NULL) 118 break; 119 if ((how & IIC_RECURSIVE) && sc->owner == dev) 120 break; 121 if ((error = iicbus_poll(sc, how)) != 0) 122 break; 123 } 124 125 if (error == 0) { 126 ++sc->owncount; 127 if (sc->owner == NULL) { 128 sc->owner = dev; 129 /* 130 * Drop the lock around the call to the bus driver, it 131 * should be allowed to sleep in the IIC_WAIT case. 132 * Drivers might also need to grab locks that would 133 * cause a LOR if our lock is held. 134 */ 135 IICBUS_UNLOCK(sc); 136 /* Ask the underlying layers if the request is ok */ 137 error = IICBUS_CALLBACK(device_get_parent(bus), 138 IIC_REQUEST_BUS, (caddr_t)&how); 139 IICBUS_LOCK(sc); 140 141 if (error != 0) { 142 sc->owner = NULL; 143 sc->owncount = 0; 144 wakeup_one(sc); 145 } 146 } 147 } 148 149 IICBUS_UNLOCK(sc); 150 151 return (error); 152} 153 154/* 155 * iicbus_release_bus() 156 * 157 * Release the device allocated with iicbus_request_dev() 158 */ 159int 160iicbus_release_bus(device_t bus, device_t dev) 161{ 162 struct iicbus_softc *sc = (struct iicbus_softc *)device_get_softc(bus); 163 164 IICBUS_LOCK(sc); 165 166 if (sc->owner != dev) { 167 IICBUS_UNLOCK(sc); 168 return (IIC_EBUSBSY); 169 } 170 171 if (--sc->owncount == 0) { 172 /* Drop the lock while informing the low-level driver. */ 173 IICBUS_UNLOCK(sc); 174 IICBUS_CALLBACK(device_get_parent(bus), IIC_RELEASE_BUS, NULL); 175 IICBUS_LOCK(sc); 176 sc->owner = NULL; 177 wakeup_one(sc); 178 } 179 IICBUS_UNLOCK(sc); 180 return (0); 181} 182 183/* 184 * iicbus_started() 185 * 186 * Test if the iicbus is started by the controller 187 */ 188int 189iicbus_started(device_t bus) 190{ 191 struct iicbus_softc *sc = (struct iicbus_softc *)device_get_softc(bus); 192 193 return (sc->started); 194} 195 196/* 197 * iicbus_start() 198 * 199 * Send start condition to the slave addressed by 'slave' 200 */ 201int 202iicbus_start(device_t bus, u_char slave, int timeout) 203{ 204 struct iicbus_softc *sc = (struct iicbus_softc *)device_get_softc(bus); 205 int error = 0; 206 207 if (sc->started) 208 return (IIC_ESTATUS); /* protocol error, bus already started */ 209 210 if (!(error = IICBUS_START(device_get_parent(bus), slave, timeout))) 211 sc->started = slave; 212 else 213 sc->started = 0; 214 215 return (error); 216} 217 218/* 219 * iicbus_repeated_start() 220 * 221 * Send start condition to the slave addressed by 'slave' 222 */ 223int 224iicbus_repeated_start(device_t bus, u_char slave, int timeout) 225{ 226 struct iicbus_softc *sc = (struct iicbus_softc *)device_get_softc(bus); 227 int error = 0; 228 229 if (!sc->started) 230 return (IIC_ESTATUS); /* protocol error, bus not started */ 231 232 if (!(error = IICBUS_REPEATED_START(device_get_parent(bus), slave, timeout))) 233 sc->started = slave; 234 else 235 sc->started = 0; 236 237 return (error); 238} 239 240/* 241 * iicbus_stop() 242 * 243 * Send stop condition to the bus 244 */ 245int 246iicbus_stop(device_t bus) 247{ 248 struct iicbus_softc *sc = (struct iicbus_softc *)device_get_softc(bus); 249 int error = 0; 250 251 if (!sc->started) 252 return (IIC_ESTATUS); /* protocol error, bus not started */ 253 254 error = IICBUS_STOP(device_get_parent(bus)); 255 256 /* refuse any further access */ 257 sc->started = 0; 258 259 return (error); 260} 261 262/* 263 * iicbus_write() 264 * 265 * Write a block of data to the slave previously started by 266 * iicbus_start() call 267 */ 268int 269iicbus_write(device_t bus, const char *buf, int len, int *sent, int timeout) 270{ 271 struct iicbus_softc *sc = (struct iicbus_softc *)device_get_softc(bus); 272 273 /* a slave must have been started for writing */ 274 if (sc->started == 0 || (sc->strict != 0 && (sc->started & LSB) != 0)) 275 return (IIC_ESTATUS); 276 277 return (IICBUS_WRITE(device_get_parent(bus), buf, len, sent, timeout)); 278} 279 280/* 281 * iicbus_read() 282 * 283 * Read a block of data from the slave previously started by 284 * iicbus_read() call 285 */ 286int 287iicbus_read(device_t bus, char *buf, int len, int *read, int last, int delay) 288{ 289 struct iicbus_softc *sc = (struct iicbus_softc *)device_get_softc(bus); 290 291 /* a slave must have been started for reading */ 292 if (sc->started == 0 || (sc->strict != 0 && (sc->started & LSB) == 0)) 293 return (IIC_ESTATUS); 294 295 return (IICBUS_READ(device_get_parent(bus), buf, len, read, last, delay)); 296} 297 298/* 299 * iicbus_write_byte() 300 * 301 * Write a byte to the slave previously started by iicbus_start() call 302 */ 303int 304iicbus_write_byte(device_t bus, char byte, int timeout) 305{ 306 struct iicbus_softc *sc = device_get_softc(bus); 307 char data = byte; 308 int sent; 309 310 /* a slave must have been started for writing */ 311 if (sc->started == 0 || (sc->strict != 0 && (sc->started & LSB) != 0)) 312 return (IIC_ESTATUS); 313 314 return (iicbus_write(bus, &data, 1, &sent, timeout)); 315} 316 317/* 318 * iicbus_read_byte() 319 * 320 * Read a byte from the slave previously started by iicbus_start() call 321 */ 322int 323iicbus_read_byte(device_t bus, char *byte, int timeout) 324{ 325 struct iicbus_softc *sc = device_get_softc(bus); 326 int read; 327 328 /* a slave must have been started for reading */ 329 if (sc->started == 0 || (sc->strict != 0 && (sc->started & LSB) == 0)) 330 return (IIC_ESTATUS); 331 332 return (iicbus_read(bus, byte, 1, &read, IIC_LAST_READ, timeout)); 333} 334 335/* 336 * iicbus_block_write() 337 * 338 * Write a block of data to slave ; start/stop protocol managed 339 */ 340int 341iicbus_block_write(device_t bus, u_char slave, char *buf, int len, int *sent) 342{ 343 u_char addr = slave & ~LSB; 344 int error; 345 346 if ((error = iicbus_start(bus, addr, 0))) 347 return (error); 348 349 error = iicbus_write(bus, buf, len, sent, 0); 350 351 iicbus_stop(bus); 352 353 return (error); 354} 355 356/* 357 * iicbus_block_read() 358 * 359 * Read a block of data from slave ; start/stop protocol managed 360 */ 361int 362iicbus_block_read(device_t bus, u_char slave, char *buf, int len, int *read) 363{ 364 u_char addr = slave | LSB; 365 int error; 366 367 if ((error = iicbus_start(bus, addr, 0))) 368 return (error); 369 370 error = iicbus_read(bus, buf, len, read, IIC_LAST_READ, 0); 371 372 iicbus_stop(bus); 373 374 return (error); 375} 376 377/* 378 * iicbus_transfer() 379 * 380 * Do an aribtrary number of transfers on the iicbus. We pass these 381 * raw requests to the bridge driver. If the bridge driver supports 382 * them directly, then it manages all the details. If not, it can use 383 * the helper function iicbus_transfer_gen() which will do the 384 * transfers at a low level. 385 * 386 * Pointers passed in as part of iic_msg must be kernel pointers. 387 * Callers that have user addresses to manage must do so on their own. 388 */ 389int 390iicbus_transfer(device_t bus, struct iic_msg *msgs, uint32_t nmsgs) 391{ 392 393 return (IICBUS_TRANSFER(device_get_parent(bus), msgs, nmsgs)); 394} 395 396int 397iicbus_transfer_excl(device_t dev, struct iic_msg *msgs, uint32_t nmsgs, 398 int how) 399{ 400 device_t bus; 401 int error; 402 403 bus = device_get_parent(dev); 404 error = iicbus_request_bus(bus, dev, how); 405 if (error == 0) 406 error = IICBUS_TRANSFER(bus, msgs, nmsgs); 407 iicbus_release_bus(bus, dev); 408 return (error); 409} 410 411/* 412 * Generic version of iicbus_transfer that calls the appropriate 413 * routines to accomplish this. See note above about acceptable 414 * buffer addresses. 415 */ 416int 417iicbus_transfer_gen(device_t dev, struct iic_msg *msgs, uint32_t nmsgs) 418{ 419 int i, error, lenread, lenwrote, nkid, rpstart, addr; 420 device_t *children, bus; 421 bool started; 422 423 if ((error = device_get_children(dev, &children, &nkid)) != 0) 424 return (IIC_ERESOURCE); 425 if (nkid != 1) { 426 free(children, M_TEMP); 427 return (IIC_ENOTSUPP); 428 } 429 bus = children[0]; 430 rpstart = 0; 431 free(children, M_TEMP); 432 started = false; 433 for (i = 0, error = 0; i < nmsgs && error == 0; i++) { 434 addr = msgs[i].slave; 435 if (msgs[i].flags & IIC_M_RD) 436 addr |= LSB; 437 else 438 addr &= ~LSB; 439 440 if (!(msgs[i].flags & IIC_M_NOSTART)) { 441 if (rpstart) 442 error = iicbus_repeated_start(bus, addr, 0); 443 else 444 error = iicbus_start(bus, addr, 0); 445 if (error != 0) 446 break; 447 started = true; 448 } 449 450 if (msgs[i].flags & IIC_M_RD) 451 error = iicbus_read(bus, msgs[i].buf, msgs[i].len, 452 &lenread, IIC_LAST_READ, 0); 453 else 454 error = iicbus_write(bus, msgs[i].buf, msgs[i].len, 455 &lenwrote, 0); 456 if (error != 0) 457 break; 458 459 if (!(msgs[i].flags & IIC_M_NOSTOP)) { 460 rpstart = 0; 461 iicbus_stop(bus); 462 } else { 463 rpstart = 1; /* Next message gets repeated start */ 464 } 465 } 466 if (error != 0 && started) 467 iicbus_stop(bus); 468 return (error); 469} 470 471int 472iicdev_readfrom(device_t slavedev, uint8_t regaddr, void *buffer, 473 uint16_t buflen, int waithow) 474{ 475 struct iic_msg msgs[2]; 476 uint8_t slaveaddr; 477 478 /* 479 * Two transfers back to back with a repeat-start between them; first we 480 * write the address-within-device, then we read from the device. 481 */ 482 slaveaddr = iicbus_get_addr(slavedev); 483 484 msgs[0].slave = slaveaddr; 485 msgs[0].flags = IIC_M_WR | IIC_M_NOSTOP; 486 msgs[0].len = 1; 487 msgs[0].buf = ®addr; 488 489 msgs[1].slave = slaveaddr; 490 msgs[1].flags = IIC_M_RD; 491 msgs[1].len = buflen; 492 msgs[1].buf = buffer; 493 494 return (iicbus_transfer_excl(slavedev, msgs, nitems(msgs), waithow)); 495} 496 497int iicdev_writeto(device_t slavedev, uint8_t regaddr, void *buffer, 498 uint16_t buflen, int waithow) 499{ 500 struct iic_msg msgs[2]; 501 uint8_t slaveaddr; 502 503 /* 504 * Two transfers back to back with no stop or start between them; first 505 * we write the address then we write the data to that address, all in a 506 * single transfer from two scattered buffers. 507 */ 508 slaveaddr = iicbus_get_addr(slavedev); 509 510 msgs[0].slave = slaveaddr; 511 msgs[0].flags = IIC_M_WR | IIC_M_NOSTOP; 512 msgs[0].len = 1; 513 msgs[0].buf = ®addr; 514 515 msgs[1].slave = slaveaddr; 516 msgs[1].flags = IIC_M_WR | IIC_M_NOSTART; 517 msgs[1].len = buflen; 518 msgs[1].buf = buffer; 519 520 return (iicbus_transfer_excl(slavedev, msgs, nitems(msgs), waithow)); 521} 522