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