gdium_machdep.c revision 1.7 1 1.1 bouyer /* $OpenBSD: gdium_machdep.c,v 1.6 2010/05/08 21:59:56 miod Exp $ */
2 1.1 bouyer
3 1.1 bouyer /*
4 1.1 bouyer * Copyright (c) 2010 Miodrag Vallat.
5 1.1 bouyer *
6 1.1 bouyer * Permission to use, copy, modify, and distribute this software for any
7 1.1 bouyer * purpose with or without fee is hereby granted, provided that the above
8 1.1 bouyer * copyright notice and this permission notice appear in all copies.
9 1.1 bouyer *
10 1.1 bouyer * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 1.1 bouyer * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 1.1 bouyer * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 1.1 bouyer * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 1.1 bouyer * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 1.1 bouyer * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 1.1 bouyer * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 1.1 bouyer */
18 1.1 bouyer
19 1.1 bouyer /*
20 1.1 bouyer * Gdium Liberty specific code and configuration data.
21 1.1 bouyer */
22 1.1 bouyer
23 1.1 bouyer #include <sys/param.h>
24 1.1 bouyer #include <sys/systm.h>
25 1.1 bouyer #include <sys/device.h>
26 1.1 bouyer #include <sys/types.h>
27 1.1 bouyer
28 1.7 macallan #include <mips/cpuregs.h>
29 1.1 bouyer #include <evbmips/loongson/autoconf.h>
30 1.1 bouyer #include <evbmips/loongson/loongson_intr.h>
31 1.1 bouyer
32 1.1 bouyer #include <dev/pci/pcireg.h>
33 1.1 bouyer #include <dev/pci/pcivar.h>
34 1.1 bouyer #include <dev/pci/pcidevs.h>
35 1.1 bouyer
36 1.1 bouyer #include <mips/bonito/bonitoreg.h>
37 1.1 bouyer #include <mips/bonito/bonitovar.h>
38 1.1 bouyer
39 1.2 macallan #include <dev/wscons/wsconsio.h>
40 1.2 macallan #include <dev/wscons/wsdisplayvar.h>
41 1.2 macallan #include <dev/rasops/rasops.h>
42 1.2 macallan #include <dev/wsfont/wsfont.h>
43 1.2 macallan #include <dev/wscons/wsdisplay_vconsvar.h>
44 1.2 macallan
45 1.1 bouyer int gdium_revision = 0;
46 1.2 macallan static pcireg_t fb_addr = 0;
47 1.1 bouyer
48 1.1 bouyer void gdium_attach_hook(device_t, device_t, struct pcibus_attach_args *);
49 1.5 chs void gdium_device_register(device_t, void *);
50 1.1 bouyer int gdium_intr_map(int, int, int, pci_intr_handle_t *);
51 1.1 bouyer void gdium_powerdown(void);
52 1.1 bouyer void gdium_reset(void);
53 1.1 bouyer
54 1.1 bouyer const struct bonito_config gdium_bonito = {
55 1.1 bouyer .bc_adbase = 11,
56 1.1 bouyer
57 1.1 bouyer .bc_gpioIE = LOONGSON_INTRMASK_GPIO,
58 1.1 bouyer .bc_intEdge = LOONGSON_INTRMASK_PCI_SYSERR |
59 1.1 bouyer LOONGSON_INTRMASK_PCI_PARERR,
60 1.1 bouyer .bc_intSteer = 0,
61 1.1 bouyer .bc_intPol = LOONGSON_INTRMASK_DRAM_PARERR |
62 1.1 bouyer LOONGSON_INTRMASK_PCI_SYSERR | LOONGSON_INTRMASK_PCI_PARERR,
63 1.1 bouyer
64 1.1 bouyer .bc_attach_hook = gdium_attach_hook,
65 1.1 bouyer };
66 1.1 bouyer
67 1.1 bouyer
68 1.1 bouyer const struct platform gdium_platform = {
69 1.1 bouyer .system_type = LOONGSON_GDIUM,
70 1.1 bouyer .vendor = "EMTEC",
71 1.1 bouyer .product = "Gdium",
72 1.1 bouyer
73 1.1 bouyer .bonito_config = &gdium_bonito,
74 1.1 bouyer .isa_chipset = NULL,
75 1.1 bouyer .legacy_io_ranges = NULL,
76 1.1 bouyer .bonito_mips_intr = MIPS_INT_MASK_4,
77 1.1 bouyer .isa_mips_intr = 0,
78 1.1 bouyer .isa_intr = NULL,
79 1.1 bouyer .p_pci_intr_map = gdium_intr_map,
80 1.1 bouyer .irq_map = loongson2f_irqmap,
81 1.1 bouyer
82 1.1 bouyer .setup = NULL,
83 1.1 bouyer .device_register = gdium_device_register,
84 1.1 bouyer
85 1.1 bouyer .powerdown = gdium_powerdown,
86 1.1 bouyer .reset = gdium_reset
87 1.1 bouyer };
88 1.1 bouyer
89 1.2 macallan static struct vcons_screen gdium_console_screen;
90 1.2 macallan
91 1.2 macallan static struct wsscreen_descr gdium_stdscreen = {
92 1.2 macallan .name = "std",
93 1.2 macallan };
94 1.2 macallan
95 1.1 bouyer void
96 1.1 bouyer gdium_attach_hook(device_t parent, device_t self,
97 1.1 bouyer struct pcibus_attach_args *pba)
98 1.1 bouyer {
99 1.1 bouyer pci_chipset_tag_t pc = pba->pba_pc;
100 1.1 bouyer pcireg_t id;
101 1.1 bouyer pcitag_t tag;
102 1.1 bouyer #ifdef notyet
103 1.1 bouyer int bar;
104 1.1 bouyer #endif
105 1.1 bouyer #if 0
106 1.1 bouyer pcireg_t reg;
107 1.1 bouyer int dev, func;
108 1.1 bouyer #endif
109 1.1 bouyer
110 1.1 bouyer if (pba->pba_bus != 0)
111 1.1 bouyer return;
112 1.1 bouyer
113 1.1 bouyer #ifdef notyet
114 1.1 bouyer /*
115 1.1 bouyer * Clear all BAR of the mini PCI slot; PMON did not initialize
116 1.1 bouyer * it, and we do not want it to conflict with anything.
117 1.1 bouyer */
118 1.1 bouyer tag = pci_make_tag(pc, 0, 13, 0);
119 1.1 bouyer for (bar = PCI_MAPREG_START; bar < PCI_MAPREG_END; bar += 4)
120 1.1 bouyer pci_conf_write(pc, tag, bar, 0);
121 1.1 bouyer #else
122 1.1 bouyer /*
123 1.1 bouyer * Force a non conflicting BAR for the wireless controller,
124 1.1 bouyer * until proper resource configuration code is added to
125 1.1 bouyer * bonito (work in progress).
126 1.1 bouyer */
127 1.1 bouyer tag = pci_make_tag(pc, 0, 13, 0);
128 1.1 bouyer pci_conf_write(pc, tag, PCI_MAPREG_START, 0x06228000);
129 1.1 bouyer #endif
130 1.1 bouyer
131 1.1 bouyer /*
132 1.1 bouyer * Figure out which motherboard we are running on.
133 1.1 bouyer * Might not be good enough...
134 1.1 bouyer */
135 1.1 bouyer tag = pci_make_tag(pc, 0, 17, 0);
136 1.1 bouyer id = pci_conf_read(pc, tag, PCI_ID_REG);
137 1.1 bouyer if (id == PCI_ID_CODE(PCI_VENDOR_NEC, PCI_PRODUCT_NEC_USB))
138 1.1 bouyer gdium_revision = 1;
139 1.1 bouyer
140 1.1 bouyer #if 0
141 1.1 bouyer /*
142 1.1 bouyer * Tweak the usb controller capabilities.
143 1.1 bouyer */
144 1.1 bouyer for (dev = pci_bus_maxdevs(pc, 0); dev >= 0; dev--) {
145 1.1 bouyer tag = pci_make_tag(pc, 0, dev, 0);
146 1.1 bouyer id = pci_conf_read(pc, tag, PCI_ID_REG);
147 1.1 bouyer if (id != PCI_ID_CODE(PCI_VENDOR_NEC, PCI_PRODUCT_NEC_USB))
148 1.1 bouyer continue;
149 1.1 bouyer if (gdium_revision != 0) {
150 1.1 bouyer reg = pci_conf_read(pc, tag, 0xe0);
151 1.1 bouyer /* enable ports 1 and 2 */
152 1.1 bouyer reg |= 0x00000003;
153 1.1 bouyer pci_conf_write(pc, tag, 0xe0, reg);
154 1.1 bouyer } else {
155 1.1 bouyer for (func = 0; func < 2; func++) {
156 1.1 bouyer tag = pci_make_tag(pc, 0, dev, func);
157 1.1 bouyer id = pci_conf_read(pc, tag, PCI_ID_REG);
158 1.1 bouyer if (PCI_VENDOR(id) != PCI_VENDOR_NEC)
159 1.1 bouyer continue;
160 1.1 bouyer if (PCI_PRODUCT(id) != PCI_PRODUCT_NEC_USB &&
161 1.1 bouyer PCI_PRODUCT(id) != PCI_PRODUCT_NEC_USB2)
162 1.1 bouyer continue;
163 1.1 bouyer
164 1.1 bouyer reg = pci_conf_read(pc, tag, 0xe0);
165 1.1 bouyer /* enable ports 1 and 3, disable port 2 */
166 1.1 bouyer reg &= ~0x00000007;
167 1.1 bouyer reg |= 0x00000005;
168 1.1 bouyer pci_conf_write(pc, tag, 0xe0, reg);
169 1.1 bouyer pci_conf_write(pc, tag, 0xe4, 0x00000020);
170 1.1 bouyer }
171 1.1 bouyer }
172 1.1 bouyer }
173 1.1 bouyer #endif
174 1.1 bouyer }
175 1.1 bouyer
176 1.1 bouyer int
177 1.1 bouyer gdium_intr_map(int dev, int fn, int pin, pci_intr_handle_t *ihp)
178 1.1 bouyer {
179 1.1 bouyer switch (dev) {
180 1.1 bouyer /* mini-PCI slot */
181 1.1 bouyer case 13: /* C D A B */
182 1.1 bouyer *ihp = BONITO_DIRECT_IRQ(LOONGSON_INTR_PCIA + (pin + 1) % 4);
183 1.1 bouyer return 0;
184 1.1 bouyer /* Frame buffer */
185 1.1 bouyer case 14:
186 1.1 bouyer *ihp = BONITO_DIRECT_IRQ(LOONGSON_INTR_PCIA);
187 1.1 bouyer return 0;
188 1.1 bouyer /* USB */
189 1.1 bouyer case 15:
190 1.1 bouyer if (gdium_revision == 0)
191 1.1 bouyer *ihp = BONITO_DIRECT_IRQ(LOONGSON_INTR_PCIA +
192 1.1 bouyer (pin - 1));
193 1.1 bouyer else
194 1.1 bouyer *ihp = BONITO_DIRECT_IRQ(LOONGSON_INTR_PCIB);
195 1.1 bouyer return 0;
196 1.1 bouyer /* Ethernet */
197 1.1 bouyer case 16:
198 1.1 bouyer *ihp = BONITO_DIRECT_IRQ(LOONGSON_INTR_PCID);
199 1.1 bouyer return 0;
200 1.1 bouyer /* USB, not present in old motherboard revision */
201 1.1 bouyer case 17:
202 1.1 bouyer if (gdium_revision != 0) {
203 1.1 bouyer *ihp = BONITO_DIRECT_IRQ(LOONGSON_INTR_PCIC);
204 1.1 bouyer return 0;
205 1.1 bouyer } else
206 1.1 bouyer break;
207 1.1 bouyer default:
208 1.1 bouyer break;
209 1.1 bouyer }
210 1.1 bouyer
211 1.1 bouyer return 1;
212 1.1 bouyer }
213 1.1 bouyer
214 1.1 bouyer /*
215 1.1 bouyer * Due to PMON limitations on the Gdium Liberty, we do not get boot device
216 1.1 bouyer * information from PMON.
217 1.1 bouyer *
218 1.1 bouyer * Because of this, we always pretend the G-Key port is the boot device.
219 1.1 bouyer *
220 1.1 bouyer * Note that, unlike on the Lemote machines, other USB devices gets a fixed
221 1.1 bouyer * numbering (USB0 and USB1).
222 1.1 bouyer */
223 1.1 bouyer
224 1.1 bouyer extern struct cfdriver bonito_cd;
225 1.1 bouyer extern struct cfdriver pci_cd;
226 1.1 bouyer extern struct cfdriver ehci_cd;
227 1.1 bouyer extern struct cfdriver usb_cd;
228 1.1 bouyer extern struct cfdriver uhub_cd;
229 1.1 bouyer extern struct cfdriver umass_cd;
230 1.1 bouyer extern struct cfdriver scsibus_cd;
231 1.1 bouyer extern struct cfdriver sd_cd;
232 1.1 bouyer
233 1.1 bouyer #include <dev/pci/pcivar.h>
234 1.1 bouyer #include <dev/usb/usb.h>
235 1.1 bouyer #include <dev/usb/usbdi.h>
236 1.1 bouyer
237 1.1 bouyer void
238 1.5 chs gdium_device_register(device_t dev, void *aux)
239 1.1 bouyer {
240 1.2 macallan prop_dictionary_t dict;
241 1.1 bouyer static int gkey_chain_pos = 0;
242 1.5 chs static device_t lastparent = NULL;
243 1.1 bouyer
244 1.6 macallan if (device_is_a(dev, "genfb") || device_is_a(dev, "voyagerfb")) {
245 1.6 macallan dict = device_properties(dev);
246 1.6 macallan /*
247 1.6 macallan * this is a hack
248 1.6 macallan * is_console needs to be checked against reality
249 1.6 macallan */
250 1.6 macallan prop_dictionary_set_bool(dict, "is_console", 1);
251 1.6 macallan prop_dictionary_set_uint32(dict, "width", 1024);
252 1.6 macallan prop_dictionary_set_uint32(dict, "height", 600);
253 1.6 macallan prop_dictionary_set_uint32(dict, "depth", 16);
254 1.6 macallan prop_dictionary_set_uint32(dict, "linebytes", 2048);
255 1.6 macallan if (fb_addr != 0)
256 1.6 macallan prop_dictionary_set_uint32(dict, "address", fb_addr);
257 1.6 macallan }
258 1.5 chs if (device_parent(dev) != lastparent && gkey_chain_pos != 0)
259 1.1 bouyer return;
260 1.1 bouyer
261 1.1 bouyer switch (gkey_chain_pos) {
262 1.1 bouyer case 0: /* bonito at mainbus */
263 1.1 bouyer if (device_is_a(dev, "bonito"))
264 1.1 bouyer goto advance;
265 1.1 bouyer break;
266 1.1 bouyer case 1: /* pci at bonito */
267 1.1 bouyer if (device_is_a(dev, "pci"))
268 1.1 bouyer goto advance;
269 1.1 bouyer break;
270 1.1 bouyer case 2: /* ehci at pci dev 15 */
271 1.1 bouyer if (device_is_a(dev, "ehci")) {
272 1.1 bouyer struct pci_attach_args *paa = aux;
273 1.1 bouyer if (paa->pa_device == 15)
274 1.1 bouyer goto advance;
275 1.1 bouyer }
276 1.1 bouyer break;
277 1.1 bouyer case 3: /* usb at ehci */
278 1.1 bouyer if (device_is_a(dev, "usb"))
279 1.1 bouyer goto advance;
280 1.1 bouyer break;
281 1.1 bouyer case 4: /* uhub at usb */
282 1.1 bouyer if (device_is_a(dev, "uhub"))
283 1.1 bouyer goto advance;
284 1.1 bouyer break;
285 1.1 bouyer case 5: /* umass at uhub port 3 */
286 1.1 bouyer if (device_is_a(dev, "umass")) {
287 1.1 bouyer struct usb_attach_arg *uaa = aux;
288 1.1 bouyer if (uaa->port == 3)
289 1.1 bouyer goto advance;
290 1.1 bouyer }
291 1.1 bouyer break;
292 1.1 bouyer case 6: /* scsibus at umass */
293 1.1 bouyer if (device_is_a(dev, "scsibus"))
294 1.1 bouyer goto advance;
295 1.1 bouyer break;
296 1.1 bouyer case 7: /* sd at scsibus */
297 1.1 bouyer if (booted_device == NULL)
298 1.1 bouyer booted_device = dev;
299 1.1 bouyer break;
300 1.1 bouyer }
301 1.1 bouyer
302 1.1 bouyer return;
303 1.1 bouyer
304 1.1 bouyer advance:
305 1.1 bouyer gkey_chain_pos++;
306 1.1 bouyer lastparent = dev;
307 1.1 bouyer }
308 1.1 bouyer
309 1.1 bouyer void
310 1.4 christos gdium_powerdown(void)
311 1.1 bouyer {
312 1.1 bouyer REGVAL(BONITO_GPIODATA) |= 0x00000002;
313 1.1 bouyer REGVAL(BONITO_GPIOIE) &= ~0x00000002;
314 1.3 macallan printf("Powering down...\n");
315 1.3 macallan while(1) delay(1000);
316 1.1 bouyer }
317 1.1 bouyer
318 1.1 bouyer void
319 1.4 christos gdium_reset(void)
320 1.1 bouyer {
321 1.1 bouyer REGVAL(BONITO_GPIODATA) &= ~0x00000002;
322 1.1 bouyer REGVAL(BONITO_GPIOIE) &= ~0x00000002;
323 1.1 bouyer }
324 1.2 macallan
325 1.2 macallan /*
326 1.2 macallan * Early console code
327 1.2 macallan */
328 1.2 macallan
329 1.2 macallan int
330 1.2 macallan gdium_cnattach(bus_space_tag_t memt, bus_space_tag_t iot,
331 1.2 macallan pci_chipset_tag_t pc, pcitag_t tag, pcireg_t id)
332 1.2 macallan {
333 1.2 macallan struct rasops_info * const ri = &gdium_console_screen.scr_ri;
334 1.2 macallan long defattr;
335 1.2 macallan pcireg_t reg;
336 1.2 macallan
337 1.2 macallan
338 1.2 macallan /* filter out unrecognized devices */
339 1.2 macallan switch (id) {
340 1.2 macallan default:
341 1.2 macallan return ENODEV;
342 1.2 macallan case PCI_ID_CODE(PCI_VENDOR_SILMOTION, PCI_PRODUCT_SILMOTION_SM502):
343 1.2 macallan break;
344 1.2 macallan }
345 1.2 macallan
346 1.2 macallan wsfont_init();
347 1.2 macallan
348 1.2 macallan /* set up rasops */
349 1.2 macallan ri->ri_width = 1024;
350 1.2 macallan ri->ri_height = 600;
351 1.2 macallan ri->ri_depth = 16;
352 1.2 macallan ri->ri_stride = 0x800;
353 1.2 macallan
354 1.2 macallan /* read the mapping register for the frame buffer */
355 1.2 macallan reg = pci_conf_read(pc, tag, PCI_MAPREG_START);
356 1.2 macallan fb_addr = reg;
357 1.2 macallan
358 1.2 macallan ri->ri_bits = (char *)MIPS_PHYS_TO_KSEG1(BONITO_PCILO_BASE + reg);
359 1.2 macallan ri->ri_flg = RI_CENTER | RI_NO_AUTO;
360 1.2 macallan
361 1.2 macallan memset(ri->ri_bits, 0, 0x200000);
362 1.2 macallan
363 1.2 macallan /* use as much of the screen as the font permits */
364 1.2 macallan rasops_init(ri, 30, 80);
365 1.2 macallan
366 1.2 macallan rasops_reconfig(ri, ri->ri_height / ri->ri_font->fontheight,
367 1.2 macallan ri->ri_width / ri->ri_font->fontwidth);
368 1.2 macallan
369 1.2 macallan gdium_stdscreen.nrows = ri->ri_rows;
370 1.2 macallan gdium_stdscreen.ncols = ri->ri_cols;
371 1.2 macallan gdium_stdscreen.textops = &ri->ri_ops;
372 1.2 macallan gdium_stdscreen.capabilities = ri->ri_caps;
373 1.2 macallan
374 1.2 macallan ri->ri_ops.allocattr(ri, 0, ri->ri_rows - 1, 0, &defattr);
375 1.2 macallan
376 1.2 macallan wsdisplay_preattach(&gdium_stdscreen, ri, 0, 0, defattr);
377 1.2 macallan
378 1.2 macallan return 0;
379 1.2 macallan
380 1.2 macallan }
381