1 /* $NetBSD: ar5312.c,v 1.4 2007/02/28 04:21:53 thorpej Exp $ */
4 * Copyright (c) 2006 Urbana-Champaign Independent Media Center.
5 * Copyright (c) 2006 Garrett D'Amore.
8 * Portions of this code were written by Garrett D'Amore for the
9 * Champaign-Urbana Community Wireless Network Project.
11 * Redistribution and use in source and binary forms, with or
12 * without modification, are permitted provided that the following
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above
17 * copyright notice, this list of conditions and the following
18 * disclaimer in the documentation and/or other materials provided
19 * with the distribution.
20 * 3. All advertising materials mentioning features or use of this
21 * software must display the following acknowledgements:
22 * This product includes software developed by the Urbana-Champaign
23 * Independent Media Center.
24 * This product includes software developed by Garrett D'Amore.
25 * 4. Urbana-Champaign Independent Media Center's name and Garrett
26 * D'Amore's name may not be used to endorse or promote products
27 * derived from this software without specific prior written permission.
29 * THIS SOFTWARE IS PROVIDED BY THE URBANA-CHAMPAIGN INDEPENDENT
30 * MEDIA CENTER AND GARRETT D'AMORE ``AS IS'' AND ANY EXPRESS OR
31 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
32 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
33 * ARE DISCLAIMED. IN NO EVENT SHALL THE URBANA-CHAMPAIGN INDEPENDENT
34 * MEDIA CENTER OR GARRETT D'AMORE BE LIABLE FOR ANY DIRECT, INDIRECT,
35 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
36 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
37 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
38 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
40 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
41 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
45 * This file includes a bunch of implementation specific bits for
46 * AR5312, which differents these from other members of the AR5315
52 #include "opt_memsize.h"
53 #include <sys/param.h>
54 #include <sys/systm.h>
55 #include <sys/kernel.h>
58 #include <mips/cache.h>
59 #include <mips/locore.h>
60 #include <mips/cpuregs.h>
62 #include <sys/socket.h> /* these three just to get ETHER_ADDR_LEN(!) */
64 #include <net/if_ether.h>
66 #include <prop/proplib.h>
68 #include <mips/atheros/include/ar5312reg.h>
69 #include <mips/atheros/include/ar531xvar.h>
70 #include <mips/atheros/include/arbusvar.h>
77 uint32_t memcfg
, bank0
, bank1
;
80 * Determine the memory size as established by system
83 * NB: we allow compile time override
88 memcfg
= GETSDRAMREG(AR5312_SDRAMCTL_MEM_CFG1
);
89 bank0
= (memcfg
& AR5312_MEM_CFG1_BANK0_MASK
) >>
90 AR5312_MEM_CFG1_BANK0_SHIFT
;
91 bank1
= (memcfg
& AR5312_MEM_CFG1_BANK1_MASK
) >>
92 AR5312_MEM_CFG1_BANK1_SHIFT
;
94 memsize
= (bank0
? (1 << (bank0
+ 1)) : 0) +
95 (bank1
? (1 << (bank1
+ 1)) : 0);
103 ar531x_wdog(uint32_t period
)
107 PUTSYSREG(AR5312_SYSREG_WDOG_CTL
, AR5312_WDOG_CTL_IGNORE
);
108 PUTSYSREG(AR5312_SYSREG_WDOG_TIMER
, 0);
110 PUTSYSREG(AR5312_SYSREG_WDOG_TIMER
, period
);
111 PUTSYSREG(AR5312_SYSREG_WDOG_CTL
, AR5312_WDOG_CTL_RESET
);
120 revision
= GETSYSREG(AR5312_SYSREG_REVISION
);
121 switch (AR5312_REVISION_MAJOR(revision
)) {
122 case AR5312_REVISION_MAJ_AR5311
:
123 return ("Atheros AR5311");
124 case AR5312_REVISION_MAJ_AR5312
:
125 return ("Atheros AR5312");
126 case AR5312_REVISION_MAJ_AR2313
:
127 return ("Atheros AR2313");
128 case AR5312_REVISION_MAJ_AR5315
:
129 return ("Atheros AR5315");
131 return ("Atheros AR531X");
140 * Clear previous AHB errors
142 GETSYSREG(AR5312_SYSREG_AHBPERR
);
143 GETSYSREG(AR5312_SYSREG_AHBDMAE
);
147 ar531x_cpu_freq(void)
149 static uint32_t cpufreq
;
150 uint32_t wisoc
= GETSYSREG(AR5312_SYSREG_REVISION
);
153 uint32_t predivshift
;
156 uint32_t doublermask
;
161 const int predivide_table
[4] = { 1, 2, 4, 5 };
163 /* XXX: in theory we might be able to get clock from bootrom */
166 * This logic looks at the clock control register and
167 * determines the actual CPU frequency. These parts lack any
168 * kind of real-time clock on them, but the cpu clocks should
169 * be very accurate -- WiFi requires usec resolution timers.
176 if (AR5312_REVISION_MAJOR(wisoc
) == AR5312_REVISION_MAJ_AR2313
) {
177 predivmask
= AR2313_CLOCKCTL_PREDIVIDE_MASK
;
178 predivshift
= AR2313_CLOCKCTL_PREDIVIDE_SHIFT
;
179 multmask
= AR2313_CLOCKCTL_MULTIPLIER_MASK
;
180 multshift
= AR2313_CLOCKCTL_MULTIPLIER_SHIFT
;
181 doublermask
= AR2313_CLOCKCTL_DOUBLER_MASK
;
183 predivmask
= AR5312_CLOCKCTL_PREDIVIDE_MASK
;
184 predivshift
= AR5312_CLOCKCTL_PREDIVIDE_SHIFT
;
185 multmask
= AR5312_CLOCKCTL_MULTIPLIER_MASK
;
186 multshift
= AR5312_CLOCKCTL_MULTIPLIER_SHIFT
;
187 doublermask
= AR5312_CLOCKCTL_DOUBLER_MASK
;
191 * Note that the source clock involved here is a 40MHz.
194 clockctl
= GETSYSREG(AR5312_SYSREG_CLOCKCTL
);
195 divisor
= predivide_table
[(clockctl
& predivmask
) >> predivshift
];
196 multiplier
= (clockctl
& multmask
) >> multshift
;
198 if (clockctl
& doublermask
)
201 cpufreq
= (40000000 / divisor
) * multiplier
;
207 ar531x_bus_freq(void)
209 return (ar531x_cpu_freq() / 4);
213 addprop_data(struct device
*dev
, const char *name
, const uint8_t *data
,
217 pd
= prop_data_create_data(data
, len
);
219 if (prop_dictionary_set(device_properties(dev
), name
, pd
) == false) {
220 printf("WARNING: unable to set %s property for %s\n",
221 name
, device_xname(dev
));
223 prop_object_release(pd
);
227 addprop_integer(struct device
*dev
, const char *name
, uint32_t val
)
230 pn
= prop_number_create_integer(val
);
232 if (prop_dictionary_set(device_properties(dev
), name
, pn
) == false) {
233 printf("WARNING: unable to set %s property for %s",
234 name
, device_xname(dev
));
236 prop_object_release(pn
);
240 ar531x_device_register(struct device
*dev
, void *aux
)
242 struct arbus_attach_args
*aa
= aux
;
243 const struct ar531x_boarddata
*info
;
245 info
= ar531x_board_info();
247 /* nothing known about this board! */
252 * We don't ever know the boot device. But that's because the
253 * firmware only loads from the network.
256 /* Fetch the MAC addresses. */
257 if (device_is_a(dev
, "ae")) {
260 if (aa
->aa_addr
== AR5312_ENET0_BASE
)
261 enet
= info
->enet0Mac
;
262 else if (aa
->aa_addr
== AR5312_ENET1_BASE
)
263 enet
= info
->enet1Mac
;
267 addprop_data(dev
, "mac-addr", enet
, ETHER_ADDR_LEN
);
270 if (device_is_a(dev
, "ath")) {
273 if (aa
->aa_addr
== AR5312_WLAN0_BASE
)
274 enet
= info
->wlan0Mac
;
275 else if (aa
->aa_addr
== AR5312_WLAN1_BASE
)
276 enet
= info
->wlan1Mac
;
280 addprop_data(dev
, "mac-addr", enet
, ETHER_ADDR_LEN
);
282 addprop_integer(dev
, "wmac-rev",
283 AR5312_REVISION_WMAC(GETSYSREG(AR5312_SYSREG_REVISION
)));
287 if (device_is_a(dev
, "com")) {
288 addprop_integer(dev
, "frequency", ar531x_cpu_freq() / 4);
291 if (device_is_a(dev
, "argpio")) {
292 if (info
->config
& BD_RSTFACTORY
) {
293 addprop_integer(dev
, "reset-pin",
294 info
->resetConfigGpio
);
296 if (info
->config
& BD_SYSLED
) {
297 addprop_integer(dev
, "sysled-pin",
304 ar531x_enable_device(const struct ar531x_device
*dev
)
306 const struct ar531x_boarddata
*info
;
308 info
= ar531x_board_info();
309 if (dev
->mask
&& ((dev
->mask
& info
->config
) == 0)) {
313 /* put device into reset */
314 PUTSYSREG(AR5312_SYSREG_RESETCTL
,
315 GETSYSREG(AR5312_SYSREG_RESETCTL
) | dev
->reset
);
317 delay(15000); /* XXX: tsleep? */
319 /* take it out of reset */
320 PUTSYSREG(AR5312_SYSREG_RESETCTL
,
321 GETSYSREG(AR5312_SYSREG_RESETCTL
) & ~dev
->reset
);
326 PUTSYSREG(AR5312_SYSREG_ENABLE
,
327 GETSYSREG(AR5312_SYSREG_ENABLE
) | dev
->enable
);
332 const struct ar531x_device
*
333 ar531x_get_devices(void)
335 static const struct ar531x_device devices
[] = {
338 AR5312_ENET0_BASE
, 0x100000,
339 AR5312_IRQ_ENET0
, -1,
340 AR5312_BOARD_CONFIG_ENET0
,
341 AR5312_RESET_ENET0
| AR5312_RESET_PHY0
,
346 AR5312_ENET1_BASE
, 0x100000,
347 AR5312_IRQ_ENET1
, -1,
348 AR5312_BOARD_CONFIG_ENET1
,
349 AR5312_RESET_ENET1
| AR5312_RESET_PHY1
,
354 AR5312_UART0_BASE
, 0x1000,
355 AR5312_IRQ_MISC
, AR5312_MISC_IRQ_UART0
,
356 AR5312_BOARD_CONFIG_UART0
,
362 AR5312_UART1_BASE
, 0x1000,
364 AR5312_BOARD_CONFIG_UART1
,
370 AR5312_WLAN0_BASE
, 0x100000,
371 AR5312_IRQ_WLAN0
, -1,
372 AR5312_BOARD_CONFIG_WLAN0
,
374 AR5312_RESET_WARM_WLAN0_MAC
|
375 AR5312_RESET_WARM_WLAN0_BB
,
380 AR5312_WLAN1_BASE
, 0x100000,
381 AR5312_IRQ_WLAN1
, -1,
382 AR5312_BOARD_CONFIG_WLAN1
,
384 AR5312_RESET_WARM_WLAN1_MAC
|
385 AR5312_RESET_WARM_WLAN1_BB
,
390 AR5312_FLASH_BASE
, 0,
399 AR5312_IRQ_MISC
, AR5312_MISC_IRQ_GPIO
,