diff options
author | 2025-03-08 22:04:20 +0800 | |
---|---|---|
committer | 2025-03-08 22:04:20 +0800 | |
commit | a07bb8fd1299070229f0e8f3dcb57ffd5ef9870a (patch) | |
tree | 84f21bd0bf7071bc5fc7dd989e77d7ceb5476682 /arch/mips/fw | |
download | ohosKernel-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/Makefile | 15 | ||||
-rw-r--r-- | arch/mips/fw/arc/arc_con.c | 54 | ||||
-rw-r--r-- | arch/mips/fw/arc/cmdline.c | 110 | ||||
-rw-r--r-- | arch/mips/fw/arc/env.c | 21 | ||||
-rw-r--r-- | arch/mips/fw/arc/file.c | 25 | ||||
-rw-r--r-- | arch/mips/fw/arc/identify.c | 111 | ||||
-rw-r--r-- | arch/mips/fw/arc/init.c | 51 | ||||
-rw-r--r-- | arch/mips/fw/arc/memory.c | 192 | ||||
-rw-r--r-- | arch/mips/fw/arc/misc.c | 36 | ||||
-rw-r--r-- | arch/mips/fw/arc/promlib.c | 61 | ||||
-rw-r--r-- | arch/mips/fw/cfe/Makefile | 6 | ||||
-rw-r--r-- | arch/mips/fw/cfe/cfe_api.c | 414 | ||||
-rw-r--r-- | arch/mips/fw/cfe/cfe_api_int.h | 135 | ||||
-rw-r--r-- | arch/mips/fw/lib/Makefile | 8 | ||||
-rw-r--r-- | arch/mips/fw/lib/call_o32.S | 104 | ||||
-rw-r--r-- | arch/mips/fw/lib/cmdline.c | 103 | ||||
-rw-r--r-- | arch/mips/fw/sni/Makefile | 6 | ||||
-rw-r--r-- | arch/mips/fw/sni/sniprom.c | 153 |
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 | |||
6 | ifdef CONFIG_ARC_CMDLINE_ONLY | ||
7 | lib-y += cmdline.o | ||
8 | else | ||
9 | lib-y += cmdline.o env.o file.o identify.o init.o \ | ||
10 | misc.o | ||
11 | endif | ||
12 | |||
13 | lib-$(CONFIG_ARC_MEMORY) += memory.o | ||
14 | lib-$(CONFIG_ARC_CONSOLE) += arc_con.o | ||
15 | lib-$(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 | |||
18 | static 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 | |||
29 | static 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 | |||
36 | static 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 | |||
48 | static int __init arc_console_init(void) | ||
49 | { | ||
50 | register_console(&arc_cons); | ||
51 | |||
52 | return 0; | ||
53 | } | ||
54 | console_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 | |||
26 | static char *ignored[] = { | ||
27 | "ConsoleIn=", | ||
28 | "ConsoleOut=", | ||
29 | "SystemPartition=", | ||
30 | "OSLoader=", | ||
31 | "OSLoadPartition=", | ||
32 | "OSLoadFilename=", | ||
33 | "OSLoadOptions=" | ||
34 | }; | ||
35 | |||
36 | static char *used_arc[][2] = { | ||
37 | { "OSLoadPartition=", "root=" }, | ||
38 | { "OSLoadOptions=", "" } | ||
39 | }; | ||
40 | |||
41 | static 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 | |||
73 | void __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 | |||
17 | PCHAR __init | ||
18 | ArcGetEnvironmentVariable(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 | |||
15 | LONG | ||
16 | ArcRead(ULONG FileID, VOID *Buffer, ULONG N, ULONG *Count) | ||
17 | { | ||
18 | return ARC_CALL4(read, FileID, Buffer, N, Count); | ||
19 | } | ||
20 | |||
21 | LONG | ||
22 | ArcWrite(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 | |||
23 | struct smatch { | ||
24 | char *arcname; | ||
25 | char *liname; | ||
26 | int flags; | ||
27 | }; | ||
28 | |||
29 | static 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 | |||
65 | int prom_flags; | ||
66 | |||
67 | static 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 | |||
79 | char *system_type; | ||
80 | |||
81 | const char *get_system_type(void) | ||
82 | { | ||
83 | return system_type; | ||
84 | } | ||
85 | |||
86 | static pcomponent * __init ArcGetChild(pcomponent *Current) | ||
87 | { | ||
88 | return (pcomponent *) ARC_CALL1(child_component, Current); | ||
89 | } | ||
90 | |||
91 | void __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. */ | ||
20 | struct linux_romvec *romvec; | ||
21 | |||
22 | #if defined(CONFIG_64BIT) && defined(CONFIG_FW_ARC32) | ||
23 | /* stack for calling 32bit ARC prom */ | ||
24 | u64 o32_stk[4096]; | ||
25 | #endif | ||
26 | |||
27 | void __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 | ||
30 | static phys_addr_t prom_mem_base[MAX_PROM_MEM] __initdata; | ||
31 | static phys_addr_t prom_mem_size[MAX_PROM_MEM] __initdata; | ||
32 | static 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 | |||
40 | struct 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 */ | ||
46 | static 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 | |||
57 | static 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 | |||
71 | enum { | ||
72 | mem_free, mem_prom_used, mem_reserved | ||
73 | }; | ||
74 | |||
75 | static 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 | |||
95 | static 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 | |||
115 | static 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 | |||
123 | void __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 | |||
172 | void __weak __init prom_cleanup(void) | ||
173 | { | ||
174 | } | ||
175 | |||
176 | void __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 | |||
23 | VOID __noreturn | ||
24 | ArcEnterInteractiveMode(VOID) | ||
25 | { | ||
26 | bc_disable(); | ||
27 | local_irq_disable(); | ||
28 | ARC_CALL0(imode); | ||
29 | |||
30 | unreachable(); | ||
31 | } | ||
32 | |||
33 | DISPLAY_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 | |||
39 | void 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 | |||
51 | char 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 | |||
6 | lib-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 | |||
24 | int 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 | |||
35 | static int (*cfe_dispfunc) (intptr_t handle, intptr_t xiocb); | ||
36 | static u64 cfe_handle; | ||
37 | |||
38 | int cfe_init(u64 handle, u64 ept) | ||
39 | { | ||
40 | cfe_dispfunc = NATIVE_FROM_XPTR(ept); | ||
41 | cfe_handle = handle; | ||
42 | return 0; | ||
43 | } | ||
44 | |||
45 | int 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 | |||
52 | int 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 | |||
68 | int 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 | |||
89 | int 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 | |||
106 | int 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 | |||
126 | int | ||
127 | cfe_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 | |||
150 | int 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 | |||
166 | int 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 | |||
181 | int 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 | |||
201 | int 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 | |||
223 | int 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 | |||
250 | int 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 | |||
267 | int64_t | ||
268 | cfe_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 | |||
285 | int 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 | |||
303 | int | ||
304 | cfe_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 | |||
326 | int 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 | |||
346 | int cfe_read(int handle, unsigned char *buffer, int length) | ||
347 | { | ||
348 | return cfe_readblk(handle, 0, buffer, length); | ||
349 | } | ||
350 | |||
351 | int 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 | |||
371 | int 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 | |||
391 | int cfe_write(int handle, const char *buffer, int length) | ||
392 | { | ||
393 | return cfe_writeblk(handle, 0, buffer, length); | ||
394 | } | ||
395 | |||
396 | int 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" */ | ||
43 | typedef s64 cfe_xptr_t; | ||
44 | |||
45 | struct 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 | |||
53 | struct xiocb_inpstat { | ||
54 | u64 inp_status; /* 1 means input available */ | ||
55 | }; | ||
56 | |||
57 | struct 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 | |||
65 | struct 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 | |||
74 | struct xiocb_time { | ||
75 | s64 ticks; /* current time in ticks */ | ||
76 | }; | ||
77 | |||
78 | struct xiocb_exitstat{ | ||
79 | s64 status; | ||
80 | }; | ||
81 | |||
82 | struct 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 | |||
89 | struct 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 | |||
102 | struct 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 | |||
6 | lib-y += cmdline.o | ||
7 | |||
8 | lib-$(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 | */ | ||
43 | NESTED(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 | ||
63 | 0: | ||
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 | ||
76 | 1: | ||
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 | ||
104 | END(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 | |||
15 | int fw_argc; | ||
16 | int *_fw_argv; | ||
17 | int *_fw_envp; | ||
18 | |||
19 | #ifndef CONFIG_HAVE_PLAT_FW_INIT_CMDLINE | ||
20 | void __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 | |||
47 | char * __init fw_getcmdline(void) | ||
48 | { | ||
49 | return &(arcs_cmdline[0]); | ||
50 | } | ||
51 | |||
52 | char *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 | |||
89 | unsigned 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 | |||
6 | lib-$(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. */ | ||
46 | static 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 | |||
52 | int __PROM_O32(__prom_putchar, (int *(*)(int), void *, int)); | ||
53 | char *__PROM_O32(__prom_getenv, (char *(*)(char *), void *, char *)); | ||
54 | void __PROM_O32(__prom_get_memconf, (void (*)(void *), void *, void *)); | ||
55 | u32 __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 | |||
69 | void prom_putchar(char c) | ||
70 | { | ||
71 | _prom_putchar(c); | ||
72 | } | ||
73 | |||
74 | |||
75 | char *prom_getenv(char *s) | ||
76 | { | ||
77 | return _prom_getenv(s); | ||
78 | } | ||
79 | |||
80 | void *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 | |||
90 | void __init prom_free_prom_memory(void) | ||
91 | { | ||
92 | } | ||
93 | |||
94 | /* | ||
95 | * /proc/cpuinfo system type | ||
96 | * | ||
97 | */ | ||
98 | char *system_type = "Unknown"; | ||
99 | const char *get_system_type(void) | ||
100 | { | ||
101 | return system_type; | ||
102 | } | ||
103 | |||
104 | static 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 | |||
139 | void __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 | } | ||