1*97627a75Smatt /* $NetBSD: ar5312_board.c,v 1.5 2015/06/09 22:50:50 matt Exp $ */
2e653071cSgdamore /*
3e653071cSgdamore * Copyright (c) 2006 Urbana-Champaign Independent Media Center.
4e653071cSgdamore * Copyright (c) 2006 Garrett D'Amore.
5e653071cSgdamore * All rights reserved.
6e653071cSgdamore *
7e653071cSgdamore * This code was written by Garrett D'Amore for the Champaign-Urbana
8e653071cSgdamore * Community Wireless Network Project.
9e653071cSgdamore *
10e653071cSgdamore * Redistribution and use in source and binary forms, with or
11e653071cSgdamore * without modification, are permitted provided that the following
12e653071cSgdamore * conditions are met:
13e653071cSgdamore * 1. Redistributions of source code must retain the above copyright
14e653071cSgdamore * notice, this list of conditions and the following disclaimer.
15e653071cSgdamore * 2. Redistributions in binary form must reproduce the above
16e653071cSgdamore * copyright notice, this list of conditions and the following
17e653071cSgdamore * disclaimer in the documentation and/or other materials provided
18e653071cSgdamore * with the distribution.
19e653071cSgdamore * 3. All advertising materials mentioning features or use of this
20e653071cSgdamore * software must display the following acknowledgements:
21e653071cSgdamore * This product includes software developed by the Urbana-Champaign
22e653071cSgdamore * Independent Media Center.
23e653071cSgdamore * This product includes software developed by Garrett D'Amore.
24e653071cSgdamore * 4. Urbana-Champaign Independent Media Center's name and Garrett
25e653071cSgdamore * D'Amore's name may not be used to endorse or promote products
26e653071cSgdamore * derived from this software without specific prior written permission.
27e653071cSgdamore *
28e653071cSgdamore * THIS SOFTWARE IS PROVIDED BY THE URBANA-CHAMPAIGN INDEPENDENT
29e653071cSgdamore * MEDIA CENTER AND GARRETT D'AMORE ``AS IS'' AND ANY EXPRESS OR
30e653071cSgdamore * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
31e653071cSgdamore * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
32e653071cSgdamore * ARE DISCLAIMED. IN NO EVENT SHALL THE URBANA-CHAMPAIGN INDEPENDENT
33e653071cSgdamore * MEDIA CENTER OR GARRETT D'AMORE BE LIABLE FOR ANY DIRECT, INDIRECT,
34e653071cSgdamore * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
35e653071cSgdamore * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
36e653071cSgdamore * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
37e653071cSgdamore * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
38e653071cSgdamore * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
39e653071cSgdamore * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
40e653071cSgdamore * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
41e653071cSgdamore */
42e653071cSgdamore #include <sys/cdefs.h>
43*97627a75Smatt __KERNEL_RCSID(0, "$NetBSD: ar5312_board.c,v 1.5 2015/06/09 22:50:50 matt Exp $");
44e653071cSgdamore
45e653071cSgdamore #include <sys/param.h>
46e265f67bSdyoung #include <sys/bus.h>
47*97627a75Smatt #include <sys/device.h>
48*97627a75Smatt #include <sys/systm.h>
49*97627a75Smatt
50*97627a75Smatt #include <mips/cpuregs.h>
51*97627a75Smatt
52e653071cSgdamore #include <mips/atheros/include/ar5312reg.h>
5381d18a2fSmatt #include <mips/atheros/include/platform.h>
54e653071cSgdamore
556ce0e276Salc #include <ah_soc.h>
56e653071cSgdamore
57e653071cSgdamore extern const char *ether_sprintf(const uint8_t *);
58e653071cSgdamore
59e653071cSgdamore /*
60e653071cSgdamore * Locate the Board Configuration data using heuristics.
61e653071cSgdamore * Search backward from the (aliased) end of flash looking
62e653071cSgdamore * for the signature string that marks the start of the data.
63e653071cSgdamore * We search at most 500KB.
64e653071cSgdamore */
6581d18a2fSmatt static const struct ar531x_boarddata *
ar5312_get_board_info(void)6681d18a2fSmatt ar5312_get_board_info(void)
67e653071cSgdamore {
68e653071cSgdamore static const struct ar531x_boarddata *board = NULL;
69e653071cSgdamore const uint8_t *ptr, *end;
70e653071cSgdamore uint32_t fctl;
71e653071cSgdamore
72e653071cSgdamore if (board == NULL) {
73e653071cSgdamore /* configure flash bank 0 */
74e653071cSgdamore fctl = REGVAL(AR5312_FLASHCTL_BASE + AR5312_FLASHCTL_0) &
7581d18a2fSmatt AR5312_FLASHCTL_MW;
76e653071cSgdamore
77e653071cSgdamore fctl |=
78e653071cSgdamore AR5312_FLASHCTL_E |
79e653071cSgdamore AR5312_FLASHCTL_RBLE |
80e653071cSgdamore AR5312_FLASHCTL_AC_8M |
8181d18a2fSmatt __SHIFTIN(1, AR5312_FLASHCTL_IDCY) |
8281d18a2fSmatt __SHIFTIN(7, AR5312_FLASHCTL_WST1) |
8381d18a2fSmatt __SHIFTIN(7, AR5312_FLASHCTL_WST2);
84e653071cSgdamore
85e653071cSgdamore REGVAL(AR5312_FLASHCTL_BASE + AR5312_FLASHCTL_0) = fctl;
86e653071cSgdamore
87e653071cSgdamore REGVAL(AR5312_FLASHCTL_BASE + AR5312_FLASHCTL_1) &=
8881d18a2fSmatt ~(AR5312_FLASHCTL_E | AR5312_FLASHCTL_AC);
89e653071cSgdamore
90e653071cSgdamore REGVAL(AR5312_FLASHCTL_BASE + AR5312_FLASHCTL_2) &=
9181d18a2fSmatt ~(AR5312_FLASHCTL_E | AR5312_FLASHCTL_AC);
92e653071cSgdamore
93e653071cSgdamore /* search backward in the flash looking for the signature */
94e653071cSgdamore ptr = (const uint8_t *) MIPS_PHYS_TO_KSEG1(AR5312_FLASH_END - 0x1000);
95e653071cSgdamore end = ptr - (500 * 1024); /* NB: max 500KB window */
96e653071cSgdamore /* XXX validate end */
97e653071cSgdamore for (; ptr > end; ptr -= 0x1000)
98e653071cSgdamore if (*(const uint32_t *)ptr == AR531X_BD_MAGIC) {
99e653071cSgdamore board = (const struct ar531x_boarddata *) ptr;
100e653071cSgdamore break;
101e653071cSgdamore }
102e653071cSgdamore }
103e653071cSgdamore return board;
104e653071cSgdamore }
105e653071cSgdamore
106e653071cSgdamore /*
107e653071cSgdamore * Locate the radio configuration data; it is located relative
108e653071cSgdamore * to the board configuration data.
109e653071cSgdamore */
11081d18a2fSmatt static const void *
ar5312_get_radio_info(void)11181d18a2fSmatt ar5312_get_radio_info(void)
112e653071cSgdamore {
113e653071cSgdamore static const void *radio = NULL;
114e653071cSgdamore const struct ar531x_boarddata *board;
115e653071cSgdamore const uint8_t *baddr, *ptr, *end;
116e653071cSgdamore
117e653071cSgdamore if (radio == NULL) {
11881d18a2fSmatt board = ar5312_get_board_info();
119e653071cSgdamore if (board == NULL)
120e653071cSgdamore return NULL;
121e653071cSgdamore baddr = (const uint8_t *) board;
122e653071cSgdamore ptr = baddr + 0x1000;
123e653071cSgdamore end = (const uint8_t *)
124e653071cSgdamore MIPS_PHYS_TO_KSEG1(AR5312_FLASH_END-0x1000);
125e653071cSgdamore again:
126e653071cSgdamore for (; ptr < end; ptr += 0x1000)
127e653071cSgdamore if (*(const uint32_t *)ptr != 0xffffffff) {
128e653071cSgdamore radio = ptr;
129e653071cSgdamore goto done;
130e653071cSgdamore }
131e653071cSgdamore /* sort of an Algol-style for loop ... */
132e653071cSgdamore if (end == (uint8_t *) MIPS_PHYS_TO_KSEG1(AR5312_FLASH_END)) {
133e653071cSgdamore /* NB: AR2316 has radio data in a different location */
134e653071cSgdamore ptr = baddr + 0xf8;
135e653071cSgdamore end = (const uint8_t *)
136e653071cSgdamore MIPS_PHYS_TO_KSEG1(AR5312_FLASH_END-0x1000 + 0xf8);
137e653071cSgdamore goto again;
138e653071cSgdamore }
139e653071cSgdamore }
140e653071cSgdamore done:
141e653071cSgdamore return radio;
142e653071cSgdamore }
143e653071cSgdamore
14481d18a2fSmatt const struct atheros_boardsw ar5312_boardsw = {
14581d18a2fSmatt .absw_get_board_info = ar5312_get_board_info,
14681d18a2fSmatt .absw_get_radio_info = ar5312_get_radio_info,
14781d18a2fSmatt };
148