diff options
Diffstat (limited to 'arch/mips/ddb5xxx/common')
-rw-r--r-- | arch/mips/ddb5xxx/common/Makefile | 5 | ||||
-rw-r--r-- | arch/mips/ddb5xxx/common/nile4.c | 130 | ||||
-rw-r--r-- | arch/mips/ddb5xxx/common/prom.c | 142 | ||||
-rw-r--r-- | arch/mips/ddb5xxx/common/rtc_ds1386.c | 164 |
4 files changed, 441 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 | |||
5 | obj-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 | |||
21 | u32 | ||
22 | ddb_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 | |||
95 | void | ||
96 | ddb_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 | |||
117 | void 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 | |||
21 | const 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) | ||
34 | void ddb5477_runtime_detection(void); | ||
35 | #endif | ||
36 | |||
37 | /* [jsun@junsun.net] PMON passes arguments in C main() style */ | ||
38 | void __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 | |||
71 | unsigned 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 | |||
82 | int board_ram_size; | ||
83 | void 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 | |||
36 | static unsigned long rtc_base; | ||
37 | |||
38 | static unsigned long | ||
39 | rtc_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 | |||
77 | static int | ||
78 | rtc_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 | |||
140 | void | ||
141 | rtc_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 | } | ||