0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027 #include <linux/init.h>
0028 #include <linux/types.h>
0029 #include <linux/kernel.h>
0030 #include <linux/memblock.h>
0031 #include <linux/spinlock.h>
0032 #include <linux/ssb/ssb_driver_chipcommon.h>
0033 #include <linux/ssb/ssb_regs.h>
0034 #include <linux/smp.h>
0035 #include <asm/bootinfo.h>
0036 #include <bcm47xx.h>
0037 #include <bcm47xx_board.h>
0038
0039 static char bcm47xx_system_type[20] = "Broadcom BCM47XX";
0040
0041 const char *get_system_type(void)
0042 {
0043 return bcm47xx_system_type;
0044 }
0045
0046 __init void bcm47xx_set_system_type(u16 chip_id)
0047 {
0048 snprintf(bcm47xx_system_type, sizeof(bcm47xx_system_type),
0049 (chip_id > 0x9999) ? "Broadcom BCM%d" :
0050 "Broadcom BCM%04X",
0051 chip_id);
0052 }
0053
0054 static unsigned long lowmem __initdata;
0055
0056 static __init void prom_init_mem(void)
0057 {
0058 unsigned long mem;
0059 unsigned long max;
0060 unsigned long off;
0061 struct cpuinfo_mips *c = ¤t_cpu_data;
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077 off = CPHYSADDR((unsigned long)prom_init);
0078
0079
0080 max = 128 << 20;
0081
0082 for (mem = 1 << 20; mem < max; mem += 1 << 20) {
0083
0084 if (off + mem >= max) {
0085 mem = max;
0086 pr_debug("Assume 128MB RAM\n");
0087 break;
0088 }
0089 if (!memcmp(prom_init, prom_init + mem, 32))
0090 break;
0091 }
0092 lowmem = mem;
0093
0094
0095
0096
0097
0098
0099 if (c->cputype == CPU_74K && (mem == (128 << 20)))
0100 mem -= 0x1000;
0101 memblock_add(0, mem);
0102 }
0103
0104
0105
0106
0107
0108 #define BCM47XX_SERIAL_ADDR (SSB_ENUM_BASE + SSB_CHIPCO_UART0_DATA)
0109
0110 void __init prom_init(void)
0111 {
0112 prom_init_mem();
0113 setup_8250_early_printk_port(CKSEG1ADDR(BCM47XX_SERIAL_ADDR), 0, 0);
0114 }
0115
0116 #if defined(CONFIG_BCM47XX_BCMA) && defined(CONFIG_HIGHMEM)
0117
0118 #define EXTVBASE 0xc0000000
0119 #define ENTRYLO(x) ((pte_val(pfn_pte((x) >> _PFN_SHIFT, PAGE_KERNEL_UNCACHED)) >> 6) | 1)
0120
0121 #include <asm/tlbflush.h>
0122
0123
0124
0125
0126 void early_tlb_init(void)
0127 {
0128 write_c0_pagemask(PM_DEFAULT_MASK);
0129 write_c0_wired(0);
0130 temp_tlb_entry = current_cpu_data.tlbsize - 1;
0131 local_flush_tlb_all();
0132 }
0133
0134 void __init bcm47xx_prom_highmem_init(void)
0135 {
0136 unsigned long off = (unsigned long)prom_init;
0137 unsigned long extmem = 0;
0138 bool highmem_region = false;
0139
0140 if (WARN_ON(bcm47xx_bus_type != BCM47XX_BUS_TYPE_BCMA))
0141 return;
0142
0143 if (bcm47xx_bus.bcma.bus.chipinfo.id == BCMA_CHIP_ID_BCM4706)
0144 highmem_region = true;
0145
0146 if (lowmem != 128 << 20 || !highmem_region)
0147 return;
0148
0149 early_tlb_init();
0150
0151
0152
0153
0154
0155
0156 add_temporary_entry(ENTRYLO(0x80000000),
0157 ENTRYLO(0x80000000 + (256 << 20)),
0158 EXTVBASE, PM_256M);
0159
0160 off = EXTVBASE + __pa(off);
0161 for (extmem = 128 << 20; extmem < 512 << 20; extmem <<= 1) {
0162 if (!memcmp(prom_init, (void *)(off + extmem), 16))
0163 break;
0164 }
0165 extmem -= lowmem;
0166
0167 early_tlb_init();
0168
0169 if (!extmem)
0170 return;
0171
0172 pr_warn("Found %lu MiB of extra memory, but highmem is unsupported yet!\n",
0173 extmem >> 20);
0174
0175
0176 }
0177
0178 #endif