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 * $FreeBSD: src/sys/dev/iicbus/iiconf.c,v 1.10 1999/12/03 08:41:02 mdodd Exp $ 27 * $DragonFly: src/sys/bus/iicbus/iiconf.c,v 1.4 2003/08/07 21:16:45 dillon Exp $ 28 * 29 */ 30 #include <sys/param.h> 31 #include <sys/systm.h> 32 #include <sys/kernel.h> 33 #include <sys/malloc.h> 34 #include <sys/module.h> 35 #include <sys/bus.h> 36 37 #include "iiconf.h" 38 #include "iicbus.h" 39 #include "iicbus_if.h" 40 41 /* 42 * iicbus_intr() 43 */ 44 void 45 iicbus_intr(device_t bus, int event, char *buf) 46 { 47 struct iicbus_softc *sc = (struct iicbus_softc *)device_get_softc(bus); 48 49 /* call owner's intr routine */ 50 if (sc->owner) 51 IICBUS_INTR(sc->owner, event, buf); 52 53 return; 54 } 55 56 /* 57 * iicbus_alloc_bus() 58 * 59 * Allocate a new bus connected to the given parent device 60 */ 61 device_t 62 iicbus_alloc_bus(device_t parent) 63 { 64 device_t child; 65 66 /* add the bus to the parent */ 67 child = device_add_child(parent, "iicbus", -1); 68 69 return (child); 70 } 71 72 static int 73 iicbus_poll(struct iicbus_softc *sc, int how) 74 { 75 int error; 76 77 switch (how) { 78 case (IIC_WAIT | IIC_INTR): 79 error = tsleep(sc, PCATCH, "iicreq", 0); 80 break; 81 82 case (IIC_WAIT | IIC_NOINTR): 83 error = tsleep(sc, 0, "iicreq", 0); 84 break; 85 86 default: 87 return (EWOULDBLOCK); 88 break; 89 } 90 91 return (error); 92 } 93 94 /* 95 * iicbus_request_bus() 96 * 97 * Allocate the device to perform transfers. 98 * 99 * how : IIC_WAIT or IIC_DONTWAIT 100 */ 101 int 102 iicbus_request_bus(device_t bus, device_t dev, int how) 103 { 104 struct iicbus_softc *sc = (struct iicbus_softc *)device_get_softc(bus); 105 int s, error = 0; 106 107 /* first, ask the underlying layers if the request is ok */ 108 do { 109 error = IICBUS_CALLBACK(device_get_parent(bus), 110 IIC_REQUEST_BUS, (caddr_t)&how); 111 if (error) 112 error = iicbus_poll(sc, how); 113 } while (error == EWOULDBLOCK); 114 115 while (!error) { 116 s = splhigh(); 117 if (sc->owner && sc->owner != dev) { 118 splx(s); 119 120 error = iicbus_poll(sc, how); 121 } else { 122 sc->owner = dev; 123 124 splx(s); 125 return (0); 126 } 127 128 /* free any allocated resource */ 129 if (error) 130 IICBUS_CALLBACK(device_get_parent(bus), IIC_RELEASE_BUS, 131 (caddr_t)&how); 132 } 133 134 return (error); 135 } 136 137 /* 138 * iicbus_release_bus() 139 * 140 * Release the device allocated with iicbus_request_dev() 141 */ 142 int 143 iicbus_release_bus(device_t bus, device_t dev) 144 { 145 struct iicbus_softc *sc = (struct iicbus_softc *)device_get_softc(bus); 146 int s, error; 147 148 /* first, ask the underlying layers if the release is ok */ 149 error = IICBUS_CALLBACK(device_get_parent(bus), IIC_RELEASE_BUS, NULL); 150 151 if (error) 152 return (error); 153 154 s = splhigh(); 155 if (sc->owner != dev) { 156 splx(s); 157 return (EACCES); 158 } 159 160 sc->owner = 0; 161 splx(s); 162 163 /* wakeup waiting processes */ 164 wakeup(sc); 165 166 return (0); 167 } 168 169 /* 170 * iicbus_started() 171 * 172 * Test if the iicbus is started by the controller 173 */ 174 int 175 iicbus_started(device_t bus) 176 { 177 struct iicbus_softc *sc = (struct iicbus_softc *)device_get_softc(bus); 178 179 return (sc->started); 180 } 181 182 /* 183 * iicbus_start() 184 * 185 * Send start condition to the slave addressed by 'slave' 186 */ 187 int 188 iicbus_start(device_t bus, u_char slave, int timeout) 189 { 190 struct iicbus_softc *sc = (struct iicbus_softc *)device_get_softc(bus); 191 int error = 0; 192 193 if (sc->started) 194 return (EINVAL); /* bus already started */ 195 196 if (!(error = IICBUS_START(device_get_parent(bus), slave, timeout))) 197 sc->started = slave; 198 else 199 sc->started = 0; 200 201 return (error); 202 } 203 204 /* 205 * iicbus_repeated_start() 206 * 207 * Send start condition to the slave addressed by 'slave' 208 */ 209 int 210 iicbus_repeated_start(device_t bus, u_char slave, int timeout) 211 { 212 struct iicbus_softc *sc = (struct iicbus_softc *)device_get_softc(bus); 213 int error = 0; 214 215 if (!sc->started) 216 return (EINVAL); /* bus should have been already started */ 217 218 if (!(error = IICBUS_REPEATED_START(device_get_parent(bus), slave, timeout))) 219 sc->started = slave; 220 else 221 sc->started = 0; 222 223 return (error); 224 } 225 226 /* 227 * iicbus_stop() 228 * 229 * Send stop condition to the bus 230 */ 231 int 232 iicbus_stop(device_t bus) 233 { 234 struct iicbus_softc *sc = (struct iicbus_softc *)device_get_softc(bus); 235 int error = 0; 236 237 if (!sc->started) 238 return (EINVAL); /* bus not started */ 239 240 error = IICBUS_STOP(device_get_parent(bus)); 241 242 /* refuse any further access */ 243 sc->started = 0; 244 245 return (error); 246 } 247 248 /* 249 * iicbus_write() 250 * 251 * Write a block of data to the slave previously started by 252 * iicbus_start() call 253 */ 254 int 255 iicbus_write(device_t bus, char *buf, int len, int *sent, int timeout) 256 { 257 struct iicbus_softc *sc = (struct iicbus_softc *)device_get_softc(bus); 258 259 /* a slave must have been started with the appropriate address */ 260 if (!sc->started || (sc->started & LSB)) 261 return (EINVAL); 262 263 return (IICBUS_WRITE(device_get_parent(bus), buf, len, sent, timeout)); 264 } 265 266 /* 267 * iicbus_read() 268 * 269 * Read a block of data from the slave previously started by 270 * iicbus_read() call 271 */ 272 int 273 iicbus_read(device_t bus, char *buf, int len, int *read, int last, int delay) 274 { 275 struct iicbus_softc *sc = (struct iicbus_softc *)device_get_softc(bus); 276 277 /* a slave must have been started with the appropriate address */ 278 if (!sc->started || !(sc->started & LSB)) 279 return (EINVAL); 280 281 return (IICBUS_READ(device_get_parent(bus), buf, len, read, last, delay)); 282 } 283 284 /* 285 * iicbus_write_byte() 286 * 287 * Write a byte to the slave previously started by iicbus_start() call 288 */ 289 int 290 iicbus_write_byte(device_t bus, char byte, int timeout) 291 { 292 char data = byte; 293 int sent; 294 295 return (iicbus_write(bus, &data, 1, &sent, timeout)); 296 } 297 298 /* 299 * iicbus_read_byte() 300 * 301 * Read a byte from the slave previously started by iicbus_start() call 302 */ 303 int 304 iicbus_read_byte(device_t bus, char *byte, int timeout) 305 { 306 int read; 307 308 return (iicbus_read(bus, byte, 1, &read, IIC_LAST_READ, timeout)); 309 } 310 311 /* 312 * iicbus_block_write() 313 * 314 * Write a block of data to slave ; start/stop protocol managed 315 */ 316 int 317 iicbus_block_write(device_t bus, u_char slave, char *buf, int len, int *sent) 318 { 319 u_char addr = slave & ~LSB; 320 int error; 321 322 if ((error = iicbus_start(bus, addr, 0))) 323 return (error); 324 325 error = iicbus_write(bus, buf, len, sent, 0); 326 327 iicbus_stop(bus); 328 329 return (error); 330 } 331 332 /* 333 * iicbus_block_read() 334 * 335 * Read a block of data from slave ; start/stop protocol managed 336 */ 337 int 338 iicbus_block_read(device_t bus, u_char slave, char *buf, int len, int *read) 339 { 340 u_char addr = slave | LSB; 341 int error; 342 343 if ((error = iicbus_start(bus, addr, 0))) 344 return (error); 345 346 error = iicbus_read(bus, buf, len, read, IIC_LAST_READ, 0); 347 348 iicbus_stop(bus); 349 350 return (error); 351 } 352 353 /* 354 * iicbus_get_addr() 355 * 356 * Get the I2C 7 bits address of the device 357 */ 358 u_char 359 iicbus_get_addr(device_t dev) 360 { 361 uintptr_t addr; 362 device_t parent = device_get_parent(dev); 363 364 BUS_READ_IVAR(parent, dev, IICBUS_IVAR_ADDR, &addr); 365 366 return ((u_char)addr); 367 } 368 369