FreeBSD/Linux Kernel Cross Reference
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: releng/9.0/sys/dev/pcf/pcf.c 194026 2009-06-11 17:15:44Z avg $");
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);
Cache object: 2de7786e8549f6e48e5bc45906d5d50f
|