xref: /kernel/linux/linux-5.10/arch/mips/fw/sni/sniprom.c (revision 8c2ecf20)
18c2ecf20Sopenharmony_ci/*
28c2ecf20Sopenharmony_ci * Big Endian PROM code for SNI RM machines
38c2ecf20Sopenharmony_ci *
48c2ecf20Sopenharmony_ci * This file is subject to the terms and conditions of the GNU General Public
58c2ecf20Sopenharmony_ci * License.  See the file "COPYING" in the main directory of this archive
68c2ecf20Sopenharmony_ci * for more details.
78c2ecf20Sopenharmony_ci *
88c2ecf20Sopenharmony_ci * Copyright (C) 2005-2006 Florian Lohoff (flo@rfc822.org)
98c2ecf20Sopenharmony_ci * Copyright (C) 2005-2006 Thomas Bogendoerfer (tsbogend@alpha.franken.de)
108c2ecf20Sopenharmony_ci */
118c2ecf20Sopenharmony_ci
128c2ecf20Sopenharmony_ci#include <linux/kernel.h>
138c2ecf20Sopenharmony_ci#include <linux/init.h>
148c2ecf20Sopenharmony_ci#include <linux/memblock.h>
158c2ecf20Sopenharmony_ci#include <linux/string.h>
168c2ecf20Sopenharmony_ci#include <linux/console.h>
178c2ecf20Sopenharmony_ci
188c2ecf20Sopenharmony_ci#include <asm/addrspace.h>
198c2ecf20Sopenharmony_ci#include <asm/sni.h>
208c2ecf20Sopenharmony_ci#include <asm/mipsprom.h>
218c2ecf20Sopenharmony_ci#include <asm/mipsregs.h>
228c2ecf20Sopenharmony_ci#include <asm/bootinfo.h>
238c2ecf20Sopenharmony_ci#include <asm/setup.h>
248c2ecf20Sopenharmony_ci
258c2ecf20Sopenharmony_ci/* special SNI prom calls */
268c2ecf20Sopenharmony_ci/*
278c2ecf20Sopenharmony_ci * This does not exist in all proms - SINIX compares
288c2ecf20Sopenharmony_ci * the prom env variable "version" against "2.0008"
298c2ecf20Sopenharmony_ci * or greater. If lesser it tries to probe interesting
308c2ecf20Sopenharmony_ci * registers
318c2ecf20Sopenharmony_ci */
328c2ecf20Sopenharmony_ci#define PROM_GET_MEMCONF	58
338c2ecf20Sopenharmony_ci#define PROM_GET_HWCONF		61
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_ci#define PROM_VEC		(u64 *)CKSEG1ADDR(0x1fc00000)
368c2ecf20Sopenharmony_ci#define PROM_ENTRY(x)		(PROM_VEC + (x))
378c2ecf20Sopenharmony_ci
388c2ecf20Sopenharmony_ci#define ___prom_putchar		((int *(*)(int))PROM_ENTRY(PROM_PUTCHAR))
398c2ecf20Sopenharmony_ci#define ___prom_getenv		((char *(*)(char *))PROM_ENTRY(PROM_GETENV))
408c2ecf20Sopenharmony_ci#define ___prom_get_memconf	((void (*)(void *))PROM_ENTRY(PROM_GET_MEMCONF))
418c2ecf20Sopenharmony_ci#define ___prom_get_hwconf	((u32 (*)(void))PROM_ENTRY(PROM_GET_HWCONF))
428c2ecf20Sopenharmony_ci
438c2ecf20Sopenharmony_ci#ifdef CONFIG_64BIT
448c2ecf20Sopenharmony_ci
458c2ecf20Sopenharmony_ci/* O32 stack has to be 8-byte aligned. */
468c2ecf20Sopenharmony_cistatic u64 o32_stk[4096];
478c2ecf20Sopenharmony_ci#define O32_STK	  (&o32_stk[ARRAY_SIZE(o32_stk)])
488c2ecf20Sopenharmony_ci
498c2ecf20Sopenharmony_ci#define __PROM_O32(fun, arg) fun arg __asm__(#fun); \
508c2ecf20Sopenharmony_ci				     __asm__(#fun " = call_o32")
518c2ecf20Sopenharmony_ci
528c2ecf20Sopenharmony_ciint   __PROM_O32(__prom_putchar, (int *(*)(int), void *, int));
538c2ecf20Sopenharmony_cichar *__PROM_O32(__prom_getenv, (char *(*)(char *), void *, char *));
548c2ecf20Sopenharmony_civoid  __PROM_O32(__prom_get_memconf, (void (*)(void *), void *, void *));
558c2ecf20Sopenharmony_ciu32   __PROM_O32(__prom_get_hwconf, (u32 (*)(void), void *));
568c2ecf20Sopenharmony_ci
578c2ecf20Sopenharmony_ci#define _prom_putchar(x)     __prom_putchar(___prom_putchar, O32_STK, x)
588c2ecf20Sopenharmony_ci#define _prom_getenv(x)	     __prom_getenv(___prom_getenv, O32_STK, x)
598c2ecf20Sopenharmony_ci#define _prom_get_memconf(x) __prom_get_memconf(___prom_get_memconf, O32_STK, x)
608c2ecf20Sopenharmony_ci#define _prom_get_hwconf()   __prom_get_hwconf(___prom_get_hwconf, O32_STK)
618c2ecf20Sopenharmony_ci
628c2ecf20Sopenharmony_ci#else
638c2ecf20Sopenharmony_ci#define _prom_putchar(x)     ___prom_putchar(x)
648c2ecf20Sopenharmony_ci#define _prom_getenv(x)	     ___prom_getenv(x)
658c2ecf20Sopenharmony_ci#define _prom_get_memconf(x) ___prom_get_memconf(x)
668c2ecf20Sopenharmony_ci#define _prom_get_hwconf(x)  ___prom_get_hwconf(x)
678c2ecf20Sopenharmony_ci#endif
688c2ecf20Sopenharmony_ci
698c2ecf20Sopenharmony_civoid prom_putchar(char c)
708c2ecf20Sopenharmony_ci{
718c2ecf20Sopenharmony_ci	_prom_putchar(c);
728c2ecf20Sopenharmony_ci}
738c2ecf20Sopenharmony_ci
748c2ecf20Sopenharmony_ci
758c2ecf20Sopenharmony_cichar *prom_getenv(char *s)
768c2ecf20Sopenharmony_ci{
778c2ecf20Sopenharmony_ci	return _prom_getenv(s);
788c2ecf20Sopenharmony_ci}
798c2ecf20Sopenharmony_ci
808c2ecf20Sopenharmony_civoid *prom_get_hwconf(void)
818c2ecf20Sopenharmony_ci{
828c2ecf20Sopenharmony_ci	u32 hwconf = _prom_get_hwconf();
838c2ecf20Sopenharmony_ci
848c2ecf20Sopenharmony_ci	if (hwconf == 0xffffffff)
858c2ecf20Sopenharmony_ci		return NULL;
868c2ecf20Sopenharmony_ci
878c2ecf20Sopenharmony_ci	return (void *)CKSEG1ADDR(hwconf);
888c2ecf20Sopenharmony_ci}
898c2ecf20Sopenharmony_ci
908c2ecf20Sopenharmony_civoid __init prom_free_prom_memory(void)
918c2ecf20Sopenharmony_ci{
928c2ecf20Sopenharmony_ci}
938c2ecf20Sopenharmony_ci
948c2ecf20Sopenharmony_ci/*
958c2ecf20Sopenharmony_ci * /proc/cpuinfo system type
968c2ecf20Sopenharmony_ci *
978c2ecf20Sopenharmony_ci */
988c2ecf20Sopenharmony_cichar *system_type = "Unknown";
998c2ecf20Sopenharmony_ciconst char *get_system_type(void)
1008c2ecf20Sopenharmony_ci{
1018c2ecf20Sopenharmony_ci	return system_type;
1028c2ecf20Sopenharmony_ci}
1038c2ecf20Sopenharmony_ci
1048c2ecf20Sopenharmony_cistatic void __init sni_mem_init(void)
1058c2ecf20Sopenharmony_ci{
1068c2ecf20Sopenharmony_ci	int i, memsize;
1078c2ecf20Sopenharmony_ci	struct membank {
1088c2ecf20Sopenharmony_ci		u32		size;
1098c2ecf20Sopenharmony_ci		u32		base;
1108c2ecf20Sopenharmony_ci		u32		size2;
1118c2ecf20Sopenharmony_ci		u32		pad1;
1128c2ecf20Sopenharmony_ci		u32		pad2;
1138c2ecf20Sopenharmony_ci	} memconf[8];
1148c2ecf20Sopenharmony_ci	int brd_type = *(unsigned char *)SNI_IDPROM_BRDTYPE;
1158c2ecf20Sopenharmony_ci
1168c2ecf20Sopenharmony_ci
1178c2ecf20Sopenharmony_ci	/* MemSIZE from prom in 16MByte chunks */
1188c2ecf20Sopenharmony_ci	memsize = *((unsigned char *) SNI_IDPROM_MEMSIZE) * 16;
1198c2ecf20Sopenharmony_ci
1208c2ecf20Sopenharmony_ci	pr_debug("IDProm memsize: %u MByte\n", memsize);
1218c2ecf20Sopenharmony_ci
1228c2ecf20Sopenharmony_ci	/* get memory bank layout from prom */
1238c2ecf20Sopenharmony_ci	_prom_get_memconf(&memconf);
1248c2ecf20Sopenharmony_ci
1258c2ecf20Sopenharmony_ci	pr_debug("prom_get_mem_conf memory configuration:\n");
1268c2ecf20Sopenharmony_ci	for (i = 0; i < 8 && memconf[i].size; i++) {
1278c2ecf20Sopenharmony_ci		if (brd_type == SNI_BRD_PCI_TOWER ||
1288c2ecf20Sopenharmony_ci		    brd_type == SNI_BRD_PCI_TOWER_CPLUS) {
1298c2ecf20Sopenharmony_ci			if (memconf[i].base >= 0x20000000 &&
1308c2ecf20Sopenharmony_ci			    memconf[i].base <  0x30000000)
1318c2ecf20Sopenharmony_ci				memconf[i].base -= 0x20000000;
1328c2ecf20Sopenharmony_ci		}
1338c2ecf20Sopenharmony_ci		pr_debug("Bank%d: %08x @ %08x\n", i,
1348c2ecf20Sopenharmony_ci			memconf[i].size, memconf[i].base);
1358c2ecf20Sopenharmony_ci		memblock_add(memconf[i].base, memconf[i].size);
1368c2ecf20Sopenharmony_ci	}
1378c2ecf20Sopenharmony_ci}
1388c2ecf20Sopenharmony_ci
1398c2ecf20Sopenharmony_civoid __init prom_init(void)
1408c2ecf20Sopenharmony_ci{
1418c2ecf20Sopenharmony_ci	int argc = fw_arg0;
1428c2ecf20Sopenharmony_ci	u32 *argv = (u32 *)CKSEG0ADDR(fw_arg1);
1438c2ecf20Sopenharmony_ci	int i;
1448c2ecf20Sopenharmony_ci
1458c2ecf20Sopenharmony_ci	sni_mem_init();
1468c2ecf20Sopenharmony_ci
1478c2ecf20Sopenharmony_ci	/* copy prom cmdline parameters to kernel cmdline */
1488c2ecf20Sopenharmony_ci	for (i = 1; i < argc; i++) {
1498c2ecf20Sopenharmony_ci		strcat(arcs_cmdline, (char *)CKSEG0ADDR(argv[i]));
1508c2ecf20Sopenharmony_ci		if (i < (argc - 1))
1518c2ecf20Sopenharmony_ci			strcat(arcs_cmdline, " ");
1528c2ecf20Sopenharmony_ci	}
1538c2ecf20Sopenharmony_ci}
154