162306a36Sopenharmony_ci/* 262306a36Sopenharmony_ci * Big Endian PROM code for SNI RM machines 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * This file is subject to the terms and conditions of the GNU General Public 562306a36Sopenharmony_ci * License. See the file "COPYING" in the main directory of this archive 662306a36Sopenharmony_ci * for more details. 762306a36Sopenharmony_ci * 862306a36Sopenharmony_ci * Copyright (C) 2005-2006 Florian Lohoff (flo@rfc822.org) 962306a36Sopenharmony_ci * Copyright (C) 2005-2006 Thomas Bogendoerfer (tsbogend@alpha.franken.de) 1062306a36Sopenharmony_ci */ 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci#include <linux/kernel.h> 1362306a36Sopenharmony_ci#include <linux/init.h> 1462306a36Sopenharmony_ci#include <linux/memblock.h> 1562306a36Sopenharmony_ci#include <linux/string.h> 1662306a36Sopenharmony_ci#include <linux/console.h> 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ci#include <asm/addrspace.h> 1962306a36Sopenharmony_ci#include <asm/sni.h> 2062306a36Sopenharmony_ci#include <asm/mipsprom.h> 2162306a36Sopenharmony_ci#include <asm/mipsregs.h> 2262306a36Sopenharmony_ci#include <asm/bootinfo.h> 2362306a36Sopenharmony_ci#include <asm/setup.h> 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_ci/* special SNI prom calls */ 2662306a36Sopenharmony_ci/* 2762306a36Sopenharmony_ci * This does not exist in all proms - SINIX compares 2862306a36Sopenharmony_ci * the prom env variable "version" against "2.0008" 2962306a36Sopenharmony_ci * or greater. If lesser it tries to probe interesting 3062306a36Sopenharmony_ci * registers 3162306a36Sopenharmony_ci */ 3262306a36Sopenharmony_ci#define PROM_GET_MEMCONF 58 3362306a36Sopenharmony_ci#define PROM_GET_HWCONF 61 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ci#define PROM_VEC (u64 *)CKSEG1ADDR(0x1fc00000) 3662306a36Sopenharmony_ci#define PROM_ENTRY(x) (PROM_VEC + (x)) 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_ci#define ___prom_putchar ((int *(*)(int))PROM_ENTRY(PROM_PUTCHAR)) 3962306a36Sopenharmony_ci#define ___prom_getenv ((char *(*)(char *))PROM_ENTRY(PROM_GETENV)) 4062306a36Sopenharmony_ci#define ___prom_get_memconf ((void (*)(void *))PROM_ENTRY(PROM_GET_MEMCONF)) 4162306a36Sopenharmony_ci#define ___prom_get_hwconf ((u32 (*)(void))PROM_ENTRY(PROM_GET_HWCONF)) 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ci#ifdef CONFIG_64BIT 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ci/* O32 stack has to be 8-byte aligned. */ 4662306a36Sopenharmony_cistatic u64 o32_stk[4096]; 4762306a36Sopenharmony_ci#define O32_STK (&o32_stk[ARRAY_SIZE(o32_stk)]) 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_ci#define __PROM_O32(fun, arg) fun arg __asm__(#fun); \ 5062306a36Sopenharmony_ci __asm__(#fun " = call_o32") 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ciint __PROM_O32(__prom_putchar, (int *(*)(int), void *, int)); 5362306a36Sopenharmony_cichar *__PROM_O32(__prom_getenv, (char *(*)(char *), void *, char *)); 5462306a36Sopenharmony_civoid __PROM_O32(__prom_get_memconf, (void (*)(void *), void *, void *)); 5562306a36Sopenharmony_ciu32 __PROM_O32(__prom_get_hwconf, (u32 (*)(void), void *)); 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ci#define _prom_putchar(x) __prom_putchar(___prom_putchar, O32_STK, x) 5862306a36Sopenharmony_ci#define _prom_getenv(x) __prom_getenv(___prom_getenv, O32_STK, x) 5962306a36Sopenharmony_ci#define _prom_get_memconf(x) __prom_get_memconf(___prom_get_memconf, O32_STK, x) 6062306a36Sopenharmony_ci#define _prom_get_hwconf() __prom_get_hwconf(___prom_get_hwconf, O32_STK) 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ci#else 6362306a36Sopenharmony_ci#define _prom_putchar(x) ___prom_putchar(x) 6462306a36Sopenharmony_ci#define _prom_getenv(x) ___prom_getenv(x) 6562306a36Sopenharmony_ci#define _prom_get_memconf(x) ___prom_get_memconf(x) 6662306a36Sopenharmony_ci#define _prom_get_hwconf(x) ___prom_get_hwconf(x) 6762306a36Sopenharmony_ci#endif 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_civoid prom_putchar(char c) 7062306a36Sopenharmony_ci{ 7162306a36Sopenharmony_ci _prom_putchar(c); 7262306a36Sopenharmony_ci} 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_cichar *prom_getenv(char *s) 7662306a36Sopenharmony_ci{ 7762306a36Sopenharmony_ci return _prom_getenv(s); 7862306a36Sopenharmony_ci} 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_civoid *prom_get_hwconf(void) 8162306a36Sopenharmony_ci{ 8262306a36Sopenharmony_ci u32 hwconf = _prom_get_hwconf(); 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_ci if (hwconf == 0xffffffff) 8562306a36Sopenharmony_ci return NULL; 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_ci return (void *)CKSEG1ADDR(hwconf); 8862306a36Sopenharmony_ci} 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_ci/* 9162306a36Sopenharmony_ci * /proc/cpuinfo system type 9262306a36Sopenharmony_ci * 9362306a36Sopenharmony_ci */ 9462306a36Sopenharmony_cichar *system_type = "Unknown"; 9562306a36Sopenharmony_ciconst char *get_system_type(void) 9662306a36Sopenharmony_ci{ 9762306a36Sopenharmony_ci return system_type; 9862306a36Sopenharmony_ci} 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_cistatic void __init sni_mem_init(void) 10162306a36Sopenharmony_ci{ 10262306a36Sopenharmony_ci int i, memsize; 10362306a36Sopenharmony_ci struct membank { 10462306a36Sopenharmony_ci u32 size; 10562306a36Sopenharmony_ci u32 base; 10662306a36Sopenharmony_ci u32 size2; 10762306a36Sopenharmony_ci u32 pad1; 10862306a36Sopenharmony_ci u32 pad2; 10962306a36Sopenharmony_ci } memconf[8]; 11062306a36Sopenharmony_ci int brd_type = *(unsigned char *)SNI_IDPROM_BRDTYPE; 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_ci /* MemSIZE from prom in 16MByte chunks */ 11462306a36Sopenharmony_ci memsize = *((unsigned char *) SNI_IDPROM_MEMSIZE) * 16; 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_ci pr_debug("IDProm memsize: %u MByte\n", memsize); 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_ci /* get memory bank layout from prom */ 11962306a36Sopenharmony_ci _prom_get_memconf(&memconf); 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_ci pr_debug("prom_get_mem_conf memory configuration:\n"); 12262306a36Sopenharmony_ci for (i = 0; i < 8 && memconf[i].size; i++) { 12362306a36Sopenharmony_ci if (brd_type == SNI_BRD_PCI_TOWER || 12462306a36Sopenharmony_ci brd_type == SNI_BRD_PCI_TOWER_CPLUS) { 12562306a36Sopenharmony_ci if (memconf[i].base >= 0x20000000 && 12662306a36Sopenharmony_ci memconf[i].base < 0x30000000) 12762306a36Sopenharmony_ci memconf[i].base -= 0x20000000; 12862306a36Sopenharmony_ci } 12962306a36Sopenharmony_ci pr_debug("Bank%d: %08x @ %08x\n", i, 13062306a36Sopenharmony_ci memconf[i].size, memconf[i].base); 13162306a36Sopenharmony_ci memblock_add(memconf[i].base, memconf[i].size); 13262306a36Sopenharmony_ci } 13362306a36Sopenharmony_ci} 13462306a36Sopenharmony_ci 13562306a36Sopenharmony_civoid __init prom_init(void) 13662306a36Sopenharmony_ci{ 13762306a36Sopenharmony_ci int argc = fw_arg0; 13862306a36Sopenharmony_ci u32 *argv = (u32 *)CKSEG0ADDR(fw_arg1); 13962306a36Sopenharmony_ci int i; 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_ci sni_mem_init(); 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_ci /* copy prom cmdline parameters to kernel cmdline */ 14462306a36Sopenharmony_ci for (i = 1; i < argc; i++) { 14562306a36Sopenharmony_ci strcat(arcs_cmdline, (char *)CKSEG0ADDR(argv[i])); 14662306a36Sopenharmony_ci if (i < (argc - 1)) 14762306a36Sopenharmony_ci strcat(arcs_cmdline, " "); 14862306a36Sopenharmony_ci } 14962306a36Sopenharmony_ci} 150