| // SPDX-License-Identifier: GPL-2.0-only |
| /* |
| * |
| * Parts of this file are based on Ralink's 2.6.21 BSP |
| * |
| * Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org> |
| * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> |
| * Copyright (C) 2013 John Crispin <john@phrozen.org> |
| */ |
| |
| #include <linux/kernel.h> |
| #include <linux/init.h> |
| #include <linux/bug.h> |
| #include <linux/slab.h> |
| #include <linux/sys_soc.h> |
| |
| #include <asm/mipsregs.h> |
| #include <asm/mach-ralink/ralink_regs.h> |
| #include <asm/mach-ralink/mt7620.h> |
| |
| #include "common.h" |
| |
| /* analog */ |
| #define PMU0_CFG 0x88 |
| #define PMU_SW_SET BIT(28) |
| #define A_DCDC_EN BIT(24) |
| #define A_SSC_PERI BIT(19) |
| #define A_SSC_GEN BIT(18) |
| #define A_SSC_M 0x3 |
| #define A_SSC_S 16 |
| #define A_DLY_M 0x7 |
| #define A_DLY_S 8 |
| #define A_VTUNE_M 0xff |
| |
| /* digital */ |
| #define PMU1_CFG 0x8C |
| #define DIG_SW_SEL BIT(25) |
| |
| /* EFUSE bits */ |
| #define EFUSE_MT7688 0x100000 |
| |
| /* DRAM type bit */ |
| #define DRAM_TYPE_MT7628_MASK 0x1 |
| |
| /* does the board have sdram or ddram */ |
| static int dram_type; |
| |
| static struct ralink_soc_info *soc_info_ptr; |
| |
| static __init void |
| mt7620_dram_init(struct ralink_soc_info *soc_info) |
| { |
| switch (dram_type) { |
| case SYSCFG0_DRAM_TYPE_SDRAM: |
| pr_info("Board has SDRAM\n"); |
| soc_info->mem_size_min = MT7620_SDRAM_SIZE_MIN; |
| soc_info->mem_size_max = MT7620_SDRAM_SIZE_MAX; |
| break; |
| |
| case SYSCFG0_DRAM_TYPE_DDR1: |
| pr_info("Board has DDR1\n"); |
| soc_info->mem_size_min = MT7620_DDR1_SIZE_MIN; |
| soc_info->mem_size_max = MT7620_DDR1_SIZE_MAX; |
| break; |
| |
| case SYSCFG0_DRAM_TYPE_DDR2: |
| pr_info("Board has DDR2\n"); |
| soc_info->mem_size_min = MT7620_DDR2_SIZE_MIN; |
| soc_info->mem_size_max = MT7620_DDR2_SIZE_MAX; |
| break; |
| default: |
| BUG(); |
| } |
| } |
| |
| static __init void |
| mt7628_dram_init(struct ralink_soc_info *soc_info) |
| { |
| switch (dram_type) { |
| case SYSCFG0_DRAM_TYPE_DDR1_MT7628: |
| pr_info("Board has DDR1\n"); |
| soc_info->mem_size_min = MT7620_DDR1_SIZE_MIN; |
| soc_info->mem_size_max = MT7620_DDR1_SIZE_MAX; |
| break; |
| |
| case SYSCFG0_DRAM_TYPE_DDR2_MT7628: |
| pr_info("Board has DDR2\n"); |
| soc_info->mem_size_min = MT7620_DDR2_SIZE_MIN; |
| soc_info->mem_size_max = MT7620_DDR2_SIZE_MAX; |
| break; |
| default: |
| BUG(); |
| } |
| } |
| |
| static unsigned int __init mt7620_get_soc_name0(void) |
| { |
| return __raw_readl(MT7620_SYSC_BASE + SYSC_REG_CHIP_NAME0); |
| } |
| |
| static unsigned int __init mt7620_get_soc_name1(void) |
| { |
| return __raw_readl(MT7620_SYSC_BASE + SYSC_REG_CHIP_NAME1); |
| } |
| |
| static bool __init mt7620_soc_valid(void) |
| { |
| if (mt7620_get_soc_name0() == MT7620_CHIP_NAME0 && |
| mt7620_get_soc_name1() == MT7620_CHIP_NAME1) |
| return true; |
| else |
| return false; |
| } |
| |
| static bool __init mt7628_soc_valid(void) |
| { |
| if (mt7620_get_soc_name0() == MT7620_CHIP_NAME0 && |
| mt7620_get_soc_name1() == MT7628_CHIP_NAME1) |
| return true; |
| else |
| return false; |
| } |
| |
| static unsigned int __init mt7620_get_rev(void) |
| { |
| return __raw_readl(MT7620_SYSC_BASE + SYSC_REG_CHIP_REV); |
| } |
| |
| static unsigned int __init mt7620_get_bga(void) |
| { |
| return (mt7620_get_rev() >> CHIP_REV_PKG_SHIFT) & CHIP_REV_PKG_MASK; |
| } |
| |
| static unsigned int __init mt7620_get_efuse(void) |
| { |
| return __raw_readl(MT7620_SYSC_BASE + SYSC_REG_EFUSE_CFG); |
| } |
| |
| static unsigned int __init mt7620_get_soc_ver(void) |
| { |
| return (mt7620_get_rev() >> CHIP_REV_VER_SHIFT) & CHIP_REV_VER_MASK; |
| } |
| |
| static unsigned int __init mt7620_get_soc_eco(void) |
| { |
| return (mt7620_get_rev() & CHIP_REV_ECO_MASK); |
| } |
| |
| static const char __init *mt7620_get_soc_name(struct ralink_soc_info *soc_info) |
| { |
| if (mt7620_soc_valid()) { |
| u32 bga = mt7620_get_bga(); |
| |
| if (bga) { |
| ralink_soc = MT762X_SOC_MT7620A; |
| soc_info->compatible = "ralink,mt7620a-soc"; |
| return "MT7620A"; |
| } else { |
| ralink_soc = MT762X_SOC_MT7620N; |
| soc_info->compatible = "ralink,mt7620n-soc"; |
| return "MT7620N"; |
| } |
| } else if (mt7628_soc_valid()) { |
| u32 efuse = mt7620_get_efuse(); |
| unsigned char *name = NULL; |
| |
| if (efuse & EFUSE_MT7688) { |
| ralink_soc = MT762X_SOC_MT7688; |
| name = "MT7688"; |
| } else { |
| ralink_soc = MT762X_SOC_MT7628AN; |
| name = "MT7628AN"; |
| } |
| soc_info->compatible = "ralink,mt7628an-soc"; |
| return name; |
| } else { |
| panic("mt762x: unknown SoC, n0:%08x n1:%08x\n", |
| mt7620_get_soc_name0(), mt7620_get_soc_name1()); |
| } |
| } |
| |
| static const char __init *mt7620_get_soc_id_name(void) |
| { |
| if (ralink_soc == MT762X_SOC_MT7620A) |
| return "mt7620a"; |
| else if (ralink_soc == MT762X_SOC_MT7620N) |
| return "mt7620n"; |
| else if (ralink_soc == MT762X_SOC_MT7688) |
| return "mt7688"; |
| else if (ralink_soc == MT762X_SOC_MT7628AN) |
| return "mt7628n"; |
| else |
| return "invalid"; |
| } |
| |
| static int __init mt7620_soc_dev_init(void) |
| { |
| struct soc_device *soc_dev; |
| struct soc_device_attribute *soc_dev_attr; |
| |
| soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL); |
| if (!soc_dev_attr) |
| return -ENOMEM; |
| |
| soc_dev_attr->family = "Ralink"; |
| soc_dev_attr->soc_id = mt7620_get_soc_id_name(); |
| |
| soc_dev_attr->data = soc_info_ptr; |
| |
| soc_dev = soc_device_register(soc_dev_attr); |
| if (IS_ERR(soc_dev)) { |
| kfree(soc_dev_attr); |
| return PTR_ERR(soc_dev); |
| } |
| |
| return 0; |
| } |
| device_initcall(mt7620_soc_dev_init); |
| |
| void __init prom_soc_init(struct ralink_soc_info *soc_info) |
| { |
| const char *name = mt7620_get_soc_name(soc_info); |
| u32 cfg0; |
| u32 pmu0; |
| u32 pmu1; |
| |
| snprintf(soc_info->sys_type, RAMIPS_SYS_TYPE_LEN, |
| "MediaTek %s ver:%u eco:%u", |
| name, mt7620_get_soc_ver(), mt7620_get_soc_eco()); |
| |
| cfg0 = __raw_readl(MT7620_SYSC_BASE + SYSC_REG_SYSTEM_CONFIG0); |
| if (is_mt76x8()) { |
| dram_type = cfg0 & DRAM_TYPE_MT7628_MASK; |
| } else { |
| dram_type = (cfg0 >> SYSCFG0_DRAM_TYPE_SHIFT) & |
| SYSCFG0_DRAM_TYPE_MASK; |
| if (dram_type == SYSCFG0_DRAM_TYPE_UNKNOWN) |
| dram_type = SYSCFG0_DRAM_TYPE_SDRAM; |
| } |
| |
| soc_info->mem_base = MT7620_DRAM_BASE; |
| if (is_mt76x8()) |
| mt7628_dram_init(soc_info); |
| else |
| mt7620_dram_init(soc_info); |
| |
| pmu0 = __raw_readl(MT7620_SYSC_BASE + PMU0_CFG); |
| pmu1 = __raw_readl(MT7620_SYSC_BASE + PMU1_CFG); |
| |
| pr_info("Analog PMU set to %s control\n", |
| (pmu0 & PMU_SW_SET) ? ("sw") : ("hw")); |
| pr_info("Digital PMU set to %s control\n", |
| (pmu1 & DIG_SW_SEL) ? ("sw") : ("hw")); |
| |
| soc_info_ptr = soc_info; |
| } |