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/io.h>
1862306a36Sopenharmony_ci#include <asm/mipsregs.h>
1962306a36Sopenharmony_ci#include <asm/mach-ralink/ralink_regs.h>
2062306a36Sopenharmony_ci#include <asm/mach-ralink/rt305x.h>
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_ci#include "common.h"
2362306a36Sopenharmony_ci
2462306a36Sopenharmony_cistatic struct ralink_soc_info *soc_info_ptr;
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_cistatic unsigned long rt5350_get_mem_size(void)
2762306a36Sopenharmony_ci{
2862306a36Sopenharmony_ci	unsigned long ret;
2962306a36Sopenharmony_ci	u32 t;
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_ci	t = __raw_readl(RT305X_SYSC_BASE + SYSC_REG_SYSTEM_CONFIG);
3262306a36Sopenharmony_ci	t = (t >> RT5350_SYSCFG0_DRAM_SIZE_SHIFT) &
3362306a36Sopenharmony_ci		RT5350_SYSCFG0_DRAM_SIZE_MASK;
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_ci	switch (t) {
3662306a36Sopenharmony_ci	case RT5350_SYSCFG0_DRAM_SIZE_2M:
3762306a36Sopenharmony_ci		ret = 2;
3862306a36Sopenharmony_ci		break;
3962306a36Sopenharmony_ci	case RT5350_SYSCFG0_DRAM_SIZE_8M:
4062306a36Sopenharmony_ci		ret = 8;
4162306a36Sopenharmony_ci		break;
4262306a36Sopenharmony_ci	case RT5350_SYSCFG0_DRAM_SIZE_16M:
4362306a36Sopenharmony_ci		ret = 16;
4462306a36Sopenharmony_ci		break;
4562306a36Sopenharmony_ci	case RT5350_SYSCFG0_DRAM_SIZE_32M:
4662306a36Sopenharmony_ci		ret = 32;
4762306a36Sopenharmony_ci		break;
4862306a36Sopenharmony_ci	case RT5350_SYSCFG0_DRAM_SIZE_64M:
4962306a36Sopenharmony_ci		ret = 64;
5062306a36Sopenharmony_ci		break;
5162306a36Sopenharmony_ci	default:
5262306a36Sopenharmony_ci		panic("rt5350: invalid DRAM size: %u", t);
5362306a36Sopenharmony_ci		break;
5462306a36Sopenharmony_ci	}
5562306a36Sopenharmony_ci
5662306a36Sopenharmony_ci	return ret;
5762306a36Sopenharmony_ci}
5862306a36Sopenharmony_ci
5962306a36Sopenharmony_cistatic unsigned int __init rt305x_get_soc_name0(void)
6062306a36Sopenharmony_ci{
6162306a36Sopenharmony_ci	return __raw_readl(RT305X_SYSC_BASE + SYSC_REG_CHIP_NAME0);
6262306a36Sopenharmony_ci}
6362306a36Sopenharmony_ci
6462306a36Sopenharmony_cistatic unsigned int __init rt305x_get_soc_name1(void)
6562306a36Sopenharmony_ci{
6662306a36Sopenharmony_ci	return __raw_readl(RT305X_SYSC_BASE + SYSC_REG_CHIP_NAME1);
6762306a36Sopenharmony_ci}
6862306a36Sopenharmony_ci
6962306a36Sopenharmony_cistatic bool __init rt3052_soc_valid(void)
7062306a36Sopenharmony_ci{
7162306a36Sopenharmony_ci	if (rt305x_get_soc_name0() == RT3052_CHIP_NAME0 &&
7262306a36Sopenharmony_ci	    rt305x_get_soc_name1() == RT3052_CHIP_NAME1)
7362306a36Sopenharmony_ci		return true;
7462306a36Sopenharmony_ci	else
7562306a36Sopenharmony_ci		return false;
7662306a36Sopenharmony_ci}
7762306a36Sopenharmony_ci
7862306a36Sopenharmony_cistatic bool __init rt3350_soc_valid(void)
7962306a36Sopenharmony_ci{
8062306a36Sopenharmony_ci	if (rt305x_get_soc_name0() == RT3350_CHIP_NAME0 &&
8162306a36Sopenharmony_ci	    rt305x_get_soc_name1() == RT3350_CHIP_NAME1)
8262306a36Sopenharmony_ci		return true;
8362306a36Sopenharmony_ci	else
8462306a36Sopenharmony_ci		return false;
8562306a36Sopenharmony_ci}
8662306a36Sopenharmony_ci
8762306a36Sopenharmony_cistatic bool __init rt3352_soc_valid(void)
8862306a36Sopenharmony_ci{
8962306a36Sopenharmony_ci	if (rt305x_get_soc_name0() == RT3352_CHIP_NAME0 &&
9062306a36Sopenharmony_ci	    rt305x_get_soc_name1() == RT3352_CHIP_NAME1)
9162306a36Sopenharmony_ci		return true;
9262306a36Sopenharmony_ci	else
9362306a36Sopenharmony_ci		return false;
9462306a36Sopenharmony_ci}
9562306a36Sopenharmony_ci
9662306a36Sopenharmony_cistatic bool __init rt5350_soc_valid(void)
9762306a36Sopenharmony_ci{
9862306a36Sopenharmony_ci	if (rt305x_get_soc_name0() == RT5350_CHIP_NAME0 &&
9962306a36Sopenharmony_ci	    rt305x_get_soc_name1() == RT5350_CHIP_NAME1)
10062306a36Sopenharmony_ci		return true;
10162306a36Sopenharmony_ci	else
10262306a36Sopenharmony_ci		return false;
10362306a36Sopenharmony_ci}
10462306a36Sopenharmony_ci
10562306a36Sopenharmony_cistatic const char __init *rt305x_get_soc_name(struct ralink_soc_info *soc_info)
10662306a36Sopenharmony_ci{
10762306a36Sopenharmony_ci	if (rt3052_soc_valid()) {
10862306a36Sopenharmony_ci		unsigned long icache_sets;
10962306a36Sopenharmony_ci
11062306a36Sopenharmony_ci		icache_sets = (read_c0_config1() >> 22) & 7;
11162306a36Sopenharmony_ci		if (icache_sets == 1) {
11262306a36Sopenharmony_ci			ralink_soc = RT305X_SOC_RT3050;
11362306a36Sopenharmony_ci			soc_info->compatible = "ralink,rt3050-soc";
11462306a36Sopenharmony_ci			return "RT3050";
11562306a36Sopenharmony_ci		} else {
11662306a36Sopenharmony_ci			ralink_soc = RT305X_SOC_RT3052;
11762306a36Sopenharmony_ci			soc_info->compatible = "ralink,rt3052-soc";
11862306a36Sopenharmony_ci			return "RT3052";
11962306a36Sopenharmony_ci		}
12062306a36Sopenharmony_ci	} else if (rt3350_soc_valid()) {
12162306a36Sopenharmony_ci		ralink_soc = RT305X_SOC_RT3350;
12262306a36Sopenharmony_ci		soc_info->compatible = "ralink,rt3350-soc";
12362306a36Sopenharmony_ci		return "RT3350";
12462306a36Sopenharmony_ci	} else if (rt3352_soc_valid()) {
12562306a36Sopenharmony_ci		ralink_soc = RT305X_SOC_RT3352;
12662306a36Sopenharmony_ci		soc_info->compatible = "ralink,rt3352-soc";
12762306a36Sopenharmony_ci		return "RT3352";
12862306a36Sopenharmony_ci	} else if (rt5350_soc_valid()) {
12962306a36Sopenharmony_ci		ralink_soc = RT305X_SOC_RT5350;
13062306a36Sopenharmony_ci		soc_info->compatible = "ralink,rt5350-soc";
13162306a36Sopenharmony_ci		return "RT5350";
13262306a36Sopenharmony_ci	} else {
13362306a36Sopenharmony_ci		panic("rt305x: unknown SoC, n0:%08x n1:%08x",
13462306a36Sopenharmony_ci		      rt305x_get_soc_name0(), rt305x_get_soc_name1());
13562306a36Sopenharmony_ci	}
13662306a36Sopenharmony_ci}
13762306a36Sopenharmony_ci
13862306a36Sopenharmony_cistatic unsigned int __init rt305x_get_soc_id(void)
13962306a36Sopenharmony_ci{
14062306a36Sopenharmony_ci	return __raw_readl(RT305X_SYSC_BASE + SYSC_REG_CHIP_ID);
14162306a36Sopenharmony_ci}
14262306a36Sopenharmony_ci
14362306a36Sopenharmony_cistatic unsigned int __init rt305x_get_soc_ver(void)
14462306a36Sopenharmony_ci{
14562306a36Sopenharmony_ci	return (rt305x_get_soc_id() >> CHIP_ID_ID_SHIFT) & CHIP_ID_ID_MASK;
14662306a36Sopenharmony_ci}
14762306a36Sopenharmony_ci
14862306a36Sopenharmony_cistatic unsigned int __init rt305x_get_soc_rev(void)
14962306a36Sopenharmony_ci{
15062306a36Sopenharmony_ci	return (rt305x_get_soc_id() & CHIP_ID_REV_MASK);
15162306a36Sopenharmony_ci}
15262306a36Sopenharmony_ci
15362306a36Sopenharmony_cistatic const char __init *rt305x_get_soc_id_name(void)
15462306a36Sopenharmony_ci{
15562306a36Sopenharmony_ci	if (soc_is_rt3050())
15662306a36Sopenharmony_ci		return "rt3050";
15762306a36Sopenharmony_ci	else if (soc_is_rt3052())
15862306a36Sopenharmony_ci		return "rt3052";
15962306a36Sopenharmony_ci	else if (soc_is_rt3350())
16062306a36Sopenharmony_ci		return "rt3350";
16162306a36Sopenharmony_ci	else if (soc_is_rt3352())
16262306a36Sopenharmony_ci		return "rt3352";
16362306a36Sopenharmony_ci	else if (soc_is_rt5350())
16462306a36Sopenharmony_ci		return "rt5350";
16562306a36Sopenharmony_ci	else
16662306a36Sopenharmony_ci		return "invalid";
16762306a36Sopenharmony_ci}
16862306a36Sopenharmony_ci
16962306a36Sopenharmony_cistatic int __init rt305x_soc_dev_init(void)
17062306a36Sopenharmony_ci{
17162306a36Sopenharmony_ci	struct soc_device *soc_dev;
17262306a36Sopenharmony_ci	struct soc_device_attribute *soc_dev_attr;
17362306a36Sopenharmony_ci
17462306a36Sopenharmony_ci	soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
17562306a36Sopenharmony_ci	if (!soc_dev_attr)
17662306a36Sopenharmony_ci		return -ENOMEM;
17762306a36Sopenharmony_ci
17862306a36Sopenharmony_ci	soc_dev_attr->family = "Ralink";
17962306a36Sopenharmony_ci	soc_dev_attr->soc_id = rt305x_get_soc_id_name();
18062306a36Sopenharmony_ci
18162306a36Sopenharmony_ci	soc_dev_attr->data = soc_info_ptr;
18262306a36Sopenharmony_ci
18362306a36Sopenharmony_ci	soc_dev = soc_device_register(soc_dev_attr);
18462306a36Sopenharmony_ci	if (IS_ERR(soc_dev)) {
18562306a36Sopenharmony_ci		kfree(soc_dev_attr);
18662306a36Sopenharmony_ci		return PTR_ERR(soc_dev);
18762306a36Sopenharmony_ci	}
18862306a36Sopenharmony_ci
18962306a36Sopenharmony_ci	return 0;
19062306a36Sopenharmony_ci}
19162306a36Sopenharmony_cidevice_initcall(rt305x_soc_dev_init);
19262306a36Sopenharmony_ci
19362306a36Sopenharmony_civoid __init prom_soc_init(struct ralink_soc_info *soc_info)
19462306a36Sopenharmony_ci{
19562306a36Sopenharmony_ci	const char *name = rt305x_get_soc_name(soc_info);
19662306a36Sopenharmony_ci
19762306a36Sopenharmony_ci	snprintf(soc_info->sys_type, RAMIPS_SYS_TYPE_LEN,
19862306a36Sopenharmony_ci		"Ralink %s id:%u rev:%u",
19962306a36Sopenharmony_ci		name,
20062306a36Sopenharmony_ci		rt305x_get_soc_ver(),
20162306a36Sopenharmony_ci		rt305x_get_soc_rev());
20262306a36Sopenharmony_ci
20362306a36Sopenharmony_ci	soc_info->mem_base = RT305X_SDRAM_BASE;
20462306a36Sopenharmony_ci	if (soc_is_rt5350()) {
20562306a36Sopenharmony_ci		soc_info->mem_size = rt5350_get_mem_size();
20662306a36Sopenharmony_ci	} else if (soc_is_rt305x() || soc_is_rt3350()) {
20762306a36Sopenharmony_ci		soc_info->mem_size_min = RT305X_MEM_SIZE_MIN;
20862306a36Sopenharmony_ci		soc_info->mem_size_max = RT305X_MEM_SIZE_MAX;
20962306a36Sopenharmony_ci	} else if (soc_is_rt3352()) {
21062306a36Sopenharmony_ci		soc_info->mem_size_min = RT3352_MEM_SIZE_MIN;
21162306a36Sopenharmony_ci		soc_info->mem_size_max = RT3352_MEM_SIZE_MAX;
21262306a36Sopenharmony_ci	}
21362306a36Sopenharmony_ci
21462306a36Sopenharmony_ci	soc_info_ptr = soc_info;
21562306a36Sopenharmony_ci}
216