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>
| 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: head/sys/dev/iicbus/iiconf.c 289095 2015-10-09 23:20:08Z ian $");
| 28__FBSDID("$FreeBSD: head/sys/dev/iicbus/iiconf.c 289097 2015-10-09 23:58:19Z ian $");
|
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) { 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 (EWOULDBLOCK); 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 while ((error == 0) && (sc->owner != NULL)) 117 error = iicbus_poll(sc, how); 118 119 if (error == 0) { 120 sc->owner = dev; 121 /* 122 * Drop the lock around the call to the bus driver. 123 * This call should be allowed to sleep in the IIC_WAIT case. 124 * Drivers might also need to grab locks that would cause LOR 125 * if our lock is held. 126 */ 127 IICBUS_UNLOCK(sc); 128 /* Ask the underlying layers if the request is ok */ 129 error = IICBUS_CALLBACK(device_get_parent(bus), 130 IIC_REQUEST_BUS, (caddr_t)&how); 131 IICBUS_LOCK(sc); 132 133 if (error != 0) { 134 sc->owner = NULL; 135 wakeup_one(sc); 136 } 137 } 138 139 140 IICBUS_UNLOCK(sc); 141 142 return (error); 143} 144 145/* 146 * iicbus_release_bus() 147 * 148 * Release the device allocated with iicbus_request_dev() 149 */ 150int 151iicbus_release_bus(device_t bus, device_t dev) 152{ 153 struct iicbus_softc *sc = (struct iicbus_softc *)device_get_softc(bus); 154 int error; 155 156 IICBUS_LOCK(sc); 157 158 if (sc->owner != dev) { 159 IICBUS_UNLOCK(sc); 160 return (EACCES); 161 } 162 163 /* 164 * Drop the lock around the call to the bus driver. 165 * This call should be allowed to sleep in the IIC_WAIT case. 166 * Drivers might also need to grab locks that would cause LOR 167 * if our lock is held. 168 */ 169 IICBUS_UNLOCK(sc); 170 /* Ask the underlying layers if the release is ok */ 171 error = IICBUS_CALLBACK(device_get_parent(bus), IIC_RELEASE_BUS, NULL); 172 173 if (error == 0) { 174 IICBUS_LOCK(sc); 175 sc->owner = NULL; 176 177 /* wakeup a waiting thread */ 178 wakeup_one(sc); 179 IICBUS_UNLOCK(sc); 180 } 181 182 return (error); 183} 184 185/* 186 * iicbus_started() 187 * 188 * Test if the iicbus is started by the controller 189 */ 190int 191iicbus_started(device_t bus) 192{ 193 struct iicbus_softc *sc = (struct iicbus_softc *)device_get_softc(bus); 194 195 return (sc->started); 196} 197 198/* 199 * iicbus_start() 200 * 201 * Send start condition to the slave addressed by 'slave' 202 */ 203int 204iicbus_start(device_t bus, u_char slave, int timeout) 205{ 206 struct iicbus_softc *sc = (struct iicbus_softc *)device_get_softc(bus); 207 int error = 0; 208 209 if (sc->started)
| 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) { 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 (EWOULDBLOCK); 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 while ((error == 0) && (sc->owner != NULL)) 117 error = iicbus_poll(sc, how); 118 119 if (error == 0) { 120 sc->owner = dev; 121 /* 122 * Drop the lock around the call to the bus driver. 123 * This call should be allowed to sleep in the IIC_WAIT case. 124 * Drivers might also need to grab locks that would cause LOR 125 * if our lock is held. 126 */ 127 IICBUS_UNLOCK(sc); 128 /* Ask the underlying layers if the request is ok */ 129 error = IICBUS_CALLBACK(device_get_parent(bus), 130 IIC_REQUEST_BUS, (caddr_t)&how); 131 IICBUS_LOCK(sc); 132 133 if (error != 0) { 134 sc->owner = NULL; 135 wakeup_one(sc); 136 } 137 } 138 139 140 IICBUS_UNLOCK(sc); 141 142 return (error); 143} 144 145/* 146 * iicbus_release_bus() 147 * 148 * Release the device allocated with iicbus_request_dev() 149 */ 150int 151iicbus_release_bus(device_t bus, device_t dev) 152{ 153 struct iicbus_softc *sc = (struct iicbus_softc *)device_get_softc(bus); 154 int error; 155 156 IICBUS_LOCK(sc); 157 158 if (sc->owner != dev) { 159 IICBUS_UNLOCK(sc); 160 return (EACCES); 161 } 162 163 /* 164 * Drop the lock around the call to the bus driver. 165 * This call should be allowed to sleep in the IIC_WAIT case. 166 * Drivers might also need to grab locks that would cause LOR 167 * if our lock is held. 168 */ 169 IICBUS_UNLOCK(sc); 170 /* Ask the underlying layers if the release is ok */ 171 error = IICBUS_CALLBACK(device_get_parent(bus), IIC_RELEASE_BUS, NULL); 172 173 if (error == 0) { 174 IICBUS_LOCK(sc); 175 sc->owner = NULL; 176 177 /* wakeup a waiting thread */ 178 wakeup_one(sc); 179 IICBUS_UNLOCK(sc); 180 } 181 182 return (error); 183} 184 185/* 186 * iicbus_started() 187 * 188 * Test if the iicbus is started by the controller 189 */ 190int 191iicbus_started(device_t bus) 192{ 193 struct iicbus_softc *sc = (struct iicbus_softc *)device_get_softc(bus); 194 195 return (sc->started); 196} 197 198/* 199 * iicbus_start() 200 * 201 * Send start condition to the slave addressed by 'slave' 202 */ 203int 204iicbus_start(device_t bus, u_char slave, int timeout) 205{ 206 struct iicbus_softc *sc = (struct iicbus_softc *)device_get_softc(bus); 207 int error = 0; 208 209 if (sc->started)
|
210 return (EINVAL); /* bus already started */
| 210 return (IIC_ESTATUS); /* protocol error, bus already started */
|
211 212 if (!(error = IICBUS_START(device_get_parent(bus), slave, timeout))) 213 sc->started = slave; 214 else 215 sc->started = 0; 216 217 return (error); 218} 219 220/* 221 * iicbus_repeated_start() 222 * 223 * Send start condition to the slave addressed by 'slave' 224 */ 225int 226iicbus_repeated_start(device_t bus, u_char slave, int timeout) 227{ 228 struct iicbus_softc *sc = (struct iicbus_softc *)device_get_softc(bus); 229 int error = 0; 230 231 if (!sc->started)
| 211 212 if (!(error = IICBUS_START(device_get_parent(bus), slave, timeout))) 213 sc->started = slave; 214 else 215 sc->started = 0; 216 217 return (error); 218} 219 220/* 221 * iicbus_repeated_start() 222 * 223 * Send start condition to the slave addressed by 'slave' 224 */ 225int 226iicbus_repeated_start(device_t bus, u_char slave, int timeout) 227{ 228 struct iicbus_softc *sc = (struct iicbus_softc *)device_get_softc(bus); 229 int error = 0; 230 231 if (!sc->started)
|
232 return (EINVAL); /* bus should have been already started */
| 232 return (IIC_ESTATUS); /* protocol error, bus not started */
|
233 234 if (!(error = IICBUS_REPEATED_START(device_get_parent(bus), slave, timeout))) 235 sc->started = slave; 236 else 237 sc->started = 0; 238 239 return (error); 240} 241 242/* 243 * iicbus_stop() 244 * 245 * Send stop condition to the bus 246 */ 247int 248iicbus_stop(device_t bus) 249{ 250 struct iicbus_softc *sc = (struct iicbus_softc *)device_get_softc(bus); 251 int error = 0; 252 253 if (!sc->started)
| 233 234 if (!(error = IICBUS_REPEATED_START(device_get_parent(bus), slave, timeout))) 235 sc->started = slave; 236 else 237 sc->started = 0; 238 239 return (error); 240} 241 242/* 243 * iicbus_stop() 244 * 245 * Send stop condition to the bus 246 */ 247int 248iicbus_stop(device_t bus) 249{ 250 struct iicbus_softc *sc = (struct iicbus_softc *)device_get_softc(bus); 251 int error = 0; 252 253 if (!sc->started)
|
254 return (EINVAL); /* bus not started */
| 254 return (IIC_ESTATUS); /* protocol error, bus not started */
|
255 256 error = IICBUS_STOP(device_get_parent(bus)); 257 258 /* refuse any further access */ 259 sc->started = 0; 260 261 return (error); 262} 263 264/* 265 * iicbus_write() 266 * 267 * Write a block of data to the slave previously started by 268 * iicbus_start() call 269 */ 270int 271iicbus_write(device_t bus, const char *buf, int len, int *sent, int timeout) 272{ 273 struct iicbus_softc *sc = (struct iicbus_softc *)device_get_softc(bus); 274 275 /* a slave must have been started for writing */ 276 if (sc->started == 0 || (sc->strict != 0 && (sc->started & LSB) != 0))
| 255 256 error = IICBUS_STOP(device_get_parent(bus)); 257 258 /* refuse any further access */ 259 sc->started = 0; 260 261 return (error); 262} 263 264/* 265 * iicbus_write() 266 * 267 * Write a block of data to the slave previously started by 268 * iicbus_start() call 269 */ 270int 271iicbus_write(device_t bus, const char *buf, int len, int *sent, int timeout) 272{ 273 struct iicbus_softc *sc = (struct iicbus_softc *)device_get_softc(bus); 274 275 /* a slave must have been started for writing */ 276 if (sc->started == 0 || (sc->strict != 0 && (sc->started & LSB) != 0))
|
277 return (EINVAL);
| 277 return (IIC_ESTATUS);
|
278 279 return (IICBUS_WRITE(device_get_parent(bus), buf, len, sent, timeout)); 280} 281 282/* 283 * iicbus_read() 284 * 285 * Read a block of data from the slave previously started by 286 * iicbus_read() call 287 */ 288int 289iicbus_read(device_t bus, char *buf, int len, int *read, int last, int delay) 290{ 291 struct iicbus_softc *sc = (struct iicbus_softc *)device_get_softc(bus); 292 293 /* a slave must have been started for reading */ 294 if (sc->started == 0 || (sc->strict != 0 && (sc->started & LSB) == 0))
| 278 279 return (IICBUS_WRITE(device_get_parent(bus), buf, len, sent, timeout)); 280} 281 282/* 283 * iicbus_read() 284 * 285 * Read a block of data from the slave previously started by 286 * iicbus_read() call 287 */ 288int 289iicbus_read(device_t bus, char *buf, int len, int *read, int last, int delay) 290{ 291 struct iicbus_softc *sc = (struct iicbus_softc *)device_get_softc(bus); 292 293 /* a slave must have been started for reading */ 294 if (sc->started == 0 || (sc->strict != 0 && (sc->started & LSB) == 0))
|
295 return (EINVAL);
| 295 return (IIC_ESTATUS);
|
296 297 return (IICBUS_READ(device_get_parent(bus), buf, len, read, last, delay)); 298} 299 300/* 301 * iicbus_write_byte() 302 * 303 * Write a byte to the slave previously started by iicbus_start() call 304 */ 305int 306iicbus_write_byte(device_t bus, char byte, int timeout) 307{
| 296 297 return (IICBUS_READ(device_get_parent(bus), buf, len, read, last, delay)); 298} 299 300/* 301 * iicbus_write_byte() 302 * 303 * Write a byte to the slave previously started by iicbus_start() call 304 */ 305int 306iicbus_write_byte(device_t bus, char byte, int timeout) 307{
|
| 308 struct iicbus_softc *sc = device_get_softc(bus);
|
308 char data = byte; 309 int sent; 310
| 309 char data = byte; 310 int sent; 311
|
| 312 /* a slave must have been started for writing */ 313 if (sc->started == 0 || (sc->strict != 0 && (sc->started & LSB) != 0)) 314 return (IIC_ESTATUS); 315
|
311 return (iicbus_write(bus, &data, 1, &sent, timeout)); 312} 313 314/* 315 * iicbus_read_byte() 316 * 317 * Read a byte from the slave previously started by iicbus_start() call 318 */ 319int 320iicbus_read_byte(device_t bus, char *byte, int timeout) 321{
| 316 return (iicbus_write(bus, &data, 1, &sent, timeout)); 317} 318 319/* 320 * iicbus_read_byte() 321 * 322 * Read a byte from the slave previously started by iicbus_start() call 323 */ 324int 325iicbus_read_byte(device_t bus, char *byte, int timeout) 326{
|
| 327 struct iicbus_softc *sc = device_get_softc(bus);
|
322 int read; 323
| 328 int read; 329
|
| 330 /* a slave must have been started for reading */ 331 if (sc->started == 0 || (sc->strict != 0 && (sc->started & LSB) == 0)) 332 return (IIC_ESTATUS); 333
|
324 return (iicbus_read(bus, byte, 1, &read, IIC_LAST_READ, timeout)); 325} 326 327/* 328 * iicbus_block_write() 329 * 330 * Write a block of data to slave ; start/stop protocol managed 331 */ 332int 333iicbus_block_write(device_t bus, u_char slave, char *buf, int len, int *sent) 334{ 335 u_char addr = slave & ~LSB; 336 int error; 337 338 if ((error = iicbus_start(bus, addr, 0))) 339 return (error); 340 341 error = iicbus_write(bus, buf, len, sent, 0); 342 343 iicbus_stop(bus); 344 345 return (error); 346} 347 348/* 349 * iicbus_block_read() 350 * 351 * Read a block of data from slave ; start/stop protocol managed 352 */ 353int 354iicbus_block_read(device_t bus, u_char slave, char *buf, int len, int *read) 355{ 356 u_char addr = slave | LSB; 357 int error; 358 359 if ((error = iicbus_start(bus, addr, 0))) 360 return (error); 361 362 error = iicbus_read(bus, buf, len, read, IIC_LAST_READ, 0); 363 364 iicbus_stop(bus); 365 366 return (error); 367} 368 369/* 370 * iicbus_transfer() 371 * 372 * Do an aribtrary number of transfers on the iicbus. We pass these 373 * raw requests to the bridge driver. If the bridge driver supports 374 * them directly, then it manages all the details. If not, it can use 375 * the helper function iicbus_transfer_gen() which will do the 376 * transfers at a low level. 377 * 378 * Pointers passed in as part of iic_msg must be kernel pointers. 379 * Callers that have user addresses to manage must do so on their own. 380 */ 381int 382iicbus_transfer(device_t bus, struct iic_msg *msgs, uint32_t nmsgs) 383{
| 334 return (iicbus_read(bus, byte, 1, &read, IIC_LAST_READ, timeout)); 335} 336 337/* 338 * iicbus_block_write() 339 * 340 * Write a block of data to slave ; start/stop protocol managed 341 */ 342int 343iicbus_block_write(device_t bus, u_char slave, char *buf, int len, int *sent) 344{ 345 u_char addr = slave & ~LSB; 346 int error; 347 348 if ((error = iicbus_start(bus, addr, 0))) 349 return (error); 350 351 error = iicbus_write(bus, buf, len, sent, 0); 352 353 iicbus_stop(bus); 354 355 return (error); 356} 357 358/* 359 * iicbus_block_read() 360 * 361 * Read a block of data from slave ; start/stop protocol managed 362 */ 363int 364iicbus_block_read(device_t bus, u_char slave, char *buf, int len, int *read) 365{ 366 u_char addr = slave | LSB; 367 int error; 368 369 if ((error = iicbus_start(bus, addr, 0))) 370 return (error); 371 372 error = iicbus_read(bus, buf, len, read, IIC_LAST_READ, 0); 373 374 iicbus_stop(bus); 375 376 return (error); 377} 378 379/* 380 * iicbus_transfer() 381 * 382 * Do an aribtrary number of transfers on the iicbus. We pass these 383 * raw requests to the bridge driver. If the bridge driver supports 384 * them directly, then it manages all the details. If not, it can use 385 * the helper function iicbus_transfer_gen() which will do the 386 * transfers at a low level. 387 * 388 * Pointers passed in as part of iic_msg must be kernel pointers. 389 * Callers that have user addresses to manage must do so on their own. 390 */ 391int 392iicbus_transfer(device_t bus, struct iic_msg *msgs, uint32_t nmsgs) 393{
|
| 394
|
384 return (IICBUS_TRANSFER(device_get_parent(bus), msgs, nmsgs)); 385} 386 387/* 388 * Generic version of iicbus_transfer that calls the appropriate 389 * routines to accomplish this. See note above about acceptable 390 * buffer addresses. 391 */ 392int 393iicbus_transfer_gen(device_t dev, struct iic_msg *msgs, uint32_t nmsgs) 394{ 395 int i, error, lenread, lenwrote, nkid, rpstart, addr; 396 device_t *children, bus; 397 bool nostop; 398 399 if ((error = device_get_children(dev, &children, &nkid)) != 0)
| 395 return (IICBUS_TRANSFER(device_get_parent(bus), msgs, nmsgs)); 396} 397 398/* 399 * Generic version of iicbus_transfer that calls the appropriate 400 * routines to accomplish this. See note above about acceptable 401 * buffer addresses. 402 */ 403int 404iicbus_transfer_gen(device_t dev, struct iic_msg *msgs, uint32_t nmsgs) 405{ 406 int i, error, lenread, lenwrote, nkid, rpstart, addr; 407 device_t *children, bus; 408 bool nostop; 409 410 if ((error = device_get_children(dev, &children, &nkid)) != 0)
|
400 return (error);
| 411 return (IIC_ERESOURCE);
|
401 if (nkid != 1) { 402 free(children, M_TEMP);
| 412 if (nkid != 1) { 413 free(children, M_TEMP);
|
403 return (EIO);
| 414 return (IIC_ENOTSUPP);
|
404 } 405 bus = children[0]; 406 rpstart = 0; 407 free(children, M_TEMP); 408 nostop = iicbus_get_nostop(dev); 409 for (i = 0, error = 0; i < nmsgs && error == 0; i++) { 410 addr = msgs[i].slave; 411 if (msgs[i].flags & IIC_M_RD) 412 addr |= LSB; 413 else 414 addr &= ~LSB; 415 416 if (!(msgs[i].flags & IIC_M_NOSTART)) { 417 if (rpstart) 418 error = iicbus_repeated_start(bus, addr, 0); 419 else 420 error = iicbus_start(bus, addr, 0); 421 } 422 if (error != 0) 423 break; 424 425 if (msgs[i].flags & IIC_M_RD) 426 error = iicbus_read(bus, msgs[i].buf, msgs[i].len, 427 &lenread, IIC_LAST_READ, 0); 428 else 429 error = iicbus_write(bus, msgs[i].buf, msgs[i].len, 430 &lenwrote, 0); 431 if (error != 0) 432 break; 433 434 if ((msgs[i].flags & IIC_M_NOSTOP) != 0 || 435 (nostop && i + 1 < nmsgs)) { 436 rpstart = 1; /* Next message gets repeated start */ 437 } else { 438 rpstart = 0; 439 iicbus_stop(bus); 440 } 441 } 442 if (error != 0 && !nostop) 443 iicbus_stop(bus); 444 return (error); 445}
| 415 } 416 bus = children[0]; 417 rpstart = 0; 418 free(children, M_TEMP); 419 nostop = iicbus_get_nostop(dev); 420 for (i = 0, error = 0; i < nmsgs && error == 0; i++) { 421 addr = msgs[i].slave; 422 if (msgs[i].flags & IIC_M_RD) 423 addr |= LSB; 424 else 425 addr &= ~LSB; 426 427 if (!(msgs[i].flags & IIC_M_NOSTART)) { 428 if (rpstart) 429 error = iicbus_repeated_start(bus, addr, 0); 430 else 431 error = iicbus_start(bus, addr, 0); 432 } 433 if (error != 0) 434 break; 435 436 if (msgs[i].flags & IIC_M_RD) 437 error = iicbus_read(bus, msgs[i].buf, msgs[i].len, 438 &lenread, IIC_LAST_READ, 0); 439 else 440 error = iicbus_write(bus, msgs[i].buf, msgs[i].len, 441 &lenwrote, 0); 442 if (error != 0) 443 break; 444 445 if ((msgs[i].flags & IIC_M_NOSTOP) != 0 || 446 (nostop && i + 1 < nmsgs)) { 447 rpstart = 1; /* Next message gets repeated start */ 448 } else { 449 rpstart = 0; 450 iicbus_stop(bus); 451 } 452 } 453 if (error != 0 && !nostop) 454 iicbus_stop(bus); 455 return (error); 456}
|