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