diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2000-07-21 22:00:56 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2000-07-21 22:00:56 +0000 |
commit | 168660f24dfc46c2702acbe4701a446f42a59578 (patch) | |
tree | f431368afbf6b1b71809cf3fd904d800ea126f4d /arch/arm/kernel | |
parent | 6420f767924fa73b0ea267864d96820815f4ba5a (diff) |
Merge with Linux 2.4.0-test5-pre3.
Diffstat (limited to 'arch/arm/kernel')
-rw-r--r-- | arch/arm/kernel/Makefile | 22 | ||||
-rw-r--r-- | arch/arm/kernel/arch.c | 40 | ||||
-rw-r--r-- | arch/arm/kernel/armksyms.c | 9 | ||||
-rw-r--r-- | arch/arm/kernel/bios32.c | 2 | ||||
-rw-r--r-- | arch/arm/kernel/dma-a5k.c | 99 | ||||
-rw-r--r-- | arch/arm/kernel/dma-arc.c | 260 | ||||
-rw-r--r-- | arch/arm/kernel/dma-dummy.c | 34 | ||||
-rw-r--r-- | arch/arm/kernel/dma-footbridge.c | 88 | ||||
-rw-r--r-- | arch/arm/kernel/dma-isa.c | 44 | ||||
-rw-r--r-- | arch/arm/kernel/dma-isa.h | 29 | ||||
-rw-r--r-- | arch/arm/kernel/dma-rpc.c | 312 | ||||
-rw-r--r-- | arch/arm/kernel/dma.c | 307 | ||||
-rw-r--r-- | arch/arm/kernel/dma.h | 68 | ||||
-rw-r--r-- | arch/arm/kernel/ecard.c | 11 | ||||
-rw-r--r-- | arch/arm/kernel/hw-sa1100.c | 18 | ||||
-rw-r--r-- | arch/arm/kernel/oldlatches.c | 57 | ||||
-rw-r--r-- | arch/arm/kernel/process.c | 31 | ||||
-rw-r--r-- | arch/arm/kernel/signal.c | 1 | ||||
-rw-r--r-- | arch/arm/kernel/sys_arm.c | 3 | ||||
-rw-r--r-- | arch/arm/kernel/time.c | 6 | ||||
-rw-r--r-- | arch/arm/kernel/traps.c | 3 |
21 files changed, 660 insertions, 784 deletions
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile index 7662f42ef..62c0ca60e 100644 --- a/arch/arm/kernel/Makefile +++ b/arch/arm/kernel/Makefile @@ -8,38 +8,32 @@ HEAD_OBJ = head-$(PROCESSOR).o ENTRY_OBJ = entry-$(PROCESSOR).o -ifeq ($(CONFIG_ISA_DMA),y) - ISA_DMA_OBJS += dma-isa.o -endif - O_OBJS_arc = dma-arc.o oldlatches.o -O_OBJS_a5k = dma-a5k.o O_OBJS_rpc = dma-rpc.o -O_OBJS_ebsa110 = dma-dummy.o -O_OBJS_footbridge = dma.o dma-footbridge.o $(ISA_DMA_OBJS) hw-footbridge.o isa.o -O_OBJS_clps7500 = dma-dummy.o -O_OBJS_nexuspci = dma-dummy.o -O_OBJS_sa1100 = dma-dummy.o hw-sa1100.o -O_OBJS_l7200 = dma-dummy.o fiq.o +O_OBJS_footbridge = dma-footbridge.o hw-footbridge.o isa.o +O_OBJS_sa1100 = hw-sa1100.o +O_OBJS_l7200 = fiq.o O_TARGET := kernel.o # Object file lists. -obj-y := arch.o $(ENTRY_OBJ) irq.o process.o ptrace.o \ +obj-y := arch.o dma.o $(ENTRY_OBJ) irq.o process.o ptrace.o \ semaphore.o setup.o signal.o sys_arm.o time.o \ traps.o $(O_OBJS_$(MACHINE)) obj-m := obj-n := obj- := -export-objs := armksyms.o dma.o ecard.o hw-footbridge.o hw-sa1100.o leds-$(MACHINE).o +export-objs := armksyms.o dma.o ecard.o hw-footbridge.o \ + hw-sa1100.o leds-$(MACHINE).o oldlatches.o -obj-$(CONFIG_ARCH_ACORN) += dma.o ecard.o fiq.o time-acorn.o +obj-$(CONFIG_ARCH_ACORN) += ecard.o fiq.o time-acorn.o obj-$(CONFIG_DEBUG_LL) += debug-$(PROCESSOR).o obj-$(CONFIG_MODULES) += armksyms.o obj-$(CONFIG_LEDS) += leds-$(MACHINE).o obj-$(CONFIG_ARTHUR) += arthur.o +obj-$(CONFIG_ISA_DMA) += dma-isa.o ifeq ($(MACHINE),nexuspci) obj-$(CONFIG_PCI) += plx9080.o diff --git a/arch/arm/kernel/arch.c b/arch/arm/kernel/arch.c index 8b67943ce..0ce6d9d21 100644 --- a/arch/arm/kernel/arch.c +++ b/arch/arm/kernel/arch.c @@ -8,6 +8,8 @@ */ #include <linux/config.h> #include <linux/tty.h> +#include <linux/delay.h> +#include <linux/pm.h> #include <linux/init.h> #include <asm/dec21285.h> @@ -134,8 +136,10 @@ fixup_netwinder(struct machine_desc *desc, struct param_struct *params, isapnp_disable = 1; #endif - if (params->u1.s.nr_pages != 0x2000 && - params->u1.s.nr_pages != 0x4000) { + if (params->u1.s.nr_pages != 0x02000 && + params->u1.s.nr_pages != 0x04000 && + params->u1.s.nr_pages != 0x08000 && + params->u1.s.nr_pages != 0x10000) { printk(KERN_WARNING "Warning: bad NeTTrom parameters " "detected, using defaults\n"); @@ -207,6 +211,14 @@ MACHINE_END #ifdef CONFIG_ARCH_SA1100 +static void victor_power_off(void) +{ + /* switch off power supply */ + mdelay(2000); + GPCR = GPIO_GPIO23; + while (1); +} + extern void select_sa1100_io_desc(void); #define SET_BANK(__nr,__start,__size) \ mi->bank[__nr].start = (__start), \ @@ -219,9 +231,31 @@ fixup_sa1100(struct machine_desc *desc, struct param_struct *params, select_sa1100_io_desc(); if (machine_is_assabet()) { + /* + * On Assabet, we must probe for the Neponset board *before* + * paging_init() has occured to actually determine the amount + * of RAM available. + */ + extern void map_sa1100_gpio_regs(void); + extern void get_assabet_scr(void); + map_sa1100_gpio_regs(); + get_assabet_scr(); + SET_BANK( 0, 0xc0000000, 32*1024*1024 ); mi->nr_banks = 1; + if (machine_has_neponset()) { + printk("Neponset expansion board detected\n"); + /* + * Note that Neponset RAM is slower... + * and still untested. + * This would be a candidate for + * _real_ NUMA support. + */ + //SET_BANK( 1, 0xd0000000, 32*1024*1024 ); + //mi->nr_banks = 2; + } + ROOT_DEV = MKDEV(RAMDISK_MAJOR,0); setup_ramdisk( 1, 0, 0, 8192 ); setup_initrd( 0xc0800000, 3*1024*1024 ); @@ -297,6 +331,8 @@ fixup_sa1100(struct machine_desc *desc, struct param_struct *params, /* power off if any problem */ strcat( *cmdline, " panic=1" ); + + pm_power_off = victor_power_off; } } diff --git a/arch/arm/kernel/armksyms.c b/arch/arm/kernel/armksyms.c index 5ac0743be..6723291df 100644 --- a/arch/arm/kernel/armksyms.c +++ b/arch/arm/kernel/armksyms.c @@ -8,13 +8,14 @@ #include <linux/pci.h> #include <linux/delay.h> #include <linux/in6.h> +#include <linux/interrupt.h> +#include <linux/pm.h> #include <linux/vt_kern.h> #include <asm/byteorder.h> #include <asm/elf.h> #include <asm/io.h> #include <asm/irq.h> -#include <asm/dma.h> #include <asm/pgalloc.h> #include <asm/proc-fns.h> #include <asm/processor.h> @@ -28,9 +29,6 @@ extern int dump_fpu(struct pt_regs *, struct user_fp_struct *); extern void inswb(unsigned int port, void *to, int len); extern void outswb(unsigned int port, const void *to, int len); -extern unsigned int local_bh_count[NR_CPUS]; -extern unsigned int local_irq_count[NR_CPUS]; - extern void __bad_xchg(volatile void *ptr, int size); /* @@ -68,6 +66,7 @@ extern void __umodsi3(void); extern void ret_from_exception(void); extern void fpundefinstr(void); extern void fp_enter(void); + #define EXPORT_SYMBOL_ALIAS(sym,orig) \ const char __kstrtab_##sym##[] __attribute__((section(".kstrtab"))) = \ __MODULE_STRING(##sym##); \ @@ -108,6 +107,8 @@ EXPORT_SYMBOL(__bad_xchg); EXPORT_SYMBOL(__readwrite_bug); EXPORT_SYMBOL(enable_irq); EXPORT_SYMBOL(disable_irq); +EXPORT_SYMBOL(pm_idle); +EXPORT_SYMBOL(pm_power_off); /* processor dependencies */ #ifdef MULTI_CPU diff --git a/arch/arm/kernel/bios32.c b/arch/arm/kernel/bios32.c index a077f13b9..b2c644198 100644 --- a/arch/arm/kernel/bios32.c +++ b/arch/arm/kernel/bios32.c @@ -365,7 +365,7 @@ static u8 __init no_swizzle(struct pci_dev *dev, u8 *pin) /* ebsa285 host-specific stuff */ #ifdef CONFIG_ARCH_EBSA285 -static int irqmap_ebsa285[] __initdata = { IRQ_IN1, IRQ_IN0, IRQ_PCI, IRQ_IN3 }; +static int irqmap_ebsa285[] __initdata = { IRQ_IN3, IRQ_IN1, IRQ_IN0, IRQ_PCI }; static u8 __init ebsa285_swizzle(struct pci_dev *dev, u8 *pin) { diff --git a/arch/arm/kernel/dma-a5k.c b/arch/arm/kernel/dma-a5k.c deleted file mode 100644 index d79013af2..000000000 --- a/arch/arm/kernel/dma-a5k.c +++ /dev/null @@ -1,99 +0,0 @@ -/* - * arch/arm/kernel/dma-a5k.c - * - * Copyright (C) 1998 Russell King - * - * DMA functions specific to A5000 architecture - */ -#include <linux/sched.h> -#include <linux/init.h> - -#include <asm/dma.h> -#include <asm/fiq.h> -#include <asm/io.h> -#include <asm/hardware.h> - -#include "dma.h" - -static struct fiq_handler fh = { - name: "floppydma" -}; - -int arch_request_dma(dmach_t channel, dma_t *dma, const char *dev_id) -{ - if (channel == DMA_VIRTUAL_FLOPPY) - return 0; - else - return -EINVAL; -} - -void arch_free_dma(dmach_t channel, dma_t *dma) -{ - if (channel != DMA_VIRTUAL_FLOPPY) - printk("arch_free_dma: invalid channel %d\n", channel); -} - -int arch_get_dma_residue(dmach_t channel, dma_t *dma) -{ - if (channel != DMA_VIRTUAL_FLOPPY) - printk("arch_dma_count: invalid channel %d\n", channel); - else { - struct pt_regs regs; - get_fiq_regs(®s); - return regs.ARM_r9; - } - return 0; -} - -void arch_enable_dma(dmach_t channel, dma_t *dma) -{ - if (channel != DMA_VIRTUAL_FLOPPY) - printk("arch_enable_dma: invalid channel %d\n", channel); - else { - struct pt_regs regs; - void *fiqhandler_start; - unsigned int fiqhandler_length; - extern void floppy_fiqsetup(unsigned long len, unsigned long addr, - unsigned long port); - - if (dma->dma_mode == DMA_MODE_READ) { - extern unsigned char floppy_fiqin_start, floppy_fiqin_end; - fiqhandler_start = &floppy_fiqin_start; - fiqhandler_length = &floppy_fiqin_end - &floppy_fiqin_start; - } else { - extern unsigned char floppy_fiqout_start, floppy_fiqout_end; - fiqhandler_start = &floppy_fiqout_start; - fiqhandler_length = &floppy_fiqout_end - &floppy_fiqout_start; - } - if (claim_fiq(&fh)) { - printk("floppydma: couldn't claim FIQ.\n"); - return; - } - memcpy((void *)0x1c, fiqhandler_start, fiqhandler_length); - regs.ARM_r9 = dma->buf.length; - regs.ARM_r10 = __bus_to_virt(dma->buf.address); - regs.ARM_fp = (int)PCIO_FLOPPYDMABASE; - set_fiq_regs(®s); - enable_irq(dma->dma_irq); - } -} - -void arch_disable_dma(dmach_t channel, dma_t *dma) -{ - if (channel != DMA_VIRTUAL_FLOPPY) - printk("arch_disable_dma: invalid channel %d\n", channel); - else { - disable_irq(dma->dma_irq); - release_fiq(&fh); - } -} - -int arch_set_dma_speed(dmach_t channel, dma_t *dma, int cycle_ns) -{ - return 0; -} - -void __init arch_dma_init(dma_t *dma) -{ - dma[DMA_VIRTUAL_FLOPPY].dma_irq = 64; -} diff --git a/arch/arm/kernel/dma-arc.c b/arch/arm/kernel/dma-arc.c index 53ef12b1c..5a2f93b67 100644 --- a/arch/arm/kernel/dma-arc.c +++ b/arch/arm/kernel/dma-arc.c @@ -3,148 +3,200 @@ * * Copyright (C) 1998-1999 Dave Gilbert / Russell King * - * DMA functions specific to Archimedes architecture + * DMA functions specific to Archimedes and A5000 architecture */ #include <linux/config.h> #include <linux/sched.h> #include <linux/init.h> #include <asm/dma.h> +#include <asm/fiq.h> #include <asm/io.h> #include <asm/hardware.h> #include "dma.h" -#define DEBUG +#define DPRINTK(x...) printk(KERN_DEBUG x) -int arch_request_dma(dmach_t channel, dma_t *dma, const char * dev_id) +#if defined(CONFIG_BLK_DEV_FD1772) || defined(CONFIG_BLK_DEV_FD1772_MODULE) +static void arc_floppy_data_enable_dma(dmach_t channel, dma_t *dma) { - printk("arch_request_dma channel=%d F0=%d F1=%d\n",channel,DMA_VIRTUAL_FLOPPY0,DMA_VIRTUAL_FLOPPY1); - if (channel == DMA_VIRTUAL_FLOPPY0 || - channel == DMA_VIRTUAL_FLOPPY1) - return 0; - else - return -EINVAL; -} - -void arch_free_dma(dmach_t channel, dma_t *dma) -{ -} - -void arch_enable_dma(dmach_t channel, dma_t *dma) -{ - printk("arch_enable_dma channel=%d F0=%d F1=%d\n",channel,DMA_VIRTUAL_FLOPPY0,DMA_VIRTUAL_FLOPPY1); - switch (channel) { -#ifdef CONFIG_BLK_DEV_FD1772 - case DMA_VIRTUAL_FLOPPY0: { /* Data DMA */ - switch (dma->dma_mode) { - case DMA_MODE_READ: /* read */ - { - extern unsigned char fdc1772_dma_read, fdc1772_dma_read_end; - extern void fdc1772_setupdma(unsigned int count,unsigned int addr); - unsigned long flags; -#ifdef DEBUG - printk("enable_dma fdc1772 data read\n"); -#endif - save_flags(flags); - cliIF(); + DPRINTK("arc_floppy_data_enable_dma\n"); + switch (dma->dma_mode) { + case DMA_MODE_READ: { /* read */ + extern unsigned char fdc1772_dma_read, fdc1772_dma_read_end; + extern void fdc1772_setupdma(unsigned int count,unsigned int addr); + unsigned long flags; + DPRINTK("enable_dma fdc1772 data read\n"); + save_flags(flags); + cliIF(); - memcpy ((void *)0x1c, (void *)&fdc1772_dma_read, - &fdc1772_dma_read_end - &fdc1772_dma_read); - fdc1772_setupdma(dma->buf.length, __bus_to_virt(dma->buf.address)); /* Sets data pointer up */ - enable_irq (64); - restore_flags(flags); - } - break; - - case DMA_MODE_WRITE: /* write */ - { - extern unsigned char fdc1772_dma_write, fdc1772_dma_write_end; - extern void fdc1772_setupdma(unsigned int count,unsigned int addr); - unsigned long flags; - -#ifdef DEBUG - printk("enable_dma fdc1772 data write\n"); -#endif - save_flags(flags); - cliIF(); - memcpy ((void *)0x1c, (void *)&fdc1772_dma_write, - &fdc1772_dma_write_end - &fdc1772_dma_write); - fdc1772_setupdma(dma->buf.length, __bus_to_virt(dma->buf.address)); /* Sets data pointer up */ - enable_irq (64); - - restore_flags(flags); - } - break; - default: - printk ("enable_dma: dma%d not initialised\n", channel); - return; - } - } - break; + memcpy ((void *)0x1c, (void *)&fdc1772_dma_read, + &fdc1772_dma_read_end - &fdc1772_dma_read); + fdc1772_setupdma(dma->buf.length, __bus_to_virt(dma->buf.address)); /* Sets data pointer up */ + enable_irq (64); + restore_flags(flags); + } + break; - case DMA_VIRTUAL_FLOPPY1: { /* Command end FIQ - actually just sets a flag */ - /* Need to build a branch at the FIQ address */ - extern void fdc1772_comendhandler(void); + case DMA_MODE_WRITE: { /* write */ + extern unsigned char fdc1772_dma_write, fdc1772_dma_write_end; + extern void fdc1772_setupdma(unsigned int count,unsigned int addr); unsigned long flags; - - /*printk("enable_dma fdc1772 command end FIQ\n");*/ + DPRINTK("enable_dma fdc1772 data write\n"); save_flags(flags); cliIF(); - - *((unsigned int *)0x1c)=0xea000000 | (((unsigned int)fdc1772_comendhandler-(0x1c+8))/4); /* B fdc1772_comendhandler */ + memcpy ((void *)0x1c, (void *)&fdc1772_dma_write, + &fdc1772_dma_write_end - &fdc1772_dma_write); + fdc1772_setupdma(dma->buf.length, __bus_to_virt(dma->buf.address)); /* Sets data pointer up */ + enable_irq (64); restore_flags(flags); - } - break; -#endif + } + break; + default: + printk ("enable_dma: dma%d not initialised\n", channel); } } -int arch_get_dma_residue(dmach_t channel, dma_t *dma) +static int arc_floppy_data_get_dma_residue(dmach_t channel, dma_t *dma) { - switch (channel) { -#ifdef CONFIG_BLK_DEV_FD1772 - case DMA_VIRTUAL_FLOPPY0: { /* Data DMA */ - extern unsigned int fdc1772_bytestogo; + extern unsigned int fdc1772_bytestogo; + + /* 10/1/1999 DAG - I presume its the number of bytes left? */ + return fdc1772_bytestogo; +} + +static void arc_floppy_cmdend_enable_dma(dmach_t channel, dma_t *dma) +{ + /* Need to build a branch at the FIQ address */ + extern void fdc1772_comendhandler(void); + unsigned long flags; + + DPRINTK("arc_floppy_cmdend_enable_dma\n"); + /*printk("enable_dma fdc1772 command end FIQ\n");*/ + save_flags(flags); + cliIF(); + + /* B fdc1772_comendhandler */ + *((unsigned int *)0x1c)=0xea000000 | + (((unsigned int)fdc1772_comendhandler-(0x1c+8))/4); - /* 10/1/1999 DAG - I presume its the number of bytes left? */ - return fdc1772_bytestogo; - }; - break; + restore_flags(flags); +} + +static int arc_floppy_cmdend_get_dma_residue(dmach_t channel, dma_t *dma) +{ + /* 10/1/1999 DAG - Presume whether there is an outstanding command? */ + extern unsigned int fdc1772_fdc_int_done; - case DMA_VIRTUAL_FLOPPY1: { /* Command completed */ - /* 10/1/1999 DAG - Presume whether there is an outstanding command? */ - extern unsigned int fdc1772_fdc_int_done; + * Explicit! If the int done is 0 then 1 int to go */ + return (fdc1772_fdc_int_done==0)?1:0; +} - return (fdc1772_fdc_int_done==0)?1:0; /* Explicit! If the int done is 0 then 1 int to go */ - }; - break; +static void arc_disable_dma(dmach_t channel, dma_t *dma) +{ + disable_irq(dma->dma_irq); +} +static struct dma_ops arc_floppy_data_dma_ops = { + type: "FIQDMA", + enable: arc_floppy_data_enable_dma, + disable: arc_disable_dma, + residue: arc_floppy_data_get_dma_residue, +}; + +static struct dma_ops arc_floppy_cmdend_dma_ops = { + type: "FIQCMD", + enable: arc_floppy_cmdend_enable_dma, + disable: arc_disable_dma, + residue: arc_floppy_cmdend_get_dma_residue, +}; #endif - default: - printk("dma-arc.c:arch_get_dma_residue called with unknown/unconfigured DMA channel\n"); - return 0; - }; +#ifdef CONFIG_ARCH_A5K +static struct fiq_handler fh = { + name: "floppydata" +}; + +static int a5k_floppy_get_dma_residue(dmach_t channel, dma_t *dma) +{ + struct pt_regs regs; + get_fiq_regs(®s); + return regs.ARM_r9; +} + +static void a5k_floppy_enable_dma(dmach_t channel, dma_t *dma) +{ + struct pt_regs regs; + void *fiqhandler_start; + unsigned int fiqhandler_length; + extern void floppy_fiqsetup(unsigned long len, unsigned long addr, + unsigned long port); + + if (dma->dma_mode == DMA_MODE_READ) { + extern unsigned char floppy_fiqin_start, floppy_fiqin_end; + fiqhandler_start = &floppy_fiqin_start; + fiqhandler_length = &floppy_fiqin_end - &floppy_fiqin_start; + } else { + extern unsigned char floppy_fiqout_start, floppy_fiqout_end; + fiqhandler_start = &floppy_fiqout_start; + fiqhandler_length = &floppy_fiqout_end - &floppy_fiqout_start; + } + if (claim_fiq(&fh)) { + printk("floppydma: couldn't claim FIQ.\n"); + return; + } + memcpy((void *)0x1c, fiqhandler_start, fiqhandler_length); + regs.ARM_r9 = dma->buf.length; + regs.ARM_r10 = __bus_to_virt(dma->buf.address); + regs.ARM_fp = (int)PCIO_FLOPPYDMABASE; + set_fiq_regs(®s); + enable_irq(dma->dma_irq); } -void arch_disable_dma(dmach_t channel, dma_t *dma) +static void a5k_floppy_disable_dma(dmach_t channel, dma_t *dma) { - if (channel != DMA_VIRTUAL_FLOPPY0 && - channel != DMA_VIRTUAL_FLOPPY1) - printk("arch_disable_dma: invalid channel %d\n", channel); - else - disable_irq(dma->dma_irq); + disable_irq(dma->dma_irq); + release_fiq(&fh); } -int arch_set_dma_speed(dmach_t channel, dma_t *dma, int cycle_ns) +static struct dma_ops a5k_floppy_dma_ops = { + type: "FIQDMA", + enable: a5k_floppy_enable_dma, + disable: a5k_floppy_disable_dma, + residue: a5k_floppy_get_dma_residue, +}; +#endif + +/* + * This is virtual DMA - we don't need anything here + */ +static int sound_enable_disable_dma(dmach_t channel, dma_t *dma) { - return 0; } +static struct dma_ops sound_dma_ops = { + type: "VIRTUAL", + enable: sound_enable_disable_dma, + disable: sound_enable_disable_dma, +}; + void __init arch_dma_init(dma_t *dma) { - dma[DMA_VIRTUAL_FLOPPY0].dma_irq = 64; - dma[DMA_VIRTUAL_FLOPPY1].dma_irq = 65; +#if defined(CONFIG_BLK_DEV_FD1772) || defined(CONFIG_BLK_DEV_FD1772_MODULE) + if (machine_is_arc()) { + dma[DMA_VIRTUAL_FLOPPY0].dma_irq = 64; + dma[DMA_VIRTUAL_FLOPPY0].d_ops = &arc_floppy_data_dma_ops; + dma[DMA_VIRTUAL_FLOPPY1].dma_irq = 65; + dma[DMA_VIRTUAL_FLOPPY1].d_ops = &arc_floppy_cmdend_dma_ops; + } +#endif +#ifdef CONFIG_ARCH_A5K + if (machine_is_a5k()) { + dma[DMA_VIRTUAL_FLOPPY].dma_irq = 64; + dma[DMA_VIRTUAL_FLOPPY].d_ops = &a5k_floppy_dma_ops; + } +#endif + dma[DMA_VIRTUAL_SOUND].d_ops = &sound_dma_ops; } diff --git a/arch/arm/kernel/dma-dummy.c b/arch/arm/kernel/dma-dummy.c deleted file mode 100644 index ebb9755c1..000000000 --- a/arch/arm/kernel/dma-dummy.c +++ /dev/null @@ -1,34 +0,0 @@ -/* - * arch/arm/kernel/dma-dummy.c - * - * Copyright (C) 1998 Philip Blundell - * Copyright (c) 1998 Russell King - * - * Dummy DMA functions - */ -#include <linux/errno.h> -#include <linux/init.h> -#include <linux/spinlock.h> - -spinlock_t dma_spin_lock = SPIN_LOCK_UNLOCKED; - -int request_dma(int channel, const char *device_id) -{ - return -EINVAL; -} - -int no_dma(void) -{ - return 0; -} - -#define GLOBAL_ALIAS(_a,_b) asm (".set " #_a "," #_b "; .globl " #_a) -GLOBAL_ALIAS(disable_dma, no_dma); -GLOBAL_ALIAS(enable_dma, no_dma); -GLOBAL_ALIAS(free_dma, no_dma); -GLOBAL_ALIAS(get_dma_residue, no_dma); -GLOBAL_ALIAS(get_dma_list, no_dma); -GLOBAL_ALIAS(set_dma_mode, no_dma); -GLOBAL_ALIAS(set_dma_count, no_dma); -GLOBAL_ALIAS(set_dma_addr, no_dma); -GLOBAL_ALIAS(init_dma, no_dma); diff --git a/arch/arm/kernel/dma-footbridge.c b/arch/arm/kernel/dma-footbridge.c index 1d2ef26c4..b9d4b62fa 100644 --- a/arch/arm/kernel/dma-footbridge.c +++ b/arch/arm/kernel/dma-footbridge.c @@ -15,94 +15,44 @@ #include <linux/sched.h> #include <linux/init.h> +#include <asm/dec21285.h> #include <asm/dma.h> #include <asm/io.h> #include "dma.h" -#include "dma-isa.h" -#ifdef CONFIG_ISA_DMA -static int has_isa_dma; -#else -#define has_isa_dma 0 -#endif +extern void isa_init_dma(dma_t *dma); -int arch_request_dma(dmach_t channel, dma_t *dma, const char *dev_name) +#if 0 +static int fb_dma_request(dmach_t channel, dma_t *dma) { - switch (channel) { - case _DC21285_DMA(0): - case _DC21285_DMA(1): /* 21285 internal channels */ - return 0; - - case _ISA_DMA(0) ... _ISA_DMA(7): - if (has_isa_dma) - return isa_request_dma(channel - _ISA_DMA(0), dma, dev_name); - } - return -EINVAL; } -void arch_free_dma(dmach_t channel, dma_t *dma) -{ - /* nothing to do */ -} - -int arch_get_dma_residue(dmach_t channel, dma_t *dma) -{ - int residue = 0; - - switch (channel) { - case _DC21285_DMA(0): - case _DC21285_DMA(1): - break; - - case _ISA_DMA(0) ... _ISA_DMA(7): - if (has_isa_dma) - residue = isa_get_dma_residue(channel - _ISA_DMA(0), dma); - } - return residue; -} - -void arch_enable_dma(dmach_t channel, dma_t *dma) +static void fb_dma_enable(dmach_t channel, dma_t *dma) { - switch (channel) { - case _DC21285_DMA(0): - case _DC21285_DMA(1): - /* - * Not yet implemented - */ - break; - - case _ISA_DMA(0) ... _ISA_DMA(7): - if (has_isa_dma) - isa_enable_dma(channel - _ISA_DMA(0), dma); - } } -void arch_disable_dma(dmach_t channel, dma_t *dma) +static void fb_dma_disable(dmach_t channel, dma_t *dma) { - switch (channel) { - case _DC21285_DMA(0): - case _DC21285_DMA(1): - /* - * Not yet implemented - */ - break; - - case _ISA_DMA(0) ... _ISA_DMA(7): - if (has_isa_dma) - isa_disable_dma(channel - _ISA_DMA(0), dma); - } } -int arch_set_dma_speed(dmach_t channel, dma_t *dma, int cycle_ns) -{ - return 0; -} +static struct dma_ops fb_dma_ops = { + type: "fb", + request: fb_dma_request, + enable: fb_dma_enable, + disable: fb_dma_disable, +}; +#endif void __init arch_dma_init(dma_t *dma) { +#if 0 + dma[_DC21285_DMA(0)].d_ops = &fb_dma_ops; + dma[_DC21285_DMA(1)].d_ops = &fb_dma_ops; +#endif #ifdef CONFIG_ISA_DMA - has_isa_dma = isa_init_dma(); + if (footbridge_cfn_mode()) + isa_init_dma(dma + _ISA_DMA(0)); #endif } diff --git a/arch/arm/kernel/dma-isa.c b/arch/arm/kernel/dma-isa.c index 74967a055..f144d0436 100644 --- a/arch/arm/kernel/dma-isa.c +++ b/arch/arm/kernel/dma-isa.c @@ -1,12 +1,13 @@ /* * arch/arm/kernel/dma-isa.c: ISA DMA primitives * - * Copyright (C) Russell King + * Copyright (C) 1999-2000 Russell King * * Taken from various sources, including: * linux/include/asm/dma.h: Defines for using and allocating dma channels. * Written by Hennus Bergman, 1992. - * High DMA channel support & info by Hannu Savolainen and John Boyd, Nov. 1992. + * High DMA channel support & info by Hannu Savolainen and John Boyd, + * Nov. 1992. * arch/arm/kernel/dma-ebsa285.c * Copyright (C) 1998 Phil Blundell */ @@ -18,7 +19,6 @@ #include <asm/io.h> #include "dma.h" -#include "dma-isa.h" #define ISA_DMA_MODE_READ 0x44 #define ISA_DMA_MODE_WRITE 0x48 @@ -45,17 +45,7 @@ static unsigned int isa_dma_port[8][7] = { { 0xd4, 0xd6, 0xd8, 0x48a, 0x08a, 0xcc, 0xce } }; -int isa_request_dma(int channel, dma_t *dma, const char *dev_name) -{ - return 0; -} - -void isa_free_dma(int channel, dma_t *dma) -{ - /* nothing to do */ -} - -int isa_get_dma_residue(int channel, dma_t *dma) +static int isa_get_dma_residue(dmach_t channel, dma_t *dma) { unsigned int io_port = isa_dma_port[channel][ISA_DMA_COUNT]; int count; @@ -66,7 +56,7 @@ int isa_get_dma_residue(int channel, dma_t *dma) return channel < 4 ? count : (count << 1); } -void isa_enable_dma(int channel, dma_t *dma) +static void isa_enable_dma(dmach_t channel, dma_t *dma) { if (dma->invalid) { unsigned long address, length; @@ -121,11 +111,18 @@ void isa_enable_dma(int channel, dma_t *dma) outb(channel & 3, isa_dma_port[channel][ISA_DMA_MASK]); } -void isa_disable_dma(int channel, dma_t *dma) +static void isa_disable_dma(dmach_t channel, dma_t *dma) { outb(channel | 4, isa_dma_port[channel][ISA_DMA_MASK]); } +static struct dma_ops isa_dma_ops = { + type: "ISA", + enable: isa_enable_dma, + disable: isa_disable_dma, + residue: isa_get_dma_residue, +}; + static struct resource dma_resources[] = { { "dma1", 0x0000, 0x000f }, { "dma low page", 0x0080, 0x008f }, @@ -133,7 +130,7 @@ static struct resource dma_resources[] = { { "dma high page", 0x0480, 0x048f } }; -int __init isa_init_dma(void) +void __init isa_init_dma(dma_t *dma) { int dmac_found; @@ -148,8 +145,10 @@ int __init isa_init_dma(void) if (dmac_found) { int channel, i; - for (channel = 0; channel < 8; channel++) + for (channel = 0; channel < 8; channel++) { + dma[channel].d_ops = &isa_dma_ops; isa_disable_dma(channel, NULL); + } outb(0x40, 0x0b); outb(0x41, 0x0b); @@ -167,10 +166,9 @@ int __init isa_init_dma(void) outb(0x10, 0xd0); /* - * Is this correct? According to - * my documentation, it doesn't - * appear to be. It should be - * outb(0x3f, 0x40b); outb(0x3f, 0x4d6); + * Is this correct? According to my documentation, it + * doesn't appear to be. It should be: + * outb(0x3f, 0x40b); outb(0x3f, 0x4d6); */ outb(0x30, 0x40b); outb(0x31, 0x40b); @@ -185,6 +183,4 @@ int __init isa_init_dma(void) for (i = 0; i < sizeof(dma_resources) / sizeof(dma_resources[0]); i++) request_resource(&ioport_resource, dma_resources + i); } - - return dmac_found; } diff --git a/arch/arm/kernel/dma-isa.h b/arch/arm/kernel/dma-isa.h deleted file mode 100644 index 2640f6c3a..000000000 --- a/arch/arm/kernel/dma-isa.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Request an ISA DMA channel - */ -int isa_request_dma(int channel, dma_t *dma, const char *dev_name); - -/* - * Free an ISA DMA channel - */ -void isa_free_dma(int channel, dma_t *dma); - -/* - * Get ISA DMA channel residue - */ -int isa_get_dma_residue(int channel, dma_t *dma); - -/* - * Enable (and set up) an ISA DMA channel - */ -void isa_enable_dma(int channel, dma_t *dma); - -/* - * Disable an ISA DMA channel - */ -void isa_disable_dma(int channel, dma_t *dma); - -/* - * Initialise DMA - */ -int isa_init_dma(void); diff --git a/arch/arm/kernel/dma-rpc.c b/arch/arm/kernel/dma-rpc.c index f4bc97f1d..35e3c35a3 100644 --- a/arch/arm/kernel/dma-rpc.c +++ b/arch/arm/kernel/dma-rpc.c @@ -21,10 +21,6 @@ #include "dma.h" -static struct fiq_handler fh = { - name: "floppydma" -}; - #if 0 typedef enum { dma_size_8 = 1, @@ -51,7 +47,7 @@ typedef struct { #define state_wait_a 1 #define state_wait_b 2 -static void arch_get_next_sg(dmasg_t *sg, dma_t *dma) +static void iomd_get_next_sg(dmasg_t *sg, dma_t *dma) { unsigned long end, offset, flags = 0; @@ -90,19 +86,19 @@ static void arch_get_next_sg(dmasg_t *sg, dma_t *dma) sg->length |= flags; } -static inline void arch_setup_dma_a(dmasg_t *sg, dma_t *dma) +static inline void iomd_setup_dma_a(dmasg_t *sg, dma_t *dma) { outl_t(sg->address, dma->dma_base + CURA); outl_t(sg->length, dma->dma_base + ENDA); } -static inline void arch_setup_dma_b(dmasg_t *sg, dma_t *dma) +static inline void iomd_setup_dma_b(dmasg_t *sg, dma_t *dma) { outl_t(sg->address, dma->dma_base + CURB); outl_t(sg->length, dma->dma_base + ENDB); } -static void arch_dma_handle(int irq, void *dev_id, struct pt_regs *regs) +static void iomd_dma_handle(int irq, void *dev_id, struct pt_regs *regs) { dma_t *dma = (dma_t *)dev_id; unsigned int status = 0, no_buffer = dma->sg == NULL; @@ -110,26 +106,26 @@ static void arch_dma_handle(int irq, void *dev_id, struct pt_regs *regs) do { switch (dma->state) { case state_prog_a: - arch_get_next_sg(&dma->cur_sg, dma); - arch_setup_dma_a(&dma->cur_sg, dma); + iomd_get_next_sg(&dma->cur_sg, dma); + iomd_setup_dma_a(&dma->cur_sg, dma); dma->state = state_wait_a; case state_wait_a: status = inb_t(dma->dma_base + ST); switch (status & (DMA_ST_OFL|DMA_ST_INT|DMA_ST_AB)) { case DMA_ST_OFL|DMA_ST_INT: - arch_get_next_sg(&dma->cur_sg, dma); - arch_setup_dma_a(&dma->cur_sg, dma); + iomd_get_next_sg(&dma->cur_sg, dma); + iomd_setup_dma_a(&dma->cur_sg, dma); break; case DMA_ST_INT: - arch_get_next_sg(&dma->cur_sg, dma); - arch_setup_dma_b(&dma->cur_sg, dma); + iomd_get_next_sg(&dma->cur_sg, dma); + iomd_setup_dma_b(&dma->cur_sg, dma); dma->state = state_wait_b; break; case DMA_ST_OFL|DMA_ST_INT|DMA_ST_AB: - arch_setup_dma_b(&dma->cur_sg, dma); + iomd_setup_dma_b(&dma->cur_sg, dma); dma->state = state_wait_b; break; } @@ -139,18 +135,18 @@ static void arch_dma_handle(int irq, void *dev_id, struct pt_regs *regs) status = inb_t(dma->dma_base + ST); switch (status & (DMA_ST_OFL|DMA_ST_INT|DMA_ST_AB)) { case DMA_ST_OFL|DMA_ST_INT|DMA_ST_AB: - arch_get_next_sg(&dma->cur_sg, dma); - arch_setup_dma_b(&dma->cur_sg, dma); + iomd_get_next_sg(&dma->cur_sg, dma); + iomd_setup_dma_b(&dma->cur_sg, dma); break; case DMA_ST_INT|DMA_ST_AB: - arch_get_next_sg(&dma->cur_sg, dma); - arch_setup_dma_a(&dma->cur_sg, dma); + iomd_get_next_sg(&dma->cur_sg, dma); + iomd_setup_dma_a(&dma->cur_sg, dma); dma->state = state_wait_a; break; case DMA_ST_OFL|DMA_ST_INT: - arch_setup_dma_a(&dma->cur_sg, dma); + iomd_setup_dma_a(&dma->cur_sg, dma); dma->state = state_wait_a; break; } @@ -162,167 +158,56 @@ static void arch_dma_handle(int irq, void *dev_id, struct pt_regs *regs) disable_irq(irq); } -int arch_request_dma(dmach_t channel, dma_t *dma, const char *dev_name) +static int iomd_request_dma(dmach_t channel, dma_t *dma) { unsigned long flags; int ret; - switch (channel) { - case DMA_0: - case DMA_1: - case DMA_2: - case DMA_3: - case DMA_S0: - case DMA_S1: - save_flags_cli(flags); - ret = request_irq(dma->dma_irq, arch_dma_handle, - SA_INTERRUPT, dev_name, dma); - if (!ret) - disable_irq(dma->dma_irq); - restore_flags(flags); - break; - - case DMA_VIRTUAL_FLOPPY: - case DMA_VIRTUAL_SOUND: - ret = 0; - break; - - default: - ret = -EINVAL; - break; - } + save_flags_cli(flags); + ret = request_irq(dma->dma_irq, iomd_dma_handle, + SA_INTERRUPT, dma->device_id, dma); + if (!ret) + disable_irq(dma->dma_irq); + restore_flags(flags); return ret; } -void arch_free_dma(dmach_t channel, dma_t *dma) +static void iomd_free_dma(dmach_t channel, dma_t *dma) { - switch (channel) { - case DMA_0: - case DMA_1: - case DMA_2: - case DMA_3: - case DMA_S0: - case DMA_S1: - free_irq(dma->dma_irq, dma); - break; - - default: - break; - } + free_irq(dma->dma_irq, dma); } -int arch_get_dma_residue(dmach_t channel, dma_t *dma) -{ - int residue = 0; - - switch (channel) { - case DMA_0: /* Physical DMA channels */ - case DMA_1: - case DMA_2: - case DMA_3: - case DMA_S0: - case DMA_S1: - break; - - case DMA_VIRTUAL_FLOPPY: { - struct pt_regs regs; - get_fiq_regs(®s); - return regs.ARM_r9; - } - break; - } - return residue; -} - -void arch_enable_dma(dmach_t channel, dma_t *dma) +static void iomd_enable_dma(dmach_t channel, dma_t *dma) { unsigned long dma_base = dma->dma_base; - unsigned int ctrl; - - switch (channel) { - case DMA_0: /* Physical DMA channels */ - case DMA_1: - case DMA_2: - case DMA_3: - case DMA_S0: - case DMA_S1: - ctrl = TRANSFER_SIZE | DMA_CR_E; + unsigned int ctrl = TRANSFER_SIZE | DMA_CR_E; - if (dma->invalid) { - dma->invalid = 0; + if (dma->invalid) { + dma->invalid = 0; - outb_t(DMA_CR_C, dma_base + CR); - dma->state = state_prog_a; - } + outb_t(DMA_CR_C, dma_base + CR); + dma->state = state_prog_a; + } - if (dma->dma_mode == DMA_MODE_READ) - ctrl |= DMA_CR_D; + if (dma->dma_mode == DMA_MODE_READ) + ctrl |= DMA_CR_D; - outb_t(ctrl, dma_base + CR); - enable_irq(dma->dma_irq); - break; - - case DMA_VIRTUAL_FLOPPY: { - void *fiqhandler_start; - unsigned int fiqhandler_length; - struct pt_regs regs; - - if (dma->dma_mode == DMA_MODE_READ) { - extern unsigned char floppy_fiqin_start, floppy_fiqin_end; - fiqhandler_start = &floppy_fiqin_start; - fiqhandler_length = &floppy_fiqin_end - &floppy_fiqin_start; - } else { - extern unsigned char floppy_fiqout_start, floppy_fiqout_end; - fiqhandler_start = &floppy_fiqout_start; - fiqhandler_length = &floppy_fiqout_end - &floppy_fiqout_start; - } - - regs.ARM_r9 = dma->buf.length; - regs.ARM_r10 = __bus_to_virt(dma->buf.address); - regs.ARM_fp = (int)PCIO_FLOPPYDMABASE; - - if (claim_fiq(&fh)) { - printk("floppydma: couldn't claim FIQ.\n"); - return; - } - - set_fiq_handler(fiqhandler_start, fiqhandler_length); - set_fiq_regs(®s); - enable_irq(dma->dma_irq); - } - break; - - default: - break; - } + outb_t(ctrl, dma_base + CR); + enable_irq(dma->dma_irq); } -void arch_disable_dma(dmach_t channel, dma_t *dma) +static void iomd_disable_dma(dmach_t channel, dma_t *dma) { unsigned long dma_base = dma->dma_base; unsigned int ctrl; - switch (channel) { - case DMA_0: /* Physical DMA channels */ - case DMA_1: - case DMA_2: - case DMA_3: - case DMA_S0: - case DMA_S1: - disable_irq(dma->dma_irq); - ctrl = inb_t(dma_base + CR); - outb_t(ctrl & ~DMA_CR_E, dma_base + CR); - break; - - case DMA_VIRTUAL_FLOPPY: - disable_irq(dma->dma_irq); - release_fiq(&fh); - break; - } + disable_irq(dma->dma_irq); + ctrl = inb_t(dma_base + CR); + outb_t(ctrl & ~DMA_CR_E, dma_base + CR); } -int arch_set_dma_speed(dmach_t channel, dma_t *dma, int cycle) +static int iomd_set_dma_speed(dmach_t channel, dma_t *dma, int cycle) { int tcr, speed; @@ -364,6 +249,82 @@ int arch_set_dma_speed(dmach_t channel, dma_t *dma, int cycle) return speed; } +static struct dma_ops iomd_dma_ops = { + type: "IOMD", + request: iomd_request_dma, + free: iomd_free_dma, + enable: iomd_enable_dma, + disable: iomd_disable_dma, + setspeed: iomd_set_dma_speed, +}; + +static struct fiq_handler fh = { + name: "floppydma" +}; + +static void floppy_enable_dma(dmach_t channel, dma_t *dma) +{ + void *fiqhandler_start; + unsigned int fiqhandler_length; + struct pt_regs regs; + + if (dma->dma_mode == DMA_MODE_READ) { + extern unsigned char floppy_fiqin_start, floppy_fiqin_end; + fiqhandler_start = &floppy_fiqin_start; + fiqhandler_length = &floppy_fiqin_end - &floppy_fiqin_start; + } else { + extern unsigned char floppy_fiqout_start, floppy_fiqout_end; + fiqhandler_start = &floppy_fiqout_start; + fiqhandler_length = &floppy_fiqout_end - &floppy_fiqout_start; + } + + regs.ARM_r9 = dma->buf.length; + regs.ARM_r10 = __bus_to_virt(dma->buf.address); + regs.ARM_fp = (int)PCIO_FLOPPYDMABASE; + + if (claim_fiq(&fh)) { + printk("floppydma: couldn't claim FIQ.\n"); + return; + } + + set_fiq_handler(fiqhandler_start, fiqhandler_length); + set_fiq_regs(®s); + enable_irq(dma->dma_irq); +} + +static void floppy_disable_dma(dmach_t channel, dma_t *dma) +{ + disable_irq(dma->dma_irq); + release_fiq(&fh); +} + +static int floppy_get_residue(dmach_t channel, dma_t *dma) +{ + struct pt_regs regs; + get_fiq_regs(®s); + return regs.ARM_r9; +} + +static struct dma_ops floppy_dma_ops = { + type: "FIQDMA", + enable: floppy_enable_dma, + disable: floppy_disable_dma, + residue: floppy_get_residue, +}; + +/* + * This is virtual DMA - we don't need anything here. + */ +static int sound_enable_disable_dma(dmach_t channel, dma_t *dma) +{ +} + +static struct dma_ops sound_dma_ops = { + type: "VIRTUAL", + enable: sound_enable_disable_dma, + disable: sound_enable_disable_dma, +}; + void __init arch_dma_init(dma_t *dma) { outb(0, IOMD_IO0CR); @@ -373,21 +334,30 @@ void __init arch_dma_init(dma_t *dma) outb(0xa0, IOMD_DMATCR); - dma[0].dma_base = ioaddr(IOMD_IO0CURA); - dma[0].dma_irq = IRQ_DMA0; - dma[1].dma_base = ioaddr(IOMD_IO1CURA); - dma[1].dma_irq = IRQ_DMA1; - dma[2].dma_base = ioaddr(IOMD_IO2CURA); - dma[2].dma_irq = IRQ_DMA2; - dma[3].dma_base = ioaddr(IOMD_IO3CURA); - dma[3].dma_irq = IRQ_DMA3; - dma[4].dma_base = ioaddr(IOMD_SD0CURA); - dma[4].dma_irq = IRQ_DMAS0; - dma[5].dma_base = ioaddr(IOMD_SD1CURA); - dma[5].dma_irq = IRQ_DMAS1; - dma[6].dma_irq = 64; - - /* Setup DMA channels 2,3 to be for podules + dma[DMA_0].dma_base = ioaddr(IOMD_IO0CURA); + dma[DMA_0].dma_irq = IRQ_DMA0; + dma[DMA_0].d_ops = &iomd_dma_ops; + dma[DMA_1].dma_base = ioaddr(IOMD_IO1CURA); + dma[DMA_1].dma_irq = IRQ_DMA1; + dma[DMA_1].d_ops = &iomd_dma_ops; + dma[DMA_2].dma_base = ioaddr(IOMD_IO2CURA); + dma[DMA_2].dma_irq = IRQ_DMA2; + dma[DMA_2].d_ops = &iomd_dma_ops; + dma[DMA_3].dma_base = ioaddr(IOMD_IO3CURA); + dma[DMA_3].dma_irq = IRQ_DMA3; + dma[DMA_3].d_ops = &iomd_dma_ops; + dma[DMA_S0].dma_base = ioaddr(IOMD_SD0CURA); + dma[DMA_S0].dma_irq = IRQ_DMAS0; + dma[DMA_S0].d_ops = &iomd_dma_ops; + dma[DMA_S1].dma_base = ioaddr(IOMD_SD1CURA); + dma[DMA_S1].dma_irq = IRQ_DMAS1; + dma[DMA_S1].d_ops = &iomd_dma_ops; + dma[DMA_VIRTUAL_FLOPPY].dma_irq = 64; + dma[DMA_VIRTUAL_FLOPPY].d_ops = &floppy_dma_ops; + dma[DMA_VIRTUAL_SOUND].d_ops = &sound_dma_ops; + + /* + * Setup DMA channels 2,3 to be for podules * and channels 0,1 for internal devices */ outb(DMA_EXT_IO3|DMA_EXT_IO2, IOMD_DMAEXT); diff --git a/arch/arm/kernel/dma.c b/arch/arm/kernel/dma.c index ff8322d34..7ed4c28ca 100644 --- a/arch/arm/kernel/dma.c +++ b/arch/arm/kernel/dma.c @@ -1,130 +1,123 @@ /* * linux/arch/arm/kernel/dma.c * - * Copyright (C) 1995-1998 Russell King + * Copyright (C) 1995-2000 Russell King * - * Front-end to the DMA handling. You must provide the following - * architecture-specific routines: - * - * int arch_request_dma(dmach_t channel, dma_t *dma, const char *dev_id); - * void arch_free_dma(dmach_t channel, dma_t *dma); - * void arch_enable_dma(dmach_t channel, dma_t *dma); - * void arch_disable_dma(dmach_t channel, dma_t *dma); - * int arch_get_dma_residue(dmach_t channel, dma_t *dma); - * - * Moved DMA resource allocation here... + * Front-end to the DMA handling. This handles the allocation/freeing + * of DMA channels, and provides a unified interface to the machines + * DMA facilities. */ +#include <linux/module.h> #include <linux/malloc.h> #include <linux/sched.h> -#include <linux/module.h> #include <linux/mman.h> #include <linux/init.h> #include <linux/spinlock.h> -#include <asm/page.h> -#include <asm/irq.h> -#include <asm/hardware.h> -#include <asm/io.h> #include <asm/dma.h> - -/* A note on resource allocation: - * - * All drivers needing DMA channels, should allocate and release them - * through the public routines `request_dma()' and `free_dma()'. - * - * In order to avoid problems, all processes should allocate resources in - * the same sequence and release them in the reverse order. - * - * So, when allocating DMAs and IRQs, first allocate the IRQ, then the DMA. - * When releasing them, first release the DMA, then release the IRQ. - * If you don't, you may cause allocation requests to fail unnecessarily. - * This doesn't really matter now, but it will once we get real semaphores - * in the kernel. - */ - +#include "dma.h" spinlock_t dma_spin_lock = SPIN_LOCK_UNLOCKED; -#include "dma.h" - -const char dma_str[] = "%s: dma %d not supported\n"; +#if MAX_DMA_CHANNELS > 0 static dma_t dma_chan[MAX_DMA_CHANNELS]; -/* Get dma list - * for /proc/dma +/* + * Get dma list for /proc/dma */ int get_dma_list(char *buf) { - int i, len = 0; + dma_t *dma; + char *p = buf; + int i; - for (i = 0; i < MAX_DMA_CHANNELS; i++) { - if (dma_chan[i].lock) - len += sprintf(buf + len, "%2d: %s\n", - i, dma_chan[i].device_id); - } - return len; + for (i = 0, dma = dma_chan; i < MAX_DMA_CHANNELS; i++, dma++) + if (dma->lock) + p += sprintf(p, "%2d: %14s %s\n", i, + dma->d_ops->type, dma->device_id); + + return p - buf; } -/* Request DMA channel +/* + * Request DMA channel * * On certain platforms, we have to allocate an interrupt as well... */ int request_dma(dmach_t channel, const char *device_id) { - if (channel < MAX_DMA_CHANNELS) { - int ret; - - if (xchg(&dma_chan[channel].lock, 1) != 0) - return -EBUSY; - - ret = arch_request_dma(channel, &dma_chan[channel], device_id); - if (!ret) { - dma_chan[channel].device_id = device_id; - dma_chan[channel].active = 0; - dma_chan[channel].invalid = 1; - } else - xchg(&dma_chan[channel].lock, 0); - - return ret; - } else { - printk (KERN_ERR "Trying to allocate DMA%d\n", channel); - return -EINVAL; - } + dma_t *dma = dma_chan + channel; + int ret; + + if (channel >= MAX_DMA_CHANNELS || !dma->d_ops) + goto bad_dma; + + if (xchg(&dma->lock, 1) != 0) + goto busy; + + dma->device_id = device_id; + dma->active = 0; + dma->invalid = 1; + + ret = 0; + if (dma->d_ops->request) + ret = dma->d_ops->request(channel, dma); + + if (ret) + xchg(&dma->lock, 0); + + return ret; + +bad_dma: + printk(KERN_ERR "dma: trying to allocate DMA%d\n", channel); + return -EINVAL; + +busy: + return -EBUSY; } -/* Free DMA channel +/* + * Free DMA channel * * On certain platforms, we have to free interrupt as well... */ void free_dma(dmach_t channel) { - if (channel >= MAX_DMA_CHANNELS) { - printk (KERN_ERR "Trying to free DMA%d\n", channel); - return; - } + dma_t *dma = dma_chan + channel; + + if (channel >= MAX_DMA_CHANNELS || !dma->d_ops) + goto bad_dma; - if (xchg(&dma_chan[channel].lock, 0) == 0) { - if (dma_chan[channel].active) { - printk (KERN_ERR "Freeing active DMA%d\n", channel); - arch_disable_dma(channel, &dma_chan[channel]); - dma_chan[channel].active = 0; - } + if (dma->active) { + printk(KERN_ERR "dma%d: freeing active DMA\n", channel); + dma->d_ops->disable(channel, dma); + dma->active = 0; + } - printk (KERN_ERR "Trying to free free DMA%d\n", channel); + if (xchg(&dma->lock, 0) != 0) { + if (dma->d_ops->free) + dma->d_ops->free(channel, dma); return; } - arch_free_dma(channel, &dma_chan[channel]); + + printk(KERN_ERR "dma%d: trying to free free DMA\n", channel); + return; + +bad_dma: + printk(KERN_ERR "dma: trying to free DMA%d\n", channel); } /* Set DMA Scatter-Gather list */ void set_dma_sg (dmach_t channel, dmasg_t *sg, int nr_sg) { - dma_chan[channel].sg = sg; - dma_chan[channel].sgcount = nr_sg; - dma_chan[channel].invalid = 1; + dma_t *dma = dma_chan + channel; + + dma->sg = sg; + dma->sgcount = nr_sg; + dma->invalid = 1; } /* Set DMA address @@ -133,15 +126,16 @@ void set_dma_sg (dmach_t channel, dmasg_t *sg, int nr_sg) */ void set_dma_addr (dmach_t channel, unsigned long physaddr) { - if (dma_chan[channel].active) - printk(KERN_ERR "set_dma_addr: altering DMA%d" - " address while DMA active\n", - channel); - - dma_chan[channel].sg = &dma_chan[channel].buf; - dma_chan[channel].sgcount = 1; - dma_chan[channel].buf.address = physaddr; - dma_chan[channel].invalid = 1; + dma_t *dma = dma_chan + channel; + + if (dma->active) + printk(KERN_ERR "dma%d: altering DMA address while " + "DMA active\n", channel); + + dma->sg = &dma->buf; + dma->sgcount = 1; + dma->buf.address = physaddr; + dma->invalid = 1; } /* Set DMA byte count @@ -150,78 +144,137 @@ void set_dma_addr (dmach_t channel, unsigned long physaddr) */ void set_dma_count (dmach_t channel, unsigned long count) { - if (dma_chan[channel].active) - printk(KERN_ERR "set_dma_count: altering DMA%d" - " count while DMA active\n", - channel); - - dma_chan[channel].sg = &dma_chan[channel].buf; - dma_chan[channel].sgcount = 1; - dma_chan[channel].buf.length = count; - dma_chan[channel].invalid = 1; + dma_t *dma = dma_chan + channel; + + if (dma->active) + printk(KERN_ERR "dma%d: altering DMA count while " + "DMA active\n", channel); + + dma->sg = &dma->buf; + dma->sgcount = 1; + dma->buf.length = count; + dma->invalid = 1; } /* Set DMA direction mode */ void set_dma_mode (dmach_t channel, dmamode_t mode) { - if (dma_chan[channel].active) - printk(KERN_ERR "set_dma_mode: altering DMA%d" - " mode while DMA active\n", - channel); + dma_t *dma = dma_chan + channel; + + if (dma->active) + printk(KERN_ERR "dma%d: altering DMA mode while " + "DMA active\n", channel); - dma_chan[channel].dma_mode = mode; - dma_chan[channel].invalid = 1; + dma->dma_mode = mode; + dma->invalid = 1; } /* Enable DMA channel */ void enable_dma (dmach_t channel) { - if (dma_chan[channel].lock) { - if (dma_chan[channel].active == 0) { - dma_chan[channel].active = 1; - arch_enable_dma(channel, &dma_chan[channel]); - } - } else - printk (KERN_ERR "Trying to enable free DMA%d\n", channel); + dma_t *dma = dma_chan + channel; + + if (!dma->lock) + goto free_dma; + + if (dma->active == 0) { + dma->active = 1; + dma->d_ops->enable(channel, dma); + } + return; + +free_dma: + printk(KERN_ERR "dma%d: trying to enable free DMA\n", channel); + BUG(); } /* Disable DMA channel */ void disable_dma (dmach_t channel) { - if (dma_chan[channel].lock) { - if (dma_chan[channel].active == 1) { - dma_chan[channel].active = 0; - arch_disable_dma(channel, &dma_chan[channel]); - } - } else - printk (KERN_ERR "Trying to disable free DMA%d\n", channel); + dma_t *dma = dma_chan + channel; + + if (!dma->lock) + goto free_dma; + + if (dma->active == 1) { + dma->active = 0; + dma->d_ops->disable(channel, dma); + } + return; + +free_dma: + printk(KERN_ERR "dma%d: trying to disable free DMA\n", channel); + BUG(); +} + +void set_dma_page(dmach_t channel, char pagenr) +{ + printk(KERN_ERR "dma%d: trying to set_dma_page\n", channel); } void set_dma_speed(dmach_t channel, int cycle_ns) { - dma_chan[channel].speed = - arch_set_dma_speed(channel, &dma_chan[channel], cycle_ns); + dma_t *dma = dma_chan + channel; + int ret = 0; + + if (dma->d_ops->setspeed) + ret = dma->d_ops->setspeed(channel, dma, cycle_ns); + dma->speed = ret; } int get_dma_residue(dmach_t channel) { - return arch_get_dma_residue(channel, &dma_chan[channel]); + dma_t *dma = dma_chan + channel; + int ret = 0; + + if (dma->d_ops->residue) + ret = dma->d_ops->residue(channel, dma); + + return ret; +} + +void __init init_dma(void) +{ + arch_dma_init(dma_chan); +} + +#else + +int request_dma(dmach_t channel, const char *device_id) +{ + return -EINVAL; +} + +static int no_dma(void) +{ + return 0; } -EXPORT_SYMBOL(dma_str); +#define GLOBAL_ALIAS(_a,_b) asm (".set " #_a "," #_b "; .globl " #_a) +GLOBAL_ALIAS(disable_dma, no_dma); +GLOBAL_ALIAS(enable_dma, no_dma); +GLOBAL_ALIAS(free_dma, no_dma); +GLOBAL_ALIAS(get_dma_residue, no_dma); +GLOBAL_ALIAS(get_dma_list, no_dma); +GLOBAL_ALIAS(set_dma_mode, no_dma); +GLOBAL_ALIAS(set_dma_page, no_dma); +GLOBAL_ALIAS(set_dma_count, no_dma); +GLOBAL_ALIAS(set_dma_addr, no_dma); +GLOBAL_ALIAS(set_dma_sg, no_dma); +GLOBAL_ALIAS(set_dma_speed, no_dma); +GLOBAL_ALIAS(init_dma, no_dma); + +#endif + EXPORT_SYMBOL(enable_dma); EXPORT_SYMBOL(disable_dma); EXPORT_SYMBOL(set_dma_addr); EXPORT_SYMBOL(set_dma_count); EXPORT_SYMBOL(set_dma_mode); +EXPORT_SYMBOL(set_dma_page); EXPORT_SYMBOL(get_dma_residue); EXPORT_SYMBOL(set_dma_sg); EXPORT_SYMBOL(set_dma_speed); - -void __init init_dma(void) -{ - arch_dma_init(dma_chan); -} diff --git a/arch/arm/kernel/dma.h b/arch/arm/kernel/dma.h index 33db3b03b..6cd96ed97 100644 --- a/arch/arm/kernel/dma.h +++ b/arch/arm/kernel/dma.h @@ -1,13 +1,26 @@ /* - * arch/arm/kernel/dma.h + * linux/arch/arm/kernel/dma.h * - * Copyright (C) 1998 Russell King + * Copyright (C) 1998-2000 Russell King * * This header file describes the interface between the generic DMA handler * (dma.c) and the architecture-specific DMA backends (dma-*.c) */ -typedef struct { +struct dma_struct; +typedef struct dma_struct dma_t; + +struct dma_ops { + int (*request)(dmach_t, dma_t *); /* optional */ + void (*free)(dmach_t, dma_t *); /* optional */ + void (*enable)(dmach_t, dma_t *); /* mandatory */ + void (*disable)(dmach_t, dma_t *); /* mandatory */ + int (*residue)(dmach_t, dma_t *); /* optional */ + int (*setspeed)(dmach_t, dma_t *, int); /* optional */ + char *type; +}; + +struct dma_struct { dmasg_t buf; /* single DMA */ int sgcount; /* number of DMA SG */ dmasg_t *sg; /* DMA Scatter-Gather List */ @@ -24,54 +37,9 @@ typedef struct { int dma_irq; /* Controller IRQ */ int state; /* Controller state */ dmasg_t cur_sg; /* Current controller buffer */ -} dma_t; - -/* Prototype: int arch_request_dma(channel, dma, dev_id) - * Purpose : Perform architecture specific claiming of a DMA channel - * Params : channel - DMA channel number - * : dma - DMA structure (above) for channel - * : dev_id - device ID string passed with request - * Returns : 0 on success, E????? number on error - */ -int arch_request_dma(dmach_t channel, dma_t *dma, const char *dev_id); - -/* Prototype: int arch_free_dma(channel, dma) - * Purpose : Perform architecture specific freeing of a DMA channel - * Params : channel - DMA channel number - * : dma - DMA structure for channel - */ -void arch_free_dma(dmach_t channel, dma_t *dma); - -/* Prototype: void arch_enable_dma(channel, dma) - * Purpose : Enable a claimed DMA channel - * Params : channel - DMA channel number - * : dma - DMA structure for channel - */ -void arch_enable_dma(dmach_t channel, dma_t *dma); - -/* Prototype: void arch_disable_dma(channel, dma) - * Purpose : Disable a claimed DMA channel - * Params : channel - DMA channel number - * : dma - DMA structure for channel - */ -void arch_disable_dma(dmach_t channel, dma_t *dma); -/* Prototype: int arch_get_dma_residue(channel, dma) - * Purpose : Return number of bytes left to DMA - * Params : channel - DMA channel number - * : dma - DMA structure for channel - * Returns : Number of bytes left to DMA - */ -int arch_get_dma_residue(dmach_t channel, dma_t *dma); - -/* Prototype: int arch_set_dma_speed(channel, dma, cycle) - * Purpose : Convert a cycle time to a register setting - * Params : channel - DMA channel number - * : dma - DMA structure for channel - * : cycle - cycle time in NS - * Returns : setting for 'dma->speed' - */ -int arch_set_dma_speed(dmach_t channel, dma_t *dma, int cycle); + struct dma_ops *d_ops; +}; /* Prototype: void arch_dma_init(dma) * Purpose : Initialise architecture specific DMA diff --git a/arch/arm/kernel/ecard.c b/arch/arm/kernel/ecard.c index b4d38e00f..5acfd9f24 100644 --- a/arch/arm/kernel/ecard.c +++ b/arch/arm/kernel/ecard.c @@ -44,12 +44,6 @@ #include <asm/pgalloc.h> #include <asm/mmu_context.h> -#ifdef CONFIG_ARCH_ARC -#include <asm/arch/oldlatches.h> -#else -#define oldlatch_init() -#endif - #ifndef CONFIG_ARCH_RPC #define HAVE_EXPMASK #endif @@ -378,7 +372,8 @@ ecard_call(struct ecard_request *req) ecard_task_reset(req); } else { if (ecard_pid <= 0) - ecard_pid = kernel_thread(ecard_task, NULL, 0); + ecard_pid = kernel_thread(ecard_task, NULL, + CLONE_FS | CLONE_FILES | CLONE_SIGHAND); ecard_req = req; @@ -1062,8 +1057,6 @@ void __init ecard_init(void) { int slot; - oldlatch_init(); - #ifdef CONFIG_CPU_32 init_waitqueue_head(&ecard_wait); init_waitqueue_head(&ecard_done); diff --git a/arch/arm/kernel/hw-sa1100.c b/arch/arm/kernel/hw-sa1100.c index 862c3a2c4..27786cdd2 100644 --- a/arch/arm/kernel/hw-sa1100.c +++ b/arch/arm/kernel/hw-sa1100.c @@ -81,6 +81,24 @@ void __init get_assabet_scr(void) #endif /* CONFIG_SA1100_ASSABET */ +/* + * Bitsy has extended, write-only memory-mapped GPIO's + */ +#if defined(CONFIG_SA1100_BITSY) +static int bitsy_egpio = EGPIO_BITSY_RS232_ON; +void clr_bitsy_egpio(unsigned long x) +{ + bitsy_egpio &= ~x; + *(volatile int *)0xdc000000 = bitsy_egpio; +} +void set_bitsy_egpio(unsigned long x) +{ + bitsy_egpio |= x; + *(volatile int *)0xdc000000 = bitsy_egpio; +} +EXPORT_SYMBOL(clr_bitsy_egpio); +EXPORT_SYMBOL(set_bitsy_egpio); +#endif #ifdef CONFIG_SA1111 diff --git a/arch/arm/kernel/oldlatches.c b/arch/arm/kernel/oldlatches.c index a908241d2..3d6758ff4 100644 --- a/arch/arm/kernel/oldlatches.c +++ b/arch/arm/kernel/oldlatches.c @@ -3,52 +3,53 @@ * * (c) David Alan Gilbert 1995/1996 */ +#include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> #include <asm/io.h> #include <asm/hardware.h> -#ifdef LATCHAADDR -/* - * They are static so that everyone who accesses them has to go through here - */ -static unsigned char LatchACopy; +static unsigned char latch_a_copy; +static unsigned char latch_b_copy; /* newval=(oldval & ~mask)|newdata */ void oldlatch_aupdate(unsigned char mask,unsigned char newdata) { - LatchACopy=(LatchACopy & ~mask)|newdata; - outb(LatchACopy, LATCHAADDR); -#ifdef DEBUG - printk("oldlatch_A:0x%2x\n",LatchACopy); -#endif + if (machine_is_arc()) { + latch_a_copy = (latch_a_copy & ~mask) | newdata; + + printk("Latch: A = 0x%02x\n", latch_a_copy); + outb(latch_a_copy, LATCHAADDR); + } else + BUG(); } -#endif -#ifdef LATCHBADDR -static unsigned char LatchBCopy; /* newval=(oldval & ~mask)|newdata */ void oldlatch_bupdate(unsigned char mask,unsigned char newdata) { - LatchBCopy=(LatchBCopy & ~mask)|newdata; - outb(LatchBCopy, LATCHBADDR); -#ifdef DEBUG - printk("oldlatch_B:0x%2x\n",LatchBCopy); -#endif + if (machine_is_arc()) { + latch_b_copy = (latch_b_copy & ~mask) | newdata; + + printk("Latch: B = 0x%02x\n", latch_b_copy); + + outb(latch_b_copy, LATCHBADDR); + } else + BUG(); } -#endif -void __init oldlatch_init(void) +static void __init oldlatch_init(void) { - printk("oldlatch: init\n"); -#ifdef LATCHAADDR - oldlatch_aupdate(0xff,0xff); -#endif -#ifdef LATCHBADDR - oldlatch_bupdate(0xff,0x8); /* Thats no FDC reset...*/ -#endif - return ; + if (machine_is_arc()) { + oldlatch_aupdate(0xff, 0xff); + /* Thats no FDC reset...*/ + oldlatch_bupdate(0xff, LATCHB_FDCRESET); + } } + +initcall(oldlatch_init); + +EXPORT_SYMBOL(oldlatch_aupdate); +EXPORT_SYMBOL(oldlatch_bupdate); diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c index f281f7337..3ef5bc59d 100644 --- a/arch/arm/kernel/process.c +++ b/arch/arm/kernel/process.c @@ -67,6 +67,12 @@ __setup("nohlt", nohlt_setup); __setup("hlt", hlt_setup); /* + * The following aren't currently used. + */ +void (*pm_idle)(void); +void (*pm_power_off)(void); + +/* * The idle thread. We try to conserve power, while trying to keep * overall latency low. The architecture specific idle is passed * a value to indicate the level of "idleness" of the system. @@ -79,7 +85,11 @@ void cpu_idle(void) current->counter = -100; while (1) { - arch_idle(); + void (*idle)(void) = pm_idle; + if (!idle) + idle = arch_idle; + while (!current->need_resched) + idle(); schedule(); #ifndef CONFIG_NO_PGT_CACHE check_pgt_cache(); @@ -97,6 +107,16 @@ int __init reboot_setup(char *str) __setup("reboot=", reboot_setup); +void machine_halt(void) +{ +} + +void machine_power_off(void) +{ + if (pm_power_off) + pm_power_off(); +} + void machine_restart(char * __unused) { /* @@ -125,15 +145,6 @@ void machine_restart(char * __unused) while (1); } -void machine_halt(void) -{ -} - -void machine_power_off(void) -{ - arch_power_off(); -} - void show_regs(struct pt_regs * regs) { unsigned long flags; diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c index 3e6cf6cb4..4d489bcf3 100644 --- a/arch/arm/kernel/signal.c +++ b/arch/arm/kernel/signal.c @@ -586,7 +586,6 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs, int syscall) /* FALLTHRU */ default: - lock_kernel(); sigaddset(¤t->signal, signr); recalc_sigpending(current); current->flags |= PF_SIGNALED; diff --git a/arch/arm/kernel/sys_arm.c b/arch/arm/kernel/sys_arm.c index 2c3cabadc..6d49e1427 100644 --- a/arch/arm/kernel/sys_arm.c +++ b/arch/arm/kernel/sys_arm.c @@ -11,9 +11,8 @@ #include <linux/errno.h> #include <linux/sched.h> +#include <linux/malloc.h> #include <linux/mm.h> -#include <linux/smp.h> -#include <linux/smp_lock.h> #include <linux/sem.h> #include <linux/msg.h> #include <linux/shm.h> diff --git a/arch/arm/kernel/time.c b/arch/arm/kernel/time.c index d7f6640eb..da437639f 100644 --- a/arch/arm/kernel/time.c +++ b/arch/arm/kernel/time.c @@ -30,7 +30,7 @@ extern int setup_arm_irq(int, struct irqaction *); extern void setup_timer(void); extern rwlock_t xtime_lock; -extern volatile unsigned long lost_ticks; +extern unsigned long wall_jiffies; /* change this if you have some constant time drift */ #define USECS_PER_JIFFY (1000000/HZ) @@ -189,7 +189,7 @@ void do_gettimeofday(struct timeval *tv) read_lock_irqsave(&xtime_lock, flags); usec = gettimeoffset(); { - unsigned long lost = lost_ticks; + unsigned long lost = jiffies - wall_jiffies; if (lost) usec += lost * USECS_PER_JIFFY; @@ -218,7 +218,7 @@ void do_settimeofday(struct timeval *tv) * would have done, and then undo it! */ tv->tv_usec -= gettimeoffset(); - tv->tv_usec -= lost_ticks * USECS_PER_JIFFY; + tv->tv_usec -= (jiffies - wall_jiffies) * USECS_PER_JIFFY; while (tv->tv_usec < 0) { tv->tv_usec += 1000000; diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c index 188f89722..c76a95736 100644 --- a/arch/arm/kernel/traps.c +++ b/arch/arm/kernel/traps.c @@ -37,9 +37,6 @@ char *processor_modes[]= "UK8_32" , "UK9_32" , "UK10_32", "UND_32" , "UK12_32", "UK13_32", "UK14_32", "SYS_32" }; -/* proc/system.h */ -const char xchg_str[] = "xchg"; - static const char *handler[]= { "prefetch abort", "data abort", "address exception", "interrupt" }; static inline void console_verbose(void) |