Blame view

arch/mips/bcm63xx/cpu.c 6.39 KB
e7300d04b   Maxime Bizon   MIPS: BCM63xx: Ad...
1
2
3
4
5
6
7
8
9
10
11
12
  /*
   * This file is subject to the terms and conditions of the GNU General Public
   * License.  See the file "COPYING" in the main directory of this archive
   * for more details.
   *
   * Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr>
   * Copyright (C) 2009 Florian Fainelli <florian@openwrt.org>
   */
  
  #include <linux/kernel.h>
  #include <linux/module.h>
  #include <linux/cpu.h>
602977b0d   Kevin Cernekee   MIPS: Decouple BM...
13
  #include <asm/cpu.h>
2b5b9b786   Florian Fainelli   MIPS: bcm63xx: Se...
14
  #include <asm/cpu-info.h>
602977b0d   Kevin Cernekee   MIPS: Decouple BM...
15
  #include <asm/mipsregs.h>
e7300d04b   Maxime Bizon   MIPS: BCM63xx: Ad...
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
  #include <bcm63xx_cpu.h>
  #include <bcm63xx_regs.h>
  #include <bcm63xx_io.h>
  #include <bcm63xx_irq.h>
  
  const unsigned long *bcm63xx_regs_base;
  EXPORT_SYMBOL(bcm63xx_regs_base);
  
  const int *bcm63xx_irqs;
  EXPORT_SYMBOL(bcm63xx_irqs);
  
  static u16 bcm63xx_cpu_id;
  static u16 bcm63xx_cpu_rev;
  static unsigned int bcm63xx_cpu_freq;
  static unsigned int bcm63xx_memory_size;
ec68c5206   Maxime Bizon   MIPS: BCM63XX: Cl...
31
32
  static const unsigned long bcm6338_regs_base[] = {
  	__GEN_CPU_REGS_TABLE(6338)
e7300d04b   Maxime Bizon   MIPS: BCM63xx: Ad...
33
  };
ec68c5206   Maxime Bizon   MIPS: BCM63XX: Cl...
34
35
  static const int bcm6338_irqs[] = {
  	__GEN_CPU_IRQ_TABLE(6338)
e7300d04b   Maxime Bizon   MIPS: BCM63xx: Ad...
36
  };
ec68c5206   Maxime Bizon   MIPS: BCM63XX: Cl...
37
38
  static const unsigned long bcm6345_regs_base[] = {
  	__GEN_CPU_REGS_TABLE(6345)
e7300d04b   Maxime Bizon   MIPS: BCM63xx: Ad...
39
  };
ec68c5206   Maxime Bizon   MIPS: BCM63XX: Cl...
40
41
  static const int bcm6345_irqs[] = {
  	__GEN_CPU_IRQ_TABLE(6345)
e7300d04b   Maxime Bizon   MIPS: BCM63xx: Ad...
42
  };
ec68c5206   Maxime Bizon   MIPS: BCM63XX: Cl...
43
44
  static const unsigned long bcm6348_regs_base[] = {
  	__GEN_CPU_REGS_TABLE(6348)
e7300d04b   Maxime Bizon   MIPS: BCM63xx: Ad...
45
  };
ec68c5206   Maxime Bizon   MIPS: BCM63XX: Cl...
46
47
  static const int bcm6348_irqs[] = {
  	__GEN_CPU_IRQ_TABLE(6348)
e7300d04b   Maxime Bizon   MIPS: BCM63xx: Ad...
48
  };
ec68c5206   Maxime Bizon   MIPS: BCM63XX: Cl...
49
50
  static const unsigned long bcm6358_regs_base[] = {
  	__GEN_CPU_REGS_TABLE(6358)
e7300d04b   Maxime Bizon   MIPS: BCM63xx: Ad...
51
  };
ec68c5206   Maxime Bizon   MIPS: BCM63XX: Cl...
52
53
  static const int bcm6358_irqs[] = {
  	__GEN_CPU_IRQ_TABLE(6358)
e7300d04b   Maxime Bizon   MIPS: BCM63xx: Ad...
54
  };
