1/* 2 * setup.c 3 * 4 * BRIEF MODULE DESCRIPTION 5 * Momentum Computer Ocelot-3 board dependent boot routines 6 * 7 * Copyright (C) 1996, 1997, 01, 05 - 06 Ralf Baechle 8 * Copyright (C) 2000 RidgeRun, Inc. 9 * Copyright (C) 2001 Red Hat, Inc. 10 * Copyright (C) 2002 Momentum Computer 11 * 12 * Author: Matthew Dharm, Momentum Computer 13 * mdharm@momenco.com 14 * 15 * Louis Hamilton, Red Hat, Inc. 16 * hamilton@redhat.com [MIPS64 modifications] 17 * 18 * Author: RidgeRun, Inc. 19 * glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com 20 * 21 * Copyright 2001 MontaVista Software Inc. 22 * Author: jsun@mvista.com or jsun@junsun.net 23 * 24 * Copyright 2004 PMC-Sierra 25 * Author: Manish Lachwani (lachwani@pmc-sierra.com) 26 * 27 * Copyright (C) 2004 MontaVista Software Inc. 28 * Author: Manish Lachwani, mlachwani@mvista.com 29 * 30 * This program is free software; you can redistribute it and/or modify it 31 * under the terms of the GNU General Public License as published by the 32 * Free Software Foundation; either version 2 of the License, or (at your 33 * option) any later version. 34 * 35 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED 36 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 37 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN 38 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 39 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 40 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 41 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 42 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 43 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 44 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 45 * 46 * You should have received a copy of the GNU General Public License along 47 * with this program; if not, write to the Free Software Foundation, Inc., 48 * 675 Mass Ave, Cambridge, MA 02139, USA. 49 */ 50#include <linux/init.h> 51#include <linux/kernel.h> 52#include <linux/types.h> 53#include <linux/mc146818rtc.h> 54#include <linux/ioport.h> 55#include <linux/interrupt.h> 56#include <linux/pci.h> 57#include <linux/timex.h> 58#include <linux/bootmem.h> 59#include <linux/mv643xx.h> 60#include <linux/pm.h> 61#include <linux/bcd.h> 62 63#include <asm/time.h> 64#include <asm/page.h> 65#include <asm/bootinfo.h> 66#include <asm/io.h> 67#include <asm/irq.h> 68#include <asm/pci.h> 69#include <asm/processor.h> 70#include <asm/reboot.h> 71#include <asm/mc146818rtc.h> 72#include <asm/tlbflush.h> 73#include "ocelot_3_fpga.h" 74 75/* Marvell Discovery Register Base */ 76unsigned long marvell_base = (signed)0xf4000000; 77 78/* CPU clock */ 79unsigned long cpu_clock; 80 81/* RTC/NVRAM */ 82unsigned char* rtc_base = (unsigned char*)(signed)0xfc800000; 83 84/* FPGA Base */ 85unsigned long ocelot_fpga_base = (signed)0xfc000000; 86 87/* Serial base */ 88unsigned long uart_base = (signed)0xfd000000; 89 90/* 91 * Marvell Discovery SRAM. This is one place where Ethernet 92 * Tx and Rx descriptors can be placed to improve performance 93 */ 94extern unsigned long mv64340_sram_base; 95 96/* These functions are used for rebooting or halting the machine*/ 97extern void momenco_ocelot_restart(char *command); 98extern void momenco_ocelot_halt(void); 99extern void momenco_ocelot_power_off(void); 100 101void momenco_time_init(void); 102static char reset_reason; 103 104void add_wired_entry(unsigned long entrylo0, unsigned long entrylo1, 105 unsigned long entryhi, unsigned long pagemask); 106 107static inline unsigned long ENTRYLO(unsigned long paddr) 108{ 109 return ((paddr & PAGE_MASK) | 110 (_PAGE_PRESENT | __READABLE | __WRITEABLE | _PAGE_GLOBAL | 111 _CACHE_UNCACHED)) >> 6; 112} 113 114void __init bus_error_init(void) 115{ 116 /* nothing */ 117} 118 119/* 120 * setup code for a handoff from a version 2 PMON 2000 PROM 121 */ 122void setup_wired_tlb_entries(void) 123{ 124 write_c0_wired(0); 125 local_flush_tlb_all(); 126 127 /* marvell and extra space */ 128 add_wired_entry(ENTRYLO(0xf4000000), ENTRYLO(0xf4010000), (signed)0xf4000000, PM_64K); 129 130 /* fpga, rtc, and uart */ 131 add_wired_entry(ENTRYLO(0xfc000000), ENTRYLO(0xfd000000), (signed)0xfc000000, PM_16M); 132} 133 134unsigned long m48t37y_get_time(void) 135{ 136 unsigned int year, month, day, hour, min, sec; 137 unsigned long flags; 138 139 spin_lock_irqsave(&rtc_lock, flags); 140 /* stop the update */ 141 rtc_base[0x7ff8] = 0x40; 142 143 year = BCD2BIN(rtc_base[0x7fff]); 144 year += BCD2BIN(rtc_base[0x7ff1]) * 100; 145 146 month = BCD2BIN(rtc_base[0x7ffe]); 147 148 day = BCD2BIN(rtc_base[0x7ffd]); 149 150 hour = BCD2BIN(rtc_base[0x7ffb]); 151 min = BCD2BIN(rtc_base[0x7ffa]); 152 sec = BCD2BIN(rtc_base[0x7ff9]); 153 154 /* start the update */ 155 rtc_base[0x7ff8] = 0x00; 156 spin_unlock_irqrestore(&rtc_lock, flags); 157 158 return mktime(year, month, day, hour, min, sec); 159} 160 161int m48t37y_set_time(unsigned long sec) 162{ 163 struct rtc_time tm; 164 unsigned long flags; 165 166 /* convert to a more useful format -- note months count from 0 */ 167 to_tm(sec, &tm); 168 tm.tm_mon += 1; 169 170 spin_lock_irqsave(&rtc_lock, flags); 171 /* enable writing */ 172 rtc_base[0x7ff8] = 0x80; 173 174 /* year */ 175 rtc_base[0x7fff] = BIN2BCD(tm.tm_year % 100); 176 rtc_base[0x7ff1] = BIN2BCD(tm.tm_year / 100); 177 178 /* month */ 179 rtc_base[0x7ffe] = BIN2BCD(tm.tm_mon); 180 181 /* day */ 182 rtc_base[0x7ffd] = BIN2BCD(tm.tm_mday); 183 184 /* hour/min/sec */ 185 rtc_base[0x7ffb] = BIN2BCD(tm.tm_hour); 186 rtc_base[0x7ffa] = BIN2BCD(tm.tm_min); 187 rtc_base[0x7ff9] = BIN2BCD(tm.tm_sec); 188 189 /* day of week -- not really used, but let's keep it up-to-date */ 190 rtc_base[0x7ffc] = BIN2BCD(tm.tm_wday + 1); 191 192 /* disable writing */ 193 rtc_base[0x7ff8] = 0x00; 194 spin_unlock_irqrestore(&rtc_lock, flags); 195 196 return 0; 197} 198 199void __init plat_timer_setup(struct irqaction *irq) 200{ 201 setup_irq(7, irq); /* Timer interrupt, unmask status IM7 */ 202} 203 204void momenco_time_init(void) 205{ 206 setup_wired_tlb_entries(); 207 208 /* 209 * Ocelot-3 board has been built with both 210 * the Rm7900 and the Rm7065C 211 */ 212 mips_hpt_frequency = cpu_clock / 2; 213 214 rtc_mips_get_time = m48t37y_get_time; 215 rtc_mips_set_time = m48t37y_set_time; 216} 217 218/* 219 * PCI Support for Ocelot-3 220 */ 221 222/* Bus #0 IO and MEM space */ 223#define OCELOT_3_PCI_IO_0_START 0xe0000000 224#define OCELOT_3_PCI_IO_0_SIZE 0x08000000 225#define OCELOT_3_PCI_MEM_0_START 0xc0000000 226#define OCELOT_3_PCI_MEM_0_SIZE 0x10000000 227 228/* Bus #1 IO and MEM space */ 229#define OCELOT_3_PCI_IO_1_START 0xe8000000 230#define OCELOT_3_PCI_IO_1_SIZE 0x08000000 231#define OCELOT_3_PCI_MEM_1_START 0xd0000000 232#define OCELOT_3_PCI_MEM_1_SIZE 0x10000000 233 234static struct resource mv_pci_io_mem0_resource = { 235 .name = "MV64340 PCI0 IO MEM", 236 .start = OCELOT_3_PCI_IO_0_START, 237 .end = OCELOT_3_PCI_IO_0_START + OCELOT_3_PCI_IO_0_SIZE - 1, 238 .flags = IORESOURCE_IO, 239}; 240 241static struct resource mv_pci_io_mem1_resource = { 242 .name = "MV64340 PCI1 IO MEM", 243 .start = OCELOT_3_PCI_IO_1_START, 244 .end = OCELOT_3_PCI_IO_1_START + OCELOT_3_PCI_IO_1_SIZE - 1, 245 .flags = IORESOURCE_IO, 246}; 247 248static struct resource mv_pci_mem0_resource = { 249 .name = "MV64340 PCI0 MEM", 250 .start = OCELOT_3_PCI_MEM_0_START, 251 .end = OCELOT_3_PCI_MEM_0_START + OCELOT_3_PCI_MEM_0_SIZE - 1, 252 .flags = IORESOURCE_MEM, 253}; 254 255static struct resource mv_pci_mem1_resource = { 256 .name = "MV64340 PCI1 MEM", 257 .start = OCELOT_3_PCI_MEM_1_START, 258 .end = OCELOT_3_PCI_MEM_1_START + OCELOT_3_PCI_MEM_1_SIZE - 1, 259 .flags = IORESOURCE_MEM, 260}; 261 262static struct mv_pci_controller mv_bus0_controller = { 263 .pcic = { 264 .pci_ops = &mv_pci_ops, 265 .mem_resource = &mv_pci_mem0_resource, 266 .io_resource = &mv_pci_io_mem0_resource, 267 }, 268 .config_addr = MV64340_PCI_0_CONFIG_ADDR, 269 .config_vreg = MV64340_PCI_0_CONFIG_DATA_VIRTUAL_REG, 270}; 271 272static struct mv_pci_controller mv_bus1_controller = { 273 .pcic = { 274 .pci_ops = &mv_pci_ops, 275 .mem_resource = &mv_pci_mem1_resource, 276 .io_resource = &mv_pci_io_mem1_resource, 277 }, 278 .config_addr = MV64340_PCI_1_CONFIG_ADDR, 279 .config_vreg = MV64340_PCI_1_CONFIG_DATA_VIRTUAL_REG, 280}; 281 282static __init int __init ja_pci_init(void) 283{ 284 uint32_t enable; 285 extern int pci_probe_only; 286 287 /* PMON will assign PCI resources */ 288 pci_probe_only = 1; 289 290 enable = ~MV_READ(MV64340_BASE_ADDR_ENABLE); 291 /* 292 * We require at least one enabled I/O or PCI memory window or we 293 * will ignore this PCI bus. We ignore PCI windows 1, 2 and 3. 294 */ 295 if (enable & (0x01 << 9) || enable & (0x01 << 10)) 296 register_pci_controller(&mv_bus0_controller.pcic); 297 298 if (enable & (0x01 << 14) || enable & (0x01 << 15)) 299 register_pci_controller(&mv_bus1_controller.pcic); 300 301 ioport_resource.end = OCELOT_3_PCI_IO_0_START + OCELOT_3_PCI_IO_0_SIZE + 302 OCELOT_3_PCI_IO_1_SIZE - 1; 303 304 iomem_resource.end = OCELOT_3_PCI_MEM_0_START + OCELOT_3_PCI_MEM_0_SIZE + 305 OCELOT_3_PCI_MEM_1_SIZE - 1; 306 307 set_io_port_base(OCELOT_3_PCI_IO_0_START); /* mips_io_port_base */ 308 309 return 0; 310} 311 312arch_initcall(ja_pci_init); 313 314void __init plat_mem_setup(void) 315{ 316 unsigned int tmpword; 317 318 board_time_init = momenco_time_init; 319 320 _machine_restart = momenco_ocelot_restart; 321 _machine_halt = momenco_ocelot_halt; 322 pm_power_off = momenco_ocelot_power_off; 323 324 /* Wired TLB entries */ 325 setup_wired_tlb_entries(); 326 327 /* shut down ethernet ports, just to be sure our memory doesn't get 328 * corrupted by random ethernet traffic. 329 */ 330 MV_WRITE(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(0), 0xff << 8); 331 MV_WRITE(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(1), 0xff << 8); 332 MV_WRITE(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(0), 0xff << 8); 333 MV_WRITE(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(1), 0xff << 8); 334 do {} 335 while (MV_READ(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(0)) & 0xff); 336 do {} 337 while (MV_READ(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(1)) & 0xff); 338 do {} 339 while (MV_READ(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(0)) & 0xff); 340 do {} 341 while (MV_READ(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(1)) & 0xff); 342 MV_WRITE(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(0), 343 MV_READ(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(0)) & ~1); 344 MV_WRITE(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(1), 345 MV_READ(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(1)) & ~1); 346 347 /* Turn off the Bit-Error LED */ 348 OCELOT_FPGA_WRITE(0x80, CLR); 349 350 tmpword = OCELOT_FPGA_READ(BOARDREV); 351 if (tmpword < 26) 352 printk("Momenco Ocelot-3: Board Assembly Rev. %c\n", 353 'A'+tmpword); 354 else 355 printk("Momenco Ocelot-3: Board Assembly Revision #0x%x\n", 356 tmpword); 357 358 tmpword = OCELOT_FPGA_READ(FPGA_REV); 359 printk("FPGA Rev: %d.%d\n", tmpword>>4, tmpword&15); 360 tmpword = OCELOT_FPGA_READ(RESET_STATUS); 361 printk("Reset reason: 0x%x\n", tmpword); 362 switch (tmpword) { 363 case 0x1: 364 printk(" - Power-up reset\n"); 365 break; 366 case 0x2: 367 printk(" - Push-button reset\n"); 368 break; 369 case 0x4: 370 printk(" - cPCI bus reset\n"); 371 break; 372 case 0x8: 373 printk(" - Watchdog reset\n"); 374 break; 375 case 0x10: 376 printk(" - Software reset\n"); 377 break; 378 default: 379 printk(" - Unknown reset cause\n"); 380 } 381 reset_reason = tmpword; 382 OCELOT_FPGA_WRITE(0xff, RESET_STATUS); 383 384 tmpword = OCELOT_FPGA_READ(CPCI_ID); 385 printk("cPCI ID register: 0x%02x\n", tmpword); 386 printk(" - Slot number: %d\n", tmpword & 0x1f); 387 printk(" - PCI bus present: %s\n", tmpword & 0x40 ? "yes" : "no"); 388 printk(" - System Slot: %s\n", tmpword & 0x20 ? "yes" : "no"); 389 390 tmpword = OCELOT_FPGA_READ(BOARD_STATUS); 391 printk("Board Status register: 0x%02x\n", tmpword); 392 printk(" - User jumper: %s\n", (tmpword & 0x80)?"installed":"absent"); 393 printk(" - Boot flash write jumper: %s\n", (tmpword&0x40)?"installed":"absent"); 394 printk(" - L3 cache size: %d MB\n", (1<<((tmpword&12) >> 2))&~1); 395 396 /* Support for 128 MB memory */ 397 add_memory_region(0x0, 0x08000000, BOOT_MEM_RAM); 398} 399