1*cbab9cadSchs /* $NetBSD: ar5312.c,v 1.9 2012/10/27 17:18:01 chs Exp $ */
25cdb703dSgdamore
35cdb703dSgdamore /*
45cdb703dSgdamore * Copyright (c) 2006 Urbana-Champaign Independent Media Center.
55cdb703dSgdamore * Copyright (c) 2006 Garrett D'Amore.
65cdb703dSgdamore * All rights reserved.
75cdb703dSgdamore *
85cdb703dSgdamore * Portions of this code were written by Garrett D'Amore for the
95cdb703dSgdamore * Champaign-Urbana Community Wireless Network Project.
105cdb703dSgdamore *
115cdb703dSgdamore * Redistribution and use in source and binary forms, with or
125cdb703dSgdamore * without modification, are permitted provided that the following
135cdb703dSgdamore * conditions are met:
145cdb703dSgdamore * 1. Redistributions of source code must retain the above copyright
155cdb703dSgdamore * notice, this list of conditions and the following disclaimer.
165cdb703dSgdamore * 2. Redistributions in binary form must reproduce the above
175cdb703dSgdamore * copyright notice, this list of conditions and the following
185cdb703dSgdamore * disclaimer in the documentation and/or other materials provided
195cdb703dSgdamore * with the distribution.
205cdb703dSgdamore * 3. All advertising materials mentioning features or use of this
215cdb703dSgdamore * software must display the following acknowledgements:
225cdb703dSgdamore * This product includes software developed by the Urbana-Champaign
235cdb703dSgdamore * Independent Media Center.
245cdb703dSgdamore * This product includes software developed by Garrett D'Amore.
255cdb703dSgdamore * 4. Urbana-Champaign Independent Media Center's name and Garrett
265cdb703dSgdamore * D'Amore's name may not be used to endorse or promote products
275cdb703dSgdamore * derived from this software without specific prior written permission.
285cdb703dSgdamore *
295cdb703dSgdamore * THIS SOFTWARE IS PROVIDED BY THE URBANA-CHAMPAIGN INDEPENDENT
305cdb703dSgdamore * MEDIA CENTER AND GARRETT D'AMORE ``AS IS'' AND ANY EXPRESS OR
315cdb703dSgdamore * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
325cdb703dSgdamore * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
335cdb703dSgdamore * ARE DISCLAIMED. IN NO EVENT SHALL THE URBANA-CHAMPAIGN INDEPENDENT
345cdb703dSgdamore * MEDIA CENTER OR GARRETT D'AMORE BE LIABLE FOR ANY DIRECT, INDIRECT,
355cdb703dSgdamore * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
365cdb703dSgdamore * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
375cdb703dSgdamore * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
385cdb703dSgdamore * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
395cdb703dSgdamore * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
405cdb703dSgdamore * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
415cdb703dSgdamore * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
425cdb703dSgdamore */
435cdb703dSgdamore
445cdb703dSgdamore /*
455cdb703dSgdamore * This file includes a bunch of implementation specific bits for
465cdb703dSgdamore * AR5312, which differents these from other members of the AR5315
475cdb703dSgdamore * family.
485cdb703dSgdamore */
495cdb703dSgdamore #include "opt_ddb.h"
505cdb703dSgdamore #include "opt_kgdb.h"
5181d18a2fSmatt #define __INTR_PRIVATE
525cdb703dSgdamore
535cdb703dSgdamore #include "opt_memsize.h"
545cdb703dSgdamore #include <sys/param.h>
555cdb703dSgdamore #include <sys/systm.h>
565d17e613Smatt #include <sys/device.h>
575cdb703dSgdamore #include <sys/kernel.h>
585cdb703dSgdamore #include <sys/buf.h>
595cdb703dSgdamore
605cdb703dSgdamore #include <mips/cache.h>
615cdb703dSgdamore #include <mips/locore.h>
625cdb703dSgdamore #include <mips/cpuregs.h>
635cdb703dSgdamore
641f585717Sgdamore #include <sys/socket.h> /* these three just to get ETHER_ADDR_LEN(!) */
651f585717Sgdamore #include <net/if.h>
661f585717Sgdamore #include <net/if_ether.h>
671f585717Sgdamore
683a08c4a5Sdyoung #include <prop/proplib.h>
693a08c4a5Sdyoung
7081d18a2fSmatt #include <ah_soc.h>
7181d18a2fSmatt
7281d18a2fSmatt #include <mips/atheros/include/platform.h>
735cdb703dSgdamore #include <mips/atheros/include/arbusvar.h>
7481d18a2fSmatt #include <mips/atheros/include/ar5312reg.h>
755cdb703dSgdamore #include "com.h"
765cdb703dSgdamore
7781d18a2fSmatt static uint32_t
ar5312_get_memsize(void)7881d18a2fSmatt ar5312_get_memsize(void)
795cdb703dSgdamore {
805cdb703dSgdamore uint32_t memsize;
815cdb703dSgdamore uint32_t memcfg, bank0, bank1;
825cdb703dSgdamore
835cdb703dSgdamore /*
841f585717Sgdamore * Determine the memory size as established by system
851f585717Sgdamore * firmware.
865cdb703dSgdamore *
875cdb703dSgdamore * NB: we allow compile time override
885cdb703dSgdamore */
895cdb703dSgdamore #if defined(MEMSIZE)
905cdb703dSgdamore memsize = MEMSIZE;
915cdb703dSgdamore #else
925cdb703dSgdamore memcfg = GETSDRAMREG(AR5312_SDRAMCTL_MEM_CFG1);
9381d18a2fSmatt bank0 = __SHIFTOUT(memcfg, AR5312_MEM_CFG1_BANK0);
9481d18a2fSmatt bank1 = __SHIFTOUT(memcfg, AR5312_MEM_CFG1_BANK1);
955cdb703dSgdamore
965cdb703dSgdamore memsize = (bank0 ? (1 << (bank0 + 1)) : 0) +
975cdb703dSgdamore (bank1 ? (1 << (bank1 + 1)) : 0);
985cdb703dSgdamore memsize <<= 20;
995cdb703dSgdamore #endif
1005cdb703dSgdamore
1015cdb703dSgdamore return (memsize);
1025cdb703dSgdamore }
1035cdb703dSgdamore
10481d18a2fSmatt static void
ar5312_wdog_reload(uint32_t period)10581d18a2fSmatt ar5312_wdog_reload(uint32_t period)
1065cdb703dSgdamore {
1075cdb703dSgdamore
1085cdb703dSgdamore if (period == 0) {
1095cdb703dSgdamore PUTSYSREG(AR5312_SYSREG_WDOG_CTL, AR5312_WDOG_CTL_IGNORE);
1105cdb703dSgdamore PUTSYSREG(AR5312_SYSREG_WDOG_TIMER, 0);
1115cdb703dSgdamore } else {
1125cdb703dSgdamore PUTSYSREG(AR5312_SYSREG_WDOG_TIMER, period);
1135cdb703dSgdamore PUTSYSREG(AR5312_SYSREG_WDOG_CTL, AR5312_WDOG_CTL_RESET);
1145cdb703dSgdamore }
1155cdb703dSgdamore }
1165cdb703dSgdamore
11781d18a2fSmatt static void
ar5312_bus_init(void)11881d18a2fSmatt ar5312_bus_init(void)
1195cdb703dSgdamore {
1205cdb703dSgdamore /*
1215cdb703dSgdamore * Clear previous AHB errors
1225cdb703dSgdamore */
1235cdb703dSgdamore GETSYSREG(AR5312_SYSREG_AHBPERR);
1245cdb703dSgdamore GETSYSREG(AR5312_SYSREG_AHBDMAE);
1255cdb703dSgdamore }
1265cdb703dSgdamore
12781d18a2fSmatt static void
ar5312_reset(void)12881d18a2fSmatt ar5312_reset(void)
1295cdb703dSgdamore {
13081d18a2fSmatt PUTSYSREG(AR5312_SYSREG_RESETCTL, AR5312_RESET_SYSTEM);
13181d18a2fSmatt }
1325cdb703dSgdamore
13381d18a2fSmatt static void
ar5312_get_freqs(struct arfreqs * freqs)13481d18a2fSmatt ar5312_get_freqs(struct arfreqs *freqs)
13581d18a2fSmatt {
13681d18a2fSmatt const uint32_t wisoc = GETSYSREG(AR5312_SYSREG_REVISION);
13781d18a2fSmatt
13881d18a2fSmatt uint32_t predivisor;
1395cdb703dSgdamore uint32_t multiplier;
1405cdb703dSgdamore
1415cdb703dSgdamore /*
1425cdb703dSgdamore * This logic looks at the clock control register and
1435cdb703dSgdamore * determines the actual CPU frequency. These parts lack any
1445cdb703dSgdamore * kind of real-time clock on them, but the cpu clocks should
1455cdb703dSgdamore * be very accurate -- WiFi requires usec resolution timers.
1465cdb703dSgdamore */
1475cdb703dSgdamore
14881d18a2fSmatt const uint32_t clockctl = GETSYSREG(AR5312_SYSREG_CLOCKCTL);
1495cdb703dSgdamore
1505cdb703dSgdamore if (AR5312_REVISION_MAJOR(wisoc) == AR5312_REVISION_MAJ_AR2313) {
15181d18a2fSmatt predivisor = __SHIFTOUT(clockctl, AR2313_CLOCKCTL_PREDIVIDE);
15281d18a2fSmatt multiplier = __SHIFTOUT(clockctl, AR2313_CLOCKCTL_MULTIPLIER);
1535cdb703dSgdamore } else {
15481d18a2fSmatt predivisor = __SHIFTOUT(clockctl, AR5312_CLOCKCTL_PREDIVIDE);
15581d18a2fSmatt multiplier = __SHIFTOUT(clockctl, AR5312_CLOCKCTL_MULTIPLIER);
15681d18a2fSmatt if (clockctl & AR5312_CLOCKCTL_DOUBLER)
15781d18a2fSmatt multiplier <<= 1;
1585cdb703dSgdamore }
1595cdb703dSgdamore
1605cdb703dSgdamore /*
1615cdb703dSgdamore * Note that the source clock involved here is a 40MHz.
1625cdb703dSgdamore */
1635cdb703dSgdamore
16481d18a2fSmatt const uint32_t divisor = (0x5421 >> (predivisor * 4)) & 15;
1655cdb703dSgdamore
16681d18a2fSmatt const uint32_t cpufreq = (40000000 / divisor) * multiplier;
1675cdb703dSgdamore
16881d18a2fSmatt freqs->freq_cpu = cpufreq;
16981d18a2fSmatt freqs->freq_bus = cpufreq / 4;
17081d18a2fSmatt freqs->freq_mem = 0;
17181d18a2fSmatt freqs->freq_ref = 40000000;
17281d18a2fSmatt freqs->freq_pll = 40000000;
1735cdb703dSgdamore }
1745cdb703dSgdamore
1751f585717Sgdamore
1761f585717Sgdamore static void
addprop_data(device_t dev,const char * name,const uint8_t * data,int len)177*cbab9cadSchs addprop_data(device_t dev, const char *name, const uint8_t *data, int len)
1781f585717Sgdamore {
1791f585717Sgdamore prop_data_t pd;
1801f585717Sgdamore pd = prop_data_create_data(data, len);
1811f585717Sgdamore KASSERT(pd != NULL);
18209c5f9ccSthorpej if (prop_dictionary_set(device_properties(dev), name, pd) == false) {
1831f585717Sgdamore printf("WARNING: unable to set %s property for %s\n",
1841f585717Sgdamore name, device_xname(dev));
1851f585717Sgdamore }
1861f585717Sgdamore prop_object_release(pd);
1871f585717Sgdamore }
1881f585717Sgdamore
1891f585717Sgdamore static void
addprop_integer(device_t dev,const char * name,uint32_t val)190*cbab9cadSchs addprop_integer(device_t dev, const char *name, uint32_t val)
1911f585717Sgdamore {
1921f585717Sgdamore prop_number_t pn;
1931f585717Sgdamore pn = prop_number_create_integer(val);
1941f585717Sgdamore KASSERT(pn != NULL);
19509c5f9ccSthorpej if (prop_dictionary_set(device_properties(dev), name, pn) == false) {
1961f585717Sgdamore printf("WARNING: unable to set %s property for %s",
1971f585717Sgdamore name, device_xname(dev));
1981f585717Sgdamore }
1991f585717Sgdamore prop_object_release(pn);
2001f585717Sgdamore }
2011f585717Sgdamore
20281d18a2fSmatt static void
ar5312_device_register(device_t dev,void * aux)20381d18a2fSmatt ar5312_device_register(device_t dev, void *aux)
2041f585717Sgdamore {
20581d18a2fSmatt const struct arbus_attach_args * const aa = aux;
2061f585717Sgdamore
20781d18a2fSmatt if (device_is_a(dev, "com")) {
20881d18a2fSmatt addprop_integer(dev, "frequency", atheros_get_bus_freq());
20981d18a2fSmatt }
21081d18a2fSmatt
21181d18a2fSmatt const struct ar531x_boarddata * const info = atheros_get_board_info();
2121f585717Sgdamore if (info == NULL) {
2131f585717Sgdamore /* nothing known about this board! */
2141f585717Sgdamore return;
2151f585717Sgdamore }
2161f585717Sgdamore
2171f585717Sgdamore /*
2181f585717Sgdamore * We don't ever know the boot device. But that's because the
2191f585717Sgdamore * firmware only loads from the network.
2201f585717Sgdamore */
2211f585717Sgdamore
2221f585717Sgdamore /* Fetch the MAC addresses. */
2231f585717Sgdamore if (device_is_a(dev, "ae")) {
2241f585717Sgdamore const uint8_t *enet;
2251f585717Sgdamore
2261f585717Sgdamore if (aa->aa_addr == AR5312_ENET0_BASE)
2271f585717Sgdamore enet = info->enet0Mac;
2281f585717Sgdamore else if (aa->aa_addr == AR5312_ENET1_BASE)
2291f585717Sgdamore enet = info->enet1Mac;
2301f585717Sgdamore else
2311f585717Sgdamore return;
2321f585717Sgdamore
233f9e1815aSmartin addprop_data(dev, "mac-address", enet, ETHER_ADDR_LEN);
2341f585717Sgdamore }
2351f585717Sgdamore
2361f585717Sgdamore if (device_is_a(dev, "ath")) {
2371f585717Sgdamore const uint8_t *enet;
2381f585717Sgdamore
2391f585717Sgdamore if (aa->aa_addr == AR5312_WLAN0_BASE)
2401f585717Sgdamore enet = info->wlan0Mac;
2411f585717Sgdamore else if (aa->aa_addr == AR5312_WLAN1_BASE)
2421f585717Sgdamore enet = info->wlan1Mac;
2431f585717Sgdamore else
2441f585717Sgdamore return;
2451f585717Sgdamore
246f9e1815aSmartin addprop_data(dev, "mac-address", enet, ETHER_ADDR_LEN);
247e653071cSgdamore
248e653071cSgdamore addprop_integer(dev, "wmac-rev",
249e653071cSgdamore AR5312_REVISION_WMAC(GETSYSREG(AR5312_SYSREG_REVISION)));
250e653071cSgdamore
2511f585717Sgdamore }
2521f585717Sgdamore
2531f585717Sgdamore if (device_is_a(dev, "argpio")) {
2541f585717Sgdamore if (info->config & BD_RSTFACTORY) {
2551f585717Sgdamore addprop_integer(dev, "reset-pin",
2561f585717Sgdamore info->resetConfigGpio);
2571f585717Sgdamore }
2581f585717Sgdamore if (info->config & BD_SYSLED) {
2591f585717Sgdamore addprop_integer(dev, "sysled-pin",
2601f585717Sgdamore info->sysLedGpio);
2611f585717Sgdamore }
2621f585717Sgdamore }
2631f585717Sgdamore }
2641f585717Sgdamore
26581d18a2fSmatt static int
ar5312_enable_device(const struct atheros_device * adv)26681d18a2fSmatt ar5312_enable_device(const struct atheros_device *adv)
2671f585717Sgdamore {
26881d18a2fSmatt const struct ar531x_boarddata * const info = atheros_get_board_info();
2691f585717Sgdamore
27081d18a2fSmatt if (info != NULL
27181d18a2fSmatt && adv->adv_mask && ((adv->adv_mask & info->config) == 0)) {
2721f585717Sgdamore return -1;
2731f585717Sgdamore }
27481d18a2fSmatt if (adv->adv_reset) {
2751f585717Sgdamore /* put device into reset */
2761f585717Sgdamore PUTSYSREG(AR5312_SYSREG_RESETCTL,
27781d18a2fSmatt GETSYSREG(AR5312_SYSREG_RESETCTL) | adv->adv_reset);
2781f585717Sgdamore
2791f585717Sgdamore delay(15000); /* XXX: tsleep? */
2801f585717Sgdamore
2811f585717Sgdamore /* take it out of reset */
2821f585717Sgdamore PUTSYSREG(AR5312_SYSREG_RESETCTL,
28381d18a2fSmatt GETSYSREG(AR5312_SYSREG_RESETCTL) & ~adv->adv_reset);
2841f585717Sgdamore
2851f585717Sgdamore delay(25);
2861f585717Sgdamore }
28781d18a2fSmatt if (adv->adv_enable) {
2881f585717Sgdamore PUTSYSREG(AR5312_SYSREG_ENABLE,
28981d18a2fSmatt GETSYSREG(AR5312_SYSREG_ENABLE) | adv->adv_enable);
2901f585717Sgdamore }
2911f585717Sgdamore return 0;
2921f585717Sgdamore }
2931f585717Sgdamore
29481d18a2fSmatt static void
ar5312_intr_init(void)29581d18a2fSmatt ar5312_intr_init(void)
2961f585717Sgdamore {
29781d18a2fSmatt atheros_intr_init();
2981f585717Sgdamore }
2991f585717Sgdamore
30081d18a2fSmatt static const struct atheros_device ar5312_devices[] = {
30181d18a2fSmatt {
30281d18a2fSmatt .adv_name = "ae",
30381d18a2fSmatt .adv_addr = AR5312_ENET0_BASE,
30481d18a2fSmatt .adv_size = 0x100000,
30581d18a2fSmatt .adv_cirq = AR5312_IRQ_ENET0,
30681d18a2fSmatt .adv_mirq = -1,
30781d18a2fSmatt .adv_mask = AR5312_BOARD_CONFIG_ENET0,
30881d18a2fSmatt .adv_reset = AR5312_RESET_ENET0 | AR5312_RESET_PHY0,
30981d18a2fSmatt .adv_enable = AR5312_ENABLE_ENET0
31081d18a2fSmatt }, {
31181d18a2fSmatt .adv_name = "ae",
31281d18a2fSmatt .adv_addr = AR5312_ENET1_BASE,
31381d18a2fSmatt .adv_size = 0x100000,
31481d18a2fSmatt .adv_cirq = AR5312_IRQ_ENET1,
31581d18a2fSmatt .adv_mirq = -1,
31681d18a2fSmatt .adv_mask = AR5312_BOARD_CONFIG_ENET1,
31781d18a2fSmatt .adv_reset = AR5312_RESET_ENET1 | AR5312_RESET_PHY1,
31881d18a2fSmatt .adv_enable = AR5312_ENABLE_ENET1
31981d18a2fSmatt }, {
32081d18a2fSmatt .adv_name = "com",
32181d18a2fSmatt .adv_addr = AR5312_UART0_BASE,
32281d18a2fSmatt .adv_size = 0x1000,
32381d18a2fSmatt .adv_cirq = AR5312_IRQ_MISC,
32481d18a2fSmatt .adv_mirq = AR5312_MISC_IRQ_UART0,
32581d18a2fSmatt .adv_mask = AR5312_BOARD_CONFIG_UART0,
32681d18a2fSmatt }, {
32781d18a2fSmatt .adv_name = "com",
32881d18a2fSmatt .adv_addr = AR5312_UART1_BASE,
32981d18a2fSmatt .adv_size = 0x1000,
33081d18a2fSmatt .adv_cirq = -1,
33181d18a2fSmatt .adv_mirq = -1,
33281d18a2fSmatt .adv_mask = AR5312_BOARD_CONFIG_UART1,
33381d18a2fSmatt }, {
33481d18a2fSmatt .adv_name = "ath",
33581d18a2fSmatt .adv_addr = AR5312_WLAN0_BASE,
33681d18a2fSmatt .adv_size = 0x100000,
33781d18a2fSmatt .adv_cirq = AR5312_IRQ_WLAN0,
33881d18a2fSmatt .adv_mirq = -1,
33981d18a2fSmatt .adv_mask = AR5312_BOARD_CONFIG_WLAN0,
34081d18a2fSmatt .adv_reset = AR5312_RESET_WLAN0 | AR5312_RESET_WARM_WLAN0_MAC
34181d18a2fSmatt | AR5312_RESET_WARM_WLAN0_BB,
34281d18a2fSmatt .adv_enable = AR5312_ENABLE_WLAN0
34381d18a2fSmatt }, {
34481d18a2fSmatt .adv_name = "ath",
34581d18a2fSmatt .adv_addr = AR5312_WLAN1_BASE,
34681d18a2fSmatt .adv_size = 0x100000,
34781d18a2fSmatt .adv_cirq = AR5312_IRQ_WLAN1,
34881d18a2fSmatt .adv_mirq = -1,
34981d18a2fSmatt .adv_mask = AR5312_BOARD_CONFIG_WLAN1,
35081d18a2fSmatt .adv_reset = AR5312_RESET_WLAN1 | AR5312_RESET_WARM_WLAN1_MAC
35181d18a2fSmatt | AR5312_RESET_WARM_WLAN1_BB,
35281d18a2fSmatt .adv_enable = AR5312_ENABLE_WLAN1
35381d18a2fSmatt }, {
35481d18a2fSmatt .adv_name = "athflash",
35581d18a2fSmatt .adv_addr = AR5312_FLASH_BASE,
35681d18a2fSmatt .adv_size = 0,
35781d18a2fSmatt .adv_cirq = -1,
35881d18a2fSmatt .adv_mirq = -1,
35981d18a2fSmatt }, {
36081d18a2fSmatt .adv_name = "argpio",
36181d18a2fSmatt .adv_addr = AR5312_GPIO_BASE,
36281d18a2fSmatt .adv_size = 0x1000,
36381d18a2fSmatt .adv_cirq = AR5312_IRQ_MISC,
36481d18a2fSmatt .adv_mirq = AR5312_MISC_IRQ_GPIO,
36581d18a2fSmatt }, {
36681d18a2fSmatt .adv_name = NULL
36781d18a2fSmatt }
36881d18a2fSmatt };
36981d18a2fSmatt
37081d18a2fSmatt static const struct ipl_sr_map ar5312_ipl_sr_map = {
37181d18a2fSmatt .sr_bits = {
37281d18a2fSmatt [IPL_NONE] = 0,
37381d18a2fSmatt [IPL_SOFTCLOCK] = MIPS_SOFT_INT_MASK_0,
37481d18a2fSmatt [IPL_SOFTBIO] = MIPS_SOFT_INT_MASK_0,
37581d18a2fSmatt [IPL_SOFTNET] = MIPS_SOFT_INT_MASK,
37681d18a2fSmatt [IPL_SOFTSERIAL] = MIPS_SOFT_INT_MASK,
37781d18a2fSmatt [IPL_VM] = MIPS_SOFT_INT_MASK | MIPS_INT_MASK_0
37881d18a2fSmatt | MIPS_INT_MASK_1 | MIPS_INT_MASK_2
37981d18a2fSmatt | MIPS_INT_MASK_3,
38081d18a2fSmatt [IPL_SCHED] = MIPS_INT_MASK,
38181d18a2fSmatt [IPL_DDB] = MIPS_INT_MASK,
38281d18a2fSmatt [IPL_HIGH] = MIPS_INT_MASK,
38381d18a2fSmatt },
38481d18a2fSmatt };
38581d18a2fSmatt
38681d18a2fSmatt static const char * const ar5312_cpu_intrnames[] = {
38781d18a2fSmatt "int 0 (wlan0)",
38881d18a2fSmatt "int 1 (enet0)",
38981d18a2fSmatt "int 2 (enet1)",
39081d18a2fSmatt "int 3 (wlan1)",
39181d18a2fSmatt "int 4 (misc)",
39281d18a2fSmatt "int 5 (timer)",
39381d18a2fSmatt };
39481d18a2fSmatt
39581d18a2fSmatt static const char * const ar5312_misc_intrnames[] = {
39681d18a2fSmatt "misc 0 (timer)",
39781d18a2fSmatt "misc 1 (AHBproc error)",
39881d18a2fSmatt "misc 2 (AHBdma error)",
39981d18a2fSmatt "misc 3 (gpio)",
40081d18a2fSmatt "misc 4 (uart)",
40181d18a2fSmatt "misc 5 (uart dma)",
40281d18a2fSmatt "misc 6 (watchdog)"
40381d18a2fSmatt };
40481d18a2fSmatt
40581d18a2fSmatt
40681d18a2fSmatt const struct atheros_platformsw ar5312_platformsw = {
40781d18a2fSmatt .apsw_intrsw = &atheros_intrsw,
40881d18a2fSmatt .apsw_intr_init = ar5312_intr_init,
40981d18a2fSmatt .apsw_cpu_intrnames = ar5312_cpu_intrnames,
41081d18a2fSmatt .apsw_misc_intrnames = ar5312_misc_intrnames,
41181d18a2fSmatt .apsw_cpu_nintrs = __arraycount(ar5312_cpu_intrnames),
41281d18a2fSmatt .apsw_misc_nintrs = __arraycount(ar5312_misc_intrnames),
41381d18a2fSmatt .apsw_cpuirq_misc = AR5312_IRQ_MISC,
41481d18a2fSmatt .apsw_ipl_sr_map = &ar5312_ipl_sr_map,
41581d18a2fSmatt
41681d18a2fSmatt .apsw_revision_id_addr = AR5312_SYSREG_BASE + AR5312_SYSREG_REVISION,
41781d18a2fSmatt .apsw_uart0_base = AR5312_UART0_BASE,
41881d18a2fSmatt .apsw_misc_intstat = AR5312_SYSREG_BASE + AR5312_SYSREG_MISC_INTSTAT,
41981d18a2fSmatt .apsw_misc_intmask = AR5312_SYSREG_BASE + AR5312_SYSREG_MISC_INTMASK,
42081d18a2fSmatt
42181d18a2fSmatt /*
42281d18a2fSmatt * CPU specific routines.
42381d18a2fSmatt */
42481d18a2fSmatt .apsw_get_memsize = ar5312_get_memsize,
42581d18a2fSmatt .apsw_wdog_reload = ar5312_wdog_reload,
42681d18a2fSmatt .apsw_bus_init = ar5312_bus_init,
42781d18a2fSmatt .apsw_reset = ar5312_reset,
42881d18a2fSmatt
42981d18a2fSmatt .apsw_get_freqs = ar5312_get_freqs,
43081d18a2fSmatt .apsw_device_register = ar5312_device_register,
43181d18a2fSmatt .apsw_enable_device = ar5312_enable_device,
43281d18a2fSmatt .apsw_devices = ar5312_devices,
43381d18a2fSmatt };
434