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