aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/ddb5xxx
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
commit1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch)
tree0bba044c4ce775e45a88a51686b5d9f90697ea9d /arch/mips/ddb5xxx
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history, even though we have it. We can create a separate "historical" git archive of that later if we want to, and in the meantime it's about 3.2GB when imported into git - space that would just make the early git days unnecessarily complicated, when we don't have a lot of good infrastructure for it. Let it rip!
Diffstat (limited to 'arch/mips/ddb5xxx')
-rw-r--r--arch/mips/ddb5xxx/common/Makefile5
-rw-r--r--arch/mips/ddb5xxx/common/nile4.c130
-rw-r--r--arch/mips/ddb5xxx/common/prom.c142
-rw-r--r--arch/mips/ddb5xxx/common/rtc_ds1386.c164
-rw-r--r--arch/mips/ddb5xxx/ddb5074/Makefile8
-rw-r--r--arch/mips/ddb5xxx/ddb5074/int-handler.S120
-rw-r--r--arch/mips/ddb5xxx/ddb5074/irq.c159
-rw-r--r--arch/mips/ddb5xxx/ddb5074/nile4_pic.c287
-rw-r--r--arch/mips/ddb5xxx/ddb5074/setup.c235
-rw-r--r--arch/mips/ddb5xxx/ddb5476/Makefile9
-rw-r--r--arch/mips/ddb5xxx/ddb5476/dbg_io.c136
-rw-r--r--arch/mips/ddb5xxx/ddb5476/int-handler.S112
-rw-r--r--arch/mips/ddb5xxx/ddb5476/irq.c143
-rw-r--r--arch/mips/ddb5xxx/ddb5476/nile4_pic.c190
-rw-r--r--arch/mips/ddb5xxx/ddb5476/setup.c297
-rw-r--r--arch/mips/ddb5xxx/ddb5476/vrc5476_irq.c112
-rw-r--r--arch/mips/ddb5xxx/ddb5477/Makefile10
-rw-r--r--arch/mips/ddb5xxx/ddb5477/debug.c160
-rw-r--r--arch/mips/ddb5xxx/ddb5477/int-handler.S75
-rw-r--r--arch/mips/ddb5xxx/ddb5477/irq.c199
-rw-r--r--arch/mips/ddb5xxx/ddb5477/irq_5477.c168
-rw-r--r--arch/mips/ddb5xxx/ddb5477/kgdb_io.c136
-rw-r--r--arch/mips/ddb5xxx/ddb5477/lcd44780.c92
-rw-r--r--arch/mips/ddb5xxx/ddb5477/lcd44780.h15
-rw-r--r--arch/mips/ddb5xxx/ddb5477/setup.c405
25 files changed, 3509 insertions, 0 deletions
diff --git a/arch/mips/ddb5xxx/common/Makefile b/arch/mips/ddb5xxx/common/Makefile
new file mode 100644
index 000000000000..bc44e3032711
--- /dev/null
+++ b/arch/mips/ddb5xxx/common/Makefile
@@ -0,0 +1,5 @@
1#
2# Makefile for the common code of NEC DDB-Vrc5xxx board
3#
4
5obj-y += nile4.o prom.o rtc_ds1386.o
diff --git a/arch/mips/ddb5xxx/common/nile4.c b/arch/mips/ddb5xxx/common/nile4.c
new file mode 100644
index 000000000000..7ec7d903ba97
--- /dev/null
+++ b/arch/mips/ddb5xxx/common/nile4.c
@@ -0,0 +1,130 @@
1/*
2 *
3 * Copyright 2001 MontaVista Software Inc.
4 * Author: jsun@mvista.com or jsun@junsun.net
5 *
6 * arch/mips/ddb5xxx/common/nile4.c
7 * misc low-level routines for vrc-5xxx controllers.
8 *
9 * derived from original code by Geert Uytterhoeven <geert@sonycom.com>
10 *
11 * This program is free software; you can redistribute it and/or modify it
12 * under the terms of the GNU General Public License as published by the
13 * Free Software Foundation; either version 2 of the License, or (at your
14 * option) any later version.
15 */
16#include <linux/types.h>
17#include <linux/kernel.h>
18
19#include <asm/ddb5xxx/ddb5xxx.h>
20
21u32
22ddb_calc_pdar(u32 phys, u32 size, int width,
23 int on_memory_bus, int pci_visible)
24{
25 u32 maskbits;
26 u32 widthbits;
27
28 switch (size) {
29#if 0 /* We don't support 4 GB yet */
30 case 0x100000000: /* 4 GB */
31 maskbits = 4;
32 break;
33#endif
34 case 0x80000000: /* 2 GB */
35 maskbits = 5;
36 break;
37 case 0x40000000: /* 1 GB */
38 maskbits = 6;
39 break;
40 case 0x20000000: /* 512 MB */
41 maskbits = 7;
42 break;
43 case 0x10000000: /* 256 MB */
44 maskbits = 8;
45 break;
46 case 0x08000000: /* 128 MB */
47 maskbits = 9;
48 break;
49 case 0x04000000: /* 64 MB */
50 maskbits = 10;
51 break;
52 case 0x02000000: /* 32 MB */
53 maskbits = 11;
54 break;
55 case 0x01000000: /* 16 MB */
56 maskbits = 12;
57 break;
58 case 0x00800000: /* 8 MB */
59 maskbits = 13;
60 break;
61 case 0x00400000: /* 4 MB */
62 maskbits = 14;
63 break;
64 case 0x00200000: /* 2 MB */
65 maskbits = 15;
66 break;
67 case 0: /* OFF */
68 maskbits = 0;
69 break;
70 default:
71 panic("nile4_set_pdar: unsupported size %p", (void *) size);
72 }
73 switch (width) {
74 case 8:
75 widthbits = 0;
76 break;
77 case 16:
78 widthbits = 1;
79 break;
80 case 32:
81 widthbits = 2;
82 break;
83 case 64:
84 widthbits = 3;
85 break;
86 default:
87 panic("nile4_set_pdar: unsupported width %d", width);
88 }
89
90 return maskbits | (on_memory_bus ? 0x10 : 0) |
91 (pci_visible ? 0x20 : 0) | (widthbits << 6) |
92 (phys & 0xffe00000);
93}
94
95void
96ddb_set_pdar(u32 pdar, u32 phys, u32 size, int width,
97 int on_memory_bus, int pci_visible)
98{
99 u32 temp= ddb_calc_pdar(phys, size, width, on_memory_bus, pci_visible);
100 ddb_out32(pdar, temp);
101 ddb_out32(pdar + 4, 0);
102
103 /*
104 * When programming a PDAR, the register should be read immediately
105 * after writing it. This ensures that address decoders are properly
106 * configured.
107 * [jsun] is this really necessary?
108 */
109 ddb_in32(pdar);
110 ddb_in32(pdar + 4);
111}
112
113/*
114 * routines that mess with PCIINITx registers
115 */
116
117void ddb_set_pmr(u32 pmr, u32 type, u32 addr, u32 options)
118{
119 switch (type) {
120 case DDB_PCICMD_IACK: /* PCI Interrupt Acknowledge */
121 case DDB_PCICMD_IO: /* PCI I/O Space */
122 case DDB_PCICMD_MEM: /* PCI Memory Space */
123 case DDB_PCICMD_CFG: /* PCI Configuration Space */
124 break;
125 default:
126 panic("nile4_set_pmr: invalid type %d", type);
127 }
128 ddb_out32(pmr, (type << 1) | (addr & 0xffe00000) | options );
129 ddb_out32(pmr + 4, 0);
130}
diff --git a/arch/mips/ddb5xxx/common/prom.c b/arch/mips/ddb5xxx/common/prom.c
new file mode 100644
index 000000000000..b8d1f7489f3b
--- /dev/null
+++ b/arch/mips/ddb5xxx/common/prom.c
@@ -0,0 +1,142 @@
1/*
2 * Copyright 2001 MontaVista Software Inc.
3 * Author: jsun@mvista.com or jsun@junsun.net
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version.
9 */
10#include <linux/config.h>
11#include <linux/init.h>
12#include <linux/mm.h>
13#include <linux/sched.h>
14#include <linux/bootmem.h>
15
16#include <asm/addrspace.h>
17#include <asm/bootinfo.h>
18#include <asm/ddb5xxx/ddb5xxx.h>
19#include <asm/debug.h>
20
21const char *get_system_type(void)
22{
23 switch (mips_machtype) {
24 case MACH_NEC_DDB5074: return "NEC DDB Vrc-5074";
25 case MACH_NEC_DDB5476: return "NEC DDB Vrc-5476";
26 case MACH_NEC_DDB5477: return "NEC DDB Vrc-5477";
27 case MACH_NEC_ROCKHOPPER: return "NEC Rockhopper";
28 case MACH_NEC_ROCKHOPPERII: return "NEC RockhopperII";
29 default: return "Unknown NEC board";
30 }
31}
32
33#if defined(CONFIG_DDB5477)
34void ddb5477_runtime_detection(void);
35#endif
36
37/* [jsun@junsun.net] PMON passes arguments in C main() style */
38void __init prom_init(void)
39{
40 int argc = fw_arg0;
41 char **arg = (char**) fw_arg1;
42 int i;
43
44 /* if user passes kernel args, ignore the default one */
45 if (argc > 1)
46 arcs_cmdline[0] = '\0';
47
48 /* arg[0] is "g", the rest is boot parameters */
49 for (i = 1; i < argc; i++) {
50 if (strlen(arcs_cmdline) + strlen(arg[i] + 1)
51 >= sizeof(arcs_cmdline))
52 break;
53 strcat(arcs_cmdline, arg[i]);
54 strcat(arcs_cmdline, " ");
55 }
56
57 mips_machgroup = MACH_GROUP_NEC_DDB;
58
59#if defined(CONFIG_DDB5074)
60 mips_machtype = MACH_NEC_DDB5074;
61 add_memory_region(0, DDB_SDRAM_SIZE, BOOT_MEM_RAM);
62#elif defined(CONFIG_DDB5476)
63 mips_machtype = MACH_NEC_DDB5476;
64 add_memory_region(0, DDB_SDRAM_SIZE, BOOT_MEM_RAM);
65#elif defined(CONFIG_DDB5477)
66 ddb5477_runtime_detection();
67 add_memory_region(0, board_ram_size, BOOT_MEM_RAM);
68#endif
69}
70
71unsigned long __init prom_free_prom_memory(void)
72{
73 return 0;
74}
75
76#if defined(CONFIG_DDB5477)
77
78#define DEFAULT_LCS1_BASE 0x19000000
79#define TESTVAL1 'K'
80#define TESTVAL2 'S'
81
82int board_ram_size;
83void ddb5477_runtime_detection(void)
84{
85 volatile char *test_offset;
86 char saved_test_byte;
87
88 /* Determine if this is a DDB5477 board, or a BSB-VR0300
89 base board. We can tell by checking for the location of
90 the NVRAM. It lives at the beginning of LCS1 on the DDB5477,
91 and the beginning of LCS1 on the BSB-VR0300 is flash memory.
92 The first 2K of the NVRAM are reserved, so don't we'll poke
93 around just after that.
94 */
95
96 /* We can only use the PCI bus to distinquish between
97 the Rockhopper and RockhopperII backplanes and this must
98 wait until ddb5477_board_init() in setup.c after the 5477
99 is initialized. So, until then handle
100 both Rockhopper and RockhopperII backplanes as Rockhopper 1
101 */
102
103 test_offset = (char *)KSEG1ADDR(DEFAULT_LCS1_BASE + 0x800);
104 saved_test_byte = *test_offset;
105
106 *test_offset = TESTVAL1;
107 if (*test_offset != TESTVAL1) {
108 /* We couldn't set our test value, so it must not be NVRAM,
109 so it's a BSB_VR0300 */
110 mips_machtype = MACH_NEC_ROCKHOPPER;
111 } else {
112 /* We may have gotten lucky, and the TESTVAL1 was already
113 stored at the test location, so we must check a second
114 test value */
115 *test_offset = TESTVAL2;
116 if (*test_offset != TESTVAL2) {
117 /* OK, we couldn't set this value either, so it must
118 definately be a BSB_VR0300 */
119 mips_machtype = MACH_NEC_ROCKHOPPER;
120 } else {
121 /* We could change the value twice, so it must be
122 NVRAM, so it's a DDB_VRC5477 */
123 mips_machtype = MACH_NEC_DDB5477;
124 }
125 }
126 /* Restore the original byte */
127 *test_offset = saved_test_byte;
128
129 /* before we know a better way, we will trust PMON for getting
130 * RAM size
131 */
132 board_ram_size = 1 << (36 - (ddb_in32(DDB_SDRAM0) & 0xf));
133
134 db_run(printk("DDB run-time detection : %s, %d MB RAM\n",
135 mips_machtype == MACH_NEC_DDB5477 ?
136 "DDB5477" : "Rockhopper",
137 board_ram_size >> 20));
138
139 /* we can't handle ram size > 128 MB */
140 db_assert(board_ram_size <= (128 << 20));
141}
142#endif
diff --git a/arch/mips/ddb5xxx/common/rtc_ds1386.c b/arch/mips/ddb5xxx/common/rtc_ds1386.c
new file mode 100644
index 000000000000..f5b11508ff2f
--- /dev/null
+++ b/arch/mips/ddb5xxx/common/rtc_ds1386.c
@@ -0,0 +1,164 @@
1/*
2 * Copyright 2001 MontaVista Software Inc.
3 * Author: jsun@mvista.com or jsun@junsun.net
4 *
5 * arch/mips/ddb5xxx/common/rtc_ds1386.c
6 * low-level RTC hookups for s for Dallas 1396 chip.
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
12 */
13
14
15/*
16 * This file exports a function, rtc_ds1386_init(), which expects an
17 * uncached base address as the argument. It will set the two function
18 * pointers expected by the MIPS generic timer code.
19 */
20
21#include <linux/types.h>
22#include <linux/time.h>
23#include <linux/bcd.h>
24
25#include <asm/time.h>
26#include <asm/addrspace.h>
27
28#include <asm/mc146818rtc.h>
29#include <asm/debug.h>
30
31#define EPOCH 2000
32
33#define READ_RTC(x) *(volatile unsigned char*)(rtc_base+x)
34#define WRITE_RTC(x, y) *(volatile unsigned char*)(rtc_base+x) = y
35
36static unsigned long rtc_base;
37
38static unsigned long
39rtc_ds1386_get_time(void)
40{
41 u8 byte;
42 u8 temp;
43 unsigned int year, month, day, hour, minute, second;
44
45 /* let us freeze external registers */
46 byte = READ_RTC(0xB);
47 byte &= 0x3f;
48 WRITE_RTC(0xB, byte);
49
50 /* read time data */
51 year = BCD2BIN(READ_RTC(0xA)) + EPOCH;
52 month = BCD2BIN(READ_RTC(0x9) & 0x1f);
53 day = BCD2BIN(READ_RTC(0x8));
54 minute = BCD2BIN(READ_RTC(0x2));
55 second = BCD2BIN(READ_RTC(0x1));
56
57 /* hour is special - deal with it later */
58 temp = READ_RTC(0x4);
59
60 /* enable time transfer */
61 byte |= 0x80;
62 WRITE_RTC(0xB, byte);
63
64 /* calc hour */
65 if (temp & 0x40) {
66 /* 12 hour format */
67 hour = BCD2BIN(temp & 0x1f);
68 if (temp & 0x20) hour += 12; /* PM */
69 } else {
70 /* 24 hour format */
71 hour = BCD2BIN(temp & 0x3f);
72 }
73
74 return mktime(year, month, day, hour, minute, second);
75}
76
77static int
78rtc_ds1386_set_time(unsigned long t)
79{
80 struct rtc_time tm;
81 u8 byte;
82 u8 temp;
83 u8 year, month, day, hour, minute, second;
84
85 /* let us freeze external registers */
86 byte = READ_RTC(0xB);
87 byte &= 0x3f;
88 WRITE_RTC(0xB, byte);
89
90 /* convert */
91 to_tm(t, &tm);
92
93
94 /* check each field one by one */
95 year = BIN2BCD(tm.tm_year - EPOCH);
96 if (year != READ_RTC(0xA)) {
97 WRITE_RTC(0xA, year);
98 }
99
100 temp = READ_RTC(0x9);
101 month = BIN2BCD(tm.tm_mon+1); /* tm_mon starts from 0 to 11 */
102 if (month != (temp & 0x1f)) {
103 WRITE_RTC( 0x9,
104 (month & 0x1f) | (temp & ~0x1f) );
105 }
106
107 day = BIN2BCD(tm.tm_mday);
108 if (day != READ_RTC(0x8)) {
109 WRITE_RTC(0x8, day);
110 }
111
112 temp = READ_RTC(0x4);
113 if (temp & 0x40) {
114 /* 12 hour format */
115 hour = 0x40;
116 if (tm.tm_hour > 12) {
117 hour |= 0x20 | (BIN2BCD(hour-12) & 0x1f);
118 } else {
119 hour |= BIN2BCD(tm.tm_hour);
120 }
121 } else {
122 /* 24 hour format */
123 hour = BIN2BCD(tm.tm_hour) & 0x3f;
124 }
125 if (hour != temp) WRITE_RTC(0x4, hour);
126
127 minute = BIN2BCD(tm.tm_min);
128 if (minute != READ_RTC(0x2)) {
129 WRITE_RTC(0x2, minute);
130 }
131
132 second = BIN2BCD(tm.tm_sec);
133 if (second != READ_RTC(0x1)) {
134 WRITE_RTC(0x1, second);
135 }
136
137 return 0;
138}
139
140void
141rtc_ds1386_init(unsigned long base)
142{
143 unsigned char byte;
144
145 /* remember the base */
146 rtc_base = base;
147 db_assert((rtc_base & 0xe0000000) == KSEG1);
148
149 /* turn on RTC if it is not on */
150 byte = READ_RTC(0x9);
151 if (byte & 0x80) {
152 byte &= 0x7f;
153 WRITE_RTC(0x9, byte);
154 }
155
156 /* enable time transfer */
157 byte = READ_RTC(0xB);
158 byte |= 0x80;
159 WRITE_RTC(0xB, byte);
160
161 /* set the function pointers */
162 rtc_get_time = rtc_ds1386_get_time;
163 rtc_set_time = rtc_ds1386_set_time;
164}
diff --git a/arch/mips/ddb5xxx/ddb5074/Makefile b/arch/mips/ddb5xxx/ddb5074/Makefile
new file mode 100644
index 000000000000..488206b8d94e
--- /dev/null
+++ b/arch/mips/ddb5xxx/ddb5074/Makefile
@@ -0,0 +1,8 @@
1#
2# Makefile for the NEC DDB Vrc-5074 specific kernel interface routines
3# under Linux.
4#
5
6obj-y += setup.o irq.o int-handler.o nile4_pic.o
7
8EXTRA_AFLAGS := $(CFLAGS)
diff --git a/arch/mips/ddb5xxx/ddb5074/int-handler.S b/arch/mips/ddb5xxx/ddb5074/int-handler.S
new file mode 100644
index 000000000000..a78644150b37
--- /dev/null
+++ b/arch/mips/ddb5xxx/ddb5074/int-handler.S
@@ -0,0 +1,120 @@
1/*
2 * arch/mips/ddb5074/int-handler.S -- NEC DDB Vrc-5074 interrupt handler
3 *
4 * Based on arch/mips/sgi/kernel/indyIRQ.S
5 *
6 * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
7 *
8 * Copyright (C) 2000 Geert Uytterhoeven <geert@sonycom.com>
9 * Sony Software Development Center Europe (SDCE), Brussels
10 */
11#include <asm/asm.h>
12#include <asm/mipsregs.h>
13#include <asm/regdef.h>
14#include <asm/stackframe.h>
15
16/* A lot of complication here is taken away because:
17 *
18 * 1) We handle one interrupt and return, sitting in a loop and moving across
19 * all the pending IRQ bits in the cause register is _NOT_ the answer, the
20 * common case is one pending IRQ so optimize in that direction.
21 *
22 * 2) We need not check against bits in the status register IRQ mask, that
23 * would make this routine slow as hell.
24 *
25 * 3) Linux only thinks in terms of all IRQs on or all IRQs off, nothing in
26 * between like BSD spl() brain-damage.
27 *
28 * Furthermore, the IRQs on the INDY look basically (barring software IRQs
29 * which we don't use at all) like:
30 *
31 * MIPS IRQ Source
32 * -------- ------
33 * 0 Software (ignored)
34 * 1 Software (ignored)
35 * 2 Local IRQ level zero
36 * 3 Local IRQ level one
37 * 4 8254 Timer zero
38 * 5 8254 Timer one
39 * 6 Bus Error
40 * 7 R4k timer (what we use)
41 *
42 * We handle the IRQ according to _our_ priority which is:
43 *
44 * Highest ---- R4k Timer
45 * Local IRQ zero
46 * Local IRQ one
47 * Bus Error
48 * 8254 Timer zero
49 * Lowest ---- 8254 Timer one
50 *
51 * then we just return, if multiple IRQs are pending then we will just take
52 * another exception, big deal.
53 */
54
55 .text
56 .set noreorder
57 .set noat
58 .align 5
59 NESTED(ddbIRQ, PT_SIZE, sp)
60 SAVE_ALL
61 CLI
62 .set at
63 mfc0 s0, CP0_CAUSE # get irq mask
64
65#if 1
66 mfc0 t2,CP0_STATUS # get enabled interrupts
67 and s0,t2 # isolate allowed ones
68#endif
69 /* First we check for r4k counter/timer IRQ. */
70 andi a0, s0, CAUSEF_IP2 # delay slot, check local level zero
71 beq a0, zero, 1f
72 andi a0, s0, CAUSEF_IP3 # delay slot, check local level one
73
74 /* Wheee, local level zero interrupt. */
75 jal ddb_local0_irqdispatch
76 move a0, sp # delay slot
77
78 j ret_from_irq
79 nop # delay slot
80
811:
82 beq a0, zero, 1f
83 andi a0, s0, CAUSEF_IP6 # delay slot, check bus error
84
85 /* Wheee, local level one interrupt. */
86 move a0, sp
87 jal ddb_local1_irqdispatch
88 nop
89
90 j ret_from_irq
91 nop
92
931:
94 beq a0, zero, 1f
95 nop
96
97 /* Wheee, an asynchronous bus error... */
98 move a0, sp
99 jal ddb_buserror_irq
100 nop
101
102 j ret_from_irq
103 nop
104
1051:
106 /* Here by mistake? This is possible, what can happen
107 * is that by the time we take the exception the IRQ
108 * pin goes low, so just leave if this is the case.
109 */
110 andi a0, s0, (CAUSEF_IP4 | CAUSEF_IP5)
111 beq a0, zero, 1f
112
113 /* Must be one of the 8254 timers... */
114 move a0, sp
115 jal ddb_8254timer_irq
116 nop
1171:
118 j ret_from_irq
119 nop
120 END(ddbIRQ)
diff --git a/arch/mips/ddb5xxx/ddb5074/irq.c b/arch/mips/ddb5xxx/ddb5074/irq.c
new file mode 100644
index 000000000000..45088a1be414
--- /dev/null
+++ b/arch/mips/ddb5xxx/ddb5074/irq.c
@@ -0,0 +1,159 @@
1/*
2 * arch/mips/ddb5074/irq.c -- NEC DDB Vrc-5074 interrupt routines
3 *
4 * Copyright (C) 2000 Geert Uytterhoeven <geert@sonycom.com>
5 * Sony Software Development Center Europe (SDCE), Brussels
6 */
7#include <linux/init.h>
8#include <linux/irq.h>
9#include <linux/signal.h>
10#include <linux/sched.h>
11#include <linux/types.h>
12#include <linux/interrupt.h>
13#include <linux/ioport.h>
14
15#include <asm/i8259.h>
16#include <asm/io.h>
17#include <asm/irq_cpu.h>
18#include <asm/ptrace.h>
19#include <asm/nile4.h>
20#include <asm/ddb5xxx/ddb5xxx.h>
21#include <asm/ddb5xxx/ddb5074.h>
22
23
24extern asmlinkage void ddbIRQ(void);
25
26static struct irqaction irq_cascade = { no_action, 0, CPU_MASK_NONE, "cascade", NULL, NULL };
27
28#define M1543_PNP_CONFIG 0x03f0 /* PnP Config Port */
29#define M1543_PNP_INDEX 0x03f0 /* PnP Index Port */
30#define M1543_PNP_DATA 0x03f1 /* PnP Data Port */
31
32#define M1543_PNP_ALT_CONFIG 0x0370 /* Alternative PnP Config Port */
33#define M1543_PNP_ALT_INDEX 0x0370 /* Alternative PnP Index Port */
34#define M1543_PNP_ALT_DATA 0x0371 /* Alternative PnP Data Port */
35
36#define M1543_INT1_MASTER_CTRL 0x0020 /* INT_1 (master) Control Register */
37#define M1543_INT1_MASTER_MASK 0x0021 /* INT_1 (master) Mask Register */
38
39#define M1543_INT1_SLAVE_CTRL 0x00a0 /* INT_1 (slave) Control Register */
40#define M1543_INT1_SLAVE_MASK 0x00a1 /* INT_1 (slave) Mask Register */
41
42#define M1543_INT1_MASTER_ELCR 0x04d0 /* INT_1 (master) Edge/Level Control */
43#define M1543_INT1_SLAVE_ELCR 0x04d1 /* INT_1 (slave) Edge/Level Control */
44
45
46static void m1543_irq_setup(void)
47{
48 /*
49 * The ALI M1543 has 13 interrupt inputs, IRQ1..IRQ13. Not all
50 * the possible IO sources in the M1543 are in use by us. We will
51 * use the following mapping:
52 *
53 * IRQ1 - keyboard (default set by M1543)
54 * IRQ3 - reserved for UART B (default set by M1543) (note that
55 * the schematics for the DDB Vrc-5074 board seem to
56 * indicate that IRQ3 is connected to the DS1386
57 * watchdog timer interrupt output so we might have
58 * a conflict)
59 * IRQ4 - reserved for UART A (default set by M1543)
60 * IRQ5 - parallel (default set by M1543)
61 * IRQ8 - DS1386 time of day (RTC) interrupt
62 * IRQ12 - mouse
63 */
64
65 /*
66 * Assing mouse interrupt to IRQ12
67 */
68
69 /* Enter configuration mode */
70 outb(0x51, M1543_PNP_CONFIG);
71 outb(0x23, M1543_PNP_CONFIG);
72
73 /* Select logical device 7 (Keyboard) */
74 outb(0x07, M1543_PNP_INDEX);
75 outb(0x07, M1543_PNP_DATA);
76
77 /* Select IRQ12 */
78 outb(0x72, M1543_PNP_INDEX);
79 outb(0x0c, M1543_PNP_DATA);
80
81 outb(0x30, M1543_PNP_INDEX);
82 printk("device 7, 0x30: %02x\n",inb(M1543_PNP_DATA));
83
84 outb(0x70, M1543_PNP_INDEX);
85 printk("device 7, 0x70: %02x\n",inb(M1543_PNP_DATA));
86
87 /* Leave configration mode */
88 outb(0xbb, M1543_PNP_CONFIG);
89
90
91}
92
93void ddb_local0_irqdispatch(struct pt_regs *regs)
94{
95 u32 mask;
96 int nile4_irq;
97
98 mask = nile4_get_irq_stat(0);
99
100 /* Handle the timer interrupt first */
101#if 0
102 if (mask & (1 << NILE4_INT_GPT)) {
103 do_IRQ(nile4_to_irq(NILE4_INT_GPT), regs);
104 mask &= ~(1 << NILE4_INT_GPT);
105 }
106#endif
107 for (nile4_irq = 0; mask; nile4_irq++, mask >>= 1)
108 if (mask & 1) {
109 if (nile4_irq == NILE4_INT_INTE) {
110 int i8259_irq;
111
112 nile4_clear_irq(NILE4_INT_INTE);
113 i8259_irq = nile4_i8259_iack();
114 do_IRQ(i8259_irq, regs);
115 } else
116 do_IRQ(nile4_to_irq(nile4_irq), regs);
117
118 }
119}
120
121void ddb_local1_irqdispatch(void)
122{
123 printk("ddb_local1_irqdispatch called\n");
124}
125
126void ddb_buserror_irq(void)
127{
128 printk("ddb_buserror_irq called\n");
129}
130
131void ddb_8254timer_irq(void)
132{
133 printk("ddb_8254timer_irq called\n");
134}
135
136void __init arch_init_irq(void)
137{
138 /* setup cascade interrupts */
139 setup_irq(NILE4_IRQ_BASE + NILE4_INT_INTE, &irq_cascade);
140 setup_irq(CPU_IRQ_BASE + CPU_NILE4_CASCADE, &irq_cascade);
141
142 set_except_vector(0, ddbIRQ);
143
144 nile4_irq_setup(NILE4_IRQ_BASE);
145 m1543_irq_setup();
146 init_i8259_irqs();
147
148
149 printk("CPU_IRQ_BASE: %d\n",CPU_IRQ_BASE);
150
151 mips_cpu_irq_init(CPU_IRQ_BASE);
152
153 printk("enabling 8259 cascade\n");
154
155 ddb5074_led_hex(0);
156
157 /* Enable the interrupt cascade */
158 nile4_enable_irq(NILE4_IRQ_BASE+IRQ_I8259_CASCADE);
159}
diff --git a/arch/mips/ddb5xxx/ddb5074/nile4_pic.c b/arch/mips/ddb5xxx/ddb5074/nile4_pic.c
new file mode 100644
index 000000000000..68c127cd70c9
--- /dev/null
+++ b/arch/mips/ddb5xxx/ddb5074/nile4_pic.c
@@ -0,0 +1,287 @@
1/*
2 * arch/mips/ddb5476/nile4.c --
3 * low-level PIC code for NEC Vrc-5476 (Nile 4)
4 *
5 * Copyright (C) 2000 Geert Uytterhoeven <geert@sonycom.com>
6 * Sony Software Development Center Europe (SDCE), Brussels
7 *
8 * Copyright 2001 MontaVista Software Inc.
9 * Author: jsun@mvista.com or jsun@junsun.net
10 *
11 */
12#include <linux/config.h>
13#include <linux/kernel.h>
14#include <linux/types.h>
15#include <linux/interrupt.h>
16#include <linux/ioport.h>
17
18#include <asm/addrspace.h>
19
20#include <asm/ddb5xxx/ddb5xxx.h>
21
22static int irq_base;
23
24/*
25 * Interrupt Programming
26 */
27void nile4_map_irq(int nile4_irq, int cpu_irq)
28{
29 u32 offset, t;
30
31 offset = DDB_INTCTRL;
32 if (nile4_irq >= 8) {
33 offset += 4;
34 nile4_irq -= 8;
35 }
36 t = ddb_in32(offset);
37 t &= ~(7 << (nile4_irq * 4));
38 t |= cpu_irq << (nile4_irq * 4);
39 ddb_out32(offset, t);
40}
41
42void nile4_map_irq_all(int cpu_irq)
43{
44 u32 all, t;
45
46 all = cpu_irq;
47 all |= all << 4;
48 all |= all << 8;
49 all |= all << 16;
50 t = ddb_in32(DDB_INTCTRL);
51 t &= 0x88888888;
52 t |= all;
53 ddb_out32(DDB_INTCTRL, t);
54 t = ddb_in32(DDB_INTCTRL + 4);
55 t &= 0x88888888;
56 t |= all;
57 ddb_out32(DDB_INTCTRL + 4, t);
58}
59
60void nile4_enable_irq(unsigned int nile4_irq)
61{
62 u32 offset, t;
63
64 nile4_irq-=irq_base;
65
66 ddb5074_led_hex(8);
67
68 offset = DDB_INTCTRL;
69 if (nile4_irq >= 8) {
70 offset += 4;
71 nile4_irq -= 8;
72 }
73 ddb5074_led_hex(9);
74 t = ddb_in32(offset);
75 ddb5074_led_hex(0xa);
76 t |= 8 << (nile4_irq * 4);
77 ddb_out32(offset, t);
78 ddb5074_led_hex(0xb);
79}
80
81void nile4_disable_irq(unsigned int nile4_irq)
82{
83 u32 offset, t;
84
85 nile4_irq-=irq_base;
86
87 offset = DDB_INTCTRL;
88 if (nile4_irq >= 8) {
89 offset += 4;
90 nile4_irq -= 8;
91 }
92 t = ddb_in32(offset);
93 t &= ~(8 << (nile4_irq * 4));
94 ddb_out32(offset, t);
95}
96
97void nile4_disable_irq_all(void)
98{
99 ddb_out32(DDB_INTCTRL, 0);
100 ddb_out32(DDB_INTCTRL + 4, 0);
101}
102
103u16 nile4_get_irq_stat(int cpu_irq)
104{
105 return ddb_in16(DDB_INTSTAT0 + cpu_irq * 2);
106}
107
108void nile4_enable_irq_output(int cpu_irq)
109{
110 u32 t;
111
112 t = ddb_in32(DDB_INTSTAT1 + 4);
113 t |= 1 << (16 + cpu_irq);
114 ddb_out32(DDB_INTSTAT1, t);
115}
116
117void nile4_disable_irq_output(int cpu_irq)
118{
119 u32 t;
120
121 t = ddb_in32(DDB_INTSTAT1 + 4);
122 t &= ~(1 << (16 + cpu_irq));
123 ddb_out32(DDB_INTSTAT1, t);
124}
125
126void nile4_set_pci_irq_polarity(int pci_irq, int high)
127{
128 u32 t;
129
130 t = ddb_in32(DDB_INTPPES);
131 if (high)
132 t &= ~(1 << (pci_irq * 2));
133 else
134 t |= 1 << (pci_irq * 2);
135 ddb_out32(DDB_INTPPES, t);
136}
137
138void nile4_set_pci_irq_level_or_edge(int pci_irq, int level)
139{
140 u32 t;
141
142 t = ddb_in32(DDB_INTPPES);
143 if (level)
144 t |= 2 << (pci_irq * 2);
145 else
146 t &= ~(2 << (pci_irq * 2));
147 ddb_out32(DDB_INTPPES, t);
148}
149
150void nile4_clear_irq(int nile4_irq)
151{
152 nile4_irq-=irq_base;
153 ddb_out32(DDB_INTCLR, 1 << nile4_irq);
154}
155
156void nile4_clear_irq_mask(u32 mask)
157{
158 ddb_out32(DDB_INTCLR, mask);
159}
160
161u8 nile4_i8259_iack(void)
162{
163 u8 irq;
164 u32 reg;
165
166 /* Set window 0 for interrupt acknowledge */
167 reg = ddb_in32(DDB_PCIINIT0);
168
169 ddb_set_pmr(DDB_PCIINIT0, DDB_PCICMD_IACK, 0, DDB_PCI_ACCESS_32);
170 irq = *(volatile u8 *) KSEG1ADDR(DDB_PCI_IACK_BASE);
171 /* restore window 0 for PCI I/O space */
172 // ddb_set_pmr(DDB_PCIINIT0, DDB_PCICMD_IO, 0, DDB_PCI_ACCESS_32);
173 ddb_out32(DDB_PCIINIT0, reg);
174
175 /* i8269.c set the base vector to be 0x0 */
176 return irq ;
177}
178
179static unsigned int nile4_irq_startup(unsigned int irq) {
180
181 nile4_enable_irq(irq);
182 return 0;
183
184}
185
186static void nile4_ack_irq(unsigned int irq) {
187
188 ddb5074_led_hex(4);
189
190 nile4_clear_irq(irq);
191 ddb5074_led_hex(2);
192 nile4_disable_irq(irq);
193
194 ddb5074_led_hex(0);
195}
196
197static void nile4_irq_end(unsigned int irq) {
198
199 ddb5074_led_hex(3);
200 if(!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) {
201 ddb5074_led_hex(5);
202 nile4_enable_irq(irq);
203 ddb5074_led_hex(7);
204 }
205
206 ddb5074_led_hex(1);
207}
208
209#define nile4_irq_shutdown nile4_disable_irq
210
211static hw_irq_controller nile4_irq_controller = {
212 "nile4",
213 nile4_irq_startup,
214 nile4_irq_shutdown,
215 nile4_enable_irq,
216 nile4_disable_irq,
217 nile4_ack_irq,
218 nile4_irq_end,
219 NULL
220};
221
222void nile4_irq_setup(u32 base) {
223
224 int i;
225
226 irq_base=base;
227
228 /* Map all interrupts to CPU int #0 */
229 nile4_map_irq_all(0);
230
231 /* PCI INTA#-E# must be level triggered */
232 nile4_set_pci_irq_level_or_edge(0, 1);
233 nile4_set_pci_irq_level_or_edge(1, 1);
234 nile4_set_pci_irq_level_or_edge(2, 1);
235 nile4_set_pci_irq_level_or_edge(3, 1);
236 nile4_set_pci_irq_level_or_edge(4, 1);
237
238 /* PCI INTA#-D# must be active low, INTE# must be active high */
239 nile4_set_pci_irq_polarity(0, 0);
240 nile4_set_pci_irq_polarity(1, 0);
241 nile4_set_pci_irq_polarity(2, 0);
242 nile4_set_pci_irq_polarity(3, 0);
243 nile4_set_pci_irq_polarity(4, 1);
244
245
246 for (i = 0; i < 16; i++) {
247 nile4_clear_irq(i);
248 nile4_disable_irq(i);
249 }
250
251 /* Enable CPU int #0 */
252 nile4_enable_irq_output(0);
253
254 for (i= base; i< base + NUM_NILE4_INTERRUPTS; i++) {
255 irq_desc[i].status = IRQ_DISABLED;
256 irq_desc[i].action = NULL;
257 irq_desc[i].depth = 1;
258 irq_desc[i].handler = &nile4_irq_controller;
259 }
260}
261
262#if defined(CONFIG_RUNTIME_DEBUG)
263void nile4_dump_irq_status(void)
264{
265 printk(KERN_DEBUG "
266 CPUSTAT = %p:%p\n", (void *) ddb_in32(DDB_CPUSTAT + 4),
267 (void *) ddb_in32(DDB_CPUSTAT));
268 printk(KERN_DEBUG "
269 INTCTRL = %p:%p\n", (void *) ddb_in32(DDB_INTCTRL + 4),
270 (void *) ddb_in32(DDB_INTCTRL));
271 printk(KERN_DEBUG
272 "INTSTAT0 = %p:%p\n",
273 (void *) ddb_in32(DDB_INTSTAT0 + 4),
274 (void *) ddb_in32(DDB_INTSTAT0));
275 printk(KERN_DEBUG
276 "INTSTAT1 = %p:%p\n",
277 (void *) ddb_in32(DDB_INTSTAT1 + 4),
278 (void *) ddb_in32(DDB_INTSTAT1));
279 printk(KERN_DEBUG
280 "INTCLR = %p:%p\n", (void *) ddb_in32(DDB_INTCLR + 4),
281 (void *) ddb_in32(DDB_INTCLR));
282 printk(KERN_DEBUG
283 "INTPPES = %p:%p\n", (void *) ddb_in32(DDB_INTPPES + 4),
284 (void *) ddb_in32(DDB_INTPPES));
285}
286
287#endif
diff --git a/arch/mips/ddb5xxx/ddb5074/setup.c b/arch/mips/ddb5xxx/ddb5074/setup.c
new file mode 100644
index 000000000000..a73a5978d550
--- /dev/null
+++ b/arch/mips/ddb5xxx/ddb5074/setup.c
@@ -0,0 +1,235 @@
1/*
2 * arch/mips/ddb5074/setup.c -- NEC DDB Vrc-5074 setup routines
3 *
4 * Copyright (C) 2000 Geert Uytterhoeven <geert@sonycom.com>
5 * Sony Software Development Center Europe (SDCE), Brussels
6 */
7#include <linux/init.h>
8#include <linux/kbd_ll.h>
9#include <linux/kernel.h>
10#include <linux/kdev_t.h>
11#include <linux/types.h>
12#include <linux/sched.h>
13#include <linux/pci.h>
14#include <linux/ide.h>
15#include <linux/ioport.h>
16#include <linux/irq.h>
17
18#include <asm/addrspace.h>
19#include <asm/bcache.h>
20#include <asm/irq.h>
21#include <asm/reboot.h>
22#include <asm/gdb-stub.h>
23#include <asm/time.h>
24#include <asm/nile4.h>
25#include <asm/ddb5xxx/ddb5074.h>
26#include <asm/ddb5xxx/ddb5xxx.h>
27
28static void (*back_to_prom) (void) = (void (*)(void)) 0xbfc00000;
29
30static void ddb_machine_restart(char *command)
31{
32 u32 t;
33
34 /* PCI cold reset */
35 t = nile4_in32(NILE4_PCICTRL + 4);
36 t |= 0x40000000;
37 nile4_out32(NILE4_PCICTRL + 4, t);
38 /* CPU cold reset */
39 t = nile4_in32(NILE4_CPUSTAT);
40 t |= 1;
41 nile4_out32(NILE4_CPUSTAT, t);
42 /* Call the PROM */
43 back_to_prom();
44}
45
46static void ddb_machine_halt(void)
47{
48 printk("DDB Vrc-5074 halted.\n");
49 do {
50 } while (1);
51}
52
53static void ddb_machine_power_off(void)
54{
55 printk("DDB Vrc-5074 halted. Please turn off the power.\n");
56 do {
57 } while (1);
58}
59
60extern void rtc_ds1386_init(unsigned long base);
61
62extern void (*board_timer_setup) (struct irqaction * irq);
63
64static void __init ddb_timer_init(struct irqaction *irq)
65{
66 /* set the clock to 1 Hz */
67 nile4_out32(NILE4_T2CTRL, 1000000);
68 /* enable the General-Purpose Timer */
69 nile4_out32(NILE4_T2CTRL + 4, 0x00000001);
70 /* reset timer */
71 nile4_out32(NILE4_T2CNTR, 0);
72 /* enable interrupt */
73 setup_irq(nile4_to_irq(NILE4_INT_GPT), irq);
74 nile4_enable_irq(nile4_to_irq(NILE4_INT_GPT));
75 change_c0_status(ST0_IM,
76 IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4);
77
78}
79
80static void __init ddb_time_init(void)
81{
82 /* we have ds1396 RTC chip */
83 rtc_ds1386_init(KSEG1ADDR(DDB_PCI_MEM_BASE));
84}
85
86
87
88static void __init ddb5074_setup(void)
89{
90 set_io_port_base(NILE4_PCI_IO_BASE);
91 isa_slot_offset = NILE4_PCI_MEM_BASE;
92 board_timer_setup = ddb_timer_init;
93 board_time_init = ddb_time_init;
94
95
96 _machine_restart = ddb_machine_restart;
97 _machine_halt = ddb_machine_halt;
98 _machine_power_off = ddb_machine_power_off;
99
100 ddb_out32(DDB_BAR0, 0);
101
102 ddb_set_pmr(DDB_PCIINIT0, DDB_PCICMD_IO, 0, 0x10);
103 ddb_set_pmr(DDB_PCIINIT1, DDB_PCICMD_MEM, DDB_PCI_MEM_BASE , 0x10);
104
105 /* Reboot on panic */
106 panic_timeout = 180;
107}
108
109early_initcall(ddb5074_setup);
110
111#define USE_NILE4_SERIAL 0
112
113#if USE_NILE4_SERIAL
114#define ns16550_in(reg) nile4_in8((reg)*8)
115#define ns16550_out(reg, val) nile4_out8((reg)*8, (val))
116#else
117#define NS16550_BASE (NILE4_PCI_IO_BASE+0x03f8)
118static inline u8 ns16550_in(u32 reg)
119{
120 return *(volatile u8 *) (NS16550_BASE + reg);
121}
122
123static inline void ns16550_out(u32 reg, u8 val)
124{
125 *(volatile u8 *) (NS16550_BASE + reg) = val;
126}
127#endif
128
129#define NS16550_RBR 0
130#define NS16550_THR 0
131#define NS16550_DLL 0
132#define NS16550_IER 1
133#define NS16550_DLM 1
134#define NS16550_FCR 2
135#define NS16550_IIR 2
136#define NS16550_LCR 3
137#define NS16550_MCR 4
138#define NS16550_LSR 5
139#define NS16550_MSR 6
140#define NS16550_SCR 7
141
142#define NS16550_LSR_DR 0x01 /* Data ready */
143#define NS16550_LSR_OE 0x02 /* Overrun */
144#define NS16550_LSR_PE 0x04 /* Parity error */
145#define NS16550_LSR_FE 0x08 /* Framing error */
146#define NS16550_LSR_BI 0x10 /* Break */
147#define NS16550_LSR_THRE 0x20 /* Xmit holding register empty */
148#define NS16550_LSR_TEMT 0x40 /* Xmitter empty */
149#define NS16550_LSR_ERR 0x80 /* Error */
150
151
152void _serinit(void)
153{
154#if USE_NILE4_SERIAL
155 ns16550_out(NS16550_LCR, 0x80);
156 ns16550_out(NS16550_DLM, 0x00);
157 ns16550_out(NS16550_DLL, 0x36); /* 9600 baud */
158 ns16550_out(NS16550_LCR, 0x00);
159 ns16550_out(NS16550_LCR, 0x03);
160 ns16550_out(NS16550_FCR, 0x47);
161#else
162 /* done by PMON */
163#endif
164}
165
166void _putc(char c)
167{
168 while (!(ns16550_in(NS16550_LSR) & NS16550_LSR_THRE));
169 ns16550_out(NS16550_THR, c);
170 if (c == '\n') {
171 while (!(ns16550_in(NS16550_LSR) & NS16550_LSR_THRE));
172 ns16550_out(NS16550_THR, '\r');
173 }
174}
175
176void _puts(const char *s)
177{
178 char c;
179 while ((c = *s++))
180 _putc(c);
181}
182
183char _getc(void)
184{
185 while (!(ns16550_in(NS16550_LSR) & NS16550_LSR_DR));
186 return ns16550_in(NS16550_RBR);
187}
188
189int _testc(void)
190{
191 return (ns16550_in(NS16550_LSR) & NS16550_LSR_DR) != 0;
192}
193
194
195/*
196 * Hexadecimal 7-segment LED
197 */
198void ddb5074_led_hex(int hex)
199{
200 outb(hex, 0x80);
201}
202
203
204/*
205 * LEDs D2 and D3, connected to the GPIO pins of the PMU in the ALi M1543
206 */
207struct pci_dev *pci_pmu = NULL;
208
209void ddb5074_led_d2(int on)
210{
211 u8 t;
212
213 if (pci_pmu) {
214 pci_read_config_byte(pci_pmu, 0x7e, &t);
215 if (on)
216 t &= 0x7f;
217 else
218 t |= 0x80;
219 pci_write_config_byte(pci_pmu, 0x7e, t);
220 }
221}
222
223void ddb5074_led_d3(int on)
224{
225 u8 t;
226
227 if (pci_pmu) {
228 pci_read_config_byte(pci_pmu, 0x7e, &t);
229 if (on)
230 t &= 0xbf;
231 else
232 t |= 0x40;
233 pci_write_config_byte(pci_pmu, 0x7e, t);
234 }
235}
diff --git a/arch/mips/ddb5xxx/ddb5476/Makefile b/arch/mips/ddb5xxx/ddb5476/Makefile
new file mode 100644
index 000000000000..61eec363cb02
--- /dev/null
+++ b/arch/mips/ddb5xxx/ddb5476/Makefile
@@ -0,0 +1,9 @@
1#
2# Makefile for the NEC DDB Vrc-5476 specific kernel interface routines
3# under Linux.
4#
5
6obj-y += setup.o irq.o int-handler.o nile4_pic.o vrc5476_irq.o
7obj-$(CONFIG_KGDB) += dbg_io.o
8
9EXTRA_AFLAGS := $(CFLAGS)
diff --git a/arch/mips/ddb5xxx/ddb5476/dbg_io.c b/arch/mips/ddb5xxx/ddb5476/dbg_io.c
new file mode 100644
index 000000000000..85e9e5013679
--- /dev/null
+++ b/arch/mips/ddb5xxx/ddb5476/dbg_io.c
@@ -0,0 +1,136 @@
1/*
2 * kgdb io functions for DDB5476. We use the second serial port.
3 *
4 * Copyright (C) 2001 MontaVista Software Inc.
5 * Author: jsun@mvista.com or jsun@junsun.net
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version.
11 *
12 */
13
14/* ======================= CONFIG ======================== */
15
16/* [jsun] we use the second serial port for kdb */
17#define BASE 0xa60002f8
18#define MAX_BAUD 115200
19
20/* distance in bytes between two serial registers */
21#define REG_OFFSET 1
22
23/*
24 * 0 - kgdb does serial init
25 * 1 - kgdb skip serial init
26 */
27static int remoteDebugInitialized = 0;
28
29/*
30 * the default baud rate *if* kgdb does serial init
31 */
32#define BAUD_DEFAULT UART16550_BAUD_38400
33
34/* ======================= END OF CONFIG ======================== */
35
36typedef unsigned char uint8;
37typedef unsigned int uint32;
38
39#define UART16550_BAUD_2400 2400
40#define UART16550_BAUD_4800 4800
41#define UART16550_BAUD_9600 9600
42#define UART16550_BAUD_19200 19200
43#define UART16550_BAUD_38400 38400
44#define UART16550_BAUD_57600 57600
45#define UART16550_BAUD_115200 115200
46
47#define UART16550_PARITY_NONE 0
48#define UART16550_PARITY_ODD 0x08
49#define UART16550_PARITY_EVEN 0x18
50#define UART16550_PARITY_MARK 0x28
51#define UART16550_PARITY_SPACE 0x38
52
53#define UART16550_DATA_5BIT 0x0
54#define UART16550_DATA_6BIT 0x1
55#define UART16550_DATA_7BIT 0x2
56#define UART16550_DATA_8BIT 0x3
57
58#define UART16550_STOP_1BIT 0x0
59#define UART16550_STOP_2BIT 0x4
60
61/* register offset */
62#define OFS_RCV_BUFFER 0
63#define OFS_TRANS_HOLD 0
64#define OFS_SEND_BUFFER 0
65#define OFS_INTR_ENABLE (1*REG_OFFSET)
66#define OFS_INTR_ID (2*REG_OFFSET)
67#define OFS_DATA_FORMAT (3*REG_OFFSET)
68#define OFS_LINE_CONTROL (3*REG_OFFSET)
69#define OFS_MODEM_CONTROL (4*REG_OFFSET)
70#define OFS_RS232_OUTPUT (4*REG_OFFSET)
71#define OFS_LINE_STATUS (5*REG_OFFSET)
72#define OFS_MODEM_STATUS (6*REG_OFFSET)
73#define OFS_RS232_INPUT (6*REG_OFFSET)
74#define OFS_SCRATCH_PAD (7*REG_OFFSET)
75
76#define OFS_DIVISOR_LSB (0*REG_OFFSET)
77#define OFS_DIVISOR_MSB (1*REG_OFFSET)
78
79
80/* memory-mapped read/write of the port */
81#define UART16550_READ(y) (*((volatile uint8*)(BASE + y)))
82#define UART16550_WRITE(y, z) ((*((volatile uint8*)(BASE + y))) = z)
83
84void debugInit(uint32 baud, uint8 data, uint8 parity, uint8 stop)
85{
86 /* disable interrupts */
87 UART16550_WRITE(OFS_INTR_ENABLE, 0);
88
89 /* set up buad rate */
90 {
91 uint32 divisor;
92
93 /* set DIAB bit */
94 UART16550_WRITE(OFS_LINE_CONTROL, 0x80);
95
96 /* set divisor */
97 divisor = MAX_BAUD / baud;
98 UART16550_WRITE(OFS_DIVISOR_LSB, divisor & 0xff);
99 UART16550_WRITE(OFS_DIVISOR_MSB, (divisor & 0xff00) >> 8);
100
101 /* clear DIAB bit */
102 UART16550_WRITE(OFS_LINE_CONTROL, 0x0);
103 }
104
105 /* set data format */
106 UART16550_WRITE(OFS_DATA_FORMAT, data | parity | stop);
107}
108
109
110uint8 getDebugChar(void)
111{
112 if (!remoteDebugInitialized) {
113 remoteDebugInitialized = 1;
114 debugInit(BAUD_DEFAULT,
115 UART16550_DATA_8BIT,
116 UART16550_PARITY_NONE, UART16550_STOP_1BIT);
117 }
118
119 while ((UART16550_READ(OFS_LINE_STATUS) & 0x1) == 0);
120 return UART16550_READ(OFS_RCV_BUFFER);
121}
122
123
124int putDebugChar(uint8 byte)
125{
126 if (!remoteDebugInitialized) {
127 remoteDebugInitialized = 1;
128 debugInit(BAUD_DEFAULT,
129 UART16550_DATA_8BIT,
130 UART16550_PARITY_NONE, UART16550_STOP_1BIT);
131 }
132
133 while ((UART16550_READ(OFS_LINE_STATUS) & 0x20) == 0);
134 UART16550_WRITE(OFS_SEND_BUFFER, byte);
135 return 1;
136}
diff --git a/arch/mips/ddb5xxx/ddb5476/int-handler.S b/arch/mips/ddb5xxx/ddb5476/int-handler.S
new file mode 100644
index 000000000000..12c292e189ba
--- /dev/null
+++ b/arch/mips/ddb5xxx/ddb5476/int-handler.S
@@ -0,0 +1,112 @@
1/*
2 * Copyright 2001 MontaVista Software Inc.
3 * Author: jsun@mvista.com or jsun@junsun.net
4 *
5 * First-level interrupt dispatcher for ddb5476
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version.
11 */
12#include <asm/asm.h>
13#include <asm/mipsregs.h>
14#include <asm/addrspace.h>
15#include <asm/regdef.h>
16#include <asm/stackframe.h>
17
18#include <asm/ddb5xxx/ddb5476.h>
19
20/*
21 * first level interrupt dispatcher for ocelot board -
22 * We check for the timer first, then check PCI ints A and D.
23 * Then check for serial IRQ and fall through.
24 */
25 .align 5
26 NESTED(ddb5476_handle_int, PT_SIZE, sp)
27 SAVE_ALL
28 CLI
29 .set at
30 .set noreorder
31 mfc0 t0, CP0_CAUSE
32 mfc0 t2, CP0_STATUS
33
34 and t0, t2
35
36 andi t1, t0, STATUSF_IP7 /* cpu timer */
37 bnez t1, ll_cpu_ip7
38 andi t1, t0, STATUSF_IP2 /* vrc5476 & i8259 */
39 bnez t1, ll_cpu_ip2
40 andi t1, t0, STATUSF_IP3
41 bnez t1, ll_cpu_ip3
42 andi t1, t0, STATUSF_IP4
43 bnez t1, ll_cpu_ip4
44 andi t1, t0, STATUSF_IP5
45 bnez t1, ll_cpu_ip5
46 andi t1, t0, STATUSF_IP6
47 bnez t1, ll_cpu_ip6
48 andi t1, t0, STATUSF_IP0 /* software int 0 */
49 bnez t1, ll_cpu_ip0
50 andi t1, t0, STATUSF_IP1 /* software int 1 */
51 bnez t1, ll_cpu_ip1
52 nop
53
54 .set reorder
55
56 /* wrong alarm or masked ... */
57 // j spurious_interrupt
58 move a0, sp
59 jal vrc5476_irq_dispatch
60 j ret_from_irq
61 nop
62
63 .align 5
64
65ll_cpu_ip0:
66 li a0, CPU_IRQ_BASE + 0
67 move a1, sp
68 jal do_IRQ
69 j ret_from_irq
70
71ll_cpu_ip1:
72 li a0, CPU_IRQ_BASE + 1
73 move a1, sp
74 jal do_IRQ
75 j ret_from_irq
76
77ll_cpu_ip2: /* jump to second-level dispatching */
78 move a0, sp
79 jal vrc5476_irq_dispatch
80 j ret_from_irq
81
82ll_cpu_ip3:
83 li a0, CPU_IRQ_BASE + 3
84 move a1, sp
85 jal do_IRQ
86 j ret_from_irq
87
88ll_cpu_ip4:
89 li a0, CPU_IRQ_BASE + 4
90 move a1, sp
91 jal do_IRQ
92 j ret_from_irq
93
94ll_cpu_ip5:
95 li a0, CPU_IRQ_BASE + 5
96 move a1, sp
97 jal do_IRQ
98 j ret_from_irq
99
100ll_cpu_ip6:
101 li a0, CPU_IRQ_BASE + 6
102 move a1, sp
103 jal do_IRQ
104 j ret_from_irq
105
106ll_cpu_ip7:
107 li a0, CPU_IRQ_BASE + 7
108 move a1, sp
109 jal do_IRQ
110 j ret_from_irq
111
112 END(ddb5476_handle_int)
diff --git a/arch/mips/ddb5xxx/ddb5476/irq.c b/arch/mips/ddb5xxx/ddb5476/irq.c
new file mode 100644
index 000000000000..5388b5868c4a
--- /dev/null
+++ b/arch/mips/ddb5xxx/ddb5476/irq.c
@@ -0,0 +1,143 @@
1/*
2 * arch/mips/ddb5476/irq.c -- NEC DDB Vrc-5476 interrupt routines
3 *
4 * Copyright (C) 2000 Geert Uytterhoeven <geert@sonycom.com>
5 * Sony Software Development Center Europe (SDCE), Brussels
6 *
7 * Re-write the whole thing to use new irq.c file.
8 * Copyright (C) 2001 MontaVista Software Inc.
9 * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
10 *
11 */
12#include <linux/init.h>
13#include <linux/sched.h>
14#include <linux/types.h>
15#include <linux/interrupt.h>
16
17#include <asm/i8259.h>
18#include <asm/io.h>
19#include <asm/ptrace.h>
20
21#include <asm/ddb5xxx/ddb5xxx.h>
22
23#define M1543_PNP_CONFIG 0x03f0 /* PnP Config Port */
24#define M1543_PNP_INDEX 0x03f0 /* PnP Index Port */
25#define M1543_PNP_DATA 0x03f1 /* PnP Data Port */
26
27#define M1543_PNP_ALT_CONFIG 0x0370 /* Alternative PnP Config Port */
28#define M1543_PNP_ALT_INDEX 0x0370 /* Alternative PnP Index Port */
29#define M1543_PNP_ALT_DATA 0x0371 /* Alternative PnP Data Port */
30
31#define M1543_INT1_MASTER_CTRL 0x0020 /* INT_1 (master) Control Register */
32#define M1543_INT1_MASTER_MASK 0x0021 /* INT_1 (master) Mask Register */
33
34#define M1543_INT1_SLAVE_CTRL 0x00a0 /* INT_1 (slave) Control Register */
35#define M1543_INT1_SLAVE_MASK 0x00a1 /* INT_1 (slave) Mask Register */
36
37#define M1543_INT1_MASTER_ELCR 0x04d0 /* INT_1 (master) Edge/Level Control */
38#define M1543_INT1_SLAVE_ELCR 0x04d1 /* INT_1 (slave) Edge/Level Control */
39
40static void m1543_irq_setup(void)
41{
42 /*
43 * The ALI M1543 has 13 interrupt inputs, IRQ1..IRQ13. Not all
44 * the possible IO sources in the M1543 are in use by us. We will
45 * use the following mapping:
46 *
47 * IRQ1 - keyboard (default set by M1543)
48 * IRQ3 - reserved for UART B (default set by M1543) (note that
49 * the schematics for the DDB Vrc-5476 board seem to
50 * indicate that IRQ3 is connected to the DS1386
51 * watchdog timer interrupt output so we might have
52 * a conflict)
53 * IRQ4 - reserved for UART A (default set by M1543)
54 * IRQ5 - parallel (default set by M1543)
55 * IRQ8 - DS1386 time of day (RTC) interrupt
56 * IRQ9 - USB (hardwired in ddb_setup)
57 * IRQ10 - PMU (hardwired in ddb_setup)
58 * IRQ12 - mouse
59 * IRQ14,15 - IDE controller (need to be confirmed, jsun)
60 */
61
62 /*
63 * Assing mouse interrupt to IRQ12
64 */
65
66 /* Enter configuration mode */
67 outb(0x51, M1543_PNP_CONFIG);
68 outb(0x23, M1543_PNP_CONFIG);
69
70 /* Select logical device 7 (Keyboard) */
71 outb(0x07, M1543_PNP_INDEX);
72 outb(0x07, M1543_PNP_DATA);
73
74 /* Select IRQ12 */
75 outb(0x72, M1543_PNP_INDEX);
76 outb(0x0c, M1543_PNP_DATA);
77
78 /* Leave configration mode */
79 outb(0xbb, M1543_PNP_CONFIG);
80}
81
82static void nile4_irq_setup(void)
83{
84 int i;
85
86 /* Map all interrupts to CPU int #0 (IP2) */
87 nile4_map_irq_all(0);
88
89 /* PCI INTA#-E# must be level triggered */
90 nile4_set_pci_irq_level_or_edge(0, 1);
91 nile4_set_pci_irq_level_or_edge(1, 1);
92 nile4_set_pci_irq_level_or_edge(2, 1);
93 nile4_set_pci_irq_level_or_edge(3, 1);
94
95 /* PCI INTA#, B#, D# must be active low, INTC# must be active high */
96 nile4_set_pci_irq_polarity(0, 0);
97 nile4_set_pci_irq_polarity(1, 0);
98 nile4_set_pci_irq_polarity(2, 1);
99 nile4_set_pci_irq_polarity(3, 0);
100
101 for (i = 0; i < 16; i++)
102 nile4_clear_irq(i);
103
104 /* Enable CPU int #0 */
105 nile4_enable_irq_output(0);
106
107 /* memory resource acquire in ddb_setup */
108}
109
110static struct irqaction irq_cascade = { no_action, 0, CPU_MASK_NONE, "cascade", NULL, NULL };
111static struct irqaction irq_error = { no_action, 0, CPU_MASK_NONE, "error", NULL, NULL };
112
113extern asmlinkage void ddb5476_handle_int(void);
114extern int setup_irq(unsigned int irq, struct irqaction *irqaction);
115extern void mips_cpu_irq_init(u32 irq_base);
116extern void vrc5476_irq_init(u32 irq_base);
117
118void __init arch_init_irq(void)
119{
120 /* hardware initialization */
121 nile4_irq_setup();
122 m1543_irq_setup();
123
124 /* controller setup */
125 init_i8259_irqs();
126 vrc5476_irq_init(VRC5476_IRQ_BASE);
127 mips_cpu_irq_init(CPU_IRQ_BASE);
128
129 /* setup cascade interrupts */
130 setup_irq(VRC5476_IRQ_BASE + VRC5476_I8259_CASCADE, &irq_cascade);
131 setup_irq(CPU_IRQ_BASE + CPU_VRC5476_CASCADE, &irq_cascade);
132
133 /* setup error interrupts for debugging */
134 setup_irq(VRC5476_IRQ_BASE + VRC5476_IRQ_CPCE, &irq_error);
135 setup_irq(VRC5476_IRQ_BASE + VRC5476_IRQ_CNTD, &irq_error);
136 setup_irq(VRC5476_IRQ_BASE + VRC5476_IRQ_MCE, &irq_error);
137 setup_irq(VRC5476_IRQ_BASE + VRC5476_IRQ_LBRT, &irq_error);
138 setup_irq(VRC5476_IRQ_BASE + VRC5476_IRQ_PCIS, &irq_error);
139 setup_irq(VRC5476_IRQ_BASE + VRC5476_IRQ_PCI, &irq_error);
140
141 /* setup the grandpa intr vector */
142 set_except_vector(0, ddb5476_handle_int);
143}
diff --git a/arch/mips/ddb5xxx/ddb5476/nile4_pic.c b/arch/mips/ddb5xxx/ddb5476/nile4_pic.c
new file mode 100644
index 000000000000..e930cee7944f
--- /dev/null
+++ b/arch/mips/ddb5xxx/ddb5476/nile4_pic.c
@@ -0,0 +1,190 @@
1/*
2 * arch/mips/ddb5476/nile4.c --
3 * low-level PIC code for NEC Vrc-5476 (Nile 4)
4 *
5 * Copyright (C) 2000 Geert Uytterhoeven <geert@sonycom.com>
6 * Sony Software Development Center Europe (SDCE), Brussels
7 *
8 * Copyright 2001 MontaVista Software Inc.
9 * Author: jsun@mvista.com or jsun@junsun.net
10 *
11 */
12#include <linux/config.h>
13#include <linux/kernel.h>
14#include <linux/types.h>
15
16#include <asm/addrspace.h>
17
18#include <asm/ddb5xxx/ddb5xxx.h>
19
20
21/*
22 * Interrupt Programming
23 */
24void nile4_map_irq(int nile4_irq, int cpu_irq)
25{
26 u32 offset, t;
27
28 offset = DDB_INTCTRL;
29 if (nile4_irq >= 8) {
30 offset += 4;
31 nile4_irq -= 8;
32 }
33 t = ddb_in32(offset);
34 t &= ~(7 << (nile4_irq * 4));
35 t |= cpu_irq << (nile4_irq * 4);
36 ddb_out32(offset, t);
37}
38
39void nile4_map_irq_all(int cpu_irq)
40{
41 u32 all, t;
42
43 all = cpu_irq;
44 all |= all << 4;
45 all |= all << 8;
46 all |= all << 16;
47 t = ddb_in32(DDB_INTCTRL);
48 t &= 0x88888888;
49 t |= all;
50 ddb_out32(DDB_INTCTRL, t);
51 t = ddb_in32(DDB_INTCTRL + 4);
52 t &= 0x88888888;
53 t |= all;
54 ddb_out32(DDB_INTCTRL + 4, t);
55}
56
57void nile4_enable_irq(int nile4_irq)
58{
59 u32 offset, t;
60
61 offset = DDB_INTCTRL;
62 if (nile4_irq >= 8) {
63 offset += 4;
64 nile4_irq -= 8;
65 }
66 t = ddb_in32(offset);
67 t |= 8 << (nile4_irq * 4);
68 ddb_out32(offset, t);
69}
70
71void nile4_disable_irq(int nile4_irq)
72{
73 u32 offset, t;
74
75 offset = DDB_INTCTRL;
76 if (nile4_irq >= 8) {
77 offset += 4;
78 nile4_irq -= 8;
79 }
80 t = ddb_in32(offset);
81 t &= ~(8 << (nile4_irq * 4));
82 ddb_out32(offset, t);
83}
84
85void nile4_disable_irq_all(void)
86{
87 ddb_out32(DDB_INTCTRL, 0);
88 ddb_out32(DDB_INTCTRL + 4, 0);
89}
90
91u16 nile4_get_irq_stat(int cpu_irq)
92{
93 return ddb_in16(DDB_INTSTAT0 + cpu_irq * 2);
94}
95
96void nile4_enable_irq_output(int cpu_irq)
97{
98 u32 t;
99
100 t = ddb_in32(DDB_INTSTAT1 + 4);
101 t |= 1 << (16 + cpu_irq);
102 ddb_out32(DDB_INTSTAT1, t);
103}
104
105void nile4_disable_irq_output(int cpu_irq)
106{
107 u32 t;
108
109 t = ddb_in32(DDB_INTSTAT1 + 4);
110 t &= ~(1 << (16 + cpu_irq));
111 ddb_out32(DDB_INTSTAT1, t);
112}
113
114void nile4_set_pci_irq_polarity(int pci_irq, int high)
115{
116 u32 t;
117
118 t = ddb_in32(DDB_INTPPES);
119 if (high)
120 t &= ~(1 << (pci_irq * 2));
121 else
122 t |= 1 << (pci_irq * 2);
123 ddb_out32(DDB_INTPPES, t);
124}
125
126void nile4_set_pci_irq_level_or_edge(int pci_irq, int level)
127{
128 u32 t;
129
130 t = ddb_in32(DDB_INTPPES);
131 if (level)
132 t |= 2 << (pci_irq * 2);
133 else
134 t &= ~(2 << (pci_irq * 2));
135 ddb_out32(DDB_INTPPES, t);
136}
137
138void nile4_clear_irq(int nile4_irq)
139{
140 ddb_out32(DDB_INTCLR, 1 << nile4_irq);
141}
142
143void nile4_clear_irq_mask(u32 mask)
144{
145 ddb_out32(DDB_INTCLR, mask);
146}
147
148u8 nile4_i8259_iack(void)
149{
150 u8 irq;
151 u32 reg;
152
153 /* Set window 0 for interrupt acknowledge */
154 reg = ddb_in32(DDB_PCIINIT0);
155
156 ddb_set_pmr(DDB_PCIINIT0, DDB_PCICMD_IACK, 0, DDB_PCI_ACCESS_32);
157 irq = *(volatile u8 *) KSEG1ADDR(DDB_PCI_IACK_BASE);
158 /* restore window 0 for PCI I/O space */
159 // ddb_set_pmr(DDB_PCIINIT0, DDB_PCICMD_IO, 0, DDB_PCI_ACCESS_32);
160 ddb_out32(DDB_PCIINIT0, reg);
161
162 /* i8269.c set the base vector to be 0x0 */
163 return irq + I8259_IRQ_BASE;
164}
165
166#if defined(CONFIG_RUNTIME_DEBUG)
167void nile4_dump_irq_status(void)
168{
169 printk(KERN_DEBUG "
170 CPUSTAT = %p:%p\n", (void *) ddb_in32(DDB_CPUSTAT + 4),
171 (void *) ddb_in32(DDB_CPUSTAT));
172 printk(KERN_DEBUG "
173 INTCTRL = %p:%p\n", (void *) ddb_in32(DDB_INTCTRL + 4),
174 (void *) ddb_in32(DDB_INTCTRL));
175 printk(KERN_DEBUG
176 "INTSTAT0 = %p:%p\n",
177 (void *) ddb_in32(DDB_INTSTAT0 + 4),
178 (void *) ddb_in32(DDB_INTSTAT0));
179 printk(KERN_DEBUG
180 "INTSTAT1 = %p:%p\n",
181 (void *) ddb_in32(DDB_INTSTAT1 + 4),
182 (void *) ddb_in32(DDB_INTSTAT1));
183 printk(KERN_DEBUG
184 "INTCLR = %p:%p\n", (void *) ddb_in32(DDB_INTCLR + 4),
185 (void *) ddb_in32(DDB_INTCLR));
186 printk(KERN_DEBUG
187 "INTPPES = %p:%p\n", (void *) ddb_in32(DDB_INTPPES + 4),
188 (void *) ddb_in32(DDB_INTPPES));
189}
190#endif
diff --git a/arch/mips/ddb5xxx/ddb5476/setup.c b/arch/mips/ddb5xxx/ddb5476/setup.c
new file mode 100644
index 000000000000..71531f8146ea
--- /dev/null
+++ b/arch/mips/ddb5xxx/ddb5476/setup.c
@@ -0,0 +1,297 @@
1/*
2 * arch/mips/ddb5476/setup.c -- NEC DDB Vrc-5476 setup routines
3 *
4 * Copyright (C) 2000 Geert Uytterhoeven <geert@sonycom.com>
5 * Sony Software Development Center Europe (SDCE), Brussels
6 */
7#include <linux/init.h>
8#include <linux/kbd_ll.h>
9#include <linux/kernel.h>
10#include <linux/kdev_t.h>
11#include <linux/types.h>
12#include <linux/sched.h>
13#include <linux/pci.h>
14
15#include <asm/addrspace.h>
16#include <asm/bcache.h>
17#include <asm/irq.h>
18#include <asm/reboot.h>
19#include <asm/gdb-stub.h>
20#include <asm/time.h>
21#include <asm/debug.h>
22#include <asm/traps.h>
23
24#include <asm/ddb5xxx/ddb5xxx.h>
25
26// #define USE_CPU_COUNTER_TIMER /* whether we use cpu counter */
27
28#ifdef USE_CPU_COUNTER_TIMER
29
30#define CPU_COUNTER_FREQUENCY 83000000
31#else
32/* otherwise we use general purpose timer */
33#define TIMER_FREQUENCY 83000000
34#define TIMER_BASE DDB_T2CTRL
35#define TIMER_IRQ (VRC5476_IRQ_BASE + VRC5476_IRQ_GPT)
36#endif
37
38static void (*back_to_prom) (void) = (void (*)(void)) 0xbfc00000;
39
40static void ddb_machine_restart(char *command)
41{
42 u32 t;
43
44 /* PCI cold reset */
45 t = ddb_in32(DDB_PCICTRL + 4);
46 t |= 0x40000000;
47 ddb_out32(DDB_PCICTRL + 4, t);
48 /* CPU cold reset */
49 t = ddb_in32(DDB_CPUSTAT);
50 t |= 1;
51 ddb_out32(DDB_CPUSTAT, t);
52 /* Call the PROM */
53 back_to_prom();
54}
55
56static void ddb_machine_halt(void)
57{
58 printk(KERN_NOTICE "DDB Vrc-5476 halted.\n");
59 while (1);
60}
61
62static void ddb_machine_power_off(void)
63{
64 printk(KERN_NOTICE "DDB Vrc-5476 halted. Please turn off the power.\n");
65 while (1);
66}
67
68extern void rtc_ds1386_init(unsigned long base);
69
70static void __init ddb_time_init(void)
71{
72#if defined(USE_CPU_COUNTER_TIMER)
73 mips_hpt_frequency = CPU_COUNTER_FREQUENCY;
74#endif
75
76 /* we have ds1396 RTC chip */
77 rtc_ds1386_init(KSEG1ADDR(DDB_PCI_MEM_BASE));
78}
79
80
81extern int setup_irq(unsigned int irq, struct irqaction *irqaction);
82static void __init ddb_timer_setup(struct irqaction *irq)
83{
84#if defined(USE_CPU_COUNTER_TIMER)
85
86 unsigned int count;
87
88 /* we are using the cpu counter for timer interrupts */
89 setup_irq(CPU_IRQ_BASE + 7, irq);
90
91 /* to generate the first timer interrupt */
92 count = read_c0_count();
93 write_c0_compare(count + 1000);
94
95#else
96
97 ddb_out32(TIMER_BASE, TIMER_FREQUENCY/HZ);
98 ddb_out32(TIMER_BASE+4, 0x1); /* enable timer */
99 setup_irq(TIMER_IRQ, irq);
100#endif
101}
102
103static struct {
104 struct resource dma1;
105 struct resource timer;
106 struct resource rtc;
107 struct resource dma_page_reg;
108 struct resource dma2;
109} ddb5476_ioport = {
110 {
111 "dma1", 0x00, 0x1f, IORESOURCE_BUSY}, {
112 "timer", 0x40, 0x5f, IORESOURCE_BUSY}, {
113 "rtc", 0x70, 0x7f, IORESOURCE_BUSY}, {
114 "dma page reg", 0x80, 0x8f, IORESOURCE_BUSY}, {
115 "dma2", 0xc0, 0xdf, IORESOURCE_BUSY}
116};
117
118static struct {
119 struct resource nile4;
120} ddb5476_iomem = {
121 { "Nile 4", DDB_BASE, DDB_BASE + DDB_SIZE - 1, IORESOURCE_BUSY}
122};
123
124
125static void ddb5476_board_init(void);
126
127static void __init ddb5476_setup(void)
128{
129 set_io_port_base(KSEG1ADDR(DDB_PCI_IO_BASE));
130
131 board_time_init = ddb_time_init;
132 board_timer_setup = ddb_timer_setup;
133
134 _machine_restart = ddb_machine_restart;
135 _machine_halt = ddb_machine_halt;
136 _machine_power_off = ddb_machine_power_off;
137
138 /* request io port/mem resources */
139 if (request_resource(&ioport_resource, &ddb5476_ioport.dma1) ||
140 request_resource(&ioport_resource, &ddb5476_ioport.timer) ||
141 request_resource(&ioport_resource, &ddb5476_ioport.rtc) ||
142 request_resource(&ioport_resource,
143 &ddb5476_ioport.dma_page_reg)
144 || request_resource(&ioport_resource, &ddb5476_ioport.dma2)
145 || request_resource(&iomem_resource, &ddb5476_iomem.nile4)) {
146 printk
147 ("ddb_setup - requesting oo port resources failed.\n");
148 for (;;);
149 }
150
151 /* Reboot on panic */
152 panic_timeout = 180;
153
154 /* [jsun] we need to set BAR0 so that SDRAM 0 appears at 0x0 in PCI */
155 /* *(long*)0xbfa00218 = 0x8; */
156
157 /* board initialization stuff */
158 ddb5476_board_init();
159}
160
161early_initcall(ddb5476_setup);
162
163/*
164 * We don't trust bios. We essentially does hardware re-initialization
165 * as complete as possible, as far as we know we can safely do.
166 */
167static void ddb5476_board_init(void)
168{
169 /* ----------- setup PDARs ------------ */
170 /* check SDRAM0, whether we are on MEM bus does not matter */
171 db_assert((ddb_in32(DDB_SDRAM0) & 0xffffffef) ==
172 ddb_calc_pdar(DDB_SDRAM_BASE, DDB_SDRAM_SIZE, 32, 0, 1));
173
174 /* SDRAM1 should be turned off. What is this for anyway ? */
175 db_assert( (ddb_in32(DDB_SDRAM1) & 0xf) == 0);
176
177 /* flash 1&2, DDB status, DDB control */
178 ddb_set_pdar(DDB_DCS2, DDB_DCS2_BASE, DDB_DCS2_SIZE, 16, 0, 0);
179 ddb_set_pdar(DDB_DCS3, DDB_DCS3_BASE, DDB_DCS3_SIZE, 16, 0, 0);
180 ddb_set_pdar(DDB_DCS4, DDB_DCS4_BASE, DDB_DCS4_SIZE, 8, 0, 0);
181 ddb_set_pdar(DDB_DCS5, DDB_DCS5_BASE, DDB_DCS5_SIZE, 8, 0, 0);
182
183 /* shut off other pdar so they don't accidentally get into the way */
184 ddb_set_pdar(DDB_DCS6, 0xffffffff, 0, 32, 0, 0);
185 ddb_set_pdar(DDB_DCS7, 0xffffffff, 0, 32, 0, 0);
186 ddb_set_pdar(DDB_DCS8, 0xffffffff, 0, 32, 0, 0);
187
188 /* verify VRC5477 base addr */
189 /* don't care about some details */
190 db_assert((ddb_in32(DDB_INTCS) & 0xffffff0f) ==
191 ddb_calc_pdar(DDB_INTCS_BASE, DDB_INTCS_SIZE, 8, 0, 0));
192
193 /* verify BOOT ROM addr */
194 /* don't care about some details */
195 db_assert((ddb_in32(DDB_BOOTCS) & 0xffffff0f) ==
196 ddb_calc_pdar(DDB_BOOTCS_BASE, DDB_BOOTCS_SIZE, 8, 0, 0));
197
198 /* setup PCI windows - window1 for MEM/config, window0 for IO */
199 ddb_set_pdar(DDB_PCIW0, DDB_PCI_IO_BASE, DDB_PCI_IO_SIZE, 32, 0, 1);
200 ddb_set_pmr(DDB_PCIINIT0, DDB_PCICMD_IO, 0, DDB_PCI_ACCESS_32);
201
202 ddb_set_pdar(DDB_PCIW1, DDB_PCI_MEM_BASE, DDB_PCI_MEM_SIZE, 32, 0, 1);
203 ddb_set_pmr(DDB_PCIINIT1, DDB_PCICMD_MEM, DDB_PCI_MEM_BASE, DDB_PCI_ACCESS_32);
204
205 /* ----------- setup PDARs ------------ */
206 /* this is problematic - it will reset Aladin which cause we loose
207 * serial port, and we don't know how to set up Aladin chip again.
208 */
209 // ddb_pci_reset_bus();
210
211 ddb_out32(DDB_BAR0, 0x00000008);
212
213 ddb_out32(DDB_BARC, 0xffffffff);
214 ddb_out32(DDB_BARB, 0xffffffff);
215 ddb_out32(DDB_BAR1, 0xffffffff);
216 ddb_out32(DDB_BAR2, 0xffffffff);
217 ddb_out32(DDB_BAR3, 0xffffffff);
218 ddb_out32(DDB_BAR4, 0xffffffff);
219 ddb_out32(DDB_BAR5, 0xffffffff);
220 ddb_out32(DDB_BAR6, 0xffffffff);
221 ddb_out32(DDB_BAR7, 0xffffffff);
222 ddb_out32(DDB_BAR8, 0xffffffff);
223
224 /* ----------- switch PCI1 to PCI CONFIG space ------------ */
225 ddb_set_pdar(DDB_PCIW1, DDB_PCI_CONFIG_BASE, DDB_PCI_CONFIG_SIZE, 32, 0, 1);
226 ddb_set_pmr(DDB_PCIINIT1, DDB_PCICMD_CFG, 0x0, DDB_PCI_ACCESS_32);
227
228 /* ----- M1543 PCI setup ------ */
229
230 /* we know M1543 PCI-ISA controller is at addr:18 */
231 /* xxxx1010 makes USB at addr:13 and PMU at addr:14 */
232 *(volatile unsigned char *) 0xa8040072 &= 0xf0;
233 *(volatile unsigned char *) 0xa8040072 |= 0xa;
234
235 /* setup USB interrupt to IRQ 9, (bit 0:3 - 0001)
236 * no IOCHRDY signal, (bit 7 - 1)
237 * M1543C & M7101 VID and Subsys Device ID are read-only (bit 6 - 1)
238 * Make USB Master INTAJ level to edge conversion (bit 4 - 1)
239 */
240 *(unsigned char *) 0xa8040074 = 0xd1;
241
242 /* setup PMU(SCI to IRQ 10 (bit 0:3 - 0011)
243 * SCI routing to IRQ 13 disabled (bit 7 - 1)
244 * SCI interrupt level to edge conversion bypassed (bit 4 - 0)
245 */
246 *(unsigned char *) 0xa8040076 = 0x83;
247
248 /* setup IDE controller
249 * enable IDE controller (bit 6 - 1)
250 * IDE IDSEL to be addr:24 (bit 4:5 - 11)
251 * no IDE ATA Secondary Bus Signal Pad Control (bit 3 - 0)
252 * no IDE ATA Primary Bus Signal Pad Control (bit 2 - 0)
253 * primary IRQ is 14, secondary is 15 (bit 1:0 - 01
254 */
255 // *(unsigned char*)0xa8040058 = 0x71;
256 // *(unsigned char*)0xa8040058 = 0x79;
257 // *(unsigned char*)0xa8040058 = 0x74; // use SIRQ, primary tri-state
258 *(unsigned char *) 0xa8040058 = 0x75; // primary tri-state
259
260#if 0
261 /* this is not necessary if M5229 does not use SIRQ */
262 *(unsigned char *) 0xa8040044 = 0x0d; // primary to IRQ 14
263 *(unsigned char *) 0xa8040075 = 0x0d; // secondary to IRQ 14
264#endif
265
266 /* enable IDE in the M5229 config register 0x50 (bit 0 - 1) */
267 /* M5229 IDSEL is addr:24; see above setting */
268 *(unsigned char *) 0xa9000050 |= 0x1;
269
270 /* enable bus master (bit 2) and IO decoding (bit 0) */
271 *(unsigned char *) 0xa9000004 |= 0x5;
272
273 /* enable native, copied from arch/ppc/k2boot/head.S */
274 /* TODO - need volatile, need to be portable */
275 *(unsigned char *) 0xa9000009 = 0xff;
276
277 /* ----- end of M1543 PCI setup ------ */
278
279 /* ----- reset on-board ether chip ------ */
280 *((volatile u32 *) 0xa8020004) |= 1; /* decode I/O */
281 *((volatile u32 *) 0xa8020010) = 0; /* set BAR address */
282
283 /* send reset command */
284 *((volatile u32 *) 0xa6000000) = 1; /* do a soft reset */
285
286 /* disable ether chip */
287 *((volatile u32 *) 0xa8020004) = 0; /* disable any decoding */
288
289 /* put it into sleep */
290 *((volatile u32 *) 0xa8020040) = 0x80000000;
291
292 /* ----- end of reset on-board ether chip ------ */
293
294 /* ----------- switch PCI1 back to PCI MEM space ------------ */
295 ddb_set_pdar(DDB_PCIW1, DDB_PCI_MEM_BASE, DDB_PCI_MEM_SIZE, 32, 0, 1);
296 ddb_set_pmr(DDB_PCIINIT1, DDB_PCICMD_MEM, DDB_PCI_MEM_BASE, DDB_PCI_ACCESS_32);
297}
diff --git a/arch/mips/ddb5xxx/ddb5476/vrc5476_irq.c b/arch/mips/ddb5xxx/ddb5476/vrc5476_irq.c
new file mode 100644
index 000000000000..a77682be01ac
--- /dev/null
+++ b/arch/mips/ddb5xxx/ddb5476/vrc5476_irq.c
@@ -0,0 +1,112 @@
1/*
2 * The irq controller for vrc5476.
3 *
4 * Copyright (C) 2001 MontaVista Software Inc.
5 * Author: jsun@mvista.com or jsun@junsun.net
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version.
11 *
12 */
13#include <linux/init.h>
14#include <linux/interrupt.h>
15#include <linux/irq.h>
16#include <linux/types.h>
17#include <linux/ptrace.h>
18
19#include <asm/system.h>
20
21#include <asm/ddb5xxx/ddb5xxx.h>
22
23static int irq_base;
24
25static void vrc5476_irq_enable(uint irq)
26{
27 nile4_enable_irq(irq - irq_base);
28}
29
30static void vrc5476_irq_disable(uint irq)
31{
32 nile4_disable_irq(irq - irq_base);
33}
34
35static unsigned int vrc5476_irq_startup(uint irq)
36{
37 nile4_enable_irq(irq - irq_base);
38 return 0;
39}
40
41#define vrc5476_irq_shutdown vrc5476_irq_disable
42
43static void vrc5476_irq_ack(uint irq)
44{
45 nile4_clear_irq(irq - irq_base);
46 nile4_disable_irq(irq - irq_base);
47}
48
49static void vrc5476_irq_end(uint irq)
50{
51 if(!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
52 vrc5476_irq_enable(irq);
53}
54
55static hw_irq_controller vrc5476_irq_controller = {
56 "vrc5476",
57 vrc5476_irq_startup,
58 vrc5476_irq_shutdown,
59 vrc5476_irq_enable,
60 vrc5476_irq_disable,
61 vrc5476_irq_ack,
62 vrc5476_irq_end,
63 NULL /* no affinity stuff for UP */
64};
65
66void __init
67vrc5476_irq_init(u32 base)
68{
69 u32 i;
70
71 irq_base = base;
72 for (i= base; i< base + NUM_VRC5476_IRQ; i++) {
73 irq_desc[i].status = IRQ_DISABLED;
74 irq_desc[i].action = NULL;
75 irq_desc[i].depth = 1;
76 irq_desc[i].handler = &vrc5476_irq_controller;
77 }
78}
79
80
81asmlinkage void
82vrc5476_irq_dispatch(struct pt_regs *regs)
83{
84 extern void spurious_interrupt(void);
85
86 u32 mask;
87 int nile4_irq;
88
89 mask = nile4_get_irq_stat(0);
90
91 /* quick check for possible time interrupt */
92 if (mask & (1 << VRC5476_IRQ_GPT)) {
93 do_IRQ(VRC5476_IRQ_BASE + VRC5476_IRQ_GPT, regs);
94 return;
95 }
96
97 /* check for i8259 interrupts */
98 if (mask & (1 << VRC5476_I8259_CASCADE)) {
99 int i8259_irq = nile4_i8259_iack();
100 do_IRQ(I8259_IRQ_BASE + i8259_irq, regs);
101 return;
102 }
103
104 /* regular nile4 interrupts (we should not really have any */
105 for (nile4_irq = 0; mask; nile4_irq++, mask >>= 1) {
106 if (mask & 1) {
107 do_IRQ(VRC5476_IRQ_BASE + nile4_irq, regs);
108 return;
109 }
110 }
111 spurious_interrupt();
112}
diff --git a/arch/mips/ddb5xxx/ddb5477/Makefile b/arch/mips/ddb5xxx/ddb5477/Makefile
new file mode 100644
index 000000000000..b79b43c9f93b
--- /dev/null
+++ b/arch/mips/ddb5xxx/ddb5477/Makefile
@@ -0,0 +1,10 @@
1#
2# Makefile for NEC DDB-Vrc5477 board
3#
4
5obj-y += int-handler.o irq.o irq_5477.o setup.o lcd44780.o
6
7obj-$(CONFIG_RUNTIME_DEBUG) += debug.o
8obj-$(CONFIG_KGDB) += kgdb_io.o
9
10EXTRA_AFLAGS := $(CFLAGS)
diff --git a/arch/mips/ddb5xxx/ddb5477/debug.c b/arch/mips/ddb5xxx/ddb5477/debug.c
new file mode 100644
index 000000000000..68919d5f8ffd
--- /dev/null
+++ b/arch/mips/ddb5xxx/ddb5477/debug.c
@@ -0,0 +1,160 @@
1/***********************************************************************
2 *
3 * Copyright 2001 MontaVista Software Inc.
4 * Author: jsun@mvista.com or jsun@junsun.net
5 *
6 * arch/mips/ddb5xxx/ddb5477/debug.c
7 * vrc5477 specific debug routines.
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the
11 * Free Software Foundation; either version 2 of the License, or (at your
12 * option) any later version.
13 *
14 ***********************************************************************
15 */
16
17#include <linux/kernel.h>
18
19#include <asm/mipsregs.h>
20#include <asm/ddb5xxx/ddb5xxx.h>
21
22typedef struct {
23 const char *regname;
24 unsigned regaddr;
25} Register;
26
27void jsun_show_regs(char *name, Register *regs)
28{
29 int i;
30
31 printk("\nshow regs: %s\n", name);
32 for(i=0;regs[i].regname!= NULL; i++) {
33 printk("%-16s= %08x\t\t(@%08x)\n",
34 regs[i].regname,
35 *(unsigned *)(regs[i].regaddr),
36 regs[i].regaddr);
37 }
38}
39
40static Register int_regs[] = {
41 {"DDB_INTCTRL0", DDB_BASE + DDB_INTCTRL0},
42 {"DDB_INTCTRL1", DDB_BASE + DDB_INTCTRL1},
43 {"DDB_INTCTRL2", DDB_BASE + DDB_INTCTRL2},
44 {"DDB_INTCTRL3", DDB_BASE + DDB_INTCTRL3},
45 {"DDB_INT0STAT", DDB_BASE + DDB_INT0STAT},
46 {"DDB_INT1STAT", DDB_BASE + DDB_INT1STAT},
47 {"DDB_INT2STAT", DDB_BASE + DDB_INT2STAT},
48 {"DDB_INT3STAT", DDB_BASE + DDB_INT3STAT},
49 {"DDB_INT4STAT", DDB_BASE + DDB_INT4STAT},
50 {"DDB_NMISTAT", DDB_BASE + DDB_NMISTAT},
51 {"DDB_INTPPES0", DDB_BASE + DDB_INTPPES0},
52 {"DDB_INTPPES1", DDB_BASE + DDB_INTPPES1},
53 {NULL, 0x0}
54};
55
56void vrc5477_show_int_regs()
57{
58 jsun_show_regs("interrupt registers", int_regs);
59 printk("CPU CAUSE = %08x\n", read_c0_cause());
60 printk("CPU STATUS = %08x\n", read_c0_status());
61}
62static Register pdar_regs[] = {
63 {"DDB_SDRAM0", DDB_BASE + DDB_SDRAM0},
64 {"DDB_SDRAM1", DDB_BASE + DDB_SDRAM1},
65 {"DDB_LCS0", DDB_BASE + DDB_LCS0},
66 {"DDB_LCS1", DDB_BASE + DDB_LCS1},
67 {"DDB_LCS2", DDB_BASE + DDB_LCS2},
68 {"DDB_INTCS", DDB_BASE + DDB_INTCS},
69 {"DDB_BOOTCS", DDB_BASE + DDB_BOOTCS},
70 {"DDB_PCIW0", DDB_BASE + DDB_PCIW0},
71 {"DDB_PCIW1", DDB_BASE + DDB_PCIW1},
72 {"DDB_IOPCIW0", DDB_BASE + DDB_IOPCIW0},
73 {"DDB_IOPCIW1", DDB_BASE + DDB_IOPCIW1},
74 {NULL, 0x0}
75};
76void vrc5477_show_pdar_regs(void)
77{
78 jsun_show_regs("PDAR regs", pdar_regs);
79}
80
81static Register bar_regs[] = {
82 {"DDB_BARC0", DDB_BASE + DDB_BARC0},
83 {"DDB_BARM010", DDB_BASE + DDB_BARM010},
84 {"DDB_BARM230", DDB_BASE + DDB_BARM230},
85 {"DDB_BAR00", DDB_BASE + DDB_BAR00},
86 {"DDB_BAR10", DDB_BASE + DDB_BAR10},
87 {"DDB_BAR20", DDB_BASE + DDB_BAR20},
88 {"DDB_BAR30", DDB_BASE + DDB_BAR30},
89 {"DDB_BAR40", DDB_BASE + DDB_BAR40},
90 {"DDB_BAR50", DDB_BASE + DDB_BAR50},
91 {"DDB_BARB0", DDB_BASE + DDB_BARB0},
92 {"DDB_BARC1", DDB_BASE + DDB_BARC1},
93 {"DDB_BARM011", DDB_BASE + DDB_BARM011},
94 {"DDB_BARM231", DDB_BASE + DDB_BARM231},
95 {"DDB_BAR01", DDB_BASE + DDB_BAR01},
96 {"DDB_BAR11", DDB_BASE + DDB_BAR11},
97 {"DDB_BAR21", DDB_BASE + DDB_BAR21},
98 {"DDB_BAR31", DDB_BASE + DDB_BAR31},
99 {"DDB_BAR41", DDB_BASE + DDB_BAR41},
100 {"DDB_BAR51", DDB_BASE + DDB_BAR51},
101 {"DDB_BARB1", DDB_BASE + DDB_BARB1},
102 {NULL, 0x0}
103};
104void vrc5477_show_bar_regs(void)
105{
106 jsun_show_regs("BAR regs", bar_regs);
107}
108
109static Register pci_regs[] = {
110 {"DDB_PCIW0", DDB_BASE + DDB_PCIW0},
111 {"DDB_PCIW1", DDB_BASE + DDB_PCIW1},
112 {"DDB_PCIINIT00", DDB_BASE + DDB_PCIINIT00},
113 {"DDB_PCIINIT10", DDB_BASE + DDB_PCIINIT10},
114 {"DDB_PCICTL0_L", DDB_BASE + DDB_PCICTL0_L},
115 {"DDB_PCICTL0_H", DDB_BASE + DDB_PCICTL0_H},
116 {"DDB_PCIARB0_L", DDB_BASE + DDB_PCIARB0_L},
117 {"DDB_PCIARB0_H", DDB_BASE + DDB_PCIARB0_H},
118 {"DDB_PCISWP0", DDB_BASE + DDB_PCISWP0},
119 {"DDB_PCIERR0", DDB_BASE + DDB_PCIERR0},
120 {"DDB_IOPCIW0", DDB_BASE + DDB_IOPCIW0},
121 {"DDB_IOPCIW1", DDB_BASE + DDB_IOPCIW1},
122 {"DDB_PCIINIT01", DDB_BASE + DDB_PCIINIT01},
123 {"DDB_PCIINIT11", DDB_BASE + DDB_PCIINIT11},
124 {"DDB_PCICTL1_L", DDB_BASE + DDB_PCICTL1_L},
125 {"DDB_PCICTL1_H", DDB_BASE + DDB_PCICTL1_H},
126 {"DDB_PCIARB1_L", DDB_BASE + DDB_PCIARB1_L},
127 {"DDB_PCIARB1_H", DDB_BASE + DDB_PCIARB1_H},
128 {"DDB_PCISWP1", DDB_BASE + DDB_PCISWP1},
129 {"DDB_PCIERR1", DDB_BASE + DDB_PCIERR1},
130 {NULL, 0x0}
131};
132void vrc5477_show_pci_regs(void)
133{
134 jsun_show_regs("PCI regs", pci_regs);
135}
136
137static Register lb_regs[] = {
138 {"DDB_LCNFG", DDB_BASE + DDB_LCNFG},
139 {"DDB_LCST0", DDB_BASE + DDB_LCST0},
140 {"DDB_LCST1", DDB_BASE + DDB_LCST1},
141 {"DDB_LCST2", DDB_BASE + DDB_LCST2},
142 {"DDB_ERRADR", DDB_BASE + DDB_ERRADR},
143 {"DDB_ERRCS", DDB_BASE + DDB_ERRCS},
144 {"DDB_BTM", DDB_BASE + DDB_BTM},
145 {"DDB_BCST", DDB_BASE + DDB_BCST},
146 {NULL, 0x0}
147};
148void vrc5477_show_lb_regs(void)
149{
150 jsun_show_regs("Local Bus regs", lb_regs);
151}
152
153void vrc5477_show_all_regs(void)
154{
155 vrc5477_show_pdar_regs();
156 vrc5477_show_pci_regs();
157 vrc5477_show_bar_regs();
158 vrc5477_show_int_regs();
159 vrc5477_show_lb_regs();
160}
diff --git a/arch/mips/ddb5xxx/ddb5477/int-handler.S b/arch/mips/ddb5xxx/ddb5477/int-handler.S
new file mode 100644
index 000000000000..a2502a14400e
--- /dev/null
+++ b/arch/mips/ddb5xxx/ddb5477/int-handler.S
@@ -0,0 +1,75 @@
1/*
2 * Copyright 2001 MontaVista Software Inc.
3 * Author: jsun@mvista.com or jsun@junsun.net
4 *
5 * First-level interrupt dispatcher for ddb5477
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version.
11 */
12#include <asm/asm.h>
13#include <asm/mipsregs.h>
14#include <asm/addrspace.h>
15#include <asm/regdef.h>
16#include <asm/stackframe.h>
17#include <asm/ddb5xxx/ddb5477.h>
18
19/*
20 * first level interrupt dispatcher for ocelot board -
21 * We check for the timer first, then check PCI ints A and D.
22 * Then check for serial IRQ and fall through.
23 */
24 .align 5
25 NESTED(ddb5477_handle_int, PT_SIZE, sp)
26 SAVE_ALL
27 CLI
28 .set at
29 .set noreorder
30 mfc0 t0, CP0_CAUSE
31 mfc0 t2, CP0_STATUS
32
33 and t0, t2
34
35 andi t1, t0, STATUSF_IP7 /* cpu timer */
36 bnez t1, ll_cputimer_irq
37 andi t1, t0, (STATUSF_IP2 | STATUSF_IP3 | STATUSF_IP4 | STATUSF_IP5 | STATUSF_IP6 )
38 bnez t1, ll_vrc5477_irq
39 andi t1, t0, STATUSF_IP0 /* software int 0 */
40 bnez t1, ll_cpu_ip0
41 andi t1, t0, STATUSF_IP1 /* software int 1 */
42 bnez t1, ll_cpu_ip1
43 nop
44 .set reorder
45
46 /* wrong alarm or masked ... */
47 j spurious_interrupt
48 nop
49 END(ddb5477_handle_int)
50
51 .align 5
52
53ll_vrc5477_irq:
54 move a0, sp
55 jal vrc5477_irq_dispatch
56 j ret_from_irq
57
58ll_cputimer_irq:
59 li a0, CPU_IRQ_BASE + 7
60 move a1, sp
61 jal do_IRQ
62 j ret_from_irq
63
64
65ll_cpu_ip0:
66 li a0, CPU_IRQ_BASE + 0
67 move a1, sp
68 jal do_IRQ
69 j ret_from_irq
70
71ll_cpu_ip1:
72 li a0, CPU_IRQ_BASE + 1
73 move a1, sp
74 jal do_IRQ
75 j ret_from_irq
diff --git a/arch/mips/ddb5xxx/ddb5477/irq.c b/arch/mips/ddb5xxx/ddb5477/irq.c
new file mode 100644
index 000000000000..5f027bfa4af8
--- /dev/null
+++ b/arch/mips/ddb5xxx/ddb5477/irq.c
@@ -0,0 +1,199 @@
1/*
2 * Copyright 2001 MontaVista Software Inc.
3 * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
4 *
5 * arch/mips/ddb5xxx/ddb5477/irq.c
6 * The irq setup and misc routines for DDB5476.
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
12 */
13#include <linux/config.h>
14#include <linux/init.h>
15#include <linux/interrupt.h>
16#include <linux/irq.h>
17#include <linux/types.h>
18#include <linux/ptrace.h>
19
20#include <asm/i8259.h>
21#include <asm/system.h>
22#include <asm/mipsregs.h>
23#include <asm/debug.h>
24#include <asm/addrspace.h>
25#include <asm/bootinfo.h>
26
27#include <asm/ddb5xxx/ddb5xxx.h>
28
29
30/*
31 * IRQ mapping
32 *
33 * 0-7: 8 CPU interrupts
34 * 0 - software interrupt 0
35 * 1 - software interrupt 1
36 * 2 - most Vrc5477 interrupts are routed to this pin
37 * 3 - (optional) some other interrupts routed to this pin for debugg
38 * 4 - not used
39 * 5 - not used
40 * 6 - not used
41 * 7 - cpu timer (used by default)
42 *
43 * 8-39: 32 Vrc5477 interrupt sources
44 * (refer to the Vrc5477 manual)
45 */
46
47#define PCI0 DDB_INTPPES0
48#define PCI1 DDB_INTPPES1
49
50#define ACTIVE_LOW 1
51#define ACTIVE_HIGH 0
52
53#define LEVEL_SENSE 2
54#define EDGE_TRIGGER 0
55
56#define INTA 0
57#define INTB 1
58#define INTC 2
59#define INTD 3
60#define INTE 4
61
62static inline void
63set_pci_int_attr(u32 pci, u32 intn, u32 active, u32 trigger)
64{
65 u32 reg_value;
66 u32 reg_bitmask;
67
68 reg_value = ddb_in32(pci);
69 reg_bitmask = 0x3 << (intn * 2);
70
71 reg_value &= ~reg_bitmask;
72 reg_value |= (active | trigger) << (intn * 2);
73 ddb_out32(pci, reg_value);
74}
75
76extern void vrc5477_irq_init(u32 base);
77extern void mips_cpu_irq_init(u32 base);
78extern asmlinkage void ddb5477_handle_int(void);
79extern int setup_irq(unsigned int irq, struct irqaction *irqaction);
80static struct irqaction irq_cascade = { no_action, 0, CPU_MASK_NONE, "cascade", NULL, NULL };
81
82void __init arch_init_irq(void)
83{
84 /* by default, we disable all interrupts and route all vrc5477
85 * interrupts to pin 0 (irq 2) */
86 ddb_out32(DDB_INTCTRL0, 0);
87 ddb_out32(DDB_INTCTRL1, 0);
88 ddb_out32(DDB_INTCTRL2, 0);
89 ddb_out32(DDB_INTCTRL3, 0);
90
91 clear_c0_status(0xff00);
92 set_c0_status(0x0400);
93
94 /* setup PCI interrupt attributes */
95 set_pci_int_attr(PCI0, INTA, ACTIVE_LOW, LEVEL_SENSE);
96 set_pci_int_attr(PCI0, INTB, ACTIVE_LOW, LEVEL_SENSE);
97 if (mips_machtype == MACH_NEC_ROCKHOPPERII)
98 set_pci_int_attr(PCI0, INTC, ACTIVE_HIGH, LEVEL_SENSE);
99 else
100 set_pci_int_attr(PCI0, INTC, ACTIVE_LOW, LEVEL_SENSE);
101 set_pci_int_attr(PCI0, INTD, ACTIVE_LOW, LEVEL_SENSE);
102 set_pci_int_attr(PCI0, INTE, ACTIVE_LOW, LEVEL_SENSE);
103
104 set_pci_int_attr(PCI1, INTA, ACTIVE_LOW, LEVEL_SENSE);
105 set_pci_int_attr(PCI1, INTB, ACTIVE_LOW, LEVEL_SENSE);
106 set_pci_int_attr(PCI1, INTC, ACTIVE_LOW, LEVEL_SENSE);
107 set_pci_int_attr(PCI1, INTD, ACTIVE_LOW, LEVEL_SENSE);
108 set_pci_int_attr(PCI1, INTE, ACTIVE_LOW, LEVEL_SENSE);
109
110 /*
111 * for debugging purpose, we enable several error interrupts
112 * and route them to pin 1. (IP3)
113 */
114 /* cpu parity check - 0 */
115 ll_vrc5477_irq_route(0, 1); ll_vrc5477_irq_enable(0);
116 /* cpu no-target decode - 1 */
117 ll_vrc5477_irq_route(1, 1); ll_vrc5477_irq_enable(1);
118 /* local bus read time-out - 7 */
119 ll_vrc5477_irq_route(7, 1); ll_vrc5477_irq_enable(7);
120 /* PCI SERR# - 14 */
121 ll_vrc5477_irq_route(14, 1); ll_vrc5477_irq_enable(14);
122 /* PCI internal error - 15 */
123 ll_vrc5477_irq_route(15, 1); ll_vrc5477_irq_enable(15);
124 /* IOPCI SERR# - 30 */
125 ll_vrc5477_irq_route(30, 1); ll_vrc5477_irq_enable(30);
126 /* IOPCI internal error - 31 */
127 ll_vrc5477_irq_route(31, 1); ll_vrc5477_irq_enable(31);
128
129 /* init all controllers */
130 init_i8259_irqs();
131 mips_cpu_irq_init(CPU_IRQ_BASE);
132 vrc5477_irq_init(VRC5477_IRQ_BASE);
133
134
135 /* setup cascade interrupts */
136 setup_irq(VRC5477_IRQ_BASE + VRC5477_I8259_CASCADE, &irq_cascade);
137 setup_irq(CPU_IRQ_BASE + CPU_VRC5477_CASCADE, &irq_cascade);
138
139 /* hook up the first-level interrupt handler */
140 set_except_vector(0, ddb5477_handle_int);
141}
142
143u8 i8259_interrupt_ack(void)
144{
145 u8 irq;
146 u32 reg;
147
148 /* Set window 0 for interrupt acknowledge */
149 reg = ddb_in32(DDB_PCIINIT10);
150
151 ddb_set_pmr(DDB_PCIINIT10, DDB_PCICMD_IACK, 0, DDB_PCI_ACCESS_32);
152 irq = *(volatile u8 *) KSEG1ADDR(DDB_PCI_IACK_BASE);
153 ddb_out32(DDB_PCIINIT10, reg);
154
155 /* i8259.c set the base vector to be 0x0 */
156 return irq + I8259_IRQ_BASE;
157}
158/*
159 * the first level int-handler will jump here if it is a vrc5477 irq
160 */
161#define NUM_5477_IRQS 32
162asmlinkage void
163vrc5477_irq_dispatch(struct pt_regs *regs)
164{
165 u32 intStatus;
166 u32 bitmask;
167 u32 i;
168
169 db_assert(ddb_in32(DDB_INT2STAT) == 0);
170 db_assert(ddb_in32(DDB_INT3STAT) == 0);
171 db_assert(ddb_in32(DDB_INT4STAT) == 0);
172 db_assert(ddb_in32(DDB_NMISTAT) == 0);
173
174 if (ddb_in32(DDB_INT1STAT) != 0) {
175#if defined(CONFIG_RUNTIME_DEBUG)
176 vrc5477_show_int_regs();
177#endif
178 panic("error interrupt has happened.");
179 }
180
181 intStatus = ddb_in32(DDB_INT0STAT);
182
183 if (mips_machtype == MACH_NEC_ROCKHOPPERII) {
184 /* check for i8259 interrupts */
185 if (intStatus & (1 << VRC5477_I8259_CASCADE)) {
186 int i8259_irq = i8259_interrupt_ack();
187 do_IRQ(I8259_IRQ_BASE + i8259_irq, regs);
188 return;
189 }
190 }
191
192 for (i=0, bitmask=1; i<= NUM_5477_IRQS; bitmask <<=1, i++) {
193 /* do we need to "and" with the int mask? */
194 if (intStatus & bitmask) {
195 do_IRQ(VRC5477_IRQ_BASE + i, regs);
196 return;
197 }
198 }
199}
diff --git a/arch/mips/ddb5xxx/ddb5477/irq_5477.c b/arch/mips/ddb5xxx/ddb5477/irq_5477.c
new file mode 100644
index 000000000000..0d5e706207ec
--- /dev/null
+++ b/arch/mips/ddb5xxx/ddb5477/irq_5477.c
@@ -0,0 +1,168 @@
1/*
2 * Copyright 2001 MontaVista Software Inc.
3 * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
4 *
5 * arch/mips/ddb5xxx/ddb5477/irq_5477.c
6 * This file defines the irq handler for Vrc5477.
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
12 *
13 */
14
15/*
16 * Vrc5477 defines 32 IRQs.
17 *
18 * This file exports one function:
19 * vrc5477_irq_init(u32 irq_base);
20 */
21
22#include <linux/interrupt.h>
23#include <linux/types.h>
24#include <linux/ptrace.h>
25
26#include <asm/debug.h>
27
28#include <asm/ddb5xxx/ddb5xxx.h>
29
30/* number of total irqs supported by Vrc5477 */
31#define NUM_5477_IRQ 32
32
33static int vrc5477_irq_base = -1;
34
35
36static void
37vrc5477_irq_enable(unsigned int irq)
38{
39 db_assert(vrc5477_irq_base != -1);
40 db_assert(irq >= vrc5477_irq_base);
41 db_assert(irq < vrc5477_irq_base+ NUM_5477_IRQ);
42
43 ll_vrc5477_irq_enable(irq - vrc5477_irq_base);
44}
45
46static void
47vrc5477_irq_disable(unsigned int irq)
48{
49 db_assert(vrc5477_irq_base != -1);
50 db_assert(irq >= vrc5477_irq_base);
51 db_assert(irq < vrc5477_irq_base + NUM_5477_IRQ);
52
53 ll_vrc5477_irq_disable(irq - vrc5477_irq_base);
54}
55
56static unsigned int vrc5477_irq_startup(unsigned int irq)
57{
58 vrc5477_irq_enable(irq);
59 return 0;
60}
61
62#define vrc5477_irq_shutdown vrc5477_irq_disable
63
64static void
65vrc5477_irq_ack(unsigned int irq)
66{
67 db_assert(vrc5477_irq_base != -1);
68 db_assert(irq >= vrc5477_irq_base);
69 db_assert(irq < vrc5477_irq_base+ NUM_5477_IRQ);
70
71 /* clear the interrupt bit */
72 /* some irqs require the driver to clear the sources */
73 ddb_out32(DDB_INTCLR32, 1 << (irq - vrc5477_irq_base));
74
75 /* disable interrupt - some handler will re-enable the irq
76 * and if the interrupt is leveled, we will have infinite loop
77 */
78 ll_vrc5477_irq_disable(irq - vrc5477_irq_base);
79}
80
81static void
82vrc5477_irq_end(unsigned int irq)
83{
84 db_assert(vrc5477_irq_base != -1);
85 db_assert(irq >= vrc5477_irq_base);
86 db_assert(irq < vrc5477_irq_base + NUM_5477_IRQ);
87
88 if(!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
89 ll_vrc5477_irq_enable( irq - vrc5477_irq_base);
90}
91
92hw_irq_controller vrc5477_irq_controller = {
93 "vrc5477_irq",
94 vrc5477_irq_startup,
95 vrc5477_irq_shutdown,
96 vrc5477_irq_enable,
97 vrc5477_irq_disable,
98 vrc5477_irq_ack,
99 vrc5477_irq_end,
100 NULL /* no affinity stuff for UP */
101};
102
103void __init vrc5477_irq_init(u32 irq_base)
104{
105 u32 i;
106
107 for (i= irq_base; i< irq_base+ NUM_5477_IRQ; i++) {
108 irq_desc[i].status = IRQ_DISABLED;
109 irq_desc[i].action = NULL;
110 irq_desc[i].depth = 1;
111 irq_desc[i].handler = &vrc5477_irq_controller;
112 }
113
114 vrc5477_irq_base = irq_base;
115}
116
117void ll_vrc5477_irq_route(int vrc5477_irq, int ip)
118{
119 u32 reg_value;
120 u32 reg_bitmask;
121 u32 reg_index;
122
123 db_assert(vrc5477_irq >= 0);
124 db_assert(vrc5477_irq < NUM_5477_IRQ);
125 db_assert(ip >= 0);
126 db_assert((ip < 5) || (ip == 6));
127
128 reg_index = DDB_INTCTRL0 + vrc5477_irq/8*4;
129 reg_value = ddb_in32(reg_index);
130 reg_bitmask = 7 << (vrc5477_irq % 8 * 4);
131 reg_value &= ~reg_bitmask;
132 reg_value |= ip << (vrc5477_irq % 8 * 4);
133 ddb_out32(reg_index, reg_value);
134}
135
136void ll_vrc5477_irq_enable(int vrc5477_irq)
137{
138 u32 reg_value;
139 u32 reg_bitmask;
140 u32 reg_index;
141
142 db_assert(vrc5477_irq >= 0);
143 db_assert(vrc5477_irq < NUM_5477_IRQ);
144
145 reg_index = DDB_INTCTRL0 + vrc5477_irq/8*4;
146 reg_value = ddb_in32(reg_index);
147 reg_bitmask = 8 << (vrc5477_irq % 8 * 4);
148 db_assert((reg_value & reg_bitmask) == 0);
149 ddb_out32(reg_index, reg_value | reg_bitmask);
150}
151
152void ll_vrc5477_irq_disable(int vrc5477_irq)
153{
154 u32 reg_value;
155 u32 reg_bitmask;
156 u32 reg_index;
157
158 db_assert(vrc5477_irq >= 0);
159 db_assert(vrc5477_irq < NUM_5477_IRQ);
160
161 reg_index = DDB_INTCTRL0 + vrc5477_irq/8*4;
162 reg_value = ddb_in32(reg_index);
163 reg_bitmask = 8 << (vrc5477_irq % 8 * 4);
164
165 /* we assert that the interrupt is enabled (perhaps over-zealous) */
166 db_assert( (reg_value & reg_bitmask) != 0);
167 ddb_out32(reg_index, reg_value & ~reg_bitmask);
168}
diff --git a/arch/mips/ddb5xxx/ddb5477/kgdb_io.c b/arch/mips/ddb5xxx/ddb5477/kgdb_io.c
new file mode 100644
index 000000000000..1d18d590495b
--- /dev/null
+++ b/arch/mips/ddb5xxx/ddb5477/kgdb_io.c
@@ -0,0 +1,136 @@
1/*
2 * kgdb io functions for DDB5477. We use the second serial port (upper one).
3 *
4 * Copyright (C) 2001 MontaVista Software Inc.
5 * Author: jsun@mvista.com or jsun@junsun.net
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version.
11 *
12 */
13
14/* ======================= CONFIG ======================== */
15
16/* [jsun] we use the second serial port for kdb */
17#define BASE 0xbfa04240
18#define MAX_BAUD 115200
19
20/* distance in bytes between two serial registers */
21#define REG_OFFSET 8
22
23/*
24 * 0 - kgdb does serial init
25 * 1 - kgdb skip serial init
26 */
27static int remoteDebugInitialized = 0;
28
29/*
30 * the default baud rate *if* kgdb does serial init
31 */
32#define BAUD_DEFAULT UART16550_BAUD_38400
33
34/* ======================= END OF CONFIG ======================== */
35
36typedef unsigned char uint8;
37typedef unsigned int uint32;
38
39#define UART16550_BAUD_2400 2400
40#define UART16550_BAUD_4800 4800
41#define UART16550_BAUD_9600 9600
42#define UART16550_BAUD_19200 19200
43#define UART16550_BAUD_38400 38400
44#define UART16550_BAUD_57600 57600
45#define UART16550_BAUD_115200 115200
46
47#define UART16550_PARITY_NONE 0
48#define UART16550_PARITY_ODD 0x08
49#define UART16550_PARITY_EVEN 0x18
50#define UART16550_PARITY_MARK 0x28
51#define UART16550_PARITY_SPACE 0x38
52
53#define UART16550_DATA_5BIT 0x0
54#define UART16550_DATA_6BIT 0x1
55#define UART16550_DATA_7BIT 0x2
56#define UART16550_DATA_8BIT 0x3
57
58#define UART16550_STOP_1BIT 0x0
59#define UART16550_STOP_2BIT 0x4
60
61/* register offset */
62#define OFS_RCV_BUFFER 0
63#define OFS_TRANS_HOLD 0
64#define OFS_SEND_BUFFER 0
65#define OFS_INTR_ENABLE (1*REG_OFFSET)
66#define OFS_INTR_ID (2*REG_OFFSET)
67#define OFS_DATA_FORMAT (3*REG_OFFSET)
68#define OFS_LINE_CONTROL (3*REG_OFFSET)
69#define OFS_MODEM_CONTROL (4*REG_OFFSET)
70#define OFS_RS232_OUTPUT (4*REG_OFFSET)
71#define OFS_LINE_STATUS (5*REG_OFFSET)
72#define OFS_MODEM_STATUS (6*REG_OFFSET)
73#define OFS_RS232_INPUT (6*REG_OFFSET)
74#define OFS_SCRATCH_PAD (7*REG_OFFSET)
75
76#define OFS_DIVISOR_LSB (0*REG_OFFSET)
77#define OFS_DIVISOR_MSB (1*REG_OFFSET)
78
79
80/* memory-mapped read/write of the port */
81#define UART16550_READ(y) (*((volatile uint8*)(BASE + y)))
82#define UART16550_WRITE(y, z) ((*((volatile uint8*)(BASE + y))) = z)
83
84void debugInit(uint32 baud, uint8 data, uint8 parity, uint8 stop)
85{
86 /* disable interrupts */
87 UART16550_WRITE(OFS_INTR_ENABLE, 0);
88
89 /* set up buad rate */
90 {
91 uint32 divisor;
92
93 /* set DIAB bit */
94 UART16550_WRITE(OFS_LINE_CONTROL, 0x80);
95
96 /* set divisor */
97 divisor = MAX_BAUD / baud;
98 UART16550_WRITE(OFS_DIVISOR_LSB, divisor & 0xff);
99 UART16550_WRITE(OFS_DIVISOR_MSB, (divisor & 0xff00) >> 8);
100
101 /* clear DIAB bit */
102 UART16550_WRITE(OFS_LINE_CONTROL, 0x0);
103 }
104
105 /* set data format */
106 UART16550_WRITE(OFS_DATA_FORMAT, data | parity | stop);
107}
108
109
110uint8 getDebugChar(void)
111{
112 if (!remoteDebugInitialized) {
113 remoteDebugInitialized = 1;
114 debugInit(BAUD_DEFAULT,
115 UART16550_DATA_8BIT,
116 UART16550_PARITY_NONE, UART16550_STOP_1BIT);
117 }
118
119 while ((UART16550_READ(OFS_LINE_STATUS) & 0x1) == 0);
120 return UART16550_READ(OFS_RCV_BUFFER);
121}
122
123
124int putDebugChar(uint8 byte)
125{
126 if (!remoteDebugInitialized) {
127 remoteDebugInitialized = 1;
128 debugInit(BAUD_DEFAULT,
129 UART16550_DATA_8BIT,
130 UART16550_PARITY_NONE, UART16550_STOP_1BIT);
131 }
132
133 while ((UART16550_READ(OFS_LINE_STATUS) & 0x20) == 0);
134 UART16550_WRITE(OFS_SEND_BUFFER, byte);
135 return 1;
136}
diff --git a/arch/mips/ddb5xxx/ddb5477/lcd44780.c b/arch/mips/ddb5xxx/ddb5477/lcd44780.c
new file mode 100644
index 000000000000..35c6c22610c5
--- /dev/null
+++ b/arch/mips/ddb5xxx/ddb5477/lcd44780.c
@@ -0,0 +1,92 @@
1/*
2 * lcd44780.c
3 * Simple "driver" for a memory-mapped 44780-style LCD display.
4 *
5 * Copyright 2001 Bradley D. LaRonde <brad@ltc.com>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version.
11 *
12 */
13
14#define LCD44780_COMMAND ((volatile unsigned char *)0xbe020000)
15#define LCD44780_DATA ((volatile unsigned char *)0xbe020001)
16
17#define LCD44780_4BIT_1LINE 0x20
18#define LCD44780_4BIT_2LINE 0x28
19#define LCD44780_8BIT_1LINE 0x30
20#define LCD44780_8BIT_2LINE 0x38
21#define LCD44780_MODE_DEC 0x04
22#define LCD44780_MODE_DEC_SHIFT 0x05
23#define LCD44780_MODE_INC 0x06
24#define LCD44780_MODE_INC_SHIFT 0x07
25#define LCD44780_SCROLL_LEFT 0x18
26#define LCD44780_SCROLL_RIGHT 0x1e
27#define LCD44780_CURSOR_UNDERLINE 0x0e
28#define LCD44780_CURSOR_BLOCK 0x0f
29#define LCD44780_CURSOR_OFF 0x0c
30#define LCD44780_CLEAR 0x01
31#define LCD44780_BLANK 0x08
32#define LCD44780_RESTORE 0x0c // Same as CURSOR_OFF
33#define LCD44780_HOME 0x02
34#define LCD44780_LEFT 0x10
35#define LCD44780_RIGHT 0x14
36
37void lcd44780_wait(void)
38{
39 int i, j;
40 for(i=0; i < 400; i++)
41 for(j=0; j < 10000; j++);
42}
43
44void lcd44780_command(unsigned char c)
45{
46 *LCD44780_COMMAND = c;
47 lcd44780_wait();
48}
49
50void lcd44780_data(unsigned char c)
51{
52 *LCD44780_DATA = c;
53 lcd44780_wait();
54}
55
56void lcd44780_puts(const char* s)
57{
58 int i,j;
59 int pos = 0;
60
61 lcd44780_command(LCD44780_CLEAR);
62 while(*s) {
63 lcd44780_data(*s);
64 s++;
65 pos++;
66 if (pos == 8) {
67 /* We must write 32 of spaces to get cursor to 2nd line */
68 for (j=0; j<32; j++) {
69 lcd44780_data(' ');
70 }
71 }
72 if (pos == 16) {
73 /* We have filled all 16 character positions, so stop
74 outputing data */
75 break;
76 }
77 }
78#ifdef LCD44780_PUTS_PAUSE
79 for(i = 1; i < 2000; i++)
80 lcd44780_wait();
81#endif
82}
83
84void lcd44780_init(void)
85{
86 // The display on the RockHopper is physically a single
87 // 16 char line (two 8 char lines concatenated). bdl
88 lcd44780_command(LCD44780_8BIT_2LINE);
89 lcd44780_command(LCD44780_MODE_INC);
90 lcd44780_command(LCD44780_CURSOR_BLOCK);
91 lcd44780_command(LCD44780_CLEAR);
92}
diff --git a/arch/mips/ddb5xxx/ddb5477/lcd44780.h b/arch/mips/ddb5xxx/ddb5477/lcd44780.h
new file mode 100644
index 000000000000..cf2f0f71eee5
--- /dev/null
+++ b/arch/mips/ddb5xxx/ddb5477/lcd44780.h
@@ -0,0 +1,15 @@
1/*
2 * lcd44780.h
3 * Simple "driver" for a memory-mapped 44780-style LCD display.
4 *
5 * Copyright 2001 Bradley D. LaRonde <brad@ltc.com>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version.
11 *
12 */
13
14void lcd44780_puts(const char* s);
15void lcd44780_init(void);
diff --git a/arch/mips/ddb5xxx/ddb5477/setup.c b/arch/mips/ddb5xxx/ddb5477/setup.c
new file mode 100644
index 000000000000..15c6e543b56f
--- /dev/null
+++ b/arch/mips/ddb5xxx/ddb5477/setup.c
@@ -0,0 +1,405 @@
1/*
2 *
3 * Copyright 2001 MontaVista Software Inc.
4 * Author: jsun@mvista.com or jsun@junsun.net
5 *
6 * Copyright (C) 2004 by Ralf Baechle (ralf@linux-mips.org)
7 *
8 * arch/mips/ddb5xxx/ddb5477/setup.c
9 * Setup file for DDB5477.
10 *
11 * This program is free software; you can redistribute it and/or modify it
12 * under the terms of the GNU General Public License as published by the
13 * Free Software Foundation; either version 2 of the License, or (at your
14 * option) any later version.
15 */
16#include <linux/config.h>
17#include <linux/init.h>
18#include <linux/kernel.h>
19#include <linux/types.h>
20#include <linux/sched.h>
21#include <linux/pci.h>
22#include <linux/ide.h>
23#include <linux/fs.h>
24#include <linux/ioport.h>
25#include <linux/param.h> /* for HZ */
26#include <linux/major.h>
27#include <linux/kdev_t.h>
28#include <linux/root_dev.h>
29
30#include <asm/cpu.h>
31#include <asm/bootinfo.h>
32#include <asm/addrspace.h>
33#include <asm/time.h>
34#include <asm/bcache.h>
35#include <asm/irq.h>
36#include <asm/reboot.h>
37#include <asm/gdb-stub.h>
38#include <asm/traps.h>
39#include <asm/debug.h>
40
41#include <asm/ddb5xxx/ddb5xxx.h>
42
43#include "lcd44780.h"
44
45
46#define USE_CPU_COUNTER_TIMER /* whether we use cpu counter */
47
48#define SP_TIMER_BASE DDB_SPT1CTRL_L
49#define SP_TIMER_IRQ VRC5477_IRQ_SPT1
50
51static int bus_frequency = CONFIG_DDB5477_BUS_FREQUENCY*1000;
52
53static void ddb_machine_restart(char *command)
54{
55 static void (*back_to_prom) (void) = (void (*)(void)) 0xbfc00000;
56
57 u32 t;
58
59 /* PCI cold reset */
60 ddb_pci_reset_bus();
61
62 /* CPU cold reset */
63 t = ddb_in32(DDB_CPUSTAT);
64 db_assert((t&1));
65 ddb_out32(DDB_CPUSTAT, t);
66
67 /* Call the PROM */
68 back_to_prom();
69}
70
71static void ddb_machine_halt(void)
72{
73 printk("DDB Vrc-5477 halted.\n");
74 while (1);
75}
76
77static void ddb_machine_power_off(void)
78{
79 printk("DDB Vrc-5477 halted. Please turn off the power.\n");
80 while (1);
81}
82
83extern void rtc_ds1386_init(unsigned long base);
84
85static unsigned int __init detect_bus_frequency(unsigned long rtc_base)
86{
87 unsigned int freq;
88 unsigned char c;
89 unsigned int t1, t2;
90 unsigned i;
91
92 ddb_out32(SP_TIMER_BASE, 0xffffffff);
93 ddb_out32(SP_TIMER_BASE+4, 0x1);
94 ddb_out32(SP_TIMER_BASE+8, 0xffffffff);
95
96 /* check if rtc is running */
97 c= *(volatile unsigned char*)rtc_base;
98 for(i=0; (c == *(volatile unsigned char*)rtc_base) && (i<100000000); i++);
99 if (c == *(volatile unsigned char*)rtc_base) {
100 printk("Failed to detect bus frequency. Use default 83.3MHz.\n");
101 return 83333000;
102 }
103
104 c= *(volatile unsigned char*)rtc_base;
105 while (c == *(volatile unsigned char*)rtc_base);
106 /* we are now at the turn of 1/100th second, if no error. */
107 t1 = ddb_in32(SP_TIMER_BASE+8);
108
109 for (i=0; i< 10; i++) {
110 c= *(volatile unsigned char*)rtc_base;
111 while (c == *(volatile unsigned char*)rtc_base);
112 /* we are now at the turn of another 1/100th second */
113 t2 = ddb_in32(SP_TIMER_BASE+8);
114 }
115
116 ddb_out32(SP_TIMER_BASE+4, 0x0); /* disable it again */
117
118 freq = (t1 - t2)*10;
119 printk("DDB bus frequency detection : %u \n", freq);
120 return freq;
121}
122
123static void __init ddb_time_init(void)
124{
125 unsigned long rtc_base;
126 unsigned int i;
127
128 /* we have ds1396 RTC chip */
129 if (mips_machtype == MACH_NEC_ROCKHOPPER
130 || mips_machtype == MACH_NEC_ROCKHOPPERII) {
131 rtc_base = KSEG1ADDR(DDB_LCS2_BASE);
132 } else {
133 rtc_base = KSEG1ADDR(DDB_LCS1_BASE);
134 }
135 rtc_ds1386_init(rtc_base);
136
137 /* do we need to do run-time detection of bus speed? */
138 if (bus_frequency == 0) {
139 bus_frequency = detect_bus_frequency(rtc_base);
140 }
141
142 /* mips_hpt_frequency is 1/2 of the cpu core freq */
143 i = (read_c0_config() >> 28 ) & 7;
144 if ((current_cpu_data.cputype == CPU_R5432) && (i == 3))
145 i = 4;
146 mips_hpt_frequency = bus_frequency*(i+4)/4;
147}
148
149extern int setup_irq(unsigned int irq, struct irqaction *irqaction);
150
151static void __init ddb_timer_setup(struct irqaction *irq)
152{
153#if defined(USE_CPU_COUNTER_TIMER)
154
155 /* we are using the cpu counter for timer interrupts */
156 setup_irq(CPU_IRQ_BASE + 7, irq);
157
158#else
159
160 /* if we use Special purpose timer 1 */
161 ddb_out32(SP_TIMER_BASE, bus_frequency/HZ);
162 ddb_out32(SP_TIMER_BASE+4, 0x1);
163 setup_irq(SP_TIMER_IRQ, irq);
164
165#endif
166}
167
168static void ddb5477_board_init(void);
169
170extern struct pci_controller ddb5477_ext_controller;
171extern struct pci_controller ddb5477_io_controller;
172
173static int ddb5477_setup(void)
174{
175 /* initialize board - we don't trust the loader */
176 ddb5477_board_init();
177
178 set_io_port_base(KSEG1ADDR(DDB_PCI_IO_BASE));
179
180 board_time_init = ddb_time_init;
181 board_timer_setup = ddb_timer_setup;
182
183 _machine_restart = ddb_machine_restart;
184 _machine_halt = ddb_machine_halt;
185 _machine_power_off = ddb_machine_power_off;
186
187 /* setup resource limits */
188 ioport_resource.end = DDB_PCI0_IO_SIZE + DDB_PCI1_IO_SIZE - 1;
189 iomem_resource.end = 0xffffffff;
190
191 /* Reboot on panic */
192 panic_timeout = 180;
193
194 register_pci_controller (&ddb5477_ext_controller);
195 register_pci_controller (&ddb5477_io_controller);
196
197 return 0;
198}
199
200early_initcall(ddb5477_setup);
201
202static void __init ddb5477_board_init(void)
203{
204 /* ----------- setup PDARs ------------ */
205
206 /* SDRAM should have been set */
207 db_assert(ddb_in32(DDB_SDRAM0) ==
208 ddb_calc_pdar(DDB_SDRAM_BASE, board_ram_size, 32, 0, 1));
209
210 /* SDRAM1 should be turned off. What is this for anyway ? */
211 db_assert( (ddb_in32(DDB_SDRAM1) & 0xf) == 0);
212
213 /* Setup local bus. */
214
215 /* Flash U12 PDAR and timing. */
216 ddb_set_pdar(DDB_LCS0, DDB_LCS0_BASE, DDB_LCS0_SIZE, 16, 0, 0);
217 ddb_out32(DDB_LCST0, 0x00090842);
218
219 /* We need to setup LCS1 and LCS2 differently based on the
220 board_version */
221 if (mips_machtype == MACH_NEC_ROCKHOPPER) {
222 /* Flash U13 PDAR and timing. */
223 ddb_set_pdar(DDB_LCS1, DDB_LCS1_BASE, DDB_LCS1_SIZE, 16, 0, 0);
224 ddb_out32(DDB_LCST1, 0x00090842);
225
226 /* EPLD (NVRAM, switch, LCD, and mezzanie). */
227 ddb_set_pdar(DDB_LCS2, DDB_LCS2_BASE, DDB_LCS2_SIZE, 8, 0, 0);
228 } else {
229 /* misc */
230 ddb_set_pdar(DDB_LCS1, DDB_LCS1_BASE, DDB_LCS1_SIZE, 8, 0, 0);
231 /* mezzanie (?) */
232 ddb_set_pdar(DDB_LCS2, DDB_LCS2_BASE, DDB_LCS2_SIZE, 16, 0, 0);
233 }
234
235 /* verify VRC5477 base addr */
236 db_assert(ddb_in32(DDB_VRC5477) ==
237 ddb_calc_pdar(DDB_VRC5477_BASE, DDB_VRC5477_SIZE, 32, 0, 1));
238
239 /* verify BOOT ROM addr */
240 db_assert(ddb_in32(DDB_BOOTCS) ==
241 ddb_calc_pdar(DDB_BOOTCS_BASE, DDB_BOOTCS_SIZE, 8, 0, 0));
242
243 /* setup PCI windows - window0 for MEM/config, window1 for IO */
244 ddb_set_pdar(DDB_PCIW0, DDB_PCI0_MEM_BASE, DDB_PCI0_MEM_SIZE, 32, 0, 1);
245 ddb_set_pdar(DDB_PCIW1, DDB_PCI0_IO_BASE, DDB_PCI0_IO_SIZE, 32, 0, 1);
246 ddb_set_pdar(DDB_IOPCIW0, DDB_PCI1_MEM_BASE, DDB_PCI1_MEM_SIZE, 32, 0, 1);
247 ddb_set_pdar(DDB_IOPCIW1, DDB_PCI1_IO_BASE, DDB_PCI1_IO_SIZE, 32, 0, 1);
248
249 /* ------------ reset PCI bus and BARs ----------------- */
250 ddb_pci_reset_bus();
251
252 ddb_out32(DDB_BARM010, 0x00000008);
253 ddb_out32(DDB_BARM011, 0x00000008);
254
255 ddb_out32(DDB_BARC0, 0xffffffff);
256 ddb_out32(DDB_BARM230, 0xffffffff);
257 ddb_out32(DDB_BAR00, 0xffffffff);
258 ddb_out32(DDB_BAR10, 0xffffffff);
259 ddb_out32(DDB_BAR20, 0xffffffff);
260 ddb_out32(DDB_BAR30, 0xffffffff);
261 ddb_out32(DDB_BAR40, 0xffffffff);
262 ddb_out32(DDB_BAR50, 0xffffffff);
263 ddb_out32(DDB_BARB0, 0xffffffff);
264
265 ddb_out32(DDB_BARC1, 0xffffffff);
266 ddb_out32(DDB_BARM231, 0xffffffff);
267 ddb_out32(DDB_BAR01, 0xffffffff);
268 ddb_out32(DDB_BAR11, 0xffffffff);
269 ddb_out32(DDB_BAR21, 0xffffffff);
270 ddb_out32(DDB_BAR31, 0xffffffff);
271 ddb_out32(DDB_BAR41, 0xffffffff);
272 ddb_out32(DDB_BAR51, 0xffffffff);
273 ddb_out32(DDB_BARB1, 0xffffffff);
274
275 /*
276 * We use pci master register 0 for memory space / config space
277 * And we use register 1 for IO space.
278 * Note that for memory space, we bump up the pci base address
279 * so that we have 1:1 mapping between PCI memory and cpu physical.
280 * For PCI IO space, it starts from 0 in PCI IO space but with
281 * DDB_xx_IO_BASE in CPU physical address space.
282 */
283 ddb_set_pmr(DDB_PCIINIT00, DDB_PCICMD_MEM, DDB_PCI0_MEM_BASE,
284 DDB_PCI_ACCESS_32);
285 ddb_set_pmr(DDB_PCIINIT10, DDB_PCICMD_IO, 0, DDB_PCI_ACCESS_32);
286
287 ddb_set_pmr(DDB_PCIINIT01, DDB_PCICMD_MEM, DDB_PCI1_MEM_BASE,
288 DDB_PCI_ACCESS_32);
289 ddb_set_pmr(DDB_PCIINIT11, DDB_PCICMD_IO, DDB_PCI0_IO_SIZE,
290 DDB_PCI_ACCESS_32);
291
292
293 /* PCI cross window should be set properly */
294 ddb_set_pdar(DDB_BARP00, DDB_PCI1_MEM_BASE, DDB_PCI1_MEM_SIZE, 32, 0, 1);
295 ddb_set_pdar(DDB_BARP10, DDB_PCI1_IO_BASE, DDB_PCI1_IO_SIZE, 32, 0, 1);
296 ddb_set_pdar(DDB_BARP01, DDB_PCI0_MEM_BASE, DDB_PCI0_MEM_SIZE, 32, 0, 1);
297 ddb_set_pdar(DDB_BARP11, DDB_PCI0_IO_BASE, DDB_PCI0_IO_SIZE, 32, 0, 1);
298
299 if (mips_machtype == MACH_NEC_ROCKHOPPER
300 || mips_machtype == MACH_NEC_ROCKHOPPERII) {
301 /* Disable bus diagnostics. */
302 ddb_out32(DDB_PCICTL0_L, 0);
303 ddb_out32(DDB_PCICTL0_H, 0);
304 ddb_out32(DDB_PCICTL1_L, 0);
305 ddb_out32(DDB_PCICTL1_H, 0);
306 }
307
308 if (mips_machtype == MACH_NEC_ROCKHOPPER) {
309 u16 vid;
310 struct pci_bus bus;
311 struct pci_dev dev_m1533;
312 extern struct pci_ops ddb5477_ext_pci_ops;
313
314 bus.parent = NULL; /* we scan the top level only */
315 bus.ops = &ddb5477_ext_pci_ops;
316 dev_m1533.bus = &bus;
317 dev_m1533.sysdata = NULL;
318 dev_m1533.devfn = 7*8; // slot 7: M1533 SouthBridge.
319 pci_read_config_word(&dev_m1533, 0, &vid);
320 if (vid == PCI_VENDOR_ID_AL) {
321 printk("Changing mips_machtype to MACH_NEC_ROCKHOPPERII\n");
322 mips_machtype = MACH_NEC_ROCKHOPPERII;
323 }
324 }
325
326 /* enable USB input buffers */
327 ddb_out32(DDB_PIBMISC, 0x00000007);
328
329 /* For dual-function pins, make them all non-GPIO */
330 ddb_out32(DDB_GIUFUNSEL, 0x0);
331 // ddb_out32(DDB_GIUFUNSEL, 0xfe0fcfff); /* NEC recommanded value */
332
333 if (mips_machtype == MACH_NEC_ROCKHOPPERII) {
334
335 /* enable IDE controller on Ali chip (south bridge) */
336 u8 temp8;
337 struct pci_bus bus;
338 struct pci_dev dev_m1533;
339 struct pci_dev dev_m5229;
340 extern struct pci_ops ddb5477_ext_pci_ops;
341
342 /* Setup M1535 registers */
343 bus.parent = NULL; /* we scan the top level only */
344 bus.ops = &ddb5477_ext_pci_ops;
345 dev_m1533.bus = &bus;
346 dev_m1533.sysdata = NULL;
347 dev_m1533.devfn = 7*8; // slot 7: M1533 SouthBridge.
348
349 /* setup IDE controller
350 * enable IDE controller (bit 6 - 1)
351 * IDE IDSEL to be addr:A15 (bit 4:5 - 11)
352 * disable IDE ATA Secondary Bus Signal Pad Control (bit 3 - 0)
353 * enable IDE ATA Primary Bus Signal Pad Control (bit 2 - 1)
354 */
355 pci_write_config_byte(&dev_m1533, 0x58, 0x74);
356
357 /*
358 * positive decode (bit6 -0)
359 * enable IDE controler interrupt (bit 4 -1)
360 * setup SIRQ to point to IRQ 14 (bit 3:0 - 1101)
361 */
362 pci_write_config_byte(&dev_m1533, 0x44, 0x1d);
363
364 /* Setup M5229 registers */
365 dev_m5229.bus = &bus;
366 dev_m5229.sysdata = NULL;
367 dev_m5229.devfn = 4*8; // slot 4 (AD15): M5229 IDE
368
369 /*
370 * enable IDE in the M5229 config register 0x50 (bit 0 - 1)
371 * M5229 IDSEL is addr:15; see above setting
372 */
373 pci_read_config_byte(&dev_m5229, 0x50, &temp8);
374 pci_write_config_byte(&dev_m5229, 0x50, temp8 | 0x1);
375
376 /*
377 * enable bus master (bit 2) and IO decoding (bit 0)
378 */
379 pci_read_config_byte(&dev_m5229, 0x04, &temp8);
380 pci_write_config_byte(&dev_m5229, 0x04, temp8 | 0x5);
381
382 /*
383 * enable native, copied from arch/ppc/k2boot/head.S
384 * TODO - need volatile, need to be portable
385 */
386 pci_write_config_byte(&dev_m5229, 0x09, 0xef);
387
388 /* Set Primary Channel Command Block Timing */
389 pci_write_config_byte(&dev_m5229, 0x59, 0x31);
390
391 /*
392 * Enable primary channel 40-pin cable
393 * M5229 register 0x4a (bit 0)
394 */
395 pci_read_config_byte(&dev_m5229, 0x4a, &temp8);
396 pci_write_config_byte(&dev_m5229, 0x4a, temp8 | 0x1);
397 }
398
399 if (mips_machtype == MACH_NEC_ROCKHOPPER
400 || mips_machtype == MACH_NEC_ROCKHOPPERII) {
401 printk("lcd44780: initializing\n");
402 lcd44780_init();
403 lcd44780_puts("MontaVista Linux");
404 }
405}