1 /* $OpenBSD: gdium_machdep.c,v 1.9 2023/04/13 02:19:05 jsg Exp $ */
2
3 /*
4 * Copyright (c) 2010 Miodrag Vallat.
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19 /*
20 * Gdium Liberty specific code and configuration data.
21 */
22
23 #include <sys/param.h>
24 #include <sys/systm.h>
25 #include <sys/device.h>
26
27 #include <machine/autoconf.h>
28
29 #include <dev/pci/pcireg.h>
30 #include <dev/pci/pcivar.h>
31 #include <dev/pci/pcidevs.h>
32
33 #include <loongson/dev/bonitoreg.h>
34 #include <loongson/dev/bonitovar.h>
35 #include <loongson/dev/bonito_irq.h>
36
37 int gdium_revision = 0;
38
39 void gdium_attach_hook(pci_chipset_tag_t);
40 void gdium_device_register(struct device *, void *);
41 int gdium_intr_map(int, int, int);
42 void gdium_powerdown(void);
43 void gdium_reset(void);
44 void gdium_setup(void);
45
46 const struct bonito_config gdium_bonito = {
47 .bc_adbase = 11,
48
49 .bc_gpioIE = LOONGSON_INTRMASK_GPIO,
50 .bc_intEdge = LOONGSON_INTRMASK_PCI_SYSERR |
51 LOONGSON_INTRMASK_PCI_PARERR,
52 .bc_intSteer = 0,
53 .bc_intPol = LOONGSON_INTRMASK_DRAM_PARERR |
54 LOONGSON_INTRMASK_PCI_SYSERR | LOONGSON_INTRMASK_PCI_PARERR,
55
56 .bc_attach_hook = gdium_attach_hook,
57 .bc_intr_map = gdium_intr_map
58 };
59
60 const struct platform gdium_platform = {
61 .system_type = LOONGSON_GDIUM,
62 .vendor = "EMTEC",
63 .product = "Gdium",
64
65 .bonito_config = &gdium_bonito,
66 .isa_chipset = NULL,
67 .legacy_io_ranges = NULL,
68
69 .setup = gdium_setup,
70 .device_register = gdium_device_register,
71
72 .powerdown = gdium_powerdown,
73 .reset = gdium_reset
74 };
75
76 void
gdium_attach_hook(pci_chipset_tag_t pc)77 gdium_attach_hook(pci_chipset_tag_t pc)
78 {
79 pcireg_t id;
80 pcitag_t tag;
81 #ifdef notyet
82 int bar;
83 #endif
84 #if 0
85 pcireg_t reg;
86 int dev, func;
87 #endif
88
89 #ifdef notyet
90 /*
91 * Clear all BAR of the mini PCI slot; PMON did not initialize
92 * it, and we do not want it to conflict with anything.
93 */
94 tag = pci_make_tag(pc, 0, 13, 0);
95 for (bar = PCI_MAPREG_START; bar < PCI_MAPREG_END; bar += 4)
96 pci_conf_write(pc, tag, bar, 0);
97 #else
98 /*
99 * Force a non conflicting BAR for the wireless controller,
100 * until proper resource configuration code is added to
101 * bonito (work in progress).
102 */
103 tag = pci_make_tag(pc, 0, 13, 0);
104 pci_conf_write(pc, tag, PCI_MAPREG_START, 0x06228000);
105 #endif
106
107 /*
108 * Figure out which motherboard we are running on.
109 * Might not be good enough...
110 */
111 tag = pci_make_tag(pc, 0, 17, 0);
112 id = pci_conf_read(pc, tag, PCI_ID_REG);
113 if (id == PCI_ID_CODE(PCI_VENDOR_NEC, PCI_PRODUCT_NEC_USB))
114 gdium_revision = 1;
115
116 #if 0
117 /*
118 * Tweak the usb controller capabilities.
119 */
120 for (dev = pci_bus_maxdevs(pc, 0); dev >= 0; dev--) {
121 tag = pci_make_tag(pc, 0, dev, 0);
122 id = pci_conf_read(pc, tag, PCI_ID_REG);
123 if (id != PCI_ID_CODE(PCI_VENDOR_NEC, PCI_PRODUCT_NEC_USB))
124 continue;
125 if (gdium_revision != 0) {
126 reg = pci_conf_read(pc, tag, 0xe0);
127 /* enable ports 1 and 2 */
128 reg |= 0x00000003;
129 pci_conf_write(pc, tag, 0xe0, reg);
130 } else {
131 for (func = 0; func < 2; func++) {
132 tag = pci_make_tag(pc, 0, dev, func);
133 id = pci_conf_read(pc, tag, PCI_ID_REG);
134 if (PCI_VENDOR(id) != PCI_VENDOR_NEC)
135 continue;
136 if (PCI_PRODUCT(id) != PCI_PRODUCT_NEC_USB &&
137 PCI_PRODUCT(id) != PCI_PRODUCT_NEC_USB2)
138 continue;
139
140 reg = pci_conf_read(pc, tag, 0xe0);
141 /* enable ports 1 and 3, disable port 2 */
142 reg &= ~0x00000007;
143 reg |= 0x00000005;
144 pci_conf_write(pc, tag, 0xe0, reg);
145 pci_conf_write(pc, tag, 0xe4, 0x00000020);
146 }
147 }
148 }
149 #endif
150 }
151
152 int
gdium_intr_map(int dev,int fn,int pin)153 gdium_intr_map(int dev, int fn, int pin)
154 {
155 switch (dev) {
156 /* mini-PCI slot */
157 case 13: /* C D A B */
158 return BONITO_DIRECT_IRQ(LOONGSON_INTR_PCIA + (pin + 1) % 4);
159 /* Frame buffer */
160 case 14:
161 return BONITO_DIRECT_IRQ(LOONGSON_INTR_PCIA);
162 /* USB */
163 case 15:
164 if (gdium_revision == 0)
165 return BONITO_DIRECT_IRQ(LOONGSON_INTR_PCIA +
166 (pin - 1));
167 else
168 return BONITO_DIRECT_IRQ(LOONGSON_INTR_PCIB);
169 /* Ethernet */
170 case 16:
171 return BONITO_DIRECT_IRQ(LOONGSON_INTR_PCID);
172 /* USB, not present in old motherboard revision */
173 case 17:
174 if (gdium_revision != 0)
175 return BONITO_DIRECT_IRQ(LOONGSON_INTR_PCIC);
176 else
177 break;
178 default:
179 break;
180 }
181
182 return -1;
183 }
184
185 /*
186 * Due to PMON limitations on the Gdium Liberty, we do not get boot device
187 * information from PMON.
188 *
189 * Because of this, we always pretend the G-Key port is the boot device.
190 *
191 * Note that, unlike on the Lemote machines, other USB devices gets a fixed
192 * numbering (USB0 and USB1).
193 */
194
195 extern struct cfdriver bonito_cd;
196 extern struct cfdriver pci_cd;
197 extern struct cfdriver ehci_cd;
198 extern struct cfdriver usb_cd;
199 extern struct cfdriver uhub_cd;
200 extern struct cfdriver umass_cd;
201 extern struct cfdriver scsibus_cd;
202 extern struct cfdriver sd_cd;
203
204 #include <dev/usb/usb.h>
205 #include <dev/usb/usbdi.h>
206
207 void
gdium_device_register(struct device * dev,void * aux)208 gdium_device_register(struct device *dev, void *aux)
209 {
210 struct cfdriver *cf = dev->dv_cfdata->cf_driver;
211 static int gkey_chain_pos = 0;
212 static struct device *lastparent = NULL;
213
214 if (dev->dv_parent != lastparent && gkey_chain_pos != 0)
215 return;
216
217 switch (gkey_chain_pos) {
218 case 0: /* bonito at mainbus */
219 if (cf == &bonito_cd)
220 goto advance;
221 break;
222 case 1: /* pci at bonito */
223 if (cf == &pci_cd)
224 goto advance;
225 break;
226 case 2: /* ehci at pci dev 15 */
227 if (cf == &ehci_cd) {
228 struct pci_attach_args *paa = aux;
229 if (paa->pa_device == 15)
230 goto advance;
231 }
232 break;
233 case 3: /* usb at ehci */
234 if (cf == &usb_cd)
235 goto advance;
236 break;
237 case 4: /* uhub at usb */
238 if (cf == &uhub_cd)
239 goto advance;
240 break;
241 case 5: /* umass at uhub port 3 */
242 if (cf == &umass_cd) {
243 struct usb_attach_arg *uaa = aux;
244 if (uaa->port == 3)
245 goto advance;
246 }
247 break;
248 case 6: /* scsibus at umass */
249 if (cf == &scsibus_cd)
250 goto advance;
251 break;
252 case 7: /* sd at scsibus */
253 bootdv = dev;
254 break;
255 }
256
257 return;
258
259 advance:
260 gkey_chain_pos++;
261 lastparent = dev;
262 }
263
264 void
gdium_powerdown()265 gdium_powerdown()
266 {
267 REGVAL(BONITO_GPIODATA) |= 0x00000002;
268 REGVAL(BONITO_GPIOIE) &= ~0x00000002;
269 }
270
271 void
gdium_reset()272 gdium_reset()
273 {
274 REGVAL(BONITO_GPIODATA) &= ~0x00000002;
275 REGVAL(BONITO_GPIOIE) &= ~0x00000002;
276 }
277
278 void
gdium_setup()279 gdium_setup()
280 {
281 bonito_early_setup();
282 }
283