1 // SPDX-License-Identifier: GPL-2.0
2 /* Prom access routines for the sun3x */
3 
4 #include <linux/types.h>
5 #include <linux/kernel.h>
6 #include <linux/tty.h>
7 #include <linux/console.h>
8 #include <linux/init.h>
9 #include <linux/mm.h>
10 #include <linux/string.h>
11 
12 #include <asm/page.h>
13 #include <asm/setup.h>
14 #include <asm/traps.h>
15 #include <asm/sun3xprom.h>
16 #include <asm/idprom.h>
17 #include <asm/sun3ints.h>
18 #include <asm/openprom.h>
19 #include <asm/machines.h>
20 
21 void (*sun3x_putchar)(int);
22 int (*sun3x_getchar)(void);
23 int (*sun3x_mayget)(void);
24 int (*sun3x_mayput)(int);
25 void (*sun3x_prom_reboot)(void);
26 e_vector sun3x_prom_abort;
27 struct linux_romvec *romvec;
28 
29 /* prom vector table */
30 e_vector *sun3x_prom_vbr;
31 
32 /* Handle returning to the prom */
sun3x_halt(void)33 void sun3x_halt(void)
34 {
35 	unsigned long flags;
36 
37 	/* Disable interrupts while we mess with things */
38 	local_irq_save(flags);
39 
40 	/* Restore prom vbr */
41 	asm volatile ("movec %0,%%vbr" : : "r" ((void*)sun3x_prom_vbr));
42 
43 	/* Restore prom NMI clock */
44 //	sun3x_disable_intreg(5);
45 	sun3_enable_irq(7);
46 
47 	/* Let 'er rip */
48 	asm volatile ("trap #14");
49 
50 	/* Restore everything */
51 	sun3_disable_irq(7);
52 	sun3_enable_irq(5);
53 
54 	asm volatile ("movec %0,%%vbr" : : "r" ((void*)vectors));
55 	local_irq_restore(flags);
56 }
57 
sun3x_reboot(void)58 void sun3x_reboot(void)
59 {
60 	/* This never returns, don't bother saving things */
61 	local_irq_disable();
62 
63 	/* Restore prom vbr */
64 	asm volatile ("movec %0,%%vbr" : : "r" ((void*)sun3x_prom_vbr));
65 
66 	/* Restore prom NMI clock */
67 	sun3_disable_irq(5);
68 	sun3_enable_irq(7);
69 
70 	/* Let 'er rip */
71 	(*romvec->pv_reboot)("vmlinux");
72 }
73 
sun3x_prom_write(struct console * co,const char * s,unsigned int count)74 static void sun3x_prom_write(struct console *co, const char *s,
75                              unsigned int count)
76 {
77 	while (count--) {
78 		if (*s == '\n')
79 			sun3x_putchar('\r');
80 		sun3x_putchar(*s++);
81 	}
82 }
83 
84 /* debug console - write-only */
85 
86 static struct console sun3x_debug = {
87 	.name	= "debug",
88 	.write	= sun3x_prom_write,
89 	.flags	= CON_PRINTBUFFER,
90 	.index	= -1,
91 };
92 
sun3x_prom_init(void)93 void __init sun3x_prom_init(void)
94 {
95 	/* Read the vector table */
96 
97 	sun3x_putchar = *(void (**)(int)) (SUN3X_P_PUTCHAR);
98 	sun3x_getchar = *(int (**)(void)) (SUN3X_P_GETCHAR);
99 	sun3x_mayget = *(int (**)(void))  (SUN3X_P_MAYGET);
100 	sun3x_mayput = *(int (**)(int))   (SUN3X_P_MAYPUT);
101 	sun3x_prom_reboot = *(void (**)(void)) (SUN3X_P_REBOOT);
102 	sun3x_prom_abort = *(e_vector *)  (SUN3X_P_ABORT);
103 	romvec = (struct linux_romvec *)SUN3X_PROM_BASE;
104 
105 	idprom_init();
106 
107 	if (!((idprom->id_machtype & SM_ARCH_MASK) == SM_SUN3X)) {
108 		pr_warn("Machine reports strange type %02x\n",
109 			idprom->id_machtype);
110 		pr_warn("Pretending it's a 3/80, but very afraid...\n");
111 		idprom->id_machtype = SM_SUN3X | SM_3_80;
112 	}
113 
114 	/* point trap #14 at abort.
115 	 * XXX this is futile since we restore the vbr first - oops
116 	 */
117 	vectors[VEC_TRAP14] = sun3x_prom_abort;
118 }
119 
sun3x_debug_setup(char * arg)120 static int __init sun3x_debug_setup(char *arg)
121 {
122 	/* If debug=prom was specified, start the debug console */
123 	if (MACH_IS_SUN3X && !strcmp(arg, "prom"))
124 		register_console(&sun3x_debug);
125 	return 0;
126 }
127 
128 early_param("debug", sun3x_debug_setup);
129 
130 /* some prom functions to export */
prom_getintdefault(int node,char * property,int deflt)131 int prom_getintdefault(int node, char *property, int deflt)
132 {
133 	return deflt;
134 }
135 
prom_getbool(int node,char * prop)136 int prom_getbool (int node, char *prop)
137 {
138 	return 1;
139 }
140 
prom_printf(char * fmt,...)141 void prom_printf(char *fmt, ...)
142 {
143 }
144 
prom_halt(void)145 void prom_halt (void)
146 {
147 	sun3x_halt();
148 }
149 
150 /* Get the idprom and stuff it into buffer 'idbuf'.  Returns the
151  * format type.  'num_bytes' is the number of bytes that your idbuf
152  * has space for.  Returns 0xff on error.
153  */
154 unsigned char
prom_get_idprom(char * idbuf,int num_bytes)155 prom_get_idprom(char *idbuf, int num_bytes)
156 {
157         int i;
158 
159 	/* make a copy of the idprom structure */
160 	for (i = 0; i < num_bytes; i++)
161 		idbuf[i] = ((char *)SUN3X_IDPROM)[i];
162 
163         return idbuf[0];
164 }
165