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/vr41xx | |
download | ohosKernel-a07bb8fd1299070229f0e8f3dcb57ffd5ef9870a.tar.gz ohosKernel-a07bb8fd1299070229f0e8f3dcb57ffd5ef9870a.zip |
Initial commit: OpenHarmony-v4.0-ReleaseOpenHarmony-v4.0-Release
Diffstat (limited to 'arch/mips/vr41xx')
-rw-r--r-- | arch/mips/vr41xx/Kconfig | 104 | ||||
-rw-r--r-- | arch/mips/vr41xx/Makefile | 5 | ||||
-rw-r--r-- | arch/mips/vr41xx/Platform | 29 | ||||
-rw-r--r-- | arch/mips/vr41xx/casio-e55/Makefile | 6 | ||||
-rw-r--r-- | arch/mips/vr41xx/casio-e55/setup.c | 27 | ||||
-rw-r--r-- | arch/mips/vr41xx/common/Makefile | 6 | ||||
-rw-r--r-- | arch/mips/vr41xx/common/bcu.c | 210 | ||||
-rw-r--r-- | arch/mips/vr41xx/common/cmu.c | 244 | ||||
-rw-r--r-- | arch/mips/vr41xx/common/giu.c | 110 | ||||
-rw-r--r-- | arch/mips/vr41xx/common/icu.c | 714 | ||||
-rw-r--r-- | arch/mips/vr41xx/common/init.c | 64 | ||||
-rw-r--r-- | arch/mips/vr41xx/common/irq.c | 106 | ||||
-rw-r--r-- | arch/mips/vr41xx/common/pmu.c | 123 | ||||
-rw-r--r-- | arch/mips/vr41xx/common/rtc.c | 105 | ||||
-rw-r--r-- | arch/mips/vr41xx/common/siu.c | 142 | ||||
-rw-r--r-- | arch/mips/vr41xx/common/type.c | 11 | ||||
-rw-r--r-- | arch/mips/vr41xx/ibm-workpad/Makefile | 6 | ||||
-rw-r--r-- | arch/mips/vr41xx/ibm-workpad/setup.c | 27 |
18 files changed, 2039 insertions, 0 deletions
diff --git a/arch/mips/vr41xx/Kconfig b/arch/mips/vr41xx/Kconfig new file mode 100644 index 000000000..e0b651db3 --- /dev/null +++ b/arch/mips/vr41xx/Kconfig | |||
@@ -0,0 +1,104 @@ | |||
1 | # SPDX-License-Identifier: GPL-2.0 | ||
2 | choice | ||
3 | prompt "Machine type" | ||
4 | depends on MACH_VR41XX | ||
5 | default TANBAC_TB022X | ||
6 | |||
7 | config CASIO_E55 | ||
8 | bool "CASIO CASSIOPEIA E-10/15/55/65" | ||
9 | select CEVT_R4K | ||
10 | select CSRC_R4K | ||
11 | select DMA_NONCOHERENT | ||
12 | select IRQ_MIPS_CPU | ||
13 | select ISA | ||
14 | select SYS_SUPPORTS_32BIT_KERNEL | ||
15 | select SYS_SUPPORTS_LITTLE_ENDIAN | ||
16 | |||
17 | config IBM_WORKPAD | ||
18 | bool "IBM WorkPad z50" | ||
19 | select CEVT_R4K | ||
20 | select CSRC_R4K | ||
21 | select DMA_NONCOHERENT | ||
22 | select IRQ_MIPS_CPU | ||
23 | select ISA | ||
24 | select SYS_SUPPORTS_32BIT_KERNEL | ||
25 | select SYS_SUPPORTS_LITTLE_ENDIAN | ||
26 | |||
27 | config TANBAC_TB022X | ||
28 | bool "TANBAC VR4131 multichip module and TANBAC VR4131DIMM" | ||
29 | select CEVT_R4K | ||
30 | select CSRC_R4K | ||
31 | select DMA_NONCOHERENT | ||
32 | select IRQ_MIPS_CPU | ||
33 | select HAVE_PCI | ||
34 | select SYS_SUPPORTS_32BIT_KERNEL | ||
35 | select SYS_SUPPORTS_LITTLE_ENDIAN | ||
36 | help | ||
37 | The TANBAC VR4131 multichip module(TB0225) and | ||
38 | the TANBAC VR4131DIMM(TB0229) are MIPS-based platforms | ||
39 | manufactured by TANBAC. | ||
40 | Please refer to <http://www.tanbac.co.jp/> | ||
41 | about VR4131 multichip module and VR4131DIMM. | ||
42 | |||
43 | config VICTOR_MPC30X | ||
44 | bool "Victor MP-C303/304" | ||
45 | select CEVT_R4K | ||
46 | select CSRC_R4K | ||
47 | select DMA_NONCOHERENT | ||
48 | select IRQ_MIPS_CPU | ||
49 | select HAVE_PCI | ||
50 | select PCI_VR41XX | ||
51 | select SYS_SUPPORTS_32BIT_KERNEL | ||
52 | select SYS_SUPPORTS_LITTLE_ENDIAN | ||
53 | |||
54 | config ZAO_CAPCELLA | ||
55 | bool "ZAO Networks Capcella" | ||
56 | select CEVT_R4K | ||
57 | select CSRC_R4K | ||
58 | select DMA_NONCOHERENT | ||
59 | select IRQ_MIPS_CPU | ||
60 | select HAVE_PCI | ||
61 | select PCI_VR41XX | ||
62 | select SYS_SUPPORTS_32BIT_KERNEL | ||
63 | select SYS_SUPPORTS_LITTLE_ENDIAN | ||
64 | |||
65 | endchoice | ||
66 | |||
67 | choice | ||
68 | prompt "Base board type" | ||
69 | depends on TANBAC_TB022X | ||
70 | default TANBAC_TB0287 | ||
71 | |||
72 | config TANBAC_TB0219 | ||
73 | bool "TANBAC DIMM Evaluation Kit(TB0219)" | ||
74 | select GPIO_VR41XX | ||
75 | select PCI_VR41XX | ||
76 | help | ||
77 | The TANBAC DIMM Evaluation Kit(TB0219) is a MIPS-based platform | ||
78 | manufactured by TANBAC. | ||
79 | Please refer to <http://www.tanbac.co.jp/> about DIMM Evaluation Kit. | ||
80 | |||
81 | config TANBAC_TB0226 | ||
82 | bool "TANBAC Mbase(TB0226)" | ||
83 | select GPIO_VR41XX | ||
84 | select PCI_VR41XX | ||
85 | help | ||
86 | The TANBAC Mbase(TB0226) is a MIPS-based platform | ||
87 | manufactured by TANBAC. | ||
88 | Please refer to <http://www.tanbac.co.jp/> about Mbase. | ||
89 | |||
90 | config TANBAC_TB0287 | ||
91 | bool "TANBAC Mini-ITX DIMM base(TB0287)" | ||
92 | select PCI_VR41XX | ||
93 | help | ||
94 | The TANBAC Mini-ITX DIMM base(TB0287) is a MIPS-based platform | ||
95 | manufactured by TANBAC. | ||
96 | Please refer to <http://www.tanbac.co.jp/> about Mini-ITX DIMM base. | ||
97 | |||
98 | endchoice | ||
99 | |||
100 | config PCI_VR41XX | ||
101 | bool "Add PCI control unit support of NEC VR4100 series" | ||
102 | depends on MACH_VR41XX && HAVE_PCI | ||
103 | default y | ||
104 | select PCI | ||
diff --git a/arch/mips/vr41xx/Makefile b/arch/mips/vr41xx/Makefile new file mode 100644 index 000000000..765020d5e --- /dev/null +++ b/arch/mips/vr41xx/Makefile | |||
@@ -0,0 +1,5 @@ | |||
1 | # SPDX-License-Identifier: GPL-2.0 | ||
2 | # | ||
3 | obj-$(CONFIG_MACH_VR41XX) += common/ | ||
4 | obj-$(CONFIG_CASIO_E55) += casio-e55/ | ||
5 | obj-$(CONFIG_IBM_WORKPAD) += ibm-workpad/ | ||
diff --git a/arch/mips/vr41xx/Platform b/arch/mips/vr41xx/Platform new file mode 100644 index 000000000..3f593a3e5 --- /dev/null +++ b/arch/mips/vr41xx/Platform | |||
@@ -0,0 +1,29 @@ | |||
1 | # | ||
2 | # NEC VR4100 series based machines | ||
3 | # | ||
4 | cflags-$(CONFIG_MACH_VR41XX) += -I$(srctree)/arch/mips/include/asm/mach-vr41xx | ||
5 | |||
6 | # | ||
7 | # CASIO CASSIPEIA E-55/65 (VR4111) | ||
8 | # | ||
9 | load-$(CONFIG_CASIO_E55) += 0xffffffff80004000 | ||
10 | |||
11 | # | ||
12 | # IBM WorkPad z50 (VR4121) | ||
13 | # | ||
14 | load-$(CONFIG_IBM_WORKPAD) += 0xffffffff80004000 | ||
15 | |||
16 | # | ||
17 | # TANBAC VR4131 multichip module(TB0225) and TANBAC VR4131DIMM(TB0229) (VR4131) | ||
18 | # | ||
19 | load-$(CONFIG_TANBAC_TB022X) += 0xffffffff80000000 | ||
20 | |||
21 | # | ||
22 | # Victor MP-C303/304 (VR4122) | ||
23 | # | ||
24 | load-$(CONFIG_VICTOR_MPC30X) += 0xffffffff80001000 | ||
25 | |||
26 | # | ||
27 | # ZAO Networks Capcella (VR4131) | ||
28 | # | ||
29 | load-$(CONFIG_ZAO_CAPCELLA) += 0xffffffff80000000 | ||
diff --git a/arch/mips/vr41xx/casio-e55/Makefile b/arch/mips/vr41xx/casio-e55/Makefile new file mode 100644 index 000000000..65d30d7c8 --- /dev/null +++ b/arch/mips/vr41xx/casio-e55/Makefile | |||
@@ -0,0 +1,6 @@ | |||
1 | # SPDX-License-Identifier: GPL-2.0-only | ||
2 | # | ||
3 | # Makefile for the CASIO CASSIOPEIA E-55/65 specific parts of the kernel | ||
4 | # | ||
5 | |||
6 | obj-y += setup.o | ||
diff --git a/arch/mips/vr41xx/casio-e55/setup.c b/arch/mips/vr41xx/casio-e55/setup.c new file mode 100644 index 000000000..25ea7f19f --- /dev/null +++ b/arch/mips/vr41xx/casio-e55/setup.c | |||
@@ -0,0 +1,27 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
2 | /* | ||
3 | * setup.c, Setup for the CASIO CASSIOPEIA E-11/15/55/65. | ||
4 | * | ||
5 | * Copyright (C) 2002-2006 Yoichi Yuasa <yuasa@linux-mips.org> | ||
6 | */ | ||
7 | #include <linux/init.h> | ||
8 | #include <linux/ioport.h> | ||
9 | |||
10 | #include <asm/io.h> | ||
11 | |||
12 | #define E55_ISA_IO_BASE 0x1400c000 | ||
13 | #define E55_ISA_IO_SIZE 0x03ff4000 | ||
14 | #define E55_ISA_IO_START 0 | ||
15 | #define E55_ISA_IO_END (E55_ISA_IO_SIZE - 1) | ||
16 | #define E55_IO_PORT_BASE KSEG1ADDR(E55_ISA_IO_BASE) | ||
17 | |||
18 | static int __init casio_e55_setup(void) | ||
19 | { | ||
20 | set_io_port_base(E55_IO_PORT_BASE); | ||
21 | ioport_resource.start = E55_ISA_IO_START; | ||
22 | ioport_resource.end = E55_ISA_IO_END; | ||
23 | |||
24 | return 0; | ||
25 | } | ||
26 | |||
27 | arch_initcall(casio_e55_setup); | ||
diff --git a/arch/mips/vr41xx/common/Makefile b/arch/mips/vr41xx/common/Makefile new file mode 100644 index 000000000..57d3eee29 --- /dev/null +++ b/arch/mips/vr41xx/common/Makefile | |||
@@ -0,0 +1,6 @@ | |||
1 | # SPDX-License-Identifier: GPL-2.0-only | ||
2 | # | ||
3 | # Makefile for common code of the NEC VR4100 series. | ||
4 | # | ||
5 | |||
6 | obj-y += bcu.o cmu.o giu.o icu.o init.o irq.o pmu.o rtc.o siu.o type.o | ||
diff --git a/arch/mips/vr41xx/common/bcu.c b/arch/mips/vr41xx/common/bcu.c new file mode 100644 index 000000000..0677d1779 --- /dev/null +++ b/arch/mips/vr41xx/common/bcu.c | |||
@@ -0,0 +1,210 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
2 | /* | ||
3 | * bcu.c, Bus Control Unit routines for the NEC VR4100 series. | ||
4 | * | ||
5 | * Copyright (C) 2002 MontaVista Software Inc. | ||
6 | * Author: Yoichi Yuasa <source@mvista.com> | ||
7 | * Copyright (C) 2003-2005 Yoichi Yuasa <yuasa@linux-mips.org> | ||
8 | */ | ||
9 | /* | ||
10 | * Changes: | ||
11 | * MontaVista Software Inc. <source@mvista.com> | ||
12 | * - New creation, NEC VR4122 and VR4131 are supported. | ||
13 | * - Added support for NEC VR4111 and VR4121. | ||
14 | * | ||
15 | * Yoichi Yuasa <yuasa@linux-mips.org> | ||
16 | * - Added support for NEC VR4133. | ||
17 | */ | ||
18 | #include <linux/export.h> | ||
19 | #include <linux/kernel.h> | ||
20 | #include <linux/smp.h> | ||
21 | #include <linux/types.h> | ||
22 | |||
23 | #include <asm/cpu-type.h> | ||
24 | #include <asm/cpu.h> | ||
25 | #include <asm/io.h> | ||
26 | |||
27 | #define CLKSPEEDREG_TYPE1 (void __iomem *)KSEG1ADDR(0x0b000014) | ||
28 | #define CLKSPEEDREG_TYPE2 (void __iomem *)KSEG1ADDR(0x0f000014) | ||
29 | #define CLKSP(x) ((x) & 0x001f) | ||
30 | #define CLKSP_VR4133(x) ((x) & 0x0007) | ||
31 | |||
32 | #define DIV2B 0x8000 | ||
33 | #define DIV3B 0x4000 | ||
34 | #define DIV4B 0x2000 | ||
35 | |||
36 | #define DIVT(x) (((x) & 0xf000) >> 12) | ||
37 | #define DIVVT(x) (((x) & 0x0f00) >> 8) | ||
38 | |||
39 | #define TDIVMODE(x) (2 << (((x) & 0x1000) >> 12)) | ||
40 | #define VTDIVMODE(x) (((x) & 0x0700) >> 8) | ||
41 | |||
42 | static unsigned long vr41xx_vtclock; | ||
43 | static unsigned long vr41xx_tclock; | ||
44 | |||
45 | unsigned long vr41xx_get_vtclock_frequency(void) | ||
46 | { | ||
47 | return vr41xx_vtclock; | ||
48 | } | ||
49 | |||
50 | EXPORT_SYMBOL_GPL(vr41xx_get_vtclock_frequency); | ||
51 | |||
52 | unsigned long vr41xx_get_tclock_frequency(void) | ||
53 | { | ||
54 | return vr41xx_tclock; | ||
55 | } | ||
56 | |||
57 | EXPORT_SYMBOL_GPL(vr41xx_get_tclock_frequency); | ||
58 | |||
59 | static inline uint16_t read_clkspeed(void) | ||
60 | { | ||
61 | switch (current_cpu_type()) { | ||
62 | case CPU_VR4111: | ||
63 | case CPU_VR4121: return readw(CLKSPEEDREG_TYPE1); | ||
64 | case CPU_VR4122: | ||
65 | case CPU_VR4131: | ||
66 | case CPU_VR4133: return readw(CLKSPEEDREG_TYPE2); | ||
67 | default: | ||
68 | printk(KERN_INFO "Unexpected CPU of NEC VR4100 series\n"); | ||
69 | break; | ||
70 | } | ||
71 | |||
72 | return 0; | ||
73 | } | ||
74 | |||
75 | static inline unsigned long calculate_pclock(uint16_t clkspeed) | ||
76 | { | ||
77 | unsigned long pclock = 0; | ||
78 | |||
79 | switch (current_cpu_type()) { | ||
80 | case CPU_VR4111: | ||
81 | case CPU_VR4121: | ||
82 | pclock = 18432000 * 64; | ||
83 | pclock /= CLKSP(clkspeed); | ||
84 | break; | ||
85 | case CPU_VR4122: | ||
86 | pclock = 18432000 * 98; | ||
87 | pclock /= CLKSP(clkspeed); | ||
88 | break; | ||
89 | case CPU_VR4131: | ||
90 | pclock = 18432000 * 108; | ||
91 | pclock /= CLKSP(clkspeed); | ||
92 | break; | ||
93 | case CPU_VR4133: | ||
94 | switch (CLKSP_VR4133(clkspeed)) { | ||
95 | case 0: | ||
96 | pclock = 133000000; | ||
97 | break; | ||
98 | case 1: | ||
99 | pclock = 149000000; | ||
100 | break; | ||
101 | case 2: | ||
102 | pclock = 165900000; | ||
103 | break; | ||
104 | case 3: | ||
105 | pclock = 199100000; | ||
106 | break; | ||
107 | case 4: | ||
108 | pclock = 265900000; | ||
109 | break; | ||
110 | default: | ||
111 | printk(KERN_INFO "Unknown PClock speed for NEC VR4133\n"); | ||
112 | break; | ||
113 | } | ||
114 | break; | ||
115 | default: | ||
116 | printk(KERN_INFO "Unexpected CPU of NEC VR4100 series\n"); | ||
117 | break; | ||
118 | } | ||
119 | |||
120 | printk(KERN_INFO "PClock: %ldHz\n", pclock); | ||
121 | |||
122 | return pclock; | ||
123 | } | ||
124 | |||
125 | static inline unsigned long calculate_vtclock(uint16_t clkspeed, unsigned long pclock) | ||
126 | { | ||
127 | unsigned long vtclock = 0; | ||
128 | |||
129 | switch (current_cpu_type()) { | ||
130 | case CPU_VR4111: | ||
131 | /* The NEC VR4111 doesn't have the VTClock. */ | ||
132 | break; | ||
133 | case CPU_VR4121: | ||
134 | vtclock = pclock; | ||
135 | /* DIVVT == 9 Divide by 1.5 . VTClock = (PClock * 6) / 9 */ | ||
136 | if (DIVVT(clkspeed) == 9) | ||
137 | vtclock = pclock * 6; | ||
138 | /* DIVVT == 10 Divide by 2.5 . VTClock = (PClock * 4) / 10 */ | ||
139 | else if (DIVVT(clkspeed) == 10) | ||
140 | vtclock = pclock * 4; | ||
141 | vtclock /= DIVVT(clkspeed); | ||
142 | printk(KERN_INFO "VTClock: %ldHz\n", vtclock); | ||
143 | break; | ||
144 | case CPU_VR4122: | ||
145 | if(VTDIVMODE(clkspeed) == 7) | ||
146 | vtclock = pclock / 1; | ||
147 | else if(VTDIVMODE(clkspeed) == 1) | ||
148 | vtclock = pclock / 2; | ||
149 | else | ||
150 | vtclock = pclock / VTDIVMODE(clkspeed); | ||
151 | printk(KERN_INFO "VTClock: %ldHz\n", vtclock); | ||
152 | break; | ||
153 | case CPU_VR4131: | ||
154 | case CPU_VR4133: | ||
155 | vtclock = pclock / VTDIVMODE(clkspeed); | ||
156 | printk(KERN_INFO "VTClock: %ldHz\n", vtclock); | ||
157 | break; | ||
158 | default: | ||
159 | printk(KERN_INFO "Unexpected CPU of NEC VR4100 series\n"); | ||
160 | break; | ||
161 | } | ||
162 | |||
163 | return vtclock; | ||
164 | } | ||
165 | |||
166 | static inline unsigned long calculate_tclock(uint16_t clkspeed, unsigned long pclock, | ||
167 | unsigned long vtclock) | ||
168 | { | ||
169 | unsigned long tclock = 0; | ||
170 | |||
171 | switch (current_cpu_type()) { | ||
172 | case CPU_VR4111: | ||
173 | if (!(clkspeed & DIV2B)) | ||
174 | tclock = pclock / 2; | ||
175 | else if (!(clkspeed & DIV3B)) | ||
176 | tclock = pclock / 3; | ||
177 | else if (!(clkspeed & DIV4B)) | ||
178 | tclock = pclock / 4; | ||
179 | break; | ||
180 | case CPU_VR4121: | ||
181 | tclock = pclock / DIVT(clkspeed); | ||
182 | break; | ||
183 | case CPU_VR4122: | ||
184 | case CPU_VR4131: | ||
185 | case CPU_VR4133: | ||
186 | tclock = vtclock / TDIVMODE(clkspeed); | ||
187 | break; | ||
188 | default: | ||
189 | printk(KERN_INFO "Unexpected CPU of NEC VR4100 series\n"); | ||
190 | break; | ||
191 | } | ||
192 | |||
193 | printk(KERN_INFO "TClock: %ldHz\n", tclock); | ||
194 | |||
195 | return tclock; | ||
196 | } | ||
197 | |||
198 | void vr41xx_calculate_clock_frequency(void) | ||
199 | { | ||
200 | unsigned long pclock; | ||
201 | uint16_t clkspeed; | ||
202 | |||
203 | clkspeed = read_clkspeed(); | ||
204 | |||
205 | pclock = calculate_pclock(clkspeed); | ||
206 | vr41xx_vtclock = calculate_vtclock(clkspeed, pclock); | ||
207 | vr41xx_tclock = calculate_tclock(clkspeed, pclock, vr41xx_vtclock); | ||
208 | } | ||
209 | |||
210 | EXPORT_SYMBOL_GPL(vr41xx_calculate_clock_frequency); | ||
diff --git a/arch/mips/vr41xx/common/cmu.c b/arch/mips/vr41xx/common/cmu.c new file mode 100644 index 000000000..b59ee5479 --- /dev/null +++ b/arch/mips/vr41xx/common/cmu.c | |||
@@ -0,0 +1,244 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
2 | /* | ||
3 | * cmu.c, Clock Mask Unit routines for the NEC VR4100 series. | ||
4 | * | ||
5 | * Copyright (C) 2001-2002 MontaVista Software Inc. | ||
6 | * Author: Yoichi Yuasa <source@mvista.com> | ||
7 | * Copyright (C) 2003-2005 Yoichi Yuasa <yuasa@linux-mips.org> | ||
8 | */ | ||
9 | /* | ||
10 | * Changes: | ||
11 | * MontaVista Software Inc. <source@mvista.com> | ||
12 | * - New creation, NEC VR4122 and VR4131 are supported. | ||
13 | * - Added support for NEC VR4111 and VR4121. | ||
14 | * | ||
15 | * Yoichi Yuasa <yuasa@linux-mips.org> | ||
16 | * - Added support for NEC VR4133. | ||
17 | */ | ||
18 | #include <linux/export.h> | ||
19 | #include <linux/init.h> | ||
20 | #include <linux/ioport.h> | ||
21 | #include <linux/smp.h> | ||
22 | #include <linux/spinlock.h> | ||
23 | #include <linux/types.h> | ||
24 | |||
25 | #include <asm/cpu.h> | ||
26 | #include <asm/io.h> | ||
27 | #include <asm/vr41xx/vr41xx.h> | ||
28 | |||
29 | #define CMU_TYPE1_BASE 0x0b000060UL | ||
30 | #define CMU_TYPE1_SIZE 0x4 | ||
31 | |||
32 | #define CMU_TYPE2_BASE 0x0f000060UL | ||
33 | #define CMU_TYPE2_SIZE 0x4 | ||
34 | |||
35 | #define CMU_TYPE3_BASE 0x0f000060UL | ||
36 | #define CMU_TYPE3_SIZE 0x8 | ||
37 | |||
38 | #define CMUCLKMSK 0x0 | ||
39 | #define MSKPIU 0x0001 | ||
40 | #define MSKSIU 0x0002 | ||
41 | #define MSKAIU 0x0004 | ||
42 | #define MSKKIU 0x0008 | ||
43 | #define MSKFIR 0x0010 | ||
44 | #define MSKDSIU 0x0820 | ||
45 | #define MSKCSI 0x0040 | ||
46 | #define MSKPCIU 0x0080 | ||
47 | #define MSKSSIU 0x0100 | ||
48 | #define MSKSHSP 0x0200 | ||
49 | #define MSKFFIR 0x0400 | ||
50 | #define MSKSCSI 0x1000 | ||
51 | #define MSKPPCIU 0x2000 | ||
52 | #define CMUCLKMSK2 0x4 | ||
53 | #define MSKCEU 0x0001 | ||
54 | #define MSKMAC0 0x0002 | ||
55 | #define MSKMAC1 0x0004 | ||
56 | |||
57 | static void __iomem *cmu_base; | ||
58 | static uint16_t cmuclkmsk, cmuclkmsk2; | ||
59 | static DEFINE_SPINLOCK(cmu_lock); | ||
60 | |||
61 | #define cmu_read(offset) readw(cmu_base + (offset)) | ||
62 | #define cmu_write(offset, value) writew((value), cmu_base + (offset)) | ||
63 | |||
64 | void vr41xx_supply_clock(vr41xx_clock_t clock) | ||
65 | { | ||
66 | spin_lock_irq(&cmu_lock); | ||
67 | |||
68 | switch (clock) { | ||
69 | case PIU_CLOCK: | ||
70 | cmuclkmsk |= MSKPIU; | ||
71 | break; | ||
72 | case SIU_CLOCK: | ||
73 | cmuclkmsk |= MSKSIU | MSKSSIU; | ||
74 | break; | ||
75 | case AIU_CLOCK: | ||
76 | cmuclkmsk |= MSKAIU; | ||
77 | break; | ||
78 | case KIU_CLOCK: | ||
79 | cmuclkmsk |= MSKKIU; | ||
80 | break; | ||
81 | case FIR_CLOCK: | ||
82 | cmuclkmsk |= MSKFIR | MSKFFIR; | ||
83 | break; | ||
84 | case DSIU_CLOCK: | ||
85 | if (current_cpu_type() == CPU_VR4111 || | ||
86 | current_cpu_type() == CPU_VR4121) | ||
87 | cmuclkmsk |= MSKDSIU; | ||
88 | else | ||
89 | cmuclkmsk |= MSKSIU | MSKDSIU; | ||
90 | break; | ||
91 | case CSI_CLOCK: | ||
92 | cmuclkmsk |= MSKCSI | MSKSCSI; | ||
93 | break; | ||
94 | case PCIU_CLOCK: | ||
95 | cmuclkmsk |= MSKPCIU; | ||
96 | break; | ||
97 | case HSP_CLOCK: | ||
98 | cmuclkmsk |= MSKSHSP; | ||
99 | break; | ||
100 | case PCI_CLOCK: | ||
101 | cmuclkmsk |= MSKPPCIU; | ||
102 | break; | ||
103 | case CEU_CLOCK: | ||
104 | cmuclkmsk2 |= MSKCEU; | ||
105 | break; | ||
106 | case ETHER0_CLOCK: | ||
107 | cmuclkmsk2 |= MSKMAC0; | ||
108 | break; | ||
109 | case ETHER1_CLOCK: | ||
110 | cmuclkmsk2 |= MSKMAC1; | ||
111 | break; | ||
112 | default: | ||
113 | break; | ||
114 | } | ||
115 | |||
116 | if (clock == CEU_CLOCK || clock == ETHER0_CLOCK || | ||
117 | clock == ETHER1_CLOCK) | ||
118 | cmu_write(CMUCLKMSK2, cmuclkmsk2); | ||
119 | else | ||
120 | cmu_write(CMUCLKMSK, cmuclkmsk); | ||
121 | |||
122 | spin_unlock_irq(&cmu_lock); | ||
123 | } | ||
124 | |||
125 | EXPORT_SYMBOL_GPL(vr41xx_supply_clock); | ||
126 | |||
127 | void vr41xx_mask_clock(vr41xx_clock_t clock) | ||
128 | { | ||
129 | spin_lock_irq(&cmu_lock); | ||
130 | |||
131 | switch (clock) { | ||
132 | case PIU_CLOCK: | ||
133 | cmuclkmsk &= ~MSKPIU; | ||
134 | break; | ||
135 | case SIU_CLOCK: | ||
136 | if (current_cpu_type() == CPU_VR4111 || | ||
137 | current_cpu_type() == CPU_VR4121) { | ||
138 | cmuclkmsk &= ~(MSKSIU | MSKSSIU); | ||
139 | } else { | ||
140 | if (cmuclkmsk & MSKDSIU) | ||
141 | cmuclkmsk &= ~MSKSSIU; | ||
142 | else | ||
143 | cmuclkmsk &= ~(MSKSIU | MSKSSIU); | ||
144 | } | ||
145 | break; | ||
146 | case AIU_CLOCK: | ||
147 | cmuclkmsk &= ~MSKAIU; | ||
148 | break; | ||
149 | case KIU_CLOCK: | ||
150 | cmuclkmsk &= ~MSKKIU; | ||
151 | break; | ||
152 | case FIR_CLOCK: | ||
153 | cmuclkmsk &= ~(MSKFIR | MSKFFIR); | ||
154 | break; | ||
155 | case DSIU_CLOCK: | ||
156 | if (current_cpu_type() == CPU_VR4111 || | ||
157 | current_cpu_type() == CPU_VR4121) { | ||
158 | cmuclkmsk &= ~MSKDSIU; | ||
159 | } else { | ||
160 | if (cmuclkmsk & MSKSSIU) | ||
161 | cmuclkmsk &= ~MSKDSIU; | ||
162 | else | ||
163 | cmuclkmsk &= ~(MSKSIU | MSKDSIU); | ||
164 | } | ||
165 | break; | ||
166 | case CSI_CLOCK: | ||
167 | cmuclkmsk &= ~(MSKCSI | MSKSCSI); | ||
168 | break; | ||
169 | case PCIU_CLOCK: | ||
170 | cmuclkmsk &= ~MSKPCIU; | ||
171 | break; | ||
172 | case HSP_CLOCK: | ||
173 | cmuclkmsk &= ~MSKSHSP; | ||
174 | break; | ||
175 | case PCI_CLOCK: | ||
176 | cmuclkmsk &= ~MSKPPCIU; | ||
177 | break; | ||
178 | case CEU_CLOCK: | ||
179 | cmuclkmsk2 &= ~MSKCEU; | ||
180 | break; | ||
181 | case ETHER0_CLOCK: | ||
182 | cmuclkmsk2 &= ~MSKMAC0; | ||
183 | break; | ||
184 | case ETHER1_CLOCK: | ||
185 | cmuclkmsk2 &= ~MSKMAC1; | ||
186 | break; | ||
187 | default: | ||
188 | break; | ||
189 | } | ||
190 | |||
191 | if (clock == CEU_CLOCK || clock == ETHER0_CLOCK || | ||
192 | clock == ETHER1_CLOCK) | ||
193 | cmu_write(CMUCLKMSK2, cmuclkmsk2); | ||
194 | else | ||
195 | cmu_write(CMUCLKMSK, cmuclkmsk); | ||
196 | |||
197 | spin_unlock_irq(&cmu_lock); | ||
198 | } | ||
199 | |||
200 | EXPORT_SYMBOL_GPL(vr41xx_mask_clock); | ||
201 | |||
202 | static int __init vr41xx_cmu_init(void) | ||
203 | { | ||
204 | unsigned long start, size; | ||
205 | |||
206 | switch (current_cpu_type()) { | ||
207 | case CPU_VR4111: | ||
208 | case CPU_VR4121: | ||
209 | start = CMU_TYPE1_BASE; | ||
210 | size = CMU_TYPE1_SIZE; | ||
211 | break; | ||
212 | case CPU_VR4122: | ||
213 | case CPU_VR4131: | ||
214 | start = CMU_TYPE2_BASE; | ||
215 | size = CMU_TYPE2_SIZE; | ||
216 | break; | ||
217 | case CPU_VR4133: | ||
218 | start = CMU_TYPE3_BASE; | ||
219 | size = CMU_TYPE3_SIZE; | ||
220 | break; | ||
221 | default: | ||
222 | panic("Unexpected CPU of NEC VR4100 series"); | ||
223 | break; | ||
224 | } | ||
225 | |||
226 | if (request_mem_region(start, size, "CMU") == NULL) | ||
227 | return -EBUSY; | ||
228 | |||
229 | cmu_base = ioremap(start, size); | ||
230 | if (cmu_base == NULL) { | ||
231 | release_mem_region(start, size); | ||
232 | return -EBUSY; | ||
233 | } | ||
234 | |||
235 | cmuclkmsk = cmu_read(CMUCLKMSK); | ||
236 | if (current_cpu_type() == CPU_VR4133) | ||
237 | cmuclkmsk2 = cmu_read(CMUCLKMSK2); | ||
238 | |||
239 | spin_lock_init(&cmu_lock); | ||
240 | |||
241 | return 0; | ||
242 | } | ||
243 | |||
244 | core_initcall(vr41xx_cmu_init); | ||
diff --git a/arch/mips/vr41xx/common/giu.c b/arch/mips/vr41xx/common/giu.c new file mode 100644 index 000000000..398c62641 --- /dev/null +++ b/arch/mips/vr41xx/common/giu.c | |||
@@ -0,0 +1,110 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
2 | /* | ||
3 | * NEC VR4100 series GIU platform device. | ||
4 | * | ||
5 | * Copyright (C) 2007 Yoichi Yuasa <yuasa@linux-mips.org> | ||
6 | */ | ||
7 | #include <linux/errno.h> | ||
8 | #include <linux/init.h> | ||
9 | #include <linux/smp.h> | ||
10 | #include <linux/ioport.h> | ||
11 | #include <linux/platform_device.h> | ||
12 | |||
13 | #include <asm/cpu.h> | ||
14 | #include <asm/vr41xx/giu.h> | ||
15 | #include <asm/vr41xx/irq.h> | ||
16 | |||
17 | static struct resource giu_50pins_pullupdown_resource[] __initdata = { | ||
18 | { | ||
19 | .start = 0x0b000100, | ||
20 | .end = 0x0b00011f, | ||
21 | .flags = IORESOURCE_MEM, | ||
22 | }, | ||
23 | { | ||
24 | .start = 0x0b0002e0, | ||
25 | .end = 0x0b0002e3, | ||
26 | .flags = IORESOURCE_MEM, | ||
27 | }, | ||
28 | { | ||
29 | .start = GIUINT_IRQ, | ||
30 | .end = GIUINT_IRQ, | ||
31 | .flags = IORESOURCE_IRQ, | ||
32 | }, | ||
33 | }; | ||
34 | |||
35 | static struct resource giu_36pins_resource[] __initdata = { | ||
36 | { | ||
37 | .start = 0x0f000140, | ||
38 | .end = 0x0f00015f, | ||
39 | .flags = IORESOURCE_MEM, | ||
40 | }, | ||
41 | { | ||
42 | .start = GIUINT_IRQ, | ||
43 | .end = GIUINT_IRQ, | ||
44 | .flags = IORESOURCE_IRQ, | ||
45 | }, | ||
46 | }; | ||
47 | |||
48 | static struct resource giu_48pins_resource[] __initdata = { | ||
49 | { | ||
50 | .start = 0x0f000140, | ||
51 | .end = 0x0f000167, | ||
52 | .flags = IORESOURCE_MEM, | ||
53 | }, | ||
54 | { | ||
55 | .start = GIUINT_IRQ, | ||
56 | .end = GIUINT_IRQ, | ||
57 | .flags = IORESOURCE_IRQ, | ||
58 | }, | ||
59 | }; | ||
60 | |||
61 | static int __init vr41xx_giu_add(void) | ||
62 | { | ||
63 | struct platform_device *pdev; | ||
64 | struct resource *res; | ||
65 | unsigned int num; | ||
66 | int retval; | ||
67 | |||
68 | pdev = platform_device_alloc("GIU", -1); | ||
69 | if (!pdev) | ||
70 | return -ENOMEM; | ||
71 | |||
72 | switch (current_cpu_type()) { | ||
73 | case CPU_VR4111: | ||
74 | case CPU_VR4121: | ||
75 | pdev->id = GPIO_50PINS_PULLUPDOWN; | ||
76 | res = giu_50pins_pullupdown_resource; | ||
77 | num = ARRAY_SIZE(giu_50pins_pullupdown_resource); | ||
78 | break; | ||
79 | case CPU_VR4122: | ||
80 | case CPU_VR4131: | ||
81 | pdev->id = GPIO_36PINS; | ||
82 | res = giu_36pins_resource; | ||
83 | num = ARRAY_SIZE(giu_36pins_resource); | ||
84 | break; | ||
85 | case CPU_VR4133: | ||
86 | pdev->id = GPIO_48PINS_EDGE_SELECT; | ||
87 | res = giu_48pins_resource; | ||
88 | num = ARRAY_SIZE(giu_48pins_resource); | ||
89 | break; | ||
90 | default: | ||
91 | retval = -ENODEV; | ||
92 | goto err_free_device; | ||
93 | } | ||
94 | |||
95 | retval = platform_device_add_resources(pdev, res, num); | ||
96 | if (retval) | ||
97 | goto err_free_device; | ||
98 | |||
99 | retval = platform_device_add(pdev); | ||
100 | if (retval) | ||
101 | goto err_free_device; | ||
102 | |||
103 | return 0; | ||
104 | |||
105 | err_free_device: | ||
106 | platform_device_put(pdev); | ||
107 | |||
108 | return retval; | ||
109 | } | ||
110 | device_initcall(vr41xx_giu_add); | ||
diff --git a/arch/mips/vr41xx/common/icu.c b/arch/mips/vr41xx/common/icu.c new file mode 100644 index 000000000..9240bcdbe --- /dev/null +++ b/arch/mips/vr41xx/common/icu.c | |||
@@ -0,0 +1,714 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
2 | /* | ||
3 | * icu.c, Interrupt Control Unit routines for the NEC VR4100 series. | ||
4 | * | ||
5 | * Copyright (C) 2001-2002 MontaVista Software Inc. | ||
6 | * Author: Yoichi Yuasa <source@mvista.com> | ||
7 | * Copyright (C) 2003-2006 Yoichi Yuasa <yuasa@linux-mips.org> | ||
8 | */ | ||
9 | /* | ||
10 | * Changes: | ||
11 | * MontaVista Software Inc. <source@mvista.com> | ||
12 | * - New creation, NEC VR4122 and VR4131 are supported. | ||
13 | * - Added support for NEC VR4111 and VR4121. | ||
14 | * | ||
15 | * Yoichi Yuasa <yuasa@linux-mips.org> | ||
16 | * - Coped with INTASSIGN of NEC VR4133. | ||
17 | */ | ||
18 | #include <linux/errno.h> | ||
19 | #include <linux/export.h> | ||
20 | #include <linux/init.h> | ||
21 | #include <linux/ioport.h> | ||
22 | #include <linux/irq.h> | ||
23 | #include <linux/smp.h> | ||
24 | #include <linux/types.h> | ||
25 | |||
26 | #include <asm/cpu.h> | ||
27 | #include <asm/io.h> | ||
28 | #include <asm/vr41xx/irq.h> | ||
29 | #include <asm/vr41xx/vr41xx.h> | ||
30 | |||
31 | static void __iomem *icu1_base; | ||
32 | static void __iomem *icu2_base; | ||
33 | |||
34 | static unsigned char sysint1_assign[16] = { | ||
35 | 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; | ||
36 | static unsigned char sysint2_assign[16] = { | ||
37 | 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; | ||
38 | |||
39 | #define ICU1_TYPE1_BASE 0x0b000080UL | ||
40 | #define ICU2_TYPE1_BASE 0x0b000200UL | ||
41 | |||
42 | #define ICU1_TYPE2_BASE 0x0f000080UL | ||
43 | #define ICU2_TYPE2_BASE 0x0f0000a0UL | ||
44 | |||
45 | #define ICU1_SIZE 0x20 | ||
46 | #define ICU2_SIZE 0x1c | ||
47 | |||
48 | #define SYSINT1REG 0x00 | ||
49 | #define PIUINTREG 0x02 | ||
50 | #define INTASSIGN0 0x04 | ||
51 | #define INTASSIGN1 0x06 | ||
52 | #define GIUINTLREG 0x08 | ||
53 | #define DSIUINTREG 0x0a | ||
54 | #define MSYSINT1REG 0x0c | ||
55 | #define MPIUINTREG 0x0e | ||
56 | #define MAIUINTREG 0x10 | ||
57 | #define MKIUINTREG 0x12 | ||
58 | #define MMACINTREG 0x12 | ||
59 | #define MGIUINTLREG 0x14 | ||
60 | #define MDSIUINTREG 0x16 | ||
61 | #define NMIREG 0x18 | ||
62 | #define SOFTREG 0x1a | ||
63 | #define INTASSIGN2 0x1c | ||
64 | #define INTASSIGN3 0x1e | ||
65 | |||
66 | #define SYSINT2REG 0x00 | ||
67 | #define GIUINTHREG 0x02 | ||
68 | #define FIRINTREG 0x04 | ||
69 | #define MSYSINT2REG 0x06 | ||
70 | #define MGIUINTHREG 0x08 | ||
71 | #define MFIRINTREG 0x0a | ||
72 | #define PCIINTREG 0x0c | ||
73 | #define PCIINT0 0x0001 | ||
74 | #define SCUINTREG 0x0e | ||
75 | #define SCUINT0 0x0001 | ||
76 | #define CSIINTREG 0x10 | ||
77 | #define MPCIINTREG 0x12 | ||
78 | #define MSCUINTREG 0x14 | ||
79 | #define MCSIINTREG 0x16 | ||
80 | #define BCUINTREG 0x18 | ||
81 | #define BCUINTR 0x0001 | ||
82 | #define MBCUINTREG 0x1a | ||
83 | |||
84 | #define SYSINT1_IRQ_TO_PIN(x) ((x) - SYSINT1_IRQ_BASE) /* Pin 0-15 */ | ||
85 | #define SYSINT2_IRQ_TO_PIN(x) ((x) - SYSINT2_IRQ_BASE) /* Pin 0-15 */ | ||
86 | |||
87 | #define INT_TO_IRQ(x) ((x) + 2) /* Int0-4 -> IRQ2-6 */ | ||
88 | |||
89 | #define icu1_read(offset) readw(icu1_base + (offset)) | ||
90 | #define icu1_write(offset, value) writew((value), icu1_base + (offset)) | ||
91 | |||
92 | #define icu2_read(offset) readw(icu2_base + (offset)) | ||
93 | #define icu2_write(offset, value) writew((value), icu2_base + (offset)) | ||
94 | |||
95 | #define INTASSIGN_MAX 4 | ||
96 | #define INTASSIGN_MASK 0x0007 | ||
97 | |||
98 | static inline uint16_t icu1_set(uint8_t offset, uint16_t set) | ||
99 | { | ||
100 | uint16_t data; | ||
101 | |||
102 | data = icu1_read(offset); | ||
103 | data |= set; | ||
104 | icu1_write(offset, data); | ||
105 | |||
106 | return data; | ||
107 | } | ||
108 | |||
109 | static inline uint16_t icu1_clear(uint8_t offset, uint16_t clear) | ||
110 | { | ||
111 | uint16_t data; | ||
112 | |||
113 | data = icu1_read(offset); | ||
114 | data &= ~clear; | ||
115 | icu1_write(offset, data); | ||
116 | |||
117 | return data; | ||
118 | } | ||
119 | |||
120 | static inline uint16_t icu2_set(uint8_t offset, uint16_t set) | ||
121 | { | ||
122 | uint16_t data; | ||
123 | |||
124 | data = icu2_read(offset); | ||
125 | data |= set; | ||
126 | icu2_write(offset, data); | ||
127 | |||
128 | return data; | ||
129 | } | ||
130 | |||
131 | static inline uint16_t icu2_clear(uint8_t offset, uint16_t clear) | ||
132 | { | ||
133 | uint16_t data; | ||
134 | |||
135 | data = icu2_read(offset); | ||
136 | data &= ~clear; | ||
137 | icu2_write(offset, data); | ||
138 | |||
139 | return data; | ||
140 | } | ||
141 | |||
142 | void vr41xx_enable_piuint(uint16_t mask) | ||
143 | { | ||
144 | struct irq_desc *desc = irq_to_desc(PIU_IRQ); | ||
145 | unsigned long flags; | ||
146 | |||
147 | if (current_cpu_type() == CPU_VR4111 || | ||
148 | current_cpu_type() == CPU_VR4121) { | ||
149 | raw_spin_lock_irqsave(&desc->lock, flags); | ||
150 | icu1_set(MPIUINTREG, mask); | ||
151 | raw_spin_unlock_irqrestore(&desc->lock, flags); | ||
152 | } | ||
153 | } | ||
154 | |||
155 | EXPORT_SYMBOL(vr41xx_enable_piuint); | ||
156 | |||
157 | void vr41xx_disable_piuint(uint16_t mask) | ||
158 | { | ||
159 | struct irq_desc *desc = irq_to_desc(PIU_IRQ); | ||
160 | unsigned long flags; | ||
161 | |||
162 | if (current_cpu_type() == CPU_VR4111 || | ||
163 | current_cpu_type() == CPU_VR4121) { | ||
164 | raw_spin_lock_irqsave(&desc->lock, flags); | ||
165 | icu1_clear(MPIUINTREG, mask); | ||
166 | raw_spin_unlock_irqrestore(&desc->lock, flags); | ||
167 | } | ||
168 | } | ||
169 | |||
170 | EXPORT_SYMBOL(vr41xx_disable_piuint); | ||
171 | |||
172 | void vr41xx_enable_aiuint(uint16_t mask) | ||
173 | { | ||
174 | struct irq_desc *desc = irq_to_desc(AIU_IRQ); | ||
175 | unsigned long flags; | ||
176 | |||
177 | if (current_cpu_type() == CPU_VR4111 || | ||
178 | current_cpu_type() == CPU_VR4121) { | ||
179 | raw_spin_lock_irqsave(&desc->lock, flags); | ||
180 | icu1_set(MAIUINTREG, mask); | ||
181 | raw_spin_unlock_irqrestore(&desc->lock, flags); | ||
182 | } | ||
183 | } | ||
184 | |||
185 | EXPORT_SYMBOL(vr41xx_enable_aiuint); | ||
186 | |||
187 | void vr41xx_disable_aiuint(uint16_t mask) | ||
188 | { | ||
189 | struct irq_desc *desc = irq_to_desc(AIU_IRQ); | ||
190 | unsigned long flags; | ||
191 | |||
192 | if (current_cpu_type() == CPU_VR4111 || | ||
193 | current_cpu_type() == CPU_VR4121) { | ||
194 | raw_spin_lock_irqsave(&desc->lock, flags); | ||
195 | icu1_clear(MAIUINTREG, mask); | ||
196 | raw_spin_unlock_irqrestore(&desc->lock, flags); | ||
197 | } | ||
198 | } | ||
199 | |||
200 | EXPORT_SYMBOL(vr41xx_disable_aiuint); | ||
201 | |||
202 | void vr41xx_enable_kiuint(uint16_t mask) | ||
203 | { | ||
204 | struct irq_desc *desc = irq_to_desc(KIU_IRQ); | ||
205 | unsigned long flags; | ||
206 | |||
207 | if (current_cpu_type() == CPU_VR4111 || | ||
208 | current_cpu_type() == CPU_VR4121) { | ||
209 | raw_spin_lock_irqsave(&desc->lock, flags); | ||
210 | icu1_set(MKIUINTREG, mask); | ||
211 | raw_spin_unlock_irqrestore(&desc->lock, flags); | ||
212 | } | ||
213 | } | ||
214 | |||
215 | EXPORT_SYMBOL(vr41xx_enable_kiuint); | ||
216 | |||
217 | void vr41xx_disable_kiuint(uint16_t mask) | ||
218 | { | ||
219 | struct irq_desc *desc = irq_to_desc(KIU_IRQ); | ||
220 | unsigned long flags; | ||
221 | |||
222 | if (current_cpu_type() == CPU_VR4111 || | ||
223 | current_cpu_type() == CPU_VR4121) { | ||
224 | raw_spin_lock_irqsave(&desc->lock, flags); | ||
225 | icu1_clear(MKIUINTREG, mask); | ||
226 | raw_spin_unlock_irqrestore(&desc->lock, flags); | ||
227 | } | ||
228 | } | ||
229 | |||
230 | EXPORT_SYMBOL(vr41xx_disable_kiuint); | ||
231 | |||
232 | void vr41xx_enable_macint(uint16_t mask) | ||
233 | { | ||
234 | struct irq_desc *desc = irq_to_desc(ETHERNET_IRQ); | ||
235 | unsigned long flags; | ||
236 | |||
237 | raw_spin_lock_irqsave(&desc->lock, flags); | ||
238 | icu1_set(MMACINTREG, mask); | ||
239 | raw_spin_unlock_irqrestore(&desc->lock, flags); | ||
240 | } | ||
241 | |||
242 | EXPORT_SYMBOL(vr41xx_enable_macint); | ||
243 | |||
244 | void vr41xx_disable_macint(uint16_t mask) | ||
245 | { | ||
246 | struct irq_desc *desc = irq_to_desc(ETHERNET_IRQ); | ||
247 | unsigned long flags; | ||
248 | |||
249 | raw_spin_lock_irqsave(&desc->lock, flags); | ||
250 | icu1_clear(MMACINTREG, mask); | ||
251 | raw_spin_unlock_irqrestore(&desc->lock, flags); | ||
252 | } | ||
253 | |||
254 | EXPORT_SYMBOL(vr41xx_disable_macint); | ||
255 | |||
256 | void vr41xx_enable_dsiuint(uint16_t mask) | ||
257 | { | ||
258 | struct irq_desc *desc = irq_to_desc(DSIU_IRQ); | ||
259 | unsigned long flags; | ||
260 | |||
261 | raw_spin_lock_irqsave(&desc->lock, flags); | ||
262 | icu1_set(MDSIUINTREG, mask); | ||
263 | raw_spin_unlock_irqrestore(&desc->lock, flags); | ||
264 | } | ||
265 | |||
266 | EXPORT_SYMBOL(vr41xx_enable_dsiuint); | ||
267 | |||
268 | void vr41xx_disable_dsiuint(uint16_t mask) | ||
269 | { | ||
270 | struct irq_desc *desc = irq_to_desc(DSIU_IRQ); | ||
271 | unsigned long flags; | ||
272 | |||
273 | raw_spin_lock_irqsave(&desc->lock, flags); | ||
274 | icu1_clear(MDSIUINTREG, mask); | ||
275 | raw_spin_unlock_irqrestore(&desc->lock, flags); | ||
276 | } | ||
277 | |||
278 | EXPORT_SYMBOL(vr41xx_disable_dsiuint); | ||
279 | |||
280 | void vr41xx_enable_firint(uint16_t mask) | ||
281 | { | ||
282 | struct irq_desc *desc = irq_to_desc(FIR_IRQ); | ||
283 | unsigned long flags; | ||
284 | |||
285 | raw_spin_lock_irqsave(&desc->lock, flags); | ||
286 | icu2_set(MFIRINTREG, mask); | ||
287 | raw_spin_unlock_irqrestore(&desc->lock, flags); | ||
288 | } | ||
289 | |||
290 | EXPORT_SYMBOL(vr41xx_enable_firint); | ||
291 | |||
292 | void vr41xx_disable_firint(uint16_t mask) | ||
293 | { | ||
294 | struct irq_desc *desc = irq_to_desc(FIR_IRQ); | ||
295 | unsigned long flags; | ||
296 | |||
297 | raw_spin_lock_irqsave(&desc->lock, flags); | ||
298 | icu2_clear(MFIRINTREG, mask); | ||
299 | raw_spin_unlock_irqrestore(&desc->lock, flags); | ||
300 | } | ||
301 | |||
302 | EXPORT_SYMBOL(vr41xx_disable_firint); | ||
303 | |||
304 | void vr41xx_enable_pciint(void) | ||
305 | { | ||
306 | struct irq_desc *desc = irq_to_desc(PCI_IRQ); | ||
307 | unsigned long flags; | ||
308 | |||
309 | if (current_cpu_type() == CPU_VR4122 || | ||
310 | current_cpu_type() == CPU_VR4131 || | ||
311 | current_cpu_type() == CPU_VR4133) { | ||
312 | raw_spin_lock_irqsave(&desc->lock, flags); | ||
313 | icu2_write(MPCIINTREG, PCIINT0); | ||
314 | raw_spin_unlock_irqrestore(&desc->lock, flags); | ||
315 | } | ||
316 | } | ||
317 | |||
318 | EXPORT_SYMBOL(vr41xx_enable_pciint); | ||
319 | |||
320 | void vr41xx_disable_pciint(void) | ||
321 | { | ||
322 | struct irq_desc *desc = irq_to_desc(PCI_IRQ); | ||
323 | unsigned long flags; | ||
324 | |||
325 | if (current_cpu_type() == CPU_VR4122 || | ||
326 | current_cpu_type() == CPU_VR4131 || | ||
327 | current_cpu_type() == CPU_VR4133) { | ||
328 | raw_spin_lock_irqsave(&desc->lock, flags); | ||
329 | icu2_write(MPCIINTREG, 0); | ||
330 | raw_spin_unlock_irqrestore(&desc->lock, flags); | ||
331 | } | ||
332 | } | ||
333 | |||
334 | EXPORT_SYMBOL(vr41xx_disable_pciint); | ||
335 | |||
336 | void vr41xx_enable_scuint(void) | ||
337 | { | ||
338 | struct irq_desc *desc = irq_to_desc(SCU_IRQ); | ||
339 | unsigned long flags; | ||
340 | |||
341 | if (current_cpu_type() == CPU_VR4122 || | ||
342 | current_cpu_type() == CPU_VR4131 || | ||
343 | current_cpu_type() == CPU_VR4133) { | ||
344 | raw_spin_lock_irqsave(&desc->lock, flags); | ||
345 | icu2_write(MSCUINTREG, SCUINT0); | ||
346 | raw_spin_unlock_irqrestore(&desc->lock, flags); | ||
347 | } | ||
348 | } | ||
349 | |||
350 | EXPORT_SYMBOL(vr41xx_enable_scuint); | ||
351 | |||
352 | void vr41xx_disable_scuint(void) | ||
353 | { | ||
354 | struct irq_desc *desc = irq_to_desc(SCU_IRQ); | ||
355 | unsigned long flags; | ||
356 | |||
357 | if (current_cpu_type() == CPU_VR4122 || | ||
358 | current_cpu_type() == CPU_VR4131 || | ||
359 | current_cpu_type() == CPU_VR4133) { | ||
360 | raw_spin_lock_irqsave(&desc->lock, flags); | ||
361 | icu2_write(MSCUINTREG, 0); | ||
362 | raw_spin_unlock_irqrestore(&desc->lock, flags); | ||
363 | } | ||
364 | } | ||
365 | |||
366 | EXPORT_SYMBOL(vr41xx_disable_scuint); | ||
367 | |||
368 | void vr41xx_enable_csiint(uint16_t mask) | ||
369 | { | ||
370 | struct irq_desc *desc = irq_to_desc(CSI_IRQ); | ||
371 | unsigned long flags; | ||
372 | |||
373 | if (current_cpu_type() == CPU_VR4122 || | ||
374 | current_cpu_type() == CPU_VR4131 || | ||
375 | current_cpu_type() == CPU_VR4133) { | ||
376 | raw_spin_lock_irqsave(&desc->lock, flags); | ||
377 | icu2_set(MCSIINTREG, mask); | ||
378 | raw_spin_unlock_irqrestore(&desc->lock, flags); | ||
379 | } | ||
380 | } | ||
381 | |||
382 | EXPORT_SYMBOL(vr41xx_enable_csiint); | ||
383 | |||
384 | void vr41xx_disable_csiint(uint16_t mask) | ||
385 | { | ||
386 | struct irq_desc *desc = irq_to_desc(CSI_IRQ); | ||
387 | unsigned long flags; | ||
388 | |||
389 | if (current_cpu_type() == CPU_VR4122 || | ||
390 | current_cpu_type() == CPU_VR4131 || | ||
391 | current_cpu_type() == CPU_VR4133) { | ||
392 | raw_spin_lock_irqsave(&desc->lock, flags); | ||
393 | icu2_clear(MCSIINTREG, mask); | ||
394 | raw_spin_unlock_irqrestore(&desc->lock, flags); | ||
395 | } | ||
396 | } | ||
397 | |||
398 | EXPORT_SYMBOL(vr41xx_disable_csiint); | ||
399 | |||
400 | void vr41xx_enable_bcuint(void) | ||
401 | { | ||
402 | struct irq_desc *desc = irq_to_desc(BCU_IRQ); | ||
403 | unsigned long flags; | ||
404 | |||
405 | if (current_cpu_type() == CPU_VR4122 || | ||
406 | current_cpu_type() == CPU_VR4131 || | ||
407 | current_cpu_type() == CPU_VR4133) { | ||
408 | raw_spin_lock_irqsave(&desc->lock, flags); | ||
409 | icu2_write(MBCUINTREG, BCUINTR); | ||
410 | raw_spin_unlock_irqrestore(&desc->lock, flags); | ||
411 | } | ||
412 | } | ||
413 | |||
414 | EXPORT_SYMBOL(vr41xx_enable_bcuint); | ||
415 | |||
416 | void vr41xx_disable_bcuint(void) | ||
417 | { | ||
418 | struct irq_desc *desc = irq_to_desc(BCU_IRQ); | ||
419 | unsigned long flags; | ||
420 | |||
421 | if (current_cpu_type() == CPU_VR4122 || | ||
422 | current_cpu_type() == CPU_VR4131 || | ||
423 | current_cpu_type() == CPU_VR4133) { | ||
424 | raw_spin_lock_irqsave(&desc->lock, flags); | ||
425 | icu2_write(MBCUINTREG, 0); | ||
426 | raw_spin_unlock_irqrestore(&desc->lock, flags); | ||
427 | } | ||
428 | } | ||
429 | |||
430 | EXPORT_SYMBOL(vr41xx_disable_bcuint); | ||
431 | |||
432 | static void disable_sysint1_irq(struct irq_data *d) | ||
433 | { | ||
434 | icu1_clear(MSYSINT1REG, 1 << SYSINT1_IRQ_TO_PIN(d->irq)); | ||
435 | } | ||
436 | |||
437 | static void enable_sysint1_irq(struct irq_data *d) | ||
438 | { | ||
439 | icu1_set(MSYSINT1REG, 1 << SYSINT1_IRQ_TO_PIN(d->irq)); | ||
440 | } | ||
441 | |||
442 | static struct irq_chip sysint1_irq_type = { | ||
443 | .name = "SYSINT1", | ||
444 | .irq_mask = disable_sysint1_irq, | ||
445 | .irq_unmask = enable_sysint1_irq, | ||
446 | }; | ||
447 | |||
448 | static void disable_sysint2_irq(struct irq_data *d) | ||
449 | { | ||
450 | icu2_clear(MSYSINT2REG, 1 << SYSINT2_IRQ_TO_PIN(d->irq)); | ||
451 | } | ||
452 | |||
453 | static void enable_sysint2_irq(struct irq_data *d) | ||
454 | { | ||
455 | icu2_set(MSYSINT2REG, 1 << SYSINT2_IRQ_TO_PIN(d->irq)); | ||
456 | } | ||
457 | |||
458 | static struct irq_chip sysint2_irq_type = { | ||
459 | .name = "SYSINT2", | ||
460 | .irq_mask = disable_sysint2_irq, | ||
461 | .irq_unmask = enable_sysint2_irq, | ||
462 | }; | ||
463 | |||
464 | static inline int set_sysint1_assign(unsigned int irq, unsigned char assign) | ||
465 | { | ||
466 | struct irq_desc *desc = irq_to_desc(irq); | ||
467 | uint16_t intassign0, intassign1; | ||
468 | unsigned int pin; | ||
469 | |||
470 | pin = SYSINT1_IRQ_TO_PIN(irq); | ||
471 | |||
472 | raw_spin_lock_irq(&desc->lock); | ||
473 | |||
474 | intassign0 = icu1_read(INTASSIGN0); | ||
475 | intassign1 = icu1_read(INTASSIGN1); | ||
476 | |||
477 | switch (pin) { | ||
478 | case 0: | ||
479 | intassign0 &= ~INTASSIGN_MASK; | ||
480 | intassign0 |= (uint16_t)assign; | ||
481 | break; | ||
482 | case 1: | ||
483 | intassign0 &= ~(INTASSIGN_MASK << 3); | ||
484 | intassign0 |= (uint16_t)assign << 3; | ||
485 | break; | ||
486 | case 2: | ||
487 | intassign0 &= ~(INTASSIGN_MASK << 6); | ||
488 | intassign0 |= (uint16_t)assign << 6; | ||
489 | break; | ||
490 | case 3: | ||
491 | intassign0 &= ~(INTASSIGN_MASK << 9); | ||
492 | intassign0 |= (uint16_t)assign << 9; | ||
493 | break; | ||
494 | case 8: | ||
495 | intassign0 &= ~(INTASSIGN_MASK << 12); | ||
496 | intassign0 |= (uint16_t)assign << 12; | ||
497 | break; | ||
498 | case 9: | ||
499 | intassign1 &= ~INTASSIGN_MASK; | ||
500 | intassign1 |= (uint16_t)assign; | ||
501 | break; | ||
502 | case 11: | ||
503 | intassign1 &= ~(INTASSIGN_MASK << 6); | ||
504 | intassign1 |= (uint16_t)assign << 6; | ||
505 | break; | ||
506 | case 12: | ||
507 | intassign1 &= ~(INTASSIGN_MASK << 9); | ||
508 | intassign1 |= (uint16_t)assign << 9; | ||
509 | break; | ||
510 | default: | ||
511 | raw_spin_unlock_irq(&desc->lock); | ||
512 | return -EINVAL; | ||
513 | } | ||
514 | |||
515 | sysint1_assign[pin] = assign; | ||
516 | icu1_write(INTASSIGN0, intassign0); | ||
517 | icu1_write(INTASSIGN1, intassign1); | ||
518 | |||
519 | raw_spin_unlock_irq(&desc->lock); | ||
520 | |||
521 | return 0; | ||
522 | } | ||
523 | |||
524 | static inline int set_sysint2_assign(unsigned int irq, unsigned char assign) | ||
525 | { | ||
526 | struct irq_desc *desc = irq_to_desc(irq); | ||
527 | uint16_t intassign2, intassign3; | ||
528 | unsigned int pin; | ||
529 | |||
530 | pin = SYSINT2_IRQ_TO_PIN(irq); | ||
531 | |||
532 | raw_spin_lock_irq(&desc->lock); | ||
533 | |||
534 | intassign2 = icu1_read(INTASSIGN2); | ||
535 | intassign3 = icu1_read(INTASSIGN3); | ||
536 | |||
537 | switch (pin) { | ||
538 | case 0: | ||
539 | intassign2 &= ~INTASSIGN_MASK; | ||
540 | intassign2 |= (uint16_t)assign; | ||
541 | break; | ||
542 | case 1: | ||
543 | intassign2 &= ~(INTASSIGN_MASK << 3); | ||
544 | intassign2 |= (uint16_t)assign << 3; | ||
545 | break; | ||
546 | case 3: | ||
547 | intassign2 &= ~(INTASSIGN_MASK << 6); | ||
548 | intassign2 |= (uint16_t)assign << 6; | ||
549 | break; | ||
550 | case 4: | ||
551 | intassign2 &= ~(INTASSIGN_MASK << 9); | ||
552 | intassign2 |= (uint16_t)assign << 9; | ||
553 | break; | ||
554 | case 5: | ||
555 | intassign2 &= ~(INTASSIGN_MASK << 12); | ||
556 | intassign2 |= (uint16_t)assign << 12; | ||
557 | break; | ||
558 | case 6: | ||
559 | intassign3 &= ~INTASSIGN_MASK; | ||
560 | intassign3 |= (uint16_t)assign; | ||
561 | break; | ||
562 | case 7: | ||
563 | intassign3 &= ~(INTASSIGN_MASK << 3); | ||
564 | intassign3 |= (uint16_t)assign << 3; | ||
565 | break; | ||
566 | case 8: | ||
567 | intassign3 &= ~(INTASSIGN_MASK << 6); | ||
568 | intassign3 |= (uint16_t)assign << 6; | ||
569 | break; | ||
570 | case 9: | ||
571 | intassign3 &= ~(INTASSIGN_MASK << 9); | ||
572 | intassign3 |= (uint16_t)assign << 9; | ||
573 | break; | ||
574 | case 10: | ||
575 | intassign3 &= ~(INTASSIGN_MASK << 12); | ||
576 | intassign3 |= (uint16_t)assign << 12; | ||
577 | break; | ||
578 | default: | ||
579 | raw_spin_unlock_irq(&desc->lock); | ||
580 | return -EINVAL; | ||
581 | } | ||
582 | |||
583 | sysint2_assign[pin] = assign; | ||
584 | icu1_write(INTASSIGN2, intassign2); | ||
585 | icu1_write(INTASSIGN3, intassign3); | ||
586 | |||
587 | raw_spin_unlock_irq(&desc->lock); | ||
588 | |||
589 | return 0; | ||
590 | } | ||
591 | |||
592 | int vr41xx_set_intassign(unsigned int irq, unsigned char intassign) | ||
593 | { | ||
594 | int retval = -EINVAL; | ||
595 | |||
596 | if (current_cpu_type() != CPU_VR4133) | ||
597 | return -EINVAL; | ||
598 | |||
599 | if (intassign > INTASSIGN_MAX) | ||
600 | return -EINVAL; | ||
601 | |||
602 | if (irq >= SYSINT1_IRQ_BASE && irq <= SYSINT1_IRQ_LAST) | ||
603 | retval = set_sysint1_assign(irq, intassign); | ||
604 | else if (irq >= SYSINT2_IRQ_BASE && irq <= SYSINT2_IRQ_LAST) | ||
605 | retval = set_sysint2_assign(irq, intassign); | ||
606 | |||
607 | return retval; | ||
608 | } | ||
609 | |||
610 | EXPORT_SYMBOL(vr41xx_set_intassign); | ||
611 | |||
612 | static int icu_get_irq(unsigned int irq) | ||
613 | { | ||
614 | uint16_t pend1, pend2; | ||
615 | uint16_t mask1, mask2; | ||
616 | int i; | ||
617 | |||
618 | pend1 = icu1_read(SYSINT1REG); | ||
619 | mask1 = icu1_read(MSYSINT1REG); | ||
620 | |||
621 | pend2 = icu2_read(SYSINT2REG); | ||
622 | mask2 = icu2_read(MSYSINT2REG); | ||
623 | |||
624 | mask1 &= pend1; | ||
625 | mask2 &= pend2; | ||
626 | |||
627 | if (mask1) { | ||
628 | for (i = 0; i < 16; i++) { | ||
629 | if (irq == INT_TO_IRQ(sysint1_assign[i]) && (mask1 & (1 << i))) | ||
630 | return SYSINT1_IRQ(i); | ||
631 | } | ||
632 | } | ||
633 | |||
634 | if (mask2) { | ||
635 | for (i = 0; i < 16; i++) { | ||
636 | if (irq == INT_TO_IRQ(sysint2_assign[i]) && (mask2 & (1 << i))) | ||
637 | return SYSINT2_IRQ(i); | ||
638 | } | ||
639 | } | ||
640 | |||
641 | printk(KERN_ERR "spurious ICU interrupt: %04x,%04x\n", pend1, pend2); | ||
642 | |||
643 | return -1; | ||
644 | } | ||
645 | |||
646 | static int __init vr41xx_icu_init(void) | ||
647 | { | ||
648 | unsigned long icu1_start, icu2_start; | ||
649 | int i; | ||
650 | |||
651 | switch (current_cpu_type()) { | ||
652 | case CPU_VR4111: | ||
653 | case CPU_VR4121: | ||
654 | icu1_start = ICU1_TYPE1_BASE; | ||
655 | icu2_start = ICU2_TYPE1_BASE; | ||
656 | break; | ||
657 | case CPU_VR4122: | ||
658 | case CPU_VR4131: | ||
659 | case CPU_VR4133: | ||
660 | icu1_start = ICU1_TYPE2_BASE; | ||
661 | icu2_start = ICU2_TYPE2_BASE; | ||
662 | break; | ||
663 | default: | ||
664 | printk(KERN_ERR "ICU: Unexpected CPU of NEC VR4100 series\n"); | ||
665 | return -ENODEV; | ||
666 | } | ||
667 | |||
668 | if (request_mem_region(icu1_start, ICU1_SIZE, "ICU") == NULL) | ||
669 | return -EBUSY; | ||
670 | |||
671 | if (request_mem_region(icu2_start, ICU2_SIZE, "ICU") == NULL) { | ||
672 | release_mem_region(icu1_start, ICU1_SIZE); | ||
673 | return -EBUSY; | ||
674 | } | ||
675 | |||
676 | icu1_base = ioremap(icu1_start, ICU1_SIZE); | ||
677 | if (icu1_base == NULL) { | ||
678 | release_mem_region(icu1_start, ICU1_SIZE); | ||
679 | release_mem_region(icu2_start, ICU2_SIZE); | ||
680 | return -ENOMEM; | ||
681 | } | ||
682 | |||
683 | icu2_base = ioremap(icu2_start, ICU2_SIZE); | ||
684 | if (icu2_base == NULL) { | ||
685 | iounmap(icu1_base); | ||
686 | release_mem_region(icu1_start, ICU1_SIZE); | ||
687 | release_mem_region(icu2_start, ICU2_SIZE); | ||
688 | return -ENOMEM; | ||
689 | } | ||
690 | |||
691 | icu1_write(MSYSINT1REG, 0); | ||
692 | icu1_write(MGIUINTLREG, 0xffff); | ||
693 | |||
694 | icu2_write(MSYSINT2REG, 0); | ||
695 | icu2_write(MGIUINTHREG, 0xffff); | ||
696 | |||
697 | for (i = SYSINT1_IRQ_BASE; i <= SYSINT1_IRQ_LAST; i++) | ||
698 | irq_set_chip_and_handler(i, &sysint1_irq_type, | ||
699 | handle_level_irq); | ||
700 | |||
701 | for (i = SYSINT2_IRQ_BASE; i <= SYSINT2_IRQ_LAST; i++) | ||
702 | irq_set_chip_and_handler(i, &sysint2_irq_type, | ||
703 | handle_level_irq); | ||
704 | |||
705 | cascade_irq(INT0_IRQ, icu_get_irq); | ||
706 | cascade_irq(INT1_IRQ, icu_get_irq); | ||
707 | cascade_irq(INT2_IRQ, icu_get_irq); | ||
708 | cascade_irq(INT3_IRQ, icu_get_irq); | ||
709 | cascade_irq(INT4_IRQ, icu_get_irq); | ||
710 | |||
711 | return 0; | ||
712 | } | ||
713 | |||
714 | core_initcall(vr41xx_icu_init); | ||
diff --git a/arch/mips/vr41xx/common/init.c b/arch/mips/vr41xx/common/init.c new file mode 100644 index 000000000..ca53ac306 --- /dev/null +++ b/arch/mips/vr41xx/common/init.c | |||
@@ -0,0 +1,64 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
2 | /* | ||
3 | * init.c, Common initialization routines for NEC VR4100 series. | ||
4 | * | ||
5 | * Copyright (C) 2003-2009 Yoichi Yuasa <yuasa@linux-mips.org> | ||
6 | */ | ||
7 | #include <linux/init.h> | ||
8 | #include <linux/ioport.h> | ||
9 | #include <linux/irq.h> | ||
10 | #include <linux/string.h> | ||
11 | |||
12 | #include <asm/bootinfo.h> | ||
13 | #include <asm/time.h> | ||
14 | #include <asm/vr41xx/irq.h> | ||
15 | #include <asm/vr41xx/vr41xx.h> | ||
16 | |||
17 | #define IO_MEM_RESOURCE_START 0UL | ||
18 | #define IO_MEM_RESOURCE_END 0x1fffffffUL | ||
19 | |||
20 | static void __init iomem_resource_init(void) | ||
21 | { | ||
22 | iomem_resource.start = IO_MEM_RESOURCE_START; | ||
23 | iomem_resource.end = IO_MEM_RESOURCE_END; | ||
24 | } | ||
25 | |||
26 | void __init plat_time_init(void) | ||
27 | { | ||
28 | unsigned long tclock; | ||
29 | |||
30 | vr41xx_calculate_clock_frequency(); | ||
31 | |||
32 | tclock = vr41xx_get_tclock_frequency(); | ||
33 | if (current_cpu_data.processor_id == PRID_VR4131_REV2_0 || | ||
34 | current_cpu_data.processor_id == PRID_VR4131_REV2_1) | ||
35 | mips_hpt_frequency = tclock / 2; | ||
36 | else | ||
37 | mips_hpt_frequency = tclock / 4; | ||
38 | } | ||
39 | |||
40 | void __init plat_mem_setup(void) | ||
41 | { | ||
42 | iomem_resource_init(); | ||
43 | |||
44 | vr41xx_siu_setup(); | ||
45 | } | ||
46 | |||
47 | void __init prom_init(void) | ||
48 | { | ||
49 | int argc, i; | ||
50 | char **argv; | ||
51 | |||
52 | argc = fw_arg0; | ||
53 | argv = (char **)fw_arg1; | ||
54 | |||
55 | for (i = 1; i < argc; i++) { | ||
56 | strlcat(arcs_cmdline, argv[i], COMMAND_LINE_SIZE); | ||
57 | if (i < (argc - 1)) | ||
58 | strlcat(arcs_cmdline, " ", COMMAND_LINE_SIZE); | ||
59 | } | ||
60 | } | ||
61 | |||
62 | void __init prom_free_prom_memory(void) | ||
63 | { | ||
64 | } | ||
diff --git a/arch/mips/vr41xx/common/irq.c b/arch/mips/vr41xx/common/irq.c new file mode 100644 index 000000000..8f68446ff --- /dev/null +++ b/arch/mips/vr41xx/common/irq.c | |||
@@ -0,0 +1,106 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
2 | /* | ||
3 | * Interrupt handing routines for NEC VR4100 series. | ||
4 | * | ||
5 | * Copyright (C) 2005-2007 Yoichi Yuasa <yuasa@linux-mips.org> | ||
6 | */ | ||
7 | #include <linux/export.h> | ||
8 | #include <linux/interrupt.h> | ||
9 | #include <linux/irq.h> | ||
10 | |||
11 | #include <asm/irq_cpu.h> | ||
12 | #include <asm/vr41xx/irq.h> | ||
13 | |||
14 | typedef struct irq_cascade { | ||
15 | int (*get_irq)(unsigned int); | ||
16 | } irq_cascade_t; | ||
17 | |||
18 | static irq_cascade_t irq_cascade[NR_IRQS] __cacheline_aligned; | ||
19 | |||
20 | int cascade_irq(unsigned int irq, int (*get_irq)(unsigned int)) | ||
21 | { | ||
22 | int retval = 0; | ||
23 | |||
24 | if (irq >= NR_IRQS) | ||
25 | return -EINVAL; | ||
26 | |||
27 | if (irq_cascade[irq].get_irq != NULL) | ||
28 | free_irq(irq, NULL); | ||
29 | |||
30 | irq_cascade[irq].get_irq = get_irq; | ||
31 | |||
32 | if (get_irq != NULL) { | ||
33 | retval = request_irq(irq, no_action, IRQF_NO_THREAD, | ||
34 | "cascade", NULL); | ||
35 | if (retval < 0) | ||
36 | irq_cascade[irq].get_irq = NULL; | ||
37 | } | ||
38 | |||
39 | return retval; | ||
40 | } | ||
41 | |||
42 | EXPORT_SYMBOL_GPL(cascade_irq); | ||
43 | |||
44 | static void irq_dispatch(unsigned int irq) | ||
45 | { | ||
46 | irq_cascade_t *cascade; | ||
47 | |||
48 | if (irq >= NR_IRQS) { | ||
49 | atomic_inc(&irq_err_count); | ||
50 | return; | ||
51 | } | ||
52 | |||
53 | cascade = irq_cascade + irq; | ||
54 | if (cascade->get_irq != NULL) { | ||
55 | struct irq_desc *desc = irq_to_desc(irq); | ||
56 | struct irq_data *idata = irq_desc_get_irq_data(desc); | ||
57 | struct irq_chip *chip = irq_desc_get_chip(desc); | ||
58 | int ret; | ||
59 | |||
60 | if (chip->irq_mask_ack) | ||
61 | chip->irq_mask_ack(idata); | ||
62 | else { | ||
63 | chip->irq_mask(idata); | ||
64 | chip->irq_ack(idata); | ||
65 | } | ||
66 | ret = cascade->get_irq(irq); | ||
67 | irq = ret; | ||
68 | if (ret < 0) | ||
69 | atomic_inc(&irq_err_count); | ||
70 | else | ||
71 | irq_dispatch(irq); | ||
72 | if (!irqd_irq_disabled(idata) && chip->irq_unmask) | ||
73 | chip->irq_unmask(idata); | ||
74 | } else | ||
75 | do_IRQ(irq); | ||
76 | } | ||
77 | |||
78 | asmlinkage void plat_irq_dispatch(void) | ||
79 | { | ||
80 | unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM; | ||
81 | |||
82 | if (pending & CAUSEF_IP7) | ||
83 | do_IRQ(TIMER_IRQ); | ||
84 | else if (pending & 0x7800) { | ||
85 | if (pending & CAUSEF_IP3) | ||
86 | irq_dispatch(INT1_IRQ); | ||
87 | else if (pending & CAUSEF_IP4) | ||
88 | irq_dispatch(INT2_IRQ); | ||
89 | else if (pending & CAUSEF_IP5) | ||
90 | irq_dispatch(INT3_IRQ); | ||
91 | else if (pending & CAUSEF_IP6) | ||
92 | irq_dispatch(INT4_IRQ); | ||
93 | } else if (pending & CAUSEF_IP2) | ||
94 | irq_dispatch(INT0_IRQ); | ||
95 | else if (pending & CAUSEF_IP0) | ||
96 | do_IRQ(MIPS_SOFTINT0_IRQ); | ||
97 | else if (pending & CAUSEF_IP1) | ||
98 | do_IRQ(MIPS_SOFTINT1_IRQ); | ||
99 | else | ||
100 | spurious_interrupt(); | ||
101 | } | ||
102 | |||
103 | void __init arch_init_irq(void) | ||
104 | { | ||
105 | mips_cpu_irq_init(); | ||
106 | } | ||
diff --git a/arch/mips/vr41xx/common/pmu.c b/arch/mips/vr41xx/common/pmu.c new file mode 100644 index 000000000..93cc7e0b3 --- /dev/null +++ b/arch/mips/vr41xx/common/pmu.c | |||
@@ -0,0 +1,123 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
2 | /* | ||
3 | * pmu.c, Power Management Unit routines for NEC VR4100 series. | ||
4 | * | ||
5 | * Copyright (C) 2003-2007 Yoichi Yuasa <yuasa@linux-mips.org> | ||
6 | */ | ||
7 | #include <linux/cpu.h> | ||
8 | #include <linux/errno.h> | ||
9 | #include <linux/init.h> | ||
10 | #include <linux/ioport.h> | ||
11 | #include <linux/kernel.h> | ||
12 | #include <linux/pm.h> | ||
13 | #include <linux/sched.h> | ||
14 | #include <linux/types.h> | ||
15 | |||
16 | #include <asm/cacheflush.h> | ||
17 | #include <asm/cpu.h> | ||
18 | #include <asm/idle.h> | ||
19 | #include <asm/io.h> | ||
20 | #include <asm/processor.h> | ||
21 | #include <asm/reboot.h> | ||
22 | |||
23 | #define PMU_TYPE1_BASE 0x0b0000a0UL | ||
24 | #define PMU_TYPE1_SIZE 0x0eUL | ||
25 | |||
26 | #define PMU_TYPE2_BASE 0x0f0000c0UL | ||
27 | #define PMU_TYPE2_SIZE 0x10UL | ||
28 | |||
29 | #define PMUCNT2REG 0x06 | ||
30 | #define SOFTRST 0x0010 | ||
31 | |||
32 | static void __iomem *pmu_base; | ||
33 | |||
34 | #define pmu_read(offset) readw(pmu_base + (offset)) | ||
35 | #define pmu_write(offset, value) writew((value), pmu_base + (offset)) | ||
36 | |||
37 | static void __cpuidle vr41xx_cpu_wait(void) | ||
38 | { | ||
39 | local_irq_disable(); | ||
40 | if (!need_resched()) | ||
41 | /* | ||
42 | * "standby" sets IE bit of the CP0_STATUS to 1. | ||
43 | */ | ||
44 | __asm__("standby;\n"); | ||
45 | else | ||
46 | local_irq_enable(); | ||
47 | } | ||
48 | |||
49 | static inline void software_reset(void) | ||
50 | { | ||
51 | uint16_t pmucnt2; | ||
52 | |||
53 | switch (current_cpu_type()) { | ||
54 | case CPU_VR4122: | ||
55 | case CPU_VR4131: | ||
56 | case CPU_VR4133: | ||
57 | pmucnt2 = pmu_read(PMUCNT2REG); | ||
58 | pmucnt2 |= SOFTRST; | ||
59 | pmu_write(PMUCNT2REG, pmucnt2); | ||
60 | break; | ||
61 | default: | ||
62 | set_c0_status(ST0_BEV | ST0_ERL); | ||
63 | change_c0_config(CONF_CM_CMASK, CONF_CM_UNCACHED); | ||
64 | __flush_cache_all(); | ||
65 | write_c0_wired(0); | ||
66 | __asm__("jr %0"::"r"(0xbfc00000)); | ||
67 | break; | ||
68 | } | ||
69 | } | ||
70 | |||
71 | static void vr41xx_restart(char *command) | ||
72 | { | ||
73 | local_irq_disable(); | ||
74 | software_reset(); | ||
75 | while (1) ; | ||
76 | } | ||
77 | |||
78 | static void vr41xx_halt(void) | ||
79 | { | ||
80 | local_irq_disable(); | ||
81 | printk(KERN_NOTICE "\nYou can turn off the power supply\n"); | ||
82 | __asm__("hibernate;\n"); | ||
83 | } | ||
84 | |||
85 | static int __init vr41xx_pmu_init(void) | ||
86 | { | ||
87 | unsigned long start, size; | ||
88 | |||
89 | switch (current_cpu_type()) { | ||
90 | case CPU_VR4111: | ||
91 | case CPU_VR4121: | ||
92 | start = PMU_TYPE1_BASE; | ||
93 | size = PMU_TYPE1_SIZE; | ||
94 | break; | ||
95 | case CPU_VR4122: | ||
96 | case CPU_VR4131: | ||
97 | case CPU_VR4133: | ||
98 | start = PMU_TYPE2_BASE; | ||
99 | size = PMU_TYPE2_SIZE; | ||
100 | break; | ||
101 | default: | ||
102 | printk("Unexpected CPU of NEC VR4100 series\n"); | ||
103 | return -ENODEV; | ||
104 | } | ||
105 | |||
106 | if (request_mem_region(start, size, "PMU") == NULL) | ||
107 | return -EBUSY; | ||
108 | |||
109 | pmu_base = ioremap(start, size); | ||
110 | if (pmu_base == NULL) { | ||
111 | release_mem_region(start, size); | ||
112 | return -EBUSY; | ||
113 | } | ||
114 | |||
115 | cpu_wait = vr41xx_cpu_wait; | ||
116 | _machine_restart = vr41xx_restart; | ||
117 | _machine_halt = vr41xx_halt; | ||
118 | pm_power_off = vr41xx_halt; | ||
119 | |||
120 | return 0; | ||
121 | } | ||
122 | |||
123 | core_initcall(vr41xx_pmu_init); | ||
diff --git a/arch/mips/vr41xx/common/rtc.c b/arch/mips/vr41xx/common/rtc.c new file mode 100644 index 000000000..5ce668317 --- /dev/null +++ b/arch/mips/vr41xx/common/rtc.c | |||
@@ -0,0 +1,105 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
2 | /* | ||
3 | * NEC VR4100 series RTC platform device. | ||
4 | * | ||
5 | * Copyright (C) 2007 Yoichi Yuasa <yuasa@linux-mips.org> | ||
6 | */ | ||
7 | #include <linux/errno.h> | ||
8 | #include <linux/init.h> | ||
9 | #include <linux/smp.h> | ||
10 | #include <linux/ioport.h> | ||
11 | #include <linux/platform_device.h> | ||
12 | |||
13 | #include <asm/cpu.h> | ||
14 | #include <asm/vr41xx/irq.h> | ||
15 | |||
16 | static struct resource rtc_type1_resource[] __initdata = { | ||
17 | { | ||
18 | .start = 0x0b0000c0, | ||
19 | .end = 0x0b0000df, | ||
20 | .flags = IORESOURCE_MEM, | ||
21 | }, | ||
22 | { | ||
23 | .start = 0x0b0001c0, | ||
24 | .end = 0x0b0001df, | ||
25 | .flags = IORESOURCE_MEM, | ||
26 | }, | ||
27 | { | ||
28 | .start = ELAPSEDTIME_IRQ, | ||
29 | .end = ELAPSEDTIME_IRQ, | ||
30 | .flags = IORESOURCE_IRQ, | ||
31 | }, | ||
32 | { | ||
33 | .start = RTCLONG1_IRQ, | ||
34 | .end = RTCLONG1_IRQ, | ||
35 | .flags = IORESOURCE_IRQ, | ||
36 | }, | ||
37 | }; | ||
38 | |||
39 | static struct resource rtc_type2_resource[] __initdata = { | ||
40 | { | ||
41 | .start = 0x0f000100, | ||
42 | .end = 0x0f00011f, | ||
43 | .flags = IORESOURCE_MEM, | ||
44 | }, | ||
45 | { | ||
46 | .start = 0x0f000120, | ||
47 | .end = 0x0f00013f, | ||
48 | .flags = IORESOURCE_MEM, | ||
49 | }, | ||
50 | { | ||
51 | .start = ELAPSEDTIME_IRQ, | ||
52 | .end = ELAPSEDTIME_IRQ, | ||
53 | .flags = IORESOURCE_IRQ, | ||
54 | }, | ||
55 | { | ||
56 | .start = RTCLONG1_IRQ, | ||
57 | .end = RTCLONG1_IRQ, | ||
58 | .flags = IORESOURCE_IRQ, | ||
59 | }, | ||
60 | }; | ||
61 | |||
62 | static int __init vr41xx_rtc_add(void) | ||
63 | { | ||
64 | struct platform_device *pdev; | ||
65 | struct resource *res; | ||
66 | unsigned int num; | ||
67 | int retval; | ||
68 | |||
69 | pdev = platform_device_alloc("RTC", -1); | ||
70 | if (!pdev) | ||
71 | return -ENOMEM; | ||
72 | |||
73 | switch (current_cpu_type()) { | ||
74 | case CPU_VR4111: | ||
75 | case CPU_VR4121: | ||
76 | res = rtc_type1_resource; | ||
77 | num = ARRAY_SIZE(rtc_type1_resource); | ||
78 | break; | ||
79 | case CPU_VR4122: | ||
80 | case CPU_VR4131: | ||
81 | case CPU_VR4133: | ||
82 | res = rtc_type2_resource; | ||
83 | num = ARRAY_SIZE(rtc_type2_resource); | ||
84 | break; | ||
85 | default: | ||
86 | retval = -ENODEV; | ||
87 | goto err_free_device; | ||
88 | } | ||
89 | |||
90 | retval = platform_device_add_resources(pdev, res, num); | ||
91 | if (retval) | ||
92 | goto err_free_device; | ||
93 | |||
94 | retval = platform_device_add(pdev); | ||
95 | if (retval) | ||
96 | goto err_free_device; | ||
97 | |||
98 | return 0; | ||
99 | |||
100 | err_free_device: | ||
101 | platform_device_put(pdev); | ||
102 | |||
103 | return retval; | ||
104 | } | ||
105 | device_initcall(vr41xx_rtc_add); | ||
diff --git a/arch/mips/vr41xx/common/siu.c b/arch/mips/vr41xx/common/siu.c new file mode 100644 index 000000000..b37a79154 --- /dev/null +++ b/arch/mips/vr41xx/common/siu.c | |||
@@ -0,0 +1,142 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
2 | /* | ||
3 | * NEC VR4100 series SIU platform device. | ||
4 | * | ||
5 | * Copyright (C) 2007-2008 Yoichi Yuasa <yuasa@linux-mips.org> | ||
6 | */ | ||
7 | #include <linux/errno.h> | ||
8 | #include <linux/init.h> | ||
9 | #include <linux/ioport.h> | ||
10 | #include <linux/platform_device.h> | ||
11 | #include <linux/serial_core.h> | ||
12 | #include <linux/irq.h> | ||
13 | |||
14 | #include <asm/cpu.h> | ||
15 | #include <asm/vr41xx/siu.h> | ||
16 | |||
17 | static unsigned int siu_type1_ports[SIU_PORTS_MAX] __initdata = { | ||
18 | PORT_VR41XX_SIU, | ||
19 | PORT_UNKNOWN, | ||
20 | }; | ||
21 | |||
22 | static struct resource siu_type1_resource[] __initdata = { | ||
23 | { | ||
24 | .start = 0x0c000000, | ||
25 | .end = 0x0c00000a, | ||
26 | .flags = IORESOURCE_MEM, | ||
27 | }, | ||
28 | { | ||
29 | .start = SIU_IRQ, | ||
30 | .end = SIU_IRQ, | ||
31 | .flags = IORESOURCE_IRQ, | ||
32 | }, | ||
33 | }; | ||
34 | |||
35 | static unsigned int siu_type2_ports[SIU_PORTS_MAX] __initdata = { | ||
36 | PORT_VR41XX_SIU, | ||
37 | PORT_VR41XX_DSIU, | ||
38 | }; | ||
39 | |||
40 | static struct resource siu_type2_resource[] __initdata = { | ||
41 | { | ||
42 | .start = 0x0f000800, | ||
43 | .end = 0x0f00080a, | ||
44 | .flags = IORESOURCE_MEM, | ||
45 | }, | ||
46 | { | ||
47 | .start = 0x0f000820, | ||
48 | .end = 0x0f000829, | ||
49 | .flags = IORESOURCE_MEM, | ||
50 | }, | ||
51 | { | ||
52 | .start = SIU_IRQ, | ||
53 | .end = SIU_IRQ, | ||
54 | .flags = IORESOURCE_IRQ, | ||
55 | }, | ||
56 | { | ||
57 | .start = DSIU_IRQ, | ||
58 | .end = DSIU_IRQ, | ||
59 | .flags = IORESOURCE_IRQ, | ||
60 | }, | ||
61 | }; | ||
62 | |||
63 | static int __init vr41xx_siu_add(void) | ||
64 | { | ||
65 | struct platform_device *pdev; | ||
66 | struct resource *res; | ||
67 | unsigned int num; | ||
68 | int retval; | ||
69 | |||
70 | pdev = platform_device_alloc("SIU", -1); | ||
71 | if (!pdev) | ||
72 | return -ENOMEM; | ||
73 | |||
74 | switch (current_cpu_type()) { | ||
75 | case CPU_VR4111: | ||
76 | case CPU_VR4121: | ||
77 | pdev->dev.platform_data = siu_type1_ports; | ||
78 | res = siu_type1_resource; | ||
79 | num = ARRAY_SIZE(siu_type1_resource); | ||
80 | break; | ||
81 | case CPU_VR4122: | ||
82 | case CPU_VR4131: | ||
83 | case CPU_VR4133: | ||
84 | pdev->dev.platform_data = siu_type2_ports; | ||
85 | res = siu_type2_resource; | ||
86 | num = ARRAY_SIZE(siu_type2_resource); | ||
87 | break; | ||
88 | default: | ||
89 | retval = -ENODEV; | ||
90 | goto err_free_device; | ||
91 | } | ||
92 | |||
93 | retval = platform_device_add_resources(pdev, res, num); | ||
94 | if (retval) | ||
95 | goto err_free_device; | ||
96 | |||
97 | retval = platform_device_add(pdev); | ||
98 | if (retval) | ||
99 | goto err_free_device; | ||
100 | |||
101 | return 0; | ||
102 | |||
103 | err_free_device: | ||
104 | platform_device_put(pdev); | ||
105 | |||
106 | return retval; | ||
107 | } | ||
108 | device_initcall(vr41xx_siu_add); | ||
109 | |||
110 | void __init vr41xx_siu_setup(void) | ||
111 | { | ||
112 | struct uart_port port; | ||
113 | struct resource *res; | ||
114 | unsigned int *type; | ||
115 | int i; | ||
116 | |||
117 | switch (current_cpu_type()) { | ||
118 | case CPU_VR4111: | ||
119 | case CPU_VR4121: | ||
120 | type = siu_type1_ports; | ||
121 | res = siu_type1_resource; | ||
122 | break; | ||
123 | case CPU_VR4122: | ||
124 | case CPU_VR4131: | ||
125 | case CPU_VR4133: | ||
126 | type = siu_type2_ports; | ||
127 | res = siu_type2_resource; | ||
128 | break; | ||
129 | default: | ||
130 | return; | ||
131 | } | ||
132 | |||
133 | for (i = 0; i < SIU_PORTS_MAX; i++) { | ||
134 | port.line = i; | ||
135 | port.type = type[i]; | ||
136 | if (port.type == PORT_UNKNOWN) | ||
137 | break; | ||
138 | port.mapbase = res[i].start; | ||
139 | port.membase = (unsigned char __iomem *)KSEG1ADDR(res[i].start); | ||
140 | vr41xx_siu_early_setup(&port); | ||
141 | } | ||
142 | } | ||
diff --git a/arch/mips/vr41xx/common/type.c b/arch/mips/vr41xx/common/type.c new file mode 100644 index 000000000..dddcf1eaa --- /dev/null +++ b/arch/mips/vr41xx/common/type.c | |||
@@ -0,0 +1,11 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
2 | /* | ||
3 | * type.c, System type for NEC VR4100 series. | ||
4 | * | ||
5 | * Copyright (C) 2005 Yoichi Yuasa <yuasa@linux-mips.org> | ||
6 | */ | ||
7 | |||
8 | const char *get_system_type(void) | ||
9 | { | ||
10 | return "NEC VR4100 series"; | ||
11 | } | ||
diff --git a/arch/mips/vr41xx/ibm-workpad/Makefile b/arch/mips/vr41xx/ibm-workpad/Makefile new file mode 100644 index 000000000..c7be704e7 --- /dev/null +++ b/arch/mips/vr41xx/ibm-workpad/Makefile | |||
@@ -0,0 +1,6 @@ | |||
1 | # SPDX-License-Identifier: GPL-2.0-only | ||
2 | # | ||
3 | # Makefile for the IBM WorkPad z50 specific parts of the kernel | ||
4 | # | ||
5 | |||
6 | obj-y += setup.o | ||
diff --git a/arch/mips/vr41xx/ibm-workpad/setup.c b/arch/mips/vr41xx/ibm-workpad/setup.c new file mode 100644 index 000000000..7e14d65c5 --- /dev/null +++ b/arch/mips/vr41xx/ibm-workpad/setup.c | |||
@@ -0,0 +1,27 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
2 | /* | ||
3 | * setup.c, Setup for the IBM WorkPad z50. | ||
4 | * | ||
5 | * Copyright (C) 2002-2006 Yoichi Yuasa <yuasa@linux-mips.org> | ||
6 | */ | ||
7 | #include <linux/init.h> | ||
8 | #include <linux/ioport.h> | ||
9 | |||
10 | #include <asm/io.h> | ||
11 | |||
12 | #define WORKPAD_ISA_IO_BASE 0x15000000 | ||
13 | #define WORKPAD_ISA_IO_SIZE 0x03000000 | ||
14 | #define WORKPAD_ISA_IO_START 0 | ||
15 | #define WORKPAD_ISA_IO_END (WORKPAD_ISA_IO_SIZE - 1) | ||
16 | #define WORKPAD_IO_PORT_BASE KSEG1ADDR(WORKPAD_ISA_IO_BASE) | ||
17 | |||
18 | static int __init ibm_workpad_setup(void) | ||
19 | { | ||
20 | set_io_port_base(WORKPAD_IO_PORT_BASE); | ||
21 | ioport_resource.start = WORKPAD_ISA_IO_START; | ||
22 | ioport_resource.end = WORKPAD_ISA_IO_END; | ||
23 | |||
24 | return 0; | ||
25 | } | ||
26 | |||
27 | arch_initcall(ibm_workpad_setup); | ||