1231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer/* 2231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer * Big Endian PROM code for SNI RM machines 3231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer * 4231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer * This file is subject to the terms and conditions of the GNU General Public 5231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer * License. See the file "COPYING" in the main directory of this archive 6231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer * for more details. 7231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer * 8231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer * Copyright (C) 2005-2006 Florian Lohoff (flo@rfc822.org) 9231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer * Copyright (C) 2005-2006 Thomas Bogendoerfer (tsbogend@alpha.franken.de) 10231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer */ 11231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer 12231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer#include <linux/kernel.h> 13231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer#include <linux/init.h> 14231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer#include <linux/string.h> 15231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer#include <linux/console.h> 16231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer 17231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer#include <asm/addrspace.h> 18231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer#include <asm/sni.h> 19231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer#include <asm/mipsprom.h> 20231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer#include <asm/mipsregs.h> 21231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer#include <asm/bootinfo.h> 22231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer 23231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer/* special SNI prom calls */ 24231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer/* 25231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer * This does not exist in all proms - SINIX compares 26231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer * the prom env variable "version" against "2.0008" 27231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer * or greater. If lesser it tries to probe interesting 28231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer * registers 29231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer */ 30231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer#define PROM_GET_MEMCONF 58 317034228792cc561e79ff8600f02884bd4c80e287Ralf Baechle#define PROM_GET_HWCONF 61 32231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer 33231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer#define PROM_VEC (u64 *)CKSEG1ADDR(0x1fc00000) 34231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer#define PROM_ENTRY(x) (PROM_VEC + (x)) 35231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer 367034228792cc561e79ff8600f02884bd4c80e287Ralf Baechle#define ___prom_putchar ((int *(*)(int))PROM_ENTRY(PROM_PUTCHAR)) 377034228792cc561e79ff8600f02884bd4c80e287Ralf Baechle#define ___prom_getenv ((char *(*)(char *))PROM_ENTRY(PROM_GETENV)) 387034228792cc561e79ff8600f02884bd4c80e287Ralf Baechle#define ___prom_get_memconf ((void (*)(void *))PROM_ENTRY(PROM_GET_MEMCONF)) 397034228792cc561e79ff8600f02884bd4c80e287Ralf Baechle#define ___prom_get_hwconf ((u32 (*)(void))PROM_ENTRY(PROM_GET_HWCONF)) 40231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer 41231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer#ifdef CONFIG_64BIT 42231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer 43824122a319d827d42aeb4646a3bf639937fdb2ceMaciej W. Rozycki/* O32 stack has to be 8-byte aligned. */ 44824122a319d827d42aeb4646a3bf639937fdb2ceMaciej W. Rozyckistatic u64 o32_stk[4096]; 457034228792cc561e79ff8600f02884bd4c80e287Ralf Baechle#define O32_STK &o32_stk[sizeof(o32_stk)] 46231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer 47231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer#define __PROM_O32(fun, arg) fun arg __asm__(#fun); \ 48231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer __asm__(#fun " = call_o32") 49231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer 50231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerferint __PROM_O32(__prom_putchar, (int *(*)(int), void *, int)); 51231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerferchar *__PROM_O32(__prom_getenv, (char *(*)(char *), void *, char *)); 52231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfervoid __PROM_O32(__prom_get_memconf, (void (*)(void *), void *, void *)); 53231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerferu32 __PROM_O32(__prom_get_hwconf, (u32 (*)(void), void *)); 54231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer 55231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer#define _prom_putchar(x) __prom_putchar(___prom_putchar, O32_STK, x) 567034228792cc561e79ff8600f02884bd4c80e287Ralf Baechle#define _prom_getenv(x) __prom_getenv(___prom_getenv, O32_STK, x) 57231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer#define _prom_get_memconf(x) __prom_get_memconf(___prom_get_memconf, O32_STK, x) 58231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer#define _prom_get_hwconf() __prom_get_hwconf(___prom_get_hwconf, O32_STK) 59231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer 60231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer#else 61231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer#define _prom_putchar(x) ___prom_putchar(x) 627034228792cc561e79ff8600f02884bd4c80e287Ralf Baechle#define _prom_getenv(x) ___prom_getenv(x) 63231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer#define _prom_get_memconf(x) ___prom_get_memconf(x) 64231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer#define _prom_get_hwconf(x) ___prom_get_hwconf(x) 65231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer#endif 66231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer 67231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfervoid prom_putchar(char c) 68231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer{ 69231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer _prom_putchar(c); 70231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer} 71231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer 72231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer 73231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerferchar *prom_getenv(char *s) 74231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer{ 75231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer return _prom_getenv(s); 76231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer} 77231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer 78231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfervoid *prom_get_hwconf(void) 79231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer{ 80231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer u32 hwconf = _prom_get_hwconf(); 81231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer 82231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer if (hwconf == 0xffffffff) 83231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer return NULL; 84231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer 85231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer return (void *)CKSEG1ADDR(hwconf); 86231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer} 87231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer 88231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfervoid __init prom_free_prom_memory(void) 89231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer{ 90231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer} 91231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer 92231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer/* 93231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer * /proc/cpuinfo system type 94231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer * 95231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer */ 96231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerferchar *system_type = "Unknown"; 97231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerferconst char *get_system_type(void) 98231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer{ 99231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer return system_type; 100231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer} 101231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer 102231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerferstatic void __init sni_mem_init(void) 103231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer{ 104231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer int i, memsize; 105231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer struct membank { 106231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer u32 size; 107231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer u32 base; 108231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer u32 size2; 109231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer u32 pad1; 110231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer u32 pad2; 111231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer } memconf[8]; 112231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer int brd_type = *(unsigned char *)SNI_IDPROM_BRDTYPE; 113231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer 114231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer 115231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer /* MemSIZE from prom in 16MByte chunks */ 116231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer memsize = *((unsigned char *) SNI_IDPROM_MEMSIZE) * 16; 117231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer 118231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer pr_debug("IDProm memsize: %u MByte\n", memsize); 119231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer 120231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer /* get memory bank layout from prom */ 121231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer _prom_get_memconf(&memconf); 122231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer 123231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer pr_debug("prom_get_mem_conf memory configuration:\n"); 124231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer for (i = 0; i < 8 && memconf[i].size; i++) { 125231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer if (brd_type == SNI_BRD_PCI_TOWER || 126231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer brd_type == SNI_BRD_PCI_TOWER_CPLUS) { 127231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer if (memconf[i].base >= 0x20000000 && 128231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer memconf[i].base < 0x30000000) 129231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer memconf[i].base -= 0x20000000; 130231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer } 131231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer pr_debug("Bank%d: %08x @ %08x\n", i, 132231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer memconf[i].size, memconf[i].base); 133231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer add_memory_region(memconf[i].base, memconf[i].size, 134231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer BOOT_MEM_RAM); 135231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer } 136231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer} 137231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer 138231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfervoid __init prom_init(void) 139231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer{ 140231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer int argc = fw_arg0; 141231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer u32 *argv = (u32 *)CKSEG0ADDR(fw_arg1); 142231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer int i; 143231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer 144231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer sni_mem_init(); 145231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer 146231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer /* copy prom cmdline parameters to kernel cmdline */ 147231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer for (i = 1; i < argc; i++) { 148231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer strcat(arcs_cmdline, (char *)CKSEG0ADDR(argv[i])); 149231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer if (i < (argc - 1)) 150231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer strcat(arcs_cmdline, " "); 151231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer } 152231a35d37293ab88d325a9cb94e5474c156282c0Thomas Bogendoerfer} 153