1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * 4 * Parts of this file are based on Ralink's 2.6.21 BSP 5 * 6 * Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org> 7 * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> 8 * Copyright (C) 2013 John Crispin <john@phrozen.org> 9 */ 10 11 #include <linux/kernel.h> 12 #include <linux/init.h> 13 #include <linux/bug.h> 14 #include <linux/slab.h> 15 #include <linux/sys_soc.h> 16 17 #include <asm/io.h> 18 #include <asm/mipsregs.h> 19 #include <asm/mach-ralink/ralink_regs.h> 20 #include <asm/mach-ralink/rt305x.h> 21 22 #include "common.h" 23 24 static struct ralink_soc_info *soc_info_ptr; 25 26 static unsigned long rt5350_get_mem_size(void) 27 { 28 unsigned long ret; 29 u32 t; 30 31 t = __raw_readl(RT305X_SYSC_BASE + SYSC_REG_SYSTEM_CONFIG); 32 t = (t >> RT5350_SYSCFG0_DRAM_SIZE_SHIFT) & 33 RT5350_SYSCFG0_DRAM_SIZE_MASK; 34 35 switch (t) { 36 case RT5350_SYSCFG0_DRAM_SIZE_2M: 37 ret = 2; 38 break; 39 case RT5350_SYSCFG0_DRAM_SIZE_8M: 40 ret = 8; 41 break; 42 case RT5350_SYSCFG0_DRAM_SIZE_16M: 43 ret = 16; 44 break; 45 case RT5350_SYSCFG0_DRAM_SIZE_32M: 46 ret = 32; 47 break; 48 case RT5350_SYSCFG0_DRAM_SIZE_64M: 49 ret = 64; 50 break; 51 default: 52 panic("rt5350: invalid DRAM size: %u", t); 53 break; 54 } 55 56 return ret; 57 } 58 59 static unsigned int __init rt305x_get_soc_name0(void) 60 { 61 return __raw_readl(RT305X_SYSC_BASE + SYSC_REG_CHIP_NAME0); 62 } 63 64 static unsigned int __init rt305x_get_soc_name1(void) 65 { 66 return __raw_readl(RT305X_SYSC_BASE + SYSC_REG_CHIP_NAME1); 67 } 68 69 static bool __init rt3052_soc_valid(void) 70 { 71 if (rt305x_get_soc_name0() == RT3052_CHIP_NAME0 && 72 rt305x_get_soc_name1() == RT3052_CHIP_NAME1) 73 return true; 74 else 75 return false; 76 } 77 78 static bool __init rt3350_soc_valid(void) 79 { 80 if (rt305x_get_soc_name0() == RT3350_CHIP_NAME0 && 81 rt305x_get_soc_name1() == RT3350_CHIP_NAME1) 82 return true; 83 else 84 return false; 85 } 86 87 static bool __init rt3352_soc_valid(void) 88 { 89 if (rt305x_get_soc_name0() == RT3352_CHIP_NAME0 && 90 rt305x_get_soc_name1() == RT3352_CHIP_NAME1) 91 return true; 92 else 93 return false; 94 } 95 96 static bool __init rt5350_soc_valid(void) 97 { 98 if (rt305x_get_soc_name0() == RT5350_CHIP_NAME0 && 99 rt305x_get_soc_name1() == RT5350_CHIP_NAME1) 100 return true; 101 else 102 return false; 103 } 104 105 static const char __init *rt305x_get_soc_name(struct ralink_soc_info *soc_info) 106 { 107 if (rt3052_soc_valid()) { 108 unsigned long icache_sets; 109 110 icache_sets = (read_c0_config1() >> 22) & 7; 111 if (icache_sets == 1) { 112 ralink_soc = RT305X_SOC_RT3050; 113 soc_info->compatible = "ralink,rt3050-soc"; 114 return "RT3050"; 115 } else { 116 ralink_soc = RT305X_SOC_RT3052; 117 soc_info->compatible = "ralink,rt3052-soc"; 118 return "RT3052"; 119 } 120 } else if (rt3350_soc_valid()) { 121 ralink_soc = RT305X_SOC_RT3350; 122 soc_info->compatible = "ralink,rt3350-soc"; 123 return "RT3350"; 124 } else if (rt3352_soc_valid()) { 125 ralink_soc = RT305X_SOC_RT3352; 126 soc_info->compatible = "ralink,rt3352-soc"; 127 return "RT3352"; 128 } else if (rt5350_soc_valid()) { 129 ralink_soc = RT305X_SOC_RT5350; 130 soc_info->compatible = "ralink,rt5350-soc"; 131 return "RT5350"; 132 } else { 133 panic("rt305x: unknown SoC, n0:%08x n1:%08x", 134 rt305x_get_soc_name0(), rt305x_get_soc_name1()); 135 } 136 } 137 138 static unsigned int __init rt305x_get_soc_id(void) 139 { 140 return __raw_readl(RT305X_SYSC_BASE + SYSC_REG_CHIP_ID); 141 } 142 143 static unsigned int __init rt305x_get_soc_ver(void) 144 { 145 return (rt305x_get_soc_id() >> CHIP_ID_ID_SHIFT) & CHIP_ID_ID_MASK; 146 } 147 148 static unsigned int __init rt305x_get_soc_rev(void) 149 { 150 return (rt305x_get_soc_id() & CHIP_ID_REV_MASK); 151 } 152 153 static const char __init *rt305x_get_soc_id_name(void) 154 { 155 if (soc_is_rt3050()) 156 return "rt3050"; 157 else if (soc_is_rt3052()) 158 return "rt3052"; 159 else if (soc_is_rt3350()) 160 return "rt3350"; 161 else if (soc_is_rt3352()) 162 return "rt3352"; 163 else if (soc_is_rt5350()) 164 return "rt5350"; 165 else 166 return "invalid"; 167 } 168 169 static int __init rt305x_soc_dev_init(void) 170 { 171 struct soc_device *soc_dev; 172 struct soc_device_attribute *soc_dev_attr; 173 174 soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL); 175 if (!soc_dev_attr) 176 return -ENOMEM; 177 178 soc_dev_attr->family = "Ralink"; 179 soc_dev_attr->soc_id = rt305x_get_soc_id_name(); 180 181 soc_dev_attr->data = soc_info_ptr; 182 183 soc_dev = soc_device_register(soc_dev_attr); 184 if (IS_ERR(soc_dev)) { 185 kfree(soc_dev_attr); 186 return PTR_ERR(soc_dev); 187 } 188 189 return 0; 190 } 191 device_initcall(rt305x_soc_dev_init); 192 193 void __init prom_soc_init(struct ralink_soc_info *soc_info) 194 { 195 const char *name = rt305x_get_soc_name(soc_info); 196 197 snprintf(soc_info->sys_type, RAMIPS_SYS_TYPE_LEN, 198 "Ralink %s id:%u rev:%u", 199 name, 200 rt305x_get_soc_ver(), 201 rt305x_get_soc_rev()); 202 203 soc_info->mem_base = RT305X_SDRAM_BASE; 204 if (soc_is_rt5350()) { 205 soc_info->mem_size = rt5350_get_mem_size(); 206 } else if (soc_is_rt305x() || soc_is_rt3350()) { 207 soc_info->mem_size_min = RT305X_MEM_SIZE_MIN; 208 soc_info->mem_size_max = RT305X_MEM_SIZE_MAX; 209 } else if (soc_is_rt3352()) { 210 soc_info->mem_size_min = RT3352_MEM_SIZE_MIN; 211 soc_info->mem_size_max = RT3352_MEM_SIZE_MAX; 212 } 213 214 soc_info_ptr = soc_info; 215 } 216
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.