Commit afc275d8 authored by Paul Mundt's avatar Paul Mundt Committed by Linus Torvalds

[PATCH] sh64 support

This patch adds sh64 support.

This is a bit overdue, as this was on the should-fix list, though we
weren't done debugging and finishing off the port until just recently (I
did a port against 2.5.68 but it wasn't in any shape to be merged).

sh64 is already in 2.4 and has been for quite awhile, so this is mostly
just a forward port of that code to 2.6 with appropriate bug fixes, etc.
along the way.  There isn't much in the way of new features that have been
added to the port yet, though I have added rough hugetlb and oprofile
support.

This patch doesn't really touch any common code, with the exception of an
ifdef or two for keyboard support and an ifdef in fb.h to omit sh64 from
the __raw_xxx() wrapping that sh does.

The only other common driver changes were to sh-sci for serial support, but
those bits were already merged with the latest batch of sh-sci updates.

Beyond that, the port is completely isolated.
Signed-off-by: default avatarRichard Curnow <richard.curnow@superh.com>
Signed-off-by: default avatarPaul Mundt <lethal@linux-sh.org>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 7f93b631
#
# For a description of the syntax of this configuration file,
# see Documentation/kbuild/config-language.txt.
#
mainmenu "Linux/SH64 Kernel Configuration"
config SUPERH
bool
default y
config SUPERH64
bool
default y
config MMU
bool
default y
config UID16
bool
default y
config RWSEM_GENERIC_SPINLOCK
bool
default y
config LOG_BUF_SHIFT
int
default 14
config RWSEM_XCHGADD_ALGORITHM
bool
config GENERIC_ISA_DMA
bool
source init/Kconfig
menu "System type"
choice
prompt "SuperH system type"
default SH_SIMULATOR
config SH_GENERIC
bool "Generic"
config SH_SIMULATOR
bool "Simulator"
config SH_CAYMAN
bool "Cayman"
config SH_ROMRAM
bool "ROM/RAM"
config SH_HARP
bool "ST50-Harp"
endchoice
choice
prompt "Processor family"
default CPU_SH5
config CPU_SH5
bool "SH-5"
endchoice
choice
prompt "Processor type"
config CPU_SUBTYPE_SH5_101
bool "SH5-101"
depends on CPU_SH5
config CPU_SUBTYPE_SH5_103
bool "SH5-103"
depends on CPU_SH5
endchoice
choice
prompt "Endianness"
default LITTLE_ENDIAN
config LITTLE_ENDIAN
bool "Little-Endian"
config BIG_ENDIAN
bool "Big-Endian"
endchoice
config SH64_FPU_DENORM_FLUSH
bool "Flush floating point denorms to zero"
choice
prompt "Page table levels"
default SH64_PGTABLE_2_LEVEL
config SH64_PGTABLE_2_LEVEL
bool "2"
config SH64_PGTABLE_3_LEVEL
bool "3"
endchoice
choice
prompt "HugeTLB page size"
depends on HUGETLB_PAGE && MMU
default HUGETLB_PAGE_SIZE_64K
config HUGETLB_PAGE_SIZE_64K
bool "64K"
config HUGETLB_PAGE_SIZE_1MB
bool "1MB"
config HUGETLB_PAGE_SIZE_512MB
bool "512MB"
endchoice
config SH64_USER_MISALIGNED_FIXUP
bool "Fixup misaligned loads/stores occurring in user mode"
comment "Memory options"
config CACHED_MEMORY_OFFSET
hex "Cached Area Offset"
depends on SH_HARP || SH_CAYMAN || SH_SIMULATOR
default "20000000"
config MEMORY_START
hex "Physical memory start address"
depends on SH_HARP || SH_CAYMAN || SH_SIMULATOR
default "80000000"
config MEMORY_SIZE_IN_MB
int "Memory size (in MB)" if SH_HARP || SH_CAYMAN || SH_SIMULATOR
default "64" if SH_HARP || SH_CAYMAN
default "8" if SH_SIMULATOR
comment "Cache options"
config DCACHE_DISABLED
bool "DCache Disabling"
depends on SH_HARP || SH_CAYMAN || SH_SIMULATOR
choice
prompt "DCache mode"
depends on !DCACHE_DISABLED && !SH_SIMULATOR
default DCACHE_WRITE_BACK
config DCACHE_WRITE_BACK
bool "Write-back"
config DCACHE_WRITE_THROUGH
bool "Write-through"
endchoice
config ICACHE_DISABLED
bool "ICache Disabling"
depends on SH_HARP || SH_CAYMAN || SH_SIMULATOR
config PCIDEVICE_MEMORY_START
hex
depends on SH_HARP || SH_CAYMAN || SH_SIMULATOR
default "C0000000"
config DEVICE_MEMORY_START
hex
depends on SH_HARP || SH_CAYMAN || SH_SIMULATOR
default "E0000000"
config FLASH_MEMORY_START
hex "Flash memory/on-chip devices start address"
depends on SH_HARP || SH_CAYMAN || SH_SIMULATOR
default "00000000"
config PCI_BLOCK_START
hex "PCI block start address"
depends on SH_HARP || SH_CAYMAN || SH_SIMULATOR
default "40000000"
comment "CPU Subtype specific options"
config SH64_ID2815_WORKAROUND
bool "Include workaround for SH5-101 cut2 silicon defect ID2815"
comment "Misc options"
config HEARTBEAT
bool "Heartbeat LED"
config HDSP253_LED
bool "Support for HDSP-253 LED"
depends on SH_CAYMAN
config SH_DMA
tristate "DMA controller (DMAC) support"
config PREEMPT
bool "Preemptible Kernel (EXPERIMENTAL)"
depends on EXPERIMENTAL
endmenu
menu "Bus options (PCI, PCMCIA, EISA, MCA, ISA)"
config ISA
bool
config SBUS
bool
config PCI
bool "PCI support"
help
Find out whether you have a PCI motherboard. PCI is the name of a
bus system, i.e. the way the CPU talks to the other stuff inside
your box. Other bus systems are ISA, EISA, MicroChannel (MCA) or
VESA. If you have PCI, say Y, otherwise N.
The PCI-HOWTO, available from
<http://www.tldp.org/docs.html#howto>, contains valuable
information about which PCI hardware does work under Linux and which
doesn't.
config SH_PCIDMA_NONCOHERENT
bool "Cache and PCI noncoherent"
depends on PCI
default y
help
Enable this option if your platform does not have a CPU cache which
remains coherent with PCI DMA. It is safest to say 'Y', although you
will see better performance if you can say 'N', because the PCI DMA
code will not have to flush the CPU's caches. If you have a PCI host
bridge integrated with your SH CPU, refer carefully to the chip specs
to see if you can say 'N' here. Otherwise, leave it as 'Y'.
source "drivers/pci/Kconfig"
source "drivers/pcmcia/Kconfig"
source "drivers/pci/hotplug/Kconfig"
endmenu
menu "Executable file formats"
source "fs/Kconfig.binfmt"
endmenu
source "drivers/Kconfig"
source "fs/Kconfig"
source "arch/sh64/oprofile/Kconfig"
menu "Kernel hacking"
config MAGIC_SYSRQ
bool "Magic SysRq key"
help
If you say Y here, you will have some control over the system even
if the system crashes for example during kernel debugging (e.g., you
will be able to flush the buffer cache to disk, reboot the system
immediately or dump some status information). This is accomplished
by pressing various keys while holding SysRq (Alt+PrintScreen). It
also works on a serial console (on PC hardware at least), if you
send a BREAK and then within 5 seconds a command keypress. The
keys are documented in Documentation/sysrq.txt. Don't say Y unless
you really know what this hack does.
config EARLY_PRINTK
bool "Early SCIF console support"
config DEBUG_KERNEL_WITH_GDB_STUB
bool "GDB Stub kernel debug"
config SH64_PROC_TLB
bool "Debug: report TLB fill/purge activity through /proc/tlb"
depends on PROC_FS
config SH64_PROC_ASIDS
bool "Debug: report ASIDs through /proc/asids"
depends on PROC_FS
config SH64_SR_WATCH
bool "Debug: set SR.WATCH to enable hardware watchpoints and trace"
config SH_ALPHANUMERIC
bool "Enable debug outputs to on-board alphanumeric display"
config SH_NO_BSS_INIT
bool "Avoid zeroing BSS (to speed-up startup on suitable platforms)"
config FRAME_POINTER
bool "Compile the kernel with frame pointers"
default y if KGDB
help
If you say Y here the resulting kernel image will be slightly larger
and slower, but it will give very useful debugging information.
If you don't debug the kernel, you can say N, but we may not be able
to solve problems without frame pointers.
endmenu
source "security/Kconfig"
source "crypto/Kconfig"
source "lib/Kconfig"
#
# This file is subject to the terms and conditions of the GNU General Public
# License. See the file "COPYING" in the main directory of this archive
# for more details.
#
# Copyright (C) 2000, 2001 Paolo Alberelli
# Copyright (C) 2003, 2004 Paul Mundt
#
# This file is included by the global makefile so that you can add your own
# architecture-specific flags and dependencies. Remember to do have actions
# for "archclean" and "archdep" for cleaning up and making dependencies for
# this architecture
#
# Note that top level Makefile automagically builds dependencies for SUBDIRS
# but does not automagically clean SUBDIRS. Therefore "archclean" should clean
# up all, "archdep" does nothing on added SUBDIRS.
#
ifndef include_config
-include .config
endif
cpu-y := -mb
cpu-$(CONFIG_LITTLE_ENDIAN) := -ml
cpu-$(CONFIG_CPU_SH5) += -m5-32media-nofpu
ifdef CONFIG_LITTLE_ENDIAN
LDFLAGS_vmlinux += --defsym 'jiffies=jiffies_64'
LDFLAGS += -EL -mshlelf32_linux
else
LDFLAGS_vmlinux += --defsym 'jiffies=jiffies_64+4'
LDFLAGS += -EB -mshelf32_linux
endif
# No requirements for endianess support from AFLAGS, 'as' always run through gcc
AFLAGS += -m5 -isa=sh64 -traditional
CFLAGS += $(cpu-y)
LDFLAGS_vmlinux += --defsym phys_stext=_stext-$(CONFIG_CACHED_MEMORY_OFFSET) \
-e phys_stext
OBJCOPYFLAGS := -O binary -R .note -R .comment -R .stab -R .stabstr -S
ifdef LOADADDR
LINKFLAGS += -Ttext $(word 1,$(LOADADDR))
endif
machine-$(CONFIG_SH_CAYMAN) := cayman
machine-$(CONFIG_SH_SIMULATOR) := sim
machine-$(CONFIG_SH_HARP) := harp
machine-$(CONFIG_SH_ROMRAM) := romram
head-y := arch/$(ARCH)/kernel/head.o arch/$(ARCH)/kernel/init_task.o
core-y += $(addprefix arch/$(ARCH)/, kernel/ mm/ mach-$(machine-y)/)
LIBGCC := $(shell $(CC) $(CFLAGS) -print-libgcc-file-name)
libs-y += arch/$(ARCH)/lib/ $(LIBGCC)
drivers-$(CONFIG_OPROFILE) += arch/sh64/oprofile/
boot := arch/$(ARCH)/boot
zImage: vmlinux
$(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
compressed: zImage
archclean:
$(Q)$(MAKE) $(clean)=$(boot)
prepare: include/asm-$(ARCH)/asm-offsets.h arch/$(ARCH)/lib/syscalltab.h
include/asm-$(ARCH)/asm-offsets.h: arch/$(ARCH)/kernel/asm-offsets.s \
include/asm include/linux/version.h
$(call filechk,gen-asm-offsets)
define filechk_gen-syscalltab
(set -e; \
echo "/*"; \
echo " * DO NOT MODIFY."; \
echo " *"; \
echo " * This file was generated by arch/$(ARCH)/Makefile"; \
echo " * Any changes will be reverted at build time."; \
echo " */"; \
echo ""; \
echo "#ifndef __SYSCALLTAB_H"; \
echo "#define __SYSCALLTAB_H"; \
echo ""; \
echo "#include <linux/kernel.h>"; \
echo ""; \
echo "struct syscall_info {"; \
echo " const char *name;"; \
echo "} syscall_info_table[] = {"; \
sed -e '/^.*\.long /!d;s//\t{ "/;s/\(\([^/]*\)\/\)\{1\}.*/\2/; \
s/[ \t]*$$//g;s/$$/" },/;s/\("\)sys_/\1/g'; \
echo "};"; \
echo ""; \
echo "#define NUM_SYSCALL_INFO_ENTRIES ARRAY_SIZE(syscall_info_table)"; \
echo ""; \
echo "#endif /* __SYSCALLTAB_H */" )
endef
arch/$(ARCH)/lib/syscalltab.h: arch/sh64/kernel/syscalls.S
$(call filechk,gen-syscalltab)
CLEAN_FILES += include/asm-$(ARCH)/asm-offsets.h arch/$(ARCH)/lib/syscalltab.h
define archhelp
@echo ' zImage - Compressed kernel image (arch/sh64/boot/zImage)'
endef
#
# arch/sh64/boot/Makefile
#
# This file is subject to the terms and conditions of the GNU General Public
# License. See the file "COPYING" in the main directory of this archive
# for more details.
#
# Copyright (C) 2002 Stuart Menefy
#
targets := zImage
subdir- := compressed
$(obj)/zImage: $(obj)/compressed/vmlinux FORCE
$(call if_changed,objcopy)
@echo 'Kernel: $@ is ready'
$(obj)/compressed/vmlinux: FORCE
$(Q)$(MAKE) $(build)=$(obj)/compressed $@
#
# linux/arch/sh64/boot/compressed/Makefile
#
# This file is subject to the terms and conditions of the GNU General Public
# License. See the file "COPYING" in the main directory of this archive
# for more details.
#
# Copyright (C) 2002 Stuart Menefy
# Copyright (C) 2004 Paul Mundt
#
# create a compressed vmlinux image from the original vmlinux
#
targets := vmlinux vmlinux.bin vmlinux.bin.gz \
head.o misc.o cache.o piggy.o vmlinux.lds.o
EXTRA_AFLAGS := -traditional
OBJECTS := $(obj)/head.o $(obj)/misc.o $(obj)/cache.o
#
# ZIMAGE_OFFSET is the load offset of the compression loader
# (4M for the kernel plus 64K for this loader)
#
ZIMAGE_OFFSET = $(shell printf "0x%8x" $$[$(CONFIG_MEMORY_START)+0x400000+0x10000])
LDFLAGS_vmlinux := -Ttext $(ZIMAGE_OFFSET) -e startup \
-T $(obj)/../../kernel/vmlinux.lds.s \
--no-warn-mismatch
$(obj)/vmlinux: $(OBJECTS) $(obj)/piggy.o FORCE
$(call if_changed,ld)
@:
$(obj)/vmlinux.bin: vmlinux FORCE
$(call if_changed,objcopy)
$(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin FORCE
$(call if_changed,gzip)
LDFLAGS_piggy.o := -r --format binary --oformat elf32-sh64-linux -T
OBJCOPYFLAGS += -R .empty_zero_page
$(obj)/piggy.o: $(obj)/vmlinux.lds.s $(obj)/vmlinux.bin.gz FORCE
$(call if_changed,ld)
/*
* arch/shmedia/boot/compressed/cache.c -- simple cache management functions
*
* Code extracted from sh-ipl+g, sh-stub.c, which has the copyright:
*
* This is originally based on an m68k software stub written by Glenn
* Engel at HP, but has changed quite a bit.
*
* Modifications for the SH by Ben Lee and Steve Chamberlain
*
****************************************************************************
THIS SOFTWARE IS NOT COPYRIGHTED
HP offers the following for use in the public domain. HP makes no
warranty with regard to the software or it's performance and the
user accepts the software "AS IS" with all faults.
HP DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD
TO THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
****************************************************************************/
#define CACHE_ENABLE 0
#define CACHE_DISABLE 1
int cache_control(unsigned int command)
{
volatile unsigned int *p = (volatile unsigned int *) 0x80000000;
int i;
for (i = 0; i < (32 * 1024); i += 32) {
(void *) *p;
p += (32 / sizeof (int));
}
return 0;
}
/*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* arch/shmedia/boot/compressed/head.S
*
* Copied from
* arch/shmedia/kernel/head.S
* which carried the copyright:
* Copyright (C) 2000, 2001 Paolo Alberelli
*
* Modification for compressed loader:
* Copyright (C) 2002 Stuart Menefy (stuart.menefy@st.com)
*/
#include <linux/linkage.h>
#include <asm/registers.h>
#include <asm/cache.h>
#include <asm/mmu_context.h>
/*
* Fixed TLB entries to identity map the beginning of RAM
*/
#define MMUIR_TEXT_H 0x0000000000000003 | CONFIG_MEMORY_START
/* Enabled, Shared, ASID 0, Eff. Add. 0xA0000000 */
#define MMUIR_TEXT_L 0x000000000000009a | CONFIG_MEMORY_START
/* 512 Mb, Cacheable (Write-back), execute, Not User, Ph. Add. */
#define MMUDR_CACHED_H 0x0000000000000003 | CONFIG_MEMORY_START
/* Enabled, Shared, ASID 0, Eff. Add. 0xA0000000 */
#define MMUDR_CACHED_L 0x000000000000015a | CONFIG_MEMORY_START
/* 512 Mb, Cacheable (Write-back), read/write, Not User, Ph. Add. */
#define ICCR0_INIT_VAL ICCR0_ON | ICCR0_ICI /* ICE + ICI */
#define ICCR1_INIT_VAL ICCR1_NOLOCK /* No locking */
#if 1
#define OCCR0_INIT_VAL OCCR0_ON | OCCR0_OCI | OCCR0_WB /* OCE + OCI + WB */
#else
#define OCCR0_INIT_VAL OCCR0_OFF
#endif
#define OCCR1_INIT_VAL OCCR1_NOLOCK /* No locking */
.text
.global startup
startup:
/*
* Prevent speculative fetch on device memory due to
* uninitialized target registers.
* This must be executed before the first branch.
*/
ptabs/u ZERO, tr0
ptabs/u ZERO, tr1
ptabs/u ZERO, tr2
ptabs/u ZERO, tr3
ptabs/u ZERO, tr4
ptabs/u ZERO, tr5
ptabs/u ZERO, tr6
ptabs/u ZERO, tr7
synci
/*
* Set initial TLB entries for cached and uncached regions.
* Note: PTA/BLINK is PIC code, PTABS/BLINK isn't !
*/
/* Clear ITLBs */
pta 1f, tr1
movi ITLB_FIXED, r21
movi ITLB_LAST_VAR_UNRESTRICTED+TLB_STEP, r22
1: putcfg r21, 0, ZERO /* Clear MMUIR[n].PTEH.V */
addi r21, TLB_STEP, r21
bne r21, r22, tr1
/* Clear DTLBs */
pta 1f, tr1
movi DTLB_FIXED, r21
movi DTLB_LAST_VAR_UNRESTRICTED+TLB_STEP, r22
1: putcfg r21, 0, ZERO /* Clear MMUDR[n].PTEH.V */
addi r21, TLB_STEP, r21
bne r21, r22, tr1
/* Map one big (512Mb) page for ITLB */
movi ITLB_FIXED, r21
movi MMUIR_TEXT_L, r22 /* PTEL first */
putcfg r21, 1, r22 /* Set MMUIR[0].PTEL */
movi MMUIR_TEXT_H, r22 /* PTEH last */
putcfg r21, 0, r22 /* Set MMUIR[0].PTEH */
/* Map one big CACHED (512Mb) page for DTLB */
movi DTLB_FIXED, r21
movi MMUDR_CACHED_L, r22 /* PTEL first */
putcfg r21, 1, r22 /* Set MMUDR[0].PTEL */
movi MMUDR_CACHED_H, r22 /* PTEH last */
putcfg r21, 0, r22 /* Set MMUDR[0].PTEH */
/* ICache */
movi ICCR_BASE, r21
movi ICCR0_INIT_VAL, r22
movi ICCR1_INIT_VAL, r23
putcfg r21, ICCR_REG0, r22
putcfg r21, ICCR_REG1, r23
synci
/* OCache */
movi OCCR_BASE, r21
movi OCCR0_INIT_VAL, r22
movi OCCR1_INIT_VAL, r23
putcfg r21, OCCR_REG0, r22
putcfg r21, OCCR_REG1, r23
synco
/*
* Enable the MMU.
* From here-on code can be non-PIC.
*/
movi SR_HARMLESS | SR_ENABLE_MMU, r22
putcon r22, SSR
movi 1f, r22
putcon r22, SPC
synco
rte /* And now go into the hyperspace ... */
1: /* ... that's the next instruction ! */
/* Set initial stack pointer */
movi datalabel stack_start, r0
ld.l r0, 0, r15
/*
* Clear bss
*/
pt 1f, tr1
movi datalabel __bss_start, r22
movi datalabel _end, r23
1: st.l r22, 0, ZERO
addi r22, 4, r22
bne r22, r23, tr1
/*
* Decompress the kernel.
*/
pt decompress_kernel, tr0
blink tr0, r18
/*
* Disable the MMU.
*/
movi SR_HARMLESS, r22
putcon r22, SSR
movi 1f, r22
putcon r22, SPC
synco
rte /* And now go into the hyperspace ... */
1: /* ... that's the next instruction ! */
/* Jump into the decompressed kernel */
movi datalabel (CONFIG_MEMORY_START + 0x2000)+1, r19
ptabs r19, tr0
blink tr0, r18
/* Shouldn't return here, but just in case, loop forever */
pt 1f, tr0
1: blink tr0, ZERO
#!/bin/sh
#
# arch/sh/boot/install.sh
#
# This file is subject to the terms and conditions of the GNU General Public
# License. See the file "COPYING" in the main directory of this archive
# for more details.
#
# Copyright (C) 1995 by Linus Torvalds
#
# Adapted from code in arch/i386/boot/Makefile by H. Peter Anvin
# Adapted from code in arch/i386/boot/install.sh by Russell King
# Adapted from code in arch/arm/boot/install.sh by Stuart Menefy
#
# "make install" script for sh architecture
#
# Arguments:
# $1 - kernel version
# $2 - kernel image file
# $3 - kernel map file
# $4 - default install path (blank if root directory)
#
# User may have a custom install script
if [ -x /sbin/installkernel ]; then
exec /sbin/installkernel "$@"
fi
if [ "$2" = "zImage" ]; then
# Compressed install
echo "Installing compressed kernel"
if [ -f $4/vmlinuz-$1 ]; then
mv $4/vmlinuz-$1 $4/vmlinuz.old
fi
if [ -f $4/System.map-$1 ]; then
mv $4/System.map-$1 $4/System.old
fi
cat $2 > $4/vmlinuz-$1
cp $3 $4/System.map-$1
else
# Normal install
echo "Installing normal kernel"
if [ -f $4/vmlinux-$1 ]; then
mv $4/vmlinux-$1 $4/vmlinux.old
fi
if [ -f $4/System.map ]; then
mv $4/System.map $4/System.old
fi
cat $2 > $4/vmlinux-$1
cp $3 $4/System.map
fi
/*
* arch/shmedia/boot/compressed/misc.c
*
* This is a collection of several routines from gzip-1.0.3
* adapted for Linux.
*
* malloc by Hannu Savolainen 1993 and Matthias Urlichs 1994
*
* Adapted for SHmedia from sh by Stuart Menefy, May 2002
*/
#include <linux/config.h>
#include <asm/uaccess.h>
/* cache.c */
#define CACHE_ENABLE 0
#define CACHE_DISABLE 1
int cache_control(unsigned int command);
/*
* gzip declarations
*/
#define OF(args) args
#define STATIC static
#undef memset
#undef memcpy
#define memzero(s, n) memset ((s), 0, (n))
typedef unsigned char uch;
typedef unsigned short ush;
typedef unsigned long ulg;
#define WSIZE 0x8000 /* Window size must be at least 32k, */
/* and a power of two */
static uch *inbuf; /* input buffer */
static uch window[WSIZE]; /* Sliding window buffer */
static unsigned insize = 0; /* valid bytes in inbuf */
static unsigned inptr = 0; /* index of next byte to be processed in inbuf */
static unsigned outcnt = 0; /* bytes in output buffer */
/* gzip flag byte */
#define ASCII_FLAG 0x01 /* bit 0 set: file probably ASCII text */
#define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */
#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */
#define ORIG_NAME 0x08 /* bit 3 set: original file name present */
#define COMMENT 0x10 /* bit 4 set: file comment present */
#define ENCRYPTED 0x20 /* bit 5 set: file is encrypted */
#define RESERVED 0xC0 /* bit 6,7: reserved */
#define get_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf())
/* Diagnostic functions */
#ifdef DEBUG
# define Assert(cond,msg) {if(!(cond)) error(msg);}
# define Trace(x) fprintf x
# define Tracev(x) {if (verbose) fprintf x ;}
# define Tracevv(x) {if (verbose>1) fprintf x ;}
# define Tracec(c,x) {if (verbose && (c)) fprintf x ;}
# define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;}
#else
# define Assert(cond,msg)
# define Trace(x)
# define Tracev(x)
# define Tracevv(x)
# define Tracec(c,x)
# define Tracecv(c,x)
#endif
static int fill_inbuf(void);
static void flush_window(void);
static void error(char *m);
static void gzip_mark(void **);
static void gzip_release(void **);
extern char input_data[];
extern int input_len;
static long bytes_out = 0;
static uch *output_data;
static unsigned long output_ptr = 0;
static void *malloc(int size);
static void free(void *where);
static void error(char *m);
static void gzip_mark(void **);
static void gzip_release(void **);
static void puts(const char *);
extern int _text; /* Defined in vmlinux.lds.S */
extern int _end;
static unsigned long free_mem_ptr;
static unsigned long free_mem_end_ptr;
#define HEAP_SIZE 0x10000
#include "../../../../lib/inflate.c"
static void *malloc(int size)
{
void *p;
if (size < 0)
error("Malloc error\n");
if (free_mem_ptr == 0)
error("Memory error\n");
free_mem_ptr = (free_mem_ptr + 3) & ~3; /* Align */
p = (void *) free_mem_ptr;
free_mem_ptr += size;
if (free_mem_ptr >= free_mem_end_ptr)
error("\nOut of memory\n");
return p;
}
static void free(void *where)
{ /* Don't care */
}
static void gzip_mark(void **ptr)
{
*ptr = (void *) free_mem_ptr;
}
static void gzip_release(void **ptr)
{
free_mem_ptr = (long) *ptr;
}
void puts(const char *s)
{
}
void *memset(void *s, int c, size_t n)
{
int i;
char *ss = (char *) s;
for (i = 0; i < n; i++)
ss[i] = c;
return s;
}
void *memcpy(void *__dest, __const void *__src, size_t __n)
{
int i;
char *d = (char *) __dest, *s = (char *) __src;
for (i = 0; i < __n; i++)
d[i] = s[i];
return __dest;
}
/* ===========================================================================
* Fill the input buffer. This is called only when the buffer is empty
* and at least one byte is really needed.
*/
static int fill_inbuf(void)
{
if (insize != 0) {
error("ran out of input data\n");
}
inbuf = input_data;
insize = input_len;
inptr = 1;
return inbuf[0];
}
/* ===========================================================================
* Write the output window window[0..outcnt-1] and update crc and bytes_out.
* (Used for the decompressed data only.)
*/
static void flush_window(void)
{
ulg c = crc; /* temporary variable */
unsigned n;
uch *in, *out, ch;
in = window;
out = &output_data[output_ptr];
for (n = 0; n < outcnt; n++) {
ch = *out++ = *in++;
c = crc_32_tab[((int) c ^ ch) & 0xff] ^ (c >> 8);
}
crc = c;
bytes_out += (ulg) outcnt;
output_ptr += (ulg) outcnt;
outcnt = 0;
puts(".");
}
static void error(char *x)
{
puts("\n\n");
puts(x);
puts("\n\n -- System halted");
while (1) ; /* Halt */
}
#define STACK_SIZE (4096)
long __attribute__ ((aligned(8))) user_stack[STACK_SIZE];
long *stack_start = &user_stack[STACK_SIZE];
void decompress_kernel(void)
{
output_data = (uch *) (CONFIG_MEMORY_START + 0x2000);
free_mem_ptr = (unsigned long) &_end;
free_mem_end_ptr = free_mem_ptr + HEAP_SIZE;
makecrc();
puts("Uncompressing Linux... ");
cache_control(CACHE_ENABLE);
gunzip();
puts("\n");
#if 0
/* When booting from ROM may want to do something like this if the
* boot loader doesn't.
*/
/* Set up the parameters and command line */
{
volatile unsigned int *parambase =
(int *) (CONFIG_MEMORY_START + 0x1000);
parambase[0] = 0x1; /* MOUNT_ROOT_RDONLY */
parambase[1] = 0x0; /* RAMDISK_FLAGS */
parambase[2] = 0x0200; /* ORIG_ROOT_DEV */
parambase[3] = 0x0; /* LOADER_TYPE */
parambase[4] = 0x0; /* INITRD_START */
parambase[5] = 0x0; /* INITRD_SIZE */
parambase[6] = 0;
strcpy((char *) ((int) parambase + 0x100),
"console=ttySC0,38400");
}
#endif
puts("Ok, booting the kernel.\n");
cache_control(CACHE_DISABLE);
}
/*
* ld script to make compressed SuperH/shmedia Linux kernel+decompression
* bootstrap
* Modified by Stuart Menefy from arch/sh/vmlinux.lds.S written by Niibe Yutaka
*/
#include <linux/config.h>
#ifdef CONFIG_LITTLE_ENDIAN
/* OUTPUT_FORMAT("elf32-sh64l-linux", "elf32-sh64l-linux", "elf32-sh64l-linux") */
#define NOP 0x6ff0fff0
#else
/* OUTPUT_FORMAT("elf32-sh64", "elf32-sh64", "elf32-sh64") */
#define NOP 0xf0fff06f
#endif
OUTPUT_FORMAT("elf32-sh64-linux")
OUTPUT_ARCH(sh)
ENTRY(_start)
#define ALIGNED_GAP(section, align) (((ADDR(section)+SIZEOF(section)+(align)-1) & ~((align)-1))-ADDR(section))
#define FOLLOWING(section, align) AT (LOADADDR(section) + ALIGNED_GAP(section,align))
SECTIONS
{
_text = .; /* Text and read-only data */
.text : {
*(.text)
*(.text64)
*(.text..SHmedia32)
*(.fixup)
*(.gnu.warning)
} = NOP
. = ALIGN(4);
.rodata : { *(.rodata) }
/* There is no 'real' reason for eight byte alignment, four would work
* as well, but gdb downloads much (*4) faster with this.
*/
. = ALIGN(8);
.image : { *(.image) }
. = ALIGN(4);
_etext = .; /* End of text section */
.data : /* Data */
FOLLOWING(.image, 4)
{
_data = .;
*(.data)
}
_data_image = LOADADDR(.data);/* Address of data section in ROM */
_edata = .; /* End of data section */
.stack : { stack = .; _stack = .; }
. = ALIGN(4);
__bss_start = .; /* BSS */
.bss : {
*(.bss)
}
. = ALIGN(4);
_end = . ;
}
This diff is collapsed.
This diff is collapsed.
#
# This file is subject to the terms and conditions of the GNU General Public
# License. See the file "COPYING" in the main directory of this archive
# for more details.
#
# Copyright (C) 2000, 2001 Paolo Alberelli
# Copyright (C) 2003 Paul Mundt
#
# Makefile for the Linux sh64 kernel.
#
# 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).
#
extra-y := head.o init_task.o vmlinux.lds.s
obj-y := process.o signal.o entry.o traps.o irq.o irq_intc.o \
ptrace.o setup.o time.o sys_sh64.o semaphore.o sh_ksyms.o \
switchto.o syscalls.o
obj-$(CONFIG_HEARTBEAT) += led.o
obj-$(CONFIG_SH_ALPHANUMERIC) += alphanum.o
obj-$(CONFIG_SH_DMA) += dma.o
obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
obj-$(CONFIG_KALLSYMS) += unwind.o
obj-$(CONFIG_PCI) += pci-dma.o pcibios.o
ifeq ($(CONFIG_PCI),y)
obj-$(CONFIG_CPU_SH5) += pci_sh5.o
endif
ifndef CONFIG_NOFPU_SUPPORT
obj-y += fpu.o
endif
USE_STANDARD_AS_RULE := true
/*
* arch/sh64/kernel/alpanum.c
*
* Copyright (C) 2002 Stuart Menefy <stuart.menefy@st.com>
*
* May be copied or modified under the terms of the GNU General Public
* License. See linux/COPYING for more information.
*
* Machine-independent functions for handling 8-digit alphanumeric display
* (e.g. Agilent HDSP-253x)
*/
#include <linux/config.h>
#include <linux/stddef.h>
#include <linux/sched.h>
void mach_alphanum(int pos, unsigned char val);
void mach_led(int pos, int val);
void print_seg(char *file, int line)
{
int i;
unsigned int nibble;
for (i = 0; i < 5; i++) {
mach_alphanum(i, file[i]);
}
for (i = 0; i < 3; i++) {
nibble = ((line >> (i * 4)) & 0xf);
mach_alphanum(7 - i, nibble + ((nibble > 9) ? 55 : 48));
}
}
void print_seg_num(unsigned num)
{
int i;
unsigned int nibble;
for (i = 0; i < 8; i++) {
nibble = ((num >> (i * 4)) & 0xf);
mach_alphanum(7 - i, nibble + ((nibble > 9) ? 55 : 48));
}
}
/*
* This program is used to generate definitions needed by
* assembly language modules.
*
* We use the technique used in the OSF Mach kernel code:
* generate asm statements containing #defines,
* compile this file to assembler, and then extract the
* #defines from the assembly-language output.
*/
#include <linux/stddef.h>
#include <linux/types.h>
#include <linux/mm.h>
#include <asm/thread_info.h>
#define DEFINE(sym, val) \
asm volatile("\n->" #sym " %0 " #val : : "i" (val))
#define BLANK() asm volatile("\n->" : : )
int main(void)
{
/* offsets into the thread_info struct */
DEFINE(TI_TASK, offsetof(struct thread_info, task));
DEFINE(TI_EXEC_DOMAIN, offsetof(struct thread_info, exec_domain));
DEFINE(TI_FLAGS, offsetof(struct thread_info, flags));
DEFINE(TI_PRE_COUNT, offsetof(struct thread_info, preempt_count));
DEFINE(TI_CPU, offsetof(struct thread_info, cpu));
DEFINE(TI_ADDR_LIMIT, offsetof(struct thread_info, addr_limit));
DEFINE(TI_RESTART_BLOCK,offsetof(struct thread_info, restart_block));
return 0;
}
/*
* arch/sh64/kernel/dma.c
*
* DMA routines for the SH-5 DMAC.
*
* Copyright (C) 2003 Paul Mundt
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*/
#include <linux/init.h>
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/types.h>
#include <linux/irq.h>
#include <linux/spinlock.h>
#include <linux/mm.h>
#include <asm/hardware.h>
#include <asm/dma.h>
#include <asm/signal.h>
#include <asm/errno.h>
#include <asm/io.h>
typedef struct {
unsigned long dev_addr;
unsigned long mem_addr;
unsigned int mode;
unsigned int count;
} dma_info_t;
static dma_info_t dma_info[MAX_DMA_CHANNELS];
extern spinlock_t dma_spin_lock;
/* arch/sh64/kernel/irq_intc.c */
extern void make_intc_irq(unsigned int irq);
/* DMAC Interrupts */
#define DMA_IRQ_DMTE0 18
#define DMA_IRQ_DERR 22
#define DMAC_COMMON_BASE (dmac_base + 0x08)
#define DMAC_SAR_BASE (dmac_base + 0x10)
#define DMAC_DAR_BASE (dmac_base + 0x18)
#define DMAC_COUNT_BASE (dmac_base + 0x20)
#define DMAC_CTRL_BASE (dmac_base + 0x28)
#define DMAC_STATUS_BASE (dmac_base + 0x30)
#define DMAC_SAR(n) (DMAC_SAR_BASE + ((n) * 0x28))
#define DMAC_DAR(n) (DMAC_DAR_BASE + ((n) * 0x28))
#define DMAC_COUNT(n) (DMAC_COUNT_BASE + ((n) * 0x28))
#define DMAC_CTRL(n) (DMAC_CTRL_BASE + ((n) * 0x28))
#define DMAC_STATUS(n) (DMAC_STATUS_BASE + ((n) * 0x28))
/* DMAC.COMMON Bit Definitions */
#define DMAC_COMMON_PR 0x00000001 /* Priority */
/* Bits 1-2 Reserved */
#define DMAC_COMMON_ME 0x00000008 /* Master Enable */
#define DMAC_COMMON_NMI 0x00000010 /* NMI Flag */
/* Bits 5-6 Reserved */
#define DMAC_COMMON_ER 0x00000780 /* Error Response */
#define DMAC_COMMON_AAE 0x00007800 /* Address Alignment Error */
/* Bits 15-63 Reserved */
/* DMAC.SAR Bit Definitions */
#define DMAC_SAR_ADDR 0xffffffff /* Source Address */
/* DMAC.DAR Bit Definitions */
#define DMAC_DAR_ADDR 0xffffffff /* Destination Address */
/* DMAC.COUNT Bit Definitions */
#define DMAC_COUNT_CNT 0xffffffff /* Transfer Count */
/* DMAC.CTRL Bit Definitions */
#define DMAC_CTRL_TS 0x00000007 /* Transfer Size */
#define DMAC_CTRL_SI 0x00000018 /* Source Increment */
#define DMAC_CTRL_DI 0x00000060 /* Destination Increment */
#define DMAC_CTRL_RS 0x00000780 /* Resource Select */
#define DMAC_CTRL_IE 0x00000800 /* Interrupt Enable */
#define DMAC_CTRL_TE 0x00001000 /* Transfer Enable */
/* Bits 15-63 Reserved */
/* DMAC.STATUS Bit Definitions */
#define DMAC_STATUS_TE 0x00000001 /* Transfer End */
#define DMAC_STATUS_AAE 0x00000002 /* Address Alignment Error */
/* Bits 2-63 Reserved */
static unsigned long dmac_base;
void set_dma_count(unsigned int chan, unsigned int count);
void set_dma_addr(unsigned int chan, unsigned int addr);
static irqreturn_t dma_mte(int irq, void *dev_id, struct pt_regs *regs)
{
unsigned int chan = irq - DMA_IRQ_DMTE0;
dma_info_t *info = dma_info + chan;
u64 status;
if (info->mode & DMA_MODE_WRITE) {
sh64_out64(info->mem_addr & DMAC_SAR_ADDR, DMAC_SAR(chan));
} else {
sh64_out64(info->mem_addr & DMAC_DAR_ADDR, DMAC_DAR(chan));
}
set_dma_count(chan, info->count);
/* Clear the TE bit */
status = sh64_in64(DMAC_STATUS(chan));
status &= ~DMAC_STATUS_TE;
sh64_out64(status, DMAC_STATUS(chan));
return IRQ_HANDLED;
}
static struct irqaction irq_dmte = {
.handler = dma_mte,
.flags = SA_INTERRUPT,
.name = "DMA MTE",
};
static irqreturn_t dma_err(int irq, void *dev_id, struct pt_regs *regs)
{
u64 tmp;
u8 chan;
printk(KERN_NOTICE "DMAC: Got a DMA Error!\n");
tmp = sh64_in64(DMAC_COMMON_BASE);
/* Check for the type of error */
if ((chan = tmp & DMAC_COMMON_AAE)) {
/* It's an address alignment error.. */
printk(KERN_NOTICE "DMAC: Alignment error on channel %d, ", chan);
printk(KERN_NOTICE "SAR: 0x%08llx, DAR: 0x%08llx, COUNT: %lld\n",
(sh64_in64(DMAC_SAR(chan)) & DMAC_SAR_ADDR),
(sh64_in64(DMAC_DAR(chan)) & DMAC_DAR_ADDR),
(sh64_in64(DMAC_COUNT(chan)) & DMAC_COUNT_CNT));
} else if ((chan = tmp & DMAC_COMMON_ER)) {
/* Something else went wrong.. */
printk(KERN_NOTICE "DMAC: Error on channel %d\n", chan);
}
/* Reset the ME bit to clear the interrupt */
tmp |= DMAC_COMMON_ME;
sh64_out64(tmp, DMAC_COMMON_BASE);
return IRQ_HANDLED;
}
static struct irqaction irq_derr = {
.handler = dma_err,
.flags = SA_INTERRUPT,
.name = "DMA Error",
};
static inline unsigned long calc_xmit_shift(unsigned int chan)
{
return sh64_in64(DMAC_CTRL(chan)) & 0x03;
}
void setup_dma(unsigned int chan, dma_info_t *info)
{
unsigned int irq = DMA_IRQ_DMTE0 + chan;
dma_info_t *dma = dma_info + chan;
make_intc_irq(irq);
setup_irq(irq, &irq_dmte);
dma = info;
}
void enable_dma(unsigned int chan)
{
u64 ctrl;
ctrl = sh64_in64(DMAC_CTRL(chan));
ctrl |= DMAC_CTRL_TE;
sh64_out64(ctrl, DMAC_CTRL(chan));
}
void disable_dma(unsigned int chan)
{
u64 ctrl;
ctrl = sh64_in64(DMAC_CTRL(chan));
ctrl &= ~DMAC_CTRL_TE;
sh64_out64(ctrl, DMAC_CTRL(chan));
}
void set_dma_mode(unsigned int chan, char mode)
{
dma_info_t *info = dma_info + chan;
info->mode = mode;
set_dma_addr(chan, info->mem_addr);
set_dma_count(chan, info->count);
}
void set_dma_addr(unsigned int chan, unsigned int addr)
{
dma_info_t *info = dma_info + chan;
unsigned long sar, dar;
info->mem_addr = addr;
sar = (info->mode & DMA_MODE_WRITE) ? info->mem_addr : info->dev_addr;
dar = (info->mode & DMA_MODE_WRITE) ? info->dev_addr : info->mem_addr;
sh64_out64(sar & DMAC_SAR_ADDR, DMAC_SAR(chan));
sh64_out64(dar & DMAC_SAR_ADDR, DMAC_DAR(chan));
}
void set_dma_count(unsigned int chan, unsigned int count)
{
dma_info_t *info = dma_info + chan;
u64 tmp;
info->count = count;
tmp = (info->count >> calc_xmit_shift(chan)) & DMAC_COUNT_CNT;
sh64_out64(tmp, DMAC_COUNT(chan));
}
unsigned long claim_dma_lock(void)
{
unsigned long flags;
spin_lock_irqsave(&dma_spin_lock, flags);
return flags;
}
void release_dma_lock(unsigned long flags)
{
spin_unlock_irqrestore(&dma_spin_lock, flags);
}
int get_dma_residue(unsigned int chan)
{
return sh64_in64(DMAC_COUNT(chan) << calc_xmit_shift(chan));
}
int __init init_dma(void)
{
struct vcr_info vcr;
u64 tmp;
/* Remap the DMAC */
dmac_base = onchip_remap(PHYS_DMAC_BLOCK, 1024, "DMAC");
if (!dmac_base) {
printk(KERN_ERR "Unable to remap DMAC\n");
return -ENOMEM;
}
/* Report DMAC.VCR Info */
vcr = sh64_get_vcr_info(dmac_base);
printk("DMAC: Module ID: 0x%04x, Module version: 0x%04x\n",
vcr.mod_id, vcr.mod_vers);
/* Set the ME bit */
tmp = sh64_in64(DMAC_COMMON_BASE);
tmp |= DMAC_COMMON_ME;
sh64_out64(tmp, DMAC_COMMON_BASE);
/* Enable the DMAC Error Interrupt */
make_intc_irq(DMA_IRQ_DERR);
setup_irq(DMA_IRQ_DERR, &irq_derr);
return 0;
}
static void __exit exit_dma(void)
{
onchip_unmap(dmac_base);
free_irq(DMA_IRQ_DERR, 0);
}
module_init(init_dma);
module_exit(exit_dma);
MODULE_AUTHOR("Paul Mundt");
MODULE_DESCRIPTION("DMA API for SH-5 DMAC");
MODULE_LICENSE("GPL");
EXPORT_SYMBOL(setup_dma);
EXPORT_SYMBOL(claim_dma_lock);
EXPORT_SYMBOL(release_dma_lock);
EXPORT_SYMBOL(enable_dma);
EXPORT_SYMBOL(disable_dma);
EXPORT_SYMBOL(set_dma_mode);
EXPORT_SYMBOL(set_dma_addr);
EXPORT_SYMBOL(set_dma_count);
EXPORT_SYMBOL(get_dma_residue);
/*
* arch/sh64/kernel/early_printk.c
*
* SH-5 Early SCIF console (cloned and hacked from sh implementation)
*
* Copyright (C) 2003, 2004 Paul Mundt <lethal@linux-sh.org>
* Copyright (C) 2002 M. R. Brown <mrbrown@0xd6.org>
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*/
#include <linux/console.h>
#include <linux/tty.h>
#include <linux/init.h>
#include <asm/io.h>
#include <asm/hardware.h>
extern void cpu_relax(void);
#define SCIF_BASE_ADDR 0x01030000
#define SCIF_ADDR_SH5 PHYS_PERIPHERAL_BLOCK+SCIF_BASE_ADDR
/*
* Fixed virtual address where SCIF is mapped (should already be done
* in arch/sh64/kernel/head.S!).
*/
#define SCIF_REG 0xfa030000
enum {
SCIF_SCSMR2 = SCIF_REG + 0x00,
SCIF_SCBRR2 = SCIF_REG + 0x04,
SCIF_SCSCR2 = SCIF_REG + 0x08,
SCIF_SCFTDR2 = SCIF_REG + 0x0c,
SCIF_SCFSR2 = SCIF_REG + 0x10,
SCIF_SCFRDR2 = SCIF_REG + 0x14,
SCIF_SCFCR2 = SCIF_REG + 0x18,
SCIF_SCFDR2 = SCIF_REG + 0x1c,
SCIF_SCSPTR2 = SCIF_REG + 0x20,
SCIF_SCLSR2 = SCIF_REG + 0x24,
};
static void sh_console_putc(int c)
{
while (!(ctrl_inw(SCIF_SCFSR2) & 0x20))
cpu_relax();
ctrl_outb(c, SCIF_SCFTDR2);
ctrl_outw((ctrl_inw(SCIF_SCFSR2) & 0x9f), SCIF_SCFSR2);
if (c == '\n')
sh_console_putc('\r');
}
static void sh_console_flush(void)
{
ctrl_outw((ctrl_inw(SCIF_SCFSR2) & 0xbf), SCIF_SCFSR2);
while (!(ctrl_inw(SCIF_SCFSR2) & 0x40))
cpu_relax();
ctrl_outw((ctrl_inw(SCIF_SCFSR2) & 0xbf), SCIF_SCFSR2);
}
static void sh_console_write(struct console *con, const char *s, unsigned count)
{
while (count-- > 0)
sh_console_putc(*s++);
sh_console_flush();
}
static int __init sh_console_setup(struct console *con, char *options)
{
con->cflag = CREAD | HUPCL | CLOCAL | B19200 | CS8;
return 0;
}
static struct console sh_console = {
.name = "scifcon",
.write = sh_console_write,
.setup = sh_console_setup,
.flags = CON_PRINTBUFFER,
.index = -1,
};
void __init enable_early_printk(void)
{
ctrl_outb(0x2a, SCIF_SCBRR2); /* 19200bps */
ctrl_outw(0x04, SCIF_SCFCR2); /* Reset TFRST */
ctrl_outw(0x10, SCIF_SCFCR2); /* TTRG0=1 */
ctrl_outw(0, SCIF_SCSPTR2);
ctrl_outw(0x60, SCIF_SCFSR2);
ctrl_outw(0, SCIF_SCLSR2);
ctrl_outw(0x30, SCIF_SCSCR2);
register_console(&sh_console);
}
void disable_early_printk(void)
{
unregister_console(&sh_console);
}
This diff is collapsed.
/*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* arch/sh64/kernel/fpu.c
*
* Copyright (C) 2001 Manuela Cirronis, Paolo Alberelli
* Copyright (C) 2002 STMicroelectronics Limited
* Author : Stuart Menefy
*
* Started from SH4 version:
* Copyright (C) 1999, 2000 Kaz Kojima & Niibe Yutaka
*
*/
#include <linux/sched.h>
#include <linux/signal.h>
#include <asm/processor.h>
#include <asm/user.h>
#include <asm/io.h>
/*
* Initially load the FPU with signalling NANS. This bit pattern
* has the property that no matter whether considered as single or as
* double precision, it still represents a signalling NAN.
*/
#define sNAN64 0xFFFFFFFFFFFFFFFFULL
#define sNAN32 0xFFFFFFFFUL
static union sh_fpu_union init_fpuregs = {
.hard = {
.fp_regs = { [0 ... 63] = sNAN32 },
.fpscr = FPSCR_INIT
}
};
inline void fpsave(struct sh_fpu_hard_struct *fpregs)
{
asm volatile("fst.p %0, (0*8), fp0\n\t"
"fst.p %0, (1*8), fp2\n\t"
"fst.p %0, (2*8), fp4\n\t"
"fst.p %0, (3*8), fp6\n\t"
"fst.p %0, (4*8), fp8\n\t"
"fst.p %0, (5*8), fp10\n\t"
"fst.p %0, (6*8), fp12\n\t"
"fst.p %0, (7*8), fp14\n\t"
"fst.p %0, (8*8), fp16\n\t"
"fst.p %0, (9*8), fp18\n\t"
"fst.p %0, (10*8), fp20\n\t"
"fst.p %0, (11*8), fp22\n\t"
"fst.p %0, (12*8), fp24\n\t"
"fst.p %0, (13*8), fp26\n\t"
"fst.p %0, (14*8), fp28\n\t"
"fst.p %0, (15*8), fp30\n\t"
"fst.p %0, (16*8), fp32\n\t"
"fst.p %0, (17*8), fp34\n\t"
"fst.p %0, (18*8), fp36\n\t"
"fst.p %0, (19*8), fp38\n\t"
"fst.p %0, (20*8), fp40\n\t"
"fst.p %0, (21*8), fp42\n\t"
"fst.p %0, (22*8), fp44\n\t"
"fst.p %0, (23*8), fp46\n\t"
"fst.p %0, (24*8), fp48\n\t"
"fst.p %0, (25*8), fp50\n\t"
"fst.p %0, (26*8), fp52\n\t"
"fst.p %0, (27*8), fp54\n\t"
"fst.p %0, (28*8), fp56\n\t"
"fst.p %0, (29*8), fp58\n\t"
"fst.p %0, (30*8), fp60\n\t"
"fst.p %0, (31*8), fp62\n\t"
"fgetscr fr63\n\t"
"fst.s %0, (32*8), fr63\n\t"
: /* no output */
: "r" (fpregs)
: "memory");
}
static inline void
fpload(struct sh_fpu_hard_struct *fpregs)
{
asm volatile("fld.p %0, (0*8), fp0\n\t"
"fld.p %0, (1*8), fp2\n\t"
"fld.p %0, (2*8), fp4\n\t"
"fld.p %0, (3*8), fp6\n\t"
"fld.p %0, (4*8), fp8\n\t"
"fld.p %0, (5*8), fp10\n\t"
"fld.p %0, (6*8), fp12\n\t"
"fld.p %0, (7*8), fp14\n\t"
"fld.p %0, (8*8), fp16\n\t"
"fld.p %0, (9*8), fp18\n\t"
"fld.p %0, (10*8), fp20\n\t"
"fld.p %0, (11*8), fp22\n\t"
"fld.p %0, (12*8), fp24\n\t"
"fld.p %0, (13*8), fp26\n\t"
"fld.p %0, (14*8), fp28\n\t"
"fld.p %0, (15*8), fp30\n\t"
"fld.p %0, (16*8), fp32\n\t"
"fld.p %0, (17*8), fp34\n\t"
"fld.p %0, (18*8), fp36\n\t"
"fld.p %0, (19*8), fp38\n\t"
"fld.p %0, (20*8), fp40\n\t"
"fld.p %0, (21*8), fp42\n\t"
"fld.p %0, (22*8), fp44\n\t"
"fld.p %0, (23*8), fp46\n\t"
"fld.p %0, (24*8), fp48\n\t"
"fld.p %0, (25*8), fp50\n\t"
"fld.p %0, (26*8), fp52\n\t"
"fld.p %0, (27*8), fp54\n\t"
"fld.p %0, (28*8), fp56\n\t"
"fld.p %0, (29*8), fp58\n\t"
"fld.p %0, (30*8), fp60\n\t"
"fld.s %0, (32*8), fr63\n\t"
"fputscr fr63\n\t"
"fld.p %0, (31*8), fp62\n\t"
: /* no output */
: "r" (fpregs) );
}
void fpinit(struct sh_fpu_hard_struct *fpregs)
{
*fpregs = init_fpuregs.hard;
}
asmlinkage void
do_fpu_error(unsigned long ex, struct pt_regs *regs)
{
struct task_struct *tsk = current;
regs->pc += 4;
tsk->thread.trap_no = 11;
tsk->thread.error_code = 0;
force_sig(SIGFPE, tsk);
}
asmlinkage void
do_fpu_state_restore(unsigned long ex, struct pt_regs *regs)
{
void die(const char *str, struct pt_regs *regs, long err);
if (! user_mode(regs))
die("FPU used in kernel", regs, ex);
regs->sr &= ~SR_FD;
if (last_task_used_math == current)
return;
grab_fpu();
if (last_task_used_math != NULL) {
/* Other processes fpu state, save away */
fpsave(&last_task_used_math->thread.fpu.hard);
}
last_task_used_math = current;
if (current->used_math) {
fpload(&current->thread.fpu.hard);
} else {
/* First time FPU user. */
fpload(&init_fpuregs.hard);
current->used_math = 1;
}
release_fpu();
}
This diff is collapsed.
/*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* arch/sh64/kernel/init_task.c
*
* Copyright (C) 2000, 2001 Paolo Alberelli
* Copyright (C) 2003 Paul Mundt
*
*/
#include <linux/rwsem.h>
#include <linux/mm.h>
#include <linux/sched.h>
#include <linux/init_task.h>
#include <asm/uaccess.h>
#include <asm/pgtable.h>
static struct fs_struct init_fs = INIT_FS;
static struct files_struct init_files = INIT_FILES;
static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
struct mm_struct init_mm = INIT_MM(init_mm);
struct pt_regs fake_swapper_regs;
/*
* Initial thread structure.
*
* We need to make sure that this is THREAD_SIZE-byte aligned due
* to the way process stacks are handled. This is done by having a
* special "init_task" linker map entry..
*/
union thread_union init_thread_union
__attribute__((__section__(".data.init_task"))) =
{ INIT_THREAD_INFO(init_task) };
/*
* Initial task structure.
*
* All other task structs will be allocated on slabs in fork.c
*/
struct task_struct init_task = INIT_TASK(init_task);
This diff is collapsed.
/*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* arch/sh64/kernel/irq_intc.c
*
* Copyright (C) 2000, 2001 Paolo Alberelli
* Copyright (C) 2003 Paul Mundt
*
* Interrupt Controller support for SH5 INTC.
* Per-interrupt selective. IRLM=0 (Fixed priority) is not
* supported being useless without a cascaded interrupt
* controller.
*
*/
#include <linux/config.h>
#include <linux/init.h>
#include <linux/irq.h>
#include <linux/kernel.h>
#include <linux/stddef.h>
#include <asm/hardware.h>
#include <asm/platform.h>
#include <asm/bitops.h> /* this includes also <asm/registers.h */
/* which is required to remap register */
/* names used into __asm__ blocks... */
#include <asm/page.h>
#include <asm/io.h>
#include <asm/irq.h>
/*
* Maybe the generic Peripheral block could move to a more
* generic include file. INTC Block will be defined here
* and only here to make INTC self-contained in a single
* file.
*/
#define INTC_BLOCK_OFFSET 0x01000000
/* Base */
#define INTC_BASE PHYS_PERIPHERAL_BLOCK + \
INTC_BLOCK_OFFSET
/* Address */
#define INTC_ICR_SET (intc_virt + 0x0)
#define INTC_ICR_CLEAR (intc_virt + 0x8)
#define INTC_INTPRI_0 (intc_virt + 0x10)
#define INTC_INTSRC_0 (intc_virt + 0x50)
#define INTC_INTSRC_1 (intc_virt + 0x58)
#define INTC_INTREQ_0 (intc_virt + 0x60)
#define INTC_INTREQ_1 (intc_virt + 0x68)
#define INTC_INTENB_0 (intc_virt + 0x70)
#define INTC_INTENB_1 (intc_virt + 0x78)
#define INTC_INTDSB_0 (intc_virt + 0x80)
#define INTC_INTDSB_1 (intc_virt + 0x88)
#define INTC_ICR_IRLM 0x1
#define INTC_INTPRI_PREGS 8 /* 8 Priority Registers */
#define INTC_INTPRI_PPREG 8 /* 8 Priorities per Register */
/*
* Mapper between the vector ordinal and the IRQ number
* passed to kernel/device drivers.
*/
int intc_evt_to_irq[(0xE20/0x20)+1] = {
-1, -1, -1, -1, -1, -1, -1, -1, /* 0x000 - 0x0E0 */
-1, -1, -1, -1, -1, -1, -1, -1, /* 0x100 - 0x1E0 */
0, 0, 0, 0, 0, 1, 0, 0, /* 0x200 - 0x2E0 */
2, 0, 0, 3, 0, 0, 0, -1, /* 0x300 - 0x3E0 */
32, 33, 34, 35, 36, 37, 38, -1, /* 0x400 - 0x4E0 */
-1, -1, -1, 63, -1, -1, -1, -1, /* 0x500 - 0x5E0 */
-1, -1, 18, 19, 20, 21, 22, -1, /* 0x600 - 0x6E0 */
39, 40, 41, 42, -1, -1, -1, -1, /* 0x700 - 0x7E0 */
4, 5, 6, 7, -1, -1, -1, -1, /* 0x800 - 0x8E0 */
-1, -1, -1, -1, -1, -1, -1, -1, /* 0x900 - 0x9E0 */
12, 13, 14, 15, 16, 17, -1, -1, /* 0xA00 - 0xAE0 */
-1, -1, -1, -1, -1, -1, -1, -1, /* 0xB00 - 0xBE0 */
-1, -1, -1, -1, -1, -1, -1, -1, /* 0xC00 - 0xCE0 */
-1, -1, -1, -1, -1, -1, -1, -1, /* 0xD00 - 0xDE0 */
-1, -1 /* 0xE00 - 0xE20 */
};
/*
* Opposite mapper.
*/
static int IRQ_to_vectorN[NR_INTC_IRQS] = {
0x12, 0x15, 0x18, 0x1B, 0x40, 0x41, 0x42, 0x43, /* 0- 7 */
-1, -1, -1, -1, 0x50, 0x51, 0x52, 0x53, /* 8-15 */
0x54, 0x55, 0x32, 0x33, 0x34, 0x35, 0x36, -1, /* 16-23 */
-1, -1, -1, -1, -1, -1, -1, -1, /* 24-31 */
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x38, /* 32-39 */
0x39, 0x3A, 0x3B, -1, -1, -1, -1, -1, /* 40-47 */
-1, -1, -1, -1, -1, -1, -1, -1, /* 48-55 */
-1, -1, -1, -1, -1, -1, -1, 0x2B, /* 56-63 */
};
static unsigned long intc_virt;
static unsigned int startup_intc_irq(unsigned int irq);
static void shutdown_intc_irq(unsigned int irq);
static void enable_intc_irq(unsigned int irq);
static void disable_intc_irq(unsigned int irq);
static void mask_and_ack_intc(unsigned int);
static void end_intc_irq(unsigned int irq);
static struct hw_interrupt_type intc_irq_type = {
"INTC",
startup_intc_irq,
shutdown_intc_irq,
enable_intc_irq,
disable_intc_irq,
mask_and_ack_intc,
end_intc_irq
};
static int irlm; /* IRL mode */
static unsigned int startup_intc_irq(unsigned int irq)
{
enable_intc_irq(irq);
return 0; /* never anything pending */
}
static void shutdown_intc_irq(unsigned int irq)
{
disable_intc_irq(irq);
}
static void enable_intc_irq(unsigned int irq)
{
unsigned long reg;
unsigned long bitmask;
if ((irq <= IRQ_IRL3) && (irlm == NO_PRIORITY))
printk("Trying to use straight IRL0-3 with an encoding platform.\n");
if (irq < 32) {
reg = INTC_INTENB_0;
bitmask = 1 << irq;
} else {
reg = INTC_INTENB_1;
bitmask = 1 << (irq - 32);
}
ctrl_outl(bitmask, reg);
}
static void disable_intc_irq(unsigned int irq)
{
unsigned long reg;
unsigned long bitmask;
if (irq < 32) {
reg = INTC_INTDSB_0;
bitmask = 1 << irq;
} else {
reg = INTC_INTDSB_1;
bitmask = 1 << (irq - 32);
}
ctrl_outl(bitmask, reg);
}
static void mask_and_ack_intc(unsigned int irq)
{
disable_intc_irq(irq);
}
static void end_intc_irq(unsigned int irq)
{
enable_intc_irq(irq);
}
/* For future use, if we ever support IRLM=0) */
void make_intc_irq(unsigned int irq)
{
disable_irq_nosync(irq);
irq_desc[irq].handler = &intc_irq_type;
disable_intc_irq(irq);
}
#if defined(CONFIG_PROC_FS) && defined(CONFIG_SYSCTL)
int intc_irq_describe(char* p, int irq)
{
if (irq < NR_INTC_IRQS)
return sprintf(p, "(0x%3x)", IRQ_to_vectorN[irq]*0x20);
else
return 0;
}
#endif
void __init init_IRQ(void)
{
unsigned long long __dummy0, __dummy1=~0x00000000100000f0;
unsigned long reg;
unsigned long data;
int i;
intc_virt = onchip_remap(INTC_BASE, 1024, "INTC");
if (!intc_virt) {
panic("Unable to remap INTC\n");
}
/* Set default: per-line enable/disable, priority driven ack/eoi */
for (i = 0; i < NR_INTC_IRQS; i++) {
if (platform_int_priority[i] != NO_PRIORITY) {
irq_desc[i].handler = &intc_irq_type;
}
}
/* Disable all interrupts and set all priorities to 0 to avoid trouble */
ctrl_outl(-1, INTC_INTDSB_0);
ctrl_outl(-1, INTC_INTDSB_1);
for (reg = INTC_INTPRI_0, i = 0; i < INTC_INTPRI_PREGS; i++, reg += 8)
ctrl_outl( NO_PRIORITY, reg);
/* Set IRLM */
/* If all the priorities are set to 'no priority', then
* assume we are using encoded mode.
*/
irlm = platform_int_priority[IRQ_IRL0] + platform_int_priority[IRQ_IRL1] + \
platform_int_priority[IRQ_IRL2] + platform_int_priority[IRQ_IRL3];
if (irlm == NO_PRIORITY) {
/* IRLM = 0 */
reg = INTC_ICR_CLEAR;
i = IRQ_INTA;
printk("Trying to use encoded IRL0-3. IRLs unsupported.\n");
} else {
/* IRLM = 1 */
reg = INTC_ICR_SET;
i = IRQ_IRL0;
}
ctrl_outl(INTC_ICR_IRLM, reg);
/* Set interrupt priorities according to platform description */
for (data = 0, reg = INTC_INTPRI_0; i < NR_INTC_IRQS; i++) {
data |= platform_int_priority[i] << ((i % INTC_INTPRI_PPREG) * 4);
if ((i % INTC_INTPRI_PPREG) == (INTC_INTPRI_PPREG - 1)) {
/* Upon the 7th, set Priority Register */
ctrl_outl(data, reg);
data = 0;
reg += 8;
}
}
#ifdef CONFIG_SH_CAYMAN
{
extern void init_cayman_irq(void);
init_cayman_irq();
}
#endif
/*
* And now let interrupts come in.
* sti() is not enough, we need to
* lower priority, too.
*/
__asm__ __volatile__("getcon " __SR ", %0\n\t"
"and %0, %1, %0\n\t"
"putcon %0, " __SR "\n\t"
: "=&r" (__dummy0)
: "r" (__dummy1));
}
/*
* arch/sh64/kernel/led.c
*
* Copyright (C) 2002 Stuart Menefy <stuart.menefy@st.com>
*
* May be copied or modified under the terms of the GNU General Public
* License. See linux/COPYING for more information.
*
* Flash the LEDs
*/
#include <linux/config.h>
#include <linux/stddef.h>
#include <linux/sched.h>
void mach_led(int pos, int val);
/* acts like an actual heart beat -- ie thump-thump-pause... */
void heartbeat(void)
{
static unsigned int cnt = 0, period = 0, dist = 0;
if (cnt == 0 || cnt == dist) {
mach_led(-1, 1);
} else if (cnt == 7 || cnt == dist + 7) {
mach_led(-1, 0);
}
if (++cnt > period) {
cnt = 0;
/*
* The hyperbolic function below modifies the heartbeat period
* length in dependency of the current (5min) load. It goes
* through the points f(0)=126, f(1)=86, f(5)=51, f(inf)->30.
*/
period = ((672 << FSHIFT) / (5 * avenrun[0] +
(7 << FSHIFT))) + 30;
dist = period / 4;
}
}
/*
* Copyright (C) 2001 David J. Mckay (david.mckay@st.com)
* Copyright (C) 2003 Paul Mundt (lethal@linux-sh.org)
*
* May be copied or modified under the terms of the GNU General Public
* License. See linux/COPYING for more information.
*
* Dynamic DMA mapping support.
*/
#include <linux/types.h>
#include <linux/mm.h>
#include <linux/string.h>
#include <linux/pci.h>
#include <asm/io.h>
void *consistent_alloc(struct pci_dev *hwdev, size_t size,
dma_addr_t *dma_handle)
{
void *ret;
int gfp = GFP_ATOMIC;
void *vp;
if (hwdev == NULL || hwdev->dma_mask != 0xffffffff)
gfp |= GFP_DMA;
ret = (void *)__get_free_pages(gfp, get_order(size));
/* now call our friend ioremap_nocache to give us an uncached area */
vp = ioremap_nocache(virt_to_phys(ret), size);
if (vp != NULL) {
memset(vp, 0, size);
*dma_handle = virt_to_bus(ret);
dma_cache_wback_inv((unsigned long)ret, size);
}
return vp;
}
void consistent_free(struct pci_dev *hwdev, size_t size,
void *vaddr, dma_addr_t dma_handle)
{
void *alloc;
alloc = bus_to_virt((unsigned long)dma_handle);
free_pages((unsigned long)alloc, get_order(size));
iounmap(vaddr);
}
This diff is collapsed.
/*
* Copyright (C) 2001 David J. Mckay (david.mckay@st.com)
*
* May be copied or modified under the terms of the GNU General Public
* License. See linux/COPYING for more information.
*
* Defintions for the SH5 PCI hardware.
*/
/* Product ID */
#define PCISH5_PID 0x350d
/* vendor ID */
#define PCISH5_VID 0x1054
/* Configuration types */
#define ST_TYPE0 0x00 /* Configuration cycle type 0 */
#define ST_TYPE1 0x01 /* Configuration cycle type 1 */
/* VCR data */
#define PCISH5_VCR_STATUS 0x00
#define PCISH5_VCR_VERSION 0x08
/*
** ICR register offsets and bits
*/
#define PCISH5_ICR_CR 0x100 /* PCI control register values */
#define CR_PBAM (1<<12)
#define CR_PFCS (1<<11)
#define CR_FTO (1<<10)
#define CR_PFE (1<<9)
#define CR_TBS (1<<8)
#define CR_SPUE (1<<7)
#define CR_BMAM (1<<6)
#define CR_HOST (1<<5)
#define CR_CLKEN (1<<4)
#define CR_SOCS (1<<3)
#define CR_IOCS (1<<2)
#define CR_RSTCTL (1<<1)
#define CR_CFINT (1<<0)
#define CR_LOCK_MASK 0xa5000000
#define PCISH5_ICR_INT 0x114 /* Interrupt registert values */
#define INT_MADIM (1<<2)
#define PCISH5_ICR_LSR0 0X104 /* Local space register values */
#define PCISH5_ICR_LSR1 0X108 /* Local space register values */
#define PCISH5_ICR_LAR0 0x10c /* Local address register values */
#define PCISH5_ICR_LAR1 0x110 /* Local address register values */
#define PCISH5_ICR_INTM 0x118 /* Interrupt mask register values */
#define PCISH5_ICR_AIR 0x11c /* Interrupt error address information register values */
#define PCISH5_ICR_CIR 0x120 /* Interrupt error command information register values */
#define PCISH5_ICR_AINT 0x130 /* Interrupt error arbiter interrupt register values */
#define PCISH5_ICR_AINTM 0x134 /* Interrupt error arbiter interrupt mask register values */
#define PCISH5_ICR_BMIR 0x138 /* Interrupt error info register of bus master values */
#define PCISH5_ICR_PAR 0x1c0 /* Pio address register values */
#define PCISH5_ICR_MBR 0x1c4 /* Memory space bank register values */
#define PCISH5_ICR_IOBR 0x1c8 /* I/O space bank register values */
#define PCISH5_ICR_PINT 0x1cc /* power management interrupt register values */
#define PCISH5_ICR_PINTM 0x1d0 /* power management interrupt mask register values */
#define PCISH5_ICR_MBMR 0x1d8 /* memory space bank mask register values */
#define PCISH5_ICR_IOBMR 0x1dc /* I/O space bank mask register values */
#define PCISH5_ICR_CSCR0 0x210 /* PCI cache snoop control register 0 */
#define PCISH5_ICR_CSCR1 0x214 /* PCI cache snoop control register 1 */
#define PCISH5_ICR_PDR 0x220 /* Pio data register values */
/* These are configs space registers */
#define PCISH5_ICR_CSR_VID 0x000 /* Vendor id */
#define PCISH5_ICR_CSR_DID 0x002 /* Device id */
#define PCISH5_ICR_CSR_CMD 0x004 /* Command register */
#define PCISH5_ICR_CSR_STATUS 0x006 /* Stautus */
#define PCISH5_ICR_CSR_IBAR0 0x010 /* I/O base address register */
#define PCISH5_ICR_CSR_MBAR0 0x014 /* First Memory base address register */
#define PCISH5_ICR_CSR_MBAR1 0x018 /* Second Memory base address register */
/* Base address of registers */
#define SH5PCI_ICR_BASE (PHYS_PCI_BLOCK + 0x00040000)
#define SH5PCI_IO_BASE (PHYS_PCI_BLOCK + 0x00800000)
/* #define SH5PCI_VCR_BASE (P2SEG_PCICB_BLOCK + P2SEG) */
/* Register selection macro */
#define PCISH5_ICR_REG(x) ( pcicr_virt + (PCISH5_ICR_##x))
/* #define PCISH5_VCR_REG(x) ( SH5PCI_VCR_BASE (PCISH5_VCR_##x)) */
/* Write I/O functions */
#define SH5PCI_WRITE(reg,val) ctrl_outl((u32)(val),PCISH5_ICR_REG(reg))
#define SH5PCI_WRITE_SHORT(reg,val) ctrl_outw((u16)(val),PCISH5_ICR_REG(reg))
#define SH5PCI_WRITE_BYTE(reg,val) ctrl_outb((u8)(val),PCISH5_ICR_REG(reg))
/* Read I/O functions */
#define SH5PCI_READ(reg) ctrl_inl(PCISH5_ICR_REG(reg))
#define SH5PCI_READ_SHORT(reg) ctrl_inw(PCISH5_ICR_REG(reg))
#define SH5PCI_READ_BYTE(reg) ctrl_inb(PCISH5_ICR_REG(reg))
/* Set PCI config bits */
#define SET_CONFIG_BITS(bus,devfn,where) ((((bus) << 16) | ((devfn) << 8) | ((where) & ~3)) | 0x80000000)
/* Set PCI command register */
#define CONFIG_CMD(bus, devfn, where) SET_CONFIG_BITS(bus->number,devfn,where)
/* Size converters */
#define PCISH5_MEM_SIZCONV(x) (((x / 0x40000) - 1) << 18)
#define PCISH5_IO_SIZCONV(x) (((x / 0x40000) - 1) << 18)
/*
* $Id: pcibios.c,v 1.1 2001/08/24 12:38:19 dwmw2 Exp $
*
* arch/sh/kernel/pcibios.c
*
* Copyright (C) 2002 STMicroelectronics Limited
* Author : David J. McKay
*
* Copyright (C) 2004 Richard Curnow, SuperH UK Limited
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
* This is GPL'd.
*
* Provided here are generic versions of:
* pcibios_update_resource()
* pcibios_align_resource()
* pcibios_enable_device()
* pcibios_set_master()
* pcibios_update_irq()
*
* These functions are collected here to reduce duplication of common
* code amongst the many platform-specific PCI support code files.
*
* Platform-specific files are expected to provide:
* pcibios_fixup_bus()
* pcibios_init()
* pcibios_setup()
* pcibios_fixup_pbus_ranges()
*/
#include <linux/kernel.h>
#include <linux/pci.h>
#include <linux/init.h>
void
pcibios_update_resource(struct pci_dev *dev, struct resource *root,
struct resource *res, int resource)
{
u32 new, check;
int reg;
new = res->start | (res->flags & PCI_REGION_FLAG_MASK);
if (resource < 6) {
reg = PCI_BASE_ADDRESS_0 + 4*resource;
} else if (resource == PCI_ROM_RESOURCE) {
res->flags |= PCI_ROM_ADDRESS_ENABLE;
new |= PCI_ROM_ADDRESS_ENABLE;
reg = dev->rom_base_reg;
} else {
/* Somebody might have asked allocation of a non-standard resource */
return;
}
pci_write_config_dword(dev, reg, new);
pci_read_config_dword(dev, reg, &check);
if ((new ^ check) & ((new & PCI_BASE_ADDRESS_SPACE_IO) ? PCI_BASE_ADDRESS_IO_MASK : PCI_BASE_ADDRESS_MEM_MASK)) {
printk(KERN_ERR "PCI: Error while updating region "
"%s/%d (%08x != %08x)\n", dev->slot_name, resource,
new, check);
}
}
/*
* We need to avoid collisions with `mirrored' VGA ports
* and other strange ISA hardware, so we always want the
* addresses to be allocated in the 0x000-0x0ff region
* modulo 0x400.
*/
void pcibios_align_resource(void *data, struct resource *res,
unsigned long size, unsigned long align)
{
if (res->flags & IORESOURCE_IO) {
unsigned long start = res->start;
if (start & 0x300) {
start = (start + 0x3ff) & ~0x3ff;
res->start = start;
}
}
}
static void pcibios_enable_bridge(struct pci_dev *dev)
{
struct pci_bus *bus = dev->subordinate;
u16 cmd, old_cmd;
pci_read_config_word(dev, PCI_COMMAND, &cmd);
old_cmd = cmd;
if (bus->resource[0]->flags & IORESOURCE_IO) {
cmd |= PCI_COMMAND_IO;
}
if ((bus->resource[1]->flags & IORESOURCE_MEM) ||
(bus->resource[2]->flags & IORESOURCE_PREFETCH)) {
cmd |= PCI_COMMAND_MEMORY;
}
if (cmd != old_cmd) {
pci_write_config_word(dev, PCI_COMMAND, cmd);
}
printk("PCI bridge %s, command register -> %04x\n",
pci_name(dev), cmd);
}
int pcibios_enable_device(struct pci_dev *dev, int mask)
{
u16 cmd, old_cmd;
int idx;
struct resource *r;
if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) {
pcibios_enable_bridge(dev);
}
pci_read_config_word(dev, PCI_COMMAND, &cmd);
old_cmd = cmd;
for(idx=0; idx<6; idx++) {
if (!(mask & (1 << idx)))
continue;
r = &dev->resource[idx];
if (!r->start && r->end) {
printk(KERN_ERR "PCI: Device %s not available because of resource collisions\n", dev->slot_name);
return -EINVAL;
}
if (r->flags & IORESOURCE_IO)
cmd |= PCI_COMMAND_IO;
if (r->flags & IORESOURCE_MEM)
cmd |= PCI_COMMAND_MEMORY;
}
if (dev->resource[PCI_ROM_RESOURCE].start)
cmd |= PCI_COMMAND_MEMORY;
if (cmd != old_cmd) {
printk(KERN_INFO "PCI: Enabling device %s (%04x -> %04x)\n", pci_name(dev), old_cmd, cmd);
pci_write_config_word(dev, PCI_COMMAND, cmd);
}
return 0;
}
/*
* If we set up a device for bus mastering, we need to check and set
* the latency timer as it may not be properly set.
*/
unsigned int pcibios_max_latency = 255;
void pcibios_set_master(struct pci_dev *dev)
{
u8 lat;
pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat);
if (lat < 16)
lat = (64 <= pcibios_max_latency) ? 64 : pcibios_max_latency;
else if (lat > pcibios_max_latency)
lat = pcibios_max_latency;
else
return;
printk(KERN_INFO "PCI: Setting latency timer of device %s to %d\n", pci_name(dev), lat);
pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat);
}
void __init pcibios_update_irq(struct pci_dev *dev, int irq)
{
pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
}
This diff is collapsed.
This diff is collapsed.
/*
* Just taken from alpha implementation.
* This can't work well, perhaps.
*/
/*
* Generic semaphore code. Buyer beware. Do your own
* specific changes in <asm/semaphore-helper.h>
*/
#include <linux/errno.h>
#include <linux/rwsem.h>
#include <linux/sched.h>
#include <linux/wait.h>
#include <linux/init.h>
#include <asm/semaphore.h>
#include <asm/semaphore-helper.h>
spinlock_t semaphore_wake_lock;
/*
* Semaphores are implemented using a two-way counter:
* The "count" variable is decremented for each process
* that tries to sleep, while the "waking" variable is
* incremented when the "up()" code goes to wake up waiting
* processes.
*
* Notably, the inline "up()" and "down()" functions can
* efficiently test if they need to do any extra work (up
* needs to do something only if count was negative before
* the increment operation.
*
* waking_non_zero() (from asm/semaphore.h) must execute
* atomically.
*
* When __up() is called, the count was negative before
* incrementing it, and we need to wake up somebody.
*
* This routine adds one to the count of processes that need to
* wake up and exit. ALL waiting processes actually wake up but
* only the one that gets to the "waking" field first will gate
* through and acquire the semaphore. The others will go back
* to sleep.
*
* Note that these functions are only called when there is
* contention on the lock, and as such all this is the
* "non-critical" part of the whole semaphore business. The
* critical part is the inline stuff in <asm/semaphore.h>
* where we want to avoid any extra jumps and calls.
*/
void __up(struct semaphore *sem)
{
wake_one_more(sem);
wake_up(&sem->wait);
}
/*
* Perform the "down" function. Return zero for semaphore acquired,
* return negative for signalled out of the function.
*
* If called from __down, the return is ignored and the wait loop is
* not interruptible. This means that a task waiting on a semaphore
* using "down()" cannot be killed until someone does an "up()" on
* the semaphore.
*
* If called from __down_interruptible, the return value gets checked
* upon return. If the return value is negative then the task continues
* with the negative value in the return register (it can be tested by
* the caller).
*
* Either form may be used in conjunction with "up()".
*
*/
#define DOWN_VAR \
struct task_struct *tsk = current; \
wait_queue_t wait; \
init_waitqueue_entry(&wait, tsk);
#define DOWN_HEAD(task_state) \
\
\
tsk->state = (task_state); \
add_wait_queue(&sem->wait, &wait); \
\
/* \
* Ok, we're set up. sem->count is known to be less than zero \
* so we must wait. \
* \
* We can let go the lock for purposes of waiting. \
* We re-acquire it after awaking so as to protect \
* all semaphore operations. \
* \
* If "up()" is called before we call waking_non_zero() then \
* we will catch it right away. If it is called later then \
* we will have to go through a wakeup cycle to catch it. \
* \
* Multiple waiters contend for the semaphore lock to see \
* who gets to gate through and who has to wait some more. \
*/ \
for (;;) {
#define DOWN_TAIL(task_state) \
tsk->state = (task_state); \
} \
tsk->state = TASK_RUNNING; \
remove_wait_queue(&sem->wait, &wait);
void __sched __down(struct semaphore * sem)
{
DOWN_VAR
DOWN_HEAD(TASK_UNINTERRUPTIBLE)
if (waking_non_zero(sem))
break;
schedule();
DOWN_TAIL(TASK_UNINTERRUPTIBLE)
}
int __sched __down_interruptible(struct semaphore * sem)
{
int ret = 0;
DOWN_VAR
DOWN_HEAD(TASK_INTERRUPTIBLE)
ret = waking_non_zero_interruptible(sem, tsk);
if (ret)
{
if (ret == 1)
/* ret != 0 only if we get interrupted -arca */
ret = 0;
break;
}
schedule();
DOWN_TAIL(TASK_INTERRUPTIBLE)
return ret;
}
int __down_trylock(struct semaphore * sem)
{
return waking_non_zero_trylock(sem);
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment