xref: /netbsd-src/sys/arch/hppa/dev/siop_sgc.c (revision 6d3ceb1d619615401b17c9aa3e4bc674a1cb048b)
1*6d3ceb1dSskrll /*	$NetBSD: siop_sgc.c,v 1.1 2014/02/24 07:23:42 skrll Exp $	*/
2*6d3ceb1dSskrll 
3*6d3ceb1dSskrll /*	$OpenBSD: siop_sgc.c,v 1.1 2007/08/05 19:09:52 kettenis Exp $	*/
4*6d3ceb1dSskrll 
5*6d3ceb1dSskrll /*
6*6d3ceb1dSskrll  * Copyright (c) 2007 Mark Kettenis
7*6d3ceb1dSskrll  *
8*6d3ceb1dSskrll  * Permission to use, copy, modify, and distribute this software for any
9*6d3ceb1dSskrll  * purpose with or without fee is hereby granted, provided that the above
10*6d3ceb1dSskrll  * copyright notice and this permission notice appear in all copies.
11*6d3ceb1dSskrll  *
12*6d3ceb1dSskrll  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13*6d3ceb1dSskrll  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14*6d3ceb1dSskrll  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15*6d3ceb1dSskrll  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16*6d3ceb1dSskrll  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17*6d3ceb1dSskrll  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18*6d3ceb1dSskrll  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19*6d3ceb1dSskrll  */
20*6d3ceb1dSskrll 
21*6d3ceb1dSskrll #include <sys/cdefs.h>
22*6d3ceb1dSskrll __KERNEL_RCSID(0, "$NetBSD: siop_sgc.c,v 1.1 2014/02/24 07:23:42 skrll Exp $");
23*6d3ceb1dSskrll 
24*6d3ceb1dSskrll #include <sys/param.h>
25*6d3ceb1dSskrll #include <sys/device.h>
26*6d3ceb1dSskrll #include <sys/systm.h>
27*6d3ceb1dSskrll 
28*6d3ceb1dSskrll #include <uvm/uvm_extern.h>
29*6d3ceb1dSskrll 
30*6d3ceb1dSskrll #include <machine/autoconf.h>
31*6d3ceb1dSskrll #include <sys/bus.h>
32*6d3ceb1dSskrll #include <machine/iomod.h>
33*6d3ceb1dSskrll 
34*6d3ceb1dSskrll #include <dev/scsipi/scsi_all.h>
35*6d3ceb1dSskrll #include <dev/scsipi/scsipi_all.h>
36*6d3ceb1dSskrll #include <dev/scsipi/scsiconf.h>
37*6d3ceb1dSskrll 
38*6d3ceb1dSskrll #include <dev/ic/siopreg.h>
39*6d3ceb1dSskrll #include <dev/ic/siopvar_common.h>
40*6d3ceb1dSskrll #include <dev/ic/siopvar.h>
41*6d3ceb1dSskrll 
42*6d3ceb1dSskrll #include <hppa/dev/cpudevs.h>
43*6d3ceb1dSskrll 
44*6d3ceb1dSskrll #define IO_II_INTEN		0x20000000
45*6d3ceb1dSskrll #define IO_II_PACKEN		0x10000000
46*6d3ceb1dSskrll #define IO_II_PREFETCHEN	0x08000000
47*6d3ceb1dSskrll 
48*6d3ceb1dSskrll int siop_sgc_match(device_t, cfdata_t, void *);
49*6d3ceb1dSskrll void siop_sgc_attach(device_t, device_t, void *);
50*6d3ceb1dSskrll int siop_sgc_intr(void *);
51*6d3ceb1dSskrll void siop_sgc_reset(struct siop_common_softc *);
52*6d3ceb1dSskrll 
53*6d3ceb1dSskrll uint8_t siop_sgc_r1(void *, bus_space_handle_t, bus_size_t);
54*6d3ceb1dSskrll uint16_t siop_sgc_r2(void *, bus_space_handle_t, bus_size_t);
55*6d3ceb1dSskrll void siop_sgc_w1(void *, bus_space_handle_t, bus_size_t, uint8_t);
56*6d3ceb1dSskrll void siop_sgc_w2(void *, bus_space_handle_t, bus_size_t, uint16_t);
57*6d3ceb1dSskrll 
58*6d3ceb1dSskrll struct siop_sgc_softc {
59*6d3ceb1dSskrll 	struct siop_softc sc_siop;
60*6d3ceb1dSskrll 	bus_space_tag_t sc_iot;
61*6d3ceb1dSskrll 	bus_space_handle_t sc_ioh;
62*6d3ceb1dSskrll 	struct hppa_bus_space_tag sc_bustag;
63*6d3ceb1dSskrll };
64*6d3ceb1dSskrll 
65*6d3ceb1dSskrll CFATTACH_DECL_NEW(siop_gedoens, sizeof(struct siop_sgc_softc),
66*6d3ceb1dSskrll     siop_sgc_match, siop_sgc_attach, NULL, NULL);
67*6d3ceb1dSskrll 
68*6d3ceb1dSskrll int
siop_sgc_match(device_t parent,cfdata_t match,void * aux)69*6d3ceb1dSskrll siop_sgc_match(device_t parent, cfdata_t match, void *aux)
70*6d3ceb1dSskrll {
71*6d3ceb1dSskrll 	struct confargs *ca = aux;
72*6d3ceb1dSskrll 
73*6d3ceb1dSskrll 	if (ca->ca_type.iodc_type != HPPA_TYPE_ADMA ||
74*6d3ceb1dSskrll 	    ca->ca_type.iodc_sv_model != HPPA_ADMA_FWSCSI)
75*6d3ceb1dSskrll 		return 0;
76*6d3ceb1dSskrll 
77*6d3ceb1dSskrll 	return 1;
78*6d3ceb1dSskrll }
79*6d3ceb1dSskrll 
80*6d3ceb1dSskrll void
siop_sgc_attach(device_t parent,device_t self,void * aux)81*6d3ceb1dSskrll siop_sgc_attach(device_t parent, device_t self, void *aux)
82*6d3ceb1dSskrll {
83*6d3ceb1dSskrll 	struct siop_sgc_softc *sgc = device_private(self);
84*6d3ceb1dSskrll 	struct siop_softc *sc = &sgc->sc_siop;
85*6d3ceb1dSskrll 	struct confargs *ca = aux;
86*6d3ceb1dSskrll 	struct cpu_info *ci = &cpus[0];
87*6d3ceb1dSskrll 	volatile struct iomod *regs;
88*6d3ceb1dSskrll 
89*6d3ceb1dSskrll 	sc->sc_c.sc_dev = self;
90*6d3ceb1dSskrll 	sgc->sc_iot = ca->ca_iot;
91*6d3ceb1dSskrll 	if (bus_space_map(sgc->sc_iot, ca->ca_hpa,
92*6d3ceb1dSskrll 	    IOMOD_HPASIZE, 0, &sgc->sc_ioh)) {
93*6d3ceb1dSskrll 		aprint_error(": can't map io space\n");
94*6d3ceb1dSskrll 		return;
95*6d3ceb1dSskrll 	}
96*6d3ceb1dSskrll 
97*6d3ceb1dSskrll 	ca->ca_irq = hppa_intr_allocate_bit(&ci->ci_ir, ca->ca_irq);
98*6d3ceb1dSskrll 	if (ca->ca_irq == HPPACF_IRQ_UNDEF) {
99*6d3ceb1dSskrll 		aprint_error(": can't allocate interrupt\n");
100*6d3ceb1dSskrll 		return;
101*6d3ceb1dSskrll 	}
102*6d3ceb1dSskrll 
103*6d3ceb1dSskrll 	sgc->sc_bustag = *sgc->sc_iot;
104*6d3ceb1dSskrll 	sgc->sc_bustag.hbt_r1 = siop_sgc_r1;
105*6d3ceb1dSskrll 	sgc->sc_bustag.hbt_r2 = siop_sgc_r2;
106*6d3ceb1dSskrll 	sgc->sc_bustag.hbt_w1 = siop_sgc_w1;
107*6d3ceb1dSskrll 	sgc->sc_bustag.hbt_w2 = siop_sgc_w2;
108*6d3ceb1dSskrll 
109*6d3ceb1dSskrll 	sc->sc_c.features = SF_CHIP_PF | SF_CHIP_BE | SF_BUS_WIDE;
110*6d3ceb1dSskrll 	sc->sc_c.maxburst = 4;
111*6d3ceb1dSskrll 	sc->sc_c.maxoff = 8;
112*6d3ceb1dSskrll 	sc->sc_c.clock_div = 3;
113*6d3ceb1dSskrll 	sc->sc_c.clock_period = 250;
114*6d3ceb1dSskrll 	sc->sc_c.ram_size = 0;
115*6d3ceb1dSskrll 
116*6d3ceb1dSskrll 	sc->sc_c.sc_reset = siop_sgc_reset;
117*6d3ceb1dSskrll 	sc->sc_c.sc_dmat = ca->ca_dmatag;
118*6d3ceb1dSskrll 
119*6d3ceb1dSskrll 	sc->sc_c.sc_rt = &sgc->sc_bustag;
120*6d3ceb1dSskrll 	bus_space_subregion(sgc->sc_iot, sgc->sc_ioh, IOMOD_DEVOFFSET,
121*6d3ceb1dSskrll 	    IOMOD_HPASIZE - IOMOD_DEVOFFSET, &sc->sc_c.sc_rh);
122*6d3ceb1dSskrll 
123*6d3ceb1dSskrll 	regs = bus_space_vaddr(sgc->sc_iot, sgc->sc_ioh);
124*6d3ceb1dSskrll 	regs->io_command = CMD_RESET;
125*6d3ceb1dSskrll 	while ((regs->io_status & IO_ERR_MEM_RY) == 0)
126*6d3ceb1dSskrll 		delay(100);
127*6d3ceb1dSskrll 	regs->io_ii_rw = IO_II_PACKEN | IO_II_PREFETCHEN;
128*6d3ceb1dSskrll 
129*6d3ceb1dSskrll 	siop_sgc_reset(&sc->sc_c);
130*6d3ceb1dSskrll 
131*6d3ceb1dSskrll 	regs->io_eim = ci->ci_hpa | (31 - ca->ca_irq);
132*6d3ceb1dSskrll 	regs->io_ii_rw |= IO_II_INTEN;
133*6d3ceb1dSskrll 
134*6d3ceb1dSskrll 	aprint_normal(": NCR53C720 rev %d\n", bus_space_read_1(sc->sc_c.sc_rt,
135*6d3ceb1dSskrll 	    sc->sc_c.sc_rh, SIOP_CTEST3) >> 4);
136*6d3ceb1dSskrll 
137*6d3ceb1dSskrll 	siop_attach(&sgc->sc_siop);
138*6d3ceb1dSskrll 
139*6d3ceb1dSskrll 	(void)hppa_intr_establish(IPL_BIO, siop_intr, sc, &ci->ci_ir,
140*6d3ceb1dSskrll 	    ca->ca_irq);
141*6d3ceb1dSskrll }
142*6d3ceb1dSskrll 
143*6d3ceb1dSskrll void
siop_sgc_reset(struct siop_common_softc * sc)144*6d3ceb1dSskrll siop_sgc_reset(struct siop_common_softc *sc)
145*6d3ceb1dSskrll {
146*6d3ceb1dSskrll 	bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_DCNTL, DCNTL_EA);
147*6d3ceb1dSskrll 	bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_CTEST0, CTEST0_EHP);
148*6d3ceb1dSskrll 	bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_CTEST4, CTEST4_MUX);
149*6d3ceb1dSskrll 
150*6d3ceb1dSskrll 	bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_STIME0,
151*6d3ceb1dSskrll 	    (0xc << STIME0_SEL_SHIFT));
152*6d3ceb1dSskrll }
153*6d3ceb1dSskrll 
154*6d3ceb1dSskrll uint8_t
siop_sgc_r1(void * v,bus_space_handle_t h,bus_size_t o)155*6d3ceb1dSskrll siop_sgc_r1(void *v, bus_space_handle_t h, bus_size_t o)
156*6d3ceb1dSskrll {
157*6d3ceb1dSskrll 	return *(volatile uint8_t *)(h + (o ^ 3));
158*6d3ceb1dSskrll }
159*6d3ceb1dSskrll 
160*6d3ceb1dSskrll uint16_t
siop_sgc_r2(void * v,bus_space_handle_t h,bus_size_t o)161*6d3ceb1dSskrll siop_sgc_r2(void *v, bus_space_handle_t h, bus_size_t o)
162*6d3ceb1dSskrll {
163*6d3ceb1dSskrll 	if (o == SIOP_SIST0) {
164*6d3ceb1dSskrll 		uint16_t reg;
165*6d3ceb1dSskrll 
166*6d3ceb1dSskrll 		reg = siop_sgc_r1(v, h, SIOP_SIST0);
167*6d3ceb1dSskrll 		reg |= siop_sgc_r1(v, h, SIOP_SIST1) << 8;
168*6d3ceb1dSskrll 		return reg;
169*6d3ceb1dSskrll 	}
170*6d3ceb1dSskrll 	return *(volatile uint16_t *)(h + (o ^ 2));
171*6d3ceb1dSskrll }
172*6d3ceb1dSskrll 
173*6d3ceb1dSskrll void
siop_sgc_w1(void * v,bus_space_handle_t h,bus_size_t o,uint8_t vv)174*6d3ceb1dSskrll siop_sgc_w1(void *v, bus_space_handle_t h, bus_size_t o, uint8_t vv)
175*6d3ceb1dSskrll {
176*6d3ceb1dSskrll 	*(volatile uint8_t *)(h + (o ^ 3)) = vv;
177*6d3ceb1dSskrll }
178*6d3ceb1dSskrll 
179*6d3ceb1dSskrll void
siop_sgc_w2(void * v,bus_space_handle_t h,bus_size_t o,uint16_t vv)180*6d3ceb1dSskrll siop_sgc_w2(void *v, bus_space_handle_t h, bus_size_t o, uint16_t vv)
181*6d3ceb1dSskrll {
182*6d3ceb1dSskrll 	*(volatile uint16_t *)(h + (o ^ 2)) = vv;
183*6d3ceb1dSskrll }
184