1/* $NetBSD: ar_conf.c,v 1.1 2011/07/07 05:06:44 matt Exp $ */ 2/*- 3 * Copyright (c) 2011 The NetBSD Foundation, Inc. 4 * All rights reserved. 5 * 6 * This code is derived from software contributed to The NetBSD Foundation 7 * by Matt Thomas of 3am Software Foundry. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 19 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 20 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 21 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 22 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31#include <sys/cdefs.h> 32 33__KERNEL_RCSID(0, "$NetBSD: ar_conf.c,v 1.1 2011/07/07 05:06:44 matt Exp $"); 34 35#include <sys/param.h> 36 37#include "opt_wisoc.h" 38 39#include <mips/cpuregs.h> 40#include <mips/locore.h> 41 42#include <mips/atheros/include/platform.h> 43#include <mips/atheros/include/ar9344reg.h> 44 45struct atheros_chip { 46 const struct atheros_platformsw *ac_platformsw; 47 const struct atheros_boardsw *ac_boardsw; 48 uint8_t ac_chipid; 49 uint8_t ac_chipmask; 50 uint8_t ac_cid; 51 uint8_t ac_pid; 52 const char ac_name[8]; 53}; 54 55static const struct atheros_chip chips[] = { 56#ifdef WISOC_AR5312 57 { 58 .ac_platformsw = &ar5312_platformsw, 59 .ac_boardsw = &ar5312_boardsw, 60 .ac_chipid = ARCHIP_AR5312, 61 .ac_chipmask = 0xff, 62 .ac_cid = MIPS_PRID_CID_MTI, 63 .ac_pid = MIPS_4Kc, 64 .ac_name = "AR5312" 65 }, 66#endif 67#ifdef WISOC_AR5315 68 { 69 .ac_platformsw = &ar5315_platformsw, 70 .ac_boardsw = &ar5315_boardsw, 71 .ac_chipid = ARCHIP_AR5315, 72 .ac_chipmask = 0xf0, 73 .ac_cid = MIPS_PRID_CID_MTI, 74 .ac_pid = MIPS_4Kc, 75 .ac_name = "AR5315" 76 }, 77#endif 78#ifdef WISOC_AR7100 79 { 80 .ac_platformsw = &ar7100_platformsw, 81 .ac_chipid = ARCHIP_AR7130, 82 .ac_chipmask = 0xf3, 83 .ac_cid = MIPS_PRID_CID_MTI, 84 .ac_pid = MIPS_24K, 85 .ac_name = "AR7130" 86 }, { 87 .ac_platformsw = &ar7100_platformsw, 88 .ac_chipid = ARCHIP_AR7141, 89 .ac_chipmask = 0xf3, 90 .ac_cid = MIPS_PRID_CID_MTI, 91 .ac_pid = MIPS_24K, 92 .ac_name = "AR7141" 93 }, { 94 .ac_platformsw = &ar7100_platformsw, 95 .ac_chipid = ARCHIP_AR7161, 96 .ac_chipmask = 0xf3, 97 .ac_cid = MIPS_PRID_CID_MTI, 98 .ac_pid = MIPS_24K, 99 .ac_name = "AR7161" 100 }, 101#endif 102#ifdef WISOC_AR9344 103 { 104 .ac_platformsw = &ar9344_platformsw, 105 .ac_chipid = 0x20, /* 7240? */ 106 .ac_chipmask = 0xff, 107 .ac_cid = MIPS_PRID_CID_MTI, 108 .ac_pid = MIPS_74K, 109 .ac_name = "AR7240" 110 }, { 111 .ac_platformsw = &ar9344_platformsw, 112 .ac_chipid = ARCHIP_AR9344, 113 .ac_chipmask = 0xff, 114 .ac_cid = MIPS_PRID_CID_MTI, 115 .ac_pid = MIPS_74K, 116 .ac_name = "AR9344" 117 }, 118#endif 119}; 120 121__CTASSERT(__arraycount(chips) > 0); 122 123const struct atheros_platformsw *platformsw; 124 125static const struct atheros_chip *my_chip; 126 127static struct arfreqs chip_freqs; 128 129const char * 130atheros_get_cpuname(void) 131{ 132 return my_chip->ac_name; 133} 134 135u_int 136atheros_get_chipid(void) 137{ 138 return my_chip->ac_chipid; 139} 140 141uint32_t 142atheros_get_uart_freq(void) 143{ 144 if (chip_freqs.freq_uart) 145 return chip_freqs.freq_uart; 146 147 return chip_freqs.freq_bus; 148} 149 150uint32_t 151atheros_get_bus_freq(void) 152{ 153 return chip_freqs.freq_bus; 154} 155 156uint32_t 157atheros_get_cpu_freq(void) 158{ 159 return chip_freqs.freq_cpu; 160} 161 162uint32_t 163atheros_get_mem_freq(void) 164{ 165 return chip_freqs.freq_mem; 166} 167 168void 169atheros_set_platformsw(void) 170{ 171 const u_int cid = MIPS_PRID_CID(mips_options.mips_cpu_id); 172 const u_int pid = MIPS_PRID_IMPL(mips_options.mips_cpu_id); 173 174 for (const struct atheros_chip *ac = chips; 175 ac < chips + __arraycount(chips); 176 ac++) { 177 const struct atheros_platformsw * const apsw = ac->ac_platformsw; 178 if (cid != ac->ac_cid || pid != ac->ac_pid) 179 continue; 180 181 const uint32_t revision_id = *(volatile uint32_t *) 182 MIPS_PHYS_TO_KSEG1(apsw->apsw_revision_id_addr); 183 const uint32_t chipid = AR9344_REVISION_CHIPID(revision_id); 184 185 if ((chipid & ac->ac_chipmask) == ac->ac_chipid) { 186 platformsw = apsw; 187 my_chip = ac; 188 atheros_early_consinit(); 189 printf("Early console started!\n"); 190 (*apsw->apsw_get_freqs)(&chip_freqs); 191 printf("freqs: cpu=%u bus=%u mem=%u ref=%u pll=%u\n", 192 chip_freqs.freq_cpu, 193 chip_freqs.freq_bus, 194 chip_freqs.freq_mem, 195 chip_freqs.freq_ref, 196 chip_freqs.freq_pll); 197 return; 198 } 199 } 200 panic("%s: unrecognized platform", __func__); 201} 202 203#include "ath_arbus.h" 204#if NATH_ARBUS > 0 205#include <ah_soc.h> 206 207const struct ar531x_boarddata * 208atheros_get_board_info(void) 209{ 210 const struct atheros_boardsw * const boardsw = my_chip->ac_boardsw; 211 if (boardsw == NULL) 212 return NULL; 213 return (*boardsw->absw_get_board_info)(); 214} 215 216/* 217 * Locate board and radio configuration data in flash. 218 */ 219int 220atheros_get_board_config(struct ar531x_config *config) 221{ 222 const struct atheros_boardsw * const boardsw = my_chip->ac_boardsw; 223 if (boardsw == NULL) 224 return ENOENT; 225 226 config->board = (*boardsw->absw_get_board_info)(); 227 if (config->board == NULL) 228 return ENOENT; 229 230 config->radio = (*boardsw->absw_get_radio_info)(); 231 if (config->radio == NULL) 232 return ENOENT; /* XXX distinct code */ 233 234 return 0; 235} 236#endif /* NATH_ARBUS > 0 */ 237