]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/pcf/pcf.c
MFS r354090:
[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
70                 if ((pcf_get_S1(sc) & PIN) == 0)
71                         return (0);
72         }
73
74 #ifdef PCFDEBUG
75         printf("pcf: timeout!\n");
76 #endif
77
78         return (IIC_ETIMEOUT);
79 }
80
81 static void
82 pcf_stop_locked(struct pcf_softc *sc)
83 {
84
85         PCF_ASSERT_LOCKED(sc);
86 #ifdef PCFDEBUG
87         device_printf(dev, " >> stop\n");
88 #endif
89         /*
90          * Send STOP condition iff the START condition was previously sent.
91          * STOP is sent only once even if an iicbus_stop() is called after
92          * an iicbus_read()... see pcf_read(): the PCF needs to send the stop
93          * before the last char is read.
94          */
95         if (sc->pcf_started) {
96                 /* set stop condition and enable IT */
97                 pcf_set_S1(sc, PIN|ESO|ENI|STO|ACK);
98
99                 sc->pcf_started = 0;
100         }
101 }
102
103 static int
104 pcf_noack(struct pcf_softc *sc, int timeout)
105 {
106         int noack;
107         int k = timeout/10;
108
109         PCF_ASSERT_LOCKED(sc);
110         do {
111                 noack = pcf_get_S1(sc) & LRB;
112                 if (!noack)
113                         break;
114                 DELAY(10);                              /* XXX wait 10 us */
115         } while (k--);
116
117         return (noack);
118 }
119
120 int
121 pcf_repeated_start(device_t dev, u_char slave, int timeout)
122 {
123         struct pcf_softc *sc = DEVTOSOFTC(dev);
124         int error = 0;
125
126         PCF_LOCK(sc);
127 #ifdef PCFDEBUG
128         device_printf(dev, " >> repeated start for slave %#x\n",
129                       (unsigned)slave);
130 #endif
131         /* repeated start */
132         pcf_set_S1(sc, ESO|STA|STO|ACK);
133
134         /* set slave address to PCF. Last bit (LSB) must be set correctly
135          * according to transfer direction */
136         pcf_set_S0(sc, slave);
137
138         /* wait for address sent, polling */
139         if ((error = pcf_wait_byte(sc)))
140                 goto error;
141
142         /* check for ack */
143         if (pcf_noack(sc, timeout)) {
144                 error = IIC_ENOACK;
145 #ifdef PCFDEBUG
146                 printf("pcf: no ack on repeated_start!\n");
147 #endif
148                 goto error;
149         }
150
151         PCF_UNLOCK(sc);
152         return (0);
153
154 error:
155         pcf_stop_locked(sc);
156         PCF_UNLOCK(sc);
157         return (error);
158 }
159
160 int
161 pcf_start(device_t dev, u_char slave, int timeout)
162 {
163         struct pcf_softc *sc = DEVTOSOFTC(dev);
164         int error = 0;
165
166         PCF_LOCK(sc);
167 #ifdef PCFDEBUG
168         device_printf(dev, " >> start for slave %#x\n", (unsigned)slave);
169 #endif
170         if ((pcf_get_S1(sc) & nBB) == 0) {
171 #ifdef PCFDEBUG
172                 printf("pcf: busy!\n");
173 #endif
174                 PCF_UNLOCK(sc);
175                 return (IIC_EBUSERR);
176         }
177
178         /* set slave address to PCF. Last bit (LSB) must be set correctly
179          * according to transfer direction */
180         pcf_set_S0(sc, slave);
181
182         /* START only */
183         pcf_set_S1(sc, PIN|ESO|STA|ACK);
184
185         sc->pcf_started = 1;
186
187         /* wait for address sent, polling */
188         if ((error = pcf_wait_byte(sc)))
189                 goto error;
190
191         /* check for ACK */
192         if (pcf_noack(sc, timeout)) {
193                 error = IIC_ENOACK;
194 #ifdef PCFDEBUG
195                 printf("pcf: no ack on start!\n");
196 #endif
197                 goto error;
198         }
199
200         PCF_UNLOCK(sc);
201         return (0);
202
203 error:
204         pcf_stop_locked(sc);
205         PCF_UNLOCK(sc);
206         return (error);
207 }
208
209 int
210 pcf_stop(device_t dev)
211 {
212         struct pcf_softc *sc = DEVTOSOFTC(dev);
213
214 #ifdef PCFDEBUG
215         device_printf(dev, " >> stop\n");
216 #endif
217         PCF_LOCK(sc);
218         pcf_stop_locked(sc);
219         PCF_UNLOCK(sc);
220
221         return (0);
222 }
223
224 void
225 pcf_intr(void *arg)
226 {
227         struct pcf_softc *sc = arg;
228         char data, status, addr;
229         char error = 0;
230
231         PCF_LOCK(sc);
232         status = pcf_get_S1(sc);
233
234         if (status & PIN) {
235                 printf("pcf: spurious interrupt, status=0x%x\n",
236                        status & 0xff);
237
238                 goto error;
239         }
240
241         if (status & LAB)
242                 printf("pcf: bus arbitration lost!\n");
243
244         if (status & BER) {
245                 error = IIC_EBUSERR;
246                 iicbus_intr(sc->iicbus, INTR_ERROR, &error);
247
248                 goto error;
249         }
250
251         do {
252                 status = pcf_get_S1(sc);
253
254                 switch(sc->pcf_slave_mode) {
255
256                 case SLAVE_TRANSMITTER:
257                         if (status & LRB) {
258                                 /* ack interrupt line */
259                                 dummy_write(sc);
260
261                                 /* no ack, don't send anymore */
262                                 sc->pcf_slave_mode = SLAVE_RECEIVER;
263
264                                 iicbus_intr(sc->iicbus, INTR_NOACK, NULL);
265                                 break;
266                         }
267
268                         /* get data from upper code */
269                         iicbus_intr(sc->iicbus, INTR_TRANSMIT, &data);
270
271                         pcf_set_S0(sc, data);
272                         break;
273
274                 case SLAVE_RECEIVER:
275                         if (status & AAS) {
276                                 addr = pcf_get_S0(sc);
277
278                                 if (status & AD0)
279                                         iicbus_intr(sc->iicbus, INTR_GENERAL, &addr);
280                                 else
281                                         iicbus_intr(sc->iicbus, INTR_START, &addr);
282
283                                 if (addr & LSB) {
284                                         sc->pcf_slave_mode = SLAVE_TRANSMITTER;
285
286                                         /* get the first char from upper code */
287                                         iicbus_intr(sc->iicbus, INTR_TRANSMIT, &data);
288
289                                         /* send first data byte */
290                                         pcf_set_S0(sc, data);
291                                 }
292
293                                 break;
294                         }
295
296                         /* stop condition received? */
297                         if (status & STS) {
298                                 /* ack interrupt line */
299                                 dummy_read(sc);
300
301                                 /* emulate intr stop condition */
302                                 iicbus_intr(sc->iicbus, INTR_STOP, NULL);
303
304                         } else {
305                                 /* get data, ack interrupt line */
306                                 data = pcf_get_S0(sc);
307
308                                 /* deliver the character */
309                                 iicbus_intr(sc->iicbus, INTR_RECEIVE, &data);
310                         }
311                         break;
312
313                     default:
314                         panic("%s: unknown slave mode (%d)!", __func__,
315                                 sc->pcf_slave_mode);
316                     }
317
318         } while ((pcf_get_S1(sc) & PIN) == 0);
319         PCF_UNLOCK(sc);
320
321         return;
322
323 error:
324         /* unknown event on bus...reset PCF */
325         pcf_set_S1(sc, PIN|ESO|ENI|ACK);
326
327         sc->pcf_slave_mode = SLAVE_RECEIVER;
328         PCF_UNLOCK(sc);
329
330         return;
331 }
332
333 int
334 pcf_rst_card(device_t dev, u_char speed, u_char addr, u_char *oldaddr)
335 {
336         struct pcf_softc *sc = DEVTOSOFTC(dev);
337
338         PCF_LOCK(sc);
339         if (oldaddr)
340                 *oldaddr = sc->pcf_addr;
341
342         /* retrieve own address from bus level */
343         if (!addr)
344                 sc->pcf_addr = PCF_DEFAULT_ADDR;
345         else
346                 sc->pcf_addr = addr;
347
348         pcf_set_S1(sc, PIN);                            /* initialize S1 */
349
350         /* own address S'O<>0 */
351         pcf_set_S0(sc, sc->pcf_addr >> 1);
352
353         /* select clock register */
354         pcf_set_S1(sc, PIN|ES1);
355
356         /* select bus speed : 18=90kb, 19=45kb, 1A=11kb, 1B=1.5kb */
357         switch (speed) {
358         case IIC_SLOW:
359                 pcf_set_S0(sc,  0x1b); /* XXX Sun uses 0x1f */
360                 break;
361
362         case IIC_FAST:
363                 pcf_set_S0(sc,  0x19); /* XXX Sun: 0x1d */
364                 break;
365
366         case IIC_UNKNOWN:
367         case IIC_FASTEST:
368         default:
369                 pcf_set_S0(sc,  0x18); /* XXX Sun: 0x1c */
370                 break;
371         }
372
373         /* set bus on, ack=yes, INT=yes */
374         pcf_set_S1(sc, PIN|ESO|ENI|ACK);
375
376         sc->pcf_slave_mode = SLAVE_RECEIVER;
377         PCF_UNLOCK(sc);
378
379         return (0);
380 }
381
382 int
383 pcf_write(device_t dev, const char *buf, int len, int *sent, int timeout /* us */)
384 {
385         struct pcf_softc *sc = DEVTOSOFTC(dev);
386         int bytes, error = 0;
387
388 #ifdef PCFDEBUG
389         device_printf(dev, " >> writing %d bytes: %#x%s\n", len,
390                       (unsigned)buf[0], len > 1? "...": "");
391 #endif
392
393         bytes = 0;
394         PCF_LOCK(sc);
395         while (len) {
396
397                 pcf_set_S0(sc, *buf++);
398
399                 /* wait for the byte to be send */
400                 if ((error = pcf_wait_byte(sc)))
401                         goto error;
402
403                 /* check if ack received */
404                 if (pcf_noack(sc, timeout)) {
405                         error = IIC_ENOACK;
406                         goto error;
407                 }
408
409                 len --;
410                 bytes ++;
411         }
412
413 error:
414         *sent = bytes;
415         PCF_UNLOCK(sc);
416
417 #ifdef PCFDEBUG
418         device_printf(dev, " >> %d bytes written (%d)\n", bytes, error);
419 #endif
420
421         return (error);
422 }
423
424 int
425 pcf_read(device_t dev, char *buf, int len, int *read, int last,
426          int delay /* us */)
427 {
428         struct pcf_softc *sc = DEVTOSOFTC(dev);
429         int bytes, error = 0;
430 #ifdef PCFDEBUG
431         char *obuf = buf;
432
433         device_printf(dev, " << reading %d bytes\n", len);
434 #endif
435
436         PCF_LOCK(sc);
437         /* trig the bus to get the first data byte in S0 */
438         if (len) {
439                 if (len == 1 && last)
440                         /* just one byte to read */
441                         pcf_set_S1(sc, ESO);            /* no ack */
442
443                 dummy_read(sc);
444         }
445
446         bytes = 0;
447         while (len) {
448
449                 /* XXX delay needed here */
450
451                 /* wait for trigged byte */
452                 if ((error = pcf_wait_byte(sc))) {
453                         pcf_stop_locked(sc);
454                         goto error;
455                 }
456
457                 if (len == 1 && last)
458                         /* ok, last data byte already in S0, no I2C activity
459                          * on next pcf_get_S0() */
460                         pcf_stop_locked(sc);
461
462                 else if (len == 2 && last)
463                         /* next trigged byte with no ack */
464                         pcf_set_S1(sc, ESO);
465
466                 /* receive byte, trig next byte */
467                 *buf++ = pcf_get_S0(sc);
468
469                 len --;
470                 bytes ++;
471         }
472
473 error:
474         *read = bytes;
475         PCF_UNLOCK(sc);
476
477 #ifdef PCFDEBUG
478         device_printf(dev, " << %d bytes read (%d): %#x%s\n", bytes, error,
479                       (unsigned)obuf[0], bytes > 1? "...": "");
480 #endif
481
482         return (error);
483 }
484
485 DRIVER_MODULE(iicbus, pcf, iicbus_driver, iicbus_devclass, 0, 0);
486 MODULE_DEPEND(pcf, iicbus, PCF_MINVER, PCF_PREFVER, PCF_MAXVER);
487 MODULE_VERSION(pcf, PCF_MODVER);