Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1 | /* |
| 2 | * BRIEF MODULE DESCRIPTION |
| 3 | * Momentum Computer Ocelot-G (CP7000G) - board dependent boot routines |
| 4 | * |
| 5 | * Copyright (C) 1996, 1997, 2001 Ralf Baechle |
| 6 | * Copyright (C) 2000 RidgeRun, Inc. |
| 7 | * Copyright (C) 2001 Red Hat, Inc. |
| 8 | * Copyright (C) 2002 Momentum Computer |
| 9 | * |
| 10 | * Author: Matthew Dharm, Momentum Computer |
| 11 | * mdharm@momenco.com |
| 12 | * |
| 13 | * Author: RidgeRun, Inc. |
| 14 | * glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com |
| 15 | * |
| 16 | * Copyright 2001 MontaVista Software Inc. |
| 17 | * Author: jsun@mvista.com or jsun@junsun.net |
| 18 | * |
| 19 | * This program is free software; you can redistribute it and/or modify it |
| 20 | * under the terms of the GNU General Public License as published by the |
| 21 | * Free Software Foundation; either version 2 of the License, or (at your |
| 22 | * option) any later version. |
| 23 | * |
| 24 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED |
| 25 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
| 26 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN |
| 27 | * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
| 28 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
| 29 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF |
| 30 | * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON |
| 31 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 32 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
| 33 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 34 | * |
| 35 | * You should have received a copy of the GNU General Public License along |
| 36 | * with this program; if not, write to the Free Software Foundation, Inc., |
| 37 | * 675 Mass Ave, Cambridge, MA 02139, USA. |
| 38 | * |
| 39 | */ |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 40 | #include <linux/init.h> |
| 41 | #include <linux/kernel.h> |
| 42 | #include <linux/types.h> |
| 43 | #include <linux/mm.h> |
| 44 | #include <linux/swap.h> |
| 45 | #include <linux/ioport.h> |
| 46 | #include <linux/sched.h> |
| 47 | #include <linux/interrupt.h> |
| 48 | #include <linux/pci.h> |
Ralf Baechle | fcdb27a | 2006-01-18 17:37:07 +0000 | [diff] [blame] | 49 | #include <linux/pm.h> |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 50 | #include <linux/timex.h> |
| 51 | #include <linux/vmalloc.h> |
Ralf Baechle | fcdb27a | 2006-01-18 17:37:07 +0000 | [diff] [blame] | 52 | |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 53 | #include <asm/time.h> |
| 54 | #include <asm/bootinfo.h> |
| 55 | #include <asm/page.h> |
| 56 | #include <asm/io.h> |
| 57 | #include <asm/gt64240.h> |
| 58 | #include <asm/irq.h> |
| 59 | #include <asm/pci.h> |
| 60 | #include <asm/processor.h> |
| 61 | #include <asm/ptrace.h> |
| 62 | #include <asm/reboot.h> |
| 63 | #include <linux/bootmem.h> |
| 64 | |
| 65 | #include "ocelot_pld.h" |
| 66 | |
| 67 | #ifdef CONFIG_GALILLEO_GT64240_ETH |
| 68 | extern unsigned char prom_mac_addr_base[6]; |
| 69 | #endif |
| 70 | |
| 71 | unsigned long marvell_base; |
| 72 | |
| 73 | /* These functions are used for rebooting or halting the machine*/ |
| 74 | extern void momenco_ocelot_restart(char *command); |
| 75 | extern void momenco_ocelot_halt(void); |
| 76 | extern void momenco_ocelot_power_off(void); |
| 77 | |
| 78 | extern void gt64240_time_init(void); |
| 79 | extern void momenco_ocelot_irq_setup(void); |
| 80 | |
| 81 | static char reset_reason; |
| 82 | |
| 83 | static unsigned long ENTRYLO(unsigned long paddr) |
| 84 | { |
| 85 | return ((paddr & PAGE_MASK) | |
| 86 | (_PAGE_PRESENT | __READABLE | __WRITEABLE | _PAGE_GLOBAL | |
| 87 | _CACHE_UNCACHED)) >> 6; |
| 88 | } |
| 89 | |
| 90 | /* setup code for a handoff from a version 2 PMON 2000 PROM */ |
| 91 | void PMON_v2_setup(void) |
| 92 | { |
| 93 | /* A wired TLB entry for the GT64240 and the serial port. The |
| 94 | GT64240 is going to be hit on every IRQ anyway - there's |
| 95 | absolutely no point in letting it be a random TLB entry, as |
| 96 | it'll just cause needless churning of the TLB. And we use |
| 97 | the other half for the serial port, which is just a PITA |
| 98 | otherwise :) |
| 99 | |
| 100 | Device Physical Virtual |
| 101 | GT64240 Internal Regs 0xf4000000 0xe0000000 |
| 102 | UARTs (CS2) 0xfd000000 0xe0001000 |
| 103 | */ |
| 104 | add_wired_entry(ENTRYLO(0xf4000000), ENTRYLO(0xf4010000), |
| 105 | 0xf4000000, PM_64K); |
| 106 | add_wired_entry(ENTRYLO(0xfd000000), ENTRYLO(0xfd001000), |
| 107 | 0xfd000000, PM_4K); |
| 108 | |
| 109 | /* Also a temporary entry to let us talk to the Ocelot PLD and NVRAM |
| 110 | in the CS[012] region. We can't use ioremap() yet. The NVRAM |
| 111 | is a ST M48T37Y, which includes NVRAM, RTC, and Watchdog functions. |
| 112 | |
| 113 | Ocelot PLD (CS0) 0xfc000000 0xe0020000 |
| 114 | NVRAM (CS1) 0xfc800000 0xe0030000 |
| 115 | */ |
| 116 | add_temporary_entry(ENTRYLO(0xfc000000), ENTRYLO(0xfc010000), |
| 117 | 0xfc000000, PM_64K); |
| 118 | add_temporary_entry(ENTRYLO(0xfc800000), ENTRYLO(0xfc810000), |
| 119 | 0xfc800000, PM_64K); |
| 120 | |
| 121 | marvell_base = 0xf4000000; |
| 122 | } |
| 123 | |
| 124 | extern int rm7k_tcache_enabled; |
| 125 | |
| 126 | /* |
| 127 | * This runs in KSEG1. See the verbiage in rm7k.c::probe_scache() |
| 128 | */ |
| 129 | #define Page_Invalidate_T 0x16 |
| 130 | static void __init setup_l3cache(unsigned long size) |
| 131 | { |
| 132 | int register i; |
| 133 | |
| 134 | printk("Enabling L3 cache..."); |
| 135 | |
| 136 | /* Enable the L3 cache in the GT64120A's CPU Configuration register */ |
| 137 | MV_WRITE(0, MV_READ(0) | (1<<14)); |
| 138 | |
| 139 | /* Enable the L3 cache in the CPU */ |
| 140 | set_c0_config(1<<12 /* CONF_TE */); |
| 141 | |
| 142 | /* Clear the cache */ |
| 143 | write_c0_taglo(0); |
| 144 | write_c0_taghi(0); |
| 145 | |
| 146 | for (i=0; i < size; i+= 4096) { |
| 147 | __asm__ __volatile__ ( |
| 148 | ".set noreorder\n\t" |
| 149 | ".set mips3\n\t" |
| 150 | "cache %1, (%0)\n\t" |
| 151 | ".set mips0\n\t" |
| 152 | ".set reorder" |
| 153 | : |
| 154 | : "r" (KSEG0ADDR(i)), |
| 155 | "i" (Page_Invalidate_T)); |
| 156 | } |
| 157 | |
| 158 | /* Let the RM7000 MM code know that the tertiary cache is enabled */ |
| 159 | rm7k_tcache_enabled = 1; |
| 160 | |
| 161 | printk("Done\n"); |
| 162 | } |
| 163 | |
Ralf Baechle | 2925aba | 2006-06-18 01:32:22 +0100 | [diff] [blame] | 164 | void __init plat_mem_setup(void) |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 165 | { |
| 166 | void (*l3func)(unsigned long) = (void *) KSEG1ADDR(setup_l3cache); |
| 167 | unsigned int tmpword; |
| 168 | |
| 169 | board_time_init = gt64240_time_init; |
| 170 | |
| 171 | _machine_restart = momenco_ocelot_restart; |
| 172 | _machine_halt = momenco_ocelot_halt; |
Ralf Baechle | fcdb27a | 2006-01-18 17:37:07 +0000 | [diff] [blame] | 173 | pm_power_off = momenco_ocelot_power_off; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 174 | |
| 175 | /* |
Ralf Baechle | fc10334 | 2006-06-28 11:24:12 +0100 | [diff] [blame] | 176 | * initrd_start = (unsigned long)ocelot_initrd_start; |
| 177 | * initrd_end = (unsigned long)ocelot_initrd_start + (ulong)ocelot_initrd_size; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 178 | * initrd_below_start_ok = 1; |
| 179 | */ |
| 180 | |
| 181 | /* do handoff reconfiguration */ |
| 182 | PMON_v2_setup(); |
| 183 | |
| 184 | #ifdef CONFIG_GALILLEO_GT64240_ETH |
| 185 | /* get the mac addr */ |
| 186 | memcpy(prom_mac_addr_base, (void*)0xfc807cf2, 6); |
| 187 | #endif |
| 188 | |
| 189 | /* Turn off the Bit-Error LED */ |
| 190 | OCELOT_PLD_WRITE(0x80, INTCLR); |
| 191 | |
| 192 | tmpword = OCELOT_PLD_READ(BOARDREV); |
| 193 | if (tmpword < 26) |
| 194 | printk("Momenco Ocelot-G: Board Assembly Rev. %c\n", 'A'+tmpword); |
| 195 | else |
| 196 | printk("Momenco Ocelot-G: Board Assembly Revision #0x%x\n", tmpword); |
| 197 | |
| 198 | tmpword = OCELOT_PLD_READ(PLD1_ID); |
| 199 | printk("PLD 1 ID: %d.%d\n", tmpword>>4, tmpword&15); |
| 200 | tmpword = OCELOT_PLD_READ(PLD2_ID); |
| 201 | printk("PLD 2 ID: %d.%d\n", tmpword>>4, tmpword&15); |
| 202 | tmpword = OCELOT_PLD_READ(RESET_STATUS); |
| 203 | printk("Reset reason: 0x%x\n", tmpword); |
| 204 | reset_reason = tmpword; |
| 205 | OCELOT_PLD_WRITE(0xff, RESET_STATUS); |
| 206 | |
| 207 | tmpword = OCELOT_PLD_READ(BOARD_STATUS); |
| 208 | printk("Board Status register: 0x%02x\n", tmpword); |
| 209 | printk(" - User jumper: %s\n", (tmpword & 0x80)?"installed":"absent"); |
| 210 | printk(" - Boot flash write jumper: %s\n", (tmpword&0x40)?"installed":"absent"); |
| 211 | printk(" - Tulip PHY %s connected\n", (tmpword&0x10)?"is":"not"); |
| 212 | printk(" - L3 Cache size: %d MiB\n", (1<<((tmpword&12) >> 2))&~1); |
| 213 | printk(" - SDRAM size: %d MiB\n", 1<<(6+(tmpword&3))); |
| 214 | |
| 215 | if (tmpword&12) |
| 216 | l3func((1<<(((tmpword&12) >> 2)+20))); |
| 217 | |
| 218 | switch(tmpword &3) { |
| 219 | case 3: |
| 220 | /* 512MiB -- two banks of 256MiB */ |
| 221 | add_memory_region( 0x0<<20, 0x100<<20, BOOT_MEM_RAM); |
| 222 | /* |
| 223 | add_memory_region(0x100<<20, 0x100<<20, BOOT_MEM_RAM); |
| 224 | */ |
| 225 | break; |
| 226 | case 2: |
| 227 | /* 256MiB -- two banks of 128MiB */ |
| 228 | add_memory_region( 0x0<<20, 0x80<<20, BOOT_MEM_RAM); |
| 229 | add_memory_region(0x80<<20, 0x80<<20, BOOT_MEM_RAM); |
| 230 | break; |
| 231 | case 1: |
| 232 | /* 128MiB -- 64MiB per bank */ |
| 233 | add_memory_region( 0x0<<20, 0x40<<20, BOOT_MEM_RAM); |
| 234 | add_memory_region(0x40<<20, 0x40<<20, BOOT_MEM_RAM); |
| 235 | break; |
| 236 | case 0: |
| 237 | /* 64MiB */ |
| 238 | add_memory_region( 0x0<<20, 0x40<<20, BOOT_MEM_RAM); |
| 239 | break; |
| 240 | } |
| 241 | |
| 242 | /* FIXME: Fix up the DiskOnChip mapping */ |
| 243 | MV_WRITE(0x468, 0xfef73); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 244 | } |
| 245 | |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 246 | /* This needs to be one of the first initcalls, because no I/O port access |
| 247 | can work before this */ |
| 248 | |
| 249 | static int io_base_ioremap(void) |
| 250 | { |
| 251 | /* we're mapping PCI accesses from 0xc0000000 to 0xf0000000 */ |
| 252 | unsigned long io_remap_range; |
| 253 | |
| 254 | io_remap_range = (unsigned long) ioremap(0xc0000000, 0x30000000); |
| 255 | if (!io_remap_range) |
| 256 | panic("Could not ioremap I/O port range"); |
| 257 | |
| 258 | set_io_port_base(io_remap_range - 0xc0000000); |
| 259 | |
| 260 | return 0; |
| 261 | } |
| 262 | |
| 263 | module_init(io_base_ioremap); |