162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * Parts of this file are based on Ralink's 2.6.21 BSP 562306a36Sopenharmony_ci * 662306a36Sopenharmony_ci * Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org> 762306a36Sopenharmony_ci * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> 862306a36Sopenharmony_ci * Copyright (C) 2013 John Crispin <john@phrozen.org> 962306a36Sopenharmony_ci */ 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci#include <linux/kernel.h> 1262306a36Sopenharmony_ci#include <linux/init.h> 1362306a36Sopenharmony_ci#include <linux/bug.h> 1462306a36Sopenharmony_ci#include <linux/slab.h> 1562306a36Sopenharmony_ci#include <linux/sys_soc.h> 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ci#include <asm/mipsregs.h> 1862306a36Sopenharmony_ci#include <asm/mach-ralink/ralink_regs.h> 1962306a36Sopenharmony_ci#include <asm/mach-ralink/mt7620.h> 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_ci#include "common.h" 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci/* analog */ 2462306a36Sopenharmony_ci#define PMU0_CFG 0x88 2562306a36Sopenharmony_ci#define PMU_SW_SET BIT(28) 2662306a36Sopenharmony_ci#define A_DCDC_EN BIT(24) 2762306a36Sopenharmony_ci#define A_SSC_PERI BIT(19) 2862306a36Sopenharmony_ci#define A_SSC_GEN BIT(18) 2962306a36Sopenharmony_ci#define A_SSC_M 0x3 3062306a36Sopenharmony_ci#define A_SSC_S 16 3162306a36Sopenharmony_ci#define A_DLY_M 0x7 3262306a36Sopenharmony_ci#define A_DLY_S 8 3362306a36Sopenharmony_ci#define A_VTUNE_M 0xff 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ci/* digital */ 3662306a36Sopenharmony_ci#define PMU1_CFG 0x8C 3762306a36Sopenharmony_ci#define DIG_SW_SEL BIT(25) 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_ci/* EFUSE bits */ 4062306a36Sopenharmony_ci#define EFUSE_MT7688 0x100000 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_ci/* DRAM type bit */ 4362306a36Sopenharmony_ci#define DRAM_TYPE_MT7628_MASK 0x1 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ci/* does the board have sdram or ddram */ 4662306a36Sopenharmony_cistatic int dram_type; 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_cistatic struct ralink_soc_info *soc_info_ptr; 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_cistatic __init void 5162306a36Sopenharmony_cimt7620_dram_init(struct ralink_soc_info *soc_info) 5262306a36Sopenharmony_ci{ 5362306a36Sopenharmony_ci switch (dram_type) { 5462306a36Sopenharmony_ci case SYSCFG0_DRAM_TYPE_SDRAM: 5562306a36Sopenharmony_ci pr_info("Board has SDRAM\n"); 5662306a36Sopenharmony_ci soc_info->mem_size_min = MT7620_SDRAM_SIZE_MIN; 5762306a36Sopenharmony_ci soc_info->mem_size_max = MT7620_SDRAM_SIZE_MAX; 5862306a36Sopenharmony_ci break; 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_ci case SYSCFG0_DRAM_TYPE_DDR1: 6162306a36Sopenharmony_ci pr_info("Board has DDR1\n"); 6262306a36Sopenharmony_ci soc_info->mem_size_min = MT7620_DDR1_SIZE_MIN; 6362306a36Sopenharmony_ci soc_info->mem_size_max = MT7620_DDR1_SIZE_MAX; 6462306a36Sopenharmony_ci break; 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ci case SYSCFG0_DRAM_TYPE_DDR2: 6762306a36Sopenharmony_ci pr_info("Board has DDR2\n"); 6862306a36Sopenharmony_ci soc_info->mem_size_min = MT7620_DDR2_SIZE_MIN; 6962306a36Sopenharmony_ci soc_info->mem_size_max = MT7620_DDR2_SIZE_MAX; 7062306a36Sopenharmony_ci break; 7162306a36Sopenharmony_ci default: 7262306a36Sopenharmony_ci BUG(); 7362306a36Sopenharmony_ci } 7462306a36Sopenharmony_ci} 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_cistatic __init void 7762306a36Sopenharmony_cimt7628_dram_init(struct ralink_soc_info *soc_info) 7862306a36Sopenharmony_ci{ 7962306a36Sopenharmony_ci switch (dram_type) { 8062306a36Sopenharmony_ci case SYSCFG0_DRAM_TYPE_DDR1_MT7628: 8162306a36Sopenharmony_ci pr_info("Board has DDR1\n"); 8262306a36Sopenharmony_ci soc_info->mem_size_min = MT7620_DDR1_SIZE_MIN; 8362306a36Sopenharmony_ci soc_info->mem_size_max = MT7620_DDR1_SIZE_MAX; 8462306a36Sopenharmony_ci break; 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ci case SYSCFG0_DRAM_TYPE_DDR2_MT7628: 8762306a36Sopenharmony_ci pr_info("Board has DDR2\n"); 8862306a36Sopenharmony_ci soc_info->mem_size_min = MT7620_DDR2_SIZE_MIN; 8962306a36Sopenharmony_ci soc_info->mem_size_max = MT7620_DDR2_SIZE_MAX; 9062306a36Sopenharmony_ci break; 9162306a36Sopenharmony_ci default: 9262306a36Sopenharmony_ci BUG(); 9362306a36Sopenharmony_ci } 9462306a36Sopenharmony_ci} 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_cistatic unsigned int __init mt7620_get_soc_name0(void) 9762306a36Sopenharmony_ci{ 9862306a36Sopenharmony_ci return __raw_readl(MT7620_SYSC_BASE + SYSC_REG_CHIP_NAME0); 9962306a36Sopenharmony_ci} 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_cistatic unsigned int __init mt7620_get_soc_name1(void) 10262306a36Sopenharmony_ci{ 10362306a36Sopenharmony_ci return __raw_readl(MT7620_SYSC_BASE + SYSC_REG_CHIP_NAME1); 10462306a36Sopenharmony_ci} 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_cistatic bool __init mt7620_soc_valid(void) 10762306a36Sopenharmony_ci{ 10862306a36Sopenharmony_ci if (mt7620_get_soc_name0() == MT7620_CHIP_NAME0 && 10962306a36Sopenharmony_ci mt7620_get_soc_name1() == MT7620_CHIP_NAME1) 11062306a36Sopenharmony_ci return true; 11162306a36Sopenharmony_ci else 11262306a36Sopenharmony_ci return false; 11362306a36Sopenharmony_ci} 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_cistatic bool __init mt7628_soc_valid(void) 11662306a36Sopenharmony_ci{ 11762306a36Sopenharmony_ci if (mt7620_get_soc_name0() == MT7620_CHIP_NAME0 && 11862306a36Sopenharmony_ci mt7620_get_soc_name1() == MT7628_CHIP_NAME1) 11962306a36Sopenharmony_ci return true; 12062306a36Sopenharmony_ci else 12162306a36Sopenharmony_ci return false; 12262306a36Sopenharmony_ci} 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_cistatic unsigned int __init mt7620_get_rev(void) 12562306a36Sopenharmony_ci{ 12662306a36Sopenharmony_ci return __raw_readl(MT7620_SYSC_BASE + SYSC_REG_CHIP_REV); 12762306a36Sopenharmony_ci} 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_cistatic unsigned int __init mt7620_get_bga(void) 13062306a36Sopenharmony_ci{ 13162306a36Sopenharmony_ci return (mt7620_get_rev() >> CHIP_REV_PKG_SHIFT) & CHIP_REV_PKG_MASK; 13262306a36Sopenharmony_ci} 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_cistatic unsigned int __init mt7620_get_efuse(void) 13562306a36Sopenharmony_ci{ 13662306a36Sopenharmony_ci return __raw_readl(MT7620_SYSC_BASE + SYSC_REG_EFUSE_CFG); 13762306a36Sopenharmony_ci} 13862306a36Sopenharmony_ci 13962306a36Sopenharmony_cistatic unsigned int __init mt7620_get_soc_ver(void) 14062306a36Sopenharmony_ci{ 14162306a36Sopenharmony_ci return (mt7620_get_rev() >> CHIP_REV_VER_SHIFT) & CHIP_REV_VER_MASK; 14262306a36Sopenharmony_ci} 14362306a36Sopenharmony_ci 14462306a36Sopenharmony_cistatic unsigned int __init mt7620_get_soc_eco(void) 14562306a36Sopenharmony_ci{ 14662306a36Sopenharmony_ci return (mt7620_get_rev() & CHIP_REV_ECO_MASK); 14762306a36Sopenharmony_ci} 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_cistatic const char __init *mt7620_get_soc_name(struct ralink_soc_info *soc_info) 15062306a36Sopenharmony_ci{ 15162306a36Sopenharmony_ci if (mt7620_soc_valid()) { 15262306a36Sopenharmony_ci u32 bga = mt7620_get_bga(); 15362306a36Sopenharmony_ci 15462306a36Sopenharmony_ci if (bga) { 15562306a36Sopenharmony_ci ralink_soc = MT762X_SOC_MT7620A; 15662306a36Sopenharmony_ci soc_info->compatible = "ralink,mt7620a-soc"; 15762306a36Sopenharmony_ci return "MT7620A"; 15862306a36Sopenharmony_ci } else { 15962306a36Sopenharmony_ci ralink_soc = MT762X_SOC_MT7620N; 16062306a36Sopenharmony_ci soc_info->compatible = "ralink,mt7620n-soc"; 16162306a36Sopenharmony_ci return "MT7620N"; 16262306a36Sopenharmony_ci } 16362306a36Sopenharmony_ci } else if (mt7628_soc_valid()) { 16462306a36Sopenharmony_ci u32 efuse = mt7620_get_efuse(); 16562306a36Sopenharmony_ci unsigned char *name = NULL; 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_ci if (efuse & EFUSE_MT7688) { 16862306a36Sopenharmony_ci ralink_soc = MT762X_SOC_MT7688; 16962306a36Sopenharmony_ci name = "MT7688"; 17062306a36Sopenharmony_ci } else { 17162306a36Sopenharmony_ci ralink_soc = MT762X_SOC_MT7628AN; 17262306a36Sopenharmony_ci name = "MT7628AN"; 17362306a36Sopenharmony_ci } 17462306a36Sopenharmony_ci soc_info->compatible = "ralink,mt7628an-soc"; 17562306a36Sopenharmony_ci return name; 17662306a36Sopenharmony_ci } else { 17762306a36Sopenharmony_ci panic("mt762x: unknown SoC, n0:%08x n1:%08x\n", 17862306a36Sopenharmony_ci mt7620_get_soc_name0(), mt7620_get_soc_name1()); 17962306a36Sopenharmony_ci } 18062306a36Sopenharmony_ci} 18162306a36Sopenharmony_ci 18262306a36Sopenharmony_cistatic const char __init *mt7620_get_soc_id_name(void) 18362306a36Sopenharmony_ci{ 18462306a36Sopenharmony_ci if (ralink_soc == MT762X_SOC_MT7620A) 18562306a36Sopenharmony_ci return "mt7620a"; 18662306a36Sopenharmony_ci else if (ralink_soc == MT762X_SOC_MT7620N) 18762306a36Sopenharmony_ci return "mt7620n"; 18862306a36Sopenharmony_ci else if (ralink_soc == MT762X_SOC_MT7688) 18962306a36Sopenharmony_ci return "mt7688"; 19062306a36Sopenharmony_ci else if (ralink_soc == MT762X_SOC_MT7628AN) 19162306a36Sopenharmony_ci return "mt7628n"; 19262306a36Sopenharmony_ci else 19362306a36Sopenharmony_ci return "invalid"; 19462306a36Sopenharmony_ci} 19562306a36Sopenharmony_ci 19662306a36Sopenharmony_cistatic int __init mt7620_soc_dev_init(void) 19762306a36Sopenharmony_ci{ 19862306a36Sopenharmony_ci struct soc_device *soc_dev; 19962306a36Sopenharmony_ci struct soc_device_attribute *soc_dev_attr; 20062306a36Sopenharmony_ci 20162306a36Sopenharmony_ci soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL); 20262306a36Sopenharmony_ci if (!soc_dev_attr) 20362306a36Sopenharmony_ci return -ENOMEM; 20462306a36Sopenharmony_ci 20562306a36Sopenharmony_ci soc_dev_attr->family = "Ralink"; 20662306a36Sopenharmony_ci soc_dev_attr->soc_id = mt7620_get_soc_id_name(); 20762306a36Sopenharmony_ci 20862306a36Sopenharmony_ci soc_dev_attr->data = soc_info_ptr; 20962306a36Sopenharmony_ci 21062306a36Sopenharmony_ci soc_dev = soc_device_register(soc_dev_attr); 21162306a36Sopenharmony_ci if (IS_ERR(soc_dev)) { 21262306a36Sopenharmony_ci kfree(soc_dev_attr); 21362306a36Sopenharmony_ci return PTR_ERR(soc_dev); 21462306a36Sopenharmony_ci } 21562306a36Sopenharmony_ci 21662306a36Sopenharmony_ci return 0; 21762306a36Sopenharmony_ci} 21862306a36Sopenharmony_cidevice_initcall(mt7620_soc_dev_init); 21962306a36Sopenharmony_ci 22062306a36Sopenharmony_civoid __init prom_soc_init(struct ralink_soc_info *soc_info) 22162306a36Sopenharmony_ci{ 22262306a36Sopenharmony_ci const char *name = mt7620_get_soc_name(soc_info); 22362306a36Sopenharmony_ci u32 cfg0; 22462306a36Sopenharmony_ci u32 pmu0; 22562306a36Sopenharmony_ci u32 pmu1; 22662306a36Sopenharmony_ci 22762306a36Sopenharmony_ci snprintf(soc_info->sys_type, RAMIPS_SYS_TYPE_LEN, 22862306a36Sopenharmony_ci "MediaTek %s ver:%u eco:%u", 22962306a36Sopenharmony_ci name, mt7620_get_soc_ver(), mt7620_get_soc_eco()); 23062306a36Sopenharmony_ci 23162306a36Sopenharmony_ci cfg0 = __raw_readl(MT7620_SYSC_BASE + SYSC_REG_SYSTEM_CONFIG0); 23262306a36Sopenharmony_ci if (is_mt76x8()) { 23362306a36Sopenharmony_ci dram_type = cfg0 & DRAM_TYPE_MT7628_MASK; 23462306a36Sopenharmony_ci } else { 23562306a36Sopenharmony_ci dram_type = (cfg0 >> SYSCFG0_DRAM_TYPE_SHIFT) & 23662306a36Sopenharmony_ci SYSCFG0_DRAM_TYPE_MASK; 23762306a36Sopenharmony_ci if (dram_type == SYSCFG0_DRAM_TYPE_UNKNOWN) 23862306a36Sopenharmony_ci dram_type = SYSCFG0_DRAM_TYPE_SDRAM; 23962306a36Sopenharmony_ci } 24062306a36Sopenharmony_ci 24162306a36Sopenharmony_ci soc_info->mem_base = MT7620_DRAM_BASE; 24262306a36Sopenharmony_ci if (is_mt76x8()) 24362306a36Sopenharmony_ci mt7628_dram_init(soc_info); 24462306a36Sopenharmony_ci else 24562306a36Sopenharmony_ci mt7620_dram_init(soc_info); 24662306a36Sopenharmony_ci 24762306a36Sopenharmony_ci pmu0 = __raw_readl(MT7620_SYSC_BASE + PMU0_CFG); 24862306a36Sopenharmony_ci pmu1 = __raw_readl(MT7620_SYSC_BASE + PMU1_CFG); 24962306a36Sopenharmony_ci 25062306a36Sopenharmony_ci pr_info("Analog PMU set to %s control\n", 25162306a36Sopenharmony_ci (pmu0 & PMU_SW_SET) ? ("sw") : ("hw")); 25262306a36Sopenharmony_ci pr_info("Digital PMU set to %s control\n", 25362306a36Sopenharmony_ci (pmu1 & DIG_SW_SEL) ? ("sw") : ("hw")); 25462306a36Sopenharmony_ci 25562306a36Sopenharmony_ci soc_info_ptr = soc_info; 25662306a36Sopenharmony_ci} 257