04712f3ff   Maxime Bizon   MIPS: BCM63XX: Ad...
55
56
57
58
59
60
61
62
  static const unsigned long bcm6368_regs_base[] = {
  	__GEN_CPU_REGS_TABLE(6368)
  };
  
  static const int bcm6368_irqs[] = {
  	__GEN_CPU_IRQ_TABLE(6368)
  
  };
e7300d04b   Maxime Bizon   MIPS: BCM63xx: Ad...
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
  u16 __bcm63xx_get_cpu_id(void)
  {
  	return bcm63xx_cpu_id;
  }
  
  EXPORT_SYMBOL(__bcm63xx_get_cpu_id);
  
  u16 bcm63xx_get_cpu_rev(void)
  {
  	return bcm63xx_cpu_rev;
  }
  
  EXPORT_SYMBOL(bcm63xx_get_cpu_rev);
  
  unsigned int bcm63xx_get_cpu_freq(void)
  {
  	return bcm63xx_cpu_freq;
  }
  
  unsigned int bcm63xx_get_memory_size(void)
  {
  	return bcm63xx_memory_size;
  }
  
  static unsigned int detect_cpu_clock(void)
  {
04712f3ff   Maxime Bizon   MIPS: BCM63XX: Ad...
89
90
91
  	switch (bcm63xx_get_cpu_id()) {
  	case BCM6338_CPU_ID:
  		/* BCM6338 has a fixed 240 Mhz frequency */
e7300d04b   Maxime Bizon   MIPS: BCM63xx: Ad...
92
  		return 240000000;
04712f3ff   Maxime Bizon   MIPS: BCM63XX: Ad...
93
94
  	case BCM6345_CPU_ID:
  		/* BCM6345 has a fixed 140Mhz frequency */
e7300d04b   Maxime Bizon   MIPS: BCM63xx: Ad...
95
  		return 140000000;
04712f3ff   Maxime Bizon   MIPS: BCM63XX: Ad...
96
97
98
  	case BCM6348_CPU_ID:
  	{
  		unsigned int tmp, n1, n2, m1;
e7300d04b   Maxime Bizon   MIPS: BCM63xx: Ad...
99
100
101
102
103
104
105
106
  		/* 16MHz * (N1 + 1) * (N2 + 2) / (M1_CPU + 1) */
  		tmp = bcm_perf_readl(PERF_MIPSPLLCTL_REG);
  		n1 = (tmp & MIPSPLLCTL_N1_MASK) >> MIPSPLLCTL_N1_SHIFT;
  		n2 = (tmp & MIPSPLLCTL_N2_MASK) >> MIPSPLLCTL_N2_SHIFT;
  		m1 = (tmp & MIPSPLLCTL_M1CPU_MASK) >> MIPSPLLCTL_M1CPU_SHIFT;
  		n1 += 1;
  		n2 += 2;
  		m1 += 1;
04712f3ff   Maxime Bizon   MIPS: BCM63XX: Ad...
107
  		return (16 * 1000000 * n1 * n2) / m1;
e7300d04b   Maxime Bizon   MIPS: BCM63xx: Ad...
108
  	}
04712f3ff   Maxime Bizon   MIPS: BCM63XX: Ad...
109
110
111
  	case BCM6358_CPU_ID:
  	{
  		unsigned int tmp, n1, n2, m1;
e7300d04b   Maxime Bizon   MIPS: BCM63xx: Ad...
112
113
114
115
116
  		/* 16MHz * N1 * N2 / M1_CPU */
  		tmp = bcm_ddr_readl(DDR_DMIPSPLLCFG_REG);
  		n1 = (tmp & DMIPSPLLCFG_N1_MASK) >> DMIPSPLLCFG_N1_SHIFT;
  		n2 = (tmp & DMIPSPLLCFG_N2_MASK) >> DMIPSPLLCFG_N2_SHIFT;
  		m1 = (tmp & DMIPSPLLCFG_M1_MASK) >> DMIPSPLLCFG_M1_SHIFT;
04712f3ff   Maxime Bizon   MIPS: BCM63XX: Ad...
117
  		return (16 * 1000000 * n1 * n2) / m1;
e7300d04b   Maxime Bizon   MIPS: BCM63xx: Ad...
118
  	}
04712f3ff   Maxime Bizon   MIPS: BCM63XX: Ad...
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
  	case BCM6368_CPU_ID:
  	{
  		unsigned int tmp, p1, p2, ndiv, m1;
  
  		/* (64MHz / P1) * P2 * NDIV / M1_CPU */
  		tmp = bcm_ddr_readl(DDR_DMIPSPLLCFG_6368_REG);
  
  		p1 = (tmp & DMIPSPLLCFG_6368_P1_MASK) >>
  			DMIPSPLLCFG_6368_P1_SHIFT;
  
  		p2 = (tmp & DMIPSPLLCFG_6368_P2_MASK) >>
  			DMIPSPLLCFG_6368_P2_SHIFT;
  
  		ndiv = (tmp & DMIPSPLLCFG_6368_NDIV_MASK) >>
  			DMIPSPLLCFG_6368_NDIV_SHIFT;
  
  		tmp = bcm_ddr_readl(DDR_DMIPSPLLDIV_6368_REG);
  		m1 = (tmp & DMIPSPLLDIV_6368_MDIV_MASK) >>
  			DMIPSPLLDIV_6368_MDIV_SHIFT;
  
  		return (((64 * 1000000) / p1) * p2 * ndiv) / m1;
  	}
  
  	default:
  		BUG();
  	}
e7300d04b   Maxime Bizon   MIPS: BCM63xx: Ad...
145
146
147
148
149
150
151
152
153
  }
  
  /*
   * attempt to detect the amount of memory installed
   */
  static unsigned int detect_memory_size(void)
  {
  	unsigned int cols = 0, rows = 0, is_32bits = 0, banks = 0;
  	u32 val;
d61fcfe2b   Florian Fainelli   MIPS: BCM63xx: Fi...
154
155
156
157
  	if (BCMCPU_IS_6345()) {
  		val = bcm_sdram_readl(SDRAM_MBASE_REG);
  		return (val * 8 * 1024 * 1024);
  	}
e7300d04b   Maxime Bizon   MIPS: BCM63xx: Ad...
158
159
160
161
162
163
164
165
  
  	if (BCMCPU_IS_6338() || BCMCPU_IS_6348()) {
  		val = bcm_sdram_readl(SDRAM_CFG_REG);
  		rows = (val & SDRAM_CFG_ROW_MASK) >> SDRAM_CFG_ROW_SHIFT;
  		cols = (val & SDRAM_CFG_COL_MASK) >> SDRAM_CFG_COL_SHIFT;
  		is_32bits = (val & SDRAM_CFG_32B_MASK) ? 1 : 0;
  		banks = (val & SDRAM_CFG_BANK_MASK) ? 2 : 1;
  	}
04712f3ff   Maxime Bizon   MIPS: BCM63XX: Ad...
166
  	if (BCMCPU_IS_6358() || BCMCPU_IS_6368()) {
e7300d04b   Maxime Bizon   MIPS: BCM63xx: Ad...
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
  		val = bcm_memc_readl(MEMC_CFG_REG);
  		rows = (val & MEMC_CFG_ROW_MASK) >> MEMC_CFG_ROW_SHIFT;
  		cols = (val & MEMC_CFG_COL_MASK) >> MEMC_CFG_COL_SHIFT;
  		is_32bits = (val & MEMC_CFG_32B_MASK) ? 0 : 1;
  		banks = 2;
  	}
  
  	/* 0 => 11 address bits ... 2 => 13 address bits */
  	rows += 11;
  
  	/* 0 => 8 address bits ... 2 => 10 address bits */
  	cols += 8;
  
  	return 1 << (cols + rows + (is_32bits + 1) + banks);
  }
  
  void __init bcm63xx_cpu_init(void)
  {
  	unsigned int tmp, expected_cpu_id;
  	struct cpuinfo_mips *c = &current_cpu_data;
2b5b9b786   Florian Fainelli   MIPS: bcm63xx: Se...
187
  	unsigned int cpu = smp_processor_id();
e7300d04b   Maxime Bizon   MIPS: BCM63xx: Ad...
188
189
190
191
192
  
  	/* soc registers location depends on cpu type */
  	expected_cpu_id = 0;
  
  	switch (c->cputype) {
602977b0d   Kevin Cernekee   MIPS: Decouple BM...
193
194
195
  	case CPU_BMIPS3300:
  		if ((read_c0_prid() & 0xff00) == PRID_IMP_BMIPS3300_ALT) {
  			expected_cpu_id = BCM6348_CPU_ID;
ec68c5206   Maxime Bizon   MIPS: BCM63XX: Cl...
196
197
  			bcm63xx_regs_base = bcm6348_regs_base;
  			bcm63xx_irqs = bcm6348_irqs;
602977b0d   Kevin Cernekee   MIPS: Decouple BM...
198
199
200
  		} else {
  			__cpu_name[cpu] = "Broadcom BCM6338";
  			expected_cpu_id = BCM6338_CPU_ID;
ec68c5206   Maxime Bizon   MIPS: BCM63XX: Cl...
201
202
  			bcm63xx_regs_base = bcm6338_regs_base;
  			bcm63xx_irqs = bcm6338_irqs;
602977b0d   Kevin Cernekee   MIPS: Decouple BM...
203
  		}
e7300d04b   Maxime Bizon   MIPS: BCM63xx: Ad...
204
  		break;
602977b0d   Kevin Cernekee   MIPS: Decouple BM...
205
  	case CPU_BMIPS32:
e7300d04b   Maxime Bizon   MIPS: BCM63xx: Ad...
206
  		expected_cpu_id = BCM6345_CPU_ID;
ec68c5206   Maxime Bizon   MIPS: BCM63XX: Cl...
207
208
  		bcm63xx_regs_base = bcm6345_regs_base;
  		bcm63xx_irqs = bcm6345_irqs;
e7300d04b   Maxime Bizon   MIPS: BCM63xx: Ad...
209
  		break;
602977b0d   Kevin Cernekee   MIPS: Decouple BM...
210
  	case CPU_BMIPS4350:
04712f3ff   Maxime Bizon   MIPS: BCM63XX: Ad...
211
212
213
214
215
216
217
218
219
220
221
222
  		switch (read_c0_prid() & 0xf0) {
  		case 0x10:
  			expected_cpu_id = BCM6358_CPU_ID;
  			bcm63xx_regs_base = bcm6358_regs_base;
  			bcm63xx_irqs = bcm6358_irqs;
  			break;
  		case 0x30:
  			expected_cpu_id = BCM6368_CPU_ID;
  			bcm63xx_regs_base = bcm6368_regs_base;
  			bcm63xx_irqs = bcm6368_irqs;
  			break;
  		}
e7300d04b   Maxime Bizon   MIPS: BCM63xx: Ad...
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
257
  		break;
  	}
  
  	/*
  	 * really early to panic, but delaying panic would not help since we
  	 * will never get any working console
  	 */
  	if (!expected_cpu_id)
  		panic("unsupported Broadcom CPU");
  
  	/*
  	 * bcm63xx_regs_base is set, we can access soc registers
  	 */
  
  	/* double check CPU type */
  	tmp = bcm_perf_readl(PERF_REV_REG);
  	bcm63xx_cpu_id = (tmp & REV_CHIPID_MASK) >> REV_CHIPID_SHIFT;
  	bcm63xx_cpu_rev = (tmp & REV_REVID_MASK) >> REV_REVID_SHIFT;
  
  	if (bcm63xx_cpu_id != expected_cpu_id)
  		panic("bcm63xx CPU id mismatch");
  
  	bcm63xx_cpu_freq = detect_cpu_clock();
  	bcm63xx_memory_size = detect_memory_size();
  
  	printk(KERN_INFO "Detected Broadcom 0x%04x CPU revision %02x
  ",
  	       bcm63xx_cpu_id, bcm63xx_cpu_rev);
  	printk(KERN_INFO "CPU frequency is %u MHz
  ",
  	       bcm63xx_cpu_freq / 1000000);
  	printk(KERN_INFO "%uMB of RAM installed
  ",
  	       bcm63xx_memory_size >> 20);
  }