diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 15:20:36 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 15:20:36 -0700 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /arch/m68k/sun3x |
Linux-2.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/Makefile | 5 | ||||
-rw-r--r-- | arch/m68k/sun3x/config.c | 99 | ||||
-rw-r--r-- | arch/m68k/sun3x/dvma.c | 208 | ||||
-rw-r--r-- | arch/m68k/sun3x/prom.c | 166 | ||||
-rw-r--r-- | arch/m68k/sun3x/time.c | 103 | ||||
-rw-r--r-- | arch/m68k/sun3x/time.h | 19 |
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 @@ +# +# Makefile for Linux arch/m68k/sun3x source directory +# + +obj-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 @@ +/* + * Setup kernel for a Sun3x machine + * + * (C) 1999 Thomas Bogendoerfer (tsbogend@alpha.franken.de) + * + * based on code from Oliver Jowett <oliver@jowett.manawatu.gen.nz> + */ + +#include <linux/config.h> +#include <linux/types.h> +#include <linux/mm.h> +#include <linux/console.h> +#include <linux/init.h> + +#include <asm/system.h> +#include <asm/machdep.h> +#include <asm/irq.h> +#include <asm/sun3xprom.h> +#include <asm/sun3ints.h> +#include <asm/setup.h> +#include <asm/oplib.h> + +#include "time.h" + +volatile char *clock_va; +extern volatile unsigned char *sun3_intreg; + +extern void sun3_get_model(char *model); + +void sun3_leds(unsigned int i) +{ + +} + +static int sun3x_get_hardware_list(char *buffer) +{ + + int len = 0; + + len += sprintf(buffer + len, "PROM Revision:\t%s\n", + romvec->pv_monid); + + return len; + +} + +/* + * Setup the sun3x configuration info + */ +void __init config_sun3x(void) +{ + + sun3x_prom_init(); + + mach_get_irq_list = show_sun3_interrupts; + mach_max_dma_address = 0xffffffff; /* we can DMA anywhere, whee */ + + mach_default_handler = &sun3_default_handler; + mach_sched_init = sun3x_sched_init; + mach_init_IRQ = sun3_init_IRQ; + enable_irq = sun3_enable_irq; + disable_irq = sun3_disable_irq; + mach_request_irq = sun3_request_irq; + mach_free_irq = sun3_free_irq; + mach_process_int = sun3_process_int; + + mach_gettimeoffset = sun3x_gettimeoffset; + mach_reset = sun3x_reboot; + + mach_hwclk = sun3x_hwclk; + mach_get_model = sun3_get_model; + mach_get_hardware_list = sun3x_get_hardware_list; + +#ifdef CONFIG_DUMMY_CONSOLE + conswitchp = &dummy_con; +#endif + + sun3_intreg = (unsigned char *)SUN3X_INTREG; + + /* only the serial console is known to work anyway... */ +#if 0 + switch (*(unsigned char *)SUN3X_EEPROM_CONS) { + case 0x10: + serial_console = 1; + conswitchp = NULL; + break; + case 0x11: + serial_console = 2; + conswitchp = NULL; + break; + default: + serial_console = 0; + conswitchp = &dummy_con; + break; + } +#endif + +} + 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 @@ +/* + * Virtual DMA allocation + * + * (C) 1999 Thomas Bogendoerfer (tsbogend@alpha.franken.de) + * + * 11/26/2000 -- disabled the existing code because it didn't work for + * me in 2.4. Replaced with a significantly more primitive version + * similar to the sun3 code. the old functionality was probably more + * desirable, but.... -- Sam Creasey (sammy@oh.verio.com) + * + */ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/bitops.h> +#include <linux/mm.h> +#include <linux/bootmem.h> +#include <linux/slab.h> +#include <linux/vmalloc.h> + +#include <asm/sun3x.h> +#include <asm/dvma.h> +#include <asm/io.h> +#include <asm/page.h> +#include <asm/pgtable.h> +#include <asm/pgalloc.h> + +/* IOMMU support */ + +#define IOMMU_ADDR_MASK 0x03ffe000 +#define IOMMU_CACHE_INHIBIT 0x00000040 +#define IOMMU_FULL_BLOCK 0x00000020 +#define IOMMU_MODIFIED 0x00000010 +#define IOMMU_USED 0x00000008 +#define IOMMU_WRITE_PROTECT 0x00000004 +#define IOMMU_DT_MASK 0x00000003 +#define IOMMU_DT_INVALID 0x00000000 +#define IOMMU_DT_VALID 0x00000001 +#define IOMMU_DT_BAD 0x00000002 + + +static volatile unsigned long *iommu_pte = (unsigned long *)SUN3X_IOMMU; + + +#define dvma_entry_paddr(index) (iommu_pte[index] & IOMMU_ADDR_MASK) +#define dvma_entry_vaddr(index,paddr) ((index << DVMA_PAGE_SHIFT) | \ + (paddr & (DVMA_PAGE_SIZE-1))) +#if 0 +#define dvma_entry_set(index,addr) (iommu_pte[index] = \ + (addr & IOMMU_ADDR_MASK) | \ + IOMMU_DT_VALID | IOMMU_CACHE_INHIBIT) +#else +#define dvma_entry_set(index,addr) (iommu_pte[index] = \ + (addr & IOMMU_ADDR_MASK) | \ + IOMMU_DT_VALID) +#endif +#define dvma_entry_clr(index) (iommu_pte[index] = IOMMU_DT_INVALID) +#define dvma_entry_hash(addr) ((addr >> DVMA_PAGE_SHIFT) ^ \ + ((addr & 0x03c00000) >> \ + (DVMA_PAGE_SHIFT+4))) + +#undef DEBUG + +#ifdef DEBUG +/* code to print out a dvma mapping for debugging purposes */ +void dvma_print (unsigned long dvma_addr) +{ + + unsigned long index; + + index = dvma_addr >> DVMA_PAGE_SHIFT; + + printk("idx %lx dvma_addr %08lx paddr %08lx\n", index, dvma_addr, + dvma_entry_paddr(index)); + + +} +#endif + + +/* create a virtual mapping for a page assigned within the IOMMU + so that the cpu can reach it easily */ +inline int dvma_map_cpu(unsigned long kaddr, + unsigned long vaddr, int len) +{ + pgd_t *pgd; + unsigned long end; + int ret = 0; + + kaddr &= PAGE_MASK; + vaddr &= PAGE_MASK; + + end = PAGE_ALIGN(vaddr + len); + +#ifdef DEBUG + printk("dvma: mapping kern %08lx to virt %08lx\n", + kaddr, vaddr); +#endif + pgd = pgd_offset_k(vaddr); + + do { + pmd_t *pmd; + unsigned long end2; + + if((pmd = pmd_alloc(&init_mm, pgd, vaddr)) == NULL) { + ret = -ENOMEM; + goto out; + } + + if((end & PGDIR_MASK) > (vaddr & PGDIR_MASK)) + end2 = (vaddr + (PGDIR_SIZE-1)) & PGDIR_MASK; + else + end2 = end; + + do { + pte_t *pte; + unsigned long end3; + + if((pte = pte_alloc_kernel(&init_mm, pmd, vaddr)) == NULL) { + ret = -ENOMEM; + goto out; + } + + if((end2 & PMD_MASK) > (vaddr & PMD_MASK)) + end3 = (vaddr + (PMD_SIZE-1)) & PMD_MASK; + else + end3 = end2; + + do { +#ifdef DEBUG + printk("mapping %08lx phys to %08lx\n", + __pa(kaddr), vaddr); +#endif + set_pte(pte, pfn_pte(virt_to_pfn(kaddr), + PAGE_KERNEL)); + pte++; + kaddr += PAGE_SIZE; + vaddr += PAGE_SIZE; + } while(vaddr < end3); + + } while(vaddr < end2); + + } while(vaddr < end); + + flush_tlb_all(); + + out: + return ret; +} + + +inline int dvma_map_iommu(unsigned long kaddr, unsigned long baddr, + int len) +{ + unsigned long end, index; + + index = baddr >> DVMA_PAGE_SHIFT; + end = ((baddr+len) >> DVMA_PAGE_SHIFT); + + if(len & ~DVMA_PAGE_MASK) + end++; + + for(; index < end ; index++) { +// if(dvma_entry_use(index)) +// BUG(); +// printk("mapping pa %lx to ba %lx\n", __pa(kaddr), index << DVMA_PAGE_SHIFT); + + dvma_entry_set(index, __pa(kaddr)); + + iommu_pte[index] |= IOMMU_FULL_BLOCK; +// dvma_entry_inc(index); + + kaddr += DVMA_PAGE_SIZE; + } + +#ifdef DEBUG + for(index = (baddr >> DVMA_PAGE_SHIFT); index < end; index++) + dvma_print(index << DVMA_PAGE_SHIFT); +#endif + return 0; + +} + +void dvma_unmap_iommu(unsigned long baddr, int len) +{ + + int index, end; + + + index = baddr >> DVMA_PAGE_SHIFT; + end = (DVMA_PAGE_ALIGN(baddr+len) >> DVMA_PAGE_SHIFT); + + for(; index < end ; index++) { +#ifdef DEBUG + printk("freeing bus mapping %08x\n", index << DVMA_PAGE_SHIFT); +#endif +#if 0 + if(!dvma_entry_use(index)) + printk("dvma_unmap freeing unused entry %04x\n", + index); + else + dvma_entry_dec(index); +#endif + dvma_entry_clr(index); + } + +} + 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 @@ +/* Prom access routines for the sun3x */ + +#include <linux/types.h> +#include <linux/kernel.h> +#include <linux/tty.h> +#include <linux/console.h> +#include <linux/init.h> +#include <linux/mm.h> +#include <linux/string.h> + +#include <asm/page.h> +#include <asm/pgtable.h> +#include <asm/bootinfo.h> +#include <asm/setup.h> +#include <asm/traps.h> +#include <asm/sun3xprom.h> +#include <asm/idprom.h> +#include <asm/segment.h> +#include <asm/sun3ints.h> +#include <asm/openprom.h> +#include <asm/machines.h> + +void (*sun3x_putchar)(int); +int (*sun3x_getchar)(void); +int (*sun3x_mayget)(void); +int (*sun3x_mayput)(int); +void (*sun3x_prom_reboot)(void); +e_vector sun3x_prom_abort; +struct linux_romvec *romvec; + +/* prom vector table */ +e_vector *sun3x_prom_vbr; + +/* Handle returning to the prom */ +void sun3x_halt(void) +{ + unsigned long flags; + + /* Disable interrupts while we mess with things */ + local_irq_save(flags); + + /* Restore prom vbr */ + __asm__ volatile ("movec %0,%%vbr" : : "r" ((void*)sun3x_prom_vbr)); + + /* Restore prom NMI clock */ +// sun3x_disable_intreg(5); + sun3_enable_irq(7); + + /* Let 'er rip */ + __asm__ volatile ("trap #14" : : ); + + /* Restore everything */ + sun3_disable_irq(7); + sun3_enable_irq(5); + + __asm__ volatile ("movec %0,%%vbr" : : "r" ((void*)vectors)); + local_irq_restore(flags); +} + +void sun3x_reboot(void) +{ + /* This never returns, don't bother saving things */ + local_irq_disable(); + + /* Restore prom vbr */ + __asm__ volatile ("movec %0,%%vbr" : : "r" ((void*)sun3x_prom_vbr)); + + /* Restore prom NMI clock */ + sun3_disable_irq(5); + sun3_enable_irq(7); + + /* Let 'er rip */ + (*romvec->pv_reboot)("vmlinux"); +} + +extern char m68k_debug_device[]; + +static void sun3x_prom_write(struct console *co, const char *s, + unsigned int count) +{ + while (count--) { + if (*s == '\n') + sun3x_putchar('\r'); + sun3x_putchar(*s++); + } +} + +/* debug console - write-only */ + +static struct console sun3x_debug = { + .name = "debug", + .write = sun3x_prom_write, + .flags = CON_PRINTBUFFER, + .index = -1, +}; + +void sun3x_prom_init(void) +{ + /* Read the vector table */ + + sun3x_putchar = *(void (**)(int)) (SUN3X_P_PUTCHAR); + sun3x_getchar = *(int (**)(void)) (SUN3X_P_GETCHAR); + sun3x_mayget = *(int (**)(void)) (SUN3X_P_MAYGET); + sun3x_mayput = *(int (**)(int)) (SUN3X_P_MAYPUT); + sun3x_prom_reboot = *(void (**)(void)) (SUN3X_P_REBOOT); + sun3x_prom_abort = *(e_vector *) (SUN3X_P_ABORT); + romvec = (struct linux_romvec *)SUN3X_PROM_BASE; + + idprom_init(); + + if(!((idprom->id_machtype & SM_ARCH_MASK) == SM_SUN3X)) { + printk("Warning: machine reports strange type %02x\n", + idprom->id_machtype); + printk("Pretending it's a 3/80, but very afraid...\n"); + idprom->id_machtype = SM_SUN3X | SM_3_80; + } + + /* point trap #14 at abort. + * XXX this is futile since we restore the vbr first - oops + */ + vectors[VEC_TRAP14] = sun3x_prom_abort; + + /* If debug=prom was specified, start the debug console */ + + if (!strcmp(m68k_debug_device, "prom")) + register_console(&sun3x_debug); + + +} + +/* some prom functions to export */ +int prom_getintdefault(int node, char *property, int deflt) +{ + return deflt; +} + +int prom_getbool (int node, char *prop) +{ + return 1; +} + +void prom_printf(char *fmt, ...) +{ + +} + +void prom_halt (void) +{ + sun3x_halt(); +} + +/* Get the idprom and stuff it into buffer 'idbuf'. Returns the + * format type. 'num_bytes' is the number of bytes that your idbuf + * has space for. Returns 0xff on error. + */ +unsigned char +prom_get_idprom(char *idbuf, int num_bytes) +{ + int i; + + /* make a copy of the idprom structure */ + for(i = 0; i < num_bytes; i++) + idbuf[i] = ((char *)SUN3X_IDPROM)[i]; + + return idbuf[0]; +} 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 @@ +/* + * linux/arch/m68k/sun3x/time.c + * + * Sun3x-specific time handling + */ + +#include <linux/types.h> +#include <linux/kd.h> +#include <linux/init.h> +#include <linux/sched.h> +#include <linux/kernel_stat.h> +#include <linux/interrupt.h> +#include <linux/rtc.h> +#include <linux/bcd.h> + +#include <asm/irq.h> +#include <asm/io.h> +#include <asm/system.h> +#include <asm/traps.h> +#include <asm/sun3x.h> +#include <asm/sun3ints.h> +#include <asm/rtc.h> + +#include "time.h" + +#define M_CONTROL 0xf8 +#define M_SEC 0xf9 +#define M_MIN 0xfa +#define M_HOUR 0xfb +#define M_DAY 0xfc +#define M_DATE 0xfd +#define M_MONTH 0xfe +#define M_YEAR 0xff + +#define C_WRITE 0x80 +#define C_READ 0x40 +#define C_SIGN 0x20 +#define C_CALIB 0x1f + +int sun3x_hwclk(int set, struct rtc_time *t) +{ + volatile struct mostek_dt *h = + (struct mostek_dt *)(SUN3X_EEPROM+M_CONTROL); + unsigned long flags; + + local_irq_save(flags); + + if(set) { + h->csr |= C_WRITE; + h->sec = BIN2BCD(t->tm_sec); + h->min = BIN2BCD(t->tm_min); + h->hour = BIN2BCD(t->tm_hour); + h->wday = BIN2BCD(t->tm_wday); + h->mday = BIN2BCD(t->tm_mday); + h->month = BIN2BCD(t->tm_mon); + h->year = BIN2BCD(t->tm_year); + h->csr &= ~C_WRITE; + } else { + h->csr |= C_READ; + t->tm_sec = BCD2BIN(h->sec); + t->tm_min = BCD2BIN(h->min); + t->tm_hour = BCD2BIN(h->hour); + t->tm_wday = BCD2BIN(h->wday); + t->tm_mday = BCD2BIN(h->mday); + t->tm_mon = BCD2BIN(h->month); + t->tm_year = BCD2BIN(h->year); + h->csr &= ~C_READ; + } + + local_irq_restore(flags); + + return 0; +} +/* Not much we can do here */ +unsigned long sun3x_gettimeoffset (void) +{ + return 0L; +} + +#if 0 +static void sun3x_timer_tick(int irq, void *dev_id, struct pt_regs *regs) +{ + void (*vector)(int, void *, struct pt_regs *) = dev_id; + + /* Clear the pending interrupt - pulse the enable line low */ + disable_irq(5); + enable_irq(5); + + vector(irq, NULL, regs); +} +#endif + +void __init sun3x_sched_init(irqreturn_t (*vector)(int, void *, struct pt_regs *)) +{ + + sun3_disable_interrupts(); + + + /* Pulse enable low to get the clock started */ + sun3_disable_irq(5); + sun3_enable_irq(5); + sun3_enable_interrupts(); +} 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 @@ +#ifndef SUN3X_TIME_H +#define SUN3X_TIME_H + +extern int sun3x_hwclk(int set, struct rtc_time *t); +unsigned long sun3x_gettimeoffset (void); +void sun3x_sched_init(irqreturn_t (*vector)(int, void *, struct pt_regs *)); + +struct mostek_dt { + volatile unsigned char csr; + volatile unsigned char sec; + volatile unsigned char min; + volatile unsigned char hour; + volatile unsigned char wday; + volatile unsigned char mday; + volatile unsigned char month; + volatile unsigned char year; +}; + +#endif |