diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1999-06-13 16:29:25 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 1999-06-13 16:29:25 +0000 |
commit | db7d4daea91e105e3859cf461d7e53b9b77454b2 (patch) | |
tree | 9bb65b95440af09e8aca63abe56970dd3360cc57 /arch/m68k/sun3x | |
parent | 9c1c01ead627bdda9211c9abd5b758d6c687d8ac (diff) |
Merge with Linux 2.2.8.
Diffstat (limited to 'arch/m68k/sun3x')
-rw-r--r-- | arch/m68k/sun3x/Makefile | 14 | ||||
-rw-r--r-- | arch/m68k/sun3x/config.c | 128 | ||||
-rw-r--r-- | arch/m68k/sun3x/dvma.c | 162 | ||||
-rw-r--r-- | arch/m68k/sun3x/sbus.c | 44 | ||||
-rw-r--r-- | arch/m68k/sun3x/time.c | 83 | ||||
-rw-r--r-- | arch/m68k/sun3x/time.h | 9 |
6 files changed, 440 insertions, 0 deletions
diff --git a/arch/m68k/sun3x/Makefile b/arch/m68k/sun3x/Makefile new file mode 100644 index 000000000..ba1f2bbd5 --- /dev/null +++ b/arch/m68k/sun3x/Makefile @@ -0,0 +1,14 @@ +# +# Makefile for Linux arch/m68k/sun3x source directory +# +# Note! Dependencies are done automagically by 'make dep', which also +# removes any old dependencies. DON'T put your own dependencies here +# unless it's something special (ie not a .c file). +# +# Note 2! The CFLAGS definitions are now in the main makefile... + +O_TARGET := sun3x.o +O_OBJS := config.o time.o dvma.o sbus.o +OX_OBJS := + +include $(TOPDIR)/Rules.make diff --git a/arch/m68k/sun3x/config.c b/arch/m68k/sun3x/config.c new file mode 100644 index 000000000..5054cd888 --- /dev/null +++ b/arch/m68k/sun3x/config.c @@ -0,0 +1,128 @@ +/* + * 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/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/sun3x.h> + +#include "time.h" + +static volatile unsigned char *sun3x_intreg = (unsigned char *)SUN3X_INTREG; +extern int serial_console; + +void sun3x_halt(void) +{ + /* Disable interrupts */ + cli(); + + /* we can't drop back to PROM, so we loop here */ + for (;;); +} + +void sun3x_reboot(void) +{ + /* This never returns, don't bother saving things */ + cli(); + + /* no idea, whether this works */ + asm ("reset"); +} + +__initfunc(int sun3x_keyb_init(void)) +{ + return 0; +} + +int sun3x_kbdrate(struct kbd_repeat *r) +{ + return 0; +} + +void sun3x_kbd_leds(unsigned int i) +{ + +} + +static void sun3x_badint (int irq, void *dev_id, struct pt_regs *fp) +{ + printk ("received spurious interrupt %d\n",irq); + num_spurious += 1; +} + +void (*sun3x_default_handler[SYS_IRQS])(int, void *, struct pt_regs *) = { + sun3x_badint, sun3x_badint, sun3x_badint, sun3x_badint, + sun3x_badint, sun3x_badint, sun3x_badint, sun3x_badint +}; + +void sun3x_enable_irq(unsigned int irq) +{ + *sun3x_intreg |= (1 << irq); +} + +void sun3x_disable_irq(unsigned int irq) +{ + *sun3x_intreg &= ~(1 << irq); +} + +__initfunc(void sun3x_init_IRQ(void)) +{ + /* disable all interrupts initially */ + *sun3x_intreg = 1; /* master enable only */ +} + +int sun3x_get_irq_list(char *buf) +{ + return 0; +} + +/* + * Setup the sun3x configuration info + */ +__initfunc(void config_sun3x(void)) +{ + mach_get_irq_list = sun3x_get_irq_list; + mach_max_dma_address = 0xffffffff; /* we can DMA anywhere, whee */ + + mach_keyb_init = sun3x_keyb_init; + mach_kbdrate = sun3x_kbdrate; + mach_kbd_leds = sun3x_kbd_leds; + + mach_sched_init = sun3x_sched_init; + mach_init_IRQ = sun3x_init_IRQ; + enable_irq = sun3x_enable_irq; + disable_irq = sun3x_disable_irq; + mach_request_irq = sys_request_irq; + mach_free_irq = sys_free_irq; + mach_default_handler = &sun3x_default_handler; + mach_gettimeoffset = sun3x_gettimeoffset; + mach_reset = sun3x_reboot; + + mach_gettod = sun3x_gettod; + + 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; + } + +} diff --git a/arch/m68k/sun3x/dvma.c b/arch/m68k/sun3x/dvma.c new file mode 100644 index 000000000..9ef3471a2 --- /dev/null +++ b/arch/m68k/sun3x/dvma.c @@ -0,0 +1,162 @@ +/* + * Virtual DMA allocation + * + * (C) 1999 Thomas Bogendoerfer (tsbogend@alpha.franken.de) + */ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/bitops.h> +#include <linux/mm.h> + +#include <asm/sun3x.h> +#include <asm/dvma.h> +#include <asm/io.h> +#include <asm/page.h> + +/* IOMMU support */ + +#define IOMMU_ENTRIES 2048 +#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 + +#define DVMA_PAGE_SHIFT 13 +#define DVMA_PAGE_SIZE (1UL << DVMA_PAGE_SHIFT) +#define DVMA_PAGE_MASK (~(DVMA_PAGE_SIZE-1)) + + +static volatile unsigned long *iommu_pte = (unsigned long *)SUN3X_IOMMU; +static unsigned long iommu_use[IOMMU_ENTRIES]; +static unsigned long iommu_bitmap[IOMMU_ENTRIES/32]; + + +#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))) +#define dvma_entry_set(index,addr) (iommu_pte[index] = \ + (addr & IOMMU_ADDR_MASK) | \ + IOMMU_DT_VALID) +#define dvma_entry_clr(index) (iommu_pte[index] = IOMMU_DT_INVALID) +#define dvma_entry_use(index) (iommu_use[index]) +#define dvma_entry_inc(index) (iommu_use[index]++) +#define dvma_entry_dec(index) (iommu_use[index]--) +#define dvma_entry_hash(addr) ((addr >> DVMA_PAGE_SHIFT) ^ \ + ((addr & 0x03c00000) >> \ + (DVMA_PAGE_SHIFT+4))) +#define dvma_map iommu_bitmap +#define dvma_map_size (IOMMU_ENTRIES/2) +#define dvma_slow_offset (IOMMU_ENTRIES/2) +#define dvma_is_slow(addr) ((addr) & \ + (dvma_slow_offset << DVMA_PAGE_SHIFT)) + +static int fixed_dvma; + +void __init dvma_init(void) +{ + unsigned long tmp; + + if ((unsigned long)high_memory < (IOMMU_ENTRIES << DVMA_PAGE_SHIFT)) { + printk ("Sun3x fixed DVMA mapping\n"); + fixed_dvma = 1; + for (tmp = 0; tmp < (unsigned long)high_memory; tmp += DVMA_PAGE_SIZE) + dvma_entry_set (tmp >> DVMA_PAGE_SHIFT, virt_to_phys((void *)tmp)); + fixed_dvma = 1; + } else { + printk ("Sun3x variable DVMA mapping\n"); + for (tmp = 0; tmp < IOMMU_ENTRIES; tmp++) + dvma_entry_clr (tmp); + fixed_dvma = 0; + } +} + +unsigned long dvma_slow_alloc (unsigned long paddr, int npages) +{ + int scan, base; + + scan = 0; + for (;;) { + scan = find_next_zero_bit(dvma_map, dvma_map_size, scan); + if ((base = scan) + npages > dvma_map_size) { + printk ("dvma_slow_alloc failed for %d pages\n",npages); + return 0; + } + for (;;) { + if (scan >= base + npages) goto found; + if (test_bit(scan, dvma_map)) break; + scan++; + } + } + +found: + for (scan = base; scan < base+npages; scan++) { + dvma_entry_set(scan+dvma_slow_offset, paddr); + paddr += DVMA_PAGE_SIZE; + set_bit(scan, dvma_map); + } + return (dvma_entry_vaddr((base+dvma_slow_offset),paddr)); +} + +unsigned long dvma_alloc (unsigned long paddr, unsigned long size) +{ + int index; + int pages = ((paddr & ~DVMA_PAGE_MASK) + size + (DVMA_PAGE_SIZE-1)) >> + DVMA_PAGE_SHIFT; + + if (fixed_dvma) + return ((unsigned long)phys_to_virt (paddr)); + + if (pages > 1) /* multi page, allocate from slow pool */ + return dvma_slow_alloc (paddr, pages); + + index = dvma_entry_hash (paddr); + + if (dvma_entry_use(index)) { + if (dvma_entry_paddr(index) == (paddr & DVMA_PAGE_MASK)) { + dvma_entry_inc(index); + return dvma_entry_vaddr(index,paddr); + } + /* collision, allocate from slow pool */ + return dvma_slow_alloc (paddr, pages); + } + + dvma_entry_set(index,paddr); + dvma_entry_inc(index); + return dvma_entry_vaddr(index,paddr); +} + +void dvma_free (unsigned long dvma_addr, unsigned long size) +{ + int npages; + int index; + + if (fixed_dvma) + return; + + if (!dvma_is_slow(dvma_addr)) { + index = (dvma_addr >> DVMA_PAGE_SHIFT); + if (dvma_entry_use(index) == 0) { + printk ("dvma_free: %lx entry already free\n",dvma_addr); + return; + } + dvma_entry_dec(index); + if (dvma_entry_use(index) == 0) + dvma_entry_clr(index); + return; + } + + /* free in slow pool */ + npages = ((dvma_addr & ~DVMA_PAGE_MASK) + size + (DVMA_PAGE_SIZE-1)) >> + DVMA_PAGE_SHIFT; + for (index = (dvma_addr >> DVMA_PAGE_SHIFT); npages--; index++) { + dvma_entry_clr(index); + clear_bit (index,dvma_map); + } +} diff --git a/arch/m68k/sun3x/sbus.c b/arch/m68k/sun3x/sbus.c new file mode 100644 index 000000000..f1a89df65 --- /dev/null +++ b/arch/m68k/sun3x/sbus.c @@ -0,0 +1,44 @@ +/* + * SBus helper functions + * + * Sun3x don't have a sbus, but many of the used devices are also + * used on Sparc machines with sbus. To avoid having a lot of + * duplicate code, we provide necessary glue stuff to make using + * of the sbus driver code possible. + * + * (C) 1999 Thomas Bogendoerfer (tsbogend@alpha.franken.de) + */ + +#include <linux/types.h> +#include <linux/init.h> + +__initfunc(void sbus_init(void)) +{ + +} + +void *sparc_alloc_io (u32 address, void *virtual, int len, char *name, + u32 bus_type, int rdonly) +{ + return (void *)address; +} + +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) +{ + +} diff --git a/arch/m68k/sun3x/time.c b/arch/m68k/sun3x/time.c new file mode 100644 index 000000000..39fa5f696 --- /dev/null +++ b/arch/m68k/sun3x/time.c @@ -0,0 +1,83 @@ +/* + * linux/arch/m68k/sun3x/time.c + * + * Sun3x-specific time handling + */ + +#include <linux/config.h> +#include <linux/types.h> +#include <linux/init.h> +#include <linux/sched.h> +#include <linux/kernel_stat.h> +#include <linux/interrupt.h> + +#include <asm/irq.h> +#include <asm/io.h> +#include <asm/system.h> +#include <asm/traps.h> +#include <asm/sun3x.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 + +#define BCD_TO_BIN(val) (((val)&15) + ((val)>>4)*10) + +/* Read the Mostek */ +void sun3x_gettod (int *yearp, int *monp, int *dayp, + int *hourp, int *minp, int *secp) +{ + volatile unsigned char *eeprom = (unsigned char *)SUN3X_EEPROM; + + /* Stop updates */ + *(eeprom + M_CONTROL) |= C_READ; + + /* Read values */ + *yearp = BCD_TO_BIN(*(eeprom + M_YEAR)); + *monp = BCD_TO_BIN(*(eeprom + M_MONTH)); + *dayp = BCD_TO_BIN(*(eeprom + M_DATE)); + *hourp = BCD_TO_BIN(*(eeprom + M_HOUR)); + *minp = BCD_TO_BIN(*(eeprom + M_MIN)); + *secp = BCD_TO_BIN(*(eeprom + M_SEC)); + + /* Restart updates */ + *(eeprom + M_CONTROL) &= ~C_READ; +} + +/* Not much we can do here */ +unsigned long sun3x_gettimeoffset (void) +{ + return 0L; +} + +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); +} + +__initfunc(void sun3x_sched_init(void (*vector)(int, void *, struct pt_regs *))) +{ + sys_request_irq(5, sun3x_timer_tick, IRQ_FLG_STD, "timer tick", vector); + + /* Pulse enable low to get the clock started */ + disable_irq(5); + enable_irq(5); +} diff --git a/arch/m68k/sun3x/time.h b/arch/m68k/sun3x/time.h new file mode 100644 index 000000000..873742d70 --- /dev/null +++ b/arch/m68k/sun3x/time.h @@ -0,0 +1,9 @@ +#ifndef SUN3X_TIME_H +#define SUN3X_TIME_H + +void sun3x_gettod (int *yearp, int *monp, int *dayp, + int *hourp, int *minp, int *secp); +unsigned long sun3x_gettimeoffset (void); +void sun3x_sched_init(void (*vector)(int, void *, struct pt_regs *)); + +#endif |