aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/fw
diff options
context:
space:
mode:
authorWe-unite <3205135446@qq.com>2025-03-08 22:04:20 +0800
committerWe-unite <3205135446@qq.com>2025-03-08 22:04:20 +0800
commita07bb8fd1299070229f0e8f3dcb57ffd5ef9870a (patch)
tree84f21bd0bf7071bc5fc7dd989e77d7ceb5476682 /arch/mips/fw
downloadohosKernel-a07bb8fd1299070229f0e8f3dcb57ffd5ef9870a.tar.gz
ohosKernel-a07bb8fd1299070229f0e8f3dcb57ffd5ef9870a.zip
Initial commit: OpenHarmony-v4.0-ReleaseOpenHarmony-v4.0-Release
Diffstat (limited to 'arch/mips/fw')
-rw-r--r--arch/mips/fw/arc/Makefile15
-rw-r--r--arch/mips/fw/arc/arc_con.c54
-rw-r--r--arch/mips/fw/arc/cmdline.c110
-rw-r--r--arch/mips/fw/arc/env.c21
-rw-r--r--arch/mips/fw/arc/file.c25
-rw-r--r--arch/mips/fw/arc/identify.c111
-rw-r--r--arch/mips/fw/arc/init.c51
-rw-r--r--arch/mips/fw/arc/memory.c192
-rw-r--r--arch/mips/fw/arc/misc.c36
-rw-r--r--arch/mips/fw/arc/promlib.c61
-rw-r--r--arch/mips/fw/cfe/Makefile6
-rw-r--r--arch/mips/fw/cfe/cfe_api.c414
-rw-r--r--arch/mips/fw/cfe/cfe_api_int.h135
-rw-r--r--arch/mips/fw/lib/Makefile8
-rw-r--r--arch/mips/fw/lib/call_o32.S104
-rw-r--r--arch/mips/fw/lib/cmdline.c103
-rw-r--r--arch/mips/fw/sni/Makefile6
-rw-r--r--arch/mips/fw/sni/sniprom.c153
18 files changed, 1605 insertions, 0 deletions
diff --git a/arch/mips/fw/arc/Makefile b/arch/mips/fw/arc/Makefile
new file mode 100644
index 000000000..64d685efc
--- /dev/null
+++ b/arch/mips/fw/arc/Makefile
@@ -0,0 +1,15 @@
1# SPDX-License-Identifier: GPL-2.0
2#
3# Makefile for the ARC prom monitor library routines under Linux.
4#
5
6ifdef CONFIG_ARC_CMDLINE_ONLY
7lib-y += cmdline.o
8else
9lib-y += cmdline.o env.o file.o identify.o init.o \
10 misc.o
11endif
12
13lib-$(CONFIG_ARC_MEMORY) += memory.o
14lib-$(CONFIG_ARC_CONSOLE) += arc_con.o
15lib-$(CONFIG_ARC_PROMLIB) += promlib.o
diff --git a/arch/mips/fw/arc/arc_con.c b/arch/mips/fw/arc/arc_con.c
new file mode 100644
index 000000000..7fdce236b
--- /dev/null
+++ b/arch/mips/fw/arc/arc_con.c
@@ -0,0 +1,54 @@
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Wrap-around code for a console using the
4 * ARC io-routines.
5 *
6 * Copyright (c) 1998 Harald Koerfgen
7 * Copyright (c) 2001 Ralf Baechle
8 * Copyright (c) 2002 Thiemo Seufer
9 */
10#include <linux/tty.h>
11#include <linux/major.h>
12#include <linux/init.h>
13#include <linux/console.h>
14#include <linux/fs.h>
15#include <asm/setup.h>
16#include <asm/sgialib.h>
17
18static void prom_console_write(struct console *co, const char *s,
19 unsigned count)
20{
21 /* Do each character */
22 while (count--) {
23 if (*s == '\n')
24 prom_putchar('\r');
25 prom_putchar(*s++);
26 }
27}
28
29static int prom_console_setup(struct console *co, char *options)
30{
31 if (prom_flags & PROM_FLAG_USE_AS_CONSOLE)
32 return 0;
33 return -ENODEV;
34}
35
36static struct console arc_cons = {
37 .name = "arc",
38 .write = prom_console_write,
39 .setup = prom_console_setup,
40 .flags = CON_PRINTBUFFER,
41 .index = -1,
42};
43
44/*
45 * Register console.
46 */
47
48static int __init arc_console_init(void)
49{
50 register_console(&arc_cons);
51
52 return 0;
53}
54console_initcall(arc_console_init);
diff --git a/arch/mips/fw/arc/cmdline.c b/arch/mips/fw/arc/cmdline.c
new file mode 100644
index 000000000..155c5e911
--- /dev/null
+++ b/arch/mips/fw/arc/cmdline.c
@@ -0,0 +1,110 @@
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * cmdline.c: Kernel command line creation using ARCS argc/argv.
7 *
8 * Copyright (C) 1996 David S. Miller (davem@davemloft.net)
9 */
10#include <linux/bug.h>
11#include <linux/init.h>
12#include <linux/kernel.h>
13#include <linux/string.h>
14
15#include <asm/sgialib.h>
16#include <asm/bootinfo.h>
17
18#undef DEBUG_CMDLINE
19
20/*
21 * A 32-bit ARC PROM pass arguments and environment as 32-bit pointer.
22 * These macro take care of sign extension.
23 */
24#define prom_argv(index) ((char *) (long)argv[(index)])
25
26static char *ignored[] = {
27 "ConsoleIn=",
28 "ConsoleOut=",
29 "SystemPartition=",
30 "OSLoader=",
31 "OSLoadPartition=",
32 "OSLoadFilename=",
33 "OSLoadOptions="
34};
35
36static char *used_arc[][2] = {
37 { "OSLoadPartition=", "root=" },
38 { "OSLoadOptions=", "" }
39};
40
41static char __init *move_firmware_args(int argc, LONG *argv, char *cp)
42{
43 char *s;
44 int actr, i;
45
46 actr = 1; /* Always ignore argv[0] */
47
48 while (actr < argc) {
49 for(i = 0; i < ARRAY_SIZE(used_arc); i++) {
50 int len = strlen(used_arc[i][0]);
51
52 if (!strncmp(prom_argv(actr), used_arc[i][0], len)) {
53 /* Ok, we want it. First append the replacement... */
54 strcat(cp, used_arc[i][1]);
55 cp += strlen(used_arc[i][1]);
56 /* ... and now the argument */
57 s = strchr(prom_argv(actr), '=');
58 if (s) {
59 s++;
60 strcpy(cp, s);
61 cp += strlen(s);
62 }
63 *cp++ = ' ';
64 break;
65 }
66 }
67 actr++;
68 }
69
70 return cp;
71}
72
73void __init prom_init_cmdline(int argc, LONG *argv)
74{
75 char *cp;
76 int actr, i;
77
78 actr = 1; /* Always ignore argv[0] */
79
80 cp = arcs_cmdline;
81 /*
82 * Move ARC variables to the beginning to make sure they can be
83 * overridden by later arguments.
84 */
85 cp = move_firmware_args(argc, argv, cp);
86
87 while (actr < argc) {
88 for (i = 0; i < ARRAY_SIZE(ignored); i++) {
89 int len = strlen(ignored[i]);
90
91 if (!strncmp(prom_argv(actr), ignored[i], len))
92 goto pic_cont;
93 }
94 /* Ok, we want it. */
95 strcpy(cp, prom_argv(actr));
96 cp += strlen(prom_argv(actr));
97 *cp++ = ' ';
98
99 pic_cont:
100 actr++;
101 }
102
103 if (cp != arcs_cmdline) /* get rid of trailing space */
104 --cp;
105 *cp = '\0';
106
107#ifdef DEBUG_CMDLINE
108 printk(KERN_DEBUG "prom cmdline: %s\n", arcs_cmdline);
109#endif
110}
diff --git a/arch/mips/fw/arc/env.c b/arch/mips/fw/arc/env.c
new file mode 100644
index 000000000..02407a7bb
--- /dev/null
+++ b/arch/mips/fw/arc/env.c
@@ -0,0 +1,21 @@
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * env.c: ARCS environment variable routines.
7 *
8 * Copyright (C) 1996 David S. Miller (davem@davemloft.net)
9 */
10#include <linux/init.h>
11#include <linux/kernel.h>
12#include <linux/string.h>
13
14#include <asm/fw/arc/types.h>
15#include <asm/sgialib.h>
16
17PCHAR __init
18ArcGetEnvironmentVariable(CHAR *name)
19{
20 return (CHAR *) ARC_CALL1(get_evar, name);
21}
diff --git a/arch/mips/fw/arc/file.c b/arch/mips/fw/arc/file.c
new file mode 100644
index 000000000..b0d8535c8
--- /dev/null
+++ b/arch/mips/fw/arc/file.c
@@ -0,0 +1,25 @@
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * ARC firmware interface.
7 *
8 * Copyright (C) 1994, 1995, 1996, 1999 Ralf Baechle
9 * Copyright (C) 1999 Silicon Graphics, Inc.
10 */
11
12#include <asm/fw/arc/types.h>
13#include <asm/sgialib.h>
14
15LONG
16ArcRead(ULONG FileID, VOID *Buffer, ULONG N, ULONG *Count)
17{
18 return ARC_CALL4(read, FileID, Buffer, N, Count);
19}
20
21LONG
22ArcWrite(ULONG FileID, PVOID Buffer, ULONG N, PULONG Count)
23{
24 return ARC_CALL4(write, FileID, Buffer, N, Count);
25}
diff --git a/arch/mips/fw/arc/identify.c b/arch/mips/fw/arc/identify.c
new file mode 100644
index 000000000..5527e0f54
--- /dev/null
+++ b/arch/mips/fw/arc/identify.c
@@ -0,0 +1,111 @@
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * identify.c: identify machine by looking up system identifier
7 *
8 * Copyright (C) 1998 Thomas Bogendoerfer
9 *
10 * This code is based on arch/mips/sgi/kernel/system.c, which is
11 *
12 * Copyright (C) 1996 David S. Miller (davem@davemloft.net)
13 */
14#include <linux/bug.h>
15#include <linux/init.h>
16#include <linux/kernel.h>
17#include <linux/types.h>
18#include <linux/string.h>
19
20#include <asm/sgialib.h>
21#include <asm/bootinfo.h>
22
23struct smatch {
24 char *arcname;
25 char *liname;
26 int flags;
27};
28
29static struct smatch mach_table[] = {
30 {
31 .arcname = "SGI-IP22",
32 .liname = "SGI Indy",
33 .flags = PROM_FLAG_ARCS,
34 }, {
35 .arcname = "SGI-IP28",
36 .liname = "SGI IP28",
37 .flags = PROM_FLAG_ARCS,
38 }, {
39 .arcname = "SGI-IP30",
40 .liname = "SGI Octane",
41 .flags = PROM_FLAG_ARCS,
42 }, {
43 .arcname = "SGI-IP32",
44 .liname = "SGI O2",
45 .flags = PROM_FLAG_ARCS,
46 }, {
47 .arcname = "Microsoft-Jazz",
48 .liname = "Jazz MIPS_Magnum_4000",
49 .flags = 0,
50 }, {
51 .arcname = "PICA-61",
52 .liname = "Jazz Acer_PICA_61",
53 .flags = 0,
54 }, {
55 .arcname = "RM200PCI",
56 .liname = "SNI RM200_PCI",
57 .flags = PROM_FLAG_DONT_FREE_TEMP,
58 }, {
59 .arcname = "RM200PCI-R5K",
60 .liname = "SNI RM200_PCI-R5K",
61 .flags = PROM_FLAG_DONT_FREE_TEMP,
62 }
63};
64
65int prom_flags;
66
67static struct smatch * __init string_to_mach(const char *s)
68{
69 int i;
70
71 for (i = 0; i < ARRAY_SIZE(mach_table); i++) {
72 if (!strcmp(s, mach_table[i].arcname))
73 return &mach_table[i];
74 }
75
76 panic("Yeee, could not determine architecture type <%s>", s);
77}
78
79char *system_type;
80
81const char *get_system_type(void)
82{
83 return system_type;
84}
85
86static pcomponent * __init ArcGetChild(pcomponent *Current)
87{
88 return (pcomponent *) ARC_CALL1(child_component, Current);
89}
90
91void __init prom_identify_arch(void)
92{
93 pcomponent *p;
94 struct smatch *mach;
95 const char *iname;
96
97 /*
98 * The root component tells us what machine architecture we have here.
99 */
100 p = ArcGetChild(PROM_NULL_COMPONENT);
101 if (p == NULL) {
102 iname = "Unknown";
103 } else
104 iname = (char *) (long) p->iname;
105
106 printk("ARCH: %s\n", iname);
107 mach = string_to_mach(iname);
108 system_type = mach->liname;
109
110 prom_flags = mach->flags;
111}
diff --git a/arch/mips/fw/arc/init.c b/arch/mips/fw/arc/init.c
new file mode 100644
index 000000000..f9d1dea9b
--- /dev/null
+++ b/arch/mips/fw/arc/init.c
@@ -0,0 +1,51 @@
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * PROM library initialisation code.
7 *
8 * Copyright (C) 1996 David S. Miller (davem@davemloft.net)
9 */
10#include <linux/init.h>
11#include <linux/kernel.h>
12
13#include <asm/bootinfo.h>
14#include <asm/sgialib.h>
15#include <asm/smp-ops.h>
16
17#undef DEBUG_PROM_INIT
18
19/* Master romvec interface. */
20struct linux_romvec *romvec;
21
22#if defined(CONFIG_64BIT) && defined(CONFIG_FW_ARC32)
23/* stack for calling 32bit ARC prom */
24u64 o32_stk[4096];
25#endif
26
27void __init prom_init(void)
28{
29 PSYSTEM_PARAMETER_BLOCK pb = PROMBLOCK;
30
31 romvec = ROMVECTOR;
32
33 if (pb->magic != 0x53435241) {
34 printk(KERN_CRIT "Aieee, bad prom vector magic %08lx\n",
35 (unsigned long) pb->magic);
36 while(1)
37 ;
38 }
39
40 prom_init_cmdline(fw_arg0, (LONG *)fw_arg1);
41 prom_identify_arch();
42 printk(KERN_INFO "PROMLIB: ARC firmware Version %d Revision %d\n",
43 pb->ver, pb->rev);
44 prom_meminit();
45
46#ifdef DEBUG_PROM_INIT
47 pr_info("Press a key to reboot\n");
48 ArcRead(0, &c, 1, &cnt);
49 ArcEnterInteractiveMode();
50#endif
51}
diff --git a/arch/mips/fw/arc/memory.c b/arch/mips/fw/arc/memory.c
new file mode 100644
index 000000000..37625ae5e
--- /dev/null
+++ b/arch/mips/fw/arc/memory.c
@@ -0,0 +1,192 @@
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * memory.c: PROM library functions for acquiring/using memory descriptors
4 * given to us from the ARCS firmware.
5 *
6 * Copyright (C) 1996 by David S. Miller
7 * Copyright (C) 1999, 2000, 2001 by Ralf Baechle
8 * Copyright (C) 1999, 2000 by Silicon Graphics, Inc.
9 *
10 * PROM library functions for acquiring/using memory descriptors given to us
11 * from the ARCS firmware. This is only used when CONFIG_ARC_MEMORY is set
12 * because on some machines like SGI IP27 the ARC memory configuration data
13 * completely bogus and alternate easier to use mechanisms are available.
14 */
15#include <linux/init.h>
16#include <linux/kernel.h>
17#include <linux/types.h>
18#include <linux/sched.h>
19#include <linux/mm.h>
20#include <linux/memblock.h>
21#include <linux/swap.h>
22
23#include <asm/sgialib.h>
24#include <asm/page.h>
25#include <asm/bootinfo.h>
26
27#undef DEBUG
28
29#define MAX_PROM_MEM 5
30static phys_addr_t prom_mem_base[MAX_PROM_MEM] __initdata;
31static phys_addr_t prom_mem_size[MAX_PROM_MEM] __initdata;
32static unsigned int nr_prom_mem __initdata;
33
34/*
35 * For ARC firmware memory functions the unit of meassuring memory is always
36 * a 4k page of memory
37 */
38#define ARC_PAGE_SHIFT 12
39
40struct linux_mdesc * __init ArcGetMemoryDescriptor(struct linux_mdesc *Current)
41{
42 return (struct linux_mdesc *) ARC_CALL1(get_mdesc, Current);
43}
44
45#ifdef DEBUG /* convenient for debugging */
46static char *arcs_mtypes[8] = {
47 "Exception Block",
48 "ARCS Romvec Page",
49 "Free/Contig RAM",
50 "Generic Free RAM",
51 "Bad Memory",
52 "Standalone Program Pages",
53 "ARCS Temp Storage Area",
54 "ARCS Permanent Storage Area"
55};
56
57static char *arc_mtypes[8] = {
58 "Exception Block",
59 "SystemParameterBlock",
60 "FreeMemory",
61 "Bad Memory",
62 "LoadedProgram",
63 "FirmwareTemporary",
64 "FirmwarePermanent",
65 "FreeContiguous"
66};
67#define mtypes(a) (prom_flags & PROM_FLAG_ARCS) ? arcs_mtypes[a.arcs] \
68 : arc_mtypes[a.arc]
69#endif
70
71enum {
72 mem_free, mem_prom_used, mem_reserved
73};
74
75static inline int memtype_classify_arcs(union linux_memtypes type)
76{
77 switch (type.arcs) {
78 case arcs_fcontig:
79 case arcs_free:
80 return mem_free;
81 case arcs_atmp:
82 return mem_prom_used;
83 case arcs_eblock:
84 case arcs_rvpage:
85 case arcs_bmem:
86 case arcs_prog:
87 case arcs_aperm:
88 return mem_reserved;
89 default:
90 BUG();
91 }
92 while(1); /* Nuke warning. */
93}
94
95static inline int memtype_classify_arc(union linux_memtypes type)
96{
97 switch (type.arc) {
98 case arc_free:
99 case arc_fcontig:
100 return mem_free;
101 case arc_atmp:
102 return mem_prom_used;
103 case arc_eblock:
104 case arc_rvpage:
105 case arc_bmem:
106 case arc_prog:
107 case arc_aperm:
108 return mem_reserved;
109 default:
110 BUG();
111 }
112 while(1); /* Nuke warning. */
113}
114
115static int __init prom_memtype_classify(union linux_memtypes type)
116{
117 if (prom_flags & PROM_FLAG_ARCS) /* SGI is ``different'' ... */
118 return memtype_classify_arcs(type);
119
120 return memtype_classify_arc(type);
121}
122
123void __weak __init prom_meminit(void)
124{
125 struct linux_mdesc *p;
126
127#ifdef DEBUG
128 int i = 0;
129
130 printk("ARCS MEMORY DESCRIPTOR dump:\n");
131 p = ArcGetMemoryDescriptor(PROM_NULL_MDESC);
132 while(p) {
133 printk("[%d,%p]: base<%08lx> pages<%08lx> type<%s>\n",
134 i, p, p->base, p->pages, mtypes(p->type));
135 p = ArcGetMemoryDescriptor(p);
136 i++;
137 }
138#endif
139
140 nr_prom_mem = 0;
141 p = PROM_NULL_MDESC;
142 while ((p = ArcGetMemoryDescriptor(p))) {
143 unsigned long base, size;
144 long type;
145
146 base = p->base << ARC_PAGE_SHIFT;
147 size = p->pages << ARC_PAGE_SHIFT;
148 type = prom_memtype_classify(p->type);
149
150 /* ignore mirrored RAM on IP28/IP30 */
151 if (base < PHYS_OFFSET)
152 continue;
153
154 memblock_add(base, size);
155
156 if (type == mem_reserved)
157 memblock_reserve(base, size);
158
159 if (type == mem_prom_used) {
160 memblock_reserve(base, size);
161 if (nr_prom_mem >= 5) {
162 pr_err("Too many ROM DATA regions");
163 continue;
164 }
165 prom_mem_base[nr_prom_mem] = base;
166 prom_mem_size[nr_prom_mem] = size;
167 nr_prom_mem++;
168 }
169 }
170}
171
172void __weak __init prom_cleanup(void)
173{
174}
175
176void __weak __init prom_free_prom_memory(void)
177{
178 int i;
179
180 if (prom_flags & PROM_FLAG_DONT_FREE_TEMP)
181 return;
182
183 for (i = 0; i < nr_prom_mem; i++) {
184 free_init_pages("prom memory",
185 prom_mem_base[i], prom_mem_base[i] + prom_mem_size[i]);
186 }
187 /*
188 * at this point it isn't safe to call PROM functions
189 * give platforms a way to do PROM cleanups
190 */
191 prom_cleanup();
192}
diff --git a/arch/mips/fw/arc/misc.c b/arch/mips/fw/arc/misc.c
new file mode 100644
index 000000000..d5b2d5901
--- /dev/null
+++ b/arch/mips/fw/arc/misc.c
@@ -0,0 +1,36 @@
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Miscellaneous ARCS PROM routines.
7 *
8 * Copyright (C) 1996 David S. Miller (davem@davemloft.net)
9 * Copyright (C) 1999 Ralf Baechle (ralf@gnu.org)
10 * Copyright (C) 1999 Silicon Graphics, Inc.
11 */
12#include <linux/compiler.h>
13#include <linux/init.h>
14#include <linux/kernel.h>
15#include <linux/irqflags.h>
16
17#include <asm/bcache.h>
18
19#include <asm/fw/arc/types.h>
20#include <asm/sgialib.h>
21#include <asm/bootinfo.h>
22
23VOID __noreturn
24ArcEnterInteractiveMode(VOID)
25{
26 bc_disable();
27 local_irq_disable();
28 ARC_CALL0(imode);
29
30 unreachable();
31}
32
33DISPLAY_STATUS * __init ArcGetDisplayStatus(ULONG FileID)
34{
35 return (DISPLAY_STATUS *) ARC_CALL1(GetDisplayStatus, FileID);
36}
diff --git a/arch/mips/fw/arc/promlib.c b/arch/mips/fw/arc/promlib.c
new file mode 100644
index 000000000..5e9e840a9
--- /dev/null
+++ b/arch/mips/fw/arc/promlib.c
@@ -0,0 +1,61 @@
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Copyright (C) 1996 David S. Miller (dm@sgi.com)
7 * Compatibility with board caches, Ulf Carlsson
8 */
9#include <linux/kernel.h>
10#include <asm/sgialib.h>
11#include <asm/bcache.h>
12#include <asm/setup.h>
13
14#if defined(CONFIG_64BIT) && defined(CONFIG_FW_ARC32)
15/*
16 * For 64bit kernels working with a 32bit ARC PROM pointer arguments
17 * for ARC calls need to reside in CKEG0/1. But as soon as the kernel
18 * switches to it's first kernel thread stack is set to an address in
19 * XKPHYS, so anything on stack can't be used anymore. This is solved
20 * by using a * static declartion variables are put into BSS, which is
21 * linked to a CKSEG0 address. Since this is only used on UP platforms
22 * there is not spinlock needed
23 */
24#define O32_STATIC static
25#else
26#define O32_STATIC
27#endif
28
29/*
30 * IP22 boardcache is not compatible with board caches. Thus we disable it
31 * during romvec action. Since r4xx0.c is always compiled and linked with your
32 * kernel, this shouldn't cause any harm regardless what MIPS processor you
33 * have.
34 *
35 * The ARC write and read functions seem to interfere with the serial lines
36 * in some way. You should be careful with them.
37 */
38
39void prom_putchar(char c)
40{
41 O32_STATIC ULONG cnt;
42 O32_STATIC CHAR it;
43
44 it = c;
45
46 bc_disable();
47 ArcWrite(1, &it, 1, &cnt);
48 bc_enable();
49}
50
51char prom_getchar(void)
52{
53 O32_STATIC ULONG cnt;
54 O32_STATIC CHAR c;
55
56 bc_disable();
57 ArcRead(0, &c, 1, &cnt);
58 bc_enable();
59
60 return c;
61}
diff --git a/arch/mips/fw/cfe/Makefile b/arch/mips/fw/cfe/Makefile
new file mode 100644
index 000000000..55b77633e
--- /dev/null
+++ b/arch/mips/fw/cfe/Makefile
@@ -0,0 +1,6 @@
1# SPDX-License-Identifier: GPL-2.0-only
2#
3# Makefile for the Broadcom Common Firmware Environment support
4#
5
6lib-y += cfe_api.o
diff --git a/arch/mips/fw/cfe/cfe_api.c b/arch/mips/fw/cfe/cfe_api.c
new file mode 100644
index 000000000..0c9c97ab2
--- /dev/null
+++ b/arch/mips/fw/cfe/cfe_api.c
@@ -0,0 +1,414 @@
1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * Copyright (C) 2000, 2001, 2002 Broadcom Corporation
4 */
5
6/*
7 *
8 * Broadcom Common Firmware Environment (CFE)
9 *
10 * This module contains device function stubs (small routines to
11 * call the standard "iocb" interface entry point to CFE).
12 * There should be one routine here per iocb function call.
13 *
14 * Authors: Mitch Lichtenberg, Chris Demetriou
15 */
16
17#include <asm/fw/cfe/cfe_api.h>
18#include "cfe_api_int.h"
19
20/* Cast from a native pointer to a cfe_xptr_t and back. */
21#define XPTR_FROM_NATIVE(n) ((cfe_xptr_t) (intptr_t) (n))
22#define NATIVE_FROM_XPTR(x) ((void *) (intptr_t) (x))
23
24int cfe_iocb_dispatch(struct cfe_xiocb *xiocb);
25
26/*
27 * Declare the dispatch function with args of "intptr_t".
28 * This makes sure whatever model we're compiling in
29 * puts the pointers in a single register. For example,
30 * combining -mlong64 and -mips1 or -mips2 would lead to
31 * trouble, since the handle and IOCB pointer will be
32 * passed in two registers each, and CFE expects one.
33 */
34
35static int (*cfe_dispfunc) (intptr_t handle, intptr_t xiocb);
36static u64 cfe_handle;
37
38int cfe_init(u64 handle, u64 ept)
39{
40 cfe_dispfunc = NATIVE_FROM_XPTR(ept);
41 cfe_handle = handle;
42 return 0;
43}
44
45int cfe_iocb_dispatch(struct cfe_xiocb * xiocb)
46{
47 if (!cfe_dispfunc)
48 return -1;
49 return (*cfe_dispfunc) ((intptr_t) cfe_handle, (intptr_t) xiocb);
50}
51
52int cfe_close(int handle)
53{
54 struct cfe_xiocb xiocb;
55
56 xiocb.xiocb_fcode = CFE_CMD_DEV_CLOSE;
57 xiocb.xiocb_status = 0;
58 xiocb.xiocb_handle = handle;
59 xiocb.xiocb_flags = 0;
60 xiocb.xiocb_psize = 0;
61
62 cfe_iocb_dispatch(&xiocb);
63
64 return xiocb.xiocb_status;
65
66}
67
68int cfe_cpu_start(int cpu, void (*fn) (void), long sp, long gp, long a1)
69{
70 struct cfe_xiocb xiocb;
71
72 xiocb.xiocb_fcode = CFE_CMD_FW_CPUCTL;
73 xiocb.xiocb_status = 0;
74 xiocb.xiocb_handle = 0;
75 xiocb.xiocb_flags = 0;
76 xiocb.xiocb_psize = sizeof(struct xiocb_cpuctl);
77 xiocb.plist.xiocb_cpuctl.cpu_number = cpu;
78 xiocb.plist.xiocb_cpuctl.cpu_command = CFE_CPU_CMD_START;
79 xiocb.plist.xiocb_cpuctl.gp_val = gp;
80 xiocb.plist.xiocb_cpuctl.sp_val = sp;
81 xiocb.plist.xiocb_cpuctl.a1_val = a1;
82 xiocb.plist.xiocb_cpuctl.start_addr = (long) fn;
83
84 cfe_iocb_dispatch(&xiocb);
85
86 return xiocb.xiocb_status;
87}
88
89int cfe_cpu_stop(int cpu)
90{
91 struct cfe_xiocb xiocb;
92
93 xiocb.xiocb_fcode = CFE_CMD_FW_CPUCTL;
94 xiocb.xiocb_status = 0;
95 xiocb.xiocb_handle = 0;
96 xiocb.xiocb_flags = 0;
97 xiocb.xiocb_psize = sizeof(struct xiocb_cpuctl);
98 xiocb.plist.xiocb_cpuctl.cpu_number = cpu;
99 xiocb.plist.xiocb_cpuctl.cpu_command = CFE_CPU_CMD_STOP;
100
101 cfe_iocb_dispatch(&xiocb);
102
103 return xiocb.xiocb_status;
104}
105
106int cfe_enumenv(int idx, char *name, int namelen, char *val, int vallen)
107{
108 struct cfe_xiocb xiocb;
109
110 xiocb.xiocb_fcode = CFE_CMD_ENV_SET;
111 xiocb.xiocb_status = 0;
112 xiocb.xiocb_handle = 0;
113 xiocb.xiocb_flags = 0;
114 xiocb.xiocb_psize = sizeof(struct xiocb_envbuf);
115 xiocb.plist.xiocb_envbuf.enum_idx = idx;
116 xiocb.plist.xiocb_envbuf.name_ptr = XPTR_FROM_NATIVE(name);
117 xiocb.plist.xiocb_envbuf.name_length = namelen;
118 xiocb.plist.xiocb_envbuf.val_ptr = XPTR_FROM_NATIVE(val);
119 xiocb.plist.xiocb_envbuf.val_length = vallen;
120
121 cfe_iocb_dispatch(&xiocb);
122
123 return xiocb.xiocb_status;
124}
125
126int
127cfe_enummem(int idx, int flags, u64 *start, u64 *length, u64 *type)
128{
129 struct cfe_xiocb xiocb;
130
131 xiocb.xiocb_fcode = CFE_CMD_FW_MEMENUM;
132 xiocb.xiocb_status = 0;
133 xiocb.xiocb_handle = 0;
134 xiocb.xiocb_flags = flags;
135 xiocb.xiocb_psize = sizeof(struct xiocb_meminfo);
136 xiocb.plist.xiocb_meminfo.mi_idx = idx;
137
138 cfe_iocb_dispatch(&xiocb);
139
140 if (xiocb.xiocb_status < 0)
141 return xiocb.xiocb_status;
142
143 *start = xiocb.plist.xiocb_meminfo.mi_addr;
144 *length = xiocb.plist.xiocb_meminfo.mi_size;
145 *type = xiocb.plist.xiocb_meminfo.mi_type;
146
147 return 0;
148}
149
150int cfe_exit(int warm, int status)
151{
152 struct cfe_xiocb xiocb;
153
154 xiocb.xiocb_fcode = CFE_CMD_FW_RESTART;
155 xiocb.xiocb_status = 0;
156 xiocb.xiocb_handle = 0;
157 xiocb.xiocb_flags = warm ? CFE_FLG_WARMSTART : 0;
158 xiocb.xiocb_psize = sizeof(struct xiocb_exitstat);
159 xiocb.plist.xiocb_exitstat.status = status;
160
161 cfe_iocb_dispatch(&xiocb);
162
163 return xiocb.xiocb_status;
164}
165
166int cfe_flushcache(int flg)
167{
168 struct cfe_xiocb xiocb;
169
170 xiocb.xiocb_fcode = CFE_CMD_FW_FLUSHCACHE;
171 xiocb.xiocb_status = 0;
172 xiocb.xiocb_handle = 0;
173 xiocb.xiocb_flags = flg;
174 xiocb.xiocb_psize = 0;
175
176 cfe_iocb_dispatch(&xiocb);
177
178 return xiocb.xiocb_status;
179}
180
181int cfe_getdevinfo(char *name)
182{
183 struct cfe_xiocb xiocb;
184
185 xiocb.xiocb_fcode = CFE_CMD_DEV_GETINFO;
186 xiocb.xiocb_status = 0;
187 xiocb.xiocb_handle = 0;
188 xiocb.xiocb_flags = 0;
189 xiocb.xiocb_psize = sizeof(struct xiocb_buffer);
190 xiocb.plist.xiocb_buffer.buf_offset = 0;
191 xiocb.plist.xiocb_buffer.buf_ptr = XPTR_FROM_NATIVE(name);
192 xiocb.plist.xiocb_buffer.buf_length = strlen(name);
193
194 cfe_iocb_dispatch(&xiocb);
195
196 if (xiocb.xiocb_status < 0)
197 return xiocb.xiocb_status;
198 return xiocb.plist.xiocb_buffer.buf_ioctlcmd;
199}
200
201int cfe_getenv(char *name, char *dest, int destlen)
202{
203 struct cfe_xiocb xiocb;
204
205 *dest = 0;
206
207 xiocb.xiocb_fcode = CFE_CMD_ENV_GET;
208 xiocb.xiocb_status = 0;
209 xiocb.xiocb_handle = 0;
210 xiocb.xiocb_flags = 0;
211 xiocb.xiocb_psize = sizeof(struct xiocb_envbuf);
212 xiocb.plist.xiocb_envbuf.enum_idx = 0;
213 xiocb.plist.xiocb_envbuf.name_ptr = XPTR_FROM_NATIVE(name);
214 xiocb.plist.xiocb_envbuf.name_length = strlen(name);
215 xiocb.plist.xiocb_envbuf.val_ptr = XPTR_FROM_NATIVE(dest);
216 xiocb.plist.xiocb_envbuf.val_length = destlen;
217
218 cfe_iocb_dispatch(&xiocb);
219
220 return xiocb.xiocb_status;
221}
222
223int cfe_getfwinfo(cfe_fwinfo_t * info)
224{
225 struct cfe_xiocb xiocb;
226
227 xiocb.xiocb_fcode = CFE_CMD_FW_GETINFO;
228 xiocb.xiocb_status = 0;
229 xiocb.xiocb_handle = 0;
230 xiocb.xiocb_flags = 0;
231 xiocb.xiocb_psize = sizeof(struct xiocb_fwinfo);
232
233 cfe_iocb_dispatch(&xiocb);
234
235 if (xiocb.xiocb_status < 0)
236 return xiocb.xiocb_status;
237
238 info->fwi_version = xiocb.plist.xiocb_fwinfo.fwi_version;
239 info->fwi_totalmem = xiocb.plist.xiocb_fwinfo.fwi_totalmem;
240 info->fwi_flags = xiocb.plist.xiocb_fwinfo.fwi_flags;
241 info->fwi_boardid = xiocb.plist.xiocb_fwinfo.fwi_boardid;
242 info->fwi_bootarea_va = xiocb.plist.xiocb_fwinfo.fwi_bootarea_va;
243 info->fwi_bootarea_pa = xiocb.plist.xiocb_fwinfo.fwi_bootarea_pa;
244 info->fwi_bootarea_size =
245 xiocb.plist.xiocb_fwinfo.fwi_bootarea_size;
246
247 return 0;
248}
249
250int cfe_getstdhandle(int flg)
251{
252 struct cfe_xiocb xiocb;
253
254 xiocb.xiocb_fcode = CFE_CMD_DEV_GETHANDLE;
255 xiocb.xiocb_status = 0;
256 xiocb.xiocb_handle = 0;
257 xiocb.xiocb_flags = flg;
258 xiocb.xiocb_psize = 0;
259
260 cfe_iocb_dispatch(&xiocb);
261
262 if (xiocb.xiocb_status < 0)
263 return xiocb.xiocb_status;
264 return xiocb.xiocb_handle;
265}
266
267int64_t
268cfe_getticks(void)
269{
270 struct cfe_xiocb xiocb;
271
272 xiocb.xiocb_fcode = CFE_CMD_FW_GETTIME;
273 xiocb.xiocb_status = 0;
274 xiocb.xiocb_handle = 0;
275 xiocb.xiocb_flags = 0;
276 xiocb.xiocb_psize = sizeof(struct xiocb_time);
277 xiocb.plist.xiocb_time.ticks = 0;
278
279 cfe_iocb_dispatch(&xiocb);
280
281 return xiocb.plist.xiocb_time.ticks;
282
283}
284
285int cfe_inpstat(int handle)
286{
287 struct cfe_xiocb xiocb;
288
289 xiocb.xiocb_fcode = CFE_CMD_DEV_INPSTAT;
290 xiocb.xiocb_status = 0;
291 xiocb.xiocb_handle = handle;
292 xiocb.xiocb_flags = 0;
293 xiocb.xiocb_psize = sizeof(struct xiocb_inpstat);
294 xiocb.plist.xiocb_inpstat.inp_status = 0;
295
296 cfe_iocb_dispatch(&xiocb);
297
298 if (xiocb.xiocb_status < 0)
299 return xiocb.xiocb_status;
300 return xiocb.plist.xiocb_inpstat.inp_status;
301}
302
303int
304cfe_ioctl(int handle, unsigned int ioctlnum, unsigned char *buffer,
305 int length, int *retlen, u64 offset)
306{
307 struct cfe_xiocb xiocb;
308
309 xiocb.xiocb_fcode = CFE_CMD_DEV_IOCTL;
310 xiocb.xiocb_status = 0;
311 xiocb.xiocb_handle = handle;
312 xiocb.xiocb_flags = 0;
313 xiocb.xiocb_psize = sizeof(struct xiocb_buffer);
314 xiocb.plist.xiocb_buffer.buf_offset = offset;
315 xiocb.plist.xiocb_buffer.buf_ioctlcmd = ioctlnum;
316 xiocb.plist.xiocb_buffer.buf_ptr = XPTR_FROM_NATIVE(buffer);
317 xiocb.plist.xiocb_buffer.buf_length = length;
318
319 cfe_iocb_dispatch(&xiocb);
320
321 if (retlen)
322 *retlen = xiocb.plist.xiocb_buffer.buf_retlen;
323 return xiocb.xiocb_status;
324}
325
326int cfe_open(char *name)
327{
328 struct cfe_xiocb xiocb;
329
330 xiocb.xiocb_fcode = CFE_CMD_DEV_OPEN;
331 xiocb.xiocb_status = 0;
332 xiocb.xiocb_handle = 0;
333 xiocb.xiocb_flags = 0;
334 xiocb.xiocb_psize = sizeof(struct xiocb_buffer);
335 xiocb.plist.xiocb_buffer.buf_offset = 0;
336 xiocb.plist.xiocb_buffer.buf_ptr = XPTR_FROM_NATIVE(name);
337 xiocb.plist.xiocb_buffer.buf_length = strlen(name);
338
339 cfe_iocb_dispatch(&xiocb);
340
341 if (xiocb.xiocb_status < 0)
342 return xiocb.xiocb_status;
343 return xiocb.xiocb_handle;
344}
345
346int cfe_read(int handle, unsigned char *buffer, int length)
347{
348 return cfe_readblk(handle, 0, buffer, length);
349}
350
351int cfe_readblk(int handle, s64 offset, unsigned char *buffer, int length)
352{
353 struct cfe_xiocb xiocb;
354
355 xiocb.xiocb_fcode = CFE_CMD_DEV_READ;
356 xiocb.xiocb_status = 0;
357 xiocb.xiocb_handle = handle;
358 xiocb.xiocb_flags = 0;
359 xiocb.xiocb_psize = sizeof(struct xiocb_buffer);
360 xiocb.plist.xiocb_buffer.buf_offset = offset;
361 xiocb.plist.xiocb_buffer.buf_ptr = XPTR_FROM_NATIVE(buffer);
362 xiocb.plist.xiocb_buffer.buf_length = length;
363
364 cfe_iocb_dispatch(&xiocb);
365
366 if (xiocb.xiocb_status < 0)
367 return xiocb.xiocb_status;
368 return xiocb.plist.xiocb_buffer.buf_retlen;
369}
370
371int cfe_setenv(char *name, char *val)
372{
373 struct cfe_xiocb xiocb;
374
375 xiocb.xiocb_fcode = CFE_CMD_ENV_SET;
376 xiocb.xiocb_status = 0;
377 xiocb.xiocb_handle = 0;
378 xiocb.xiocb_flags = 0;
379 xiocb.xiocb_psize = sizeof(struct xiocb_envbuf);
380 xiocb.plist.xiocb_envbuf.enum_idx = 0;
381 xiocb.plist.xiocb_envbuf.name_ptr = XPTR_FROM_NATIVE(name);
382 xiocb.plist.xiocb_envbuf.name_length = strlen(name);
383 xiocb.plist.xiocb_envbuf.val_ptr = XPTR_FROM_NATIVE(val);
384 xiocb.plist.xiocb_envbuf.val_length = strlen(val);
385
386 cfe_iocb_dispatch(&xiocb);
387
388 return xiocb.xiocb_status;
389}
390
391int cfe_write(int handle, const char *buffer, int length)
392{
393 return cfe_writeblk(handle, 0, buffer, length);
394}
395
396int cfe_writeblk(int handle, s64 offset, const char *buffer, int length)
397{
398 struct cfe_xiocb xiocb;
399
400 xiocb.xiocb_fcode = CFE_CMD_DEV_WRITE;
401 xiocb.xiocb_status = 0;
402 xiocb.xiocb_handle = handle;
403 xiocb.xiocb_flags = 0;
404 xiocb.xiocb_psize = sizeof(struct xiocb_buffer);
405 xiocb.plist.xiocb_buffer.buf_offset = offset;
406 xiocb.plist.xiocb_buffer.buf_ptr = XPTR_FROM_NATIVE(buffer);
407 xiocb.plist.xiocb_buffer.buf_length = length;
408
409 cfe_iocb_dispatch(&xiocb);
410
411 if (xiocb.xiocb_status < 0)
412 return xiocb.xiocb_status;
413 return xiocb.plist.xiocb_buffer.buf_retlen;
414}
diff --git a/arch/mips/fw/cfe/cfe_api_int.h b/arch/mips/fw/cfe/cfe_api_int.h
new file mode 100644
index 000000000..61a665d44
--- /dev/null
+++ b/arch/mips/fw/cfe/cfe_api_int.h
@@ -0,0 +1,135 @@
1/* SPDX-License-Identifier: GPL-2.0-or-later */
2/*
3 * Copyright (C) 2000, 2001, 2002 Broadcom Corporation
4 */
5#ifndef CFE_API_INT_H
6#define CFE_API_INT_H
7
8/*
9 * Constants.
10 */
11#define CFE_CMD_FW_GETINFO 0
12#define CFE_CMD_FW_RESTART 1
13#define CFE_CMD_FW_BOOT 2
14#define CFE_CMD_FW_CPUCTL 3
15#define CFE_CMD_FW_GETTIME 4
16#define CFE_CMD_FW_MEMENUM 5
17#define CFE_CMD_FW_FLUSHCACHE 6
18
19#define CFE_CMD_DEV_GETHANDLE 9
20#define CFE_CMD_DEV_ENUM 10
21#define CFE_CMD_DEV_OPEN 11
22#define CFE_CMD_DEV_INPSTAT 12
23#define CFE_CMD_DEV_READ 13
24#define CFE_CMD_DEV_WRITE 14
25#define CFE_CMD_DEV_IOCTL 15
26#define CFE_CMD_DEV_CLOSE 16
27#define CFE_CMD_DEV_GETINFO 17
28
29#define CFE_CMD_ENV_ENUM 20
30#define CFE_CMD_ENV_GET 22
31#define CFE_CMD_ENV_SET 23
32#define CFE_CMD_ENV_DEL 24
33
34#define CFE_CMD_MAX 32
35
36#define CFE_CMD_VENDOR_USE 0x8000 /* codes above this are for customer use */
37
38/*
39 * Structures.
40 */
41
42/* eeek, signed "pointers" */
43typedef s64 cfe_xptr_t;
44
45struct xiocb_buffer {
46 u64 buf_offset; /* offset on device (bytes) */
47 cfe_xptr_t buf_ptr; /* pointer to a buffer */
48 u64 buf_length; /* length of this buffer */
49 u64 buf_retlen; /* returned length (for read ops) */
50 u64 buf_ioctlcmd; /* IOCTL command (used only for IOCTLs) */
51};
52
53struct xiocb_inpstat {
54 u64 inp_status; /* 1 means input available */
55};
56
57struct xiocb_envbuf {
58 s64 enum_idx; /* 0-based enumeration index */
59 cfe_xptr_t name_ptr; /* name string buffer */
60 s64 name_length; /* size of name buffer */
61 cfe_xptr_t val_ptr; /* value string buffer */
62 s64 val_length; /* size of value string buffer */
63};
64
65struct xiocb_cpuctl {
66 u64 cpu_number; /* cpu number to control */
67 u64 cpu_command; /* command to issue to CPU */
68 u64 start_addr; /* CPU start address */
69 u64 gp_val; /* starting GP value */
70 u64 sp_val; /* starting SP value */
71 u64 a1_val; /* starting A1 value */
72};
73
74struct xiocb_time {
75 s64 ticks; /* current time in ticks */
76};
77
78struct xiocb_exitstat{
79 s64 status;
80};
81
82struct xiocb_meminfo {
83 s64 mi_idx; /* 0-based enumeration index */
84 s64 mi_type; /* type of memory block */
85 u64 mi_addr; /* physical start address */
86 u64 mi_size; /* block size */
87};
88
89struct xiocb_fwinfo {
90 s64 fwi_version; /* major, minor, eco version */
91 s64 fwi_totalmem; /* total installed mem */
92 s64 fwi_flags; /* various flags */
93 s64 fwi_boardid; /* board ID */
94 s64 fwi_bootarea_va; /* VA of boot area */
95 s64 fwi_bootarea_pa; /* PA of boot area */
96 s64 fwi_bootarea_size; /* size of boot area */
97 s64 fwi_reserved1;
98 s64 fwi_reserved2;
99 s64 fwi_reserved3;
100};
101
102struct cfe_xiocb {
103 u64 xiocb_fcode; /* IOCB function code */
104 s64 xiocb_status; /* return status */
105 s64 xiocb_handle; /* file/device handle */
106 u64 xiocb_flags; /* flags for this IOCB */
107 u64 xiocb_psize; /* size of parameter list */
108 union {
109 /* buffer parameters */
110 struct xiocb_buffer xiocb_buffer;
111
112 /* input status parameters */
113 struct xiocb_inpstat xiocb_inpstat;
114
115 /* environment function parameters */
116 struct xiocb_envbuf xiocb_envbuf;
117
118 /* CPU control parameters */
119 struct xiocb_cpuctl xiocb_cpuctl;
120
121 /* timer parameters */
122 struct xiocb_time xiocb_time;
123
124 /* memory arena info parameters */
125 struct xiocb_meminfo xiocb_meminfo;
126
127 /* firmware information */
128 struct xiocb_fwinfo xiocb_fwinfo;
129
130 /* Exit Status */
131 struct xiocb_exitstat xiocb_exitstat;
132 } plist;
133};
134
135#endif /* CFE_API_INT_H */
diff --git a/arch/mips/fw/lib/Makefile b/arch/mips/fw/lib/Makefile
new file mode 100644
index 000000000..cf9634548
--- /dev/null
+++ b/arch/mips/fw/lib/Makefile
@@ -0,0 +1,8 @@
1# SPDX-License-Identifier: GPL-2.0-only
2#
3# Makefile for generic prom monitor library routines under Linux.
4#
5
6lib-y += cmdline.o
7
8lib-$(CONFIG_64BIT) += call_o32.o
diff --git a/arch/mips/fw/lib/call_o32.S b/arch/mips/fw/lib/call_o32.S
new file mode 100644
index 000000000..ee856709e
--- /dev/null
+++ b/arch/mips/fw/lib/call_o32.S
@@ -0,0 +1,104 @@
1/* SPDX-License-Identifier: GPL-2.0-or-later */
2/*
3 * O32 interface for the 64 (or N32) ABI.
4 *
5 * Copyright (C) 2002, 2014 Maciej W. Rozycki
6 */
7
8#include <asm/asm.h>
9#include <asm/regdef.h>
10
11/* O32 register size. */
12#define O32_SZREG 4
13/* Maximum number of arguments supported. Must be even! */
14#define O32_ARGC 32
15/* Number of static registers we save. */
16#define O32_STATC 11
17/* Argument area frame size. */
18#define O32_ARGSZ (O32_SZREG * O32_ARGC)
19/* Static register save area frame size. */
20#define O32_STATSZ (SZREG * O32_STATC)
21/* Stack pointer register save area frame size. */
22#define O32_SPSZ SZREG
23/* Combined area frame size. */
24#define O32_FRAMESZ (O32_ARGSZ + O32_SPSZ + O32_STATSZ)
25/* Switched stack frame size. */
26#define O32_NFRAMESZ (O32_ARGSZ + O32_SPSZ)
27
28 .text
29
30/*
31 * O32 function call dispatcher, for interfacing 32-bit ROM routines.
32 *
33 * The standard 64 (N32) calling sequence is supported, with a0 holding
34 * a function pointer, a1 a pointer to the new stack to call the
35 * function with or 0 if no stack switching is requested, a2-a7 -- the
36 * function call's first six arguments, and the stack -- the remaining
37 * arguments (up to O32_ARGC, including a2-a7). Static registers, gp
38 * and fp are preserved, v0 holds the result. This code relies on the
39 * called o32 function for sp and ra restoration and this dispatcher has
40 * to be placed in a KSEGx (or KUSEG) address space. Any pointers
41 * passed have to point to addresses within one of these spaces as well.
42 */
43NESTED(call_o32, O32_FRAMESZ, ra)
44 REG_SUBU sp,O32_FRAMESZ
45
46 REG_S ra,O32_FRAMESZ-1*SZREG(sp)
47 REG_S fp,O32_FRAMESZ-2*SZREG(sp)
48 REG_S gp,O32_FRAMESZ-3*SZREG(sp)
49 REG_S s7,O32_FRAMESZ-4*SZREG(sp)
50 REG_S s6,O32_FRAMESZ-5*SZREG(sp)
51 REG_S s5,O32_FRAMESZ-6*SZREG(sp)
52 REG_S s4,O32_FRAMESZ-7*SZREG(sp)
53 REG_S s3,O32_FRAMESZ-8*SZREG(sp)
54 REG_S s2,O32_FRAMESZ-9*SZREG(sp)
55 REG_S s1,O32_FRAMESZ-10*SZREG(sp)
56 REG_S s0,O32_FRAMESZ-11*SZREG(sp)
57
58 move jp,a0
59
60 move fp,sp
61 beqz a1,0f
62 REG_SUBU fp,a1,O32_NFRAMESZ
630:
64 REG_S sp,O32_NFRAMESZ-1*SZREG(fp)
65
66 sll a0,a2,zero
67 sll a1,a3,zero
68 sll a2,a4,zero
69 sll a3,a5,zero
70 sw a6,4*O32_SZREG(fp)
71 sw a7,5*O32_SZREG(fp)
72
73 PTR_LA t0,O32_FRAMESZ(sp)
74 PTR_LA t1,6*O32_SZREG(fp)
75 li t2,O32_ARGC-6
761:
77 lw t3,(t0)
78 REG_ADDU t0,SZREG
79 sw t3,(t1)
80 REG_SUBU t2,1
81 REG_ADDU t1,O32_SZREG
82 bnez t2,1b
83
84 move sp,fp
85
86 jalr jp
87
88 REG_L sp,O32_NFRAMESZ-1*SZREG(sp)
89
90 REG_L s0,O32_FRAMESZ-11*SZREG(sp)
91 REG_L s1,O32_FRAMESZ-10*SZREG(sp)
92 REG_L s2,O32_FRAMESZ-9*SZREG(sp)
93 REG_L s3,O32_FRAMESZ-8*SZREG(sp)
94 REG_L s4,O32_FRAMESZ-7*SZREG(sp)
95 REG_L s5,O32_FRAMESZ-6*SZREG(sp)
96 REG_L s6,O32_FRAMESZ-5*SZREG(sp)
97 REG_L s7,O32_FRAMESZ-4*SZREG(sp)
98 REG_L gp,O32_FRAMESZ-3*SZREG(sp)
99 REG_L fp,O32_FRAMESZ-2*SZREG(sp)
100 REG_L ra,O32_FRAMESZ-1*SZREG(sp)
101
102 REG_ADDU sp,O32_FRAMESZ
103 jr ra
104END(call_o32)
diff --git a/arch/mips/fw/lib/cmdline.c b/arch/mips/fw/lib/cmdline.c
new file mode 100644
index 000000000..f24cbb4a3
--- /dev/null
+++ b/arch/mips/fw/lib/cmdline.c
@@ -0,0 +1,103 @@
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved.
7 */
8#include <linux/init.h>
9#include <linux/kernel.h>
10#include <linux/string.h>
11
12#include <asm/addrspace.h>
13#include <asm/fw/fw.h>
14
15int fw_argc;
16int *_fw_argv;
17int *_fw_envp;
18
19#ifndef CONFIG_HAVE_PLAT_FW_INIT_CMDLINE
20void __init fw_init_cmdline(void)
21{
22 int i;
23
24 /* Validate command line parameters. */
25 if ((fw_arg0 >= CKSEG0) || (fw_arg1 < CKSEG0)) {
26 fw_argc = 0;
27 _fw_argv = NULL;
28 } else {
29 fw_argc = (fw_arg0 & 0x0000ffff);
30 _fw_argv = (int *)fw_arg1;
31 }
32
33 /* Validate environment pointer. */
34 if (fw_arg2 < CKSEG0)
35 _fw_envp = NULL;
36 else
37 _fw_envp = (int *)fw_arg2;
38
39 for (i = 1; i < fw_argc; i++) {
40 strlcat(arcs_cmdline, fw_argv(i), COMMAND_LINE_SIZE);
41 if (i < (fw_argc - 1))
42 strlcat(arcs_cmdline, " ", COMMAND_LINE_SIZE);
43 }
44}
45#endif
46
47char * __init fw_getcmdline(void)
48{
49 return &(arcs_cmdline[0]);
50}
51
52char *fw_getenv(char *envname)
53{
54 char *result = NULL;
55
56 if (_fw_envp != NULL) {
57 /*
58 * Return a pointer to the given environment variable.
59 * YAMON uses "name", "value" pairs, while U-Boot uses
60 * "name=value".
61 */
62 int i, yamon, index = 0;
63
64 yamon = (strchr(fw_envp(index), '=') == NULL);
65 i = strlen(envname);
66
67 while (fw_envp(index)) {
68 if (strncmp(envname, fw_envp(index), i) == 0) {
69 if (yamon) {
70 result = fw_envp(index + 1);
71 break;
72 } else if (fw_envp(index)[i] == '=') {
73 result = fw_envp(index) + i + 1;
74 break;
75 }
76 }
77
78 /* Increment array index. */
79 if (yamon)
80 index += 2;
81 else
82 index += 1;
83 }
84 }
85
86 return result;
87}
88
89unsigned long fw_getenvl(char *envname)
90{
91 unsigned long envl = 0UL;
92 char *str;
93 int tmp;
94
95 str = fw_getenv(envname);
96 if (str) {
97 tmp = kstrtoul(str, 0, &envl);
98 if (tmp)
99 envl = 0;
100 }
101
102 return envl;
103}
diff --git a/arch/mips/fw/sni/Makefile b/arch/mips/fw/sni/Makefile
new file mode 100644
index 000000000..e5ba8e86b
--- /dev/null
+++ b/arch/mips/fw/sni/Makefile
@@ -0,0 +1,6 @@
1# SPDX-License-Identifier: GPL-2.0-only
2#
3# Makefile for the SNI prom monitor routines under Linux.
4#
5
6lib-$(CONFIG_FW_SNIPROM) += sniprom.o
diff --git a/arch/mips/fw/sni/sniprom.c b/arch/mips/fw/sni/sniprom.c
new file mode 100644
index 000000000..8f6730376
--- /dev/null
+++ b/arch/mips/fw/sni/sniprom.c
@@ -0,0 +1,153 @@
1/*
2 * Big Endian PROM code for SNI RM machines
3 *
4 * This file is subject to the terms and conditions of the GNU General Public
5 * License. See the file "COPYING" in the main directory of this archive
6 * for more details.
7 *
8 * Copyright (C) 2005-2006 Florian Lohoff (flo@rfc822.org)
9 * Copyright (C) 2005-2006 Thomas Bogendoerfer (tsbogend@alpha.franken.de)
10 */
11
12#include <linux/kernel.h>
13#include <linux/init.h>
14#include <linux/memblock.h>
15#include <linux/string.h>
16#include <linux/console.h>
17
18#include <asm/addrspace.h>
19#include <asm/sni.h>
20#include <asm/mipsprom.h>
21#include <asm/mipsregs.h>
22#include <asm/bootinfo.h>
23#include <asm/setup.h>
24
25/* special SNI prom calls */
26/*
27 * This does not exist in all proms - SINIX compares
28 * the prom env variable "version" against "2.0008"
29 * or greater. If lesser it tries to probe interesting
30 * registers
31 */
32#define PROM_GET_MEMCONF 58
33#define PROM_GET_HWCONF 61
34
35#define PROM_VEC (u64 *)CKSEG1ADDR(0x1fc00000)
36#define PROM_ENTRY(x) (PROM_VEC + (x))
37
38#define ___prom_putchar ((int *(*)(int))PROM_ENTRY(PROM_PUTCHAR))
39#define ___prom_getenv ((char *(*)(char *))PROM_ENTRY(PROM_GETENV))
40#define ___prom_get_memconf ((void (*)(void *))PROM_ENTRY(PROM_GET_MEMCONF))
41#define ___prom_get_hwconf ((u32 (*)(void))PROM_ENTRY(PROM_GET_HWCONF))
42
43#ifdef CONFIG_64BIT
44
45/* O32 stack has to be 8-byte aligned. */
46static u64 o32_stk[4096];
47#define O32_STK (&o32_stk[ARRAY_SIZE(o32_stk)])
48
49#define __PROM_O32(fun, arg) fun arg __asm__(#fun); \
50 __asm__(#fun " = call_o32")
51
52int __PROM_O32(__prom_putchar, (int *(*)(int), void *, int));
53char *__PROM_O32(__prom_getenv, (char *(*)(char *), void *, char *));
54void __PROM_O32(__prom_get_memconf, (void (*)(void *), void *, void *));
55u32 __PROM_O32(__prom_get_hwconf, (u32 (*)(void), void *));
56
57#define _prom_putchar(x) __prom_putchar(___prom_putchar, O32_STK, x)
58#define _prom_getenv(x) __prom_getenv(___prom_getenv, O32_STK, x)
59#define _prom_get_memconf(x) __prom_get_memconf(___prom_get_memconf, O32_STK, x)
60#define _prom_get_hwconf() __prom_get_hwconf(___prom_get_hwconf, O32_STK)
61
62#else
63#define _prom_putchar(x) ___prom_putchar(x)
64#define _prom_getenv(x) ___prom_getenv(x)
65#define _prom_get_memconf(x) ___prom_get_memconf(x)
66#define _prom_get_hwconf(x) ___prom_get_hwconf(x)
67#endif
68
69void prom_putchar(char c)
70{
71 _prom_putchar(c);
72}
73
74
75char *prom_getenv(char *s)
76{
77 return _prom_getenv(s);
78}
79
80void *prom_get_hwconf(void)
81{
82 u32 hwconf = _prom_get_hwconf();
83
84 if (hwconf == 0xffffffff)
85 return NULL;
86
87 return (void *)CKSEG1ADDR(hwconf);
88}
89
90void __init prom_free_prom_memory(void)
91{
92}
93
94/*
95 * /proc/cpuinfo system type
96 *
97 */
98char *system_type = "Unknown";
99const char *get_system_type(void)
100{
101 return system_type;
102}
103
104static void __init sni_mem_init(void)
105{
106 int i, memsize;
107 struct membank {
108 u32 size;
109 u32 base;
110 u32 size2;
111 u32 pad1;
112 u32 pad2;
113 } memconf[8];
114 int brd_type = *(unsigned char *)SNI_IDPROM_BRDTYPE;
115
116
117 /* MemSIZE from prom in 16MByte chunks */
118 memsize = *((unsigned char *) SNI_IDPROM_MEMSIZE) * 16;
119
120 pr_debug("IDProm memsize: %u MByte\n", memsize);
121
122 /* get memory bank layout from prom */
123 _prom_get_memconf(&memconf);
124
125 pr_debug("prom_get_mem_conf memory configuration:\n");
126 for (i = 0; i < 8 && memconf[i].size; i++) {
127 if (brd_type == SNI_BRD_PCI_TOWER ||
128 brd_type == SNI_BRD_PCI_TOWER_CPLUS) {
129 if (memconf[i].base >= 0x20000000 &&
130 memconf[i].base < 0x30000000)
131 memconf[i].base -= 0x20000000;
132 }
133 pr_debug("Bank%d: %08x @ %08x\n", i,
134 memconf[i].size, memconf[i].base);
135 memblock_add(memconf[i].base, memconf[i].size);
136 }
137}
138
139void __init prom_init(void)
140{
141 int argc = fw_arg0;
142 u32 *argv = (u32 *)CKSEG0ADDR(fw_arg1);
143 int i;
144
145 sni_mem_init();
146
147 /* copy prom cmdline parameters to kernel cmdline */
148 for (i = 1; i < argc; i++) {
149 strcat(arcs_cmdline, (char *)CKSEG0ADDR(argv[i]));
150 if (i < (argc - 1))
151 strcat(arcs_cmdline, " ");
152 }
153}