1 1.9 chs /* $NetBSD: ar5312.c,v 1.9 2012/10/27 17:18:01 chs Exp $ */ 2 1.1 gdamore 3 1.1 gdamore /* 4 1.1 gdamore * Copyright (c) 2006 Urbana-Champaign Independent Media Center. 5 1.1 gdamore * Copyright (c) 2006 Garrett D'Amore. 6 1.1 gdamore * All rights reserved. 7 1.1 gdamore * 8 1.1 gdamore * Portions of this code were written by Garrett D'Amore for the 9 1.1 gdamore * Champaign-Urbana Community Wireless Network Project. 10 1.1 gdamore * 11 1.1 gdamore * Redistribution and use in source and binary forms, with or 12 1.1 gdamore * without modification, are permitted provided that the following 13 1.1 gdamore * conditions are met: 14 1.1 gdamore * 1. Redistributions of source code must retain the above copyright 15 1.1 gdamore * notice, this list of conditions and the following disclaimer. 16 1.1 gdamore * 2. Redistributions in binary form must reproduce the above 17 1.1 gdamore * copyright notice, this list of conditions and the following 18 1.1 gdamore * disclaimer in the documentation and/or other materials provided 19 1.1 gdamore * with the distribution. 20 1.1 gdamore * 3. All advertising materials mentioning features or use of this 21 1.1 gdamore * software must display the following acknowledgements: 22 1.1 gdamore * This product includes software developed by the Urbana-Champaign 23 1.1 gdamore * Independent Media Center. 24 1.1 gdamore * This product includes software developed by Garrett D'Amore. 25 1.1 gdamore * 4. Urbana-Champaign Independent Media Center's name and Garrett 26 1.1 gdamore * D'Amore's name may not be used to endorse or promote products 27 1.1 gdamore * derived from this software without specific prior written permission. 28 1.1 gdamore * 29 1.1 gdamore * THIS SOFTWARE IS PROVIDED BY THE URBANA-CHAMPAIGN INDEPENDENT 30 1.1 gdamore * MEDIA CENTER AND GARRETT D'AMORE ``AS IS'' AND ANY EXPRESS OR 31 1.1 gdamore * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 32 1.1 gdamore * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 33 1.1 gdamore * ARE DISCLAIMED. IN NO EVENT SHALL THE URBANA-CHAMPAIGN INDEPENDENT 34 1.1 gdamore * MEDIA CENTER OR GARRETT D'AMORE BE LIABLE FOR ANY DIRECT, INDIRECT, 35 1.1 gdamore * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 36 1.1 gdamore * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 37 1.1 gdamore * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 38 1.1 gdamore * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 39 1.1 gdamore * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 40 1.1 gdamore * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 41 1.1 gdamore * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 42 1.1 gdamore */ 43 1.1 gdamore 44 1.1 gdamore /* 45 1.1 gdamore * This file includes a bunch of implementation specific bits for 46 1.1 gdamore * AR5312, which differents these from other members of the AR5315 47 1.1 gdamore * family. 48 1.1 gdamore */ 49 1.1 gdamore #include "opt_ddb.h" 50 1.1 gdamore #include "opt_kgdb.h" 51 1.8 matt #define __INTR_PRIVATE 52 1.1 gdamore 53 1.1 gdamore #include "opt_memsize.h" 54 1.1 gdamore #include <sys/param.h> 55 1.1 gdamore #include <sys/systm.h> 56 1.7 matt #include <sys/device.h> 57 1.1 gdamore #include <sys/kernel.h> 58 1.1 gdamore #include <sys/buf.h> 59 1.1 gdamore 60 1.1 gdamore #include <mips/cache.h> 61 1.1 gdamore #include <mips/locore.h> 62 1.1 gdamore #include <mips/cpuregs.h> 63 1.1 gdamore 64 1.2 gdamore #include <sys/socket.h> /* these three just to get ETHER_ADDR_LEN(!) */ 65 1.2 gdamore #include <net/if.h> 66 1.2 gdamore #include <net/if_ether.h> 67 1.2 gdamore 68 1.5 dyoung #include <prop/proplib.h> 69 1.5 dyoung 70 1.8 matt #include <ah_soc.h> 71 1.8 matt 72 1.8 matt #include <mips/atheros/include/platform.h> 73 1.8 matt #include <mips/atheros/include/arbusvar.h> 74 1.1 gdamore #include <mips/atheros/include/ar5312reg.h> 75 1.1 gdamore #include "com.h" 76 1.1 gdamore 77 1.8 matt static uint32_t 78 1.8 matt ar5312_get_memsize(void) 79 1.1 gdamore { 80 1.1 gdamore uint32_t memsize; 81 1.1 gdamore uint32_t memcfg, bank0, bank1; 82 1.1 gdamore 83 1.1 gdamore /* 84 1.2 gdamore * Determine the memory size as established by system 85 1.2 gdamore * firmware. 86 1.1 gdamore * 87 1.1 gdamore * NB: we allow compile time override 88 1.1 gdamore */ 89 1.1 gdamore #if defined(MEMSIZE) 90 1.1 gdamore memsize = MEMSIZE; 91 1.1 gdamore #else 92 1.1 gdamore memcfg = GETSDRAMREG(AR5312_SDRAMCTL_MEM_CFG1); 93 1.8 matt bank0 = __SHIFTOUT(memcfg, AR5312_MEM_CFG1_BANK0); 94 1.8 matt bank1 = __SHIFTOUT(memcfg, AR5312_MEM_CFG1_BANK1); 95 1.1 gdamore 96 1.1 gdamore memsize = (bank0 ? (1 << (bank0 + 1)) : 0) + 97 1.1 gdamore (bank1 ? (1 << (bank1 + 1)) : 0); 98 1.1 gdamore memsize <<= 20; 99 1.1 gdamore #endif 100 1.1 gdamore 101 1.1 gdamore return (memsize); 102 1.1 gdamore } 103 1.1 gdamore 104 1.8 matt static void 105 1.8 matt ar5312_wdog_reload(uint32_t period) 106 1.1 gdamore { 107 1.1 gdamore 108 1.1 gdamore if (period == 0) { 109 1.1 gdamore PUTSYSREG(AR5312_SYSREG_WDOG_CTL, AR5312_WDOG_CTL_IGNORE); 110 1.1 gdamore PUTSYSREG(AR5312_SYSREG_WDOG_TIMER, 0); 111 1.1 gdamore } else { 112 1.1 gdamore PUTSYSREG(AR5312_SYSREG_WDOG_TIMER, period); 113 1.1 gdamore PUTSYSREG(AR5312_SYSREG_WDOG_CTL, AR5312_WDOG_CTL_RESET); 114 1.1 gdamore } 115 1.1 gdamore } 116 1.1 gdamore 117 1.8 matt static void 118 1.8 matt ar5312_bus_init(void) 119 1.1 gdamore { 120 1.1 gdamore /* 121 1.1 gdamore * Clear previous AHB errors 122 1.1 gdamore */ 123 1.1 gdamore GETSYSREG(AR5312_SYSREG_AHBPERR); 124 1.1 gdamore GETSYSREG(AR5312_SYSREG_AHBDMAE); 125 1.1 gdamore } 126 1.1 gdamore 127 1.8 matt static void 128 1.8 matt ar5312_reset(void) 129 1.8 matt { 130 1.8 matt PUTSYSREG(AR5312_SYSREG_RESETCTL, AR5312_RESET_SYSTEM); 131 1.8 matt } 132 1.8 matt 133 1.8 matt static void 134 1.8 matt ar5312_get_freqs(struct arfreqs *freqs) 135 1.1 gdamore { 136 1.8 matt const uint32_t wisoc = GETSYSREG(AR5312_SYSREG_REVISION); 137 1.1 gdamore 138 1.8 matt uint32_t predivisor; 139 1.1 gdamore uint32_t multiplier; 140 1.1 gdamore 141 1.1 gdamore /* 142 1.1 gdamore * This logic looks at the clock control register and 143 1.1 gdamore * determines the actual CPU frequency. These parts lack any 144 1.1 gdamore * kind of real-time clock on them, but the cpu clocks should 145 1.1 gdamore * be very accurate -- WiFi requires usec resolution timers. 146 1.1 gdamore */ 147 1.1 gdamore 148 1.8 matt const uint32_t clockctl = GETSYSREG(AR5312_SYSREG_CLOCKCTL); 149 1.1 gdamore 150 1.1 gdamore if (AR5312_REVISION_MAJOR(wisoc) == AR5312_REVISION_MAJ_AR2313) { 151 1.8 matt predivisor = __SHIFTOUT(clockctl, AR2313_CLOCKCTL_PREDIVIDE); 152 1.8 matt multiplier = __SHIFTOUT(clockctl, AR2313_CLOCKCTL_MULTIPLIER); 153 1.1 gdamore } else { 154 1.8 matt predivisor = __SHIFTOUT(clockctl, AR5312_CLOCKCTL_PREDIVIDE); 155 1.8 matt multiplier = __SHIFTOUT(clockctl, AR5312_CLOCKCTL_MULTIPLIER); 156 1.8 matt if (clockctl & AR5312_CLOCKCTL_DOUBLER) 157 1.8 matt multiplier <<= 1; 158 1.1 gdamore } 159 1.1 gdamore 160 1.1 gdamore /* 161 1.1 gdamore * Note that the source clock involved here is a 40MHz. 162 1.1 gdamore */ 163 1.1 gdamore 164 1.8 matt const uint32_t divisor = (0x5421 >> (predivisor * 4)) & 15; 165 1.1 gdamore 166 1.8 matt const uint32_t cpufreq = (40000000 / divisor) * multiplier; 167 1.1 gdamore 168 1.8 matt freqs->freq_cpu = cpufreq; 169 1.8 matt freqs->freq_bus = cpufreq / 4; 170 1.8 matt freqs->freq_mem = 0; 171 1.8 matt freqs->freq_ref = 40000000; 172 1.8 matt freqs->freq_pll = 40000000; 173 1.1 gdamore } 174 1.1 gdamore 175 1.2 gdamore 176 1.2 gdamore static void 177 1.9 chs addprop_data(device_t dev, const char *name, const uint8_t *data, int len) 178 1.2 gdamore { 179 1.2 gdamore prop_data_t pd; 180 1.2 gdamore pd = prop_data_create_data(data, len); 181 1.2 gdamore KASSERT(pd != NULL); 182 1.4 thorpej if (prop_dictionary_set(device_properties(dev), name, pd) == false) { 183 1.2 gdamore printf("WARNING: unable to set %s property for %s\n", 184 1.2 gdamore name, device_xname(dev)); 185 1.2 gdamore } 186 1.2 gdamore prop_object_release(pd); 187 1.2 gdamore } 188 1.2 gdamore 189 1.2 gdamore static void 190 1.9 chs addprop_integer(device_t dev, const char *name, uint32_t val) 191 1.2 gdamore { 192 1.2 gdamore prop_number_t pn; 193 1.2 gdamore pn = prop_number_create_integer(val); 194 1.2 gdamore KASSERT(pn != NULL); 195 1.4 thorpej if (prop_dictionary_set(device_properties(dev), name, pn) == false) { 196 1.2 gdamore printf("WARNING: unable to set %s property for %s", 197 1.2 gdamore name, device_xname(dev)); 198 1.2 gdamore } 199 1.2 gdamore prop_object_release(pn); 200 1.2 gdamore } 201 1.2 gdamore 202 1.8 matt static void 203 1.8 matt ar5312_device_register(device_t dev, void *aux) 204 1.2 gdamore { 205 1.8 matt const struct arbus_attach_args * const aa = aux; 206 1.8 matt 207 1.8 matt if (device_is_a(dev, "com")) { 208 1.8 matt addprop_integer(dev, "frequency", atheros_get_bus_freq()); 209 1.8 matt } 210 1.2 gdamore 211 1.8 matt const struct ar531x_boarddata * const info = atheros_get_board_info(); 212 1.2 gdamore if (info == NULL) { 213 1.2 gdamore /* nothing known about this board! */ 214 1.2 gdamore return; 215 1.2 gdamore } 216 1.2 gdamore 217 1.2 gdamore /* 218 1.2 gdamore * We don't ever know the boot device. But that's because the 219 1.2 gdamore * firmware only loads from the network. 220 1.2 gdamore */ 221 1.2 gdamore 222 1.2 gdamore /* Fetch the MAC addresses. */ 223 1.2 gdamore if (device_is_a(dev, "ae")) { 224 1.2 gdamore const uint8_t *enet; 225 1.2 gdamore 226 1.2 gdamore if (aa->aa_addr == AR5312_ENET0_BASE) 227 1.2 gdamore enet = info->enet0Mac; 228 1.2 gdamore else if (aa->aa_addr == AR5312_ENET1_BASE) 229 1.2 gdamore enet = info->enet1Mac; 230 1.2 gdamore else 231 1.2 gdamore return; 232 1.2 gdamore 233 1.6 martin addprop_data(dev, "mac-address", enet, ETHER_ADDR_LEN); 234 1.2 gdamore } 235 1.2 gdamore 236 1.2 gdamore if (device_is_a(dev, "ath")) { 237 1.2 gdamore const uint8_t *enet; 238 1.2 gdamore 239 1.2 gdamore if (aa->aa_addr == AR5312_WLAN0_BASE) 240 1.2 gdamore enet = info->wlan0Mac; 241 1.2 gdamore else if (aa->aa_addr == AR5312_WLAN1_BASE) 242 1.2 gdamore enet = info->wlan1Mac; 243 1.2 gdamore else 244 1.2 gdamore return; 245 1.2 gdamore 246 1.6 martin addprop_data(dev, "mac-address", enet, ETHER_ADDR_LEN); 247 1.3 gdamore 248 1.3 gdamore addprop_integer(dev, "wmac-rev", 249 1.3 gdamore AR5312_REVISION_WMAC(GETSYSREG(AR5312_SYSREG_REVISION))); 250 1.3 gdamore 251 1.2 gdamore } 252 1.2 gdamore 253 1.2 gdamore if (device_is_a(dev, "argpio")) { 254 1.2 gdamore if (info->config & BD_RSTFACTORY) { 255 1.2 gdamore addprop_integer(dev, "reset-pin", 256 1.2 gdamore info->resetConfigGpio); 257 1.2 gdamore } 258 1.2 gdamore if (info->config & BD_SYSLED) { 259 1.2 gdamore addprop_integer(dev, "sysled-pin", 260 1.2 gdamore info->sysLedGpio); 261 1.2 gdamore } 262 1.2 gdamore } 263 1.2 gdamore } 264 1.2 gdamore 265 1.8 matt static int 266 1.8 matt ar5312_enable_device(const struct atheros_device *adv) 267 1.2 gdamore { 268 1.8 matt const struct ar531x_boarddata * const info = atheros_get_board_info(); 269 1.2 gdamore 270 1.8 matt if (info != NULL 271 1.8 matt && adv->adv_mask && ((adv->adv_mask & info->config) == 0)) { 272 1.2 gdamore return -1; 273 1.2 gdamore } 274 1.8 matt if (adv->adv_reset) { 275 1.2 gdamore /* put device into reset */ 276 1.2 gdamore PUTSYSREG(AR5312_SYSREG_RESETCTL, 277 1.8 matt GETSYSREG(AR5312_SYSREG_RESETCTL) | adv->adv_reset); 278 1.2 gdamore 279 1.2 gdamore delay(15000); /* XXX: tsleep? */ 280 1.2 gdamore 281 1.2 gdamore /* take it out of reset */ 282 1.2 gdamore PUTSYSREG(AR5312_SYSREG_RESETCTL, 283 1.8 matt GETSYSREG(AR5312_SYSREG_RESETCTL) & ~adv->adv_reset); 284 1.2 gdamore 285 1.2 gdamore delay(25); 286 1.2 gdamore } 287 1.8 matt if (adv->adv_enable) { 288 1.2 gdamore PUTSYSREG(AR5312_SYSREG_ENABLE, 289 1.8 matt GETSYSREG(AR5312_SYSREG_ENABLE) | adv->adv_enable); 290 1.2 gdamore } 291 1.2 gdamore return 0; 292 1.2 gdamore } 293 1.2 gdamore 294 1.8 matt static void 295 1.8 matt ar5312_intr_init(void) 296 1.2 gdamore { 297 1.8 matt atheros_intr_init(); 298 1.8 matt } 299 1.2 gdamore 300 1.8 matt static const struct atheros_device ar5312_devices[] = { 301 1.8 matt { 302 1.8 matt .adv_name = "ae", 303 1.8 matt .adv_addr = AR5312_ENET0_BASE, 304 1.8 matt .adv_size = 0x100000, 305 1.8 matt .adv_cirq = AR5312_IRQ_ENET0, 306 1.8 matt .adv_mirq = -1, 307 1.8 matt .adv_mask = AR5312_BOARD_CONFIG_ENET0, 308 1.8 matt .adv_reset = AR5312_RESET_ENET0 | AR5312_RESET_PHY0, 309 1.8 matt .adv_enable = AR5312_ENABLE_ENET0 310 1.8 matt }, { 311 1.8 matt .adv_name = "ae", 312 1.8 matt .adv_addr = AR5312_ENET1_BASE, 313 1.8 matt .adv_size = 0x100000, 314 1.8 matt .adv_cirq = AR5312_IRQ_ENET1, 315 1.8 matt .adv_mirq = -1, 316 1.8 matt .adv_mask = AR5312_BOARD_CONFIG_ENET1, 317 1.8 matt .adv_reset = AR5312_RESET_ENET1 | AR5312_RESET_PHY1, 318 1.8 matt .adv_enable = AR5312_ENABLE_ENET1 319 1.8 matt }, { 320 1.8 matt .adv_name = "com", 321 1.8 matt .adv_addr = AR5312_UART0_BASE, 322 1.8 matt .adv_size = 0x1000, 323 1.8 matt .adv_cirq = AR5312_IRQ_MISC, 324 1.8 matt .adv_mirq = AR5312_MISC_IRQ_UART0, 325 1.8 matt .adv_mask = AR5312_BOARD_CONFIG_UART0, 326 1.8 matt }, { 327 1.8 matt .adv_name = "com", 328 1.8 matt .adv_addr = AR5312_UART1_BASE, 329 1.8 matt .adv_size = 0x1000, 330 1.8 matt .adv_cirq = -1, 331 1.8 matt .adv_mirq = -1, 332 1.8 matt .adv_mask = AR5312_BOARD_CONFIG_UART1, 333 1.8 matt }, { 334 1.8 matt .adv_name = "ath", 335 1.8 matt .adv_addr = AR5312_WLAN0_BASE, 336 1.8 matt .adv_size = 0x100000, 337 1.8 matt .adv_cirq = AR5312_IRQ_WLAN0, 338 1.8 matt .adv_mirq = -1, 339 1.8 matt .adv_mask = AR5312_BOARD_CONFIG_WLAN0, 340 1.8 matt .adv_reset = AR5312_RESET_WLAN0 | AR5312_RESET_WARM_WLAN0_MAC 341 1.8 matt | AR5312_RESET_WARM_WLAN0_BB, 342 1.8 matt .adv_enable = AR5312_ENABLE_WLAN0 343 1.8 matt }, { 344 1.8 matt .adv_name = "ath", 345 1.8 matt .adv_addr = AR5312_WLAN1_BASE, 346 1.8 matt .adv_size = 0x100000, 347 1.8 matt .adv_cirq = AR5312_IRQ_WLAN1, 348 1.8 matt .adv_mirq = -1, 349 1.8 matt .adv_mask = AR5312_BOARD_CONFIG_WLAN1, 350 1.8 matt .adv_reset = AR5312_RESET_WLAN1 | AR5312_RESET_WARM_WLAN1_MAC 351 1.8 matt | AR5312_RESET_WARM_WLAN1_BB, 352 1.8 matt .adv_enable = AR5312_ENABLE_WLAN1 353 1.8 matt }, { 354 1.8 matt .adv_name = "athflash", 355 1.8 matt .adv_addr = AR5312_FLASH_BASE, 356 1.8 matt .adv_size = 0, 357 1.8 matt .adv_cirq = -1, 358 1.8 matt .adv_mirq = -1, 359 1.8 matt }, { 360 1.8 matt .adv_name = "argpio", 361 1.8 matt .adv_addr = AR5312_GPIO_BASE, 362 1.8 matt .adv_size = 0x1000, 363 1.8 matt .adv_cirq = AR5312_IRQ_MISC, 364 1.8 matt .adv_mirq = AR5312_MISC_IRQ_GPIO, 365 1.8 matt }, { 366 1.8 matt .adv_name = NULL 367 1.8 matt } 368 1.8 matt }; 369 1.8 matt 370 1.8 matt static const struct ipl_sr_map ar5312_ipl_sr_map = { 371 1.8 matt .sr_bits = { 372 1.8 matt [IPL_NONE] = 0, 373 1.8 matt [IPL_SOFTCLOCK] = MIPS_SOFT_INT_MASK_0, 374 1.8 matt [IPL_SOFTBIO] = MIPS_SOFT_INT_MASK_0, 375 1.8 matt [IPL_SOFTNET] = MIPS_SOFT_INT_MASK, 376 1.8 matt [IPL_SOFTSERIAL] = MIPS_SOFT_INT_MASK, 377 1.8 matt [IPL_VM] = MIPS_SOFT_INT_MASK | MIPS_INT_MASK_0 378 1.8 matt | MIPS_INT_MASK_1 | MIPS_INT_MASK_2 379 1.8 matt | MIPS_INT_MASK_3, 380 1.8 matt [IPL_SCHED] = MIPS_INT_MASK, 381 1.8 matt [IPL_DDB] = MIPS_INT_MASK, 382 1.8 matt [IPL_HIGH] = MIPS_INT_MASK, 383 1.8 matt }, 384 1.8 matt }; 385 1.8 matt 386 1.8 matt static const char * const ar5312_cpu_intrnames[] = { 387 1.8 matt "int 0 (wlan0)", 388 1.8 matt "int 1 (enet0)", 389 1.8 matt "int 2 (enet1)", 390 1.8 matt "int 3 (wlan1)", 391 1.8 matt "int 4 (misc)", 392 1.8 matt "int 5 (timer)", 393 1.8 matt }; 394 1.8 matt 395 1.8 matt static const char * const ar5312_misc_intrnames[] = { 396 1.8 matt "misc 0 (timer)", 397 1.8 matt "misc 1 (AHBproc error)", 398 1.8 matt "misc 2 (AHBdma error)", 399 1.8 matt "misc 3 (gpio)", 400 1.8 matt "misc 4 (uart)", 401 1.8 matt "misc 5 (uart dma)", 402 1.8 matt "misc 6 (watchdog)" 403 1.8 matt }; 404 1.8 matt 405 1.8 matt 406 1.8 matt const struct atheros_platformsw ar5312_platformsw = { 407 1.8 matt .apsw_intrsw = &atheros_intrsw, 408 1.8 matt .apsw_intr_init = ar5312_intr_init, 409 1.8 matt .apsw_cpu_intrnames = ar5312_cpu_intrnames, 410 1.8 matt .apsw_misc_intrnames = ar5312_misc_intrnames, 411 1.8 matt .apsw_cpu_nintrs = __arraycount(ar5312_cpu_intrnames), 412 1.8 matt .apsw_misc_nintrs = __arraycount(ar5312_misc_intrnames), 413 1.8 matt .apsw_cpuirq_misc = AR5312_IRQ_MISC, 414 1.8 matt .apsw_ipl_sr_map = &ar5312_ipl_sr_map, 415 1.8 matt 416 1.8 matt .apsw_revision_id_addr = AR5312_SYSREG_BASE + AR5312_SYSREG_REVISION, 417 1.8 matt .apsw_uart0_base = AR5312_UART0_BASE, 418 1.8 matt .apsw_misc_intstat = AR5312_SYSREG_BASE + AR5312_SYSREG_MISC_INTSTAT, 419 1.8 matt .apsw_misc_intmask = AR5312_SYSREG_BASE + AR5312_SYSREG_MISC_INTMASK, 420 1.2 gdamore 421 1.8 matt /* 422 1.8 matt * CPU specific routines. 423 1.8 matt */ 424 1.8 matt .apsw_get_memsize = ar5312_get_memsize, 425 1.8 matt .apsw_wdog_reload = ar5312_wdog_reload, 426 1.8 matt .apsw_bus_init = ar5312_bus_init, 427 1.8 matt .apsw_reset = ar5312_reset, 428 1.8 matt 429 1.8 matt .apsw_get_freqs = ar5312_get_freqs, 430 1.8 matt .apsw_device_register = ar5312_device_register, 431 1.8 matt .apsw_enable_device = ar5312_enable_device, 432 1.8 matt .apsw_devices = ar5312_devices, 433 1.8 matt }; 434