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