aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/vr41xx
diff options
context:
space:
mode:
authorWe-unite <3205135446@qq.com>2025-03-08 22:04:20 +0800
committerWe-unite <3205135446@qq.com>2025-03-08 22:04:20 +0800
commita07bb8fd1299070229f0e8f3dcb57ffd5ef9870a (patch)
tree84f21bd0bf7071bc5fc7dd989e77d7ceb5476682 /arch/mips/vr41xx
downloadohosKernel-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/Kconfig104
-rw-r--r--arch/mips/vr41xx/Makefile5
-rw-r--r--arch/mips/vr41xx/Platform29
-rw-r--r--arch/mips/vr41xx/casio-e55/Makefile6
-rw-r--r--arch/mips/vr41xx/casio-e55/setup.c27
-rw-r--r--arch/mips/vr41xx/common/Makefile6
-rw-r--r--arch/mips/vr41xx/common/bcu.c210
-rw-r--r--arch/mips/vr41xx/common/cmu.c244
-rw-r--r--arch/mips/vr41xx/common/giu.c110
-rw-r--r--arch/mips/vr41xx/common/icu.c714
-rw-r--r--arch/mips/vr41xx/common/init.c64
-rw-r--r--arch/mips/vr41xx/common/irq.c106
-rw-r--r--arch/mips/vr41xx/common/pmu.c123
-rw-r--r--arch/mips/vr41xx/common/rtc.c105
-rw-r--r--arch/mips/vr41xx/common/siu.c142
-rw-r--r--arch/mips/vr41xx/common/type.c11
-rw-r--r--arch/mips/vr41xx/ibm-workpad/Makefile6
-rw-r--r--arch/mips/vr41xx/ibm-workpad/setup.c27
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
2choice
3 prompt "Machine type"
4 depends on MACH_VR41XX
5 default TANBAC_TB022X
6
7config 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
17config 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
27config 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
43config 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
54config 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
65endchoice
66
67choice
68 prompt "Base board type"
69 depends on TANBAC_TB022X
70 default TANBAC_TB0287
71
72config 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
81config 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
90config 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
98endchoice
99
100config 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#
3obj-$(CONFIG_MACH_VR41XX) += common/
4obj-$(CONFIG_CASIO_E55) += casio-e55/
5obj-$(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#
4cflags-$(CONFIG_MACH_VR41XX) += -I$(srctree)/arch/mips/include/asm/mach-vr41xx
5
6#
7# CASIO CASSIPEIA E-55/65 (VR4111)
8#
9load-$(CONFIG_CASIO_E55) += 0xffffffff80004000
10
11#
12# IBM WorkPad z50 (VR4121)
13#
14load-$(CONFIG_IBM_WORKPAD) += 0xffffffff80004000
15
16#
17# TANBAC VR4131 multichip module(TB0225) and TANBAC VR4131DIMM(TB0229) (VR4131)
18#
19load-$(CONFIG_TANBAC_TB022X) += 0xffffffff80000000
20
21#
22# Victor MP-C303/304 (VR4122)
23#
24load-$(CONFIG_VICTOR_MPC30X) += 0xffffffff80001000
25
26#
27# ZAO Networks Capcella (VR4131)
28#
29load-$(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
6obj-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
18static 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
27arch_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
6obj-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
42static unsigned long vr41xx_vtclock;
43static unsigned long vr41xx_tclock;
44
45unsigned long vr41xx_get_vtclock_frequency(void)
46{
47 return vr41xx_vtclock;
48}
49
50EXPORT_SYMBOL_GPL(vr41xx_get_vtclock_frequency);
51
52unsigned long vr41xx_get_tclock_frequency(void)
53{
54 return vr41xx_tclock;
55}
56
57EXPORT_SYMBOL_GPL(vr41xx_get_tclock_frequency);
58
59static 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
75static 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
125static 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
166static 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
198void 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
210EXPORT_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
57static void __iomem *cmu_base;
58static uint16_t cmuclkmsk, cmuclkmsk2;
59static 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
64void 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
125EXPORT_SYMBOL_GPL(vr41xx_supply_clock);
126
127void 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
200EXPORT_SYMBOL_GPL(vr41xx_mask_clock);
201
202static 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
244core_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
17static 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
35static 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
48static 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
61static 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
105err_free_device:
106 platform_device_put(pdev);
107
108 return retval;
109}
110device_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
31static void __iomem *icu1_base;
32static void __iomem *icu2_base;
33
34static unsigned char sysint1_assign[16] = {
35 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
36static 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
98static 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
109static 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
120static 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
131static 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
142void 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
155EXPORT_SYMBOL(vr41xx_enable_piuint);
156
157void 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
170EXPORT_SYMBOL(vr41xx_disable_piuint);
171
172void 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
185EXPORT_SYMBOL(vr41xx_enable_aiuint);
186
187void 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
200EXPORT_SYMBOL(vr41xx_disable_aiuint);
201
202void 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
215EXPORT_SYMBOL(vr41xx_enable_kiuint);
216
217void 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
230EXPORT_SYMBOL(vr41xx_disable_kiuint);
231
232void 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
242EXPORT_SYMBOL(vr41xx_enable_macint);
243
244void 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
254EXPORT_SYMBOL(vr41xx_disable_macint);
255
256void 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
266EXPORT_SYMBOL(vr41xx_enable_dsiuint);
267
268void 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
278EXPORT_SYMBOL(vr41xx_disable_dsiuint);
279
280void 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
290EXPORT_SYMBOL(vr41xx_enable_firint);
291
292void 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
302EXPORT_SYMBOL(vr41xx_disable_firint);
303
304void 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
318EXPORT_SYMBOL(vr41xx_enable_pciint);
319
320void 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
334EXPORT_SYMBOL(vr41xx_disable_pciint);
335
336void 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
350EXPORT_SYMBOL(vr41xx_enable_scuint);
351
352void 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
366EXPORT_SYMBOL(vr41xx_disable_scuint);
367
368void 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
382EXPORT_SYMBOL(vr41xx_enable_csiint);
383
384void 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
398EXPORT_SYMBOL(vr41xx_disable_csiint);
399
400void 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
414EXPORT_SYMBOL(vr41xx_enable_bcuint);
415
416void 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
430EXPORT_SYMBOL(vr41xx_disable_bcuint);
431
432static void disable_sysint1_irq(struct irq_data *d)
433{
434 icu1_clear(MSYSINT1REG, 1 << SYSINT1_IRQ_TO_PIN(d->irq));
435}
436
437static void enable_sysint1_irq(struct irq_data *d)
438{
439 icu1_set(MSYSINT1REG, 1 << SYSINT1_IRQ_TO_PIN(d->irq));
440}
441
442static struct irq_chip sysint1_irq_type = {
443 .name = "SYSINT1",
444 .irq_mask = disable_sysint1_irq,
445 .irq_unmask = enable_sysint1_irq,
446};
447
448static void disable_sysint2_irq(struct irq_data *d)
449{
450 icu2_clear(MSYSINT2REG, 1 << SYSINT2_IRQ_TO_PIN(d->irq));
451}
452
453static void enable_sysint2_irq(struct irq_data *d)
454{
455 icu2_set(MSYSINT2REG, 1 << SYSINT2_IRQ_TO_PIN(d->irq));
456}
457
458static struct irq_chip sysint2_irq_type = {
459 .name = "SYSINT2",
460 .irq_mask = disable_sysint2_irq,
461 .irq_unmask = enable_sysint2_irq,
462};
463
464static 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
524static 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
592int 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
610EXPORT_SYMBOL(vr41xx_set_intassign);
611
612static 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
646static 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
714core_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
20static 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
26void __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
40void __init plat_mem_setup(void)
41{
42 iomem_resource_init();
43
44 vr41xx_siu_setup();
45}
46
47void __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
62void __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
14typedef struct irq_cascade {
15 int (*get_irq)(unsigned int);
16} irq_cascade_t;
17
18static irq_cascade_t irq_cascade[NR_IRQS] __cacheline_aligned;
19
20int 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
42EXPORT_SYMBOL_GPL(cascade_irq);
43
44static 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
78asmlinkage 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
103void __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
32static 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
37static 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
49static 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
71static void vr41xx_restart(char *command)
72{
73 local_irq_disable();
74 software_reset();
75 while (1) ;
76}
77
78static 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
85static 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
123core_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
16static 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
39static 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
62static 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
100err_free_device:
101 platform_device_put(pdev);
102
103 return retval;
104}
105device_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
17static unsigned int siu_type1_ports[SIU_PORTS_MAX] __initdata = {
18 PORT_VR41XX_SIU,
19 PORT_UNKNOWN,
20};
21
22static 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
35static unsigned int siu_type2_ports[SIU_PORTS_MAX] __initdata = {
36 PORT_VR41XX_SIU,
37 PORT_VR41XX_DSIU,
38};
39
40static 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
63static 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
103err_free_device:
104 platform_device_put(pdev);
105
106 return retval;
107}
108device_initcall(vr41xx_siu_add);
109
110void __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
8const 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
6obj-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
18static 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
27arch_initcall(ibm_workpad_setup);