1 /* $OpenBSD: if_ral_cardbus.c,v 1.23 2022/04/06 18:59:28 naddy Exp $ */
2
3 /*-
4 * Copyright (c) 2005-2010 Damien Bergamini <damien.bergamini@free.fr>
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 * CardBus front-end for the Ralink RT2560/RT2561/RT2860/RT3090 driver.
21 */
22
23 #include "bpfilter.h"
24
25 #include <sys/param.h>
26 #include <sys/sockio.h>
27 #include <sys/mbuf.h>
28 #include <sys/kernel.h>
29 #include <sys/socket.h>
30 #include <sys/systm.h>
31 #include <sys/malloc.h>
32 #include <sys/timeout.h>
33 #include <sys/device.h>
34
35 #include <machine/bus.h>
36 #include <machine/intr.h>
37
38 #include <net/if.h>
39 #include <net/if_media.h>
40
41 #include <netinet/in.h>
42 #include <netinet/if_ether.h>
43
44 #include <net80211/ieee80211_var.h>
45 #include <net80211/ieee80211_amrr.h>
46 #include <net80211/ieee80211_radiotap.h>
47
48 #include <dev/ic/rt2560var.h>
49 #include <dev/ic/rt2661var.h>
50 #include <dev/ic/rt2860var.h>
51
52 #include <dev/pci/pcireg.h>
53 #include <dev/pci/pcivar.h>
54 #include <dev/pci/pcidevs.h>
55
56 #include <dev/cardbus/cardbusvar.h>
57
58 static struct ral_opns {
59 int (*attach)(void *, int);
60 int (*detach)(void *);
61 void (*suspend)(void *);
62 void (*resume)(void *);
63 int (*intr)(void *);
64
65 } ral_rt2560_opns = {
66 rt2560_attach,
67 rt2560_detach,
68 rt2560_suspend,
69 rt2560_wakeup,
70 rt2560_intr
71
72 }, ral_rt2661_opns = {
73 rt2661_attach,
74 rt2661_detach,
75 rt2661_suspend,
76 rt2661_wakeup,
77 rt2661_intr
78
79 }, ral_rt2860_opns = {
80 rt2860_attach,
81 rt2860_detach,
82 rt2860_suspend,
83 rt2860_wakeup,
84 rt2860_intr
85 };
86
87 struct ral_cardbus_softc {
88 union {
89 struct rt2560_softc sc_rt2560;
90 struct rt2661_softc sc_rt2661;
91 struct rt2860_softc sc_rt2860;
92 } u;
93 #define sc_sc u.sc_rt2560
94
95 /* cardbus specific goo */
96 struct ral_opns *sc_opns;
97 cardbus_devfunc_t sc_ct;
98 pcitag_t sc_tag;
99 void *sc_ih;
100 bus_size_t sc_mapsize;
101 pcireg_t sc_bar_val;
102 int sc_intrline;
103 pci_chipset_tag_t sc_pc;
104 };
105
106 int ral_cardbus_match(struct device *, void *, void *);
107 void ral_cardbus_attach(struct device *, struct device *, void *);
108 int ral_cardbus_detach(struct device *, int);
109 int ral_cardbus_activate(struct device *, int);
110
111 const struct cfattach ral_cardbus_ca = {
112 sizeof (struct ral_cardbus_softc), ral_cardbus_match,
113 ral_cardbus_attach, ral_cardbus_detach,
114 ral_cardbus_activate
115 };
116
117 static const struct pci_matchid ral_cardbus_devices[] = {
118 { PCI_VENDOR_RALINK, PCI_PRODUCT_RALINK_RT2560 },
119 { PCI_VENDOR_RALINK, PCI_PRODUCT_RALINK_RT2561 },
120 { PCI_VENDOR_RALINK, PCI_PRODUCT_RALINK_RT2561S },
121 { PCI_VENDOR_RALINK, PCI_PRODUCT_RALINK_RT2661 },
122 { PCI_VENDOR_RALINK, PCI_PRODUCT_RALINK_RT2860 },
123 { PCI_VENDOR_RALINK, PCI_PRODUCT_RALINK_RT2890 },
124 { PCI_VENDOR_RALINK, PCI_PRODUCT_RALINK_RT2760 },
125 { PCI_VENDOR_RALINK, PCI_PRODUCT_RALINK_RT2790 },
126 { PCI_VENDOR_AWT, PCI_PRODUCT_AWT_RT2890 },
127 { PCI_VENDOR_EDIMAX, PCI_PRODUCT_EDIMAX_RT2860_1 },
128 { PCI_VENDOR_EDIMAX, PCI_PRODUCT_EDIMAX_RT2860_2 },
129 { PCI_VENDOR_EDIMAX, PCI_PRODUCT_EDIMAX_RT2860_3 },
130 { PCI_VENDOR_EDIMAX, PCI_PRODUCT_EDIMAX_RT2860_4 },
131 { PCI_VENDOR_EDIMAX, PCI_PRODUCT_EDIMAX_RT2860_5 },
132 { PCI_VENDOR_EDIMAX, PCI_PRODUCT_EDIMAX_RT2860_6 },
133 { PCI_VENDOR_EDIMAX, PCI_PRODUCT_EDIMAX_RT2860_7 },
134 { PCI_VENDOR_RALINK, PCI_PRODUCT_RALINK_RT3062 },
135 { PCI_VENDOR_RALINK, PCI_PRODUCT_RALINK_RT3090 },
136 { PCI_VENDOR_RALINK, PCI_PRODUCT_RALINK_RT3091 },
137 { PCI_VENDOR_RALINK, PCI_PRODUCT_RALINK_RT3092 },
138 { PCI_VENDOR_RALINK, PCI_PRODUCT_RALINK_RT3562 },
139 { PCI_VENDOR_RALINK, PCI_PRODUCT_RALINK_RT3592 },
140 { PCI_VENDOR_RALINK, PCI_PRODUCT_RALINK_RT3593 }
141 };
142
143 int ral_cardbus_enable(struct rt2560_softc *);
144 void ral_cardbus_disable(struct rt2560_softc *);
145 void ral_cardbus_setup(struct ral_cardbus_softc *);
146 void ral_cardbus_wakeup(struct ral_cardbus_softc *);
147
148 int
149 ral_cardbus_match(struct device *parent, void *match, void *aux)
150 {
151 return (cardbus_matchbyid((struct cardbus_attach_args *)aux,
152 ral_cardbus_devices, nitems(ral_cardbus_devices)));
153 }
154
155 void
156 ral_cardbus_attach(struct device *parent, struct device *self, void *aux)
157 {
158 struct ral_cardbus_softc *csc = (struct ral_cardbus_softc *)self;
159 struct rt2560_softc *sc = &csc->sc_sc;
160 struct cardbus_attach_args *ca = aux;
161 cardbus_devfunc_t ct = ca->ca_ct;
162 bus_addr_t base;
163 int error;
164
165 if (PCI_VENDOR(ca->ca_id) == PCI_VENDOR_RALINK) {
166 switch (PCI_PRODUCT(ca->ca_id)) {
167 case PCI_PRODUCT_RALINK_RT2560:
168 csc->sc_opns = &ral_rt2560_opns;
169 break;
170 case PCI_PRODUCT_RALINK_RT2561:
171 case PCI_PRODUCT_RALINK_RT2561S:
172 case PCI_PRODUCT_RALINK_RT2661:
173 csc->sc_opns = &ral_rt2661_opns;
174 break;
175 default:
176 csc->sc_opns = &ral_rt2860_opns;
177 break;
178 }
179 } else {
180 /* all other vendors are RT2860 only */
181 csc->sc_opns = &ral_rt2860_opns;
182 }
183 sc->sc_dmat = ca->ca_dmat;
184 csc->sc_ct = ct;
185 csc->sc_tag = ca->ca_tag;
186 csc->sc_intrline = ca->ca_intrline;
187 csc->sc_pc = ca->ca_pc;
188
189 /* power management hooks */
190 sc->sc_enable = ral_cardbus_enable;
191 sc->sc_disable = ral_cardbus_disable;
192
193 /* map control/status registers */
194 error = Cardbus_mapreg_map(ct, CARDBUS_BASE0_REG,
195 PCI_MAPREG_TYPE_MEM, 0, &sc->sc_st, &sc->sc_sh, &base,
196 &csc->sc_mapsize);
197 if (error != 0) {
198 printf(": can't map mem space\n");
199 return;
200 }
201
202 csc->sc_bar_val = base | PCI_MAPREG_TYPE_MEM;
203
204 /* set up the PCI configuration registers */
205 ral_cardbus_setup(csc);
206
207 printf(": irq %d", csc->sc_intrline);
208
209 (*csc->sc_opns->attach)(sc, PCI_PRODUCT(ca->ca_id));
210
211 Cardbus_function_disable(ct);
212 }
213
214 int
215 ral_cardbus_detach(struct device *self, int flags)
216 {
217 struct ral_cardbus_softc *csc = (struct ral_cardbus_softc *)self;
218 struct rt2560_softc *sc = &csc->sc_sc;
219 cardbus_devfunc_t ct = csc->sc_ct;
220 cardbus_chipset_tag_t cc = ct->ct_cc;
221 cardbus_function_tag_t cf = ct->ct_cf;
222 int error;
223
224 error = (*csc->sc_opns->detach)(sc);
225 if (error != 0)
226 return error;
227
228 /* unhook the interrupt handler */
229 if (csc->sc_ih != NULL) {
230 cardbus_intr_disestablish(cc, cf, csc->sc_ih);
231 csc->sc_ih = NULL;
232 }
233
234 /* release bus space and close window */
235 Cardbus_mapreg_unmap(ct, CARDBUS_BASE0_REG, sc->sc_st, sc->sc_sh,
236 csc->sc_mapsize);
237
238 return 0;
239 }
240
241 int
242 ral_cardbus_activate(struct device *self, int act)
243 {
244 struct ral_cardbus_softc *csc = (struct ral_cardbus_softc *)self;
245 struct rt2560_softc *sc = &csc->sc_sc;
246
247 switch (act) {
248 case DVACT_SUSPEND:
249 (*csc->sc_opns->suspend)(sc);
250 break;
251 case DVACT_WAKEUP:
252 ral_cardbus_wakeup(csc);
253 break;
254 }
255
256 return 0;
257 }
258
259 int
260 ral_cardbus_enable(struct rt2560_softc *sc)
261 {
262 struct ral_cardbus_softc *csc = (struct ral_cardbus_softc *)sc;
263 cardbus_devfunc_t ct = csc->sc_ct;
264 cardbus_chipset_tag_t cc = ct->ct_cc;
265 cardbus_function_tag_t cf = ct->ct_cf;
266
267 /* power on the socket */
268 Cardbus_function_enable(ct);
269
270 /* setup the PCI configuration registers */
271 ral_cardbus_setup(csc);
272
273 /* map and establish the interrupt handler */
274 csc->sc_ih = cardbus_intr_establish(cc, cf, csc->sc_intrline, IPL_NET,
275 csc->sc_opns->intr, sc, sc->sc_dev.dv_xname);
276 if (csc->sc_ih == NULL) {
277 printf("%s: could not establish interrupt at %d\n",
278 sc->sc_dev.dv_xname, csc->sc_intrline);
279 Cardbus_function_disable(ct);
280 return 1;
281 }
282
283 return 0;
284 }
285
286 void
287 ral_cardbus_disable(struct rt2560_softc *sc)
288 {
289 struct ral_cardbus_softc *csc = (struct ral_cardbus_softc *)sc;
290 cardbus_devfunc_t ct = csc->sc_ct;
291 cardbus_chipset_tag_t cc = ct->ct_cc;
292 cardbus_function_tag_t cf = ct->ct_cf;
293
294 /* unhook the interrupt handler */
295 cardbus_intr_disestablish(cc, cf, csc->sc_ih);
296 csc->sc_ih = NULL;
297
298 /* power down the socket */
299 Cardbus_function_disable(ct);
300 }
301
302 void
303 ral_cardbus_setup(struct ral_cardbus_softc *csc)
304 {
305 cardbus_devfunc_t ct = csc->sc_ct;
306 cardbus_chipset_tag_t cc = ct->ct_cc;
307 pci_chipset_tag_t pc = csc->sc_pc;
308 cardbus_function_tag_t cf = ct->ct_cf;
309 pcireg_t reg;
310
311 /* program the BAR */
312 pci_conf_write(pc, csc->sc_tag, CARDBUS_BASE0_REG,
313 csc->sc_bar_val);
314
315 /* make sure the right access type is on the cardbus bridge */
316 (*cf->cardbus_ctrl)(cc, CARDBUS_MEM_ENABLE);
317 (*cf->cardbus_ctrl)(cc, CARDBUS_BM_ENABLE);
318
319 /* enable the appropriate bits in the PCI CSR */
320 reg = pci_conf_read(pc, csc->sc_tag,
321 PCI_COMMAND_STATUS_REG);
322 reg |= PCI_COMMAND_MASTER_ENABLE | PCI_COMMAND_MEM_ENABLE;
323 pci_conf_write(pc, csc->sc_tag, PCI_COMMAND_STATUS_REG,
324 reg);
325 }
326
327 void
328 ral_cardbus_wakeup(struct ral_cardbus_softc *csc)
329 {
330 struct rt2560_softc *sc = &csc->sc_sc;
331 int s;
332
333 s = splnet();
334 (*csc->sc_opns->resume)(sc);
335 splx(s);
336 }
Cache object: 2ea4adaf2f2d5b3853ce0b678e6ce559
|