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#include <linux/init.h>
28#include <linux/types.h>
29#include <linux/kernel.h>
30#include <linux/memblock.h>
31#include <linux/spinlock.h>
32#include <linux/ssb/ssb_driver_chipcommon.h>
33#include <linux/ssb/ssb_regs.h>
34#include <linux/smp.h>
35#include <asm/bootinfo.h>
36#include <bcm47xx.h>
37#include <bcm47xx_board.h>
38
39static char bcm47xx_system_type[20] = "Broadcom BCM47XX";
40
41const char *get_system_type(void)
42{
43 return bcm47xx_system_type;
44}
45
46__init void bcm47xx_set_system_type(u16 chip_id)
47{
48 snprintf(bcm47xx_system_type, sizeof(bcm47xx_system_type),
49 (chip_id > 0x9999) ? "Broadcom BCM%d" :
50 "Broadcom BCM%04X",
51 chip_id);
52}
53
54static unsigned long lowmem __initdata;
55
56static __init void prom_init_mem(void)
57{
58 unsigned long mem;
59 unsigned long max;
60 unsigned long off;
61 struct cpuinfo_mips *c = ¤t_cpu_data;
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77 off = CPHYSADDR((unsigned long)prom_init);
78
79
80 max = 128 << 20;
81
82 for (mem = 1 << 20; mem < max; mem += 1 << 20) {
83
84 if (off + mem >= max) {
85 mem = max;
86 pr_debug("Assume 128MB RAM\n");
87 break;
88 }
89 if (!memcmp(prom_init, prom_init + mem, 32))
90 break;
91 }
92 lowmem = mem;
93
94
95
96
97
98
99 if (c->cputype == CPU_74K && (mem == (128 << 20)))
100 mem -= 0x1000;
101 memblock_add(0, mem);
102}
103
104
105
106
107
108#define BCM47XX_SERIAL_ADDR (SSB_ENUM_BASE + SSB_CHIPCO_UART0_DATA)
109
110void __init prom_init(void)
111{
112 prom_init_mem();
113 setup_8250_early_printk_port(CKSEG1ADDR(BCM47XX_SERIAL_ADDR), 0, 0);
114}
115
116#if defined(CONFIG_BCM47XX_BCMA) && defined(CONFIG_HIGHMEM)
117
118#define EXTVBASE 0xc0000000
119#define ENTRYLO(x) ((pte_val(pfn_pte((x) >> _PFN_SHIFT, PAGE_KERNEL_UNCACHED)) >> 6) | 1)
120
121#include <asm/tlbflush.h>
122
123
124
125
126void early_tlb_init(void)
127{
128 write_c0_pagemask(PM_DEFAULT_MASK);
129 write_c0_wired(0);
130 temp_tlb_entry = current_cpu_data.tlbsize - 1;
131 local_flush_tlb_all();
132}
133
134void __init bcm47xx_prom_highmem_init(void)
135{
136 unsigned long off = (unsigned long)prom_init;
137 unsigned long extmem = 0;
138 bool highmem_region = false;
139
140 if (WARN_ON(bcm47xx_bus_type != BCM47XX_BUS_TYPE_BCMA))
141 return;
142
143 if (bcm47xx_bus.bcma.bus.chipinfo.id == BCMA_CHIP_ID_BCM4706)
144 highmem_region = true;
145
146 if (lowmem != 128 << 20 || !highmem_region)
147 return;
148
149 early_tlb_init();
150
151
152
153
154
155
156 add_temporary_entry(ENTRYLO(0x80000000),
157 ENTRYLO(0x80000000 + (256 << 20)),
158 EXTVBASE, PM_256M);
159
160 off = EXTVBASE + __pa(off);
161 for (extmem = 128 << 20; extmem < 512 << 20; extmem <<= 1) {
162 if (!memcmp(prom_init, (void *)(off + extmem), 16))
163 break;
164 }
165 extmem -= lowmem;
166
167 early_tlb_init();
168
169 if (!extmem)
170 return;
171
172 pr_warn("Found %lu MiB of extra memory, but highmem is unsupported yet!\n",
173 extmem >> 20);
174
175
176}
177
178#endif
179