162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Atheros AR71XX/AR724X/AR913X specific setup 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2010-2011 Jaiganesh Narayanan <jnarayanan@atheros.com> 662306a36Sopenharmony_ci * Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org> 762306a36Sopenharmony_ci * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> 862306a36Sopenharmony_ci * 962306a36Sopenharmony_ci * Parts of this file are based on Atheros' 2.6.15/2.6.31 BSP 1062306a36Sopenharmony_ci */ 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci#include <linux/kernel.h> 1362306a36Sopenharmony_ci#include <linux/init.h> 1462306a36Sopenharmony_ci#include <linux/io.h> 1562306a36Sopenharmony_ci#include <linux/memblock.h> 1662306a36Sopenharmony_ci#include <linux/err.h> 1762306a36Sopenharmony_ci#include <linux/clk.h> 1862306a36Sopenharmony_ci#include <linux/of_clk.h> 1962306a36Sopenharmony_ci#include <linux/of_fdt.h> 2062306a36Sopenharmony_ci#include <linux/irqchip.h> 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ci#include <asm/bootinfo.h> 2362306a36Sopenharmony_ci#include <asm/idle.h> 2462306a36Sopenharmony_ci#include <asm/time.h> /* for mips_hpt_frequency */ 2562306a36Sopenharmony_ci#include <asm/reboot.h> /* for _machine_{restart,halt} */ 2662306a36Sopenharmony_ci#include <asm/prom.h> 2762306a36Sopenharmony_ci#include <asm/fw/fw.h> 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ci#include <asm/mach-ath79/ath79.h> 3062306a36Sopenharmony_ci#include <asm/mach-ath79/ar71xx_regs.h> 3162306a36Sopenharmony_ci#include "common.h" 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ci#define ATH79_SYS_TYPE_LEN 64 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_cistatic char ath79_sys_type[ATH79_SYS_TYPE_LEN]; 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_cistatic void ath79_halt(void) 3862306a36Sopenharmony_ci{ 3962306a36Sopenharmony_ci while (1) 4062306a36Sopenharmony_ci cpu_wait(); 4162306a36Sopenharmony_ci} 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_cistatic void __init ath79_detect_sys_type(void) 4462306a36Sopenharmony_ci{ 4562306a36Sopenharmony_ci char *chip = "????"; 4662306a36Sopenharmony_ci u32 id; 4762306a36Sopenharmony_ci u32 major; 4862306a36Sopenharmony_ci u32 minor; 4962306a36Sopenharmony_ci u32 rev = 0; 5062306a36Sopenharmony_ci u32 ver = 1; 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ci id = ath79_reset_rr(AR71XX_RESET_REG_REV_ID); 5362306a36Sopenharmony_ci major = id & REV_ID_MAJOR_MASK; 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ci switch (major) { 5662306a36Sopenharmony_ci case REV_ID_MAJOR_AR71XX: 5762306a36Sopenharmony_ci minor = id & AR71XX_REV_ID_MINOR_MASK; 5862306a36Sopenharmony_ci rev = id >> AR71XX_REV_ID_REVISION_SHIFT; 5962306a36Sopenharmony_ci rev &= AR71XX_REV_ID_REVISION_MASK; 6062306a36Sopenharmony_ci switch (minor) { 6162306a36Sopenharmony_ci case AR71XX_REV_ID_MINOR_AR7130: 6262306a36Sopenharmony_ci ath79_soc = ATH79_SOC_AR7130; 6362306a36Sopenharmony_ci chip = "7130"; 6462306a36Sopenharmony_ci break; 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ci case AR71XX_REV_ID_MINOR_AR7141: 6762306a36Sopenharmony_ci ath79_soc = ATH79_SOC_AR7141; 6862306a36Sopenharmony_ci chip = "7141"; 6962306a36Sopenharmony_ci break; 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ci case AR71XX_REV_ID_MINOR_AR7161: 7262306a36Sopenharmony_ci ath79_soc = ATH79_SOC_AR7161; 7362306a36Sopenharmony_ci chip = "7161"; 7462306a36Sopenharmony_ci break; 7562306a36Sopenharmony_ci } 7662306a36Sopenharmony_ci break; 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ci case REV_ID_MAJOR_AR7240: 7962306a36Sopenharmony_ci ath79_soc = ATH79_SOC_AR7240; 8062306a36Sopenharmony_ci chip = "7240"; 8162306a36Sopenharmony_ci rev = id & AR724X_REV_ID_REVISION_MASK; 8262306a36Sopenharmony_ci break; 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_ci case REV_ID_MAJOR_AR7241: 8562306a36Sopenharmony_ci ath79_soc = ATH79_SOC_AR7241; 8662306a36Sopenharmony_ci chip = "7241"; 8762306a36Sopenharmony_ci rev = id & AR724X_REV_ID_REVISION_MASK; 8862306a36Sopenharmony_ci break; 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_ci case REV_ID_MAJOR_AR7242: 9162306a36Sopenharmony_ci ath79_soc = ATH79_SOC_AR7242; 9262306a36Sopenharmony_ci chip = "7242"; 9362306a36Sopenharmony_ci rev = id & AR724X_REV_ID_REVISION_MASK; 9462306a36Sopenharmony_ci break; 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_ci case REV_ID_MAJOR_AR913X: 9762306a36Sopenharmony_ci minor = id & AR913X_REV_ID_MINOR_MASK; 9862306a36Sopenharmony_ci rev = id >> AR913X_REV_ID_REVISION_SHIFT; 9962306a36Sopenharmony_ci rev &= AR913X_REV_ID_REVISION_MASK; 10062306a36Sopenharmony_ci switch (minor) { 10162306a36Sopenharmony_ci case AR913X_REV_ID_MINOR_AR9130: 10262306a36Sopenharmony_ci ath79_soc = ATH79_SOC_AR9130; 10362306a36Sopenharmony_ci chip = "9130"; 10462306a36Sopenharmony_ci break; 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_ci case AR913X_REV_ID_MINOR_AR9132: 10762306a36Sopenharmony_ci ath79_soc = ATH79_SOC_AR9132; 10862306a36Sopenharmony_ci chip = "9132"; 10962306a36Sopenharmony_ci break; 11062306a36Sopenharmony_ci } 11162306a36Sopenharmony_ci break; 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_ci case REV_ID_MAJOR_AR9330: 11462306a36Sopenharmony_ci ath79_soc = ATH79_SOC_AR9330; 11562306a36Sopenharmony_ci chip = "9330"; 11662306a36Sopenharmony_ci rev = id & AR933X_REV_ID_REVISION_MASK; 11762306a36Sopenharmony_ci break; 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_ci case REV_ID_MAJOR_AR9331: 12062306a36Sopenharmony_ci ath79_soc = ATH79_SOC_AR9331; 12162306a36Sopenharmony_ci chip = "9331"; 12262306a36Sopenharmony_ci rev = id & AR933X_REV_ID_REVISION_MASK; 12362306a36Sopenharmony_ci break; 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_ci case REV_ID_MAJOR_AR9341: 12662306a36Sopenharmony_ci ath79_soc = ATH79_SOC_AR9341; 12762306a36Sopenharmony_ci chip = "9341"; 12862306a36Sopenharmony_ci rev = id & AR934X_REV_ID_REVISION_MASK; 12962306a36Sopenharmony_ci break; 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_ci case REV_ID_MAJOR_AR9342: 13262306a36Sopenharmony_ci ath79_soc = ATH79_SOC_AR9342; 13362306a36Sopenharmony_ci chip = "9342"; 13462306a36Sopenharmony_ci rev = id & AR934X_REV_ID_REVISION_MASK; 13562306a36Sopenharmony_ci break; 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_ci case REV_ID_MAJOR_AR9344: 13862306a36Sopenharmony_ci ath79_soc = ATH79_SOC_AR9344; 13962306a36Sopenharmony_ci chip = "9344"; 14062306a36Sopenharmony_ci rev = id & AR934X_REV_ID_REVISION_MASK; 14162306a36Sopenharmony_ci break; 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_ci case REV_ID_MAJOR_QCA9533_V2: 14462306a36Sopenharmony_ci ver = 2; 14562306a36Sopenharmony_ci ath79_soc_rev = 2; 14662306a36Sopenharmony_ci fallthrough; 14762306a36Sopenharmony_ci case REV_ID_MAJOR_QCA9533: 14862306a36Sopenharmony_ci ath79_soc = ATH79_SOC_QCA9533; 14962306a36Sopenharmony_ci chip = "9533"; 15062306a36Sopenharmony_ci rev = id & QCA953X_REV_ID_REVISION_MASK; 15162306a36Sopenharmony_ci break; 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_ci case REV_ID_MAJOR_QCA9556: 15462306a36Sopenharmony_ci ath79_soc = ATH79_SOC_QCA9556; 15562306a36Sopenharmony_ci chip = "9556"; 15662306a36Sopenharmony_ci rev = id & QCA955X_REV_ID_REVISION_MASK; 15762306a36Sopenharmony_ci break; 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_ci case REV_ID_MAJOR_QCA9558: 16062306a36Sopenharmony_ci ath79_soc = ATH79_SOC_QCA9558; 16162306a36Sopenharmony_ci chip = "9558"; 16262306a36Sopenharmony_ci rev = id & QCA955X_REV_ID_REVISION_MASK; 16362306a36Sopenharmony_ci break; 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_ci case REV_ID_MAJOR_QCA956X: 16662306a36Sopenharmony_ci ath79_soc = ATH79_SOC_QCA956X; 16762306a36Sopenharmony_ci chip = "956X"; 16862306a36Sopenharmony_ci rev = id & QCA956X_REV_ID_REVISION_MASK; 16962306a36Sopenharmony_ci break; 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_ci case REV_ID_MAJOR_QCN550X: 17262306a36Sopenharmony_ci ath79_soc = ATH79_SOC_QCA956X; 17362306a36Sopenharmony_ci chip = "550X"; 17462306a36Sopenharmony_ci rev = id & QCA956X_REV_ID_REVISION_MASK; 17562306a36Sopenharmony_ci break; 17662306a36Sopenharmony_ci 17762306a36Sopenharmony_ci case REV_ID_MAJOR_TP9343: 17862306a36Sopenharmony_ci ath79_soc = ATH79_SOC_TP9343; 17962306a36Sopenharmony_ci chip = "9343"; 18062306a36Sopenharmony_ci rev = id & QCA956X_REV_ID_REVISION_MASK; 18162306a36Sopenharmony_ci break; 18262306a36Sopenharmony_ci 18362306a36Sopenharmony_ci default: 18462306a36Sopenharmony_ci panic("ath79: unknown SoC, id:0x%08x", id); 18562306a36Sopenharmony_ci } 18662306a36Sopenharmony_ci 18762306a36Sopenharmony_ci if (ver == 1) 18862306a36Sopenharmony_ci ath79_soc_rev = rev; 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_ci if (soc_is_qca953x() || soc_is_qca955x() || soc_is_qca956x()) 19162306a36Sopenharmony_ci sprintf(ath79_sys_type, "Qualcomm Atheros QCA%s ver %u rev %u", 19262306a36Sopenharmony_ci chip, ver, rev); 19362306a36Sopenharmony_ci else if (soc_is_tp9343()) 19462306a36Sopenharmony_ci sprintf(ath79_sys_type, "Qualcomm Atheros TP%s rev %u", 19562306a36Sopenharmony_ci chip, rev); 19662306a36Sopenharmony_ci else 19762306a36Sopenharmony_ci sprintf(ath79_sys_type, "Atheros AR%s rev %u", chip, rev); 19862306a36Sopenharmony_ci pr_info("SoC: %s\n", ath79_sys_type); 19962306a36Sopenharmony_ci} 20062306a36Sopenharmony_ci 20162306a36Sopenharmony_ciconst char *get_system_type(void) 20262306a36Sopenharmony_ci{ 20362306a36Sopenharmony_ci return ath79_sys_type; 20462306a36Sopenharmony_ci} 20562306a36Sopenharmony_ci 20662306a36Sopenharmony_ciunsigned int get_c0_compare_int(void) 20762306a36Sopenharmony_ci{ 20862306a36Sopenharmony_ci return CP0_LEGACY_COMPARE_IRQ; 20962306a36Sopenharmony_ci} 21062306a36Sopenharmony_ci 21162306a36Sopenharmony_civoid __init plat_mem_setup(void) 21262306a36Sopenharmony_ci{ 21362306a36Sopenharmony_ci void *dtb; 21462306a36Sopenharmony_ci 21562306a36Sopenharmony_ci set_io_port_base(KSEG1); 21662306a36Sopenharmony_ci 21762306a36Sopenharmony_ci /* Get the position of the FDT passed by the bootloader */ 21862306a36Sopenharmony_ci dtb = (void *)fw_getenvl("fdt_start"); 21962306a36Sopenharmony_ci if (dtb == NULL) 22062306a36Sopenharmony_ci dtb = get_fdt(); 22162306a36Sopenharmony_ci 22262306a36Sopenharmony_ci if (dtb) 22362306a36Sopenharmony_ci __dt_setup_arch((void *)KSEG0ADDR(dtb)); 22462306a36Sopenharmony_ci 22562306a36Sopenharmony_ci ath79_reset_base = ioremap(AR71XX_RESET_BASE, 22662306a36Sopenharmony_ci AR71XX_RESET_SIZE); 22762306a36Sopenharmony_ci ath79_pll_base = ioremap(AR71XX_PLL_BASE, 22862306a36Sopenharmony_ci AR71XX_PLL_SIZE); 22962306a36Sopenharmony_ci ath79_detect_sys_type(); 23062306a36Sopenharmony_ci ath79_ddr_ctrl_init(); 23162306a36Sopenharmony_ci 23262306a36Sopenharmony_ci detect_memory_region(0, ATH79_MEM_SIZE_MIN, ATH79_MEM_SIZE_MAX); 23362306a36Sopenharmony_ci 23462306a36Sopenharmony_ci _machine_halt = ath79_halt; 23562306a36Sopenharmony_ci pm_power_off = ath79_halt; 23662306a36Sopenharmony_ci} 23762306a36Sopenharmony_ci 23862306a36Sopenharmony_civoid __init plat_time_init(void) 23962306a36Sopenharmony_ci{ 24062306a36Sopenharmony_ci struct device_node *np; 24162306a36Sopenharmony_ci struct clk *clk; 24262306a36Sopenharmony_ci unsigned long cpu_clk_rate; 24362306a36Sopenharmony_ci 24462306a36Sopenharmony_ci of_clk_init(NULL); 24562306a36Sopenharmony_ci 24662306a36Sopenharmony_ci np = of_get_cpu_node(0, NULL); 24762306a36Sopenharmony_ci if (!np) { 24862306a36Sopenharmony_ci pr_err("Failed to get CPU node\n"); 24962306a36Sopenharmony_ci return; 25062306a36Sopenharmony_ci } 25162306a36Sopenharmony_ci 25262306a36Sopenharmony_ci clk = of_clk_get(np, 0); 25362306a36Sopenharmony_ci if (IS_ERR(clk)) { 25462306a36Sopenharmony_ci pr_err("Failed to get CPU clock: %ld\n", PTR_ERR(clk)); 25562306a36Sopenharmony_ci return; 25662306a36Sopenharmony_ci } 25762306a36Sopenharmony_ci 25862306a36Sopenharmony_ci cpu_clk_rate = clk_get_rate(clk); 25962306a36Sopenharmony_ci 26062306a36Sopenharmony_ci pr_info("CPU clock: %lu.%03lu MHz\n", 26162306a36Sopenharmony_ci cpu_clk_rate / 1000000, (cpu_clk_rate / 1000) % 1000); 26262306a36Sopenharmony_ci 26362306a36Sopenharmony_ci mips_hpt_frequency = cpu_clk_rate / 2; 26462306a36Sopenharmony_ci 26562306a36Sopenharmony_ci clk_put(clk); 26662306a36Sopenharmony_ci} 26762306a36Sopenharmony_ci 26862306a36Sopenharmony_civoid __init arch_init_irq(void) 26962306a36Sopenharmony_ci{ 27062306a36Sopenharmony_ci irqchip_init(); 27162306a36Sopenharmony_ci} 272