No empty .Rs/.Re
[netbsd-mini2440.git] / sys / arch / mac68k / nubus / cpi_nubus.c
blob0cde2949bc78691834c4bc19c19891719b003e12
1 /* $NetBSD: cpi_nubus.c,v 1.3 2008/06/11 23:54:45 cegger Exp $ */
3 /*-
4 * Copyright (c) 2008 Hauke Fath
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.
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 #include <sys/cdefs.h>
28 __KERNEL_RCSID(0, "$NetBSD: cpi_nubus.c,v 1.3 2008/06/11 23:54:45 cegger Exp $");
30 #include <sys/param.h>
31 #include <sys/systm.h>
32 #include <sys/proc.h>
33 #include <sys/device.h>
34 #include <sys/malloc.h>
35 #include <sys/event.h>
36 #include <sys/callout.h>
37 #include <sys/conf.h>
38 #include <sys/file.h>
39 #include <sys/uio.h>
40 #include <sys/ioctl.h>
41 #include <sys/tty.h>
42 #include <sys/time.h>
43 #include <sys/kernel.h>
44 #include <sys/syslog.h>
45 #include <sys/errno.h>
47 #include <machine/intr.h>
48 #include <machine/bus.h>
49 #include <machine/viareg.h>
51 #include <dev/ic/z8536reg.h>
52 #include <mac68k/nubus/nubus.h>
53 #include <mac68k/nubus/cpi_nubusvar.h>
55 #include "ioconf.h"
57 #ifdef DEBUG
58 #define CPI_DEBUG
59 #endif
62 * Stuff taken from Egan/Teixeira ch 8: 'if(TRACE_FOO)' debug output
63 * statements don't break indentation, and when DEBUG is not defined,
64 * the compiler code optimizer drops them as dead code.
66 #ifdef CPI_DEBUG
67 #define M_TRACE_CONFIG 0x0001
68 #define M_TRACE_OPEN 0x0002
69 #define M_TRACE_CLOSE 0x0004
70 #define M_TRACE_READ 0x0008
71 #define M_TRACE_WRITE 0x0010
72 #define M_TRACE_IOCTL 0x0020
73 #define M_TRACE_STATUS 0x0040
74 #define M_TRACE_ALL 0xFFFF
75 #define M_TRACE_NONE 0x0000
77 #define TRACE_CONFIG (cpi_debug_mask & M_TRACE_CONFIG)
78 #define TRACE_OPEN (cpi_debug_mask & M_TRACE_OPEN)
79 #define TRACE_CLOSE (cpi_debug_mask & M_TRACE_CLOSE)
80 #define TRACE_READ (cpi_debug_mask & M_TRACE_READ)
81 #define TRACE_WRITE (cpi_debug_mask & M_TRACE_WRITE)
82 #define TRACE_IOCTL (cpi_debug_mask & M_TRACE_IOCTL)
83 #define TRACE_STATUS (cpi_debug_mask & M_TRACE_STATUS)
84 #define TRACE_ALL (cpi_debug_mask & M_TRACE_ALL)
85 #define TRACE_NONE (cpi_debug_mask & M_TRACE_NONE)
87 uint32_t cpi_debug_mask = M_TRACE_NONE /* | M_TRACE_WRITE */ ;
89 #else
90 #define TRACE_CONFIG 0
91 #define TRACE_OPEN 0
92 #define TRACE_CLOSE 0
93 #define TRACE_READ 0
94 #define TRACE_WRITE 0
95 #define TRACE_IOCTL 0
96 #define TRACE_STATUS 0
97 #define TRACE_ALL 0
98 #define TRACE_NONE 0
99 #endif
101 #undef USE_CIO_TIMERS /* TBD */
103 /* autoconf interface */
104 int cpi_nubus_match(device_t, cfdata_t, void *);
105 void cpi_nubus_attach(device_t, device_t, void *);
106 void cpi_nubus_intr(void *);
108 CFATTACH_DECL(cpi, sizeof(struct cpi_softc),
109 cpi_nubus_match, cpi_nubus_attach, NULL, NULL);
111 dev_type_open(cpi_open);
112 dev_type_close(cpi_close);
113 dev_type_read(cpi_read);
114 dev_type_write(cpi_write);
115 dev_type_ioctl(cpi_ioctl);
117 const struct cdevsw cpi_cdevsw = {
118 cpi_open, cpi_close, noread, cpi_write, cpi_ioctl,
119 nostop, notty, nopoll, nommap, nokqfilter, D_OTHER
122 /* prototypes */
123 static void cpi_lpreset(struct cpi_softc *);
124 static int cpi_notready(struct cpi_softc *);
125 static void cpi_wakeup(void *);
126 static int cpi_flush(struct cpi_softc *);
127 static void cpi_intr(void *);
129 #ifdef USE_CIO_TIMERS
130 static void cpi_initclock(struct cpi_softc *);
131 static u_int cpi_get_timecount(struct timecounter *);
132 #endif
134 static inline void z8536_reg_set(bus_space_tag_t, bus_space_handle_t,
135 uint8_t, uint8_t);
136 static inline uint8_t z8536_reg_get(bus_space_tag_t, bus_space_handle_t,
137 uint8_t);
140 const uint8_t cio_reset[] = {
141 /* register value */
142 Z8536_MICR, 0x00,
143 Z8536_MICR, MICR_RESET,
144 Z8536_MICR, 0x00
147 const uint8_t cio_init[] = {
148 /* register value */
150 /* Interrupt vectors - clear all */
151 Z8536_IVRA, 0x00,
152 Z8536_IVRB, 0x00,
153 Z8536_IVRCT, 0x20 /* ??? Do we use this? */,
156 * Port A specification - bit port, single buffered,
157 * latched output, pulsed handshake, all bits non-inverting
158 * non-special I/O
160 Z8536_PMSRA, PMSR_PTS_OUT | PMSR_LPM,
161 Z8536_PHSRA, PHSR_HTS_PUL,
162 Z8536_DPPRA, 0x00,
163 Z8536_DDRA, 0x00,
164 Z8536_SIOCRA, 0x00,
167 * Port B specification - bit port, transparent output,
168 * pulsed handshake, all bits non-inverting
169 * bits 0, 4 output; bits 1-3, 5-8 input,
170 * non-special I/O
171 * Pattern matching: Bit 6 (BUSY) matching "1"
172 * Alternatively: Bit 3 (/ACK) matching "0"
174 Z8536_PMSRB, PMSR_PMS_OR_PEV,
175 Z8536_PHSRB, 0x00,
176 Z8536_DPPRB, 0x00,
177 Z8536_DDRB, 0xee /*11101110b*/,
178 Z8536_SIOCRB, 0x00,
179 Z8536_PPRB, 0x00,
180 Z8536_PTRB, 0x00,
181 Z8536_PMRB, 0x40 /*01000000b = PB6 */,
183 Z8536_PDRB, 0xFE, /* Assign printer -RESET */
184 Z8536_PCSRA, 0x00, /* Clear port A interrupt bits */
187 * Port C specification - bit 3 out, bits 0-2 in,
188 * all 4 non-inverting, non-special I/O
190 Z8536_DDRC, 0x07 /*00000111b*/,
191 Z8536_DPPRC, 0x00,
192 Z8536_SIOCRC, 0x00,
194 #ifdef USE_CIO_TIMERS
196 * Counter/Timers 1+2 are joined to form a free-running
197 * 32 bit timecounter
199 Z8536_CTMSR1, CTMS_CSC,
200 Z8536_CTTCR1_MSB, 0x00,
201 Z8536_CTTCR1_LSB, 0x00,
202 Z8536_CTMSR2, CTMS_CSC,
203 Z8536_CTTCR2_MSB, 0x00,
204 Z8536_CTTCR2_LSB, 0x00,
205 #endif /* USE_CIO_TIMERS */
208 * We need Timer 3 for running port A in strobed mode.
210 * Counter/Timer 3 specification -- clear IP & IUS, trigger +
211 * gate command bit, one-shot operation
213 Z8536_CTCSR3, CTCS_CLR_IP_IUS | CTCS_GCB | CTCS_TCB,
214 Z8536_CTMSR3, CTMS_DCS_ONESHOT,
215 Z8536_CTTCR3_MSB, 0x00,
216 Z8536_CTTCR3_LSB, 0x03,
219 * Enable ports A+B+C+CT3
220 * Set timer 1 to clock timer 2, but not yet enabled.
222 Z8536_MCCR, MCCR_PAE | MCCR_PBE | MCCR_CT1CT2 | MCCR_PC_CT3E,
223 /* Master Interrupt Enable, Disable Lower Chain,
224 * No Vector, port A+B+CT vectors include status */
225 Z8536_MICR, MICR_MIE | MICR_DLC | MICR_NV | MICR_PAVIS |
226 MICR_PBVIS | MICR_CTVIS,
227 Z8536_PDRB, 0xFE, /* Clear printer -RESET */
232 * Look for Creative Systems Inc. "Hurdler Centronics Parallel Interface"
235 cpi_nubus_match(device_t parent, cfdata_t cf, void *aux)
237 struct nubus_attach_args *na;
239 na = aux;
240 if ((na->category == NUBUS_CATEGORY_COMMUNICATIONS) &&
241 (na->type == NUBUS_TYPE_CENTRONICS) &&
242 (na->drsw == NUBUS_DRSW_CPI) &&
243 (na->drhw == NUBUS_DRHW_CPI))
244 return 1;
245 else
246 return 0;
249 void
250 cpi_nubus_attach(device_t parent, device_t self, void *aux)
252 struct cpi_softc *sc;
253 struct nubus_attach_args *na;
254 int err, ii;
256 sc = device_private(self);
257 na = aux;
258 sc->sc_bst = na->na_tag;
259 memcpy(&sc->sc_slot, na->fmt, sizeof(nubus_slot));
260 sc->sc_basepa = (bus_addr_t)NUBUS_SLOT2PA(na->slot);
263 * The CIO sits on the MSB (top byte lane) of the 32 bit
264 * Nubus, so map 16 byte.
266 if (TRACE_CONFIG) {
267 printf("\n");
268 printf("\tcpi_nubus_attach() mapping 8536 CIO at 0x%lx.\n",
269 sc->sc_basepa + CIO_BASE_OFFSET);
272 err = bus_space_map(sc->sc_bst, sc->sc_basepa + CIO_BASE_OFFSET,
273 (Z8536_IOSIZE << 4), 0, &sc->sc_bsh);
274 if (err) {
275 aprint_normal(": failed to map memory space.\n");
276 return;
279 sc->sc_lpstate = LP_INITIAL;
280 sc->sc_intcount = 0;
281 sc->sc_bytestoport = 0;
283 if (TRACE_CONFIG)
284 printf("\tcpi_nubus_attach() about to set up 8536 CIO.\n");
286 for (ii = 0; ii < sizeof(cio_reset); ii += 2)
287 z8536_reg_set(sc->sc_bst, sc->sc_bsh, cio_reset[ii],
288 cio_reset[ii + 1]);
290 delay(1000); /* Just in case */
291 for (ii = 0; ii < sizeof(cio_init); ii += 2) {
292 z8536_reg_set(sc->sc_bst, sc->sc_bsh, cio_init[ii],
293 cio_init[ii + 1]);
296 if (TRACE_CONFIG)
297 printf("\tcpi_nubus_attach() done with 8536 CIO setup.\n");
299 /* XXX Get the information strings from the card's ROM */
300 aprint_normal(": CSI Hurdler II Centronics\n");
302 #ifdef USE_CIO_TIMERS
303 /* Attach CIO timers as timecounters */
304 if (TRACE_CONFIG)
305 printf("\tcpi_nubus_attach() about to attach timers\n");
307 cpi_initclock(sc);
308 #endif /* USE_CIO_TIMERS */
310 callout_init(&sc->sc_wakeupchan, 0); /* XXX */
312 /* make sure interrupts are vectored to us */
313 add_nubus_intr(na->slot, cpi_nubus_intr, sc);
316 void
317 cpi_nubus_intr(void *arg)
319 struct cpi_softc *sc;
320 int s;
322 sc = (struct cpi_softc *)arg;
324 s = spltty();
326 sc->sc_intcount++;
328 /* Check for interrupt source, and clear interrupt */
331 * Clear port A interrupt
332 * Interrupt from register A, clear "pending"
333 * and set "under service"
335 z8536_reg_set(sc->sc_bst, sc->sc_bsh, Z8536_PCSRA, PCSR_CLR_IE);
336 z8536_reg_set(sc->sc_bst, sc->sc_bsh, Z8536_PCSRA, PCSR_CLR_IP);
337 z8536_reg_set(sc->sc_bst, sc->sc_bsh, Z8536_PCSRA, PCSR_SET_IUS);
339 cpi_intr(sc);
341 /* Interrupt from register A, mark serviced */
342 z8536_reg_set(sc->sc_bst, sc->sc_bsh, Z8536_PCSRA, PCSR_CLR_IUS);
343 z8536_reg_set(sc->sc_bst, sc->sc_bsh, Z8536_PCSRA, PCSR_SET_IE);
345 splx(s);
349 /* cpi nuts and bolts */
352 cpi_open(dev_t device, int flag, int mode, struct lwp *l)
354 int err, ii, s;
355 struct cpi_softc *sc;
357 if (TRACE_OPEN)
358 printf("\tcpi_open() called...\n");
360 /* Consistency checks: Valid unit number, softc, device state */
361 sc = device_lookup_private(&cpi_cd, CPI_UNIT(device));
362 if (NULL == sc) {
363 if (TRACE_OPEN)
364 printf("Tried to cpi_open() with NULL softc\n");
365 return ENXIO;
367 if (sc->sc_lpstate != LP_INITIAL) {
368 if (TRACE_OPEN)
369 printf("%s not in initial state (%x).\n",
370 sc->sc_dev.dv_xname, sc->sc_lpstate);
371 return EBUSY;
373 sc->sc_lpstate = LP_OPENING;
375 if (TRACE_OPEN)
376 printf("\tcpi_open() resetting the printer...\n");
377 cpi_lpreset(sc);
379 if (TRACE_OPEN)
380 printf("\tcpi_open() waiting for printer ready...\n");
382 /* Wait max 15 sec for printer to get ready */
383 for (ii = 15; cpi_notready(sc); ii--) {
384 if (0 == ii) {
385 sc->sc_lpstate = LP_INITIAL;
386 return EBUSY;
388 /* sleep for a second, unless we get a signal */
389 err = ltsleep(sc, PZERO | PCATCH, "cpi_open", hz, NULL);
390 if (err != EWOULDBLOCK) {
391 sc->sc_lpstate = LP_INITIAL;
392 return err;
395 if (TRACE_OPEN)
396 printf("\tcpi_open() allocating printer buffer...\n");
398 /* Allocate the driver's line buffer */
399 sc->sc_printbuf = malloc(CPI_BUFSIZE, M_DEVBUF, M_WAITOK);
400 sc->sc_bufbytes = 0;
401 sc->sc_lpstate = LP_OPEN;
403 /* Statistics */
404 sc->sc_intcount = 0;
405 sc->sc_bytestoport = 0;
407 /* Kick off transfer */
408 cpi_wakeup(sc);
411 * Reset "interrupt {pending, under service}" bits, then
412 * enable Port A interrupts
414 s = spltty();
416 z8536_reg_set(sc->sc_bst, sc->sc_bsh, Z8536_PCSRA, PCSR_CLR_IP_IUS);
417 z8536_reg_set(sc->sc_bst, sc->sc_bsh, Z8536_PCSRA, PCSR_SET_IE);
418 splx(s);
420 if (TRACE_OPEN)
421 printf("\tcpi_open() done...\n");
423 return 0;
427 cpi_close(dev_t device, int flag, int mode, struct lwp *l)
429 struct cpi_softc *sc;
431 sc = device_lookup_private(&cpi_cd, CPI_UNIT(device));
433 if (TRACE_CLOSE)
434 printf("\tcpi_close() called (%lu hard, %lu bytes to port)\n",
435 sc->sc_intcount, sc->sc_bytestoport);
437 /* Flush the remaining buffer content, ignoring any errors */
438 if (0 < sc->sc_bufbytes)
439 (void)cpi_flush(sc);
441 callout_stop(&sc->sc_wakeupchan);
443 /* Disable Port A interrupts */
444 z8536_reg_set(sc->sc_bst, sc->sc_bsh, Z8536_PCSRA, PCSR_CLR_IE);
445 z8536_reg_set(sc->sc_bst, sc->sc_bsh, Z8536_PCSRA, PCSR_CLR_IP_IUS);
447 sc->sc_lpstate = LP_INITIAL;
448 free(sc->sc_printbuf, M_DEVBUF);
450 return 0;
454 cpi_write(dev_t device, struct uio *uio, int flags)
456 int err;
457 size_t numbytes;
458 struct cpi_softc *sc;
460 err = 0;
462 if (TRACE_WRITE)
463 printf("\tcpi_write() called for %u bytes\n", uio->uio_resid);
465 sc = device_lookup_private(&cpi_cd, CPI_UNIT(device));
467 /* Send data to printer, a line buffer full at a time */
468 while (uio->uio_resid > 0) {
469 numbytes = min(CPI_BUFSIZE, uio->uio_resid);
470 sc->sc_cp = sc->sc_printbuf;
471 uiomove(sc->sc_cp, numbytes, uio);
472 sc->sc_bufbytes = numbytes;
474 if (TRACE_WRITE)
475 printf("\tQueuing %u bytes\n", numbytes);
476 err = cpi_flush(sc);
477 if (err) {
478 /* Failure; adjust residual counter */
479 if (TRACE_WRITE)
480 printf("\tQueuing failed with %d\n", err);
481 uio->uio_resid += sc->sc_bufbytes;
482 sc->sc_bufbytes = 0;
483 break;
486 return err;
490 cpi_ioctl(dev_t device, unsigned long cmd, void *data,
491 int flag, struct lwp *l)
493 int err;
495 err = 0;
497 if (TRACE_IOCTL)
498 printf("\tcpi_ioctl() called with %ld...\n", cmd);
500 switch (cmd) {
501 default:
502 if (TRACE_IOCTL)
503 printf("\tcpi_ioctl() unknown ioctl %ld\n", cmd);
504 err = ENODEV;
505 break;
507 return err;
511 * Flush the print buffer that our top half uses to provide data to
512 * our bottom, interrupt-driven half.
514 static int
515 cpi_flush(struct cpi_softc *sc)
517 int err, s;
519 err = 0;
520 while (0 < sc->sc_bufbytes) {
521 /* Feed the printer a char, if it's ready */
522 if ( !cpi_notready(sc)) {
523 if (TRACE_WRITE)
524 printf("\tcpi_flush() writes %u bytes "
525 "(%lu hard, %lu bytes to port)\n",
526 sc->sc_bufbytes, sc->sc_intcount,
527 sc->sc_bytestoport);
528 s = spltty();
529 cpi_intr(sc);
530 splx(s);
532 /* XXX Sure we want to wait forever for the printer? */
533 err = ltsleep((void *)sc, PZERO | PCATCH,
534 "cpi_flush", (60 * hz), NULL);
536 return err;
540 static void
541 cpi_wakeup(void *param)
543 struct cpi_softc *sc;
544 int s;
546 sc = param;
548 s = spltty();
549 cpi_intr(sc);
550 splx(s);
552 callout_reset(&sc->sc_wakeupchan, hz, cpi_wakeup, sc);
556 static void
557 cpi_lpreset(struct cpi_softc *sc)
559 uint8_t portb; /* Centronics -RESET is on port B, bit 0 */
560 #ifdef DIRECT_PORT_ACCESS
561 int s;
563 s = spltty();
565 portb = bus_space_read_1(sc->sc_bst, sc->sc_bsh, CIO_PORTB);
566 bus_space_write_1(sc->sc_bst, sc->sc_bsh,
567 CIO_PORTB, portb & ~CPI_RESET);
568 delay(100);
569 portb = bus_space_read_1(sc->sc_bst, sc->sc_bsh, CIO_PORTB);
570 bus_space_write_1(sc->sc_bst, sc->sc_bsh,
571 CIO_PORTB, portb | CPI_RESET);
573 splx(s);
574 #else
575 portb = z8536_reg_get(sc->sc_bst, sc->sc_bsh, Z8536_PDRB);
576 z8536_reg_set(sc->sc_bst, sc->sc_bsh, Z8536_PDRB, portb & ~CPI_RESET);
577 delay(100);
578 portb = z8536_reg_get(sc->sc_bst, sc->sc_bsh, Z8536_PDRB);
579 z8536_reg_set(sc->sc_bst, sc->sc_bsh, Z8536_PDRB, portb | CPI_RESET);
580 #endif /* DIRECT_PORT_ACCESS */
585 * Centronics BUSY is on port B, bit 6
586 * SELECT is on Port B, bit 5
587 * /FAULT is on Port B, bit 1
588 * PAPER EMPTY is on Port C, bit 1
590 static int
591 cpi_notready(struct cpi_softc *sc)
593 uint8_t portb, portc;
594 int is_busy, is_select, is_fault, is_paper_empty;
596 if (TRACE_STATUS)
597 printf("\tcpi_notready() checking printer status...\n");
599 portb = bus_space_read_1(sc->sc_bst, sc->sc_bsh, CIO_PORTB);
600 if (TRACE_STATUS)
601 printf("\tPort B has 0x0%X\n", portb);
603 is_busy = CPI_BUSY & portb;
604 if (TRACE_STATUS)
605 printf("\t\tBUSY = %d\n", is_busy);
607 is_select = CPI_SELECT & portb;
608 if (TRACE_STATUS)
609 printf("\t\tSELECT = %d\n", is_select);
611 is_fault = CPI_FAULT & portb;
612 if (TRACE_STATUS)
613 printf("\t\t/FAULT = %d\n", is_fault);
615 portc = bus_space_read_1(sc->sc_bst, sc->sc_bsh, CIO_PORTC);
616 if (TRACE_STATUS)
617 printf("\tPort C has 0x0%X\n", portc);
619 is_paper_empty = CPI_PAPER_EMPTY & portc;
620 if (TRACE_STATUS)
621 printf("\t\tPAPER EMPTY = %d\n", is_paper_empty);
623 return (is_busy || !is_select || !is_fault || is_paper_empty);
626 static void
627 cpi_intr(void *arg)
629 struct cpi_softc *sc;
631 sc = arg;
633 /* Printer ready for output? */
634 if (cpi_notready(sc))
635 return;
637 if (0 && TRACE_WRITE)
638 printf("\tcpi_soft_intr() has %u bytes.\n", sc->sc_bufbytes);
640 /* Anything to print? */
641 if (sc->sc_bufbytes) {
642 /* Data byte */
643 bus_space_write_1(sc->sc_bst, sc->sc_bsh,
644 CIO_PORTA, *sc->sc_cp++);
645 sc->sc_bufbytes--;
646 sc->sc_bytestoport++;
648 if (0 == sc->sc_bufbytes)
649 /* line buffer empty, wake up our top half */
650 wakeup((void *)sc);
653 #ifdef USE_CIO_TIMERS
655 * Z8536 CIO timers 1 + 2 used for timecounter(9) support
657 static void
658 cpi_initclock(struct cpi_softc *sc)
660 static struct timecounter cpi_timecounter = {
661 .tc_get_timecount = cpi_get_timecount,
662 .tc_poll_pps = 0,
663 .tc_counter_mask = 0x0ffffu,
664 .tc_frequency = CLK_FREQ,
665 .tc_name = "CPI Z8536 CIO",
666 .tc_quality = 50,
667 .tc_priv = NULL,
668 .tc_next = NULL
672 * Set up timers A and B as a single, free-running 32 bit counter
675 /* Disable counters A and B */
676 reg = z8536_reg_get(sc->sc_bst, sc->sc_bsh, Z8536_MCCR);
677 z8536_reg_set(sc->sc_bst, sc->sc_bsh, Z8536_MCCR,
678 reg & ~(MCCR_CT1E | MCCR_CT2E));
680 /* Make sure interrupt enable bits are cleared */
681 z8536_reg_set(sc->sc_bst, sc->sc_bsh, Z8536_CTCSR1,
682 CTCS_CLR_IE);
683 z8536_reg_set(sc->sc_bst, sc->sc_bsh, Z8536_CTCSR2,
684 CTCS_CLR_IE);
686 /* Initialise counter start values, and set to continuous cycle */
687 z8536_reg_set(sc->sc_bst, sc->sc_bsh, Z8536_CTMSR1, CTMS_CSC);
688 z8536_reg_set(sc->sc_bst, sc->sc_bsh, Z8536_CTTCR1_MSB, 0x00);
689 z8536_reg_set(sc->sc_bst, sc->sc_bsh, Z8536_CTTCR1_LSB, 0x00);
691 z8536_reg_set(sc->sc_bst, sc->sc_bsh, Z8536_CTMSR2, CTMS_CSC);
692 z8536_reg_set(sc->sc_bst, sc->sc_bsh, Z8536_CTTCR2_MSB, 0x00);
693 z8536_reg_set(sc->sc_bst, sc->sc_bsh, Z8536_CTTCR2_LSB, 0x00);
695 /* Re-enable counters A and B */
696 reg = z8536_reg_get(sc->sc_bst, sc->sc_bsh, Z8536_MCCR);
697 z8536_reg_set(sc->sc_bst, sc->sc_bsh, Z8536_MCCR,
698 reg | MCCR_CT1E | MCCR_CT2E | MCCR_CT1CT2);
700 /* Start counters A and B */
701 reg = z8536_reg_get(sc->sc_bst, sc->sc_bsh, Z8536_CTCSR1);
702 z8536_reg_set(sc->sc_bst, sc->sc_bsh, Z8536_CTCSR1,
703 reg | CTCS_TCB);
704 reg = z8536_reg_get(sc->sc_bst, sc->sc_bsh, Z8536_CTCSR2);
705 z8536_reg_set(sc->sc_bst, sc->sc_bsh, Z8536_CTCSR2,
706 reg | CTCS_TCB);
708 tc_init(&cpi_timecounter);
711 static u_int
712 cpi_get_timecount(struct timecounter *tc)
714 uint8_t high, high2, low;
715 int s;
718 * Make the timer access atomic
720 * XXX How expensive is this? And is it really necessary?
722 s = splhigh();
724 /* TBD */
727 #endif /* USE_CIO_TIMERS */
731 * Z8536 CIO nuts and bolts
734 static inline void
735 z8536_reg_set(bus_space_tag_t bspace, bus_space_handle_t bhandle,
736 uint8_t reg, uint8_t val)
738 int s;
740 s = splhigh();
741 bus_space_write_1(bspace, bhandle, CIO_CTRL, reg);
742 delay(1);
743 bus_space_write_1(bspace, bhandle, CIO_CTRL, val);
744 splx(s);
747 static inline uint8_t
748 z8536_reg_get(bus_space_tag_t bspace, bus_space_handle_t bhandle, uint8_t reg)
750 int s;
751 uint8_t val;
753 s = splhigh();
754 bus_space_write_1(bspace, bhandle, CIO_CTRL, reg);
755 delay(1);
756 val = bus_space_read_1(bspace, bhandle, CIO_CTRL);
757 splx(s);
759 return val;