aboutsummaryrefslogtreecommitdiffstats
path: root/arch/m68k/sun3x
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/m68k/sun3x
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/m68k/sun3x')
-rw-r--r--arch/m68k/sun3x/Makefile5
-rw-r--r--arch/m68k/sun3x/config.c99
-rw-r--r--arch/m68k/sun3x/dvma.c208
-rw-r--r--arch/m68k/sun3x/prom.c166
-rw-r--r--arch/m68k/sun3x/time.c103
-rw-r--r--arch/m68k/sun3x/time.h19
6 files changed, 600 insertions, 0 deletions
diff --git a/arch/m68k/sun3x/Makefile b/arch/m68k/sun3x/Makefile
new file mode 100644
index 000000000000..be5776d9a01e
--- /dev/null
+++ b/arch/m68k/sun3x/Makefile
@@ -0,0 +1,5 @@
1#
2# Makefile for Linux arch/m68k/sun3x source directory
3#
4
5obj-y := config.o time.o dvma.o prom.o
diff --git a/arch/m68k/sun3x/config.c b/arch/m68k/sun3x/config.c
new file mode 100644
index 000000000000..0ef547f5494d
--- /dev/null
+++ b/arch/m68k/sun3x/config.c
@@ -0,0 +1,99 @@
1/*
2 * Setup kernel for a Sun3x machine
3 *
4 * (C) 1999 Thomas Bogendoerfer (tsbogend@alpha.franken.de)
5 *
6 * based on code from Oliver Jowett <oliver@jowett.manawatu.gen.nz>
7 */
8
9#include <linux/config.h>
10#include <linux/types.h>
11#include <linux/mm.h>
12#include <linux/console.h>
13#include <linux/init.h>
14
15#include <asm/system.h>
16#include <asm/machdep.h>
17#include <asm/irq.h>
18#include <asm/sun3xprom.h>
19#include <asm/sun3ints.h>
20#include <asm/setup.h>
21#include <asm/oplib.h>
22
23#include "time.h"
24
25volatile char *clock_va;
26extern volatile unsigned char *sun3_intreg;
27
28extern void sun3_get_model(char *model);
29
30void sun3_leds(unsigned int i)
31{
32
33}
34
35static int sun3x_get_hardware_list(char *buffer)
36{
37
38 int len = 0;
39
40 len += sprintf(buffer + len, "PROM Revision:\t%s\n",
41 romvec->pv_monid);
42
43 return len;
44
45}
46
47/*
48 * Setup the sun3x configuration info
49 */
50void __init config_sun3x(void)
51{
52
53 sun3x_prom_init();
54
55 mach_get_irq_list = show_sun3_interrupts;
56 mach_max_dma_address = 0xffffffff; /* we can DMA anywhere, whee */
57
58 mach_default_handler = &sun3_default_handler;
59 mach_sched_init = sun3x_sched_init;
60 mach_init_IRQ = sun3_init_IRQ;
61 enable_irq = sun3_enable_irq;
62 disable_irq = sun3_disable_irq;
63 mach_request_irq = sun3_request_irq;
64 mach_free_irq = sun3_free_irq;
65 mach_process_int = sun3_process_int;
66
67 mach_gettimeoffset = sun3x_gettimeoffset;
68 mach_reset = sun3x_reboot;
69
70 mach_hwclk = sun3x_hwclk;
71 mach_get_model = sun3_get_model;
72 mach_get_hardware_list = sun3x_get_hardware_list;
73
74#ifdef CONFIG_DUMMY_CONSOLE
75 conswitchp = &dummy_con;
76#endif
77
78 sun3_intreg = (unsigned char *)SUN3X_INTREG;
79
80 /* only the serial console is known to work anyway... */
81#if 0
82 switch (*(unsigned char *)SUN3X_EEPROM_CONS) {
83 case 0x10:
84 serial_console = 1;
85 conswitchp = NULL;
86 break;
87 case 0x11:
88 serial_console = 2;
89 conswitchp = NULL;
90 break;
91 default:
92 serial_console = 0;
93 conswitchp = &dummy_con;
94 break;
95 }
96#endif
97
98}
99
diff --git a/arch/m68k/sun3x/dvma.c b/arch/m68k/sun3x/dvma.c
new file mode 100644
index 000000000000..32e55adfeb8e
--- /dev/null
+++ b/arch/m68k/sun3x/dvma.c
@@ -0,0 +1,208 @@
1/*
2 * Virtual DMA allocation
3 *
4 * (C) 1999 Thomas Bogendoerfer (tsbogend@alpha.franken.de)
5 *
6 * 11/26/2000 -- disabled the existing code because it didn't work for
7 * me in 2.4. Replaced with a significantly more primitive version
8 * similar to the sun3 code. the old functionality was probably more
9 * desirable, but.... -- Sam Creasey (sammy@oh.verio.com)
10 *
11 */
12
13#include <linux/kernel.h>
14#include <linux/init.h>
15#include <linux/bitops.h>
16#include <linux/mm.h>
17#include <linux/bootmem.h>
18#include <linux/slab.h>
19#include <linux/vmalloc.h>
20
21#include <asm/sun3x.h>
22#include <asm/dvma.h>
23#include <asm/io.h>
24#include <asm/page.h>
25#include <asm/pgtable.h>
26#include <asm/pgalloc.h>
27
28/* IOMMU support */
29
30#define IOMMU_ADDR_MASK 0x03ffe000
31#define IOMMU_CACHE_INHIBIT 0x00000040
32#define IOMMU_FULL_BLOCK 0x00000020
33#define IOMMU_MODIFIED 0x00000010
34#define IOMMU_USED 0x00000008
35#define IOMMU_WRITE_PROTECT 0x00000004
36#define IOMMU_DT_MASK 0x00000003
37#define IOMMU_DT_INVALID 0x00000000
38#define IOMMU_DT_VALID 0x00000001
39#define IOMMU_DT_BAD 0x00000002
40
41
42static volatile unsigned long *iommu_pte = (unsigned long *)SUN3X_IOMMU;
43
44
45#define dvma_entry_paddr(index) (iommu_pte[index] & IOMMU_ADDR_MASK)
46#define dvma_entry_vaddr(index,paddr) ((index << DVMA_PAGE_SHIFT) | \
47 (paddr & (DVMA_PAGE_SIZE-1)))
48#if 0
49#define dvma_entry_set(index,addr) (iommu_pte[index] = \
50 (addr & IOMMU_ADDR_MASK) | \
51 IOMMU_DT_VALID | IOMMU_CACHE_INHIBIT)
52#else
53#define dvma_entry_set(index,addr) (iommu_pte[index] = \
54 (addr & IOMMU_ADDR_MASK) | \
55 IOMMU_DT_VALID)
56#endif
57#define dvma_entry_clr(index) (iommu_pte[index] = IOMMU_DT_INVALID)
58#define dvma_entry_hash(addr) ((addr >> DVMA_PAGE_SHIFT) ^ \
59 ((addr & 0x03c00000) >> \
60 (DVMA_PAGE_SHIFT+4)))
61
62#undef DEBUG
63
64#ifdef DEBUG
65/* code to print out a dvma mapping for debugging purposes */
66void dvma_print (unsigned long dvma_addr)
67{
68
69 unsigned long index;
70
71 index = dvma_addr >> DVMA_PAGE_SHIFT;
72
73 printk("idx %lx dvma_addr %08lx paddr %08lx\n", index, dvma_addr,
74 dvma_entry_paddr(index));
75
76
77}
78#endif
79
80
81/* create a virtual mapping for a page assigned within the IOMMU
82 so that the cpu can reach it easily */
83inline int dvma_map_cpu(unsigned long kaddr,
84 unsigned long vaddr, int len)
85{
86 pgd_t *pgd;
87 unsigned long end;
88 int ret = 0;
89
90 kaddr &= PAGE_MASK;
91 vaddr &= PAGE_MASK;
92
93 end = PAGE_ALIGN(vaddr + len);
94
95#ifdef DEBUG
96 printk("dvma: mapping kern %08lx to virt %08lx\n",
97 kaddr, vaddr);
98#endif
99 pgd = pgd_offset_k(vaddr);
100
101 do {
102 pmd_t *pmd;
103 unsigned long end2;
104
105 if((pmd = pmd_alloc(&init_mm, pgd, vaddr)) == NULL) {
106 ret = -ENOMEM;
107 goto out;
108 }
109
110 if((end & PGDIR_MASK) > (vaddr & PGDIR_MASK))
111 end2 = (vaddr + (PGDIR_SIZE-1)) & PGDIR_MASK;
112 else
113 end2 = end;
114
115 do {
116 pte_t *pte;
117 unsigned long end3;
118
119 if((pte = pte_alloc_kernel(&init_mm, pmd, vaddr)) == NULL) {
120 ret = -ENOMEM;
121 goto out;
122 }
123
124 if((end2 & PMD_MASK) > (vaddr & PMD_MASK))
125 end3 = (vaddr + (PMD_SIZE-1)) & PMD_MASK;
126 else
127 end3 = end2;
128
129 do {
130#ifdef DEBUG
131 printk("mapping %08lx phys to %08lx\n",
132 __pa(kaddr), vaddr);
133#endif
134 set_pte(pte, pfn_pte(virt_to_pfn(kaddr),
135 PAGE_KERNEL));
136 pte++;
137 kaddr += PAGE_SIZE;
138 vaddr += PAGE_SIZE;
139 } while(vaddr < end3);
140
141 } while(vaddr < end2);
142
143 } while(vaddr < end);
144
145 flush_tlb_all();
146
147 out:
148 return ret;
149}
150
151
152inline int dvma_map_iommu(unsigned long kaddr, unsigned long baddr,
153 int len)
154{
155 unsigned long end, index;
156
157 index = baddr >> DVMA_PAGE_SHIFT;
158 end = ((baddr+len) >> DVMA_PAGE_SHIFT);
159
160 if(len & ~DVMA_PAGE_MASK)
161 end++;
162
163 for(; index < end ; index++) {
164// if(dvma_entry_use(index))
165// BUG();
166// printk("mapping pa %lx to ba %lx\n", __pa(kaddr), index << DVMA_PAGE_SHIFT);
167
168 dvma_entry_set(index, __pa(kaddr));
169
170 iommu_pte[index] |= IOMMU_FULL_BLOCK;
171// dvma_entry_inc(index);
172
173 kaddr += DVMA_PAGE_SIZE;
174 }
175
176#ifdef DEBUG
177 for(index = (baddr >> DVMA_PAGE_SHIFT); index < end; index++)
178 dvma_print(index << DVMA_PAGE_SHIFT);
179#endif
180 return 0;
181
182}
183
184void dvma_unmap_iommu(unsigned long baddr, int len)
185{
186
187 int index, end;
188
189
190 index = baddr >> DVMA_PAGE_SHIFT;
191 end = (DVMA_PAGE_ALIGN(baddr+len) >> DVMA_PAGE_SHIFT);
192
193 for(; index < end ; index++) {
194#ifdef DEBUG
195 printk("freeing bus mapping %08x\n", index << DVMA_PAGE_SHIFT);
196#endif
197#if 0
198 if(!dvma_entry_use(index))
199 printk("dvma_unmap freeing unused entry %04x\n",
200 index);
201 else
202 dvma_entry_dec(index);
203#endif
204 dvma_entry_clr(index);
205 }
206
207}
208
diff --git a/arch/m68k/sun3x/prom.c b/arch/m68k/sun3x/prom.c
new file mode 100644
index 000000000000..574cf06df9e4
--- /dev/null
+++ b/arch/m68k/sun3x/prom.c
@@ -0,0 +1,166 @@
1/* Prom access routines for the sun3x */
2
3#include <linux/types.h>
4#include <linux/kernel.h>
5#include <linux/tty.h>
6#include <linux/console.h>
7#include <linux/init.h>
8#include <linux/mm.h>
9#include <linux/string.h>
10
11#include <asm/page.h>
12#include <asm/pgtable.h>
13#include <asm/bootinfo.h>
14#include <asm/setup.h>
15#include <asm/traps.h>
16#include <asm/sun3xprom.h>
17#include <asm/idprom.h>
18#include <asm/segment.h>
19#include <asm/sun3ints.h>
20#include <asm/openprom.h>
21#include <asm/machines.h>
22
23void (*sun3x_putchar)(int);
24int (*sun3x_getchar)(void);
25int (*sun3x_mayget)(void);
26int (*sun3x_mayput)(int);
27void (*sun3x_prom_reboot)(void);
28e_vector sun3x_prom_abort;
29struct linux_romvec *romvec;
30
31/* prom vector table */
32e_vector *sun3x_prom_vbr;
33
34/* Handle returning to the prom */
35void sun3x_halt(void)
36{
37 unsigned long flags;
38
39 /* Disable interrupts while we mess with things */
40 local_irq_save(flags);
41
42 /* Restore prom vbr */
43 __asm__ volatile ("movec %0,%%vbr" : : "r" ((void*)sun3x_prom_vbr));
44
45 /* Restore prom NMI clock */
46// sun3x_disable_intreg(5);
47 sun3_enable_irq(7);
48
49 /* Let 'er rip */
50 __asm__ volatile ("trap #14" : : );
51
52 /* Restore everything */
53 sun3_disable_irq(7);
54 sun3_enable_irq(5);
55
56 __asm__ volatile ("movec %0,%%vbr" : : "r" ((void*)vectors));
57 local_irq_restore(flags);
58}
59
60void sun3x_reboot(void)
61{
62 /* This never returns, don't bother saving things */
63 local_irq_disable();
64
65 /* Restore prom vbr */
66 __asm__ volatile ("movec %0,%%vbr" : : "r" ((void*)sun3x_prom_vbr));
67
68 /* Restore prom NMI clock */
69 sun3_disable_irq(5);
70 sun3_enable_irq(7);
71
72 /* Let 'er rip */
73 (*romvec->pv_reboot)("vmlinux");
74}
75
76extern char m68k_debug_device[];
77
78static void sun3x_prom_write(struct console *co, const char *s,
79 unsigned int count)
80{
81 while (count--) {
82 if (*s == '\n')
83 sun3x_putchar('\r');
84 sun3x_putchar(*s++);
85 }
86}
87
88/* debug console - write-only */
89
90static struct console sun3x_debug = {
91 .name = "debug",
92 .write = sun3x_prom_write,
93 .flags = CON_PRINTBUFFER,
94 .index = -1,
95};
96
97void sun3x_prom_init(void)
98{
99 /* Read the vector table */
100
101 sun3x_putchar = *(void (**)(int)) (SUN3X_P_PUTCHAR);
102 sun3x_getchar = *(int (**)(void)) (SUN3X_P_GETCHAR);
103 sun3x_mayget = *(int (**)(void)) (SUN3X_P_MAYGET);
104 sun3x_mayput = *(int (**)(int)) (SUN3X_P_MAYPUT);
105 sun3x_prom_reboot = *(void (**)(void)) (SUN3X_P_REBOOT);
106 sun3x_prom_abort = *(e_vector *) (SUN3X_P_ABORT);
107 romvec = (struct linux_romvec *)SUN3X_PROM_BASE;
108
109 idprom_init();
110
111 if(!((idprom->id_machtype & SM_ARCH_MASK) == SM_SUN3X)) {
112 printk("Warning: machine reports strange type %02x\n",
113 idprom->id_machtype);
114 printk("Pretending it's a 3/80, but very afraid...\n");
115 idprom->id_machtype = SM_SUN3X | SM_3_80;
116 }
117
118 /* point trap #14 at abort.
119 * XXX this is futile since we restore the vbr first - oops
120 */
121 vectors[VEC_TRAP14] = sun3x_prom_abort;
122
123 /* If debug=prom was specified, start the debug console */
124
125 if (!strcmp(m68k_debug_device, "prom"))
126 register_console(&sun3x_debug);
127
128
129}
130
131/* some prom functions to export */
132int prom_getintdefault(int node, char *property, int deflt)
133{
134 return deflt;
135}
136
137int prom_getbool (int node, char *prop)
138{
139 return 1;
140}
141
142void prom_printf(char *fmt, ...)
143{
144
145}
146
147void prom_halt (void)
148{
149 sun3x_halt();
150}
151
152/* Get the idprom and stuff it into buffer 'idbuf'. Returns the
153 * format type. 'num_bytes' is the number of bytes that your idbuf
154 * has space for. Returns 0xff on error.
155 */
156unsigned char
157prom_get_idprom(char *idbuf, int num_bytes)
158{
159 int i;
160
161 /* make a copy of the idprom structure */
162 for(i = 0; i < num_bytes; i++)
163 idbuf[i] = ((char *)SUN3X_IDPROM)[i];
164
165 return idbuf[0];
166}
diff --git a/arch/m68k/sun3x/time.c b/arch/m68k/sun3x/time.c
new file mode 100644
index 000000000000..6f4204fbecd7
--- /dev/null
+++ b/arch/m68k/sun3x/time.c
@@ -0,0 +1,103 @@
1/*
2 * linux/arch/m68k/sun3x/time.c
3 *
4 * Sun3x-specific time handling
5 */
6
7#include <linux/types.h>
8#include <linux/kd.h>
9#include <linux/init.h>
10#include <linux/sched.h>
11#include <linux/kernel_stat.h>
12#include <linux/interrupt.h>
13#include <linux/rtc.h>
14#include <linux/bcd.h>
15
16#include <asm/irq.h>
17#include <asm/io.h>
18#include <asm/system.h>
19#include <asm/traps.h>
20#include <asm/sun3x.h>
21#include <asm/sun3ints.h>
22#include <asm/rtc.h>
23
24#include "time.h"
25
26#define M_CONTROL 0xf8
27#define M_SEC 0xf9
28#define M_MIN 0xfa
29#define M_HOUR 0xfb
30#define M_DAY 0xfc
31#define M_DATE 0xfd
32#define M_MONTH 0xfe
33#define M_YEAR 0xff
34
35#define C_WRITE 0x80
36#define C_READ 0x40
37#define C_SIGN 0x20
38#define C_CALIB 0x1f
39
40int sun3x_hwclk(int set, struct rtc_time *t)
41{
42 volatile struct mostek_dt *h =
43 (struct mostek_dt *)(SUN3X_EEPROM+M_CONTROL);
44 unsigned long flags;
45
46 local_irq_save(flags);
47
48 if(set) {
49 h->csr |= C_WRITE;
50 h->sec = BIN2BCD(t->tm_sec);
51 h->min = BIN2BCD(t->tm_min);
52 h->hour = BIN2BCD(t->tm_hour);
53 h->wday = BIN2BCD(t->tm_wday);
54 h->mday = BIN2BCD(t->tm_mday);
55 h->month = BIN2BCD(t->tm_mon);
56 h->year = BIN2BCD(t->tm_year);
57 h->csr &= ~C_WRITE;
58 } else {
59 h->csr |= C_READ;
60 t->tm_sec = BCD2BIN(h->sec);
61 t->tm_min = BCD2BIN(h->min);
62 t->tm_hour = BCD2BIN(h->hour);
63 t->tm_wday = BCD2BIN(h->wday);
64 t->tm_mday = BCD2BIN(h->mday);
65 t->tm_mon = BCD2BIN(h->month);
66 t->tm_year = BCD2BIN(h->year);
67 h->csr &= ~C_READ;
68 }
69
70 local_irq_restore(flags);
71
72 return 0;
73}
74/* Not much we can do here */
75unsigned long sun3x_gettimeoffset (void)
76{
77 return 0L;
78}
79
80#if 0
81static void sun3x_timer_tick(int irq, void *dev_id, struct pt_regs *regs)
82{
83 void (*vector)(int, void *, struct pt_regs *) = dev_id;
84
85 /* Clear the pending interrupt - pulse the enable line low */
86 disable_irq(5);
87 enable_irq(5);
88
89 vector(irq, NULL, regs);
90}
91#endif
92
93void __init sun3x_sched_init(irqreturn_t (*vector)(int, void *, struct pt_regs *))
94{
95
96 sun3_disable_interrupts();
97
98
99 /* Pulse enable low to get the clock started */
100 sun3_disable_irq(5);
101 sun3_enable_irq(5);
102 sun3_enable_interrupts();
103}
diff --git a/arch/m68k/sun3x/time.h b/arch/m68k/sun3x/time.h
new file mode 100644
index 000000000000..e7e43b4ec4a1
--- /dev/null
+++ b/arch/m68k/sun3x/time.h
@@ -0,0 +1,19 @@
1#ifndef SUN3X_TIME_H
2#define SUN3X_TIME_H
3
4extern int sun3x_hwclk(int set, struct rtc_time *t);
5unsigned long sun3x_gettimeoffset (void);
6void sun3x_sched_init(irqreturn_t (*vector)(int, void *, struct pt_regs *));
7
8struct mostek_dt {
9 volatile unsigned char csr;
10 volatile unsigned char sec;
11 volatile unsigned char min;
12 volatile unsigned char hour;
13 volatile unsigned char wday;
14 volatile unsigned char mday;
15 volatile unsigned char month;
16 volatile unsigned char year;
17};
18
19#endif