]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - sys/dev/pcf/pcf.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / sys / dev / pcf / pcf.c
1 /*-
2  * Copyright (c) 1998 Nicolas Souchu, Marc Bouget
3  * Copyright (c) 2004 Joerg Wunsch
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  */
27
28 #include <sys/cdefs.h>
29 __FBSDID("$FreeBSD$");
30
31 #include <sys/param.h>
32 #include <sys/bus.h>
33 #include <sys/lock.h>
34 #include <sys/kernel.h>
35 #include <sys/module.h>
36 #include <sys/mutex.h>
37 #include <sys/systm.h>
38
39 #include <machine/bus.h>
40 #include <machine/resource.h>
41
42 #include <sys/rman.h>
43
44 #include <dev/iicbus/iicbus.h>
45 #include <dev/iicbus/iiconf.h>
46 #include <dev/pcf/pcfvar.h>
47 #include "iicbus_if.h"
48
49 /* Not so official debugging option. */
50 /* #define PCFDEBUG */
51
52 static int pcf_wait_byte(struct pcf_softc *pcf);
53 static int pcf_noack(struct pcf_softc *pcf, int timeout);
54 static void pcf_stop_locked(struct pcf_softc *pcf);
55
56 /*
57  * Polling mode for master operations wait for a new
58  * byte incoming or outgoing
59  */
60 static int
61 pcf_wait_byte(struct pcf_softc *sc)
62 {
63         int counter = TIMEOUT;
64
65         PCF_ASSERT_LOCKED(sc);
66         while (counter--) {
67
68                 if ((pcf_get_S1(sc) & PIN) == 0)
69                         return (0);
70         }
71
72 #ifdef PCFDEBUG
73         printf("pcf: timeout!\n");
74 #endif
75
76         return (IIC_ETIMEOUT);
77 }
78
79 static void
80 pcf_stop_locked(struct pcf_softc *sc)
81 {
82
83         PCF_ASSERT_LOCKED(sc);
84 #ifdef PCFDEBUG
85         device_printf(dev, " >> stop\n");
86 #endif
87         /*
88          * Send STOP condition iff the START condition was previously sent.
89          * STOP is sent only once even if an iicbus_stop() is called after
90          * an iicbus_read()... see pcf_read(): the PCF needs to send the stop
91          * before the last char is read.
92          */
93         if (sc->pcf_started) {
94                 /* set stop condition and enable IT */
95                 pcf_set_S1(sc, PIN|ESO|ENI|STO|ACK);
96
97                 sc->pcf_started = 0;
98         }
99 }
100
101 static int
102 pcf_noack(struct pcf_softc *sc, int timeout)
103 {
104         int noack;
105         int k = timeout/10;
106
107         PCF_ASSERT_LOCKED(sc);
108         do {
109                 noack = pcf_get_S1(sc) & LRB;
110                 if (!noack)
111                         break;
112                 DELAY(10);                              /* XXX wait 10 us */
113         } while (k--);
114
115         return (noack);
116 }
117
118 int
119 pcf_repeated_start(device_t dev, u_char slave, int timeout)
120 {
121         struct pcf_softc *sc = DEVTOSOFTC(dev);
122         int error = 0;
123
124         PCF_LOCK(sc);
125 #ifdef PCFDEBUG
126         device_printf(dev, " >> repeated start for slave %#x\n",
127                       (unsigned)slave);
128 #endif
129         /* repeated start */
130         pcf_set_S1(sc, ESO|STA|STO|ACK);
131
132         /* set slave address to PCF. Last bit (LSB) must be set correctly
133          * according to transfer direction */
134         pcf_set_S0(sc, slave);
135
136         /* wait for address sent, polling */
137         if ((error = pcf_wait_byte(sc)))
138                 goto error;
139
140         /* check for ack */
141         if (pcf_noack(sc, timeout)) {
142                 error = IIC_ENOACK;
143 #ifdef PCFDEBUG
144                 printf("pcf: no ack on repeated_start!\n");
145 #endif
146                 goto error;
147         }
148
149         PCF_UNLOCK(sc);
150         return (0);
151
152 error:
153         pcf_stop_locked(sc);
154         PCF_UNLOCK(sc);
155         return (error);
156 }
157
158 int
159 pcf_start(device_t dev, u_char slave, int timeout)
160 {
161         struct pcf_softc *sc = DEVTOSOFTC(dev);
162         int error = 0;
163
164         PCF_LOCK(sc);
165 #ifdef PCFDEBUG
166         device_printf(dev, " >> start for slave %#x\n", (unsigned)slave);
167 #endif
168         if ((pcf_get_S1(sc) & nBB) == 0) {
169 #ifdef PCFDEBUG
170                 printf("pcf: busy!\n");
171 #endif
172                 PCF_UNLOCK(sc);
173                 return (IIC_EBUSBSY);
174         }
175
176         /* set slave address to PCF. Last bit (LSB) must be set correctly
177          * according to transfer direction */
178         pcf_set_S0(sc, slave);
179
180         /* START only */
181         pcf_set_S1(sc, PIN|ESO|STA|ACK);
182
183         sc->pcf_started = 1;
184
185         /* wait for address sent, polling */
186         if ((error = pcf_wait_byte(sc)))
187                 goto error;
188
189         /* check for ACK */
190         if (pcf_noack(sc, timeout)) {
191                 error = IIC_ENOACK;
192 #ifdef PCFDEBUG
193                 printf("pcf: no ack on start!\n");
194 #endif
195                 goto error;
196         }
197
198         PCF_UNLOCK(sc);
199         return (0);
200
201 error:
202         pcf_stop_locked(sc);
203         PCF_UNLOCK(sc);
204         return (error);
205 }
206
207 int
208 pcf_stop(device_t dev)
209 {
210         struct pcf_softc *sc = DEVTOSOFTC(dev);
211
212 #ifdef PCFDEBUG
213         device_printf(dev, " >> stop\n");
214 #endif
215         PCF_LOCK(sc);
216         pcf_stop_locked(sc);
217         PCF_UNLOCK(sc);
218
219         return (0);
220 }
221
222 void
223 pcf_intr(void *arg)
224 {
225         struct pcf_softc *sc = arg;
226         char data, status, addr;
227         char error = 0;
228
229         PCF_LOCK(sc);
230         status = pcf_get_S1(sc);
231
232         if (status & PIN) {
233                 printf("pcf: spurious interrupt, status=0x%x\n",
234                        status & 0xff);
235
236                 goto error;
237         }
238
239         if (status & LAB)
240                 printf("pcf: bus arbitration lost!\n");
241
242         if (status & BER) {
243                 error = IIC_EBUSERR;
244                 iicbus_intr(sc->iicbus, INTR_ERROR, &error);
245
246                 goto error;
247         }
248
249         do {
250                 status = pcf_get_S1(sc);
251
252                 switch(sc->pcf_slave_mode) {
253
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
395                 pcf_set_S0(sc, *buf++);
396
397                 /* wait for the byte to be send */
398                 if ((error = pcf_wait_byte(sc)))
399                         goto error;
400
401                 /* check if ack received */
402                 if (pcf_noack(sc, timeout)) {
403                         error = IIC_ENOACK;
404                         goto error;
405                 }
406
407                 len --;
408                 bytes ++;
409         }
410
411 error:
412         *sent = bytes;
413         PCF_UNLOCK(sc);
414
415 #ifdef PCFDEBUG
416         device_printf(dev, " >> %d bytes written (%d)\n", bytes, error);
417 #endif
418
419         return (error);
420 }
421
422 int
423 pcf_read(device_t dev, char *buf, int len, int *read, int last,
424          int delay /* us */)
425 {
426         struct pcf_softc *sc = DEVTOSOFTC(dev);
427         int bytes, error = 0;
428 #ifdef PCFDEBUG
429         char *obuf = buf;
430
431         device_printf(dev, " << reading %d bytes\n", len);
432 #endif
433
434         PCF_LOCK(sc);
435         /* trig the bus to get the first data byte in S0 */
436         if (len) {
437                 if (len == 1 && last)
438                         /* just one byte to read */
439                         pcf_set_S1(sc, ESO);            /* no ack */
440
441                 dummy_read(sc);
442         }
443
444         bytes = 0;
445         while (len) {
446
447                 /* XXX delay needed here */
448
449                 /* wait for trigged byte */
450                 if ((error = pcf_wait_byte(sc))) {
451                         pcf_stop_locked(sc);
452                         goto error;
453                 }
454
455                 if (len == 1 && last)
456                         /* ok, last data byte already in S0, no I2C activity
457                          * on next pcf_get_S0() */
458                         pcf_stop_locked(sc);
459
460                 else if (len == 2 && last)
461                         /* next trigged byte with no ack */
462                         pcf_set_S1(sc, ESO);
463
464                 /* receive byte, trig next byte */
465                 *buf++ = pcf_get_S0(sc);
466
467                 len --;
468                 bytes ++;
469         };
470
471 error:
472         *read = bytes;
473         PCF_UNLOCK(sc);
474
475 #ifdef PCFDEBUG
476         device_printf(dev, " << %d bytes read (%d): %#x%s\n", bytes, error,
477                       (unsigned)obuf[0], bytes > 1? "...": "");
478 #endif
479
480         return (error);
481 }
482
483 DRIVER_MODULE(iicbus, pcf, iicbus_driver, iicbus_devclass, 0, 0);
484 MODULE_DEPEND(pcf, iicbus, PCF_MINVER, PCF_PREFVER, PCF_MAXVER);
485 MODULE_VERSION(pcf, PCF_MODVER);