]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/pcf/pcf.c
fd: make serialization in fdescfree_fds conditional on hold count
[FreeBSD/FreeBSD.git] / sys / dev / pcf / pcf.c
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3  *
4  * Copyright (c) 1998 Nicolas Souchu, Marc Bouget
5  * Copyright (c) 2004 Joerg Wunsch
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  */
29
30 #include <sys/cdefs.h>
31 __FBSDID("$FreeBSD$");
32
33 #include <sys/param.h>
34 #include <sys/bus.h>
35 #include <sys/lock.h>
36 #include <sys/kernel.h>
37 #include <sys/module.h>
38 #include <sys/mutex.h>
39 #include <sys/systm.h>
40
41 #include <machine/bus.h>
42 #include <machine/resource.h>
43
44 #include <sys/rman.h>
45
46 #include <dev/iicbus/iicbus.h>
47 #include <dev/iicbus/iiconf.h>
48 #include <dev/pcf/pcfvar.h>
49 #include "iicbus_if.h"
50
51 /* Not so official debugging option. */
52 /* #define PCFDEBUG */
53
54 static int pcf_wait_byte(struct pcf_softc *pcf);
55 static int pcf_noack(struct pcf_softc *pcf, int timeout);
56 static void pcf_stop_locked(struct pcf_softc *pcf);
57
58 /*
59  * Polling mode for master operations wait for a new
60  * byte incoming or outgoing
61  */
62 static int
63 pcf_wait_byte(struct pcf_softc *sc)
64 {
65         int counter = TIMEOUT;
66
67         PCF_ASSERT_LOCKED(sc);
68         while (counter--) {
69                 if ((pcf_get_S1(sc) & PIN) == 0)
70                         return (0);
71         }
72
73 #ifdef PCFDEBUG
74         printf("pcf: timeout!\n");
75 #endif
76
77         return (IIC_ETIMEOUT);
78 }
79
80 static void
81 pcf_stop_locked(struct pcf_softc *sc)
82 {
83
84         PCF_ASSERT_LOCKED(sc);
85 #ifdef PCFDEBUG
86         device_printf(dev, " >> stop\n");
87 #endif
88         /*
89          * Send STOP condition iff the START condition was previously sent.
90          * STOP is sent only once even if an iicbus_stop() is called after
91          * an iicbus_read()... see pcf_read(): the PCF needs to send the stop
92          * before the last char is read.
93          */
94         if (sc->pcf_started) {
95                 /* set stop condition and enable IT */
96                 pcf_set_S1(sc, PIN|ESO|ENI|STO|ACK);
97
98                 sc->pcf_started = 0;
99         }
100 }
101
102 static int
103 pcf_noack(struct pcf_softc *sc, int timeout)
104 {
105         int noack;
106         int k = timeout/10;
107
108         PCF_ASSERT_LOCKED(sc);
109         do {
110                 noack = pcf_get_S1(sc) & LRB;
111                 if (!noack)
112                         break;
113                 DELAY(10);                              /* XXX wait 10 us */
114         } while (k--);
115
116         return (noack);
117 }
118
119 int
120 pcf_repeated_start(device_t dev, u_char slave, int timeout)
121 {
122         struct pcf_softc *sc = DEVTOSOFTC(dev);
123         int error = 0;
124
125         PCF_LOCK(sc);
126 #ifdef PCFDEBUG
127         device_printf(dev, " >> repeated start for slave %#x\n",
128                       (unsigned)slave);
129 #endif
130         /* repeated start */
131         pcf_set_S1(sc, ESO|STA|STO|ACK);
132
133         /* set slave address to PCF. Last bit (LSB) must be set correctly
134          * according to transfer direction */
135         pcf_set_S0(sc, slave);
136
137         /* wait for address sent, polling */
138         if ((error = pcf_wait_byte(sc)))
139                 goto error;
140
141         /* check for ack */
142         if (pcf_noack(sc, timeout)) {
143                 error = IIC_ENOACK;
144 #ifdef PCFDEBUG
145                 printf("pcf: no ack on repeated_start!\n");
146 #endif
147                 goto error;
148         }
149
150         PCF_UNLOCK(sc);
151         return (0);
152
153 error:
154         pcf_stop_locked(sc);
155         PCF_UNLOCK(sc);
156         return (error);
157 }
158
159 int
160 pcf_start(device_t dev, u_char slave, int timeout)
161 {
162         struct pcf_softc *sc = DEVTOSOFTC(dev);
163         int error = 0;
164
165         PCF_LOCK(sc);
166 #ifdef PCFDEBUG
167         device_printf(dev, " >> start for slave %#x\n", (unsigned)slave);
168 #endif
169         if ((pcf_get_S1(sc) & nBB) == 0) {
170 #ifdef PCFDEBUG
171                 printf("pcf: busy!\n");
172 #endif
173                 PCF_UNLOCK(sc);
174                 return (IIC_EBUSERR);
175         }
176
177         /* set slave address to PCF. Last bit (LSB) must be set correctly
178          * according to transfer direction */
179         pcf_set_S0(sc, slave);
180
181         /* START only */
182         pcf_set_S1(sc, PIN|ESO|STA|ACK);
183
184         sc->pcf_started = 1;
185
186         /* wait for address sent, polling */
187         if ((error = pcf_wait_byte(sc)))
188                 goto error;
189
190         /* check for ACK */
191         if (pcf_noack(sc, timeout)) {
192                 error = IIC_ENOACK;
193 #ifdef PCFDEBUG
194                 printf("pcf: no ack on start!\n");
195 #endif
196                 goto error;
197         }
198
199         PCF_UNLOCK(sc);
200         return (0);
201
202 error:
203         pcf_stop_locked(sc);
204         PCF_UNLOCK(sc);
205         return (error);
206 }
207
208 int
209 pcf_stop(device_t dev)
210 {
211         struct pcf_softc *sc = DEVTOSOFTC(dev);
212
213 #ifdef PCFDEBUG
214         device_printf(dev, " >> stop\n");
215 #endif
216         PCF_LOCK(sc);
217         pcf_stop_locked(sc);
218         PCF_UNLOCK(sc);
219
220         return (0);
221 }
222
223 void
224 pcf_intr(void *arg)
225 {
226         struct pcf_softc *sc = arg;
227         char data, status, addr;
228         char error = 0;
229
230         PCF_LOCK(sc);
231         status = pcf_get_S1(sc);
232
233         if (status & PIN) {
234                 printf("pcf: spurious interrupt, status=0x%x\n",
235                        status & 0xff);
236
237                 goto error;
238         }
239
240         if (status & LAB)
241                 printf("pcf: bus arbitration lost!\n");
242
243         if (status & BER) {
244                 error = IIC_EBUSERR;
245                 iicbus_intr(sc->iicbus, INTR_ERROR, &error);
246
247                 goto error;
248         }
249
250         do {
251                 status = pcf_get_S1(sc);
252
253                 switch(sc->pcf_slave_mode) {
254                 case SLAVE_TRANSMITTER:
255                         if (status & LRB) {
256                                 /* ack interrupt line */
257                                 dummy_write(sc);
258
259                                 /* no ack, don't send anymore */
260                                 sc->pcf_slave_mode = SLAVE_RECEIVER;
261
262                                 iicbus_intr(sc->iicbus, INTR_NOACK, NULL);
263                                 break;
264                         }
265
266                         /* get data from upper code */
267                         iicbus_intr(sc->iicbus, INTR_TRANSMIT, &data);
268
269                         pcf_set_S0(sc, data);
270                         break;
271
272                 case SLAVE_RECEIVER:
273                         if (status & AAS) {
274                                 addr = pcf_get_S0(sc);
275
276                                 if (status & AD0)
277                                         iicbus_intr(sc->iicbus, INTR_GENERAL, &addr);
278                                 else
279                                         iicbus_intr(sc->iicbus, INTR_START, &addr);
280
281                                 if (addr & LSB) {
282                                         sc->pcf_slave_mode = SLAVE_TRANSMITTER;
283
284                                         /* get the first char from upper code */
285                                         iicbus_intr(sc->iicbus, INTR_TRANSMIT, &data);
286
287                                         /* send first data byte */
288                                         pcf_set_S0(sc, data);
289                                 }
290
291                                 break;
292                         }
293
294                         /* stop condition received? */
295                         if (status & STS) {
296                                 /* ack interrupt line */
297                                 dummy_read(sc);
298
299                                 /* emulate intr stop condition */
300                                 iicbus_intr(sc->iicbus, INTR_STOP, NULL);
301
302                         } else {
303                                 /* get data, ack interrupt line */
304                                 data = pcf_get_S0(sc);
305
306                                 /* deliver the character */
307                                 iicbus_intr(sc->iicbus, INTR_RECEIVE, &data);
308                         }
309                         break;
310
311                     default:
312                         panic("%s: unknown slave mode (%d)!", __func__,
313                                 sc->pcf_slave_mode);
314                     }
315
316         } while ((pcf_get_S1(sc) & PIN) == 0);
317         PCF_UNLOCK(sc);
318
319         return;
320
321 error:
322         /* unknown event on bus...reset PCF */
323         pcf_set_S1(sc, PIN|ESO|ENI|ACK);
324
325         sc->pcf_slave_mode = SLAVE_RECEIVER;
326         PCF_UNLOCK(sc);
327
328         return;
329 }
330
331 int
332 pcf_rst_card(device_t dev, u_char speed, u_char addr, u_char *oldaddr)
333 {
334         struct pcf_softc *sc = DEVTOSOFTC(dev);
335
336         PCF_LOCK(sc);
337         if (oldaddr)
338                 *oldaddr = sc->pcf_addr;
339
340         /* retrieve own address from bus level */
341         if (!addr)
342                 sc->pcf_addr = PCF_DEFAULT_ADDR;
343         else
344                 sc->pcf_addr = addr;
345
346         pcf_set_S1(sc, PIN);                            /* initialize S1 */
347
348         /* own address S'O<>0 */
349         pcf_set_S0(sc, sc->pcf_addr >> 1);
350
351         /* select clock register */
352         pcf_set_S1(sc, PIN|ES1);
353
354         /* select bus speed : 18=90kb, 19=45kb, 1A=11kb, 1B=1.5kb */
355         switch (speed) {
356         case IIC_SLOW:
357                 pcf_set_S0(sc,  0x1b); /* XXX Sun uses 0x1f */
358                 break;
359
360         case IIC_FAST:
361                 pcf_set_S0(sc,  0x19); /* XXX Sun: 0x1d */
362                 break;
363
364         case IIC_UNKNOWN:
365         case IIC_FASTEST:
366         default:
367                 pcf_set_S0(sc,  0x18); /* XXX Sun: 0x1c */
368                 break;
369         }
370
371         /* set bus on, ack=yes, INT=yes */
372         pcf_set_S1(sc, PIN|ESO|ENI|ACK);
373
374         sc->pcf_slave_mode = SLAVE_RECEIVER;
375         PCF_UNLOCK(sc);
376
377         return (0);
378 }
379
380 int
381 pcf_write(device_t dev, const char *buf, int len, int *sent, int timeout /* us */)
382 {
383         struct pcf_softc *sc = DEVTOSOFTC(dev);
384         int bytes, error = 0;
385
386 #ifdef PCFDEBUG
387         device_printf(dev, " >> writing %d bytes: %#x%s\n", len,
388                       (unsigned)buf[0], len > 1? "...": "");
389 #endif
390
391         bytes = 0;
392         PCF_LOCK(sc);
393         while (len) {
394                 pcf_set_S0(sc, *buf++);
395
396                 /* wait for the byte to be send */
397                 if ((error = pcf_wait_byte(sc)))
398                         goto error;
399
400                 /* check if ack received */
401                 if (pcf_noack(sc, timeout)) {
402                         error = IIC_ENOACK;
403                         goto error;
404                 }
405
406                 len --;
407                 bytes ++;
408         }
409
410 error:
411         *sent = bytes;
412         PCF_UNLOCK(sc);
413
414 #ifdef PCFDEBUG
415         device_printf(dev, " >> %d bytes written (%d)\n", bytes, error);
416 #endif
417
418         return (error);
419 }
420
421 int
422 pcf_read(device_t dev, char *buf, int len, int *read, int last,
423          int delay /* us */)
424 {
425         struct pcf_softc *sc = DEVTOSOFTC(dev);
426         int bytes, error = 0;
427 #ifdef PCFDEBUG
428         char *obuf = buf;
429
430         device_printf(dev, " << reading %d bytes\n", len);
431 #endif
432
433         PCF_LOCK(sc);
434         /* trig the bus to get the first data byte in S0 */
435         if (len) {
436                 if (len == 1 && last)
437                         /* just one byte to read */
438                         pcf_set_S1(sc, ESO);            /* no ack */
439
440                 dummy_read(sc);
441         }
442
443         bytes = 0;
444         while (len) {
445                 /* XXX delay needed here */
446
447                 /* wait for trigged byte */
448                 if ((error = pcf_wait_byte(sc))) {
449                         pcf_stop_locked(sc);
450                         goto error;
451                 }
452
453                 if (len == 1 && last)
454                         /* ok, last data byte already in S0, no I2C activity
455                          * on next pcf_get_S0() */
456                         pcf_stop_locked(sc);
457
458                 else if (len == 2 && last)
459                         /* next trigged byte with no ack */
460                         pcf_set_S1(sc, ESO);
461
462                 /* receive byte, trig next byte */
463                 *buf++ = pcf_get_S0(sc);
464
465                 len --;
466                 bytes ++;
467         }
468
469 error:
470         *read = bytes;
471         PCF_UNLOCK(sc);
472
473 #ifdef PCFDEBUG
474         device_printf(dev, " << %d bytes read (%d): %#x%s\n", bytes, error,
475                       (unsigned)obuf[0], bytes > 1? "...": "");
476 #endif
477
478         return (error);
479 }
480
481 DRIVER_MODULE(iicbus, pcf, iicbus_driver, iicbus_devclass, 0, 0);
482 MODULE_DEPEND(pcf, iicbus, PCF_MINVER, PCF_PREFVER, PCF_MAXVER);
483 MODULE_VERSION(pcf, PCF_MODVER);