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