xref: /netbsd-src/sys/arch/amiga/amiga/gayle.c (revision daeff8a9d2c258b7f393b07d588735e01bbbc791)
1 /*	$NetBSD: gayle.c,v 1.8 2015/01/16 23:34:11 phx Exp $	*/
2 
3 /* public domain */
4 
5 #include <sys/cdefs.h>
6 __KERNEL_RCSID(0, "$NetBSD: gayle.c,v 1.8 2015/01/16 23:34:11 phx Exp $");
7 
8 /*
9  * Gayle management - provide functions for use in the drivers that utilise
10  * the chip.
11  *
12  * These overly complicated routines try to deal with a few variants of
13  * Gayle chip that exists.
14  */
15 #include <sys/bus.h>
16 #include <sys/systm.h>
17 
18 #include <machine/cpu.h>
19 
20 #include <amiga/amiga/gayle.h>
21 #include <amiga/dev/zbusvar.h>
22 
23 /* #define GAYLE_DEBUG 1 */
24 
25 struct gayle_tag {
26 	struct bus_space_tag gayle_io_bst;
27 	bus_space_tag_t gayle_io_t;
28 	bus_space_handle_t gayle_io_h;
29 
30 	struct bus_space_tag gayle_isr_bst;
31 	bus_space_tag_t gayle_isr_t;
32 	bus_space_handle_t gayle_isr_h;
33 };
34 
35 typedef struct gayle_tag *gayle_tag_t;
36 
37 /*
38  * Having these as static variables is ugly, but they don't fit into
39  * driver's softc, as the chip might be utilised by many different drivers.
40  * And since we can only have one Gayle per system it should be okay.
41  */
42 static struct gayle_tag gayle;
43 static gayle_tag_t gayle_t = NULL;
44 
45 /*
46  * Any module that uses gayle should call gayle_init() before using anything
47  *   related to gayle. gayle_init() can be called multiple times.
48  */
49 void
gayle_init(void)50 gayle_init(void) {
51 	bus_addr_t gayle_vbase;
52 
53 	if (gayle_t != NULL)
54 		return;
55 
56 #ifdef GAYLE_DEBUG
57 	aprint_normal("gayle: doing init\n");
58 #endif /* GAYLE_DEBUG */
59 
60 	gayle_t = &gayle;
61 
62 	gayle_vbase = (bus_addr_t) __UNVOLATILE(ztwomap(GAYLE_REGS_BASE));
63 
64 	gayle_t->gayle_io_bst.base = gayle_vbase;
65 	gayle_t->gayle_io_bst.absm = &amiga_bus_stride_0x1000;
66 	gayle_t->gayle_io_t = &(gayle_t->gayle_io_bst);
67 
68 	bus_space_map(gayle_t->gayle_io_t, 0, 0x4, 0, &gayle_t->gayle_io_h);
69 
70 	/*
71 	 * The A4000 variant of Gayle has interrupt status register at offset
72 	 * +0x1000 from IDE registers.
73 	 * XXX: in fact, on A4000 we should initialise only this part...
74 	 */
75 	if (is_a4000()) {
76 		gayle_t->gayle_isr_bst.base = (bus_addr_t) __UNVOLATILE(ztwomap(
77 		    GAYLE_IDE_BASE_A4000+GAYLE_IDE_INTREQ_A4000));
78 		gayle_t->gayle_isr_bst.absm = &amiga_bus_stride_1;
79 		gayle_t->gayle_isr_t = &(gayle_t->gayle_isr_bst);
80 
81 		bus_space_map(gayle_t->gayle_isr_t, 0, 0x1, 0,
82 		    &(gayle_t->gayle_isr_h));
83 	} else {
84 		bus_space_subregion(gayle_t->gayle_io_t, gayle_t->gayle_io_h,
85 		    GAYLE_INTREQ, 0x1, &(gayle_t->gayle_isr_h));
86 
87 		gayle_t->gayle_isr_bst = gayle_t->gayle_io_bst;
88 		gayle_t->gayle_isr_t = gayle_t->gayle_io_t;
89 	}
90 
91 }
92 
93 uint8_t
gayle_intr_status(void)94 gayle_intr_status(void)
95 {
96 	uint8_t rv;
97 
98 	rv = bus_space_read_1(gayle_t->gayle_isr_t, gayle_t->gayle_isr_h, 0);
99 #ifdef GAYLE_DEBUG
100 	aprint_normal("gayle: intr status %x\n", rv);
101 #endif /* GAYLE_DEBUG */
102 
103 	return rv;
104 }
105 
106 uint8_t
gayle_intr_enable_read(void)107 gayle_intr_enable_read(void)
108 {
109 	uint8_t rv;
110 
111 	rv = bus_space_read_1(gayle_t->gayle_io_t, gayle_t->gayle_io_h,
112 	    GAYLE_INTENA);
113 #ifdef GAYLE_DEBUG
114 	aprint_normal("gayle: intr enable register read %x\n", rv);
115 #endif /* GAYLE_DEBUG */
116 
117 	return rv;
118 }
119 
120 void
gayle_intr_enable_write(uint8_t val)121 gayle_intr_enable_write(uint8_t val)
122 {
123 #ifdef GAYLE_DEBUG
124 	aprint_normal("gayle: intr enable register write %x\n", val);
125 #endif /* GAYLE_DEBUG */
126 	bus_space_write_1(gayle_t->gayle_io_t, gayle_t->gayle_io_h,
127 	    GAYLE_INTENA, val);
128 }
129 
130 void
gayle_intr_enable_set(uint8_t bits)131 gayle_intr_enable_set(uint8_t bits)
132 {
133 	uint8_t val;
134 	val = gayle_intr_enable_read();
135 	gayle_intr_enable_write(val | bits);
136 }
137 
138 void
gayle_intr_ack(uint8_t val)139 gayle_intr_ack(uint8_t val)
140 {
141 #ifdef GAYLE_DEBUG
142 	aprint_normal("gayle: intr ack write %x\n", val);
143 #endif /* GAYLE_DEBUG */
144 	bus_space_write_1(gayle_t->gayle_io_t, gayle_t->gayle_io_h,
145 	    GAYLE_INTREQ, val);
146 }
147 
148 uint8_t
gayle_pcmcia_status_read(void)149 gayle_pcmcia_status_read(void)
150 {
151 	uint8_t rv;
152 
153 	rv = bus_space_read_1(gayle_t->gayle_io_t, gayle_t->gayle_io_h,
154 	    GAYLE_PCC_STATUS);
155 #ifdef GAYLE_DEBUG
156 	aprint_normal("gayle: pcmcia status read %x\n", rv);
157 #endif /* GAYLE_DEBUG */
158 
159 	return rv;
160 }
161 
162 void
gayle_pcmcia_status_write(uint8_t val)163 gayle_pcmcia_status_write(uint8_t val)
164 {
165 #ifdef GAYLE_DEBUG
166 	aprint_normal("gayle: pcmcia status write %x\n", val);
167 #endif /* GAYLE_DEBUG */
168 	bus_space_write_1(gayle_t->gayle_io_t, gayle_t->gayle_io_h,
169 	    GAYLE_PCC_STATUS, val);
170 }
171 
172 void
gayle_pcmcia_config_write(uint8_t val)173 gayle_pcmcia_config_write(uint8_t val)
174 {
175 #ifdef GAYLE_DEBUG
176 	aprint_normal("gayle: pcmcia config write %x\n", val);
177 #endif /* GAYLE_DEBUG */
178 	bus_space_write_1(gayle_t->gayle_io_t, gayle_t->gayle_io_h,
179 	    GAYLE_PCC_CONFIG, val);
180 }
181 
182 uint8_t
gayle_pcmcia_config_read(void)183 gayle_pcmcia_config_read(void)
184 {
185 	uint8_t rv;
186 
187 	rv = bus_space_read_1(gayle_t->gayle_io_t, gayle_t->gayle_io_h,
188 	    GAYLE_PCC_CONFIG);
189 #ifdef GAYLE_DEBUG
190 	aprint_normal("gayle: pcmcia config read %x\n", rv);
191 #endif /* GAYLE_DEBUG */
192 
193 	return rv;
194 }
195 
196