summaryrefslogtreecommitdiffstats
path: root/arch/mips/ralink/mt7620.c
blob: 672249a13a09a409bc54cc9d3d8704b70f57f624 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
// 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;
}