1*97627a75Smatt /* $NetBSD: ar_conf.c,v 1.3 2015/06/09 22:50:50 matt Exp $ */
281d18a2fSmatt /*-
381d18a2fSmatt * Copyright (c) 2011 The NetBSD Foundation, Inc.
481d18a2fSmatt * All rights reserved.
581d18a2fSmatt *
681d18a2fSmatt * This code is derived from software contributed to The NetBSD Foundation
781d18a2fSmatt * by Matt Thomas of 3am Software Foundry.
881d18a2fSmatt *
981d18a2fSmatt * Redistribution and use in source and binary forms, with or without
1081d18a2fSmatt * modification, are permitted provided that the following conditions
1181d18a2fSmatt * are met:
1281d18a2fSmatt * 1. Redistributions of source code must retain the above copyright
1381d18a2fSmatt * notice, this list of conditions and the following disclaimer.
1481d18a2fSmatt * 2. Redistributions in binary form must reproduce the above copyright
1581d18a2fSmatt * notice, this list of conditions and the following disclaimer in the
1681d18a2fSmatt * documentation and/or other materials provided with the distribution.
1781d18a2fSmatt *
1881d18a2fSmatt * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
1981d18a2fSmatt * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
2081d18a2fSmatt * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2181d18a2fSmatt * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
2281d18a2fSmatt * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2381d18a2fSmatt * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2481d18a2fSmatt * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2581d18a2fSmatt * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2681d18a2fSmatt * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2781d18a2fSmatt * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2881d18a2fSmatt * POSSIBILITY OF SUCH DAMAGE.
2981d18a2fSmatt */
3081d18a2fSmatt
3181d18a2fSmatt #include <sys/cdefs.h>
3281d18a2fSmatt
33*97627a75Smatt __KERNEL_RCSID(0, "$NetBSD: ar_conf.c,v 1.3 2015/06/09 22:50:50 matt Exp $");
3481d18a2fSmatt
3581d18a2fSmatt #include <sys/param.h>
36*97627a75Smatt #include <sys/cpu.h>
3781d18a2fSmatt
3881d18a2fSmatt #include "opt_wisoc.h"
3981d18a2fSmatt
4081d18a2fSmatt #include <mips/cpuregs.h>
4181d18a2fSmatt #include <mips/locore.h>
4281d18a2fSmatt
4381d18a2fSmatt #include <mips/atheros/include/platform.h>
4481d18a2fSmatt #include <mips/atheros/include/ar9344reg.h>
4581d18a2fSmatt
4681d18a2fSmatt struct atheros_chip {
4781d18a2fSmatt const struct atheros_platformsw *ac_platformsw;
4881d18a2fSmatt const struct atheros_boardsw *ac_boardsw;
4981d18a2fSmatt uint8_t ac_chipid;
5081d18a2fSmatt uint8_t ac_chipmask;
5181d18a2fSmatt uint8_t ac_cid;
5281d18a2fSmatt uint8_t ac_pid;
5381d18a2fSmatt const char ac_name[8];
5481d18a2fSmatt };
5581d18a2fSmatt
5681d18a2fSmatt static const struct atheros_chip chips[] = {
5781d18a2fSmatt #ifdef WISOC_AR5312
5881d18a2fSmatt {
5981d18a2fSmatt .ac_platformsw = &ar5312_platformsw,
6081d18a2fSmatt .ac_boardsw = &ar5312_boardsw,
6181d18a2fSmatt .ac_chipid = ARCHIP_AR5312,
6281d18a2fSmatt .ac_chipmask = 0xff,
6381d18a2fSmatt .ac_cid = MIPS_PRID_CID_MTI,
6481d18a2fSmatt .ac_pid = MIPS_4Kc,
6581d18a2fSmatt .ac_name = "AR5312"
6681d18a2fSmatt },
6781d18a2fSmatt #endif
6881d18a2fSmatt #ifdef WISOC_AR5315
6981d18a2fSmatt {
7081d18a2fSmatt .ac_platformsw = &ar5315_platformsw,
7181d18a2fSmatt .ac_boardsw = &ar5315_boardsw,
7281d18a2fSmatt .ac_chipid = ARCHIP_AR5315,
7381d18a2fSmatt .ac_chipmask = 0xf0,
7481d18a2fSmatt .ac_cid = MIPS_PRID_CID_MTI,
7581d18a2fSmatt .ac_pid = MIPS_4Kc,
7681d18a2fSmatt .ac_name = "AR5315"
7781d18a2fSmatt },
7881d18a2fSmatt #endif
7981d18a2fSmatt #ifdef WISOC_AR7100
8081d18a2fSmatt {
8181d18a2fSmatt .ac_platformsw = &ar7100_platformsw,
8281d18a2fSmatt .ac_chipid = ARCHIP_AR7130,
8381d18a2fSmatt .ac_chipmask = 0xf3,
8481d18a2fSmatt .ac_cid = MIPS_PRID_CID_MTI,
8581d18a2fSmatt .ac_pid = MIPS_24K,
8681d18a2fSmatt .ac_name = "AR7130"
8781d18a2fSmatt }, {
8881d18a2fSmatt .ac_platformsw = &ar7100_platformsw,
8981d18a2fSmatt .ac_chipid = ARCHIP_AR7141,
9081d18a2fSmatt .ac_chipmask = 0xf3,
9181d18a2fSmatt .ac_cid = MIPS_PRID_CID_MTI,
9281d18a2fSmatt .ac_pid = MIPS_24K,
9381d18a2fSmatt .ac_name = "AR7141"
9481d18a2fSmatt }, {
9581d18a2fSmatt .ac_platformsw = &ar7100_platformsw,
9681d18a2fSmatt .ac_chipid = ARCHIP_AR7161,
9781d18a2fSmatt .ac_chipmask = 0xf3,
9881d18a2fSmatt .ac_cid = MIPS_PRID_CID_MTI,
9981d18a2fSmatt .ac_pid = MIPS_24K,
10081d18a2fSmatt .ac_name = "AR7161"
10181d18a2fSmatt },
10281d18a2fSmatt #endif
10381d18a2fSmatt #ifdef WISOC_AR9344
10481d18a2fSmatt {
10581d18a2fSmatt .ac_platformsw = &ar9344_platformsw,
10631586d2cSmatt .ac_chipid = 0x20, /* 7240? */
10731586d2cSmatt .ac_chipmask = 0xff,
10831586d2cSmatt .ac_cid = MIPS_PRID_CID_MTI,
10931586d2cSmatt .ac_pid = MIPS_74K,
11031586d2cSmatt .ac_name = "AR7240"
11131586d2cSmatt }, {
11231586d2cSmatt .ac_platformsw = &ar9344_platformsw,
11381d18a2fSmatt .ac_chipid = ARCHIP_AR9344,
11481d18a2fSmatt .ac_chipmask = 0xff,
11581d18a2fSmatt .ac_cid = MIPS_PRID_CID_MTI,
11681d18a2fSmatt .ac_pid = MIPS_74K,
11781d18a2fSmatt .ac_name = "AR9344"
11881d18a2fSmatt },
11981d18a2fSmatt #endif
12081d18a2fSmatt };
12181d18a2fSmatt
12281d18a2fSmatt __CTASSERT(__arraycount(chips) > 0);
12381d18a2fSmatt
12481d18a2fSmatt const struct atheros_platformsw *platformsw;
12581d18a2fSmatt
12681d18a2fSmatt static const struct atheros_chip *my_chip;
12781d18a2fSmatt
12881d18a2fSmatt static struct arfreqs chip_freqs;
12981d18a2fSmatt
13081d18a2fSmatt const char *
atheros_get_cpuname(void)13181d18a2fSmatt atheros_get_cpuname(void)
13281d18a2fSmatt {
13381d18a2fSmatt return my_chip->ac_name;
13481d18a2fSmatt }
13581d18a2fSmatt
13681d18a2fSmatt u_int
atheros_get_chipid(void)13781d18a2fSmatt atheros_get_chipid(void)
13881d18a2fSmatt {
13981d18a2fSmatt return my_chip->ac_chipid;
14081d18a2fSmatt }
14181d18a2fSmatt
14281d18a2fSmatt uint32_t
atheros_get_uart_freq(void)14331586d2cSmatt atheros_get_uart_freq(void)
14431586d2cSmatt {
14531586d2cSmatt if (chip_freqs.freq_uart)
14631586d2cSmatt return chip_freqs.freq_uart;
14731586d2cSmatt
14831586d2cSmatt return chip_freqs.freq_bus;
14931586d2cSmatt }
15031586d2cSmatt
15131586d2cSmatt uint32_t
atheros_get_bus_freq(void)15281d18a2fSmatt atheros_get_bus_freq(void)
15381d18a2fSmatt {
15481d18a2fSmatt return chip_freqs.freq_bus;
15581d18a2fSmatt }
15681d18a2fSmatt
15781d18a2fSmatt uint32_t
atheros_get_cpu_freq(void)15881d18a2fSmatt atheros_get_cpu_freq(void)
15981d18a2fSmatt {
16081d18a2fSmatt return chip_freqs.freq_cpu;
16181d18a2fSmatt }
16281d18a2fSmatt
16381d18a2fSmatt uint32_t
atheros_get_mem_freq(void)16481d18a2fSmatt atheros_get_mem_freq(void)
16581d18a2fSmatt {
16681d18a2fSmatt return chip_freqs.freq_mem;
16781d18a2fSmatt }
16881d18a2fSmatt
16981d18a2fSmatt void
atheros_set_platformsw(void)17081d18a2fSmatt atheros_set_platformsw(void)
17181d18a2fSmatt {
17281d18a2fSmatt const u_int cid = MIPS_PRID_CID(mips_options.mips_cpu_id);
17381d18a2fSmatt const u_int pid = MIPS_PRID_IMPL(mips_options.mips_cpu_id);
17481d18a2fSmatt
17581d18a2fSmatt for (const struct atheros_chip *ac = chips;
17681d18a2fSmatt ac < chips + __arraycount(chips);
17781d18a2fSmatt ac++) {
17881d18a2fSmatt const struct atheros_platformsw * const apsw = ac->ac_platformsw;
17981d18a2fSmatt if (cid != ac->ac_cid || pid != ac->ac_pid)
18081d18a2fSmatt continue;
18181d18a2fSmatt
18281d18a2fSmatt const uint32_t revision_id = *(volatile uint32_t *)
18381d18a2fSmatt MIPS_PHYS_TO_KSEG1(apsw->apsw_revision_id_addr);
18481d18a2fSmatt const uint32_t chipid = AR9344_REVISION_CHIPID(revision_id);
18581d18a2fSmatt
18681d18a2fSmatt if ((chipid & ac->ac_chipmask) == ac->ac_chipid) {
18781d18a2fSmatt platformsw = apsw;
18881d18a2fSmatt my_chip = ac;
18981d18a2fSmatt atheros_early_consinit();
19081d18a2fSmatt printf("Early console started!\n");
19181d18a2fSmatt (*apsw->apsw_get_freqs)(&chip_freqs);
19231586d2cSmatt printf("freqs: cpu=%u bus=%u mem=%u ref=%u pll=%u\n",
19331586d2cSmatt chip_freqs.freq_cpu,
19431586d2cSmatt chip_freqs.freq_bus,
19531586d2cSmatt chip_freqs.freq_mem,
19631586d2cSmatt chip_freqs.freq_ref,
19731586d2cSmatt chip_freqs.freq_pll);
19881d18a2fSmatt return;
19981d18a2fSmatt }
20081d18a2fSmatt }
20181d18a2fSmatt panic("%s: unrecognized platform", __func__);
20281d18a2fSmatt }
20381d18a2fSmatt
20481d18a2fSmatt #include "ath_arbus.h"
20581d18a2fSmatt #if NATH_ARBUS > 0
20681d18a2fSmatt #include <ah_soc.h>
20781d18a2fSmatt
20881d18a2fSmatt const struct ar531x_boarddata *
atheros_get_board_info(void)20981d18a2fSmatt atheros_get_board_info(void)
21081d18a2fSmatt {
21181d18a2fSmatt const struct atheros_boardsw * const boardsw = my_chip->ac_boardsw;
21281d18a2fSmatt if (boardsw == NULL)
21381d18a2fSmatt return NULL;
21481d18a2fSmatt return (*boardsw->absw_get_board_info)();
21581d18a2fSmatt }
21681d18a2fSmatt
21781d18a2fSmatt /*
21881d18a2fSmatt * Locate board and radio configuration data in flash.
21981d18a2fSmatt */
22081d18a2fSmatt int
atheros_get_board_config(struct ar531x_config * config)22181d18a2fSmatt atheros_get_board_config(struct ar531x_config *config)
22281d18a2fSmatt {
22381d18a2fSmatt const struct atheros_boardsw * const boardsw = my_chip->ac_boardsw;
22481d18a2fSmatt if (boardsw == NULL)
22581d18a2fSmatt return ENOENT;
22681d18a2fSmatt
22781d18a2fSmatt config->board = (*boardsw->absw_get_board_info)();
22881d18a2fSmatt if (config->board == NULL)
22981d18a2fSmatt return ENOENT;
23081d18a2fSmatt
23181d18a2fSmatt config->radio = (*boardsw->absw_get_radio_info)();
23281d18a2fSmatt if (config->radio == NULL)
23381d18a2fSmatt return ENOENT; /* XXX distinct code */
23481d18a2fSmatt
23581d18a2fSmatt return 0;
23681d18a2fSmatt }
23781d18a2fSmatt #endif /* NATH_ARBUS > 0 */
238