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$"); 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 * iicbus_intr() 44 */ 45 void 46 iicbus_intr(device_t bus, int event, char *buf) 47 { 48 struct iicbus_softc *sc = (struct iicbus_softc *)device_get_softc(bus); 49 50 /* call owner's intr routine */ 51 if (sc->owner) 52 IICBUS_INTR(sc->owner, event, buf); 53 54 return; 55 } 56 57 static int 58 iicbus_poll(struct iicbus_softc *sc, int how) 59 { 60 int error; 61 62 IICBUS_ASSERT_LOCKED(sc); 63 switch (how) { 64 case IIC_WAIT | IIC_INTR: 65 error = mtx_sleep(sc, &sc->lock, IICPRI|PCATCH, "iicreq", 0); 66 break; 67 68 case IIC_WAIT | IIC_NOINTR: 69 error = mtx_sleep(sc, &sc->lock, IICPRI, "iicreq", 0); 70 break; 71 72 default: 73 return (EWOULDBLOCK); 74 break; 75 } 76 77 return (error); 78 } 79 80 /* 81 * iicbus_request_bus() 82 * 83 * Allocate the device to perform transfers. 84 * 85 * how : IIC_WAIT or IIC_DONTWAIT 86 */ 87 int 88 iicbus_request_bus(device_t bus, device_t dev, int how) 89 { 90 struct iicbus_softc *sc = (struct iicbus_softc *)device_get_softc(bus); 91 int error = 0; 92 93 /* first, ask the underlying layers if the request is ok */ 94 IICBUS_LOCK(sc); 95 do { 96 error = IICBUS_CALLBACK(device_get_parent(bus), 97 IIC_REQUEST_BUS, (caddr_t)&how); 98 if (error) 99 error = iicbus_poll(sc, how); 100 } while (error == EWOULDBLOCK); 101 102 while (!error) { 103 if (sc->owner && sc->owner != dev) { 104 105 error = iicbus_poll(sc, how); 106 } else { 107 sc->owner = dev; 108 109 IICBUS_UNLOCK(sc); 110 return (0); 111 } 112 113 /* free any allocated resource */ 114 if (error) 115 IICBUS_CALLBACK(device_get_parent(bus), IIC_RELEASE_BUS, 116 (caddr_t)&how); 117 } 118 IICBUS_UNLOCK(sc); 119 120 return (error); 121 } 122 123 /* 124 * iicbus_release_bus() 125 * 126 * Release the device allocated with iicbus_request_dev() 127 */ 128 int 129 iicbus_release_bus(device_t bus, device_t dev) 130 { 131 struct iicbus_softc *sc = (struct iicbus_softc *)device_get_softc(bus); 132 int error; 133 134 /* first, ask the underlying layers if the release is ok */ 135 error = IICBUS_CALLBACK(device_get_parent(bus), IIC_RELEASE_BUS, NULL); 136 137 if (error) 138 return (error); 139 140 IICBUS_LOCK(sc); 141 142 if (sc->owner != dev) { 143 IICBUS_UNLOCK(sc); 144 return (EACCES); 145 } 146 147 sc->owner = NULL; 148 149 /* wakeup waiting processes */ 150 wakeup(sc); 151 IICBUS_UNLOCK(sc); 152 153 return (0); 154 } 155 156 /* 157 * iicbus_started() 158 * 159 * Test if the iicbus is started by the controller 160 */ 161 int 162 iicbus_started(device_t bus) 163 { 164 struct iicbus_softc *sc = (struct iicbus_softc *)device_get_softc(bus); 165 166 return (sc->started); 167 } 168 169 /* 170 * iicbus_start() 171 * 172 * Send start condition to the slave addressed by 'slave' 173 */ 174 int 175 iicbus_start(device_t bus, u_char slave, int timeout) 176 { 177 struct iicbus_softc *sc = (struct iicbus_softc *)device_get_softc(bus); 178 int error = 0; 179 180 if (sc->started) 181 return (EINVAL); /* bus already started */ 182 183 if (!(error = IICBUS_START(device_get_parent(bus), slave, timeout))) 184 sc->started = slave; 185 else 186 sc->started = 0; 187 188 return (error); 189 } 190 191 /* 192 * iicbus_repeated_start() 193 * 194 * Send start condition to the slave addressed by 'slave' 195 */ 196 int 197 iicbus_repeated_start(device_t bus, u_char slave, int timeout) 198 { 199 struct iicbus_softc *sc = (struct iicbus_softc *)device_get_softc(bus); 200 int error = 0; 201 202 if (!sc->started) 203 return (EINVAL); /* bus should have been already started */ 204 205 if (!(error = IICBUS_REPEATED_START(device_get_parent(bus), slave, timeout))) 206 sc->started = slave; 207 else 208 sc->started = 0; 209 210 return (error); 211 } 212 213 /* 214 * iicbus_stop() 215 * 216 * Send stop condition to the bus 217 */ 218 int 219 iicbus_stop(device_t bus) 220 { 221 struct iicbus_softc *sc = (struct iicbus_softc *)device_get_softc(bus); 222 int error = 0; 223 224 if (!sc->started) 225 return (EINVAL); /* bus not started */ 226 227 error = IICBUS_STOP(device_get_parent(bus)); 228 229 /* refuse any further access */ 230 sc->started = 0; 231 232 return (error); 233 } 234 235 /* 236 * iicbus_write() 237 * 238 * Write a block of data to the slave previously started by 239 * iicbus_start() call 240 */ 241 int 242 iicbus_write(device_t bus, const char *buf, int len, int *sent, int timeout) 243 { 244 struct iicbus_softc *sc = (struct iicbus_softc *)device_get_softc(bus); 245 246 /* a slave must have been started for writing */ 247 if (sc->started == 0 || (sc->strict != 0 && (sc->started & LSB) != 0)) 248 return (EINVAL); 249 250 return (IICBUS_WRITE(device_get_parent(bus), buf, len, sent, timeout)); 251 } 252 253 /* 254 * iicbus_read() 255 * 256 * Read a block of data from the slave previously started by 257 * iicbus_read() call 258 */ 259 int 260 iicbus_read(device_t bus, char *buf, int len, int *read, int last, int delay) 261 { 262 struct iicbus_softc *sc = (struct iicbus_softc *)device_get_softc(bus); 263 264 /* a slave must have been started for reading */ 265 if (sc->started == 0 || (sc->strict != 0 && (sc->started & LSB) == 0)) 266 return (EINVAL); 267 268 return (IICBUS_READ(device_get_parent(bus), buf, len, read, last, delay)); 269 } 270 271 /* 272 * iicbus_write_byte() 273 * 274 * Write a byte to the slave previously started by iicbus_start() call 275 */ 276 int 277 iicbus_write_byte(device_t bus, char byte, int timeout) 278 { 279 char data = byte; 280 int sent; 281 282 return (iicbus_write(bus, &data, 1, &sent, timeout)); 283 } 284 285 /* 286 * iicbus_read_byte() 287 * 288 * Read a byte from the slave previously started by iicbus_start() call 289 */ 290 int 291 iicbus_read_byte(device_t bus, char *byte, int timeout) 292 { 293 int read; 294 295 return (iicbus_read(bus, byte, 1, &read, IIC_LAST_READ, timeout)); 296 } 297 298 /* 299 * iicbus_block_write() 300 * 301 * Write a block of data to slave ; start/stop protocol managed 302 */ 303 int 304 iicbus_block_write(device_t bus, u_char slave, char *buf, int len, int *sent) 305 { 306 u_char addr = slave & ~LSB; 307 int error; 308 309 if ((error = iicbus_start(bus, addr, 0))) 310 return (error); 311 312 error = iicbus_write(bus, buf, len, sent, 0); 313 314 iicbus_stop(bus); 315 316 return (error); 317 } 318 319 /* 320 * iicbus_block_read() 321 * 322 * Read a block of data from slave ; start/stop protocol managed 323 */ 324 int 325 iicbus_block_read(device_t bus, u_char slave, char *buf, int len, int *read) 326 { 327 u_char addr = slave | LSB; 328 int error; 329 330 if ((error = iicbus_start(bus, addr, 0))) 331 return (error); 332 333 error = iicbus_read(bus, buf, len, read, IIC_LAST_READ, 0); 334 335 iicbus_stop(bus); 336 337 return (error); 338 } 339 340 /* 341 * iicbus_transfer() 342 * 343 * Do an aribtrary number of transfers on the iicbus. We pass these 344 * raw requests to the bridge driver. If the bridge driver supports 345 * them directly, then it manages all the details. If not, it can use 346 * the helper function iicbus_transfer_gen() which will do the 347 * transfers at a low level. 348 * 349 * Pointers passed in as part of iic_msg must be kernel pointers. 350 * Callers that have user addresses to manage must do so on their own. 351 */ 352 int 353 iicbus_transfer(device_t bus, struct iic_msg *msgs, uint32_t nmsgs) 354 { 355 return (IICBUS_TRANSFER(device_get_parent(bus), msgs, nmsgs)); 356 } 357 358 /* 359 * Generic version of iicbus_transfer that calls the appropriate 360 * routines to accomplish this. See note above about acceptable 361 * buffer addresses. 362 */ 363 int 364 iicbus_transfer_gen(device_t dev, struct iic_msg *msgs, uint32_t nmsgs) 365 { 366 int i, error, lenread, lenwrote, nkid, rpstart, addr; 367 device_t *children, bus; 368 369 if ((error = device_get_children(dev, &children, &nkid)) != 0) 370 return (error); 371 if (nkid != 1) { 372 free(children, M_TEMP); 373 return (EIO); 374 } 375 bus = children[0]; 376 rpstart = 0; 377 free(children, M_TEMP); 378 for (i = 0, error = 0; i < nmsgs && error == 0; i++) { 379 addr = msgs[i].slave; 380 if (msgs[i].flags & IIC_M_RD) 381 addr |= LSB; 382 else 383 addr &= ~LSB; 384 385 if (!(msgs[i].flags & IIC_M_NOSTART)) { 386 if (rpstart) 387 error = iicbus_repeated_start(bus, addr, 0); 388 else 389 error = iicbus_start(bus, addr, 0); 390 } 391 392 if (error) 393 break; 394 395 if (msgs[i].flags & IIC_M_RD) 396 error = iicbus_read(bus, msgs[i].buf, msgs[i].len, 397 &lenread, IIC_LAST_READ, 0); 398 else 399 error = iicbus_write(bus, msgs[i].buf, msgs[i].len, 400 &lenwrote, 0); 401 402 if (!(msgs[i].flags & IIC_M_NOSTOP)) { 403 rpstart = 0; 404 iicbus_stop(bus); 405 } else { 406 rpstart = 1; /* Next message gets repeated start */ 407 } 408 } 409 return (error); 410 } 411