aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/sni
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/sni
downloadohosKernel-a07bb8fd1299070229f0e8f3dcb57ffd5ef9870a.tar.gz
ohosKernel-a07bb8fd1299070229f0e8f3dcb57ffd5ef9870a.zip
Initial commit: OpenHarmony-v4.0-ReleaseOpenHarmony-v4.0-Release
Diffstat (limited to 'arch/mips/sni')
-rw-r--r--arch/mips/sni/Makefile7
-rw-r--r--arch/mips/sni/Platform10
-rw-r--r--arch/mips/sni/a20r.c256
-rw-r--r--arch/mips/sni/eisa.c49
-rw-r--r--arch/mips/sni/irq.c76
-rw-r--r--arch/mips/sni/pcimt.c332
-rw-r--r--arch/mips/sni/pcit.c295
-rw-r--r--arch/mips/sni/reset.c48
-rw-r--r--arch/mips/sni/rm200.c485
-rw-r--r--arch/mips/sni/setup.c263
-rw-r--r--arch/mips/sni/time.c167
11 files changed, 1988 insertions, 0 deletions
diff --git a/arch/mips/sni/Makefile b/arch/mips/sni/Makefile
new file mode 100644
index 000000000..6d97c3e96
--- /dev/null
+++ b/arch/mips/sni/Makefile
@@ -0,0 +1,7 @@
1# SPDX-License-Identifier: GPL-2.0-only
2#
3# Makefile for the SNI specific part of the kernel
4#
5
6obj-y += irq.o reset.o setup.o a20r.o rm200.o pcimt.o pcit.o time.o
7obj-$(CONFIG_EISA) += eisa.o
diff --git a/arch/mips/sni/Platform b/arch/mips/sni/Platform
new file mode 100644
index 000000000..b0b3dde0b
--- /dev/null
+++ b/arch/mips/sni/Platform
@@ -0,0 +1,10 @@
1#
2# SNI RM
3#
4cflags-$(CONFIG_SNI_RM) += -I$(srctree)/arch/mips/include/asm/mach-rm
5ifdef CONFIG_CPU_LITTLE_ENDIAN
6load-$(CONFIG_SNI_RM) += 0xffffffff80600000
7else
8load-$(CONFIG_SNI_RM) += 0xffffffff80030000
9endif
10all-$(CONFIG_SNI_RM) := $(COMPRESSION_FNAME).ecoff
diff --git a/arch/mips/sni/a20r.c b/arch/mips/sni/a20r.c
new file mode 100644
index 000000000..eeeec18c4
--- /dev/null
+++ b/arch/mips/sni/a20r.c
@@ -0,0 +1,256 @@
1/*
2 * A20R specific code
3 *
4 * This file is subject to the terms and conditions of the GNU General Public
5 * License. See the file "COPYING" in the main directory of this archive
6 * for more details.
7 *
8 * Copyright (C) 2006 Thomas Bogendoerfer (tsbogend@alpha.franken.de)
9 */
10
11#include <linux/init.h>
12#include <linux/interrupt.h>
13#include <linux/irq.h>
14#include <linux/platform_device.h>
15#include <linux/serial_8250.h>
16
17#include <asm/sni.h>
18#include <asm/time.h>
19
20#define PORT(_base,_irq) \
21 { \
22 .iobase = _base, \
23 .irq = _irq, \
24 .uartclk = 1843200, \
25 .iotype = UPIO_PORT, \
26 .flags = UPF_BOOT_AUTOCONF, \
27 }
28
29static struct plat_serial8250_port a20r_data[] = {
30 PORT(0x3f8, 4),
31 PORT(0x2f8, 3),
32 { },
33};
34
35static struct platform_device a20r_serial8250_device = {
36 .name = "serial8250",
37 .id = PLAT8250_DEV_PLATFORM,
38 .dev = {
39 .platform_data = a20r_data,
40 },
41};
42
43static struct resource a20r_ds1216_rsrc[] = {
44 {
45 .start = 0x1c081ffc,
46 .end = 0x1c081fff,
47 .flags = IORESOURCE_MEM
48 }
49};
50
51static struct platform_device a20r_ds1216_device = {
52 .name = "rtc-ds1216",
53 .num_resources = ARRAY_SIZE(a20r_ds1216_rsrc),
54 .resource = a20r_ds1216_rsrc
55};
56
57static struct resource snirm_82596_rsrc[] = {
58 {
59 .start = 0x18000000,
60 .end = 0x18000004,
61 .flags = IORESOURCE_MEM
62 },
63 {
64 .start = 0x18010000,
65 .end = 0x18010004,
66 .flags = IORESOURCE_MEM
67 },
68 {
69 .start = 0x1ff00000,
70 .end = 0x1ff00020,
71 .flags = IORESOURCE_MEM
72 },
73 {
74 .start = 22,
75 .end = 22,
76 .flags = IORESOURCE_IRQ
77 },
78 {
79 .flags = 0x01 /* 16bit mpu port access */
80 }
81};
82
83static struct platform_device snirm_82596_pdev = {
84 .name = "snirm_82596",
85 .num_resources = ARRAY_SIZE(snirm_82596_rsrc),
86 .resource = snirm_82596_rsrc
87};
88
89static struct resource snirm_53c710_rsrc[] = {
90 {
91 .start = 0x19000000,
92 .end = 0x190fffff,
93 .flags = IORESOURCE_MEM
94 },
95 {
96 .start = 19,
97 .end = 19,
98 .flags = IORESOURCE_IRQ
99 }
100};
101
102static struct platform_device snirm_53c710_pdev = {
103 .name = "snirm_53c710",
104 .num_resources = ARRAY_SIZE(snirm_53c710_rsrc),
105 .resource = snirm_53c710_rsrc
106};
107
108static struct resource sc26xx_rsrc[] = {
109 {
110 .start = 0x1c070000,
111 .end = 0x1c0700ff,
112 .flags = IORESOURCE_MEM
113 },
114 {
115 .start = 20,
116 .end = 20,
117 .flags = IORESOURCE_IRQ
118 }
119};
120
121#include <linux/platform_data/serial-sccnxp.h>
122
123static struct sccnxp_pdata sccnxp_data = {
124 .reg_shift = 2,
125 .mctrl_cfg[0] = MCTRL_SIG(DTR_OP, LINE_OP7) |
126 MCTRL_SIG(RTS_OP, LINE_OP3) |
127 MCTRL_SIG(DSR_IP, LINE_IP5) |
128 MCTRL_SIG(DCD_IP, LINE_IP6),
129 .mctrl_cfg[1] = MCTRL_SIG(DTR_OP, LINE_OP2) |
130 MCTRL_SIG(RTS_OP, LINE_OP1) |
131 MCTRL_SIG(DSR_IP, LINE_IP0) |
132 MCTRL_SIG(CTS_IP, LINE_IP1) |
133 MCTRL_SIG(DCD_IP, LINE_IP2) |
134 MCTRL_SIG(RNG_IP, LINE_IP3),
135};
136
137static struct platform_device sc26xx_pdev = {
138 .name = "sc2681",
139 .resource = sc26xx_rsrc,
140 .num_resources = ARRAY_SIZE(sc26xx_rsrc),
141 .dev = {
142 .platform_data = &sccnxp_data,
143 },
144};
145
146/*
147 * Trigger chipset to update CPU's CAUSE IP field
148 */
149static u32 a20r_update_cause_ip(void)
150{
151 u32 status = read_c0_status();
152
153 write_c0_status(status | 0x00010000);
154 asm volatile(
155 " .set push \n"
156 " .set noat \n"
157 " .set noreorder \n"
158 " lw $1, 0(%0) \n"
159 " sb $0, 0(%1) \n"
160 " sync \n"
161 " lb %1, 0(%1) \n"
162 " b 1f \n"
163 " ori %1, $1, 2 \n"
164 " .align 8 \n"
165 "1: \n"
166 " nop \n"
167 " sw %1, 0(%0) \n"
168 " sync \n"
169 " li %1, 0x20 \n"
170 "2: \n"
171 " nop \n"
172 " bnez %1,2b \n"
173 " addiu %1, -1 \n"
174 " sw $1, 0(%0) \n"
175 " sync \n"
176 ".set pop \n"
177 :
178 : "Jr" (PCIMT_UCONF), "Jr" (0xbc000000));
179 write_c0_status(status);
180
181 return status;
182}
183
184static inline void unmask_a20r_irq(struct irq_data *d)
185{
186 set_c0_status(0x100 << (d->irq - SNI_A20R_IRQ_BASE));
187 irq_enable_hazard();
188}
189
190static inline void mask_a20r_irq(struct irq_data *d)
191{
192 clear_c0_status(0x100 << (d->irq - SNI_A20R_IRQ_BASE));
193 irq_disable_hazard();
194}
195
196static struct irq_chip a20r_irq_type = {
197 .name = "A20R",
198 .irq_mask = mask_a20r_irq,
199 .irq_unmask = unmask_a20r_irq,
200};
201
202/*
203 * hwint 0 receive all interrupts
204 */
205static void a20r_hwint(void)
206{
207 u32 cause, status;
208 int irq;
209
210 clear_c0_status(IE_IRQ0);
211 status = a20r_update_cause_ip();
212 cause = read_c0_cause();
213
214 irq = ffs(((cause & status) >> 8) & 0xf8);
215 if (likely(irq > 0))
216 do_IRQ(SNI_A20R_IRQ_BASE + irq - 1);
217
218 a20r_update_cause_ip();
219 set_c0_status(IE_IRQ0);
220}
221
222void __init sni_a20r_irq_init(void)
223{
224 int i;
225
226 for (i = SNI_A20R_IRQ_BASE + 2 ; i < SNI_A20R_IRQ_BASE + 8; i++)
227 irq_set_chip_and_handler(i, &a20r_irq_type, handle_level_irq);
228 sni_hwint = a20r_hwint;
229 change_c0_status(ST0_IM, IE_IRQ0);
230 if (request_irq(SNI_A20R_IRQ_BASE + 3, sni_isa_irq_handler,
231 IRQF_SHARED, "ISA", sni_isa_irq_handler))
232 pr_err("Failed to register ISA interrupt\n");
233}
234
235void sni_a20r_init(void)
236{
237 /* FIXME, remove if not needed */
238}
239
240static int __init snirm_a20r_setup_devinit(void)
241{
242 switch (sni_brd_type) {
243 case SNI_BRD_TOWER_OASIC:
244 case SNI_BRD_MINITOWER:
245 platform_device_register(&snirm_82596_pdev);
246 platform_device_register(&snirm_53c710_pdev);
247 platform_device_register(&sc26xx_pdev);
248 platform_device_register(&a20r_serial8250_device);
249 platform_device_register(&a20r_ds1216_device);
250 sni_eisa_root_init();
251 break;
252 }
253 return 0;
254}
255
256device_initcall(snirm_a20r_setup_devinit);
diff --git a/arch/mips/sni/eisa.c b/arch/mips/sni/eisa.c
new file mode 100644
index 000000000..483a43d07
--- /dev/null
+++ b/arch/mips/sni/eisa.c
@@ -0,0 +1,49 @@
1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * Virtual EISA root driver.
4 * Acts as a placeholder if we don't have a proper EISA bridge.
5 *
6 * (C) 2003 Marc Zyngier <maz@wild-wind.fr.eu.org>
7 * modified for SNI usage by Thomas Bogendoerfer
8 */
9
10#include <linux/kernel.h>
11#include <linux/platform_device.h>
12#include <linux/eisa.h>
13#include <linux/init.h>
14
15/* The default EISA device parent (virtual root device).
16 * Now use a platform device, since that's the obvious choice. */
17
18static struct platform_device eisa_root_dev = {
19 .name = "eisa",
20 .id = 0,
21};
22
23static struct eisa_root_device eisa_bus_root = {
24 .dev = &eisa_root_dev.dev,
25 .bus_base_addr = 0,
26 .res = &ioport_resource,
27 .slots = EISA_MAX_SLOTS,
28 .dma_mask = 0xffffffff,
29 .force_probe = 1,
30};
31
32int __init sni_eisa_root_init(void)
33{
34 int r;
35
36 r = platform_device_register(&eisa_root_dev);
37 if (!r)
38 return r;
39
40 dev_set_drvdata(&eisa_root_dev.dev, &eisa_bus_root);
41
42 if (eisa_root_register(&eisa_bus_root)) {
43 /* A real bridge may have been registered before
44 * us. So quietly unregister. */
45 platform_device_unregister(&eisa_root_dev);
46 return -1;
47 }
48 return 0;
49}
diff --git a/arch/mips/sni/irq.c b/arch/mips/sni/irq.c
new file mode 100644
index 000000000..dec89afc9
--- /dev/null
+++ b/arch/mips/sni/irq.c
@@ -0,0 +1,76 @@
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Copyright (C) 1992 Linus Torvalds
7 * Copyright (C) 1994 - 2000 Ralf Baechle
8 * Copyright (C) 2006 Thomas Bogendoerfer
9 */
10#include <linux/delay.h>
11#include <linux/init.h>
12#include <linux/interrupt.h>
13#include <linux/irq.h>
14#include <linux/kernel.h>
15
16#include <asm/i8259.h>
17#include <asm/io.h>
18#include <asm/sni.h>
19#include <asm/irq.h>
20#include <asm/irq_cpu.h>
21
22void (*sni_hwint)(void);
23
24asmlinkage void plat_irq_dispatch(void)
25{
26 sni_hwint();
27}
28
29/* ISA irq handler */
30irqreturn_t sni_isa_irq_handler(int dummy, void *p)
31{
32 int irq;
33
34 irq = i8259_irq();
35 if (unlikely(irq < 0))
36 return IRQ_NONE;
37
38 generic_handle_irq(irq);
39 return IRQ_HANDLED;
40}
41
42/*
43 * On systems with i8259-style interrupt controllers we assume for
44 * driver compatibility reasons interrupts 0 - 15 to be the i8295
45 * interrupts even if the hardware uses a different interrupt numbering.
46 */
47void __init arch_init_irq(void)
48{
49 init_i8259_irqs(); /* Integrated i8259 */
50 switch (sni_brd_type) {
51 case SNI_BRD_10:
52 case SNI_BRD_10NEW:
53 case SNI_BRD_TOWER_OASIC:
54 case SNI_BRD_MINITOWER:
55 sni_a20r_irq_init();
56 break;
57
58 case SNI_BRD_PCI_TOWER:
59 sni_pcit_irq_init();
60 break;
61
62 case SNI_BRD_PCI_TOWER_CPLUS:
63 sni_pcit_cplus_irq_init();
64 break;
65
66 case SNI_BRD_RM200:
67 sni_rm200_irq_init();
68 break;
69
70 case SNI_BRD_PCI_MTOWER:
71 case SNI_BRD_PCI_DESKTOP:
72 case SNI_BRD_PCI_MTOWER_CPLUS:
73 sni_pcimt_irq_init();
74 break;
75 }
76}
diff --git a/arch/mips/sni/pcimt.c b/arch/mips/sni/pcimt.c
new file mode 100644
index 000000000..12336c2a6
--- /dev/null
+++ b/arch/mips/sni/pcimt.c
@@ -0,0 +1,332 @@
1/*
2 * PCIMT specific code
3 *
4 * This file is subject to the terms and conditions of the GNU General Public
5 * License. See the file "COPYING" in the main directory of this archive
6 * for more details.
7 *
8 * Copyright (C) 1996, 97, 98, 2000, 03, 04, 06 Ralf Baechle (ralf@linux-mips.org)
9 * Copyright (C) 2006,2007 Thomas Bogendoerfer (tsbogend@alpha.franken.de)
10 */
11
12#include <linux/init.h>
13#include <linux/interrupt.h>
14#include <linux/irq.h>
15#include <linux/pci.h>
16#include <linux/serial_8250.h>
17
18#include <asm/sni.h>
19#include <asm/time.h>
20#include <asm/i8259.h>
21#include <asm/irq_cpu.h>
22
23#define cacheconf (*(volatile unsigned int *)PCIMT_CACHECONF)
24#define invspace (*(volatile unsigned int *)PCIMT_INVSPACE)
25
26static void __init sni_pcimt_sc_init(void)
27{
28 unsigned int scsiz, sc_size;
29
30 scsiz = cacheconf & 7;
31 if (scsiz == 0) {
32 printk("Second level cache is deactivated.\n");
33 return;
34 }
35 if (scsiz >= 6) {
36 printk("Invalid second level cache size configured, "
37 "deactivating second level cache.\n");
38 cacheconf = 0;
39 return;
40 }
41
42 sc_size = 128 << scsiz;
43 printk("%dkb second level cache detected, deactivating.\n", sc_size);
44 cacheconf = 0;
45}
46
47
48/*
49 * A bit more gossip about the iron we're running on ...
50 */
51static inline void sni_pcimt_detect(void)
52{
53 char boardtype[80];
54 unsigned char csmsr;
55 char *p = boardtype;
56 unsigned int asic;
57
58 csmsr = *(volatile unsigned char *)PCIMT_CSMSR;
59
60 p += sprintf(p, "%s PCI", (csmsr & 0x80) ? "RM200" : "RM300");
61 if ((csmsr & 0x80) == 0)
62 p += sprintf(p, ", board revision %s",
63 (csmsr & 0x20) ? "D" : "C");
64 asic = csmsr & 0x80;
65 asic = (csmsr & 0x08) ? asic : !asic;
66 p += sprintf(p, ", ASIC PCI Rev %s", asic ? "1.0" : "1.1");
67 printk("%s.\n", boardtype);
68}
69
70#define PORT(_base,_irq) \
71 { \
72 .iobase = _base, \
73 .irq = _irq, \
74 .uartclk = 1843200, \
75 .iotype = UPIO_PORT, \
76 .flags = UPF_BOOT_AUTOCONF, \
77 }
78
79static struct plat_serial8250_port pcimt_data[] = {
80 PORT(0x3f8, 4),
81 PORT(0x2f8, 3),
82 { },
83};
84
85static struct platform_device pcimt_serial8250_device = {
86 .name = "serial8250",
87 .id = PLAT8250_DEV_PLATFORM,
88 .dev = {
89 .platform_data = pcimt_data,
90 },
91};
92
93static struct resource pcimt_cmos_rsrc[] = {
94 {
95 .start = 0x70,
96 .end = 0x71,
97 .flags = IORESOURCE_IO
98 },
99 {
100 .start = 8,
101 .end = 8,
102 .flags = IORESOURCE_IRQ
103 }
104};
105
106static struct platform_device pcimt_cmos_device = {
107 .name = "rtc_cmos",
108 .num_resources = ARRAY_SIZE(pcimt_cmos_rsrc),
109 .resource = pcimt_cmos_rsrc
110};
111
112
113static struct resource sni_io_resource = {
114 .start = 0x00000000UL,
115 .end = 0x03bfffffUL,
116 .name = "PCIMT IO MEM",
117 .flags = IORESOURCE_IO,
118};
119
120static struct resource pcimt_io_resources[] = {
121 {
122 .start = 0x00,
123 .end = 0x1f,
124 .name = "dma1",
125 .flags = IORESOURCE_BUSY
126 }, {
127 .start = 0x40,
128 .end = 0x5f,
129 .name = "timer",
130 .flags = IORESOURCE_BUSY
131 }, {
132 .start = 0x60,
133 .end = 0x6f,
134 .name = "keyboard",
135 .flags = IORESOURCE_BUSY
136 }, {
137 .start = 0x80,
138 .end = 0x8f,
139 .name = "dma page reg",
140 .flags = IORESOURCE_BUSY
141 }, {
142 .start = 0xc0,
143 .end = 0xdf,
144 .name = "dma2",
145 .flags = IORESOURCE_BUSY
146 }, {
147 .start = 0xcfc,
148 .end = 0xcff,
149 .name = "PCI config data",
150 .flags = IORESOURCE_BUSY
151 }
152};
153
154static struct resource pcimt_mem_resources[] = {
155 {
156 /*
157 * this region should only be 4 bytes long,
158 * but it's 16MB on all RM300C I've checked
159 */
160 .start = 0x1a000000,
161 .end = 0x1affffff,
162 .name = "PCI INT ACK",
163 .flags = IORESOURCE_BUSY
164 }
165};
166
167static struct resource sni_mem_resource = {
168 .start = 0x18000000UL,
169 .end = 0x1fbfffffUL,
170 .name = "PCIMT PCI MEM",
171 .flags = IORESOURCE_MEM
172};
173
174static void __init sni_pcimt_resource_init(void)
175{
176 int i;
177
178 /* request I/O space for devices used on all i[345]86 PCs */
179 for (i = 0; i < ARRAY_SIZE(pcimt_io_resources); i++)
180 request_resource(&sni_io_resource, pcimt_io_resources + i);
181 /* request MEM space for devices used on all i[345]86 PCs */
182 for (i = 0; i < ARRAY_SIZE(pcimt_mem_resources); i++)
183 request_resource(&sni_mem_resource, pcimt_mem_resources + i);
184}
185
186extern struct pci_ops sni_pcimt_ops;
187
188#ifdef CONFIG_PCI
189static struct pci_controller sni_controller = {
190 .pci_ops = &sni_pcimt_ops,
191 .mem_resource = &sni_mem_resource,
192 .mem_offset = 0x00000000UL,
193 .io_resource = &sni_io_resource,
194 .io_offset = 0x00000000UL,
195 .io_map_base = SNI_PORT_BASE
196};
197#endif
198
199static void enable_pcimt_irq(struct irq_data *d)
200{
201 unsigned int mask = 1 << (d->irq - PCIMT_IRQ_INT2);
202
203 *(volatile u8 *) PCIMT_IRQSEL |= mask;
204}
205
206void disable_pcimt_irq(struct irq_data *d)
207{
208 unsigned int mask = ~(1 << (d->irq - PCIMT_IRQ_INT2));
209
210 *(volatile u8 *) PCIMT_IRQSEL &= mask;
211}
212
213static struct irq_chip pcimt_irq_type = {
214 .name = "PCIMT",
215 .irq_mask = disable_pcimt_irq,
216 .irq_unmask = enable_pcimt_irq,
217};
218
219/*
220 * hwint0 should deal with MP agent, ASIC PCI, EISA NMI and debug
221 * button interrupts. Later ...
222 */
223static void pcimt_hwint0(void)
224{
225 panic("Received int0 but no handler yet ...");
226}
227
228/*
229 * hwint 1 deals with EISA and SCSI interrupts,
230 *
231 * The EISA_INT bit in CSITPEND is high active, all others are low active.
232 */
233static void pcimt_hwint1(void)
234{
235 u8 pend = *(volatile char *)PCIMT_CSITPEND;
236 unsigned long flags;
237
238 if (pend & IT_EISA) {
239 int irq;
240 /*
241 * Note: ASIC PCI's builtin interrupt acknowledge feature is
242 * broken. Using it may result in loss of some or all i8259
243 * interrupts, so don't use PCIMT_INT_ACKNOWLEDGE ...
244 */
245 irq = i8259_irq();
246 if (unlikely(irq < 0))
247 return;
248
249 do_IRQ(irq);
250 }
251
252 if (!(pend & IT_SCSI)) {
253 flags = read_c0_status();
254 clear_c0_status(ST0_IM);
255 do_IRQ(PCIMT_IRQ_SCSI);
256 write_c0_status(flags);
257 }
258}
259
260/*
261 * hwint 3 should deal with the PCI A - D interrupts,
262 */
263static void pcimt_hwint3(void)
264{
265 u8 pend = *(volatile char *)PCIMT_CSITPEND;
266 int irq;
267
268 pend &= (IT_INTA | IT_INTB | IT_INTC | IT_INTD);
269 pend ^= (IT_INTA | IT_INTB | IT_INTC | IT_INTD);
270 clear_c0_status(IE_IRQ3);
271 irq = PCIMT_IRQ_INT2 + ffs(pend) - 1;
272 do_IRQ(irq);
273 set_c0_status(IE_IRQ3);
274}
275
276static void sni_pcimt_hwint(void)
277{
278 u32 pending = read_c0_cause() & read_c0_status();
279
280 if (pending & C_IRQ5)
281 do_IRQ(MIPS_CPU_IRQ_BASE + 7);
282 else if (pending & C_IRQ4)
283 do_IRQ(MIPS_CPU_IRQ_BASE + 6);
284 else if (pending & C_IRQ3)
285 pcimt_hwint3();
286 else if (pending & C_IRQ1)
287 pcimt_hwint1();
288 else if (pending & C_IRQ0) {
289 pcimt_hwint0();
290 }
291}
292
293void __init sni_pcimt_irq_init(void)
294{
295 int i;
296
297 *(volatile u8 *) PCIMT_IRQSEL = IT_ETH | IT_EISA;
298 mips_cpu_irq_init();
299 /* Actually we've got more interrupts to handle ... */
300 for (i = PCIMT_IRQ_INT2; i <= PCIMT_IRQ_SCSI; i++)
301 irq_set_chip_and_handler(i, &pcimt_irq_type, handle_level_irq);
302 sni_hwint = sni_pcimt_hwint;
303 change_c0_status(ST0_IM, IE_IRQ1|IE_IRQ3);
304}
305
306void __init sni_pcimt_init(void)
307{
308 sni_pcimt_detect();
309 sni_pcimt_sc_init();
310 ioport_resource.end = sni_io_resource.end;
311#ifdef CONFIG_PCI
312 PCIBIOS_MIN_IO = 0x9000;
313 register_pci_controller(&sni_controller);
314#endif
315 sni_pcimt_resource_init();
316}
317
318static int __init snirm_pcimt_setup_devinit(void)
319{
320 switch (sni_brd_type) {
321 case SNI_BRD_PCI_MTOWER:
322 case SNI_BRD_PCI_DESKTOP:
323 case SNI_BRD_PCI_MTOWER_CPLUS:
324 platform_device_register(&pcimt_serial8250_device);
325 platform_device_register(&pcimt_cmos_device);
326 break;
327 }
328
329 return 0;
330}
331
332device_initcall(snirm_pcimt_setup_devinit);
diff --git a/arch/mips/sni/pcit.c b/arch/mips/sni/pcit.c
new file mode 100644
index 000000000..b331fe22c
--- /dev/null
+++ b/arch/mips/sni/pcit.c
@@ -0,0 +1,295 @@
1/*
2 * PCI Tower specific code
3 *
4 * This file is subject to the terms and conditions of the GNU General Public
5 * License. See the file "COPYING" in the main directory of this archive
6 * for more details.
7 *
8 * Copyright (C) 2006 Thomas Bogendoerfer (tsbogend@alpha.franken.de)
9 */
10
11#include <linux/init.h>
12#include <linux/interrupt.h>
13#include <linux/irq.h>
14#include <linux/pci.h>
15#include <linux/serial_8250.h>
16
17#include <asm/sni.h>
18#include <asm/time.h>
19#include <asm/irq_cpu.h>
20
21
22#define PORT(_base,_irq) \
23 { \
24 .iobase = _base, \
25 .irq = _irq, \
26 .uartclk = 1843200, \
27 .iotype = UPIO_PORT, \
28 .flags = UPF_BOOT_AUTOCONF, \
29 }
30
31static struct plat_serial8250_port pcit_data[] = {
32 PORT(0x3f8, 0),
33 PORT(0x2f8, 3),
34 { },
35};
36
37static struct platform_device pcit_serial8250_device = {
38 .name = "serial8250",
39 .id = PLAT8250_DEV_PLATFORM,
40 .dev = {
41 .platform_data = pcit_data,
42 },
43};
44
45static struct plat_serial8250_port pcit_cplus_data[] = {
46 PORT(0x3f8, 0),
47 PORT(0x2f8, 3),
48 PORT(0x3e8, 4),
49 PORT(0x2e8, 3),
50 { },
51};
52
53static struct platform_device pcit_cplus_serial8250_device = {
54 .name = "serial8250",
55 .id = PLAT8250_DEV_PLATFORM,
56 .dev = {
57 .platform_data = pcit_cplus_data,
58 },
59};
60
61static struct resource pcit_cmos_rsrc[] = {
62 {
63 .start = 0x70,
64 .end = 0x71,
65 .flags = IORESOURCE_IO
66 },
67 {
68 .start = 8,
69 .end = 8,
70 .flags = IORESOURCE_IRQ
71 }
72};
73
74static struct platform_device pcit_cmos_device = {
75 .name = "rtc_cmos",
76 .num_resources = ARRAY_SIZE(pcit_cmos_rsrc),
77 .resource = pcit_cmos_rsrc
78};
79
80static struct platform_device pcit_pcspeaker_pdev = {
81 .name = "pcspkr",
82 .id = -1,
83};
84
85static struct resource sni_io_resource = {
86 .start = 0x00000000UL,
87 .end = 0x03bfffffUL,
88 .name = "PCIT IO",
89 .flags = IORESOURCE_IO,
90};
91
92static struct resource pcit_io_resources[] = {
93 {
94 .start = 0x00,
95 .end = 0x1f,
96 .name = "dma1",
97 .flags = IORESOURCE_BUSY
98 }, {
99 .start = 0x40,
100 .end = 0x5f,
101 .name = "timer",
102 .flags = IORESOURCE_BUSY
103 }, {
104 .start = 0x60,
105 .end = 0x6f,
106 .name = "keyboard",
107 .flags = IORESOURCE_BUSY
108 }, {
109 .start = 0x80,
110 .end = 0x8f,
111 .name = "dma page reg",
112 .flags = IORESOURCE_BUSY
113 }, {
114 .start = 0xc0,
115 .end = 0xdf,
116 .name = "dma2",
117 .flags = IORESOURCE_BUSY
118 }, {
119 .start = 0xcf8,
120 .end = 0xcfb,
121 .name = "PCI config addr",
122 .flags = IORESOURCE_BUSY
123 }, {
124 .start = 0xcfc,
125 .end = 0xcff,
126 .name = "PCI config data",
127 .flags = IORESOURCE_BUSY
128 }
129};
130
131static void __init sni_pcit_resource_init(void)
132{
133 int i;
134
135 /* request I/O space for devices used on all i[345]86 PCs */
136 for (i = 0; i < ARRAY_SIZE(pcit_io_resources); i++)
137 request_resource(&sni_io_resource, pcit_io_resources + i);
138}
139
140
141extern struct pci_ops sni_pcit_ops;
142
143#ifdef CONFIG_PCI
144static struct resource sni_mem_resource = {
145 .start = 0x18000000UL,
146 .end = 0x1fbfffffUL,
147 .name = "PCIT PCI MEM",
148 .flags = IORESOURCE_MEM
149};
150
151static struct pci_controller sni_pcit_controller = {
152 .pci_ops = &sni_pcit_ops,
153 .mem_resource = &sni_mem_resource,
154 .mem_offset = 0x00000000UL,
155 .io_resource = &sni_io_resource,
156 .io_offset = 0x00000000UL,
157 .io_map_base = SNI_PORT_BASE
158};
159#endif /* CONFIG_PCI */
160
161static void enable_pcit_irq(struct irq_data *d)
162{
163 u32 mask = 1 << (d->irq - SNI_PCIT_INT_START + 24);
164
165 *(volatile u32 *)SNI_PCIT_INT_REG |= mask;
166}
167
168void disable_pcit_irq(struct irq_data *d)
169{
170 u32 mask = 1 << (d->irq - SNI_PCIT_INT_START + 24);
171
172 *(volatile u32 *)SNI_PCIT_INT_REG &= ~mask;
173}
174
175static struct irq_chip pcit_irq_type = {
176 .name = "PCIT",
177 .irq_mask = disable_pcit_irq,
178 .irq_unmask = enable_pcit_irq,
179};
180
181static void pcit_hwint1(void)
182{
183 u32 pending = *(volatile u32 *)SNI_PCIT_INT_REG;
184 int irq;
185
186 clear_c0_status(IE_IRQ1);
187 irq = ffs((pending >> 16) & 0x7f);
188
189 if (likely(irq > 0))
190 do_IRQ(irq + SNI_PCIT_INT_START - 1);
191 set_c0_status(IE_IRQ1);
192}
193
194static void pcit_hwint0(void)
195{
196 u32 pending = *(volatile u32 *)SNI_PCIT_INT_REG;
197 int irq;
198
199 clear_c0_status(IE_IRQ0);
200 irq = ffs((pending >> 16) & 0x3f);
201
202 if (likely(irq > 0))
203 do_IRQ(irq + SNI_PCIT_INT_START - 1);
204 set_c0_status(IE_IRQ0);
205}
206
207static void sni_pcit_hwint(void)
208{
209 u32 pending = read_c0_cause() & read_c0_status();
210
211 if (pending & C_IRQ1)
212 pcit_hwint1();
213 else if (pending & C_IRQ2)
214 do_IRQ(MIPS_CPU_IRQ_BASE + 4);
215 else if (pending & C_IRQ3)
216 do_IRQ(MIPS_CPU_IRQ_BASE + 5);
217 else if (pending & C_IRQ5)
218 do_IRQ(MIPS_CPU_IRQ_BASE + 7);
219}
220
221static void sni_pcit_hwint_cplus(void)
222{
223 u32 pending = read_c0_cause() & read_c0_status();
224
225 if (pending & C_IRQ0)
226 pcit_hwint0();
227 else if (pending & C_IRQ1)
228 do_IRQ(MIPS_CPU_IRQ_BASE + 3);
229 else if (pending & C_IRQ2)
230 do_IRQ(MIPS_CPU_IRQ_BASE + 4);
231 else if (pending & C_IRQ3)
232 do_IRQ(MIPS_CPU_IRQ_BASE + 5);
233 else if (pending & C_IRQ5)
234 do_IRQ(MIPS_CPU_IRQ_BASE + 7);
235}
236
237void __init sni_pcit_irq_init(void)
238{
239 int i;
240
241 mips_cpu_irq_init();
242 for (i = SNI_PCIT_INT_START; i <= SNI_PCIT_INT_END; i++)
243 irq_set_chip_and_handler(i, &pcit_irq_type, handle_level_irq);
244 *(volatile u32 *)SNI_PCIT_INT_REG = 0;
245 sni_hwint = sni_pcit_hwint;
246 change_c0_status(ST0_IM, IE_IRQ1);
247 if (request_irq(SNI_PCIT_INT_START + 6, sni_isa_irq_handler, 0, "ISA",
248 NULL))
249 pr_err("Failed to register ISA interrupt\n");
250}
251
252void __init sni_pcit_cplus_irq_init(void)
253{
254 int i;
255
256 mips_cpu_irq_init();
257 for (i = SNI_PCIT_INT_START; i <= SNI_PCIT_INT_END; i++)
258 irq_set_chip_and_handler(i, &pcit_irq_type, handle_level_irq);
259 *(volatile u32 *)SNI_PCIT_INT_REG = 0x40000000;
260 sni_hwint = sni_pcit_hwint_cplus;
261 change_c0_status(ST0_IM, IE_IRQ0);
262 if (request_irq(MIPS_CPU_IRQ_BASE + 3, sni_isa_irq_handler, 0, "ISA",
263 NULL))
264 pr_err("Failed to register ISA interrupt\n");
265}
266
267void __init sni_pcit_init(void)
268{
269 ioport_resource.end = sni_io_resource.end;
270#ifdef CONFIG_PCI
271 PCIBIOS_MIN_IO = 0x9000;
272 register_pci_controller(&sni_pcit_controller);
273#endif
274 sni_pcit_resource_init();
275}
276
277static int __init snirm_pcit_setup_devinit(void)
278{
279 switch (sni_brd_type) {
280 case SNI_BRD_PCI_TOWER:
281 platform_device_register(&pcit_serial8250_device);
282 platform_device_register(&pcit_cmos_device);
283 platform_device_register(&pcit_pcspeaker_pdev);
284 break;
285
286 case SNI_BRD_PCI_TOWER_CPLUS:
287 platform_device_register(&pcit_cplus_serial8250_device);
288 platform_device_register(&pcit_cmos_device);
289 platform_device_register(&pcit_pcspeaker_pdev);
290 break;
291 }
292 return 0;
293}
294
295device_initcall(snirm_pcit_setup_devinit);
diff --git a/arch/mips/sni/reset.c b/arch/mips/sni/reset.c
new file mode 100644
index 000000000..66f963d8d
--- /dev/null
+++ b/arch/mips/sni/reset.c
@@ -0,0 +1,48 @@
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * linux/arch/mips/sni/process.c
4 *
5 * Reset a SNI machine.
6 */
7#include <linux/delay.h>
8
9#include <asm/io.h>
10#include <asm/reboot.h>
11#include <asm/sni.h>
12
13/*
14 * This routine reboots the machine by asking the keyboard
15 * controller to pulse the reset-line low. We try that for a while,
16 * and if it doesn't work, we do some other stupid things.
17 */
18static inline void kb_wait(void)
19{
20 int i;
21
22 for (i = 0; i < 0x10000; i++)
23 if ((inb_p(0x64) & 0x02) == 0)
24 break;
25}
26
27/* XXX This ends up at the ARC firmware prompt ... */
28void sni_machine_restart(char *command)
29{
30 int i;
31
32 /* This does a normal via the keyboard controller like a PC.
33 We can do that easier ... */
34 local_irq_disable();
35 for (;;) {
36 for (i = 0; i < 100; i++) {
37 kb_wait();
38 udelay(50);
39 outb_p(0xfe, 0x64); /* pulse reset low */
40 udelay(50);
41 }
42 }
43}
44
45void sni_machine_power_off(void)
46{
47 *(volatile unsigned char *)PCIMT_CSWCSM = 0xfd;
48}
diff --git a/arch/mips/sni/rm200.c b/arch/mips/sni/rm200.c
new file mode 100644
index 000000000..d84744ca8
--- /dev/null
+++ b/arch/mips/sni/rm200.c
@@ -0,0 +1,485 @@
1/*
2 * RM200 specific code
3 *
4 * This file is subject to the terms and conditions of the GNU General Public
5 * License. See the file "COPYING" in the main directory of this archive
6 * for more details.
7 *
8 * Copyright (C) 2006,2007 Thomas Bogendoerfer (tsbogend@alpha.franken.de)
9 *
10 * i8259 parts ripped out of arch/mips/kernel/i8259.c
11 */
12
13#include <linux/delay.h>
14#include <linux/init.h>
15#include <linux/interrupt.h>
16#include <linux/irq.h>
17#include <linux/platform_device.h>
18#include <linux/serial_8250.h>
19#include <linux/io.h>
20
21#include <asm/sni.h>
22#include <asm/time.h>
23#include <asm/irq_cpu.h>
24
25#define RM200_I8259A_IRQ_BASE 32
26
27#define MEMPORT(_base,_irq) \
28 { \
29 .mapbase = _base, \
30 .irq = _irq, \
31 .uartclk = 1843200, \
32 .iotype = UPIO_MEM, \
33 .flags = UPF_BOOT_AUTOCONF|UPF_IOREMAP, \
34 }
35
36static struct plat_serial8250_port rm200_data[] = {
37 MEMPORT(0x160003f8, RM200_I8259A_IRQ_BASE + 4),
38 MEMPORT(0x160002f8, RM200_I8259A_IRQ_BASE + 3),
39 { },
40};
41
42static struct platform_device rm200_serial8250_device = {
43 .name = "serial8250",
44 .id = PLAT8250_DEV_PLATFORM,
45 .dev = {
46 .platform_data = rm200_data,
47 },
48};
49
50static struct resource rm200_ds1216_rsrc[] = {
51 {
52 .start = 0x1cd41ffc,
53 .end = 0x1cd41fff,
54 .flags = IORESOURCE_MEM
55 }
56};
57
58static struct platform_device rm200_ds1216_device = {
59 .name = "rtc-ds1216",
60 .num_resources = ARRAY_SIZE(rm200_ds1216_rsrc),
61 .resource = rm200_ds1216_rsrc
62};
63
64static struct resource snirm_82596_rm200_rsrc[] = {
65 {
66 .start = 0x18000000,
67 .end = 0x180fffff,
68 .flags = IORESOURCE_MEM
69 },
70 {
71 .start = 0x1b000000,
72 .end = 0x1b000004,
73 .flags = IORESOURCE_MEM
74 },
75 {
76 .start = 0x1ff00000,
77 .end = 0x1ff00020,
78 .flags = IORESOURCE_MEM
79 },
80 {
81 .start = 27,
82 .end = 27,
83 .flags = IORESOURCE_IRQ
84 },
85 {
86 .flags = 0x00
87 }
88};
89
90static struct platform_device snirm_82596_rm200_pdev = {
91 .name = "snirm_82596",
92 .num_resources = ARRAY_SIZE(snirm_82596_rm200_rsrc),
93 .resource = snirm_82596_rm200_rsrc
94};
95
96static struct resource snirm_53c710_rm200_rsrc[] = {
97 {
98 .start = 0x19000000,
99 .end = 0x190fffff,
100 .flags = IORESOURCE_MEM
101 },
102 {
103 .start = 26,
104 .end = 26,
105 .flags = IORESOURCE_IRQ
106 }
107};
108
109static struct platform_device snirm_53c710_rm200_pdev = {
110 .name = "snirm_53c710",
111 .num_resources = ARRAY_SIZE(snirm_53c710_rm200_rsrc),
112 .resource = snirm_53c710_rm200_rsrc
113};
114
115static int __init snirm_setup_devinit(void)
116{
117 if (sni_brd_type == SNI_BRD_RM200) {
118 platform_device_register(&rm200_serial8250_device);
119 platform_device_register(&rm200_ds1216_device);
120 platform_device_register(&snirm_82596_rm200_pdev);
121 platform_device_register(&snirm_53c710_rm200_pdev);
122 sni_eisa_root_init();
123 }
124 return 0;
125}
126
127device_initcall(snirm_setup_devinit);
128
129/*
130 * RM200 has an ISA and an EISA bus. The iSA bus is only used
131 * for onboard devices and also has twi i8259 PICs. Since these
132 * PICs are no accessible via inb/outb the following code uses
133 * readb/writeb to access them
134 */
135
136static DEFINE_RAW_SPINLOCK(sni_rm200_i8259A_lock);
137#define PIC_CMD 0x00
138#define PIC_IMR 0x01
139#define PIC_ISR PIC_CMD
140#define PIC_POLL PIC_ISR
141#define PIC_OCW3 PIC_ISR
142
143/* i8259A PIC related value */
144#define PIC_CASCADE_IR 2
145#define MASTER_ICW4_DEFAULT 0x01
146#define SLAVE_ICW4_DEFAULT 0x01
147
148/*
149 * This contains the irq mask for both 8259A irq controllers,
150 */
151static unsigned int rm200_cached_irq_mask = 0xffff;
152static __iomem u8 *rm200_pic_master;
153static __iomem u8 *rm200_pic_slave;
154
155#define cached_master_mask (rm200_cached_irq_mask)
156#define cached_slave_mask (rm200_cached_irq_mask >> 8)
157
158static void sni_rm200_disable_8259A_irq(struct irq_data *d)
159{
160 unsigned int mask, irq = d->irq - RM200_I8259A_IRQ_BASE;
161 unsigned long flags;
162
163 mask = 1 << irq;
164 raw_spin_lock_irqsave(&sni_rm200_i8259A_lock, flags);
165 rm200_cached_irq_mask |= mask;
166 if (irq & 8)
167 writeb(cached_slave_mask, rm200_pic_slave + PIC_IMR);
168 else
169 writeb(cached_master_mask, rm200_pic_master + PIC_IMR);
170 raw_spin_unlock_irqrestore(&sni_rm200_i8259A_lock, flags);
171}
172
173static void sni_rm200_enable_8259A_irq(struct irq_data *d)
174{
175 unsigned int mask, irq = d->irq - RM200_I8259A_IRQ_BASE;
176 unsigned long flags;
177
178 mask = ~(1 << irq);
179 raw_spin_lock_irqsave(&sni_rm200_i8259A_lock, flags);
180 rm200_cached_irq_mask &= mask;
181 if (irq & 8)
182 writeb(cached_slave_mask, rm200_pic_slave + PIC_IMR);
183 else
184 writeb(cached_master_mask, rm200_pic_master + PIC_IMR);
185 raw_spin_unlock_irqrestore(&sni_rm200_i8259A_lock, flags);
186}
187
188static inline int sni_rm200_i8259A_irq_real(unsigned int irq)
189{
190 int value;
191 int irqmask = 1 << irq;
192
193 if (irq < 8) {
194 writeb(0x0B, rm200_pic_master + PIC_CMD);
195 value = readb(rm200_pic_master + PIC_CMD) & irqmask;
196 writeb(0x0A, rm200_pic_master + PIC_CMD);
197 return value;
198 }
199 writeb(0x0B, rm200_pic_slave + PIC_CMD); /* ISR register */
200 value = readb(rm200_pic_slave + PIC_CMD) & (irqmask >> 8);
201 writeb(0x0A, rm200_pic_slave + PIC_CMD);
202 return value;
203}
204
205/*
206 * Careful! The 8259A is a fragile beast, it pretty
207 * much _has_ to be done exactly like this (mask it
208 * first, _then_ send the EOI, and the order of EOI
209 * to the two 8259s is important!
210 */
211void sni_rm200_mask_and_ack_8259A(struct irq_data *d)
212{
213 unsigned int irqmask, irq = d->irq - RM200_I8259A_IRQ_BASE;
214 unsigned long flags;
215
216 irqmask = 1 << irq;
217 raw_spin_lock_irqsave(&sni_rm200_i8259A_lock, flags);
218 /*
219 * Lightweight spurious IRQ detection. We do not want
220 * to overdo spurious IRQ handling - it's usually a sign
221 * of hardware problems, so we only do the checks we can
222 * do without slowing down good hardware unnecessarily.
223 *
224 * Note that IRQ7 and IRQ15 (the two spurious IRQs
225 * usually resulting from the 8259A-1|2 PICs) occur
226 * even if the IRQ is masked in the 8259A. Thus we
227 * can check spurious 8259A IRQs without doing the
228 * quite slow i8259A_irq_real() call for every IRQ.
229 * This does not cover 100% of spurious interrupts,
230 * but should be enough to warn the user that there
231 * is something bad going on ...
232 */
233 if (rm200_cached_irq_mask & irqmask)
234 goto spurious_8259A_irq;
235 rm200_cached_irq_mask |= irqmask;
236
237handle_real_irq:
238 if (irq & 8) {
239 readb(rm200_pic_slave + PIC_IMR);
240 writeb(cached_slave_mask, rm200_pic_slave + PIC_IMR);
241 writeb(0x60+(irq & 7), rm200_pic_slave + PIC_CMD);
242 writeb(0x60+PIC_CASCADE_IR, rm200_pic_master + PIC_CMD);
243 } else {
244 readb(rm200_pic_master + PIC_IMR);
245 writeb(cached_master_mask, rm200_pic_master + PIC_IMR);
246 writeb(0x60+irq, rm200_pic_master + PIC_CMD);
247 }
248 raw_spin_unlock_irqrestore(&sni_rm200_i8259A_lock, flags);
249 return;
250
251spurious_8259A_irq:
252 /*
253 * this is the slow path - should happen rarely.
254 */
255 if (sni_rm200_i8259A_irq_real(irq))
256 /*
257 * oops, the IRQ _is_ in service according to the
258 * 8259A - not spurious, go handle it.
259 */
260 goto handle_real_irq;
261
262 {
263 static int spurious_irq_mask;
264 /*
265 * At this point we can be sure the IRQ is spurious,
266 * let's ACK and report it. [once per IRQ]
267 */
268 if (!(spurious_irq_mask & irqmask)) {
269 printk(KERN_DEBUG
270 "spurious RM200 8259A interrupt: IRQ%d.\n", irq);
271 spurious_irq_mask |= irqmask;
272 }
273 atomic_inc(&irq_err_count);
274 /*
275 * Theoretically we do not have to handle this IRQ,
276 * but in Linux this does not cause problems and is
277 * simpler for us.
278 */
279 goto handle_real_irq;
280 }
281}
282
283static struct irq_chip sni_rm200_i8259A_chip = {
284 .name = "RM200-XT-PIC",
285 .irq_mask = sni_rm200_disable_8259A_irq,
286 .irq_unmask = sni_rm200_enable_8259A_irq,
287 .irq_mask_ack = sni_rm200_mask_and_ack_8259A,
288};
289
290/*
291 * Do the traditional i8259 interrupt polling thing. This is for the few
292 * cases where no better interrupt acknowledge method is available and we
293 * absolutely must touch the i8259.
294 */
295static inline int sni_rm200_i8259_irq(void)
296{
297 int irq;
298
299 raw_spin_lock(&sni_rm200_i8259A_lock);
300
301 /* Perform an interrupt acknowledge cycle on controller 1. */
302 writeb(0x0C, rm200_pic_master + PIC_CMD); /* prepare for poll */
303 irq = readb(rm200_pic_master + PIC_CMD) & 7;
304 if (irq == PIC_CASCADE_IR) {
305 /*
306 * Interrupt is cascaded so perform interrupt
307 * acknowledge on controller 2.
308 */
309 writeb(0x0C, rm200_pic_slave + PIC_CMD); /* prepare for poll */
310 irq = (readb(rm200_pic_slave + PIC_CMD) & 7) + 8;
311 }
312
313 if (unlikely(irq == 7)) {
314 /*
315 * This may be a spurious interrupt.
316 *
317 * Read the interrupt status register (ISR). If the most
318 * significant bit is not set then there is no valid
319 * interrupt.
320 */
321 writeb(0x0B, rm200_pic_master + PIC_ISR); /* ISR register */
322 if (~readb(rm200_pic_master + PIC_ISR) & 0x80)
323 irq = -1;
324 }
325
326 raw_spin_unlock(&sni_rm200_i8259A_lock);
327
328 return likely(irq >= 0) ? irq + RM200_I8259A_IRQ_BASE : irq;
329}
330
331void sni_rm200_init_8259A(void)
332{
333 unsigned long flags;
334
335 raw_spin_lock_irqsave(&sni_rm200_i8259A_lock, flags);
336
337 writeb(0xff, rm200_pic_master + PIC_IMR);
338 writeb(0xff, rm200_pic_slave + PIC_IMR);
339
340 writeb(0x11, rm200_pic_master + PIC_CMD);
341 writeb(0, rm200_pic_master + PIC_IMR);
342 writeb(1U << PIC_CASCADE_IR, rm200_pic_master + PIC_IMR);
343 writeb(MASTER_ICW4_DEFAULT, rm200_pic_master + PIC_IMR);
344 writeb(0x11, rm200_pic_slave + PIC_CMD);
345 writeb(8, rm200_pic_slave + PIC_IMR);
346 writeb(PIC_CASCADE_IR, rm200_pic_slave + PIC_IMR);
347 writeb(SLAVE_ICW4_DEFAULT, rm200_pic_slave + PIC_IMR);
348 udelay(100); /* wait for 8259A to initialize */
349
350 writeb(cached_master_mask, rm200_pic_master + PIC_IMR);
351 writeb(cached_slave_mask, rm200_pic_slave + PIC_IMR);
352
353 raw_spin_unlock_irqrestore(&sni_rm200_i8259A_lock, flags);
354}
355
356/*
357 * IRQ2 is cascade interrupt to second interrupt controller
358 */
359
360static struct resource sni_rm200_pic1_resource = {
361 .name = "onboard ISA pic1",
362 .start = 0x16000020,
363 .end = 0x16000023,
364 .flags = IORESOURCE_BUSY
365};
366
367static struct resource sni_rm200_pic2_resource = {
368 .name = "onboard ISA pic2",
369 .start = 0x160000a0,
370 .end = 0x160000a3,
371 .flags = IORESOURCE_BUSY
372};
373
374/* ISA irq handler */
375static irqreturn_t sni_rm200_i8259A_irq_handler(int dummy, void *p)
376{
377 int irq;
378
379 irq = sni_rm200_i8259_irq();
380 if (unlikely(irq < 0))
381 return IRQ_NONE;
382
383 do_IRQ(irq);
384 return IRQ_HANDLED;
385}
386
387void __init sni_rm200_i8259_irqs(void)
388{
389 int i;
390
391 rm200_pic_master = ioremap(0x16000020, 4);
392 if (!rm200_pic_master)
393 return;
394 rm200_pic_slave = ioremap(0x160000a0, 4);
395 if (!rm200_pic_slave) {
396 iounmap(rm200_pic_master);
397 return;
398 }
399
400 insert_resource(&iomem_resource, &sni_rm200_pic1_resource);
401 insert_resource(&iomem_resource, &sni_rm200_pic2_resource);
402
403 sni_rm200_init_8259A();
404
405 for (i = RM200_I8259A_IRQ_BASE; i < RM200_I8259A_IRQ_BASE + 16; i++)
406 irq_set_chip_and_handler(i, &sni_rm200_i8259A_chip,
407 handle_level_irq);
408
409 if (request_irq(RM200_I8259A_IRQ_BASE + PIC_CASCADE_IR, no_action,
410 IRQF_NO_THREAD, "cascade", NULL))
411 pr_err("Failed to register cascade interrupt\n");
412}
413
414
415#define SNI_RM200_INT_STAT_REG CKSEG1ADDR(0xbc000000)
416#define SNI_RM200_INT_ENA_REG CKSEG1ADDR(0xbc080000)
417
418#define SNI_RM200_INT_START 24
419#define SNI_RM200_INT_END 28
420
421static void enable_rm200_irq(struct irq_data *d)
422{
423 unsigned int mask = 1 << (d->irq - SNI_RM200_INT_START);
424
425 *(volatile u8 *)SNI_RM200_INT_ENA_REG &= ~mask;
426}
427
428void disable_rm200_irq(struct irq_data *d)
429{
430 unsigned int mask = 1 << (d->irq - SNI_RM200_INT_START);
431
432 *(volatile u8 *)SNI_RM200_INT_ENA_REG |= mask;
433}
434
435static struct irq_chip rm200_irq_type = {
436 .name = "RM200",
437 .irq_mask = disable_rm200_irq,
438 .irq_unmask = enable_rm200_irq,
439};
440
441static void sni_rm200_hwint(void)
442{
443 u32 pending = read_c0_cause() & read_c0_status();
444 u8 mask;
445 u8 stat;
446 int irq;
447
448 if (pending & C_IRQ5)
449 do_IRQ(MIPS_CPU_IRQ_BASE + 7);
450 else if (pending & C_IRQ0) {
451 clear_c0_status(IE_IRQ0);
452 mask = *(volatile u8 *)SNI_RM200_INT_ENA_REG ^ 0x1f;
453 stat = *(volatile u8 *)SNI_RM200_INT_STAT_REG ^ 0x14;
454 irq = ffs(stat & mask & 0x1f);
455
456 if (likely(irq > 0))
457 do_IRQ(irq + SNI_RM200_INT_START - 1);
458 set_c0_status(IE_IRQ0);
459 }
460}
461
462void __init sni_rm200_irq_init(void)
463{
464 int i;
465
466 * (volatile u8 *)SNI_RM200_INT_ENA_REG = 0x1f;
467
468 sni_rm200_i8259_irqs();
469 mips_cpu_irq_init();
470 /* Actually we've got more interrupts to handle ... */
471 for (i = SNI_RM200_INT_START; i <= SNI_RM200_INT_END; i++)
472 irq_set_chip_and_handler(i, &rm200_irq_type, handle_level_irq);
473 sni_hwint = sni_rm200_hwint;
474 change_c0_status(ST0_IM, IE_IRQ0);
475 if (request_irq(SNI_RM200_INT_START + 0, sni_rm200_i8259A_irq_handler,
476 0, "onboard ISA", NULL))
477 pr_err("Failed to register onboard ISA interrupt\n");
478 if (request_irq(SNI_RM200_INT_START + 1, sni_isa_irq_handler, 0, "ISA",
479 NULL))
480 pr_err("Failed to register ISA interrupt\n");
481}
482
483void __init sni_rm200_init(void)
484{
485}
diff --git a/arch/mips/sni/setup.c b/arch/mips/sni/setup.c
new file mode 100644
index 000000000..efad85c8c
--- /dev/null
+++ b/arch/mips/sni/setup.c
@@ -0,0 +1,263 @@
1/*
2 * Setup pointers to hardware-dependent routines.
3 *
4 * This file is subject to the terms and conditions of the GNU General Public
5 * License. See the file "COPYING" in the main directory of this archive
6 * for more details.
7 *
8 * Copyright (C) 1996, 97, 98, 2000, 03, 04, 06 Ralf Baechle (ralf@linux-mips.org)
9 * Copyright (C) 2006,2007 Thomas Bogendoerfer (tsbogend@alpha.franken.de)
10 */
11#include <linux/eisa.h>
12#include <linux/init.h>
13#include <linux/export.h>
14#include <linux/console.h>
15#include <linux/fb.h>
16#include <linux/screen_info.h>
17
18#ifdef CONFIG_FW_ARC
19#include <asm/fw/arc/types.h>
20#include <asm/sgialib.h>
21#endif
22
23#ifdef CONFIG_FW_SNIPROM
24#include <asm/mipsprom.h>
25#endif
26
27#include <asm/bootinfo.h>
28#include <asm/cpu.h>
29#include <asm/io.h>
30#include <asm/reboot.h>
31#include <asm/sni.h>
32
33unsigned int sni_brd_type;
34EXPORT_SYMBOL(sni_brd_type);
35
36extern void sni_machine_restart(char *command);
37extern void sni_machine_power_off(void);
38
39static void __init sni_display_setup(void)
40{
41#if defined(CONFIG_VT) && defined(CONFIG_VGA_CONSOLE) && defined(CONFIG_FW_ARC)
42 struct screen_info *si = &screen_info;
43 DISPLAY_STATUS *di;
44
45 di = ArcGetDisplayStatus(1);
46
47 if (di) {
48 si->orig_x = di->CursorXPosition;
49 si->orig_y = di->CursorYPosition;
50 si->orig_video_cols = di->CursorMaxXPosition;
51 si->orig_video_lines = di->CursorMaxYPosition;
52 si->orig_video_isVGA = VIDEO_TYPE_VGAC;
53 si->orig_video_points = 16;
54 }
55#endif
56}
57
58static void __init sni_console_setup(void)
59{
60#ifndef CONFIG_FW_ARC
61 char *ctype;
62 char *cdev;
63 char *baud;
64 int port;
65 static char options[8] __initdata;
66
67 cdev = prom_getenv("console_dev");
68 if (strncmp(cdev, "tty", 3) == 0) {
69 ctype = prom_getenv("console");
70 switch (*ctype) {
71 default:
72 case 'l':
73 port = 0;
74 baud = prom_getenv("lbaud");
75 break;
76 case 'r':
77 port = 1;
78 baud = prom_getenv("rbaud");
79 break;
80 }
81 if (baud)
82 strcpy(options, baud);
83 if (strncmp(cdev, "tty552", 6) == 0)
84 add_preferred_console("ttyS", port,
85 baud ? options : NULL);
86 else
87 add_preferred_console("ttySC", port,
88 baud ? options : NULL);
89 }
90#endif
91}
92
93#ifdef DEBUG
94static void __init sni_idprom_dump(void)
95{
96 int i;
97
98 pr_debug("SNI IDProm dump:\n");
99 for (i = 0; i < 256; i++) {
100 if (i%16 == 0)
101 pr_debug("%04x ", i);
102
103 printk("%02x ", *(unsigned char *) (SNI_IDPROM_BASE + i));
104
105 if (i % 16 == 15)
106 printk("\n");
107 }
108}
109#endif
110
111void __init plat_mem_setup(void)
112{
113 int cputype;
114
115 set_io_port_base(SNI_PORT_BASE);
116// ioport_resource.end = sni_io_resource.end;
117
118 /*
119 * Setup (E)ISA I/O memory access stuff
120 */
121#ifdef CONFIG_EISA
122 EISA_bus = 1;
123#endif
124
125 sni_brd_type = *(unsigned char *)SNI_IDPROM_BRDTYPE;
126 cputype = *(unsigned char *)SNI_IDPROM_CPUTYPE;
127 switch (sni_brd_type) {
128 case SNI_BRD_TOWER_OASIC:
129 switch (cputype) {
130 case SNI_CPU_M8030:
131 system_type = "RM400-330";
132 break;
133 case SNI_CPU_M8031:
134 system_type = "RM400-430";
135 break;
136 case SNI_CPU_M8037:
137 system_type = "RM400-530";
138 break;
139 case SNI_CPU_M8034:
140 system_type = "RM400-730";
141 break;
142 default:
143 system_type = "RM400-xxx";
144 break;
145 }
146 break;
147 case SNI_BRD_MINITOWER:
148 switch (cputype) {
149 case SNI_CPU_M8021:
150 case SNI_CPU_M8043:
151 system_type = "RM400-120";
152 break;
153 case SNI_CPU_M8040:
154 system_type = "RM400-220";
155 break;
156 case SNI_CPU_M8053:
157 system_type = "RM400-225";
158 break;
159 case SNI_CPU_M8050:
160 system_type = "RM400-420";
161 break;
162 default:
163 system_type = "RM400-xxx";
164 break;
165 }
166 break;
167 case SNI_BRD_PCI_TOWER:
168 system_type = "RM400-Cxx";
169 break;
170 case SNI_BRD_RM200:
171 system_type = "RM200-xxx";
172 break;
173 case SNI_BRD_PCI_MTOWER:
174 system_type = "RM300-Cxx";
175 break;
176 case SNI_BRD_PCI_DESKTOP:
177 switch (read_c0_prid() & PRID_IMP_MASK) {
178 case PRID_IMP_R4600:
179 case PRID_IMP_R4700:
180 system_type = "RM200-C20";
181 break;
182 case PRID_IMP_R5000:
183 system_type = "RM200-C40";
184 break;
185 default:
186 system_type = "RM200-Cxx";
187 break;
188 }
189 break;
190 case SNI_BRD_PCI_TOWER_CPLUS:
191 system_type = "RM400-Exx";
192 break;
193 case SNI_BRD_PCI_MTOWER_CPLUS:
194 system_type = "RM300-Exx";
195 break;
196 }
197 pr_debug("Found SNI brdtype %02x name %s\n", sni_brd_type, system_type);
198
199#ifdef DEBUG
200 sni_idprom_dump();
201#endif
202
203 switch (sni_brd_type) {
204 case SNI_BRD_10:
205 case SNI_BRD_10NEW:
206 case SNI_BRD_TOWER_OASIC:
207 case SNI_BRD_MINITOWER:
208 sni_a20r_init();
209 break;
210
211 case SNI_BRD_PCI_TOWER:
212 case SNI_BRD_PCI_TOWER_CPLUS:
213 sni_pcit_init();
214 break;
215
216 case SNI_BRD_RM200:
217 sni_rm200_init();
218 break;
219
220 case SNI_BRD_PCI_MTOWER:
221 case SNI_BRD_PCI_DESKTOP:
222 case SNI_BRD_PCI_MTOWER_CPLUS:
223 sni_pcimt_init();
224 break;
225 }
226
227 _machine_restart = sni_machine_restart;
228 pm_power_off = sni_machine_power_off;
229
230 sni_display_setup();
231 sni_console_setup();
232}
233
234#ifdef CONFIG_PCI
235
236#include <linux/pci.h>
237#include <video/vga.h>
238#include <video/cirrus.h>
239
240static void quirk_cirrus_ram_size(struct pci_dev *dev)
241{
242 u16 cmd;
243
244 /*
245 * firmware doesn't set the ram size correct, so we
246 * need to do it here, otherwise we get screen corruption
247 * on older Cirrus chips
248 */
249 pci_read_config_word(dev, PCI_COMMAND, &cmd);
250 if ((cmd & (PCI_COMMAND_IO|PCI_COMMAND_MEMORY))
251 == (PCI_COMMAND_IO|PCI_COMMAND_MEMORY)) {
252 vga_wseq(NULL, CL_SEQR6, 0x12); /* unlock all extension registers */
253 vga_wseq(NULL, CL_SEQRF, 0x18);
254 }
255}
256
257DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_CIRRUS, PCI_DEVICE_ID_CIRRUS_5434_8,
258 quirk_cirrus_ram_size);
259DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_CIRRUS, PCI_DEVICE_ID_CIRRUS_5436,
260 quirk_cirrus_ram_size);
261DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_CIRRUS, PCI_DEVICE_ID_CIRRUS_5446,
262 quirk_cirrus_ram_size);
263#endif
diff --git a/arch/mips/sni/time.c b/arch/mips/sni/time.c
new file mode 100644
index 000000000..ff3ba7e77
--- /dev/null
+++ b/arch/mips/sni/time.c
@@ -0,0 +1,167 @@
1// SPDX-License-Identifier: GPL-2.0
2#include <linux/types.h>
3#include <linux/i8253.h>
4#include <linux/interrupt.h>
5#include <linux/irq.h>
6#include <linux/smp.h>
7#include <linux/time.h>
8#include <linux/clockchips.h>
9
10#include <asm/sni.h>
11#include <asm/time.h>
12
13#define SNI_CLOCK_TICK_RATE 3686400
14#define SNI_COUNTER2_DIV 64
15#define SNI_COUNTER0_DIV ((SNI_CLOCK_TICK_RATE / SNI_COUNTER2_DIV) / HZ)
16
17static int a20r_set_periodic(struct clock_event_device *evt)
18{
19 *(volatile u8 *)(A20R_PT_CLOCK_BASE + 12) = 0x34;
20 wmb();
21 *(volatile u8 *)(A20R_PT_CLOCK_BASE + 0) = SNI_COUNTER0_DIV & 0xff;
22 wmb();
23 *(volatile u8 *)(A20R_PT_CLOCK_BASE + 0) = SNI_COUNTER0_DIV >> 8;
24 wmb();
25
26 *(volatile u8 *)(A20R_PT_CLOCK_BASE + 12) = 0xb4;
27 wmb();
28 *(volatile u8 *)(A20R_PT_CLOCK_BASE + 8) = SNI_COUNTER2_DIV & 0xff;
29 wmb();
30 *(volatile u8 *)(A20R_PT_CLOCK_BASE + 8) = SNI_COUNTER2_DIV >> 8;
31 wmb();
32 return 0;
33}
34
35static struct clock_event_device a20r_clockevent_device = {
36 .name = "a20r-timer",
37 .features = CLOCK_EVT_FEAT_PERIODIC,
38
39 /* .mult, .shift, .max_delta_ns and .min_delta_ns left uninitialized */
40
41 .rating = 300,
42 .irq = SNI_A20R_IRQ_TIMER,
43 .set_state_periodic = a20r_set_periodic,
44};
45
46static irqreturn_t a20r_interrupt(int irq, void *dev_id)
47{
48 struct clock_event_device *cd = dev_id;
49
50 *(volatile u8 *)A20R_PT_TIM0_ACK = 0;
51 wmb();
52
53 cd->event_handler(cd);
54
55 return IRQ_HANDLED;
56}
57
58/*
59 * a20r platform uses 2 counters to divide the input frequency.
60 * Counter 2 output is connected to Counter 0 & 1 input.
61 */
62static void __init sni_a20r_timer_setup(void)
63{
64 struct clock_event_device *cd = &a20r_clockevent_device;
65 unsigned int cpu = smp_processor_id();
66
67 cd->cpumask = cpumask_of(cpu);
68 clockevents_register_device(cd);
69 if (request_irq(SNI_A20R_IRQ_TIMER, a20r_interrupt,
70 IRQF_PERCPU | IRQF_TIMER, "a20r-timer", cd))
71 pr_err("Failed to register a20r-timer interrupt\n");
72}
73
74#define SNI_8254_TICK_RATE 1193182UL
75
76#define SNI_8254_TCSAMP_COUNTER ((SNI_8254_TICK_RATE / HZ) + 255)
77
78static __init unsigned long dosample(void)
79{
80 u32 ct0, ct1;
81 volatile u8 msb;
82
83 /* Start the counter. */
84 outb_p(0x34, 0x43);
85 outb_p(SNI_8254_TCSAMP_COUNTER & 0xff, 0x40);
86 outb(SNI_8254_TCSAMP_COUNTER >> 8, 0x40);
87
88 /* Get initial counter invariant */
89 ct0 = read_c0_count();
90
91 /* Latch and spin until top byte of counter0 is zero */
92 do {
93 outb(0x00, 0x43);
94 (void) inb(0x40);
95 msb = inb(0x40);
96 ct1 = read_c0_count();
97 } while (msb);
98
99 /* Stop the counter. */
100 outb(0x38, 0x43);
101 /*
102 * Return the difference, this is how far the r4k counter increments
103 * for every 1/HZ seconds. We round off the nearest 1 MHz of master
104 * clock (= 1000000 / HZ / 2).
105 */
106 /*return (ct1 - ct0 + (500000/HZ/2)) / (500000/HZ) * (500000/HZ);*/
107 return (ct1 - ct0) / (500000/HZ) * (500000/HZ);
108}
109
110/*
111 * Here we need to calibrate the cycle counter to at least be close.
112 */
113void __init plat_time_init(void)
114{
115 unsigned long r4k_ticks[3];
116 unsigned long r4k_tick;
117
118 /*
119 * Figure out the r4k offset, the algorithm is very simple and works in
120 * _all_ cases as long as the 8254 counter register itself works ok (as
121 * an interrupt driving timer it does not because of bug, this is why
122 * we are using the onchip r4k counter/compare register to serve this
123 * purpose, but for r4k_offset calculation it will work ok for us).
124 * There are other very complicated ways of performing this calculation
125 * but this one works just fine so I am not going to futz around. ;-)
126 */
127 printk(KERN_INFO "Calibrating system timer... ");
128 dosample(); /* Prime cache. */
129 dosample(); /* Prime cache. */
130 /* Zero is NOT an option. */
131 do {
132 r4k_ticks[0] = dosample();
133 } while (!r4k_ticks[0]);
134 do {
135 r4k_ticks[1] = dosample();
136 } while (!r4k_ticks[1]);
137
138 if (r4k_ticks[0] != r4k_ticks[1]) {
139 printk("warning: timer counts differ, retrying... ");
140 r4k_ticks[2] = dosample();
141 if (r4k_ticks[2] == r4k_ticks[0]
142 || r4k_ticks[2] == r4k_ticks[1])
143 r4k_tick = r4k_ticks[2];
144 else {
145 printk("disagreement, using average... ");
146 r4k_tick = (r4k_ticks[0] + r4k_ticks[1]
147 + r4k_ticks[2]) / 3;
148 }
149 } else
150 r4k_tick = r4k_ticks[0];
151
152 printk("%d [%d.%04d MHz CPU]\n", (int) r4k_tick,
153 (int) (r4k_tick / (500000 / HZ)),
154 (int) (r4k_tick % (500000 / HZ)));
155
156 mips_hpt_frequency = r4k_tick * HZ;
157
158 switch (sni_brd_type) {
159 case SNI_BRD_10:
160 case SNI_BRD_10NEW:
161 case SNI_BRD_TOWER_OASIC:
162 case SNI_BRD_MINITOWER:
163 sni_a20r_timer_setup();
164 break;
165 }
166 setup_pit_timer();
167}