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