1238722Skargl/*	$NetBSD: timer_isa.c,v 1.13 2011/02/08 20:20:09 rmind Exp $	*/
2251315Skargl/*	$OpenBSD: clock_mc.c,v 1.9 1998/03/16 09:38:26 pefo Exp $	*/
3238722Skargl/*	NetBSD: clock_mc.c,v 1.2 1995/06/28 04:30:30 cgd Exp 	*/
4238722Skargl
5238722Skargl/*
6238722Skargl * Copyright (c) 1988 University of Utah.
7238722Skargl * Copyright (c) 1992, 1993
8238722Skargl *	The Regents of the University of California.  All rights reserved.
9238722Skargl *
10238722Skargl * This code is derived from software contributed to Berkeley by
11238722Skargl * the Systems Programming Group of the University of Utah Computer
12238722Skargl * Science Department and Ralph Campbell.
13238722Skargl *
14238722Skargl * Redistribution and use in source and binary forms, with or without
15238722Skargl * modification, are permitted provided that the following conditions
16238722Skargl * are met:
17238722Skargl * 1. Redistributions of source code must retain the above copyright
18238722Skargl *    notice, this list of conditions and the following disclaimer.
19238722Skargl * 2. Redistributions in binary form must reproduce the above copyright
20238722Skargl *    notice, this list of conditions and the following disclaimer in the
21238722Skargl *    documentation and/or other materials provided with the distribution.
22238722Skargl * 3. Neither the name of the University nor the names of its contributors
23238722Skargl *    may be used to endorse or promote products derived from this software
24238722Skargl *    without specific prior written permission.
25251337Skargl *
26251337Skargl * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27238722Skargl * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28238722Skargl * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29238722Skargl * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30238722Skargl * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31238722Skargl * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32240864Skargl * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33240864Skargl * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34240864Skargl * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35240864Skargl * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36238722Skargl * SUCH DAMAGE.
37238722Skargl *
38238783Skargl * from: Utah Hdr: clock.c 1.18 91/01/21
39238722Skargl *
40238722Skargl *	@(#)clock.c	8.1 (Berkeley) 6/10/93
41238722Skargl */
42240864Skargl
43251327Skargl#include <sys/cdefs.h>
44238722Skargl__KERNEL_RCSID(0, "$NetBSD: timer_isa.c,v 1.13 2011/02/08 20:20:09 rmind Exp $");
45238722Skargl
46251334Skargl#include <sys/param.h>
47251334Skargl#include <sys/kernel.h>
48251345Skargl#include <sys/systm.h>
49251334Skargl#include <sys/device.h>
50240864Skargl
51238722Skargl#include <sys/bus.h>
52238722Skargl
53251334Skargl#include <dev/isa/isareg.h>
54251334Skargl#include <dev/isa/isavar.h>
55238722Skargl
56251334Skargl#include <dev/ic/i8253reg.h>
57240864Skargl
58238722Skargl#include <arc/arc/timervar.h>
59251334Skargl#include <arc/isa/timer_isavar.h>
60251334Skargl
61251334Skargl#define TIMER_IOSIZE	4
62251334Skargl#define TIMER_IRQ	0
63251334Skargl
64251334Skarglstruct timer_isa_softc {
65251334Skargl	device_t sc_dev;
66251334Skargl
67238722Skargl	bus_space_tag_t sc_iot;
68251334Skargl	bus_space_handle_t sc_ioh;
69251334Skargl};
70238722Skargl
71251334Skargl/* Definition of the driver for autoconfig. */
72251334Skarglstatic int timer_isa_match(device_t, cfdata_t, void *);
73251341Skarglstatic void timer_isa_attach(device_t, device_t, void *);
74251334Skargl
75251334SkarglCFATTACH_DECL_NEW(timer_isa, sizeof(struct timer_isa_softc),
76251334Skargl    timer_isa_match, timer_isa_attach, NULL, NULL);
77251334Skargl
78251334Skargl/* ISA timer access code */
79251334Skarglstatic void timer_isa_init(device_t);
80251334Skargl
81251334Skarglstruct timerfns timerfns_isa = {
82251334Skargl	timer_isa_init
83251334Skargl};
84251334Skargl
85251334Skarglint timer_isa_conf = 0;
86251334Skargl
87251334Skarglstatic int
88251334Skargltimer_isa_match(device_t parent, cfdata_t cf, void *aux)
89238722Skargl{
90251341Skargl	struct isa_attach_args *ia = aux;
91251341Skargl	bus_space_handle_t ioh;
92251341Skargl
93251341Skargl	if (ia->ia_nio < 1 ||
94251341Skargl	    (ia->ia_io[0].ir_addr != ISA_UNKNOWN_PORT &&
95238722Skargl	     ia->ia_io[0].ir_addr != IO_TIMER1))
96238722Skargl		return 0;
97251321Skargl
98238722Skargl	if (ia->ia_niomem > 0 &&
99238722Skargl	    (ia->ia_iomem[0].ir_addr != ISA_UNKNOWN_IOMEM))
100238722Skargl		return 0;
101238722Skargl
102238722Skargl	if (ia->ia_nirq > 0 &&
103238722Skargl	    (ia->ia_irq[0].ir_irq != ISA_UNKNOWN_IRQ &&
104238722Skargl	     ia->ia_irq[0].ir_irq != TIMER_IRQ))
105238722Skargl		return 0;
106238722Skargl
107238722Skargl	if (ia->ia_ndrq > 0 &&
108238722Skargl	    (ia->ia_drq[0].ir_drq != ISA_UNKNOWN_DRQ))
109238722Skargl		return 0;
110238722Skargl
111238722Skargl	if (!timer_isa_conf)
112238722Skargl		return 0;
113238722Skargl
114238722Skargl	if (bus_space_map(ia->ia_iot, IO_TIMER1, TIMER_IOSIZE, 0, &ioh))
115238722Skargl		return 0;
116238722Skargl
117238722Skargl	bus_space_unmap(ia->ia_iot, ioh, TIMER_IOSIZE);
118238722Skargl
119238722Skargl	ia->ia_nio = 1;
120238722Skargl	ia->ia_io[0].ir_addr = IO_TIMER1;
121238722Skargl	ia->ia_io[0].ir_size = TIMER_IOSIZE;
122238722Skargl
123238722Skargl	ia->ia_niomem = 0;
124238722Skargl	ia->ia_nirq = 0;
125238722Skargl	ia->ia_ndrq = 0;
126238722Skargl
127238722Skargl	return 1;
128238722Skargl}
129238722Skargl
130238722Skarglstatic void
131238722Skargltimer_isa_attach(device_t parent, device_t self, void *aux)
132238722Skargl{
133238722Skargl	struct timer_isa_softc *sc = device_private(self);
134238722Skargl	struct isa_attach_args *ia = aux;
135238722Skargl	void *ih;
136238722Skargl
137238722Skargl	sc->sc_dev = self;
138238722Skargl
139238722Skargl	aprint_normal("\n");
140238722Skargl
141238722Skargl	sc->sc_iot = ia->ia_iot;
142238722Skargl	if (bus_space_map(sc->sc_iot, ia->ia_io[0].ir_addr,
143238722Skargl	    ia->ia_io[0].ir_size, 0, &sc->sc_ioh))
144238722Skargl		panic("timer_isa_attach: couldn't map clock I/O space");
145238722Skargl
146238722Skargl	ih = isa_intr_establish(ia->ia_ic, ia->ia_irq[0].ir_irq, IST_PULSE,
147238722Skargl	    IPL_CLOCK, (int (*)(void *))hardclock,
148238722Skargl	    NULL /* clockframe is hardcoded */);
149238722Skargl	if (ih == NULL)
150238722Skargl		aprint_error_dev(self, "can't establish interrupt\n");
151238722Skargl
152238722Skargl	timerattach(self, &timerfns_isa);
153238722Skargl}
154238722Skargl
155238722Skarglstatic void
156238722Skargltimer_isa_init(device_t self)
157238722Skargl{
158238722Skargl	struct timer_isa_softc *sc = device_private(self);
159238722Skargl
160238722Skargl	bus_space_write_1(sc->sc_iot, sc->sc_ioh, TIMER_MODE,
161238722Skargl	    TIMER_SEL0 | TIMER_16BIT | TIMER_RATEGEN);
162238722Skargl	bus_space_write_1(sc->sc_iot, sc->sc_ioh, TIMER_CNTR0,
163238722Skargl	    TIMER_DIV(hz) % 256);
164238722Skargl	bus_space_write_1(sc->sc_iot, sc->sc_ioh, TIMER_CNTR0,
165238722Skargl	    TIMER_DIV(hz) / 256);
166238722Skargl}
167238722Skargl