summaryrefslogtreecommitdiffstats
path: root/arch/sh
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sh')
-rw-r--r--arch/sh/Kconfig793
-rw-r--r--arch/sh/Kconfig.debug124
-rw-r--r--arch/sh/Makefile183
-rw-r--r--arch/sh/boards/adx/Makefile6
-rw-r--r--arch/sh/boards/adx/irq.c31
-rw-r--r--arch/sh/boards/adx/irq_maskreg.c107
-rw-r--r--arch/sh/boards/adx/setup.c56
-rw-r--r--arch/sh/boards/bigsur/Makefile6
-rw-r--r--arch/sh/boards/bigsur/io.c125
-rw-r--r--arch/sh/boards/bigsur/irq.c348
-rw-r--r--arch/sh/boards/bigsur/led.c55
-rw-r--r--arch/sh/boards/bigsur/setup.c96
-rw-r--r--arch/sh/boards/cat68701/Makefile6
-rw-r--r--arch/sh/boards/cat68701/irq.c28
-rw-r--r--arch/sh/boards/cat68701/setup.c86
-rw-r--r--arch/sh/boards/cqreek/Makefile6
-rw-r--r--arch/sh/boards/cqreek/irq.c128
-rw-r--r--arch/sh/boards/cqreek/setup.c101
-rw-r--r--arch/sh/boards/dmida/Makefile7
-rw-r--r--arch/sh/boards/dmida/mach.c59
-rw-r--r--arch/sh/boards/dreamcast/Makefile6
-rw-r--r--arch/sh/boards/dreamcast/irq.c160
-rw-r--r--arch/sh/boards/dreamcast/rtc.c81
-rw-r--r--arch/sh/boards/dreamcast/setup.c83
-rw-r--r--arch/sh/boards/ec3104/Makefile6
-rw-r--r--arch/sh/boards/ec3104/io.c81
-rw-r--r--arch/sh/boards/ec3104/irq.c196
-rw-r--r--arch/sh/boards/ec3104/setup.c78
-rw-r--r--arch/sh/boards/harp/Makefile8
-rw-r--r--arch/sh/boards/harp/irq.c148
-rw-r--r--arch/sh/boards/harp/led.c52
-rw-r--r--arch/sh/boards/harp/mach.c62
-rw-r--r--arch/sh/boards/harp/pcidma.c42
-rw-r--r--arch/sh/boards/harp/setup.c91
-rw-r--r--arch/sh/boards/hp6xx/hp620/Makefile6
-rw-r--r--arch/sh/boards/hp6xx/hp620/mach.c52
-rw-r--r--arch/sh/boards/hp6xx/hp620/setup.c45
-rw-r--r--arch/sh/boards/hp6xx/hp680/Makefile6
-rw-r--r--arch/sh/boards/hp6xx/hp680/mach.c53
-rw-r--r--arch/sh/boards/hp6xx/hp680/setup.c41
-rw-r--r--arch/sh/boards/hp6xx/hp690/Makefile6
-rw-r--r--arch/sh/boards/hp6xx/hp690/mach.c48
-rw-r--r--arch/sh/boards/mpc1211/Makefile8
-rw-r--r--arch/sh/boards/mpc1211/led.c64
-rw-r--r--arch/sh/boards/mpc1211/pci.c296
-rw-r--r--arch/sh/boards/mpc1211/rtc.c152
-rw-r--r--arch/sh/boards/mpc1211/setup.c360
-rw-r--r--arch/sh/boards/overdrive/Makefile8
-rw-r--r--arch/sh/boards/overdrive/fpga.c134
-rw-r--r--arch/sh/boards/overdrive/galileo.c588
-rw-r--r--arch/sh/boards/overdrive/io.c173
-rw-r--r--arch/sh/boards/overdrive/irq.c192
-rw-r--r--arch/sh/boards/overdrive/led.c59
-rw-r--r--arch/sh/boards/overdrive/mach.c62
-rw-r--r--arch/sh/boards/overdrive/pcidma.c46
-rw-r--r--arch/sh/boards/overdrive/setup.c41
-rw-r--r--arch/sh/boards/overdrive/time.c119
-rw-r--r--arch/sh/boards/renesas/edosk7705/Makefile10
-rw-r--r--arch/sh/boards/renesas/edosk7705/io.c94
-rw-r--r--arch/sh/boards/renesas/edosk7705/setup.c60
-rw-r--r--arch/sh/boards/renesas/hs7751rvoip/Makefile12
-rw-r--r--arch/sh/boards/renesas/hs7751rvoip/io.c310
-rw-r--r--arch/sh/boards/renesas/hs7751rvoip/irq.c122
-rw-r--r--arch/sh/boards/renesas/hs7751rvoip/led.c27
-rw-r--r--arch/sh/boards/renesas/hs7751rvoip/mach.c55
-rw-r--r--arch/sh/boards/renesas/hs7751rvoip/pci.c150
-rw-r--r--arch/sh/boards/renesas/hs7751rvoip/setup.c89
-rw-r--r--arch/sh/boards/renesas/rts7751r2d/Makefile10
-rw-r--r--arch/sh/boards/renesas/rts7751r2d/io.c319
-rw-r--r--arch/sh/boards/renesas/rts7751r2d/irq.c135
-rw-r--r--arch/sh/boards/renesas/rts7751r2d/led.c67
-rw-r--r--arch/sh/boards/renesas/rts7751r2d/mach.c70
-rw-r--r--arch/sh/boards/renesas/rts7751r2d/setup.c31
-rw-r--r--arch/sh/boards/renesas/systemh/Makefile13
-rw-r--r--arch/sh/boards/renesas/systemh/io.c283
-rw-r--r--arch/sh/boards/renesas/systemh/irq.c111
-rw-r--r--arch/sh/boards/renesas/systemh/setup.c80
-rw-r--r--arch/sh/boards/saturn/Makefile8
-rw-r--r--arch/sh/boards/saturn/io.c26
-rw-r--r--arch/sh/boards/saturn/irq.c118
-rw-r--r--arch/sh/boards/saturn/setup.c43
-rw-r--r--arch/sh/boards/saturn/smp.c68
-rw-r--r--arch/sh/boards/se/7300/Makefile7
-rw-r--r--arch/sh/boards/se/7300/io.c265
-rw-r--r--arch/sh/boards/se/7300/irq.c37
-rw-r--r--arch/sh/boards/se/7300/led.c69
-rw-r--r--arch/sh/boards/se/7300/setup.c66
-rw-r--r--arch/sh/boards/se/73180/Makefile7
-rw-r--r--arch/sh/boards/se/73180/io.c265
-rw-r--r--arch/sh/boards/se/73180/irq.c137
-rw-r--r--arch/sh/boards/se/73180/led.c67
-rw-r--r--arch/sh/boards/se/73180/setup.c68
-rw-r--r--arch/sh/boards/se/770x/Makefile6
-rw-r--r--arch/sh/boards/se/770x/io.c226
-rw-r--r--arch/sh/boards/se/770x/irq.c80
-rw-r--r--arch/sh/boards/se/770x/led.c68
-rw-r--r--arch/sh/boards/se/770x/mach.c68
-rw-r--r--arch/sh/boards/se/770x/setup.c85
-rw-r--r--arch/sh/boards/se/7751/Makefile8
-rw-r--r--arch/sh/boards/se/7751/io.c244
-rw-r--r--arch/sh/boards/se/7751/irq.c67
-rw-r--r--arch/sh/boards/se/7751/led.c68
-rw-r--r--arch/sh/boards/se/7751/mach.c55
-rw-r--r--arch/sh/boards/se/7751/pci.c148
-rw-r--r--arch/sh/boards/se/7751/setup.c228
-rw-r--r--arch/sh/boards/sh03/Makefile6
-rw-r--r--arch/sh/boards/sh03/led.c49
-rw-r--r--arch/sh/boards/sh03/rtc.c144
-rw-r--r--arch/sh/boards/sh03/setup.c72
-rw-r--r--arch/sh/boards/sh2000/Makefile6
-rw-r--r--arch/sh/boards/sh2000/setup.c71
-rw-r--r--arch/sh/boards/snapgear/Makefile6
-rw-r--r--arch/sh/boards/snapgear/io.c226
-rw-r--r--arch/sh/boards/snapgear/rtc.c333
-rw-r--r--arch/sh/boards/snapgear/setup.c216
-rw-r--r--arch/sh/boards/superh/microdev/Makefile8
-rw-r--r--arch/sh/boards/superh/microdev/io.c370
-rw-r--r--arch/sh/boards/superh/microdev/irq.c200
-rw-r--r--arch/sh/boards/superh/microdev/led.c102
-rw-r--r--arch/sh/boards/superh/microdev/setup.c278
-rw-r--r--arch/sh/boards/unknown/Makefile6
-rw-r--r--arch/sh/boards/unknown/io.c46
-rw-r--r--arch/sh/boards/unknown/mach.c67
-rw-r--r--arch/sh/boards/unknown/setup.c23
-rw-r--r--arch/sh/boot/Makefile20
-rw-r--r--arch/sh/boot/compressed/Makefile41
-rw-r--r--arch/sh/boot/compressed/head.S120
-rw-r--r--arch/sh/boot/compressed/install.sh56
-rw-r--r--arch/sh/boot/compressed/misc.c240
-rw-r--r--arch/sh/boot/compressed/vmlinux.scr9
-rw-r--r--arch/sh/cchips/Kconfig96
-rw-r--r--arch/sh/cchips/hd6446x/hd64461/Makefile6
-rw-r--r--arch/sh/cchips/hd6446x/hd64461/io.c157
-rw-r--r--arch/sh/cchips/hd6446x/hd64461/setup.c171
-rw-r--r--arch/sh/cchips/hd6446x/hd64465/Makefile6
-rw-r--r--arch/sh/cchips/hd6446x/hd64465/gpio.c196
-rw-r--r--arch/sh/cchips/hd6446x/hd64465/io.c216
-rw-r--r--arch/sh/cchips/hd6446x/hd64465/setup.c202
-rw-r--r--arch/sh/cchips/voyagergx/Makefile8
-rw-r--r--arch/sh/cchips/voyagergx/consistent.c126
-rw-r--r--arch/sh/cchips/voyagergx/irq.c194
-rw-r--r--arch/sh/cchips/voyagergx/setup.c37
-rw-r--r--arch/sh/configs/adx_defconfig539
-rw-r--r--arch/sh/configs/cqreek_defconfig533
-rw-r--r--arch/sh/configs/dreamcast_defconfig794
-rw-r--r--arch/sh/configs/hp680_defconfig554
-rw-r--r--arch/sh/configs/microdev_defconfig734
-rw-r--r--arch/sh/configs/rts7751r2d_defconfig847
-rw-r--r--arch/sh/configs/se7300_defconfig531
-rw-r--r--arch/sh/configs/se73180_defconfig496
-rw-r--r--arch/sh/configs/se7705_defconfig714
-rw-r--r--arch/sh/configs/se7750_defconfig713
-rw-r--r--arch/sh/configs/se7751_defconfig777
-rw-r--r--arch/sh/configs/sh03_defconfig924
-rw-r--r--arch/sh/configs/snapgear_defconfig699
-rw-r--r--arch/sh/configs/systemh_defconfig509
-rw-r--r--arch/sh/drivers/Makefile7
-rw-r--r--arch/sh/drivers/dma/Kconfig55
-rw-r--r--arch/sh/drivers/dma/Makefile9
-rw-r--r--arch/sh/drivers/dma/dma-api.c292
-rw-r--r--arch/sh/drivers/dma/dma-g2.c171
-rw-r--r--arch/sh/drivers/dma/dma-isa.c106
-rw-r--r--arch/sh/drivers/dma/dma-pvr2.c109
-rw-r--r--arch/sh/drivers/dma/dma-sh.c267
-rw-r--r--arch/sh/drivers/dma/dma-sh.h52
-rw-r--r--arch/sh/drivers/dma/dma-sysfs.c133
-rw-r--r--arch/sh/drivers/pci/Kconfig41
-rw-r--r--arch/sh/drivers/pci/Makefile16
-rw-r--r--arch/sh/drivers/pci/dma-dreamcast.c71
-rw-r--r--arch/sh/drivers/pci/fixups-dreamcast.c81
-rw-r--r--arch/sh/drivers/pci/fixups-rts7751r2d.c43
-rw-r--r--arch/sh/drivers/pci/fixups-sh03.c61
-rw-r--r--arch/sh/drivers/pci/ops-bigsur.c88
-rw-r--r--arch/sh/drivers/pci/ops-dreamcast.c169
-rw-r--r--arch/sh/drivers/pci/ops-rts7751r2d.c79
-rw-r--r--arch/sh/drivers/pci/ops-sh03.c45
-rw-r--r--arch/sh/drivers/pci/ops-snapgear.c102
-rw-r--r--arch/sh/drivers/pci/pci-auto.c555
-rw-r--r--arch/sh/drivers/pci/pci-sh7751.c417
-rw-r--r--arch/sh/drivers/pci/pci-sh7751.h303
-rw-r--r--arch/sh/drivers/pci/pci-st40.c509
-rw-r--r--arch/sh/drivers/pci/pci-st40.h136
-rw-r--r--arch/sh/drivers/pci/pci.c155
-rw-r--r--arch/sh/kernel/Makefile22
-rw-r--r--arch/sh/kernel/asm-offsets.c32
-rw-r--r--arch/sh/kernel/cf-enabler.c158
-rw-r--r--arch/sh/kernel/cpu/Makefile16
-rw-r--r--arch/sh/kernel/cpu/adc.c36
-rw-r--r--arch/sh/kernel/cpu/bus.c195
-rw-r--r--arch/sh/kernel/cpu/init.c222
-rw-r--r--arch/sh/kernel/cpu/irq_imask.c116
-rw-r--r--arch/sh/kernel/cpu/irq_ipr.c339
-rw-r--r--arch/sh/kernel/cpu/rtc.c136
-rw-r--r--arch/sh/kernel/cpu/sh2/Makefile6
-rw-r--r--arch/sh/kernel/cpu/sh2/probe.c39
-rw-r--r--arch/sh/kernel/cpu/sh3/Makefile6
-rw-r--r--arch/sh/kernel/cpu/sh3/ex.S199
-rw-r--r--arch/sh/kernel/cpu/sh3/probe.c97
-rw-r--r--arch/sh/kernel/cpu/sh4/Makefile10
-rw-r--r--arch/sh/kernel/cpu/sh4/ex.S384
-rw-r--r--arch/sh/kernel/cpu/sh4/fpu.c335
-rw-r--r--arch/sh/kernel/cpu/sh4/irq_intc2.c222
-rw-r--r--arch/sh/kernel/cpu/sh4/probe.c138
-rw-r--r--arch/sh/kernel/cpu/sh4/sq.c453
-rw-r--r--arch/sh/kernel/cpu/ubc.S59
-rw-r--r--arch/sh/kernel/cpufreq.c218
-rw-r--r--arch/sh/kernel/early_printk.c137
-rw-r--r--arch/sh/kernel/entry.S1149
-rw-r--r--arch/sh/kernel/head.S76
-rw-r--r--arch/sh/kernel/init_task.c36
-rw-r--r--arch/sh/kernel/io.c59
-rw-r--r--arch/sh/kernel/io_generic.c243
-rw-r--r--arch/sh/kernel/irq.c106
-rw-r--r--arch/sh/kernel/kgdb_jmp.S33
-rw-r--r--arch/sh/kernel/kgdb_stub.c1491
-rw-r--r--arch/sh/kernel/module.c146
-rw-r--r--arch/sh/kernel/process.c531
-rw-r--r--arch/sh/kernel/ptrace.c320
-rw-r--r--arch/sh/kernel/semaphore.c139
-rw-r--r--arch/sh/kernel/setup.c649
-rw-r--r--arch/sh/kernel/sh_bios.c75
-rw-r--r--arch/sh/kernel/sh_ksyms.c126
-rw-r--r--arch/sh/kernel/signal.c607
-rw-r--r--arch/sh/kernel/smp.c199
-rw-r--r--arch/sh/kernel/sys_sh.c289
-rw-r--r--arch/sh/kernel/time.c657
-rw-r--r--arch/sh/kernel/traps.c712
-rw-r--r--arch/sh/kernel/vmlinux.lds.S155
-rw-r--r--arch/sh/lib/Makefile13
-rw-r--r--arch/sh/lib/checksum.S385
-rw-r--r--arch/sh/lib/delay.c41
-rw-r--r--arch/sh/lib/div64-generic.c19
-rw-r--r--arch/sh/lib/div64.S46
-rw-r--r--arch/sh/lib/memchr.S26
-rw-r--r--arch/sh/lib/memcpy-sh4.S800
-rw-r--r--arch/sh/lib/memcpy.S227
-rw-r--r--arch/sh/lib/memmove.S254
-rw-r--r--arch/sh/lib/memset.S57
-rw-r--r--arch/sh/lib/strcasecmp.c26
-rw-r--r--arch/sh/lib/strlen.S70
-rw-r--r--arch/sh/lib/udivdi3.c16
-rw-r--r--arch/sh/mm/Makefile25
-rw-r--r--arch/sh/mm/cache-sh2.c50
-rw-r--r--arch/sh/mm/cache-sh3.c100
-rw-r--r--arch/sh/mm/cache-sh4.c362
-rw-r--r--arch/sh/mm/cache-sh7705.c206
-rw-r--r--arch/sh/mm/clear_page.S295
-rw-r--r--arch/sh/mm/consistent.c85
-rw-r--r--arch/sh/mm/copy_page.S397
-rw-r--r--arch/sh/mm/extable.c22
-rw-r--r--arch/sh/mm/fault-nommu.c82
-rw-r--r--arch/sh/mm/fault.c374
-rw-r--r--arch/sh/mm/hugetlbpage.c264
-rw-r--r--arch/sh/mm/init.c313
-rw-r--r--arch/sh/mm/ioremap.c163
-rw-r--r--arch/sh/mm/pg-dma.c97
-rw-r--r--arch/sh/mm/pg-nommu.c36
-rw-r--r--arch/sh/mm/pg-sh4.c122
-rw-r--r--arch/sh/mm/pg-sh7705.c137
-rw-r--r--arch/sh/mm/tlb-nommu.c58
-rw-r--r--arch/sh/mm/tlb-sh3.c92
-rw-r--r--arch/sh/mm/tlb-sh4.c96
-rw-r--r--arch/sh/oprofile/Kconfig23
-rw-r--r--arch/sh/oprofile/Makefile13
-rw-r--r--arch/sh/oprofile/op_model_null.c23
-rw-r--r--arch/sh/oprofile/op_model_sh7750.c281
-rw-r--r--arch/sh/ramdisk/Makefile20
-rw-r--r--arch/sh/ramdisk/ld.script9
-rw-r--r--arch/sh/tools/Makefile15
-rw-r--r--arch/sh/tools/gen-mach-types49
-rw-r--r--arch/sh/tools/mach-types31
271 files changed, 45413 insertions, 0 deletions
diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig
new file mode 100644
index 000000000000..722ea1d63c94
--- /dev/null
+++ b/arch/sh/Kconfig
@@ -0,0 +1,793 @@
+#
+# For a description of the syntax of this configuration file,
+# see Documentation/kbuild/kconfig-language.txt.
+#
+
+mainmenu "Linux/SuperH Kernel Configuration"
+
+config SUPERH
+ bool
+ default y
+ help
+ The SuperH is a RISC processor targeted for use in embedded systems
+ and consumer electronics; it was also used in the Sega Dreamcast
+ gaming console. The SuperH port has a home page at
+ <http://www.linux-sh.org/>.
+
+config UID16
+ bool
+ default y
+
+config RWSEM_GENERIC_SPINLOCK
+ bool
+ default y
+
+config RWSEM_XCHGADD_ALGORITHM
+ bool
+
+config GENERIC_HARDIRQS
+ bool
+ default y
+
+config GENERIC_IRQ_PROBE
+ bool
+ default y
+
+config GENERIC_CALIBRATE_DELAY
+ bool
+ default y
+
+source "init/Kconfig"
+
+menu "System type"
+
+choice
+ prompt "SuperH system type"
+ default SH_UNKNOWN
+
+config SH_SOLUTION_ENGINE
+ bool "SolutionEngine"
+ help
+ Select SolutionEngine if configuring for a Hitachi SH7709
+ or SH7750 evaluation board.
+
+config SH_7751_SOLUTION_ENGINE
+ bool "SolutionEngine7751"
+ help
+ Select 7751 SolutionEngine if configuring for a Hitachi SH7751
+ evaluation board.
+
+config SH_7300_SOLUTION_ENGINE
+ bool "SolutionEngine7300"
+ help
+ Select 7300 SolutionEngine if configuring for a Hitachi SH7300(SH-Mobile V)
+ evaluation board.
+
+config SH_73180_SOLUTION_ENGINE
+ bool "SolutionEngine73180"
+ help
+ Select 73180 SolutionEngine if configuring for a Hitachi SH73180(SH-Mobile 3)
+ evaluation board.
+
+config SH_7751_SYSTEMH
+ bool "SystemH7751R"
+ help
+ Select SystemH if you are configuring for a Renesas SystemH
+ 7751R evaluation board.
+
+config SH_STB1_HARP
+ bool "STB1_Harp"
+
+config SH_STB1_OVERDRIVE
+ bool "STB1_Overdrive"
+
+config SH_HP620
+ bool "HP620"
+ help
+ Select HP620 if configuring for a HP jornada HP620.
+ More information (hardware only) at
+ <http://www.hp.com/jornada/>.
+
+config SH_HP680
+ bool "HP680"
+ help
+ Select HP680 if configuring for a HP Jornada HP680.
+ More information (hardware only) at
+ <http://www.hp.com/jornada/products/680/>.
+
+config SH_HP690
+ bool "HP690"
+ help
+ Select HP690 if configuring for a HP Jornada HP690.
+ More information (hardware only)
+ at <http://www.hp.com/jornada/products/680/>.
+
+config SH_CQREEK
+ bool "CqREEK"
+ help
+ Select CqREEK if configuring for a CqREEK SH7708 or SH7750.
+ More information at
+ <http://sources.redhat.com/ecos/hardware.html#SuperH>.
+
+config SH_DMIDA
+ bool "DMIDA"
+ help
+ Select DMIDA if configuring for a DataMyte 4000 Industrial
+ Digital Assistant. More information at <http://www.dmida.com/>.
+
+config SH_EC3104
+ bool "EC3104"
+ help
+ Select EC3104 if configuring for a system with an Eclipse
+ International EC3104 chip, e.g. the Harris AD2000.
+
+config SH_SATURN
+ bool "Saturn"
+ help
+ Select Saturn if configuring for a SEGA Saturn.
+
+config SH_DREAMCAST
+ bool "Dreamcast"
+ help
+ Select Dreamcast if configuring for a SEGA Dreamcast.
+ More information at
+ <http://www.m17n.org/linux-sh/dreamcast/>. There is a
+ Dreamcast project is at <http://linuxdc.sourceforge.net/>.
+
+config SH_CAT68701
+ bool "CAT68701"
+
+config SH_BIGSUR
+ bool "BigSur"
+
+config SH_SH2000
+ bool "SH2000"
+ help
+ SH-2000 is a single-board computer based around SH7709A chip
+ intended for embedded applications.
+ It has an Ethernet interface (CS8900A), direct connected
+ Compact Flash socket, three serial ports and PC-104 bus.
+ More information at <http://sh2000.sh-linux.org>.
+
+config SH_ADX
+ bool "ADX"
+
+config SH_MPC1211
+ bool "MPC1211"
+
+config SH_SH03
+ bool "SH03"
+ help
+ CTP/PCI-SH03 is a CPU module computer that produced
+ by Interface Corporation.
+ It is compact and excellent in durability.
+ It will play an active part in your factory or laboratory
+ as a FA computer.
+ More information at <http://www.interface.co.jp>
+
+config SH_SECUREEDGE5410
+ bool "SecureEdge5410"
+ help
+ Select SecureEdge5410 if configuring for a SnapGear SH board.
+ This includes both the OEM SecureEdge products as well as the
+ SME product line.
+
+config SH_HS7751RVOIP
+ bool "HS7751RVOIP"
+ help
+ Select HS7751RVOIP if configuring for a Renesas Technology
+ Sales VoIP board.
+
+config SH_RTS7751R2D
+ bool "RTS7751R2D"
+ help
+ Select RTS7751R2D if configuring for a Renesas Technology
+ Sales SH-Graphics board.
+
+config SH_EDOSK7705
+ bool "EDOSK7705"
+
+config SH_SH4202_MICRODEV
+ bool "SH4-202 MicroDev"
+ help
+ Select SH4-202 MicroDev if configuring for a SuperH MicroDev board
+ with an SH4-202 CPU.
+
+config SH_UNKNOWN
+ bool "BareCPU"
+ help
+ "Bare CPU" aka "unknown" means an SH-based system which is not one
+ of the specific ones mentioned above, which means you need to enter
+ all sorts of stuff like CONFIG_MEMORY_START because the config
+ system doesn't already know what it is. You get a machine vector
+ without any platform-specific code in it, so things like the RTC may
+ not work.
+
+ This option is for the early stages of porting to a new machine.
+
+endchoice
+
+choice
+ prompt "Processor family"
+ default CPU_SH4
+ help
+ This option determines the CPU family to compile for. Supported
+ targets are SH-2, SH-3, and SH-4. These options are independent of
+ CPU functionality. As such, SH-DSP users will still want to select
+ their respective processor family in addition to the DSP support
+ option.
+
+config CPU_SH2
+ bool "SH-2"
+ select SH_WRITETHROUGH
+
+config CPU_SH3
+ bool "SH-3"
+
+config CPU_SH4
+ bool "SH-4"
+
+endchoice
+
+choice
+ prompt "Processor subtype"
+
+config CPU_SUBTYPE_SH7604
+ bool "SH7604"
+ depends on CPU_SH2
+ help
+ Select SH7604 if you have SH7604
+
+config CPU_SUBTYPE_SH7300
+ bool "SH7300"
+ depends on CPU_SH3
+
+config CPU_SUBTYPE_SH7705
+ bool "SH7705"
+ depends on CPU_SH3
+
+config CPU_SUBTYPE_SH7707
+ bool "SH7707"
+ depends on CPU_SH3
+ help
+ Select SH7707 if you have a 60 Mhz SH-3 HD6417707 CPU.
+
+config CPU_SUBTYPE_SH7708
+ bool "SH7708"
+ depends on CPU_SH3
+ help
+ Select SH7708 if you have a 60 Mhz SH-3 HD6417708S or
+ if you have a 100 Mhz SH-3 HD6417708R CPU.
+
+config CPU_SUBTYPE_SH7709
+ bool "SH7709"
+ depends on CPU_SH3
+ help
+ Select SH7709 if you have a 80 Mhz SH-3 HD6417709 CPU.
+
+config CPU_SUBTYPE_SH7750
+ bool "SH7750"
+ depends on CPU_SH4
+ help
+ Select SH7750 if you have a 200 Mhz SH-4 HD6417750 CPU.
+
+config CPU_SUBTYPE_SH7751
+ bool "SH7751/SH7751R"
+ depends on CPU_SH4
+ help
+ Select SH7751 if you have a 166 Mhz SH-4 HD6417751 CPU,
+ or if you have a HD6417751R CPU.
+
+config CPU_SUBTYPE_SH7760
+ bool "SH7760"
+ depends on CPU_SH4
+
+config CPU_SUBTYPE_SH73180
+ bool "SH73180"
+ depends on CPU_SH4
+
+config CPU_SUBTYPE_ST40STB1
+ bool "ST40STB1 / ST40RA"
+ depends on CPU_SH4
+ help
+ Select ST40STB1 if you have a ST40RA CPU.
+ This was previously called the ST40STB1, hence the option name.
+
+config CPU_SUBTYPE_ST40GX1
+ bool "ST40GX1"
+ depends on CPU_SH4
+ help
+ Select ST40GX1 if you have a ST40GX1 CPU.
+
+config CPU_SUBTYPE_SH4_202
+ bool "SH4-202"
+ depends on CPU_SH4
+
+endchoice
+
+config SH7705_CACHE_32KB
+ bool "Enable 32KB cache size for SH7705"
+ depends on CPU_SUBTYPE_SH7705
+ default y
+
+config MMU
+ bool "Support for memory management hardware"
+ depends on !CPU_SH2
+ default y
+ help
+ Early SH processors (such as the SH7604) lack an MMU. In order to
+ boot on these systems, this option must not be set.
+
+ On other systems (such as the SH-3 and 4) where an MMU exists,
+ turning this off will boot the kernel on these machines with the
+ MMU implicitly switched off.
+
+choice
+ prompt "HugeTLB page size"
+ depends on HUGETLB_PAGE && CPU_SH4 && MMU
+ default HUGETLB_PAGE_SIZE_64K
+
+config HUGETLB_PAGE_SIZE_64K
+ bool "64K"
+
+config HUGETLB_PAGE_SIZE_1MB
+ bool "1MB"
+
+endchoice
+
+config CMDLINE_BOOL
+ bool "Default bootloader kernel arguments"
+
+config CMDLINE
+ string "Initial kernel command string"
+ depends on CMDLINE_BOOL
+ default "console=ttySC1,115200"
+
+# Platform-specific memory start and size definitions
+config MEMORY_START
+ hex "Physical memory start address" if !MEMORY_SET || MEMORY_OVERRIDE
+ default "0x08000000" if !MEMORY_SET || MEMORY_OVERRIDE || !MEMORY_OVERRIDE && SH_ADX || SH_MPC1211 || SH_SH03 || SH_SECUREEDGE5410 || SH_SH4202_MICRODEV
+ default "0x0c000000" if !MEMORY_OVERRIDE && (SH_DREAMCAST || SH_HP600 || SH_BIGSUR || SH_SH2000 || SH_73180_SOLUTION_ENGINE || SH_7300_SOLUTION_ENGINE || SH_7751_SOLUTION_ENGINE || SH_SOLUTION_ENGINE || SH_HS7751RVOIP || SH_RTS7751R2D || SH_EDOSK7705)
+ ---help---
+ Computers built with Hitachi SuperH processors always
+ map the ROM starting at address zero. But the processor
+ does not specify the range that RAM takes.
+
+ The physical memory (RAM) start address will be automatically
+ set to 08000000, unless you selected one of the following
+ processor types: SolutionEngine, Overdrive, HP620, HP680, HP690,
+ in which case the start address will be set to 0c000000.
+
+ Tweak this only when porting to a new machine which is not already
+ known by the config system. Changing it from the known correct
+ value on any of the known systems will only lead to disaster.
+
+config MEMORY_SIZE
+ hex "Physical memory size" if !MEMORY_SET || MEMORY_OVERRIDE
+ default "0x00400000" if !MEMORY_SET || MEMORY_OVERRIDE || !MEMORY_OVERRIDE && SH_ADX || !MEMORY_OVERRIDE && (SH_HP600 || SH_BIGSUR || SH_SH2000)
+ default "0x01000000" if !MEMORY_OVERRIDE && SH_DREAMCAST || SH_SECUREEDGE5410 || SH_EDOSK7705
+ default "0x02000000" if !MEMORY_OVERRIDE && (SH_73180_SOLUTION_ENGINE || SH_SOLUTION_ENGINE)
+ default "0x04000000" if !MEMORY_OVERRIDE && (SH_7300_SOLUTION_ENGINE || SH_7751_SOLUTION_ENGINE || SH_HS7751RVOIP || SH_RTS7751R2D || SH_SH4202_MICRODEV)
+ default "0x08000000" if SH_MPC1211 || SH_SH03
+ help
+ This sets the default memory size assumed by your SH kernel. It can
+ be overridden as normal by the 'mem=' argument on the kernel command
+ line. If unsure, consult your board specifications or just leave it
+ as 0x00400000 which was the default value before this became
+ configurable.
+
+config MEMORY_SET
+ bool
+ depends on !MEMORY_OVERRIDE && (SH_MPC1211 || SH_SH03 || SH_ADX || SH_DREAMCAST || SH_HP600 || SH_BIGSUR || SH_SH2000 || SH_7751_SOLUTION_ENGINE || SH_SOLUTION_ENGINE || SH_SECUREEDGE5410 || SH_HS7751RVOIP || SH_RTS7751R2D || SH_SH4202_MICRODEV || SH_EDOSK7705)
+ default y
+ help
+ This is an option about which you will never be asked a question.
+ Therefore, I conclude that you do not exist - go away.
+
+ There is a grue here.
+
+# If none of the above have set memory start/size, ask the user.
+config MEMORY_OVERRIDE
+ bool "Override default load address and memory size"
+
+# XXX: break these out into the board-specific configs below
+config CF_ENABLER
+ bool "Compact Flash Enabler support"
+ depends on SH_ADX || SH_SOLUTION_ENGINE || SH_UNKNOWN || SH_CAT68701 || SH_SH03
+ ---help---
+ Compact Flash is a small, removable mass storage device introduced
+ in 1994 originally as a PCMCIA device. If you say `Y' here, you
+ compile in support for Compact Flash devices directly connected to
+ a SuperH processor. A Compact Flash FAQ is available at
+ <http://www.compactflash.org/faqs/faq.htm>.
+
+ If your board has "Directly Connected" CompactFlash at area 5 or 6,
+ you may want to enable this option. Then, you can use CF as
+ primary IDE drive (only tested for SanDisk).
+
+ If in doubt, select 'N'.
+
+choice
+ prompt "Compact Flash Connection Area"
+ depends on CF_ENABLER
+ default CF_AREA6
+
+config CF_AREA5
+ bool "Area5"
+ help
+ If your board has "Directly Connected" CompactFlash, You should
+ select the area where your CF is connected to.
+
+ - "Area5" if CompactFlash is connected to Area 5 (0x14000000)
+ - "Area6" if it is connected to Area 6 (0x18000000)
+
+ "Area6" will work for most boards. For ADX, select "Area5".
+
+config CF_AREA6
+ bool "Area6"
+
+endchoice
+
+config CF_BASE_ADDR
+ hex
+ depends on CF_ENABLER
+ default "0xb8000000" if CF_AREA6
+ default "0xb4000000" if CF_AREA5
+
+# The SH7750 RTC module is disabled in the Dreamcast
+config SH_RTC
+ bool
+ depends on !SH_DREAMCAST && !SH_SATURN && !SH_7300_SOLUTION_ENGINE && !SH_73180_SOLUTION_ENGINE
+ default y
+ help
+ Selecting this option will allow the Linux kernel to emulate
+ PC's RTC.
+
+ If unsure, say N.
+
+config SH_FPU
+ bool "FPU support"
+ depends on !CPU_SH3
+ default y
+ help
+ Selecting this option will enable support for SH processors that
+ have FPU units (ie, SH77xx).
+
+ This option must be set in order to enable the FPU.
+
+config SH_DSP
+ bool "DSP support"
+ depends on !CPU_SH4
+ default y
+ help
+ Selecting this option will enable support for SH processors that
+ have DSP units (ie, SH2-DSP and SH3-DSP). It is safe to say Y here
+ by default, as the existance of the DSP will be probed at runtime.
+
+ This option must be set in order to enable the DSP.
+
+config SH_ADC
+ bool "ADC support"
+ depends on CPU_SH3
+ default y
+ help
+ Selecting this option will allow the Linux kernel to use SH3 on-chip
+ ADC module.
+
+ If unsure, say N.
+
+config SH_HP600
+ bool
+ depends on SH_HP620 || SH_HP680 || SH_HP690
+ default y
+
+config CPU_SUBTYPE_ST40
+ bool
+ depends on CPU_SUBTYPE_ST40STB1 || CPU_SUBTYPE_ST40GX1
+ default y
+
+config DISCONTIGMEM
+ bool
+ depends on SH_HP690
+ default y
+ help
+ Say Y to upport efficient handling of discontiguous physical memory,
+ for architectures which are either NUMA (Non-Uniform Memory Access)
+ or have huge holes in the physical address space for other reasons.
+ See <file:Documentation/vm/numa> for more.
+
+config ZERO_PAGE_OFFSET
+ hex "Zero page offset"
+ default "0x00001000" if !(SH_MPC1211 || SH_SH03)
+ default "0x00004000" if SH_MPC1211 || SH_SH03
+ help
+ This sets the default offset of zero page.
+
+# XXX: needs to lose subtype for system type
+config ST40_LMI_MEMORY
+ bool "Memory on LMI"
+ depends on CPU_SUBTYPE_ST40STB1
+
+config MEMORY_START
+ hex
+ depends on CPU_SUBTYPE_ST40STB1 && ST40_LMI_MEMORY
+ default "0x08000000"
+
+config MEMORY_SIZE
+ hex
+ depends on CPU_SUBTYPE_ST40STB1 && ST40_LMI_MEMORY
+ default "0x00400000"
+
+config MEMORY_SET
+ bool
+ depends on CPU_SUBTYPE_ST40STB1 && ST40_LMI_MEMORY
+ default y
+
+config BOOT_LINK_OFFSET
+ hex "Link address offset for booting"
+ default "0x00800000"
+ help
+ This option allows you to set the link address offset of the zImage.
+ This can be useful if you are on a board which has a small amount of
+ memory.
+
+config CPU_LITTLE_ENDIAN
+ bool "Little Endian"
+ help
+ Some SuperH machines can be configured for either little or big
+ endian byte order. These modes require different kernels. Say Y if
+ your machine is little endian, N if it's a big endian machine.
+
+config PREEMPT
+ bool "Preemptible Kernel (EXPERIMENTAL)"
+ depends on EXPERIMENTAL
+
+config UBC_WAKEUP
+ bool "Wakeup UBC on startup"
+ help
+ Selecting this option will wakeup the User Break Controller (UBC) on
+ startup. Although the UBC is left in an awake state when the processor
+ comes up, some boot loaders misbehave by putting the UBC to sleep in a
+ power saving state, which causes issues with things like ptrace().
+
+ If unsure, say N.
+
+config SH_WRITETHROUGH
+ bool "Use write-through caching"
+ default y if CPU_SH2
+ help
+ Selecting this option will configure the caches in write-through
+ mode, as opposed to the default write-back configuration.
+
+ Since there's sill some aliasing issues on SH-4, this option will
+ unfortunately still require the majority of flushing functions to
+ be implemented to deal with aliasing.
+
+ If unsure, say N.
+
+config SH_OCRAM
+ bool "Operand Cache RAM (OCRAM) support"
+ help
+ Selecting this option will automatically tear down the number of
+ sets in the dcache by half, which in turn exposes a memory range.
+
+ The addresses for the OC RAM base will vary according to the
+ processor version. Consult vendor documentation for specifics.
+
+ If unsure, say N.
+
+config SH_STORE_QUEUES
+ bool "Support for Store Queues"
+ depends on CPU_SH4
+ help
+ Selecting this option will enable an in-kernel API for manipulating
+ the store queues integrated in the SH-4 processors.
+
+config SMP
+ bool "Symmetric multi-processing support"
+ ---help---
+ This enables support for systems with more than one CPU. If you have
+ a system with only one CPU, like most personal computers, say N. If
+ you have a system with more than one CPU, say Y.
+
+ If you say N here, the kernel will run on single and multiprocessor
+ machines, but will use only one CPU of a multiprocessor machine. If
+ you say Y here, the kernel will run on many, but not all,
+ singleprocessor machines. On a singleprocessor machine, the kernel
+ will run faster if you say N here.
+
+ People using multiprocessor machines who say Y here should also say
+ Y to "Enhanced Real Time Clock Support", below.
+
+ See also the <file:Documentation/smp.txt>,
+ <file:Documentation/nmi_watchdog.txt> and the SMP-HOWTO available
+ at <http://www.tldp.org/docs.html#howto>.
+
+ If you don't know what to do here, say N.
+
+config NR_CPUS
+ int "Maximum number of CPUs (2-32)"
+ range 2 32
+ depends on SMP
+ default "2"
+ help
+ This allows you to specify the maximum number of CPUs which this
+ kernel will support. The maximum supported value is 32 and the
+ minimum value which makes sense is 2.
+
+ This is purely to save memory - each supported CPU adds
+ approximately eight kilobytes to the kernel image.
+
+config HS7751RVOIP_CODEC
+ bool "Support VoIP Codec section"
+ depends on SH_HS7751RVOIP
+ help
+ Selecting this option will support CODEC section.
+
+config RTS7751R2D_REV11
+ bool "RTS7751R2D Rev. 1.1 board support"
+ depends on SH_RTS7751R2D
+ help
+ Selecting this option will support version rev. 1.1.
+
+config SH_PCLK_CALC
+ bool
+ default n if CPU_SUBTYPE_SH7300 || CPU_SUBTYPE_SH73180
+ default y
+ help
+ This option will cause the PCLK value to be probed at run-time. It
+ will display a notification if the probed value has greater than a
+ 1% variance of the hardcoded CONFIG_SH_PCLK_FREQ.
+
+config SH_PCLK_FREQ
+ int "Peripheral clock frequency (in Hz)"
+ default "50000000" if CPU_SUBTYPE_SH7750
+ default "60000000" if CPU_SUBTYPE_SH7751
+ default "33333333" if CPU_SUBTYPE_SH7300
+ default "27000000" if CPU_SUBTYPE_SH73180
+ default "66000000" if CPU_SUBTYPE_SH4_202
+ default "1193182"
+ help
+ This option is used to specify the peripheral clock frequency. This
+ option must be set for each processor in order for the kernel to
+ function reliably. If no sane default exists, we use a default from
+ the legacy i8254. Any discrepancies will be reported on boot time
+ with an auto-probed frequency which should be considered the proper
+ value for your hardware.
+
+menu "CPU Frequency scaling"
+
+source "drivers/cpufreq/Kconfig"
+
+config SH_CPU_FREQ
+ tristate "SuperH CPU Frequency driver"
+ depends on CPU_FREQ
+ select CPU_FREQ_TABLE
+ help
+ This adds the cpufreq driver for SuperH. At present, only
+ the SH-4 is supported.
+
+ For details, take a look at <file:Documentation/cpu-freq>.
+
+ If unsure, say N.
+
+endmenu
+
+source "arch/sh/drivers/dma/Kconfig"
+
+source "arch/sh/cchips/Kconfig"
+
+config HEARTBEAT
+ bool "Heartbeat LED"
+ depends on SH_MPC1211 || SH_SH03 || SH_CAT68701 || SH_STB1_HARP || SH_STB1_OVERDRIVE || SH_BIGSUR || SH_7751_SOLUTION_ENGINE || SH_7300_SOLUTION_ENGINE || SH_73180_SOLUTION_ENGINE || SH_SOLUTION_ENGINE || SH_RTS7751R2D || SH_SH4202_MICRODEV
+ help
+ Use the power-on LED on your machine as a load meter. The exact
+ behavior is platform-dependent, but normally the flash frequency is
+ a hyperbolic function of the 5-minute load average.
+
+config RTC_9701JE
+ tristate "EPSON RTC-9701JE support"
+ depends on SH_RTS7751R2D
+ help
+ Selecting this option will support EPSON RTC-9701JE.
+
+endmenu
+
+
+menu "Bus options (PCI, PCMCIA, EISA, MCA, ISA)"
+
+# Even on SuperH devices which don't have an ISA bus,
+# this variable helps the PCMCIA modules handle
+# IRQ requesting properly -- Greg Banks.
+#
+# Though we're generally not interested in it when
+# we're not using PCMCIA, so we make it dependent on
+# PCMCIA outright. -- PFM.
+config ISA
+ bool
+ default y if PCMCIA || SMC91X
+ help
+ Find out whether you have ISA slots on your motherboard. ISA 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 PCI, EISA, MicroChannel
+ (MCA) or VESA. ISA is an older system, now being displaced by PCI;
+ newer boards don't support it. If you have ISA, say Y, otherwise N.
+
+config EISA
+ bool
+ ---help---
+ The Extended Industry Standard Architecture (EISA) bus was
+ developed as an open alternative to the IBM MicroChannel bus.
+
+ The EISA bus provided some of the features of the IBM MicroChannel
+ bus while maintaining backward compatibility with cards made for
+ the older ISA bus. The EISA bus saw limited use between 1988 and
+ 1995 when it was made obsolete by the PCI bus.
+
+ Say Y here if you are building a kernel for an EISA-based machine.
+
+ Otherwise, say N.
+
+config MCA
+ bool
+ help
+ MicroChannel Architecture is found in some IBM PS/2 machines and
+ laptops. It is a bus system similar to PCI or ISA. See
+ <file:Documentation/mca.txt> (and especially the web page given
+ there) before attempting to build an MCA bus kernel.
+
+config SBUS
+ bool
+
+config MAPLE
+ tristate "Maple Bus support"
+ depends on SH_DREAMCAST
+ default y
+
+source "arch/sh/drivers/pci/Kconfig"
+
+source "drivers/pci/Kconfig"
+
+source "drivers/pcmcia/Kconfig"
+
+source "drivers/pci/hotplug/Kconfig"
+
+endmenu
+
+menu "Executable file formats"
+
+source "fs/Kconfig.binfmt"
+
+endmenu
+
+menu "SH initrd options"
+ depends on BLK_DEV_INITRD
+
+config EMBEDDED_RAMDISK
+ bool "Embed root filesystem ramdisk into the kernel"
+
+config EMBEDDED_RAMDISK_IMAGE
+ string "Filename of gziped ramdisk image"
+ depends on EMBEDDED_RAMDISK
+ default "ramdisk.gz"
+ help
+ This is the filename of the ramdisk image to be built into the
+ kernel. Relative pathnames are relative to arch/sh/ramdisk/.
+ The ramdisk image is not part of the kernel distribution; you must
+ provide one yourself.
+
+endmenu
+
+source "drivers/Kconfig"
+
+source "fs/Kconfig"
+
+source "arch/sh/oprofile/Kconfig"
+
+source "arch/sh/Kconfig.debug"
+
+source "security/Kconfig"
+
+source "crypto/Kconfig"
+
+source "lib/Kconfig"
diff --git a/arch/sh/Kconfig.debug b/arch/sh/Kconfig.debug
new file mode 100644
index 000000000000..3fab181da364
--- /dev/null
+++ b/arch/sh/Kconfig.debug
@@ -0,0 +1,124 @@
+menu "Kernel hacking"
+
+source "lib/Kconfig.debug"
+
+config SH_STANDARD_BIOS
+ bool "Use LinuxSH standard BIOS"
+ help
+ Say Y here if your target has the gdb-sh-stub
+ package from www.m17n.org (or any conforming standard LinuxSH BIOS)
+ in FLASH or EPROM. The kernel will use standard BIOS calls during
+ boot for various housekeeping tasks (including calls to read and
+ write characters to a system console, get a MAC address from an
+ on-board Ethernet interface, and shut down the hardware). Note this
+ does not work with machines with an existing operating system in
+ mask ROM and no flash (WindowsCE machines fall in this category).
+ If unsure, say N.
+
+config EARLY_SCIF_CONSOLE
+ bool "Use early SCIF console"
+ depends on CPU_SH4
+
+config EARLY_PRINTK
+ bool "Early printk support"
+ depends on SH_STANDARD_BIOS || EARLY_SCIF_CONSOLE
+ help
+ Say Y here to redirect kernel printk messages to the serial port
+ used by the SH-IPL bootloader, starting very early in the boot
+ process and ending when the kernel's serial console is initialised.
+ This option is only useful porting the kernel to a new machine,
+ when the kernel may crash or hang before the serial console is
+ initialised. If unsure, say N.
+
+config KGDB
+ bool "Include KGDB kernel debugger"
+ help
+ Include in-kernel hooks for kgdb, the Linux kernel source level
+ debugger. See <http://kgdb.sourceforge.net/> for more information.
+ Unless you are intending to debug the kernel, say N here.
+
+menu "KGDB configuration options"
+ depends on KGDB
+
+config MORE_COMPILE_OPTIONS
+ bool "Add any additional compile options"
+ help
+ If you want to add additional CFLAGS to the kernel build, enable this
+ option and then enter what you would like to add in the next question.
+ Note however that -g is already appended with the selection of KGDB.
+
+config COMPILE_OPTIONS
+ string "Additional compile arguments"
+ depends on MORE_COMPILE_OPTIONS
+
+config KGDB_NMI
+ bool "Enter KGDB on NMI"
+ default n
+
+config KGDB_THREAD
+ bool "Include KGDB thread support"
+ default y
+
+config SH_KGDB_CONSOLE
+ bool "Console messages through GDB"
+ default n
+
+config KGDB_SYSRQ
+ bool "Allow SysRq 'G' to enter KGDB"
+ default y
+
+config KGDB_KERNEL_ASSERTS
+ bool "Include KGDB kernel assertions"
+ default n
+
+comment "Serial port setup"
+
+config KGDB_DEFPORT
+ int "Port number (ttySCn)"
+ default "1"
+
+config KGDB_DEFBAUD
+ int "Baud rate"
+ default "115200"
+
+choice
+ prompt "Parity"
+ depends on KGDB
+ default KGDB_DEFPARITY_N
+
+config KGDB_DEFPARITY_N
+ bool "None"
+
+config KGDB_DEFPARITY_E
+ bool "Even"
+
+config KGDB_DEFPARITY_O
+ bool "Odd"
+
+endchoice
+
+choice
+ prompt "Data bits"
+ depends on KGDB
+ default KGDB_DEFBITS_8
+
+config KGDB_DEFBITS_8
+ bool "8"
+
+config KGDB_DEFBITS_7
+ bool "7"
+
+endchoice
+
+endmenu
+
+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
diff --git a/arch/sh/Makefile b/arch/sh/Makefile
new file mode 100644
index 000000000000..b5635635b5ee
--- /dev/null
+++ b/arch/sh/Makefile
@@ -0,0 +1,183 @@
+# $Id: Makefile,v 1.35 2004/04/15 03:39:20 sugioka Exp $
+#
+# 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) 1999 Kaz Kojima
+# Copyright (C) 2002, 2003, 2004 Paul Mundt
+# Copyright (C) 2002 M. R. Brown
+#
+# 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
+#
+
+cflags-y := -mb
+cflags-$(CONFIG_CPU_LITTLE_ENDIAN) := -ml
+
+cflags-$(CONFIG_CPU_SH2) += -m2
+cflags-$(CONFIG_CPU_SH3) += -m3
+cflags-$(CONFIG_CPU_SH4) += -m4 \
+ $(call cc-option,-mno-implicit-fp,-m4-nofpu)
+
+cflags-$(CONFIG_SH_DSP) += -Wa,-dsp
+cflags-$(CONFIG_SH_KGDB) += -g
+
+cflags-$(CONFIG_MORE_COMPILE_OPTIONS) += \
+ $(shell echo $(CONFIG_COMPILE_OPTIONS) | sed -e 's/"//g')
+
+OBJCOPYFLAGS := -O binary -R .note -R .comment -R .stab -R .stabstr -S
+
+#
+# arch/sh/defconfig doesn't reflect any real hardware, and as such should
+# never be used by anyone. Use a board-specific defconfig that has a
+# reasonable chance of being current instead.
+#
+KBUILD_DEFCONFIG := rts7751r2d_defconfig
+
+#
+# Choosing incompatible machines durings configuration will result in
+# error messages during linking.
+#
+LDFLAGS_vmlinux += -e _stext
+
+ifdef CONFIG_CPU_LITTLE_ENDIAN
+LDFLAGS_vmlinux += --defsym 'jiffies=jiffies_64'
+LDFLAGS += -EL
+else
+LDFLAGS_vmlinux += --defsym 'jiffies=jiffies_64+4'
+LDFLAGS += -EB
+endif
+
+CFLAGS += -pipe $(cflags-y)
+AFLAGS += $(cflags-y)
+
+head-y := arch/sh/kernel/head.o arch/sh/kernel/init_task.o
+
+LIBGCC := $(shell $(CC) $(CFLAGS) -print-libgcc-file-name)
+
+core-y += arch/sh/kernel/ arch/sh/mm/
+
+#
+# ramdisk/initrd support
+# You need a compressed ramdisk image, named
+# CONFIG_EMBEDDED_RAMDISK_IMAGE. Relative pathnames
+# are relative to arch/sh/ramdisk/.
+#
+core-$(CONFIG_EMBEDDED_RAMDISK) += arch/sh/ramdisk/
+
+# Boards
+machdir-$(CONFIG_SH_SOLUTION_ENGINE) := se/770x
+machdir-$(CONFIG_SH_7751_SOLUTION_ENGINE) := se/7751
+machdir-$(CONFIG_SH_7300_SOLUTION_ENGINE) := se/7300
+machdir-$(CONFIG_SH_73180_SOLUTION_ENGINE) := se/73180
+machdir-$(CONFIG_SH_STB1_HARP) := harp
+machdir-$(CONFIG_SH_STB1_OVERDRIVE) := overdrive
+machdir-$(CONFIG_SH_HP620) := hp6xx/hp620
+machdir-$(CONFIG_SH_HP680) := hp6xx/hp680
+machdir-$(CONFIG_SH_HP690) := hp6xx/hp690
+machdir-$(CONFIG_SH_CQREEK) := cqreek
+machdir-$(CONFIG_SH_DMIDA) := dmida
+machdir-$(CONFIG_SH_EC3104) := ec3104
+machdir-$(CONFIG_SH_SATURN) := saturn
+machdir-$(CONFIG_SH_DREAMCAST) := dreamcast
+machdir-$(CONFIG_SH_CAT68701) := cat68701
+machdir-$(CONFIG_SH_BIGSUR) := bigsur
+machdir-$(CONFIG_SH_SH2000) := sh2000
+machdir-$(CONFIG_SH_ADX) := adx
+machdir-$(CONFIG_SH_MPC1211) := mpc1211
+machdir-$(CONFIG_SH_SH03) := sh03
+machdir-$(CONFIG_SH_SECUREEDGE5410) := snapgear
+machdir-$(CONFIG_SH_HS7751RVOIP) := renesas/hs7751rvoip
+machdir-$(CONFIG_SH_RTS7751R2D) := renesas/rts7751r2d
+machdir-$(CONFIG_SH_7751_SYSTEMH) := renesas/systemh
+machdir-$(CONFIG_SH_EDOSK7705) := renesas/edosk7705
+machdir-$(CONFIG_SH_SH4202_MICRODEV) := superh/microdev
+machdir-$(CONFIG_SH_UNKNOWN) := unknown
+
+incdir-y := $(notdir $(machdir-y))
+
+incdir-$(CONFIG_SH_SOLUTION_ENGINE) := se
+incdir-$(CONFIG_SH_7751_SOLUTION_ENGINE) := se7751
+incdir-$(CONFIG_SH_7300_SOLUTION_ENGINE) := se7300
+incdir-$(CONFIG_SH_73180_SOLUTION_ENGINE) := se73180
+incdir-$(CONFIG_SH_HP600) := hp6xx
+
+ifneq ($(machdir-y),)
+core-y += arch/sh/boards/$(machdir-y)/
+endif
+
+# Companion chips
+core-$(CONFIG_HD64461) += arch/sh/cchips/hd6446x/hd64461/
+core-$(CONFIG_HD64465) += arch/sh/cchips/hd6446x/hd64465/
+core-$(CONFIG_VOYAGERGX) += arch/sh/cchips/voyagergx/
+
+cpuincdir-$(CONFIG_CPU_SH2) := cpu-sh2
+cpuincdir-$(CONFIG_CPU_SH3) := cpu-sh3
+cpuincdir-$(CONFIG_CPU_SH4) := cpu-sh4
+
+libs-y := arch/sh/lib/ $(libs-y) $(LIBGCC)
+
+drivers-y += arch/sh/drivers/
+drivers-$(CONFIG_OPROFILE) += arch/sh/oprofile/
+
+boot := arch/sh/boot
+
+CPPFLAGS_vmlinux.lds := -traditional
+
+# Update machine arch and proc symlinks if something which affects
+# them changed. We use .arch and .mach to indicate when they were
+# updated last, otherwise make uses the target directory mtime.
+
+include/asm-sh/.cpu: $(wildcard include/config/cpu/*.h) include/config/MARKER
+ @echo ' SYMLINK include/asm-sh/cpu -> include/asm-sh/$(cpuincdir-y)'
+ifneq ($(KBUILD_SRC),)
+ $(Q)mkdir -p include/asm-sh
+ $(Q)ln -fsn $(srctree)/include/asm-sh/$(cpuincdir-y) include/asm-sh/cpu
+else
+ $(Q)ln -fsn $(cpuincdir-y) include/asm-sh/cpu
+endif
+ @touch $@
+
+include/asm-sh/.mach: $(wildcard include/config/sh/*.h) include/config/MARKER
+ @echo ' SYMLINK include/asm-sh/mach -> include/asm-sh/$(incdir-y)'
+ifneq ($(KBUILD_SRC),)
+ $(Q)mkdir -p include/asm-sh
+ $(Q)ln -fsn $(srctree)/include/asm-sh/$(incdir-y) include/asm-sh/mach
+else
+ $(Q)ln -fsn $(incdir-y) include/asm-sh/mach
+endif
+ @touch $@
+
+
+prepare: maketools include/asm-sh/.cpu include/asm-sh/.mach
+
+.PHONY: maketools FORCE
+maketools: include/asm-sh/asm-offsets.h include/linux/version.h FORCE
+ $(Q)$(MAKE) $(build)=arch/sh/tools include/asm-sh/machtypes.h
+
+all: zImage
+
+zImage: vmlinux
+ $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
+
+compressed: zImage
+
+archclean:
+ $(Q)$(MAKE) $(clean)=$(boot)
+
+CLEAN_FILES += include/asm-sh/machtypes.h include/asm-sh/asm-offsets.h
+
+arch/sh/kernel/asm-offsets.s: include/asm include/linux/version.h \
+ include/asm-sh/.cpu include/asm-sh/.mach
+
+include/asm-sh/asm-offsets.h: arch/sh/kernel/asm-offsets.s
+ $(call filechk,gen-asm-offsets)
+
+
+define archhelp
+ @echo ' zImage - Compressed kernel image (arch/sh/boot/zImage)'
+endef
+
diff --git a/arch/sh/boards/adx/Makefile b/arch/sh/boards/adx/Makefile
new file mode 100644
index 000000000000..5b1c531b3991
--- /dev/null
+++ b/arch/sh/boards/adx/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for ADX boards
+#
+
+obj-y := setup.o irq.o irq_maskreq.o
+
diff --git a/arch/sh/boards/adx/irq.c b/arch/sh/boards/adx/irq.c
new file mode 100644
index 000000000000..c6ca409dff98
--- /dev/null
+++ b/arch/sh/boards/adx/irq.c
@@ -0,0 +1,31 @@
+/*
+ * linux/arch/sh/boards/adx/irq.c
+ *
+ * Copyright (C) 2001 A&D Co., Ltd.
+ *
+ * I/O routine and setup routines for A&D ADX Board
+ *
+ * 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 <asm/irq.h>
+
+void init_adx_IRQ(void)
+{
+ int i;
+
+/* printk("init_adx_IRQ()\n");*/
+ /* setup irq_mask_register */
+ irq_mask_register = (unsigned short *)0xa6000008;
+
+ /* cover all external interrupt area by maskreg_irq_type
+ * (Actually, irq15 doesn't exist)
+ */
+ for (i = 0; i < 16; i++) {
+ make_maskreg_irq(i);
+ disable_irq(i);
+ }
+}
diff --git a/arch/sh/boards/adx/irq_maskreg.c b/arch/sh/boards/adx/irq_maskreg.c
new file mode 100644
index 000000000000..ca91bb0f1f5c
--- /dev/null
+++ b/arch/sh/boards/adx/irq_maskreg.c
@@ -0,0 +1,107 @@
+/*
+ * linux/arch/sh/kernel/irq_maskreg.c
+ *
+ * Copyright (C) 2001 A&D Co., Ltd. <http://www.aandd.co.jp>
+ *
+ * This file may be copied or modified under the terms of the GNU
+ * General Public License. See linux/COPYING for more information.
+ *
+ * Interrupt handling for Simple external interrupt mask register
+ *
+ * This is for the machine which have single 16 bit register
+ * for masking external IRQ individually.
+ * Each bit of the register is for masking each interrupt.
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/machvec.h>
+
+/* address of external interrupt mask register
+ * address must be set prior to use these (maybe in init_XXX_irq())
+ * XXX : is it better to use .config than specifying it in code? */
+unsigned short *irq_mask_register = 0;
+
+/* forward declaration */
+static unsigned int startup_maskreg_irq(unsigned int irq);
+static void shutdown_maskreg_irq(unsigned int irq);
+static void enable_maskreg_irq(unsigned int irq);
+static void disable_maskreg_irq(unsigned int irq);
+static void mask_and_ack_maskreg(unsigned int);
+static void end_maskreg_irq(unsigned int irq);
+
+/* hw_interrupt_type */
+static struct hw_interrupt_type maskreg_irq_type = {
+ " Mask Register",
+ startup_maskreg_irq,
+ shutdown_maskreg_irq,
+ enable_maskreg_irq,
+ disable_maskreg_irq,
+ mask_and_ack_maskreg,
+ end_maskreg_irq
+};
+
+/* actual implementatin */
+static unsigned int startup_maskreg_irq(unsigned int irq)
+{
+ enable_maskreg_irq(irq);
+ return 0; /* never anything pending */
+}
+
+static void shutdown_maskreg_irq(unsigned int irq)
+{
+ disable_maskreg_irq(irq);
+}
+
+static void disable_maskreg_irq(unsigned int irq)
+{
+ if (irq_mask_register) {
+ unsigned long flags;
+ unsigned short val, mask = 0x01 << irq;
+
+ /* Set "irq"th bit */
+ local_irq_save(flags);
+ val = ctrl_inw((unsigned long)irq_mask_register);
+ val |= mask;
+ ctrl_outw(val, (unsigned long)irq_mask_register);
+ local_irq_restore(flags);
+ }
+}
+
+static void enable_maskreg_irq(unsigned int irq)
+{
+ if (irq_mask_register) {
+ unsigned long flags;
+ unsigned short val, mask = ~(0x01 << irq);
+
+ /* Clear "irq"th bit */
+ local_irq_save(flags);
+ val = ctrl_inw((unsigned long)irq_mask_register);
+ val &= mask;
+ ctrl_outw(val, (unsigned long)irq_mask_register);
+ local_irq_restore(flags);
+ }
+}
+
+static void mask_and_ack_maskreg(unsigned int irq)
+{
+ disable_maskreg_irq(irq);
+}
+
+static void end_maskreg_irq(unsigned int irq)
+{
+ if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+ enable_maskreg_irq(irq);
+}
+
+void make_maskreg_irq(unsigned int irq)
+{
+ disable_irq_nosync(irq);
+ irq_desc[irq].handler = &maskreg_irq_type;
+ disable_maskreg_irq(irq);
+}
diff --git a/arch/sh/boards/adx/setup.c b/arch/sh/boards/adx/setup.c
new file mode 100644
index 000000000000..4938d9592343
--- /dev/null
+++ b/arch/sh/boards/adx/setup.c
@@ -0,0 +1,56 @@
+/*
+ * linux/arch/sh/board/adx/setup.c
+ *
+ * Copyright (C) 2001 A&D Co., Ltd.
+ *
+ * I/O routine and setup routines for A&D ADX Board
+ *
+ * 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 <asm/machvec.h>
+#include <linux/module.h>
+
+extern void init_adx_IRQ(void);
+extern void *cf_io_base;
+
+const char *get_system_type(void)
+{
+ return "A&D ADX";
+}
+
+unsigned long adx_isa_port2addr(unsigned long offset)
+{
+ /* CompactFlash (IDE) */
+ if (((offset >= 0x1f0) && (offset <= 0x1f7)) || (offset == 0x3f6)) {
+ return (unsigned long)cf_io_base + offset;
+ }
+
+ /* eth0 */
+ if ((offset >= 0x300) && (offset <= 0x30f)) {
+ return 0xa5000000 + offset; /* COMM BOARD (AREA1) */
+ }
+
+ return offset + 0xb0000000; /* IOBUS (AREA 4)*/
+}
+
+/*
+ * The Machine Vector
+ */
+
+struct sh_machine_vector mv_adx __initmv = {
+ .mv_nr_irqs = 48,
+ .mv_isa_port2addr = adx_isa_port2addr,
+ .mv_init_irq = init_adx_IRQ,
+};
+ALIAS_MV(adx)
+
+int __init platform_setup(void)
+{
+ /* Nothing to see here .. */
+ return 0;
+}
+
diff --git a/arch/sh/boards/bigsur/Makefile b/arch/sh/boards/bigsur/Makefile
new file mode 100644
index 000000000000..0ff9497ac58e
--- /dev/null
+++ b/arch/sh/boards/bigsur/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for the BigSur specific parts of the kernel
+#
+
+obj-y := setup.o io.o irq.o led.o
+
diff --git a/arch/sh/boards/bigsur/io.c b/arch/sh/boards/bigsur/io.c
new file mode 100644
index 000000000000..697144de7419
--- /dev/null
+++ b/arch/sh/boards/bigsur/io.c
@@ -0,0 +1,125 @@
+/*
+ * include/asm-sh/io_bigsur.c
+ *
+ * By Dustin McIntire (dustin@sensoria.com) (c)2001
+ * Derived from io_hd64465.h, which bore the message:
+ * By Greg Banks <gbanks@pocketpenguins.com>
+ * (c) 2000 PocketPenguins Inc.
+ * and from io_hd64461.h, which bore the message:
+ * Copyright 2000 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.
+ *
+ * IO functions for a Hitachi Big Sur Evaluation Board.
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <asm/machvec.h>
+#include <asm/io.h>
+#include <asm/bigsur/bigsur.h>
+
+/* Low iomap maps port 0-1K to addresses in 8byte chunks */
+#define BIGSUR_IOMAP_LO_THRESH 0x400
+#define BIGSUR_IOMAP_LO_SHIFT 3
+#define BIGSUR_IOMAP_LO_MASK ((1<<BIGSUR_IOMAP_LO_SHIFT)-1)
+#define BIGSUR_IOMAP_LO_NMAP (BIGSUR_IOMAP_LO_THRESH>>BIGSUR_IOMAP_LO_SHIFT)
+static u32 bigsur_iomap_lo[BIGSUR_IOMAP_LO_NMAP];
+static u8 bigsur_iomap_lo_shift[BIGSUR_IOMAP_LO_NMAP];
+
+/* High iomap maps port 1K-64K to addresses in 1K chunks */
+#define BIGSUR_IOMAP_HI_THRESH 0x10000
+#define BIGSUR_IOMAP_HI_SHIFT 10
+#define BIGSUR_IOMAP_HI_MASK ((1<<BIGSUR_IOMAP_HI_SHIFT)-1)
+#define BIGSUR_IOMAP_HI_NMAP (BIGSUR_IOMAP_HI_THRESH>>BIGSUR_IOMAP_HI_SHIFT)
+static u32 bigsur_iomap_hi[BIGSUR_IOMAP_HI_NMAP];
+static u8 bigsur_iomap_hi_shift[BIGSUR_IOMAP_HI_NMAP];
+
+#ifndef MAX
+#define MAX(a,b) ((a)>(b)?(a):(b))
+#endif
+
+void bigsur_port_map(u32 baseport, u32 nports, u32 addr, u8 shift)
+{
+ u32 port, endport = baseport + nports;
+
+ pr_debug("bigsur_port_map(base=0x%0x, n=0x%0x, addr=0x%08x)\n",
+ baseport, nports, addr);
+
+ for (port = baseport ;
+ port < endport && port < BIGSUR_IOMAP_LO_THRESH ;
+ port += (1<<BIGSUR_IOMAP_LO_SHIFT)) {
+ pr_debug(" maplo[0x%x] = 0x%08x\n", port, addr);
+ bigsur_iomap_lo[port>>BIGSUR_IOMAP_LO_SHIFT] = addr;
+ bigsur_iomap_lo_shift[port>>BIGSUR_IOMAP_LO_SHIFT] = shift;
+ addr += (1<<(BIGSUR_IOMAP_LO_SHIFT));
+ }
+
+ for (port = MAX(baseport, BIGSUR_IOMAP_LO_THRESH) ;
+ port < endport && port < BIGSUR_IOMAP_HI_THRESH ;
+ port += (1<<BIGSUR_IOMAP_HI_SHIFT)) {
+ pr_debug(" maphi[0x%x] = 0x%08x\n", port, addr);
+ bigsur_iomap_hi[port>>BIGSUR_IOMAP_HI_SHIFT] = addr;
+ bigsur_iomap_hi_shift[port>>BIGSUR_IOMAP_HI_SHIFT] = shift;
+ addr += (1<<(BIGSUR_IOMAP_HI_SHIFT));
+ }
+}
+EXPORT_SYMBOL(bigsur_port_map);
+
+void bigsur_port_unmap(u32 baseport, u32 nports)
+{
+ u32 port, endport = baseport + nports;
+
+ pr_debug("bigsur_port_unmap(base=0x%0x, n=0x%0x)\n", baseport, nports);
+
+ for (port = baseport ;
+ port < endport && port < BIGSUR_IOMAP_LO_THRESH ;
+ port += (1<<BIGSUR_IOMAP_LO_SHIFT)) {
+ bigsur_iomap_lo[port>>BIGSUR_IOMAP_LO_SHIFT] = 0;
+ }
+
+ for (port = MAX(baseport, BIGSUR_IOMAP_LO_THRESH) ;
+ port < endport && port < BIGSUR_IOMAP_HI_THRESH ;
+ port += (1<<BIGSUR_IOMAP_HI_SHIFT)) {
+ bigsur_iomap_hi[port>>BIGSUR_IOMAP_HI_SHIFT] = 0;
+ }
+}
+EXPORT_SYMBOL(bigsur_port_unmap);
+
+unsigned long bigsur_isa_port2addr(unsigned long port)
+{
+ unsigned long addr = 0;
+ unsigned char shift;
+
+ /* Physical address not in P0, do nothing */
+ if (PXSEG(port)) {
+ addr = port;
+ /* physical address in P0, map to P2 */
+ } else if (port >= 0x30000) {
+ addr = P2SEGADDR(port);
+ /* Big Sur I/O + HD64465 registers 0x10000-0x30000 */
+ } else if (port >= BIGSUR_IOMAP_HI_THRESH) {
+ addr = BIGSUR_INTERNAL_BASE + (port - BIGSUR_IOMAP_HI_THRESH);
+ /* Handle remapping of high IO/PCI IO ports */
+ } else if (port >= BIGSUR_IOMAP_LO_THRESH) {
+ addr = bigsur_iomap_hi[port >> BIGSUR_IOMAP_HI_SHIFT];
+ shift = bigsur_iomap_hi_shift[port >> BIGSUR_IOMAP_HI_SHIFT];
+
+ if (addr != 0)
+ addr += (port & BIGSUR_IOMAP_HI_MASK) << shift;
+ } else {
+ /* Handle remapping of low IO ports */
+ addr = bigsur_iomap_lo[port >> BIGSUR_IOMAP_LO_SHIFT];
+ shift = bigsur_iomap_lo_shift[port >> BIGSUR_IOMAP_LO_SHIFT];
+
+ if (addr != 0)
+ addr += (port & BIGSUR_IOMAP_LO_MASK) << shift;
+ }
+
+ pr_debug("%s(0x%08lx) = 0x%08lx\n", __FUNCTION__, port, addr);
+
+ return addr;
+}
+
diff --git a/arch/sh/boards/bigsur/irq.c b/arch/sh/boards/bigsur/irq.c
new file mode 100644
index 000000000000..c188fc32dc9a
--- /dev/null
+++ b/arch/sh/boards/bigsur/irq.c
@@ -0,0 +1,348 @@
+/*
+ *
+ * By Dustin McIntire (dustin@sensoria.com) (c)2001
+ *
+ * Setup and IRQ handling code for the HD64465 companion chip.
+ * by Greg Banks <gbanks@pocketpenguins.com>
+ * Copyright (c) 2000 PocketPenguins Inc
+ *
+ * Derived from setup_hd64465.c which bore the message:
+ * Greg Banks <gbanks@pocketpenguins.com>
+ * Copyright (c) 2000 PocketPenguins Inc and
+ * Copyright (C) 2000 YAEGASHI Takeshi
+ * and setup_cqreek.c which bore message:
+ * Copyright (C) 2000 Niibe Yutaka
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License. See linux/COPYING for more information.
+ *
+ * IRQ functions for a Hitachi Big Sur Evaluation Board.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/sched.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/param.h>
+#include <linux/ioport.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/bitops.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+
+#include <asm/bigsur/io.h>
+#include <asm/hd64465/hd64465.h>
+#include <asm/bigsur/bigsur.h>
+
+//#define BIGSUR_DEBUG 3
+#undef BIGSUR_DEBUG
+
+#ifdef BIGSUR_DEBUG
+#define DPRINTK(args...) printk(args)
+#define DIPRINTK(n, args...) if (BIGSUR_DEBUG>(n)) printk(args)
+#else
+#define DPRINTK(args...)
+#define DIPRINTK(n, args...)
+#endif /* BIGSUR_DEBUG */
+
+#ifdef CONFIG_HD64465
+extern int hd64465_irq_demux(int irq);
+#endif /* CONFIG_HD64465 */
+
+
+/*===========================================================*/
+// Big Sur CPLD IRQ Routines
+/*===========================================================*/
+
+/* Level 1 IRQ routines */
+static void disable_bigsur_l1irq(unsigned int irq)
+{
+ unsigned long flags;
+ unsigned char mask;
+ unsigned int mask_port = ((irq - BIGSUR_IRQ_LOW)/8) ? BIGSUR_IRLMR1 : BIGSUR_IRLMR0;
+ unsigned char bit = (1 << ((irq - MGATE_IRQ_LOW)%8) );
+
+ if(irq >= BIGSUR_IRQ_LOW && irq < BIGSUR_IRQ_HIGH) {
+ DPRINTK("Disable L1 IRQ %d\n", irq);
+ DIPRINTK(2,"disable_bigsur_l1irq: IMR=0x%08x mask=0x%x\n",
+ mask_port, bit);
+ local_irq_save(flags);
+
+ /* Disable IRQ - set mask bit */
+ mask = inb(mask_port) | bit;
+ outb(mask, mask_port);
+ local_irq_restore(flags);
+ return;
+ }
+ DPRINTK("disable_bigsur_l1irq: Invalid IRQ %d\n", irq);
+}
+
+static void enable_bigsur_l1irq(unsigned int irq)
+{
+ unsigned long flags;
+ unsigned char mask;
+ unsigned int mask_port = ((irq - BIGSUR_IRQ_LOW)/8) ? BIGSUR_IRLMR1 : BIGSUR_IRLMR0;
+ unsigned char bit = (1 << ((irq - MGATE_IRQ_LOW)%8) );
+
+ if(irq >= BIGSUR_IRQ_LOW && irq < BIGSUR_IRQ_HIGH) {
+ DPRINTK("Enable L1 IRQ %d\n", irq);
+ DIPRINTK(2,"enable_bigsur_l1irq: IMR=0x%08x mask=0x%x\n",
+ mask_port, bit);
+ local_irq_save(flags);
+ /* Enable L1 IRQ - clear mask bit */
+ mask = inb(mask_port) & ~bit;
+ outb(mask, mask_port);
+ local_irq_restore(flags);
+ return;
+ }
+ DPRINTK("enable_bigsur_l1irq: Invalid IRQ %d\n", irq);
+}
+
+
+/* Level 2 irq masks and registers for L2 decoding */
+/* Level2 bitmasks for each level 1 IRQ */
+const u32 bigsur_l2irq_mask[] =
+ {0x40,0x80,0x08,0x01,0x01,0x3C,0x3E,0xFF,0x40,0x80,0x06,0x03};
+/* Level2 to ISR[n] map for each level 1 IRQ */
+const u32 bigsur_l2irq_reg[] =
+ { 2, 2, 3, 3, 1, 2, 1, 0, 1, 1, 3, 2};
+/* Level2 to Level 1 IRQ map */
+const u32 bigsur_l2_l1_map[] =
+ {7,7,7,7,7,7,7,7, 4,6,6,6,6,6,8,9, 11,11,5,5,5,5,0,1, 3,10,10,2,-1,-1,-1,-1};
+/* IRQ inactive level (high or low) */
+const u32 bigsur_l2_inactv_state[] = {0x00, 0xBE, 0xFC, 0xF7};
+
+/* CPLD external status and mask registers base and offsets */
+static const u32 isr_base = BIGSUR_IRQ0;
+static const u32 isr_offset = BIGSUR_IRQ0 - BIGSUR_IRQ1;
+static const u32 imr_base = BIGSUR_IMR0;
+static const u32 imr_offset = BIGSUR_IMR0 - BIGSUR_IMR1;
+
+#define REG_NUM(irq) ((irq-BIGSUR_2NDLVL_IRQ_LOW)/8 )
+
+/* Level 2 IRQ routines */
+static void disable_bigsur_l2irq(unsigned int irq)
+{
+ unsigned long flags;
+ unsigned char mask;
+ unsigned char bit = 1 << ((irq-BIGSUR_2NDLVL_IRQ_LOW)%8);
+ unsigned int mask_port = imr_base - REG_NUM(irq)*imr_offset;
+
+ if(irq >= BIGSUR_2NDLVL_IRQ_LOW && irq < BIGSUR_2NDLVL_IRQ_HIGH) {
+ DPRINTK("Disable L2 IRQ %d\n", irq);
+ DIPRINTK(2,"disable_bigsur_l2irq: IMR=0x%08x mask=0x%x\n",
+ mask_port, bit);
+ local_irq_save(flags);
+
+ /* Disable L2 IRQ - set mask bit */
+ mask = inb(mask_port) | bit;
+ outb(mask, mask_port);
+ local_irq_restore(flags);
+ return;
+ }
+ DPRINTK("disable_bigsur_l2irq: Invalid IRQ %d\n", irq);
+}
+
+static void enable_bigsur_l2irq(unsigned int irq)
+{
+ unsigned long flags;
+ unsigned char mask;
+ unsigned char bit = 1 << ((irq-BIGSUR_2NDLVL_IRQ_LOW)%8);
+ unsigned int mask_port = imr_base - REG_NUM(irq)*imr_offset;
+
+ if(irq >= BIGSUR_2NDLVL_IRQ_LOW && irq < BIGSUR_2NDLVL_IRQ_HIGH) {
+ DPRINTK("Enable L2 IRQ %d\n", irq);
+ DIPRINTK(2,"enable_bigsur_l2irq: IMR=0x%08x mask=0x%x\n",
+ mask_port, bit);
+ local_irq_save(flags);
+
+ /* Enable L2 IRQ - clear mask bit */
+ mask = inb(mask_port) & ~bit;
+ outb(mask, mask_port);
+ local_irq_restore(flags);
+ return;
+ }
+ DPRINTK("enable_bigsur_l2irq: Invalid IRQ %d\n", irq);
+}
+
+static void mask_and_ack_bigsur(unsigned int irq)
+{
+ DPRINTK("mask_and_ack_bigsur IRQ %d\n", irq);
+ if(irq >= BIGSUR_IRQ_LOW && irq < BIGSUR_IRQ_HIGH)
+ disable_bigsur_l1irq(irq);
+ else
+ disable_bigsur_l2irq(irq);
+}
+
+static void end_bigsur_irq(unsigned int irq)
+{
+ DPRINTK("end_bigsur_irq IRQ %d\n", irq);
+ if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) {
+ if(irq >= BIGSUR_IRQ_LOW && irq < BIGSUR_IRQ_HIGH)
+ enable_bigsur_l1irq(irq);
+ else
+ enable_bigsur_l2irq(irq);
+ }
+}
+
+static unsigned int startup_bigsur_irq(unsigned int irq)
+{
+ u8 mask;
+ u32 reg;
+
+ DPRINTK("startup_bigsur_irq IRQ %d\n", irq);
+
+ if(irq >= BIGSUR_IRQ_LOW && irq < BIGSUR_IRQ_HIGH) {
+ /* Enable the L1 IRQ */
+ enable_bigsur_l1irq(irq);
+ /* Enable all L2 IRQs in this L1 IRQ */
+ mask = ~(bigsur_l2irq_mask[irq-BIGSUR_IRQ_LOW]);
+ reg = imr_base - bigsur_l2irq_reg[irq-BIGSUR_IRQ_LOW] * imr_offset;
+ mask &= inb(reg);
+ outb(mask,reg);
+ DIPRINTK(2,"startup_bigsur_irq: IMR=0x%08x mask=0x%x\n",reg,inb(reg));
+ }
+ else {
+ /* Enable the L2 IRQ - clear mask bit */
+ enable_bigsur_l2irq(irq);
+ /* Enable the L1 bit masking this L2 IRQ */
+ enable_bigsur_l1irq(bigsur_l2_l1_map[irq-BIGSUR_2NDLVL_IRQ_LOW]);
+ DIPRINTK(2,"startup_bigsur_irq: L1=%d L2=%d\n",
+ bigsur_l2_l1_map[irq-BIGSUR_2NDLVL_IRQ_LOW],irq);
+ }
+ return 0;
+}
+
+static void shutdown_bigsur_irq(unsigned int irq)
+{
+ DPRINTK("shutdown_bigsur_irq IRQ %d\n", irq);
+ if(irq >= BIGSUR_IRQ_LOW && irq < BIGSUR_IRQ_HIGH)
+ disable_bigsur_l1irq(irq);
+ else
+ disable_bigsur_l2irq(irq);
+}
+
+/* Define the IRQ structures for the L1 and L2 IRQ types */
+static struct hw_interrupt_type bigsur_l1irq_type = {
+ "BigSur-CPLD-Level1-IRQ",
+ startup_bigsur_irq,
+ shutdown_bigsur_irq,
+ enable_bigsur_l1irq,
+ disable_bigsur_l1irq,
+ mask_and_ack_bigsur,
+ end_bigsur_irq
+};
+
+static struct hw_interrupt_type bigsur_l2irq_type = {
+ "BigSur-CPLD-Level2-IRQ",
+ startup_bigsur_irq,
+ shutdown_bigsur_irq,
+ enable_bigsur_l2irq,
+ disable_bigsur_l2irq,
+ mask_and_ack_bigsur,
+ end_bigsur_irq
+};
+
+
+static void make_bigsur_l1isr(unsigned int irq) {
+
+ /* sanity check first */
+ if(irq >= BIGSUR_IRQ_LOW && irq < BIGSUR_IRQ_HIGH) {
+ /* save the handler in the main description table */
+ irq_desc[irq].handler = &bigsur_l1irq_type;
+ irq_desc[irq].status = IRQ_DISABLED;
+ irq_desc[irq].action = 0;
+ irq_desc[irq].depth = 1;
+
+ disable_bigsur_l1irq(irq);
+ return;
+ }
+ DPRINTK("make_bigsur_l1isr: bad irq, %d\n", irq);
+ return;
+}
+
+static void make_bigsur_l2isr(unsigned int irq) {
+
+ /* sanity check first */
+ if(irq >= BIGSUR_2NDLVL_IRQ_LOW && irq < BIGSUR_2NDLVL_IRQ_HIGH) {
+ /* save the handler in the main description table */
+ irq_desc[irq].handler = &bigsur_l2irq_type;
+ irq_desc[irq].status = IRQ_DISABLED;
+ irq_desc[irq].action = 0;
+ irq_desc[irq].depth = 1;
+
+ disable_bigsur_l2irq(irq);
+ return;
+ }
+ DPRINTK("make_bigsur_l2isr: bad irq, %d\n", irq);
+ return;
+}
+
+/* The IRQ's will be decoded as follows:
+ * If a level 2 handler exists and there is an unmasked active
+ * IRQ, the 2nd level handler will be called.
+ * If a level 2 handler does not exist for the active IRQ
+ * the 1st level handler will be called.
+ */
+
+int bigsur_irq_demux(int irq)
+{
+ int dmux_irq = irq;
+ u8 mask, actv_irqs;
+ u32 reg_num;
+
+ DIPRINTK(3,"bigsur_irq_demux, irq=%d\n", irq);
+ /* decode the 1st level IRQ */
+ if(irq >= BIGSUR_IRQ_LOW && irq < BIGSUR_IRQ_HIGH) {
+ /* Get corresponding L2 ISR bitmask and ISR number */
+ mask = bigsur_l2irq_mask[irq-BIGSUR_IRQ_LOW];
+ reg_num = bigsur_l2irq_reg[irq-BIGSUR_IRQ_LOW];
+ /* find the active IRQ's (XOR with inactive level)*/
+ actv_irqs = inb(isr_base-reg_num*isr_offset) ^
+ bigsur_l2_inactv_state[reg_num];
+ /* decode active IRQ's */
+ actv_irqs = actv_irqs & mask & ~(inb(imr_base-reg_num*imr_offset));
+ /* if NEZ then we have an active L2 IRQ */
+ if(actv_irqs) dmux_irq = ffz(~actv_irqs) + reg_num*8+BIGSUR_2NDLVL_IRQ_LOW;
+ /* if no 2nd level IRQ action, but has 1st level, use 1st level handler */
+ if(!irq_desc[dmux_irq].action && irq_desc[irq].action)
+ dmux_irq = irq;
+ DIPRINTK(1,"bigsur_irq_demux: irq=%d dmux_irq=%d mask=0x%04x reg=%d\n",
+ irq, dmux_irq, mask, reg_num);
+ }
+#ifdef CONFIG_HD64465
+ dmux_irq = hd64465_irq_demux(dmux_irq);
+#endif /* CONFIG_HD64465 */
+ DIPRINTK(3,"bigsur_irq_demux, demux_irq=%d\n", dmux_irq);
+
+ return dmux_irq;
+}
+
+/*===========================================================*/
+// Big Sur Init Routines
+/*===========================================================*/
+void __init init_bigsur_IRQ(void)
+{
+ int i;
+
+ if (!MACH_BIGSUR) return;
+
+ /* Create ISR's for Big Sur CPLD IRQ's */
+ /*==============================================================*/
+ for(i=BIGSUR_IRQ_LOW;i<BIGSUR_IRQ_HIGH;i++)
+ make_bigsur_l1isr(i);
+
+ printk(KERN_INFO "Big Sur CPLD L1 interrupts %d to %d.\n",
+ BIGSUR_IRQ_LOW,BIGSUR_IRQ_HIGH);
+
+ for(i=BIGSUR_2NDLVL_IRQ_LOW;i<BIGSUR_2NDLVL_IRQ_HIGH;i++)
+ make_bigsur_l2isr(i);
+
+ printk(KERN_INFO "Big Sur CPLD L2 interrupts %d to %d.\n",
+ BIGSUR_2NDLVL_IRQ_LOW,BIGSUR_2NDLVL_IRQ_HIGH);
+
+}
diff --git a/arch/sh/boards/bigsur/led.c b/arch/sh/boards/bigsur/led.c
new file mode 100644
index 000000000000..0a2339c69440
--- /dev/null
+++ b/arch/sh/boards/bigsur/led.c
@@ -0,0 +1,55 @@
+/*
+ * linux/arch/sh/kernel/led_bigsur.c
+ *
+ * By Dustin McIntire (dustin@sensoria.com) (c)2001
+ * Derived from led_se.c and led.c, which bore the message:
+ * Copyright (C) 2000 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.
+ *
+ * This file contains Big Sur specific LED code.
+ */
+
+#include <linux/config.h>
+#include <asm/io.h>
+#include <asm/bigsur/bigsur.h>
+
+static void mach_led(int position, int value)
+{
+ int word;
+
+ word = bigsur_inl(BIGSUR_CSLR);
+ if (value) {
+ bigsur_outl(word & ~BIGSUR_LED, BIGSUR_CSLR);
+ } else {
+ bigsur_outl(word | BIGSUR_LED, BIGSUR_CSLR);
+ }
+}
+
+#ifdef CONFIG_HEARTBEAT
+
+#include <linux/sched.h>
+
+/* Cycle the LED on/off */
+void heartbeat_bigsur(void)
+{
+ static unsigned 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;
+ }
+}
+#endif /* CONFIG_HEARTBEAT */
+
diff --git a/arch/sh/boards/bigsur/setup.c b/arch/sh/boards/bigsur/setup.c
new file mode 100644
index 000000000000..e69be05195f5
--- /dev/null
+++ b/arch/sh/boards/bigsur/setup.c
@@ -0,0 +1,96 @@
+/*
+ *
+ * By Dustin McIntire (dustin@sensoria.com) (c)2001
+ *
+ * Setup and IRQ handling code for the HD64465 companion chip.
+ * by Greg Banks <gbanks@pocketpenguins.com>
+ * Copyright (c) 2000 PocketPenguins Inc
+ *
+ * Derived from setup_hd64465.c which bore the message:
+ * Greg Banks <gbanks@pocketpenguins.com>
+ * Copyright (c) 2000 PocketPenguins Inc and
+ * Copyright (C) 2000 YAEGASHI Takeshi
+ * and setup_cqreek.c which bore message:
+ * Copyright (C) 2000 Niibe Yutaka
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License. See linux/COPYING for more information.
+ *
+ * Setup functions for a Hitachi Big Sur Evaluation Board.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/sched.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/param.h>
+#include <linux/ioport.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/bitops.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/machvec.h>
+#include <asm/bigsur/io.h>
+#include <asm/hd64465/hd64465.h>
+#include <asm/bigsur/bigsur.h>
+
+/*===========================================================*/
+// Big Sur Init Routines
+/*===========================================================*/
+
+const char *get_system_type(void)
+{
+ return "Big Sur";
+}
+
+/*
+ * The Machine Vector
+ */
+extern void heartbeat_bigsur(void);
+extern void init_bigsur_IRQ(void);
+
+struct sh_machine_vector mv_bigsur __initmv = {
+ .mv_nr_irqs = NR_IRQS, // Defined in <asm/irq.h>
+
+ .mv_isa_port2addr = bigsur_isa_port2addr,
+ .mv_irq_demux = bigsur_irq_demux,
+
+ .mv_init_irq = init_bigsur_IRQ,
+#ifdef CONFIG_HEARTBEAT
+ .mv_heartbeat = heartbeat_bigsur,
+#endif
+};
+ALIAS_MV(bigsur)
+
+int __init platform_setup(void)
+{
+ /* Mask all 2nd level IRQ's */
+ outb(-1,BIGSUR_IMR0);
+ outb(-1,BIGSUR_IMR1);
+ outb(-1,BIGSUR_IMR2);
+ outb(-1,BIGSUR_IMR3);
+
+ /* Mask 1st level interrupts */
+ outb(-1,BIGSUR_IRLMR0);
+ outb(-1,BIGSUR_IRLMR1);
+
+#if defined (CONFIG_HD64465) && defined (CONFIG_SERIAL)
+ /* remap IO ports for first ISA serial port to HD64465 UART */
+ bigsur_port_map(0x3f8, 8, CONFIG_HD64465_IOBASE + 0x8000, 1);
+#endif /* CONFIG_HD64465 && CONFIG_SERIAL */
+ /* TODO: setup IDE registers */
+ bigsur_port_map(BIGSUR_IDECTL_IOPORT, 2, BIGSUR_ICTL, 8);
+ /* Setup the Ethernet port to BIGSUR_ETHER_IOPORT */
+ bigsur_port_map(BIGSUR_ETHER_IOPORT, 16, BIGSUR_ETHR+BIGSUR_ETHER_IOPORT, 0);
+ /* set page to 1 */
+ outw(1, BIGSUR_ETHR+0xe);
+ /* set the IO port to BIGSUR_ETHER_IOPORT */
+ outw(BIGSUR_ETHER_IOPORT<<3, BIGSUR_ETHR+0x2);
+
+ return 0;
+}
+
diff --git a/arch/sh/boards/cat68701/Makefile b/arch/sh/boards/cat68701/Makefile
new file mode 100644
index 000000000000..52c1de0a6dfd
--- /dev/null
+++ b/arch/sh/boards/cat68701/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for the CAT-68701 specific parts of the kernel
+#
+
+obj-y := setup.o irq.o
+
diff --git a/arch/sh/boards/cat68701/irq.c b/arch/sh/boards/cat68701/irq.c
new file mode 100644
index 000000000000..f9a6d185fb8b
--- /dev/null
+++ b/arch/sh/boards/cat68701/irq.c
@@ -0,0 +1,28 @@
+/*
+ * linux/arch/sh/boards/cat68701/irq.c
+ *
+ * Copyright (C) 2000 Niibe Yutaka
+ * 2001 Yutaro Ebihara
+ *
+ * Setup routines for A-ONE Corp CAT-68701 SH7708 Board
+ *
+ * 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 <asm/irq.h>
+
+int cat68701_irq_demux(int irq)
+{
+ if(irq==13) return 14;
+ if(irq==7) return 10;
+ return irq;
+}
+
+void init_cat68701_IRQ()
+{
+ make_imask_irq(10);
+ make_imask_irq(14);
+}
diff --git a/arch/sh/boards/cat68701/setup.c b/arch/sh/boards/cat68701/setup.c
new file mode 100644
index 000000000000..ae8a350ade53
--- /dev/null
+++ b/arch/sh/boards/cat68701/setup.c
@@ -0,0 +1,86 @@
+/*
+ * linux/arch/sh/boards/cat68701/setup.c
+ *
+ * Copyright (C) 2000 Niibe Yutaka
+ * 2001 Yutaro Ebihara
+ *
+ * Setup routines for A-ONE Corp CAT-68701 SH7708 Board
+ *
+ * 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 <asm/io.h>
+#include <asm/machvec.h>
+#include <asm/mach/io.h>
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+
+const char *get_system_type(void)
+{
+ return "CAT-68701";
+}
+
+#ifdef CONFIG_HEARTBEAT
+void heartbeat_cat68701()
+{
+ static unsigned int cnt = 0, period = 0 , bit = 0;
+ cnt += 1;
+ if (cnt < period) {
+ return;
+ }
+ cnt = 0;
+
+ /* Go through the points (roughly!):
+ * f(0)=10, f(1)=16, f(2)=20, f(5)=35,f(inf)->110
+ */
+ period = 110 - ( (300<<FSHIFT)/
+ ((avenrun[0]/5) + (3<<FSHIFT)) );
+
+ if(bit){ bit=0; }else{ bit=1; }
+ outw(bit<<15,0x3fe);
+}
+#endif /* CONFIG_HEARTBEAT */
+
+unsigned long cat68701_isa_port2addr(unsigned long offset)
+{
+ /* CompactFlash (IDE) */
+ if (((offset >= 0x1f0) && (offset <= 0x1f7)) || (offset==0x3f6))
+ return 0xba000000 + offset;
+
+ /* INPUT PORT */
+ if ((offset >= 0x3fc) && (offset <= 0x3fd))
+ return 0xb4007000 + offset;
+
+ /* OUTPUT PORT */
+ if ((offset >= 0x3fe) && (offset <= 0x3ff))
+ return 0xb4007400 + offset;
+
+ return offset + 0xb4000000; /* other I/O (EREA 5)*/
+}
+
+/*
+ * The Machine Vector
+ */
+
+struct sh_machine_vector mv_cat68701 __initmv = {
+ .mv_nr_irqs = 32,
+ .mv_isa_port2addr = cat68701_isa_port2addr,
+ .mv_irq_demux = cat68701_irq_demux,
+
+ .mv_init_irq = init_cat68701_IRQ,
+#ifdef CONFIG_HEARTBEAT
+ .mv_heartbeat = heartbeat_cat68701,
+#endif
+};
+ALIAS_MV(cat68701)
+
+int __init platform_setup(void)
+{
+ /* dummy read erea5 (CS8900A) */
+}
+
diff --git a/arch/sh/boards/cqreek/Makefile b/arch/sh/boards/cqreek/Makefile
new file mode 100644
index 000000000000..1a788a85eba3
--- /dev/null
+++ b/arch/sh/boards/cqreek/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for the CqREEK specific parts of the kernel
+#
+
+obj-y := setup.o irq.o
+
diff --git a/arch/sh/boards/cqreek/irq.c b/arch/sh/boards/cqreek/irq.c
new file mode 100644
index 000000000000..fa6cfe5a20a7
--- /dev/null
+++ b/arch/sh/boards/cqreek/irq.c
@@ -0,0 +1,128 @@
+/* $Id: irq.c,v 1.1.2.4 2002/11/04 20:33:56 lethal Exp $
+ *
+ * arch/sh/boards/cqreek/irq.c
+ *
+ * Copyright (C) 2000 Niibe Yutaka
+ *
+ * CqREEK IDE/ISA Bridge Support.
+ *
+ */
+
+#include <linux/irq.h>
+#include <linux/init.h>
+
+#include <asm/cqreek/cqreek.h>
+#include <asm/io.h>
+#include <asm/io_generic.h>
+#include <asm/irq.h>
+#include <asm/machvec.h>
+#include <asm/machvec_init.h>
+#include <asm/rtc.h>
+
+struct cqreek_irq_data {
+ unsigned short mask_port; /* Port of Interrupt Mask Register */
+ unsigned short stat_port; /* Port of Interrupt Status Register */
+ unsigned short bit; /* Value of the bit */
+};
+static struct cqreek_irq_data cqreek_irq_data[NR_IRQS];
+
+static void disable_cqreek_irq(unsigned int irq)
+{
+ unsigned long flags;
+ unsigned short mask;
+ unsigned short mask_port = cqreek_irq_data[irq].mask_port;
+ unsigned short bit = cqreek_irq_data[irq].bit;
+
+ local_irq_save(flags);
+ /* Disable IRQ */
+ mask = inw(mask_port) & ~bit;
+ outw_p(mask, mask_port);
+ local_irq_restore(flags);
+}
+
+static void enable_cqreek_irq(unsigned int irq)
+{
+ unsigned long flags;
+ unsigned short mask;
+ unsigned short mask_port = cqreek_irq_data[irq].mask_port;
+ unsigned short bit = cqreek_irq_data[irq].bit;
+
+ local_irq_save(flags);
+ /* Enable IRQ */
+ mask = inw(mask_port) | bit;
+ outw_p(mask, mask_port);
+ local_irq_restore(flags);
+}
+
+static void mask_and_ack_cqreek(unsigned int irq)
+{
+ unsigned short stat_port = cqreek_irq_data[irq].stat_port;
+ unsigned short bit = cqreek_irq_data[irq].bit;
+
+ disable_cqreek_irq(irq);
+ /* Clear IRQ (it might be edge IRQ) */
+ inw(stat_port);
+ outw_p(bit, stat_port);
+}
+
+static void end_cqreek_irq(unsigned int irq)
+{
+ if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+ enable_cqreek_irq(irq);
+}
+
+static unsigned int startup_cqreek_irq(unsigned int irq)
+{
+ enable_cqreek_irq(irq);
+ return 0;
+}
+
+static void shutdown_cqreek_irq(unsigned int irq)
+{
+ disable_cqreek_irq(irq);
+}
+
+static struct hw_interrupt_type cqreek_irq_type = {
+ "CqREEK-IRQ",
+ startup_cqreek_irq,
+ shutdown_cqreek_irq,
+ enable_cqreek_irq,
+ disable_cqreek_irq,
+ mask_and_ack_cqreek,
+ end_cqreek_irq
+};
+
+int cqreek_has_ide, cqreek_has_isa;
+
+/* XXX: This is just for test for my NE2000 ISA board
+ What we really need is virtualized IRQ and demultiplexer like HP600 port */
+void __init init_cqreek_IRQ(void)
+{
+ if (cqreek_has_ide) {
+ cqreek_irq_data[14].mask_port = BRIDGE_IDE_INTR_MASK;
+ cqreek_irq_data[14].stat_port = BRIDGE_IDE_INTR_STAT;
+ cqreek_irq_data[14].bit = 1;
+
+ irq_desc[14].handler = &cqreek_irq_type;
+ irq_desc[14].status = IRQ_DISABLED;
+ irq_desc[14].action = 0;
+ irq_desc[14].depth = 1;
+
+ disable_cqreek_irq(14);
+ }
+
+ if (cqreek_has_isa) {
+ cqreek_irq_data[10].mask_port = BRIDGE_ISA_INTR_MASK;
+ cqreek_irq_data[10].stat_port = BRIDGE_ISA_INTR_STAT;
+ cqreek_irq_data[10].bit = (1 << 10);
+
+ /* XXX: Err... we may need demultiplexer for ISA irq... */
+ irq_desc[10].handler = &cqreek_irq_type;
+ irq_desc[10].status = IRQ_DISABLED;
+ irq_desc[10].action = 0;
+ irq_desc[10].depth = 1;
+
+ disable_cqreek_irq(10);
+ }
+}
+
diff --git a/arch/sh/boards/cqreek/setup.c b/arch/sh/boards/cqreek/setup.c
new file mode 100644
index 000000000000..29b537cd6546
--- /dev/null
+++ b/arch/sh/boards/cqreek/setup.c
@@ -0,0 +1,101 @@
+/* $Id: setup.c,v 1.5 2003/08/04 01:51:58 lethal Exp $
+ *
+ * arch/sh/kernel/setup_cqreek.c
+ *
+ * Copyright (C) 2000 Niibe Yutaka
+ *
+ * CqREEK IDE/ISA Bridge Support.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+
+#include <asm/mach/cqreek.h>
+#include <asm/machvec.h>
+#include <asm/io.h>
+#include <asm/io_generic.h>
+#include <asm/irq.h>
+#include <asm/rtc.h>
+
+#define IDE_OFFSET 0xA4000000UL
+#define ISA_OFFSET 0xA4A00000UL
+
+const char *get_system_type(void)
+{
+ return "CqREEK";
+}
+
+static unsigned long cqreek_port2addr(unsigned long port)
+{
+ if (0x0000<=port && port<=0x0040)
+ return IDE_OFFSET + port;
+ if ((0x01f0<=port && port<=0x01f7) || port == 0x03f6)
+ return IDE_OFFSET + port;
+
+ return ISA_OFFSET + port;
+}
+
+/*
+ * The Machine Vector
+ */
+struct sh_machine_vector mv_cqreek __initmv = {
+#if defined(CONFIG_CPU_SH4)
+ .mv_nr_irqs = 48,
+#elif defined(CONFIG_CPU_SUBTYPE_SH7708)
+ .mv_nr_irqs = 32,
+#elif defined(CONFIG_CPU_SUBTYPE_SH7709)
+ .mv_nr_irqs = 61,
+#endif
+
+ .mv_init_irq = init_cqreek_IRQ,
+
+ .mv_isa_port2addr = cqreek_port2addr,
+};
+ALIAS_MV(cqreek)
+
+/*
+ * Initialize the board
+ */
+void __init platform_setup(void)
+{
+ int i;
+/* udelay is not available at setup time yet... */
+#define DELAY() do {for (i=0; i<10000; i++) ctrl_inw(0xa0000000);} while(0)
+
+ if ((inw (BRIDGE_FEATURE) & 1)) { /* We have IDE interface */
+ outw_p(0, BRIDGE_IDE_INTR_LVL);
+ outw_p(0, BRIDGE_IDE_INTR_MASK);
+
+ outw_p(0, BRIDGE_IDE_CTRL);
+ DELAY();
+
+ outw_p(0x8000, BRIDGE_IDE_CTRL);
+ DELAY();
+
+ outw_p(0xffff, BRIDGE_IDE_INTR_STAT); /* Clear interrupt status */
+ outw_p(0x0f-14, BRIDGE_IDE_INTR_LVL); /* Use 14 IPR */
+ outw_p(1, BRIDGE_IDE_INTR_MASK); /* Enable interrupt */
+ cqreek_has_ide=1;
+ }
+
+ if ((inw (BRIDGE_FEATURE) & 2)) { /* We have ISA interface */
+ outw_p(0, BRIDGE_ISA_INTR_LVL);
+ outw_p(0, BRIDGE_ISA_INTR_MASK);
+
+ outw_p(0, BRIDGE_ISA_CTRL);
+ DELAY();
+ outw_p(0x8000, BRIDGE_ISA_CTRL);
+ DELAY();
+
+ outw_p(0xffff, BRIDGE_ISA_INTR_STAT); /* Clear interrupt status */
+ outw_p(0x0f-10, BRIDGE_ISA_INTR_LVL); /* Use 10 IPR */
+ outw_p(0xfff8, BRIDGE_ISA_INTR_MASK); /* Enable interrupt */
+ cqreek_has_isa=1;
+ }
+
+ printk(KERN_INFO "CqREEK Setup (IDE=%d, ISA=%d)...done\n", cqreek_has_ide, cqreek_has_isa);
+}
+
diff --git a/arch/sh/boards/dmida/Makefile b/arch/sh/boards/dmida/Makefile
new file mode 100644
index 000000000000..75999aa0a2d9
--- /dev/null
+++ b/arch/sh/boards/dmida/Makefile
@@ -0,0 +1,7 @@
+#
+# Makefile for the DataMyte Industrial Digital Assistant(tm) specific parts
+# of the kernel
+#
+
+obj-y := mach.o
+
diff --git a/arch/sh/boards/dmida/mach.c b/arch/sh/boards/dmida/mach.c
new file mode 100644
index 000000000000..d03a25f989c2
--- /dev/null
+++ b/arch/sh/boards/dmida/mach.c
@@ -0,0 +1,59 @@
+/*
+ * linux/arch/sh/boards/dmida/mach.c
+ *
+ * by Greg Banks <gbanks@pocketpenguins.com>
+ * (c) 2000 PocketPenguins Inc
+ *
+ * Derived from mach_hp600.c, which bore the message:
+ * Copyright (C) 2000 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 vector for the DataMyte Industrial Digital Assistant(tm).
+ * See http://www.dmida.com
+ *
+ */
+
+#include <linux/init.h>
+
+#include <asm/machvec.h>
+#include <asm/rtc.h>
+#include <asm/machvec_init.h>
+
+#include <asm/io.h>
+#include <asm/hd64465/hd64465.h>
+#include <asm/irq.h>
+
+/*
+ * The Machine Vector
+ */
+
+struct sh_machine_vector mv_dmida __initmv = {
+ .mv_nr_irqs = HD64465_IRQ_BASE+HD64465_IRQ_NUM,
+
+ .mv_inb = hd64465_inb,
+ .mv_inw = hd64465_inw,
+ .mv_inl = hd64465_inl,
+ .mv_outb = hd64465_outb,
+ .mv_outw = hd64465_outw,
+ .mv_outl = hd64465_outl,
+
+ .mv_inb_p = hd64465_inb_p,
+ .mv_inw_p = hd64465_inw,
+ .mv_inl_p = hd64465_inl,
+ .mv_outb_p = hd64465_outb_p,
+ .mv_outw_p = hd64465_outw,
+ .mv_outl_p = hd64465_outl,
+
+ .mv_insb = hd64465_insb,
+ .mv_insw = hd64465_insw,
+ .mv_insl = hd64465_insl,
+ .mv_outsb = hd64465_outsb,
+ .mv_outsw = hd64465_outsw,
+ .mv_outsl = hd64465_outsl,
+
+ .mv_irq_demux = hd64465_irq_demux,
+};
+ALIAS_MV(dmida)
+
diff --git a/arch/sh/boards/dreamcast/Makefile b/arch/sh/boards/dreamcast/Makefile
new file mode 100644
index 000000000000..7b97546c7e5f
--- /dev/null
+++ b/arch/sh/boards/dreamcast/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for the Sega Dreamcast specific parts of the kernel
+#
+
+obj-y := setup.o irq.o rtc.o
+
diff --git a/arch/sh/boards/dreamcast/irq.c b/arch/sh/boards/dreamcast/irq.c
new file mode 100644
index 000000000000..b10a6b11c034
--- /dev/null
+++ b/arch/sh/boards/dreamcast/irq.c
@@ -0,0 +1,160 @@
+/*
+ * arch/sh/boards/dreamcast/irq.c
+ *
+ * Holly IRQ support for the Sega Dreamcast.
+ *
+ * Copyright (c) 2001, 2002 M. R. Brown <mrbrown@0xd6.org>
+ *
+ * This file is part of the LinuxDC project (www.linuxdc.org)
+ * Released under the terms of the GNU GPL v2.0
+ */
+
+#include <linux/irq.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/dreamcast/sysasic.h>
+
+/* Dreamcast System ASIC Hardware Events -
+
+ The Dreamcast's System ASIC (a.k.a. Holly) is responsible for receiving
+ hardware events from system peripherals and triggering an SH7750 IRQ.
+ Hardware events can trigger IRQs 13, 11, or 9 depending on which bits are
+ set in the Event Mask Registers (EMRs). When a hardware event is
+ triggered, it's corresponding bit in the Event Status Registers (ESRs)
+ is set, and that bit should be rewritten to the ESR to acknowledge that
+ event.
+
+ There are three 32-bit ESRs located at 0xa05f8900 - 0xa05f6908. Event
+ types can be found in include/asm-sh/dc_sysasic.h. There are three groups
+ of EMRs that parallel the ESRs. Each EMR group corresponds to an IRQ, so
+ 0xa05f6910 - 0xa05f6918 triggers IRQ 13, 0xa05f6920 - 0xa05f6928 triggers
+ IRQ 11, and 0xa05f6930 - 0xa05f6938 triggers IRQ 9.
+
+ In the kernel, these events are mapped to virtual IRQs so that drivers can
+ respond to them as they would a normal interrupt. In order to keep this
+ mapping simple, the events are mapped as:
+
+ 6900/6910 - Events 0-31, IRQ 13
+ 6904/6924 - Events 32-63, IRQ 11
+ 6908/6938 - Events 64-95, IRQ 9
+
+*/
+
+#define ESR_BASE 0x005f6900 /* Base event status register */
+#define EMR_BASE 0x005f6910 /* Base event mask register */
+
+/* Helps us determine the EMR group that this event belongs to: 0 = 0x6910,
+ 1 = 0x6920, 2 = 0x6930; also determine the event offset */
+#define LEVEL(event) (((event) - HW_EVENT_IRQ_BASE) / 32)
+
+/* Return the hardware event's bit positon within the EMR/ESR */
+#define EVENT_BIT(event) (((event) - HW_EVENT_IRQ_BASE) & 31)
+
+/* For each of these *_irq routines, the IRQ passed in is the virtual IRQ
+ (logically mapped to the corresponding bit for the hardware event). */
+
+/* Disable the hardware event by masking its bit in its EMR */
+static inline void disable_systemasic_irq(unsigned int irq)
+{
+ unsigned long flags;
+ __u32 emr = EMR_BASE + (LEVEL(irq) << 4) + (LEVEL(irq) << 2);
+ __u32 mask;
+
+ local_irq_save(flags);
+ mask = inl(emr);
+ mask &= ~(1 << EVENT_BIT(irq));
+ outl(mask, emr);
+ local_irq_restore(flags);
+}
+
+/* Enable the hardware event by setting its bit in its EMR */
+static inline void enable_systemasic_irq(unsigned int irq)
+{
+ unsigned long flags;
+ __u32 emr = EMR_BASE + (LEVEL(irq) << 4) + (LEVEL(irq) << 2);
+ __u32 mask;
+
+ local_irq_save(flags);
+ mask = inl(emr);
+ mask |= (1 << EVENT_BIT(irq));
+ outl(mask, emr);
+ local_irq_restore(flags);
+}
+
+/* Acknowledge a hardware event by writing its bit back to its ESR */
+static void ack_systemasic_irq(unsigned int irq)
+{
+ __u32 esr = ESR_BASE + (LEVEL(irq) << 2);
+ disable_systemasic_irq(irq);
+ outl((1 << EVENT_BIT(irq)), esr);
+}
+
+/* After a IRQ has been ack'd and responded to, it needs to be renabled */
+static void end_systemasic_irq(unsigned int irq)
+{
+ if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+ enable_systemasic_irq(irq);
+}
+
+static unsigned int startup_systemasic_irq(unsigned int irq)
+{
+ enable_systemasic_irq(irq);
+
+ return 0;
+}
+
+static void shutdown_systemasic_irq(unsigned int irq)
+{
+ disable_systemasic_irq(irq);
+}
+
+struct hw_interrupt_type systemasic_int = {
+ .typename = "System ASIC",
+ .startup = startup_systemasic_irq,
+ .shutdown = shutdown_systemasic_irq,
+ .enable = enable_systemasic_irq,
+ .disable = disable_systemasic_irq,
+ .ack = ack_systemasic_irq,
+ .end = end_systemasic_irq,
+};
+
+/*
+ * Map the hardware event indicated by the processor IRQ to a virtual IRQ.
+ */
+int systemasic_irq_demux(int irq)
+{
+ __u32 emr, esr, status, level;
+ __u32 j, bit;
+
+ switch (irq) {
+ case 13:
+ level = 0;
+ break;
+ case 11:
+ level = 1;
+ break;
+ case 9:
+ level = 2;
+ break;
+ default:
+ return irq;
+ }
+ emr = EMR_BASE + (level << 4) + (level << 2);
+ esr = ESR_BASE + (level << 2);
+
+ /* Mask the ESR to filter any spurious, unwanted interrtupts */
+ status = inl(esr);
+ status &= inl(emr);
+
+ /* Now scan and find the first set bit as the event to map */
+ for (bit = 1, j = 0; j < 32; bit <<= 1, j++) {
+ if (status & bit) {
+ irq = HW_EVENT_IRQ_BASE + j + (level << 5);
+ return irq;
+ }
+ }
+
+ /* Not reached */
+ return irq;
+}
diff --git a/arch/sh/boards/dreamcast/rtc.c b/arch/sh/boards/dreamcast/rtc.c
new file mode 100644
index 000000000000..379de1629134
--- /dev/null
+++ b/arch/sh/boards/dreamcast/rtc.c
@@ -0,0 +1,81 @@
+/* arch/sh/kernel/rtc-aica.c
+ *
+ * Dreamcast AICA RTC routines.
+ *
+ * Copyright (c) 2001, 2002 M. R. Brown <mrbrown@0xd6.org>
+ * Copyright (c) 2002 Paul Mundt <lethal@chaoticdreams.org>
+ *
+ * Released under the terms of the GNU GPL v2.0.
+ *
+ */
+
+#include <linux/time.h>
+
+#include <asm/io.h>
+
+extern void (*rtc_get_time)(struct timespec *);
+extern int (*rtc_set_time)(const time_t);
+
+/* The AICA RTC has an Epoch of 1/1/1950, so we must subtract 20 years (in
+ seconds to get the standard Unix Epoch when getting the time, and add 20
+ years when setting the time. */
+#define TWENTY_YEARS ((20 * 365LU + 5) * 86400)
+
+/* The AICA RTC is represented by a 32-bit seconds counter stored in 2 16-bit
+ registers.*/
+#define AICA_RTC_SECS_H 0xa0710000
+#define AICA_RTC_SECS_L 0xa0710004
+
+/**
+ * aica_rtc_gettimeofday - Get the time from the AICA RTC
+ * @ts: pointer to resulting timespec
+ *
+ * Grabs the current RTC seconds counter and adjusts it to the Unix Epoch.
+ */
+void aica_rtc_gettimeofday(struct timespec *ts) {
+ unsigned long val1, val2;
+
+ do {
+ val1 = ((ctrl_inl(AICA_RTC_SECS_H) & 0xffff) << 16) |
+ (ctrl_inl(AICA_RTC_SECS_L) & 0xffff);
+
+ val2 = ((ctrl_inl(AICA_RTC_SECS_H) & 0xffff) << 16) |
+ (ctrl_inl(AICA_RTC_SECS_L) & 0xffff);
+ } while (val1 != val2);
+
+ ts->tv_sec = val1 - TWENTY_YEARS;
+
+ /* Can't get nanoseconds with just a seconds counter. */
+ ts->tv_nsec = 0;
+}
+
+/**
+ * aica_rtc_settimeofday - Set the AICA RTC to the current time
+ * @secs: contains the time_t to set
+ *
+ * Adjusts the given @tv to the AICA Epoch and sets the RTC seconds counter.
+ */
+int aica_rtc_settimeofday(const time_t secs) {
+ unsigned long val1, val2;
+ unsigned long adj = secs + TWENTY_YEARS;
+
+ do {
+ ctrl_outl((adj & 0xffff0000) >> 16, AICA_RTC_SECS_H);
+ ctrl_outl((adj & 0xffff), AICA_RTC_SECS_L);
+
+ val1 = ((ctrl_inl(AICA_RTC_SECS_H) & 0xffff) << 16) |
+ (ctrl_inl(AICA_RTC_SECS_L) & 0xffff);
+
+ val2 = ((ctrl_inl(AICA_RTC_SECS_H) & 0xffff) << 16) |
+ (ctrl_inl(AICA_RTC_SECS_L) & 0xffff);
+ } while (val1 != val2);
+
+ return 0;
+}
+
+void aica_time_init(void)
+{
+ rtc_get_time = aica_rtc_gettimeofday;
+ rtc_set_time = aica_rtc_settimeofday;
+}
+
diff --git a/arch/sh/boards/dreamcast/setup.c b/arch/sh/boards/dreamcast/setup.c
new file mode 100644
index 000000000000..55dece35cde5
--- /dev/null
+++ b/arch/sh/boards/dreamcast/setup.c
@@ -0,0 +1,83 @@
+/*
+ * arch/sh/boards/dreamcast/setup.c
+ *
+ * Hardware support for the Sega Dreamcast.
+ *
+ * Copyright (c) 2001, 2002 M. R. Brown <mrbrown@linuxdc.org>
+ * Copyright (c) 2002, 2003, 2004 Paul Mundt <lethal@linux-sh.org>
+ *
+ * This file is part of the LinuxDC project (www.linuxdc.org)
+ *
+ * Released under the terms of the GNU GPL v2.0.
+ *
+ * This file originally bore the message (with enclosed-$):
+ * Id: setup_dc.c,v 1.5 2001/05/24 05:09:16 mrbrown Exp
+ * SEGA Dreamcast support
+ */
+
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/param.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/device.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/machvec.h>
+#include <asm/machvec_init.h>
+#include <asm/mach/sysasic.h>
+
+extern struct hw_interrupt_type systemasic_int;
+/* XXX: Move this into it's proper header. */
+extern void (*board_time_init)(void);
+extern void aica_time_init(void);
+extern int gapspci_init(void);
+extern int systemasic_irq_demux(int);
+
+void *dreamcast_consistent_alloc(struct device *, size_t, dma_addr_t *, int);
+int dreamcast_consistent_free(struct device *, size_t, void *, dma_addr_t);
+
+const char *get_system_type(void)
+{
+ return "Sega Dreamcast";
+}
+
+struct sh_machine_vector mv_dreamcast __initmv = {
+ .mv_nr_irqs = NR_IRQS,
+
+ .mv_irq_demux = systemasic_irq_demux,
+
+#ifdef CONFIG_PCI
+ .mv_consistent_alloc = dreamcast_consistent_alloc,
+ .mv_consistent_free = dreamcast_consistent_free,
+#endif
+};
+ALIAS_MV(dreamcast)
+
+int __init platform_setup(void)
+{
+ int i;
+
+ /* Mask all hardware events */
+ /* XXX */
+
+ /* Acknowledge any previous events */
+ /* XXX */
+
+ __set_io_port_base(0xa0000000);
+
+ /* Assign all virtual IRQs to the System ASIC int. handler */
+ for (i = HW_EVENT_IRQ_BASE; i < HW_EVENT_IRQ_MAX; i++)
+ irq_desc[i].handler = &systemasic_int;
+
+ board_time_init = aica_time_init;
+
+#ifdef CONFIG_PCI
+ if (gapspci_init() < 0)
+ printk(KERN_WARNING "GAPSPCI was not detected.\n");
+#endif
+
+ return 0;
+}
diff --git a/arch/sh/boards/ec3104/Makefile b/arch/sh/boards/ec3104/Makefile
new file mode 100644
index 000000000000..178891534b67
--- /dev/null
+++ b/arch/sh/boards/ec3104/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for the EC3104 specific parts of the kernel
+#
+
+obj-y := setup.o io.o irq.o
+
diff --git a/arch/sh/boards/ec3104/io.c b/arch/sh/boards/ec3104/io.c
new file mode 100644
index 000000000000..a70928c44753
--- /dev/null
+++ b/arch/sh/boards/ec3104/io.c
@@ -0,0 +1,81 @@
+/*
+ * linux/arch/sh/kernel/io_ec3104.c
+ * EC3104 companion chip support
+ *
+ * Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>
+ *
+ */
+/* EC3104 note:
+ * This code was written without any documentation about the EC3104 chip. While
+ * I hope I got most of the basic functionality right, the register names I use
+ * are most likely completely different from those in the chip documentation.
+ *
+ * If you have any further information about the EC3104, please tell me
+ * (prumpf@tux.org).
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <asm/io.h>
+#include <asm/page.h>
+#include <asm/ec3104/ec3104.h>
+
+/*
+ * EC3104 has a real ISA bus which we redirect low port accesses to (the
+ * actual device on mine is a ESS 1868, and I don't want to hack the driver
+ * more than strictly necessary). I am not going to duplicate the
+ * hard coding of PC addresses (for the 16550s aso) here though; it's just
+ * too ugly.
+ */
+
+#define low_port(port) ((port) < 0x10000)
+
+static inline unsigned long port2addr(unsigned long port)
+{
+ switch(port >> 16) {
+ case 0:
+ return EC3104_ISA_BASE + port * 2;
+
+ /* XXX hack. it's unclear what to do about the serial ports */
+ case 1:
+ return EC3104_BASE + (port&0xffff) * 4;
+
+ default:
+ /* XXX PCMCIA */
+ return 0;
+ }
+}
+
+unsigned char ec3104_inb(unsigned long port)
+{
+ u8 ret;
+
+ ret = *(volatile u8 *)port2addr(port);
+
+ return ret;
+}
+
+unsigned short ec3104_inw(unsigned long port)
+{
+ BUG();
+}
+
+unsigned long ec3104_inl(unsigned long port)
+{
+ BUG();
+}
+
+void ec3104_outb(unsigned char data, unsigned long port)
+{
+ *(volatile u8 *)port2addr(port) = data;
+}
+
+void ec3104_outw(unsigned short data, unsigned long port)
+{
+ BUG();
+}
+
+void ec3104_outl(unsigned long data, unsigned long port)
+{
+ BUG();
+}
diff --git a/arch/sh/boards/ec3104/irq.c b/arch/sh/boards/ec3104/irq.c
new file mode 100644
index 000000000000..ffa4ff1f090f
--- /dev/null
+++ b/arch/sh/boards/ec3104/irq.c
@@ -0,0 +1,196 @@
+/*
+ * linux/arch/sh/boards/ec3104/irq.c
+ * EC3104 companion chip support
+ *
+ * Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>
+ *
+ */
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/ec3104/ec3104.h>
+
+/* This is for debugging mostly; here's the table that I intend to keep
+ * in here:
+ *
+ * index function base addr power interrupt bit
+ * 0 power b0ec0000 --- 00000001 (unused)
+ * 1 irqs b0ec1000 --- 00000002 (unused)
+ * 2 ?? b0ec2000 b0ec0008 00000004
+ * 3 PS2 (1) b0ec3000 b0ec000c 00000008
+ * 4 PS2 (2) b0ec4000 b0ec0010 00000010
+ * 5 ?? b0ec5000 b0ec0014 00000020
+ * 6 I2C b0ec6000 b0ec0018 00000040
+ * 7 serial (1) b0ec7000 b0ec001c 00000080
+ * 8 serial (2) b0ec8000 b0ec0020 00000100
+ * 9 serial (3) b0ec9000 b0ec0024 00000200
+ * 10 serial (4) b0eca000 b0ec0028 00000400
+ * 12 GPIO (1) b0ecc000 b0ec0030
+ * 13 GPIO (2) b0ecc000 b0ec0030
+ * 16 pcmcia (1) b0ed0000 b0ec0040 00010000
+ * 17 pcmcia (2) b0ed1000 b0ec0044 00020000
+ */
+
+/* I used the register names from another interrupt controller I worked with,
+ * since it seems to be identical to the ec3104 except that all bits are
+ * inverted:
+ *
+ * IRR: Interrupt Request Register (pending and enabled interrupts)
+ * IMR: Interrupt Mask Register (which interrupts are enabled)
+ * IPR: Interrupt Pending Register (pending interrupts, even disabled ones)
+ *
+ * 0 bits mean pending or enabled, 1 bits mean not pending or disabled. all
+ * IRQs seem to be level-triggered.
+ */
+
+#define EC3104_IRR (EC3104_BASE + 0x1000)
+#define EC3104_IMR (EC3104_BASE + 0x1004)
+#define EC3104_IPR (EC3104_BASE + 0x1008)
+
+#define ctrl_readl(addr) (*(volatile u32 *)(addr))
+#define ctrl_writel(data,addr) (*(volatile u32 *)(addr) = (data))
+#define ctrl_readb(addr) (*(volatile u8 *)(addr))
+
+static char *ec3104_name(unsigned index)
+{
+ switch(index) {
+ case 0:
+ return "power management";
+ case 1:
+ return "interrupts";
+ case 3:
+ return "PS2 (1)";
+ case 4:
+ return "PS2 (2)";
+ case 5:
+ return "I2C (1)";
+ case 6:
+ return "I2C (2)";
+ case 7:
+ return "serial (1)";
+ case 8:
+ return "serial (2)";
+ case 9:
+ return "serial (3)";
+ case 10:
+ return "serial (4)";
+ case 16:
+ return "pcmcia (1)";
+ case 17:
+ return "pcmcia (2)";
+ default: {
+ static char buf[32];
+
+ sprintf(buf, "unknown (%d)", index);
+
+ return buf;
+ }
+ }
+}
+
+int get_pending_interrupts(char *buf)
+{
+ u32 ipr;
+ u32 bit;
+ char *p = buf;
+
+ p += sprintf(p, "pending: (");
+
+ ipr = ctrl_inl(EC3104_IPR);
+
+ for (bit = 1; bit < 32; bit++)
+ if (!(ipr & (1<<bit)))
+ p += sprintf(p, "%s ", ec3104_name(bit));
+
+ p += sprintf(p, ")\n");
+
+ return p - buf;
+}
+
+static inline u32 ec3104_irq2mask(unsigned int irq)
+{
+ return (1 << (irq - EC3104_IRQBASE));
+}
+
+static inline void mask_ec3104_irq(unsigned int irq)
+{
+ u32 mask;
+
+ mask = ctrl_readl(EC3104_IMR);
+
+ mask |= ec3104_irq2mask(irq);
+
+ ctrl_writel(mask, EC3104_IMR);
+}
+
+static inline void unmask_ec3104_irq(unsigned int irq)
+{
+ u32 mask;
+
+ mask = ctrl_readl(EC3104_IMR);
+
+ mask &= ~ec3104_irq2mask(irq);
+
+ ctrl_writel(mask, EC3104_IMR);
+}
+
+static void disable_ec3104_irq(unsigned int irq)
+{
+ mask_ec3104_irq(irq);
+}
+
+static void enable_ec3104_irq(unsigned int irq)
+{
+ unmask_ec3104_irq(irq);
+}
+
+static void mask_and_ack_ec3104_irq(unsigned int irq)
+{
+ mask_ec3104_irq(irq);
+}
+
+static void end_ec3104_irq(unsigned int irq)
+{
+ if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+ unmask_ec3104_irq(irq);
+}
+
+static unsigned int startup_ec3104_irq(unsigned int irq)
+{
+ unmask_ec3104_irq(irq);
+
+ return 0;
+}
+
+static void shutdown_ec3104_irq(unsigned int irq)
+{
+ mask_ec3104_irq(irq);
+
+}
+
+static struct hw_interrupt_type ec3104_int = {
+ .typename = "EC3104",
+ .enable = enable_ec3104_irq,
+ .disable = disable_ec3104_irq,
+ .ack = mask_and_ack_ec3104_irq,
+ .end = end_ec3104_irq,
+ .startup = startup_ec3104_irq,
+ .shutdown = shutdown_ec3104_irq,
+};
+
+/* Yuck. the _demux API is ugly */
+int ec3104_irq_demux(int irq)
+{
+ if (irq == EC3104_IRQ) {
+ unsigned int mask;
+
+ mask = ctrl_readl(EC3104_IRR);
+
+ if (mask == 0xffffffff)
+ return EC3104_IRQ;
+ else
+ return EC3104_IRQBASE + ffz(mask);
+ }
+
+ return irq;
+}
diff --git a/arch/sh/boards/ec3104/setup.c b/arch/sh/boards/ec3104/setup.c
new file mode 100644
index 000000000000..5130ba2b6ff1
--- /dev/null
+++ b/arch/sh/boards/ec3104/setup.c
@@ -0,0 +1,78 @@
+/*
+ * linux/arch/sh/boards/ec3104/setup.c
+ * EC3104 companion chip support
+ *
+ * Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>
+ *
+ */
+/* EC3104 note:
+ * This code was written without any documentation about the EC3104 chip. While
+ * I hope I got most of the basic functionality right, the register names I use
+ * are most likely completely different from those in the chip documentation.
+ *
+ * If you have any further information about the EC3104, please tell me
+ * (prumpf@tux.org).
+ */
+
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/param.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/types.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/machvec.h>
+#include <asm/mach/ec3104.h>
+
+const char *get_system_type(void)
+{
+ return "EC3104";
+}
+
+/*
+ * The Machine Vector
+ */
+
+struct sh_machine_vector mv_ec3104 __initmv = {
+ .mv_nr_irqs = 96,
+
+ .mv_inb = ec3104_inb,
+ .mv_inw = ec3104_inw,
+ .mv_inl = ec3104_inl,
+ .mv_outb = ec3104_outb,
+ .mv_outw = ec3104_outw,
+ .mv_outl = ec3104_outl,
+
+ .mv_irq_demux = ec3104_irq_demux,
+};
+
+ALIAS_MV(ec3104)
+
+int __init platform_setup(void)
+{
+ char str[8];
+ int i;
+
+ if (0)
+ return 0;
+
+ for (i=0; i<8; i++)
+ str[i] = ctrl_readb(EC3104_BASE + i);
+
+ for (i = EC3104_IRQBASE; i < EC3104_IRQBASE + 32; i++)
+ irq_desc[i].handler = &ec3104_int;
+
+ printk("initializing EC3104 \"%.8s\" at %08x, IRQ %d, IRQ base %d\n",
+ str, EC3104_BASE, EC3104_IRQ, EC3104_IRQBASE);
+
+
+ /* mask all interrupts. this should have been done by the boot
+ * loader for us but we want to be sure ... */
+ ctrl_writel(0xffffffff, EC3104_IMR);
+
+ return 0;
+}
+
diff --git a/arch/sh/boards/harp/Makefile b/arch/sh/boards/harp/Makefile
new file mode 100644
index 000000000000..eb753d31812e
--- /dev/null
+++ b/arch/sh/boards/harp/Makefile
@@ -0,0 +1,8 @@
+#
+# Makefile for STMicroelectronics board specific parts of the kernel
+#
+
+obj-y := irq.o setup.o mach.o led.o
+
+obj-$(CONFIG_PCI) += pcidma.o
+
diff --git a/arch/sh/boards/harp/irq.c b/arch/sh/boards/harp/irq.c
new file mode 100644
index 000000000000..acd58489970f
--- /dev/null
+++ b/arch/sh/boards/harp/irq.c
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2000 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.
+ *
+ * Looks after interrupts on the HARP board.
+ *
+ * Bases on the IPR irq system
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/harp/harp.h>
+
+
+#define NUM_EXTERNAL_IRQS 16
+
+// Early versions of the STB1 Overdrive required this nasty frig
+//#define INVERT_INTMASK_WRITES
+
+static void enable_harp_irq(unsigned int irq);
+static void disable_harp_irq(unsigned int irq);
+
+/* shutdown is same as "disable" */
+#define shutdown_harp_irq disable_harp_irq
+
+static void mask_and_ack_harp(unsigned int);
+static void end_harp_irq(unsigned int irq);
+
+static unsigned int startup_harp_irq(unsigned int irq)
+{
+ enable_harp_irq(irq);
+ return 0; /* never anything pending */
+}
+
+static struct hw_interrupt_type harp_irq_type = {
+ "Harp-IRQ",
+ startup_harp_irq,
+ shutdown_harp_irq,
+ enable_harp_irq,
+ disable_harp_irq,
+ mask_and_ack_harp,
+ end_harp_irq
+};
+
+static void disable_harp_irq(unsigned int irq)
+{
+ unsigned val, flags;
+ unsigned maskReg;
+ unsigned mask;
+ int pri;
+
+ if (irq < 0 || irq >= NUM_EXTERNAL_IRQS)
+ return;
+
+ pri = 15 - irq;
+
+ if (pri < 8) {
+ maskReg = EPLD_INTMASK0;
+ } else {
+ maskReg = EPLD_INTMASK1;
+ pri -= 8;
+ }
+
+ local_irq_save(flags);
+ mask = ctrl_inl(maskReg);
+ mask &= (~(1 << pri));
+#if defined(INVERT_INTMASK_WRITES)
+ mask ^= 0xff;
+#endif
+ ctrl_outl(mask, maskReg);
+ local_irq_restore(flags);
+}
+
+static void enable_harp_irq(unsigned int irq)
+{
+ unsigned flags;
+ unsigned maskReg;
+ unsigned mask;
+ int pri;
+
+ if (irq < 0 || irq >= NUM_EXTERNAL_IRQS)
+ return;
+
+ pri = 15 - irq;
+
+ if (pri < 8) {
+ maskReg = EPLD_INTMASK0;
+ } else {
+ maskReg = EPLD_INTMASK1;
+ pri -= 8;
+ }
+
+ local_irq_save(flags);
+ mask = ctrl_inl(maskReg);
+
+
+ mask |= (1 << pri);
+
+#if defined(INVERT_INTMASK_WRITES)
+ mask ^= 0xff;
+#endif
+ ctrl_outl(mask, maskReg);
+
+ local_irq_restore(flags);
+}
+
+/* This functions sets the desired irq handler to be an overdrive type */
+static void __init make_harp_irq(unsigned int irq)
+{
+ disable_irq_nosync(irq);
+ irq_desc[irq].handler = &harp_irq_type;
+ disable_harp_irq(irq);
+}
+
+static void mask_and_ack_harp(unsigned int irq)
+{
+ disable_harp_irq(irq);
+}
+
+static void end_harp_irq(unsigned int irq)
+{
+ enable_harp_irq(irq);
+}
+
+void __init init_harp_irq(void)
+{
+ int i;
+
+#if !defined(INVERT_INTMASK_WRITES)
+ // On the harp these are set to enable an interrupt
+ ctrl_outl(0x00, EPLD_INTMASK0);
+ ctrl_outl(0x00, EPLD_INTMASK1);
+#else
+ // On the Overdrive the data is inverted before being stored in the reg
+ ctrl_outl(0xff, EPLD_INTMASK0);
+ ctrl_outl(0xff, EPLD_INTMASK1);
+#endif
+
+ for (i = 0; i < NUM_EXTERNAL_IRQS; i++) {
+ make_harp_irq(i);
+ }
+}
diff --git a/arch/sh/boards/harp/led.c b/arch/sh/boards/harp/led.c
new file mode 100644
index 000000000000..76ca4ccac703
--- /dev/null
+++ b/arch/sh/boards/harp/led.c
@@ -0,0 +1,52 @@
+/*
+ * linux/arch/sh/stboards/led.c
+ *
+ * Copyright (C) 2000 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.
+ *
+ * This file contains ST40STB1 HARP and compatible code.
+ */
+
+#include <linux/config.h>
+#include <asm/io.h>
+#include <asm/harp/harp.h>
+
+/* Harp: Flash LD10 (front pannel) connected to EPLD (IC8) */
+/* Overdrive: Flash LD1 (front panel) connected to EPLD (IC4) */
+/* Works for HARP and overdrive */
+static void mach_led(int position, int value)
+{
+ if (value) {
+ ctrl_outl(EPLD_LED_ON, EPLD_LED);
+ } else {
+ ctrl_outl(EPLD_LED_OFF, EPLD_LED);
+ }
+}
+
+#ifdef CONFIG_HEARTBEAT
+
+#include <linux/sched.h>
+
+/* acts like an actual heart beat -- ie thump-thump-pause... */
+void heartbeat_harp(void)
+{
+ static unsigned 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;
+ }
+}
+#endif
diff --git a/arch/sh/boards/harp/mach.c b/arch/sh/boards/harp/mach.c
new file mode 100644
index 000000000000..a946dd1674ca
--- /dev/null
+++ b/arch/sh/boards/harp/mach.c
@@ -0,0 +1,62 @@
+/*
+ * linux/arch/sh/boards/harp/mach.c
+ *
+ * Copyright (C) 2000 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 vector for the STMicroelectronics STB1 HARP and compatible boards
+ */
+
+#include <linux/init.h>
+
+#include <asm/machvec.h>
+#include <asm/rtc.h>
+#include <asm/machvec_init.h>
+#include <asm/hd64465/io.h>
+#include <asm/hd64465/hd64465.h>
+
+void setup_harp(void);
+void init_harp_irq(void);
+void heartbeat_harp(void);
+
+/*
+ * The Machine Vector
+ */
+
+struct sh_machine_vector mv_harp __initmv = {
+ .mv_nr_irqs = 89 + HD64465_IRQ_NUM,
+
+ .mv_inb = hd64465_inb,
+ .mv_inw = hd64465_inw,
+ .mv_inl = hd64465_inl,
+ .mv_outb = hd64465_outb,
+ .mv_outw = hd64465_outw,
+ .mv_outl = hd64465_outl,
+
+ .mv_inb_p = hd64465_inb_p,
+ .mv_inw_p = hd64465_inw,
+ .mv_inl_p = hd64465_inl,
+ .mv_outb_p = hd64465_outb_p,
+ .mv_outw_p = hd64465_outw,
+ .mv_outl_p = hd64465_outl,
+
+ .mv_insb = hd64465_insb,
+ .mv_insw = hd64465_insw,
+ .mv_insl = hd64465_insl,
+ .mv_outsb = hd64465_outsb,
+ .mv_outsw = hd64465_outsw,
+ .mv_outsl = hd64465_outsl,
+
+ .mv_isa_port2addr = hd64465_isa_port2addr,
+
+#ifdef CONFIG_PCI
+ .mv_init_irq = init_harp_irq,
+#endif
+#ifdef CONFIG_HEARTBEAT
+ .mv_heartbeat = heartbeat_harp,
+#endif
+};
+
+ALIAS_MV(harp)
diff --git a/arch/sh/boards/harp/pcidma.c b/arch/sh/boards/harp/pcidma.c
new file mode 100644
index 000000000000..475311390fd6
--- /dev/null
+++ b/arch/sh/boards/harp/pcidma.c
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ *
+ * Dynamic DMA mapping support.
+ */
+
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/string.h>
+#include <linux/pci.h>
+#include <asm/io.h>
+#include <asm/addrspace.h>
+
+
+void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size,
+ dma_addr_t * dma_handle)
+{
+ void *ret;
+ int gfp = GFP_ATOMIC;
+
+ ret = (void *) __get_free_pages(gfp, get_order(size));
+
+ if (ret != NULL) {
+ /* Is it neccessary to do the memset? */
+ memset(ret, 0, size);
+ *dma_handle = virt_to_bus(ret);
+ }
+ /* We must flush the cache before we pass it on to the device */
+ flush_cache_all();
+ return P2SEGADDR(ret);
+}
+
+void pci_free_consistent(struct pci_dev *hwdev, size_t size,
+ void *vaddr, dma_addr_t dma_handle)
+{
+ unsigned long p1addr=P1SEGADDR((unsigned long)vaddr);
+
+ free_pages(p1addr, get_order(size));
+}
diff --git a/arch/sh/boards/harp/setup.c b/arch/sh/boards/harp/setup.c
new file mode 100644
index 000000000000..05b01b8f40aa
--- /dev/null
+++ b/arch/sh/boards/harp/setup.c
@@ -0,0 +1,91 @@
+/*
+ * arch/sh/stboard/setup.c
+ *
+ * Copyright (C) 2001 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.
+ *
+ * STMicroelectronics ST40STB1 HARP and compatible support.
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <asm/io.h>
+#include <asm/harp/harp.h>
+
+const char *get_system_type(void)
+{
+ return "STB1 Harp";
+}
+
+/*
+ * Initialize the board
+ */
+int __init platform_setup(void)
+{
+#ifdef CONFIG_SH_STB1_HARP
+ unsigned long ic8_version, ic36_version;
+
+ ic8_version = ctrl_inl(EPLD_REVID2);
+ ic36_version = ctrl_inl(EPLD_REVID1);
+
+ printk("STMicroelectronics STB1 HARP initialisaton\n");
+ printk("EPLD versions: IC8: %d.%02d, IC36: %d.%02d\n",
+ (ic8_version >> 4) & 0xf, ic8_version & 0xf,
+ (ic36_version >> 4) & 0xf, ic36_version & 0xf);
+#elif defined(CONFIG_SH_STB1_OVERDRIVE)
+ unsigned long version;
+
+ version = ctrl_inl(EPLD_REVID);
+
+ printk("STMicroelectronics STB1 Overdrive initialisaton\n");
+ printk("EPLD version: %d.%02d\n",
+ (version >> 4) & 0xf, version & 0xf);
+#else
+#error Undefined machine
+#endif
+
+ /* Currently all STB1 chips have problems with the sleep instruction,
+ * so disable it here.
+ */
+ disable_hlt();
+
+ return 0;
+}
+
+/*
+ * pcibios_map_platform_irq
+ *
+ * This is board specific and returns the IRQ for a given PCI device.
+ * It is used by the PCI code (arch/sh/kernel/st40_pci*)
+ *
+ */
+
+#define HARP_PCI_IRQ 1
+#define HARP_BRIDGE_IRQ 2
+#define OVERDRIVE_SLOT0_IRQ 0
+
+
+int __init pcibios_map_platform_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+ switch (slot) {
+#ifdef CONFIG_SH_STB1_HARP
+ case 2: /*This is the PCI slot on the */
+ return HARP_PCI_IRQ;
+ case 1: /* this is the bridge */
+ return HARP_BRIDGE_IRQ;
+#elif defined(CONFIG_SH_STB1_OVERDRIVE)
+ case 1:
+ case 2:
+ case 3:
+ return slot - 1;
+#else
+#error Unknown board
+#endif
+ default:
+ return -1;
+ }
+}
+
diff --git a/arch/sh/boards/hp6xx/hp620/Makefile b/arch/sh/boards/hp6xx/hp620/Makefile
new file mode 100644
index 000000000000..20691dbce347
--- /dev/null
+++ b/arch/sh/boards/hp6xx/hp620/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for the HP620 specific parts of the kernel
+#
+
+obj-y := mach.o setup.o
+
diff --git a/arch/sh/boards/hp6xx/hp620/mach.c b/arch/sh/boards/hp6xx/hp620/mach.c
new file mode 100644
index 000000000000..0392d82b4a7b
--- /dev/null
+++ b/arch/sh/boards/hp6xx/hp620/mach.c
@@ -0,0 +1,52 @@
+/*
+ * linux/arch/sh/boards/hp6xx/hp620/mach.c
+ *
+ * Copyright (C) 2000 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 vector for the HP620
+ */
+
+#include <linux/init.h>
+
+#include <asm/machvec.h>
+#include <asm/rtc.h>
+#include <asm/machvec_init.h>
+
+#include <asm/io.h>
+#include <asm/hd64461/hd64461.h>
+#include <asm/irq.h>
+
+/*
+ * The Machine Vector
+ */
+
+struct sh_machine_vector mv_hp620 __initmv = {
+ .mv_nr_irqs = HD64461_IRQBASE+HD64461_IRQ_NUM,
+
+ .mv_inb = hd64461_inb,
+ .mv_inw = hd64461_inw,
+ .mv_inl = hd64461_inl,
+ .mv_outb = hd64461_outb,
+ .mv_outw = hd64461_outw,
+ .mv_outl = hd64461_outl,
+
+ .mv_inb_p = hd64461_inb_p,
+ .mv_inw_p = hd64461_inw,
+ .mv_inl_p = hd64461_inl,
+ .mv_outb_p = hd64461_outb_p,
+ .mv_outw_p = hd64461_outw,
+ .mv_outl_p = hd64461_outl,
+
+ .mv_insb = hd64461_insb,
+ .mv_insw = hd64461_insw,
+ .mv_insl = hd64461_insl,
+ .mv_outsb = hd64461_outsb,
+ .mv_outsw = hd64461_outsw,
+ .mv_outsl = hd64461_outsl,
+
+ .mv_irq_demux = hd64461_irq_demux,
+};
+ALIAS_MV(hp620)
diff --git a/arch/sh/boards/hp6xx/hp620/setup.c b/arch/sh/boards/hp6xx/hp620/setup.c
new file mode 100644
index 000000000000..045fc5da7274
--- /dev/null
+++ b/arch/sh/boards/hp6xx/hp620/setup.c
@@ -0,0 +1,45 @@
+/*
+ * linux/arch/sh/boards/hp6xx/hp620/setup.c
+ *
+ * Copyright (C) 2002 Andriy Skulysh, 2005 Kristoffer Ericson
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License. See Linux/COPYING for more information.
+ *
+ * Setup code for an HP620.
+ * Due to similiarity with hp680/hp690 same inits are done (for now)
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <asm/hd64461/hd64461.h>
+#include <asm/io.h>
+#include <asm/hp6xx/hp6xx.h>
+#include <asm/cpu/dac.h>
+
+const char *get_system_type(void)
+{
+ return "HP620";
+}
+
+int __init platform_setup(void)
+{
+ u16 v;
+
+ v = inw(HD64461_STBCR);
+ v |= HD64461_STBCR_SURTST | HD64461_STBCR_SIRST |
+ HD64461_STBCR_STM1ST | HD64461_STBCR_STM0ST |
+ HD64461_STBCR_SAFEST | HD64461_STBCR_SPC0ST |
+ HD64461_STBCR_SMIAST | HD64461_STBCR_SAFECKE_OST |
+ HD64461_STBCR_SAFECKE_IST;
+ outw(v, HD64461_STBCR);
+
+ v = inw(HD64461_GPADR);
+ v |= HD64461_GPADR_SPEAKER | HD64461_GPADR_PCMCIA0;
+ outw(v, HD64461_GPADR);
+
+ sh_dac_disable(DAC_SPEAKER_VOLUME);
+
+ return 0;
+}
+
diff --git a/arch/sh/boards/hp6xx/hp680/Makefile b/arch/sh/boards/hp6xx/hp680/Makefile
new file mode 100644
index 000000000000..0beef11d9b11
--- /dev/null
+++ b/arch/sh/boards/hp6xx/hp680/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for the HP680 specific parts of the kernel
+#
+
+obj-y := mach.o setup.o
+
diff --git a/arch/sh/boards/hp6xx/hp680/mach.c b/arch/sh/boards/hp6xx/hp680/mach.c
new file mode 100644
index 000000000000..d73486136045
--- /dev/null
+++ b/arch/sh/boards/hp6xx/hp680/mach.c
@@ -0,0 +1,53 @@
+/*
+ * linux/arch/sh/boards/hp6xx/hp680/mach.c
+ *
+ * Copyright (C) 2000 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 vector for the HP680
+ */
+
+#include <linux/init.h>
+
+#include <asm/machvec.h>
+#include <asm/rtc.h>
+#include <asm/machvec_init.h>
+
+#include <asm/io.h>
+#include <asm/hd64461/hd64461.h>
+#include <asm/hp6xx/io.h>
+#include <asm/irq.h>
+
+struct sh_machine_vector mv_hp680 __initmv = {
+ .mv_nr_irqs = HD64461_IRQBASE + HD64461_IRQ_NUM,
+
+ .mv_inb = hd64461_inb,
+ .mv_inw = hd64461_inw,
+ .mv_inl = hd64461_inl,
+ .mv_outb = hd64461_outb,
+ .mv_outw = hd64461_outw,
+ .mv_outl = hd64461_outl,
+
+ .mv_inb_p = hd64461_inb_p,
+ .mv_inw_p = hd64461_inw,
+ .mv_inl_p = hd64461_inl,
+ .mv_outb_p = hd64461_outb_p,
+ .mv_outw_p = hd64461_outw,
+ .mv_outl_p = hd64461_outl,
+
+ .mv_insb = hd64461_insb,
+ .mv_insw = hd64461_insw,
+ .mv_insl = hd64461_insl,
+ .mv_outsb = hd64461_outsb,
+ .mv_outsw = hd64461_outsw,
+ .mv_outsl = hd64461_outsl,
+
+ .mv_readw = hd64461_readw,
+ .mv_writew = hd64461_writew,
+
+ .mv_irq_demux = hd64461_irq_demux,
+};
+
+ALIAS_MV(hp680)
diff --git a/arch/sh/boards/hp6xx/hp680/setup.c b/arch/sh/boards/hp6xx/hp680/setup.c
new file mode 100644
index 000000000000..4170190f2644
--- /dev/null
+++ b/arch/sh/boards/hp6xx/hp680/setup.c
@@ -0,0 +1,41 @@
+/*
+ * linux/arch/sh/boards/hp6xx/hp680/setup.c
+ *
+ * Copyright (C) 2002 Andriy Skulysh
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License. See linux/COPYING for more information.
+ *
+ * Setup code for an HP680 (internal peripherials only)
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <asm/hd64461/hd64461.h>
+#include <asm/io.h>
+#include <asm/hp6xx/hp6xx.h>
+#include <asm/cpu/dac.h>
+
+const char *get_system_type(void)
+{
+ return "HP680";
+}
+
+int __init platform_setup(void)
+{
+ u16 v;
+ v = inw(HD64461_STBCR);
+ v |= HD64461_STBCR_SURTST | HD64461_STBCR_SIRST |
+ HD64461_STBCR_STM1ST | HD64461_STBCR_STM0ST |
+ HD64461_STBCR_SAFEST | HD64461_STBCR_SPC0ST |
+ HD64461_STBCR_SMIAST | HD64461_STBCR_SAFECKE_OST |
+ HD64461_STBCR_SAFECKE_IST;
+ outw(v, HD64461_STBCR);
+ v = inw(HD64461_GPADR);
+ v |= HD64461_GPADR_SPEAKER | HD64461_GPADR_PCMCIA0;
+ outw(v, HD64461_GPADR);
+
+ sh_dac_disable(DAC_SPEAKER_VOLUME);
+
+ return 0;
+}
diff --git a/arch/sh/boards/hp6xx/hp690/Makefile b/arch/sh/boards/hp6xx/hp690/Makefile
new file mode 100644
index 000000000000..fbbe95e75f83
--- /dev/null
+++ b/arch/sh/boards/hp6xx/hp690/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for the HP690 specific parts of the kernel
+#
+
+obj-y := mach.o
+
diff --git a/arch/sh/boards/hp6xx/hp690/mach.c b/arch/sh/boards/hp6xx/hp690/mach.c
new file mode 100644
index 000000000000..2a4c68783cd6
--- /dev/null
+++ b/arch/sh/boards/hp6xx/hp690/mach.c
@@ -0,0 +1,48 @@
+/*
+ * linux/arch/sh/boards/hp6xx/hp690/mach.c
+ *
+ * Copyright (C) 2000 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 vector for the HP690
+ */
+
+#include <linux/init.h>
+
+#include <asm/machvec.h>
+#include <asm/rtc.h>
+#include <asm/machvec_init.h>
+
+#include <asm/io.h>
+#include <asm/hd64461/hd64461.h>
+#include <asm/irq.h>
+
+struct sh_machine_vector mv_hp690 __initmv = {
+ .mv_nr_irqs = HD64461_IRQBASE+HD64461_IRQ_NUM,
+
+ .mv_inb = hd64461_inb,
+ .mv_inw = hd64461_inw,
+ .mv_inl = hd64461_inl,
+ .mv_outb = hd64461_outb,
+ .mv_outw = hd64461_outw,
+ .mv_outl = hd64461_outl,
+
+ .mv_inb_p = hd64461_inb_p,
+ .mv_inw_p = hd64461_inw,
+ .mv_inl_p = hd64461_inl,
+ .mv_outb_p = hd64461_outb_p,
+ .mv_outw_p = hd64461_outw,
+ .mv_outl_p = hd64461_outl,
+
+ .mv_insb = hd64461_insb,
+ .mv_insw = hd64461_insw,
+ .mv_insl = hd64461_insl,
+ .mv_outsb = hd64461_outsb,
+ .mv_outsw = hd64461_outsw,
+ .mv_outsl = hd64461_outsl,
+
+ .mv_irq_demux = hd64461_irq_demux,
+};
+ALIAS_MV(hp690)
diff --git a/arch/sh/boards/mpc1211/Makefile b/arch/sh/boards/mpc1211/Makefile
new file mode 100644
index 000000000000..1644ebed78cb
--- /dev/null
+++ b/arch/sh/boards/mpc1211/Makefile
@@ -0,0 +1,8 @@
+#
+# Makefile for the Interface (CTP/PCI/MPC-SH02) specific parts of the kernel
+#
+
+obj-y := setup.o rtc.o led.o
+
+obj-$(CONFIG_PCI) += pci.o
+
diff --git a/arch/sh/boards/mpc1211/led.c b/arch/sh/boards/mpc1211/led.c
new file mode 100644
index 000000000000..0a31beec3465
--- /dev/null
+++ b/arch/sh/boards/mpc1211/led.c
@@ -0,0 +1,64 @@
+/*
+ * linux/arch/sh/kernel/led_mpc1211.c
+ *
+ * Copyright (C) 2001 Saito.K & Jeanne
+ *
+ * This file contains Interface MPC-1211 specific LED code.
+ */
+
+#include <linux/config.h>
+
+static void mach_led(int position, int value)
+{
+ volatile unsigned char* p = (volatile unsigned char*)0xa2000000;
+
+ if (value) {
+ *p |= 1;
+ } else {
+ *p &= ~1;
+ }
+}
+
+#ifdef CONFIG_HEARTBEAT
+
+#include <linux/sched.h>
+
+/* Cycle the LED's in the clasic Knightrider/Sun pattern */
+void heartbeat_mpc1211(void)
+{
+ static unsigned int cnt = 0, period = 0;
+ volatile unsigned char* p = (volatile unsigned char*)0xa2000000;
+ static unsigned bit = 0, up = 1;
+
+ cnt += 1;
+ if (cnt < period) {
+ return;
+ }
+
+ cnt = 0;
+
+ /* Go through the points (roughly!):
+ * f(0)=10, f(1)=16, f(2)=20, f(5)=35,f(inf)->110
+ */
+ period = 110 - ( (300<<FSHIFT)/
+ ((avenrun[0]/5) + (3<<FSHIFT)) );
+
+ if (up) {
+ if (bit == 7) {
+ bit--;
+ up=0;
+ } else {
+ bit ++;
+ }
+ } else {
+ if (bit == 0) {
+ bit++;
+ up=1;
+ } else {
+ bit--;
+ }
+ }
+ *p = 1<<bit;
+
+}
+#endif /* CONFIG_HEARTBEAT */
diff --git a/arch/sh/boards/mpc1211/pci.c b/arch/sh/boards/mpc1211/pci.c
new file mode 100644
index 000000000000..ba3a65439752
--- /dev/null
+++ b/arch/sh/boards/mpc1211/pci.c
@@ -0,0 +1,296 @@
+/*
+ * Low-Level PCI Support for the MPC-1211(CTP/PCI/MPC-SH02)
+ *
+ * (c) 2002-2003 Saito.K & Jeanne
+ *
+ * Dustin McIntire (dustin@sensoria.com)
+ * Derived from arch/i386/kernel/pci-*.c which bore the message:
+ * (c) 1999--2000 Martin Mares <mj@ucw.cz>
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License. See linux/COPYING for more information.
+ *
+ */
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+#include <linux/sched.h>
+#include <linux/ioport.h>
+#include <linux/errno.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+
+#include <asm/machvec.h>
+#include <asm/io.h>
+#include <asm/mpc1211/pci.h>
+
+static struct resource mpcpci_io_resource = {
+ "MPCPCI IO",
+ 0x00000000,
+ 0xffffffff,
+ IORESOURCE_IO
+};
+
+static struct resource mpcpci_mem_resource = {
+ "MPCPCI mem",
+ 0x00000000,
+ 0xffffffff,
+ IORESOURCE_MEM
+};
+
+static struct pci_ops pci_direct_conf1;
+struct pci_channel board_pci_channels[] = {
+ {&pci_direct_conf1, &mpcpci_io_resource, &mpcpci_mem_resource, 0, 256},
+ {NULL, NULL, NULL, 0, 0},
+};
+
+/*
+ * Direct access to PCI hardware...
+ */
+
+
+#define CONFIG_CMD(bus, devfn, where) (0x80000000 | (bus->number << 16) | (devfn << 8) | (where & ~3))
+
+/*
+ * Functions for accessing PCI configuration space with type 1 accesses
+ */
+static int pci_conf1_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *value)
+{
+ u32 word;
+ unsigned long flags;
+
+ /*
+ * PCIPDR may only be accessed as 32 bit words,
+ * so we must do byte alignment by hand
+ */
+ local_irq_save(flags);
+ writel(CONFIG_CMD(bus,devfn,where), PCIPAR);
+ word = readl(PCIPDR);
+ local_irq_restore(flags);
+
+ switch (size) {
+ case 1:
+ switch (where & 0x3) {
+ case 3:
+ *value = (u8)(word >> 24);
+ break;
+ case 2:
+ *value = (u8)(word >> 16);
+ break;
+ case 1:
+ *value = (u8)(word >> 8);
+ break;
+ default:
+ *value = (u8)word;
+ break;
+ }
+ break;
+ case 2:
+ switch (where & 0x3) {
+ case 3:
+ *value = (u16)(word >> 24);
+ local_irq_save(flags);
+ writel(CONFIG_CMD(bus,devfn,(where+1)), PCIPAR);
+ word = readl(PCIPDR);
+ local_irq_restore(flags);
+ *value |= ((word & 0xff) << 8);
+ break;
+ case 2:
+ *value = (u16)(word >> 16);
+ break;
+ case 1:
+ *value = (u16)(word >> 8);
+ break;
+ default:
+ *value = (u16)word;
+ break;
+ }
+ break;
+ case 4:
+ *value = word;
+ break;
+ }
+ PCIDBG(4,"pci_conf1_read@0x%08x=0x%x\n", CONFIG_CMD(bus,devfn,where),*value);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+/*
+ * Since MPC-1211 only does 32bit access we'll have to do a read,mask,write operation.
+ * We'll allow an odd byte offset, though it should be illegal.
+ */
+static int pci_conf1_write(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 value)
+{
+ u32 word,mask = 0;
+ unsigned long flags;
+ u32 shift = (where & 3) * 8;
+
+ if(size == 1) {
+ mask = ((1 << 8) - 1) << shift; // create the byte mask
+ } else if(size == 2){
+ if(shift == 24)
+ return PCIBIOS_BAD_REGISTER_NUMBER;
+ mask = ((1 << 16) - 1) << shift; // create the word mask
+ }
+ local_irq_save(flags);
+ writel(CONFIG_CMD(bus,devfn,where), PCIPAR);
+ if(size == 4){
+ writel(value, PCIPDR);
+ local_irq_restore(flags);
+ PCIDBG(4,"pci_conf1_write@0x%08x=0x%x\n", CONFIG_CMD(bus,devfn,where),value);
+ return PCIBIOS_SUCCESSFUL;
+ }
+ word = readl(PCIPDR);
+ word &= ~mask;
+ word |= ((value << shift) & mask);
+ writel(word, PCIPDR);
+ local_irq_restore(flags);
+ PCIDBG(4,"pci_conf1_write@0x%08x=0x%x\n", CONFIG_CMD(bus,devfn,where),word);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+#undef CONFIG_CMD
+
+static struct pci_ops pci_direct_conf1 = {
+ .read = pci_conf1_read,
+ .write = pci_conf1_write,
+};
+
+static void __devinit quirk_ali_ide_ports(struct pci_dev *dev)
+{
+ dev->resource[0].start = 0x1f0;
+ dev->resource[0].end = 0x1f7;
+ dev->resource[0].flags = IORESOURCE_IO;
+ dev->resource[1].start = 0x3f6;
+ dev->resource[1].end = 0x3f6;
+ dev->resource[1].flags = IORESOURCE_IO;
+ dev->resource[2].start = 0x170;
+ dev->resource[2].end = 0x177;
+ dev->resource[2].flags = IORESOURCE_IO;
+ dev->resource[3].start = 0x376;
+ dev->resource[3].end = 0x376;
+ dev->resource[3].flags = IORESOURCE_IO;
+ dev->resource[4].start = 0xf000;
+ dev->resource[4].end = 0xf00f;
+ dev->resource[4].flags = IORESOURCE_IO;
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M5229, quirk_ali_ide_ports);
+
+char * __devinit pcibios_setup(char *str)
+{
+ return str;
+}
+
+/*
+ * Called after each bus is probed, but before its children
+ * are examined.
+ */
+
+void __init pcibios_fixup_bus(struct pci_bus *b)
+{
+ pci_read_bridge_bases(b);
+}
+
+/*
+ * IRQ functions
+ */
+static inline u8 bridge_swizzle(u8 pin, u8 slot)
+{
+ return (((pin-1) + slot) % 4) + 1;
+}
+
+static inline u8 bridge_swizzle_pci_1(u8 pin, u8 slot)
+{
+ return (((pin-1) - slot) & 3) + 1;
+}
+
+static u8 __init mpc1211_swizzle(struct pci_dev *dev, u8 *pinp)
+{
+ unsigned long flags;
+ u8 pin = *pinp;
+ u32 word;
+
+ for ( ; dev->bus->self; dev = dev->bus->self) {
+ if (!pin)
+ continue;
+
+ if (dev->bus->number == 1) {
+ local_irq_save(flags);
+ writel(0x80000000 | 0x2c, PCIPAR);
+ word = readl(PCIPDR);
+ local_irq_restore(flags);
+ word >>= 16;
+
+ if (word == 0x0001)
+ pin = bridge_swizzle_pci_1(pin, PCI_SLOT(dev->devfn));
+ else
+ pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn));
+ } else
+ pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn));
+ }
+
+ *pinp = pin;
+
+ return PCI_SLOT(dev->devfn);
+}
+
+static int __init map_mpc1211_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+ int irq = -1;
+
+ /* now lookup the actual IRQ on a platform specific basis (pci-'platform'.c) */
+ if (dev->bus->number == 0) {
+ switch (slot) {
+ case 13: irq = 9; break; /* USB */
+ case 22: irq = 10; break; /* LAN */
+ default: irq = 0; break;
+ }
+ } else {
+ switch (pin) {
+ case 0: irq = 0; break;
+ case 1: irq = 7; break;
+ case 2: irq = 9; break;
+ case 3: irq = 10; break;
+ case 4: irq = 11; break;
+ }
+ }
+
+ if( irq < 0 ) {
+ PCIDBG(3, "PCI: Error mapping IRQ on device %s\n", pci_name(dev));
+ return irq;
+ }
+
+ PCIDBG(2, "Setting IRQ for slot %s to %d\n", pci_name(dev), irq);
+
+ return irq;
+}
+
+void __init pcibios_fixup_irqs(void)
+{
+ pci_fixup_irqs(mpc1211_swizzle, map_mpc1211_irq);
+}
+
+void pcibios_align_resource(void *data, struct resource *res,
+ unsigned long size, unsigned long align)
+{
+ unsigned long start = res->start;
+
+ if (res->flags & IORESOURCE_IO) {
+ if (start >= 0x10000UL) {
+ if ((start & 0xffffUL) < 0x4000UL) {
+ start = (start & 0xffff0000UL) + 0x4000UL;
+ } else if ((start & 0xffffUL) >= 0xf000UL) {
+ start = (start & 0xffff0000UL) + 0x10000UL;
+ }
+ res->start = start;
+ } else {
+ if (start & 0x300) {
+ start = (start + 0x3ff) & ~0x3ff;
+ res->start = start;
+ }
+ }
+ }
+}
+
diff --git a/arch/sh/boards/mpc1211/rtc.c b/arch/sh/boards/mpc1211/rtc.c
new file mode 100644
index 000000000000..4d100f048072
--- /dev/null
+++ b/arch/sh/boards/mpc1211/rtc.c
@@ -0,0 +1,152 @@
+/*
+ * linux/arch/sh/kernel/rtc-mpc1211.c -- MPC-1211 on-chip RTC support
+ *
+ * Copyright (C) 2002 Saito.K & Jeanne
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/mc146818rtc.h>
+
+#ifndef BCD_TO_BIN
+#define BCD_TO_BIN(val) ((val)=((val)&15) + ((val)>>4)*10)
+#endif
+
+#ifndef BIN_TO_BCD
+#define BIN_TO_BCD(val) ((val)=(((val)/10)<<4) + (val)%10)
+#endif
+
+/* arc/i386/kernel/time.c */
+unsigned long get_cmos_time(void)
+{
+ unsigned int year, mon, day, hour, min, sec;
+ int i;
+
+ spin_lock(&rtc_lock);
+ /* The Linux interpretation of the CMOS clock register contents:
+ * When the Update-In-Progress (UIP) flag goes from 1 to 0, the
+ * RTC registers show the second which has precisely just started.
+ * Let's hope other operating systems interpret the RTC the same way.
+ */
+ /* read RTC exactly on falling edge of update flag */
+ for (i = 0 ; i < 1000000 ; i++) /* may take up to 1 second... */
+ if (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)
+ break;
+ for (i = 0 ; i < 1000000 ; i++) /* must try at least 2.228 ms */
+ if (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP))
+ break;
+ do { /* Isn't this overkill ? UIP above should guarantee consistency */
+ sec = CMOS_READ(RTC_SECONDS);
+ min = CMOS_READ(RTC_MINUTES);
+ hour = CMOS_READ(RTC_HOURS);
+ day = CMOS_READ(RTC_DAY_OF_MONTH);
+ mon = CMOS_READ(RTC_MONTH);
+ year = CMOS_READ(RTC_YEAR);
+ } while (sec != CMOS_READ(RTC_SECONDS));
+ if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
+ {
+ BCD_TO_BIN(sec);
+ BCD_TO_BIN(min);
+ BCD_TO_BIN(hour);
+ BCD_TO_BIN(day);
+ BCD_TO_BIN(mon);
+ BCD_TO_BIN(year);
+ }
+ spin_unlock(&rtc_lock);
+ if ((year += 1900) < 1970)
+ year += 100;
+ return mktime(year, mon, day, hour, min, sec);
+}
+
+void mpc1211_rtc_gettimeofday(struct timeval *tv)
+{
+
+ tv->tv_sec = get_cmos_time();
+ tv->tv_usec = 0;
+}
+
+/* arc/i386/kernel/time.c */
+/*
+ * In order to set the CMOS clock precisely, set_rtc_mmss has to be
+ * called 500 ms after the second nowtime has started, because when
+ * nowtime is written into the registers of the CMOS clock, it will
+ * jump to the next second precisely 500 ms later. Check the Motorola
+ * MC146818A or Dallas DS12887 data sheet for details.
+ *
+ * BUG: This routine does not handle hour overflow properly; it just
+ * sets the minutes. Usually you'll only notice that after reboot!
+ */
+static int set_rtc_mmss(unsigned long nowtime)
+{
+ int retval = 0;
+ int real_seconds, real_minutes, cmos_minutes;
+ unsigned char save_control, save_freq_select;
+
+ /* gets recalled with irq locally disabled */
+ spin_lock(&rtc_lock);
+ save_control = CMOS_READ(RTC_CONTROL); /* tell the clock it's being set */
+ CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL);
+
+ save_freq_select = CMOS_READ(RTC_FREQ_SELECT); /* stop and reset prescaler */
+ CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT);
+
+ cmos_minutes = CMOS_READ(RTC_MINUTES);
+ if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
+ BCD_TO_BIN(cmos_minutes);
+
+ /*
+ * since we're only adjusting minutes and seconds,
+ * don't interfere with hour overflow. This avoids
+ * messing with unknown time zones but requires your
+ * RTC not to be off by more than 15 minutes
+ */
+ real_seconds = nowtime % 60;
+ real_minutes = nowtime / 60;
+ if (((abs(real_minutes - cmos_minutes) + 15)/30) & 1)
+ real_minutes += 30; /* correct for half hour time zone */
+ real_minutes %= 60;
+
+ if (abs(real_minutes - cmos_minutes) < 30) {
+ if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
+ BIN_TO_BCD(real_seconds);
+ BIN_TO_BCD(real_minutes);
+ }
+ CMOS_WRITE(real_seconds,RTC_SECONDS);
+ CMOS_WRITE(real_minutes,RTC_MINUTES);
+ } else {
+ printk(KERN_WARNING
+ "set_rtc_mmss: can't update from %d to %d\n",
+ cmos_minutes, real_minutes);
+ retval = -1;
+ }
+
+ /* The following flags have to be released exactly in this order,
+ * otherwise the DS12887 (popular MC146818A clone with integrated
+ * battery and quartz) will not reset the oscillator and will not
+ * update precisely 500 ms later. You won't find this mentioned in
+ * the Dallas Semiconductor data sheets, but who believes data
+ * sheets anyway ... -- Markus Kuhn
+ */
+ CMOS_WRITE(save_control, RTC_CONTROL);
+ CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);
+ spin_unlock(&rtc_lock);
+
+ return retval;
+}
+
+int mpc1211_rtc_settimeofday(const struct timeval *tv)
+{
+ unsigned long nowtime = tv->tv_sec;
+
+ return set_rtc_mmss(nowtime);
+}
+
+void mpc1211_time_init(void)
+{
+ rtc_get_time = mpc1211_rtc_gettimeofday;
+ rtc_set_time = mpc1211_rtc_settimeofday;
+}
+
diff --git a/arch/sh/boards/mpc1211/setup.c b/arch/sh/boards/mpc1211/setup.c
new file mode 100644
index 000000000000..2bb581b91683
--- /dev/null
+++ b/arch/sh/boards/mpc1211/setup.c
@@ -0,0 +1,360 @@
+/*
+ * linux/arch/sh/board/mpc1211/setup.c
+ *
+ * Copyright (C) 2002 Saito.K & Jeanne, Fujii.Y
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/hdreg.h>
+#include <linux/ide.h>
+#include <linux/interrupt.h>
+
+#include <asm/io.h>
+#include <asm/machvec.h>
+#include <asm/mpc1211/mpc1211.h>
+#include <asm/mpc1211/pci.h>
+#include <asm/mpc1211/m1543c.h>
+
+
+/* ALI15X3 SMBus address offsets */
+#define SMBHSTSTS (0 + 0x3100)
+#define SMBHSTCNT (1 + 0x3100)
+#define SMBHSTSTART (2 + 0x3100)
+#define SMBHSTCMD (7 + 0x3100)
+#define SMBHSTADD (3 + 0x3100)
+#define SMBHSTDAT0 (4 + 0x3100)
+#define SMBHSTDAT1 (5 + 0x3100)
+#define SMBBLKDAT (6 + 0x3100)
+
+/* Other settings */
+#define MAX_TIMEOUT 500 /* times 1/100 sec */
+
+/* ALI15X3 command constants */
+#define ALI15X3_ABORT 0x04
+#define ALI15X3_T_OUT 0x08
+#define ALI15X3_QUICK 0x00
+#define ALI15X3_BYTE 0x10
+#define ALI15X3_BYTE_DATA 0x20
+#define ALI15X3_WORD_DATA 0x30
+#define ALI15X3_BLOCK_DATA 0x40
+#define ALI15X3_BLOCK_CLR 0x80
+
+/* ALI15X3 status register bits */
+#define ALI15X3_STS_IDLE 0x04
+#define ALI15X3_STS_BUSY 0x08
+#define ALI15X3_STS_DONE 0x10
+#define ALI15X3_STS_DEV 0x20 /* device error */
+#define ALI15X3_STS_COLL 0x40 /* collision or no response */
+#define ALI15X3_STS_TERM 0x80 /* terminated by abort */
+#define ALI15X3_STS_ERR 0xE0 /* all the bad error bits */
+
+const char *get_system_type(void)
+{
+ return "Interface MPC-1211(CTP/PCI/MPC-SH02)";
+}
+
+static void __init pci_write_config(unsigned long busNo,
+ unsigned long devNo,
+ unsigned long fncNo,
+ unsigned long cnfAdd,
+ unsigned long cnfData)
+{
+ ctrl_outl((0x80000000
+ + ((busNo & 0xff) << 16)
+ + ((devNo & 0x1f) << 11)
+ + ((fncNo & 0x07) << 8)
+ + (cnfAdd & 0xfc)), PCIPAR);
+
+ ctrl_outl(cnfData, PCIPDR);
+}
+
+/*
+ Initialize IRQ setting
+*/
+
+static unsigned char m_irq_mask = 0xfb;
+static unsigned char s_irq_mask = 0xff;
+volatile unsigned long irq_err_count;
+
+static void disable_mpc1211_irq(unsigned int irq)
+{
+ unsigned long flags;
+
+ save_and_cli(flags);
+ if( irq < 8) {
+ m_irq_mask |= (1 << irq);
+ outb(m_irq_mask,I8259_M_MR);
+ } else {
+ s_irq_mask |= (1 << (irq - 8));
+ outb(s_irq_mask,I8259_S_MR);
+ }
+ restore_flags(flags);
+
+}
+
+static void enable_mpc1211_irq(unsigned int irq)
+{
+ unsigned long flags;
+
+ save_and_cli(flags);
+
+ if( irq < 8) {
+ m_irq_mask &= ~(1 << irq);
+ outb(m_irq_mask,I8259_M_MR);
+ } else {
+ s_irq_mask &= ~(1 << (irq - 8));
+ outb(s_irq_mask,I8259_S_MR);
+ }
+ restore_flags(flags);
+}
+
+static inline int mpc1211_irq_real(unsigned int irq)
+{
+ int value;
+ int irqmask;
+
+ if ( irq < 8) {
+ irqmask = 1<<irq;
+ outb(0x0b,I8259_M_CR); /* ISR register */
+ value = inb(I8259_M_CR) & irqmask;
+ outb(0x0a,I8259_M_CR); /* back ro the IPR reg */
+ return value;
+ }
+ irqmask = 1<<(irq - 8);
+ outb(0x0b,I8259_S_CR); /* ISR register */
+ value = inb(I8259_S_CR) & irqmask;
+ outb(0x0a,I8259_S_CR); /* back ro the IPR reg */
+ return value;
+}
+
+static void mask_and_ack_mpc1211(unsigned int irq)
+{
+ unsigned long flags;
+
+ save_and_cli(flags);
+
+ if(irq < 8) {
+ if(m_irq_mask & (1<<irq)){
+ if(!mpc1211_irq_real(irq)){
+ irq_err_count++;
+ printk("spurious 8259A interrupt: IRQ %x\n",irq);
+ }
+ } else {
+ m_irq_mask |= (1<<irq);
+ }
+ inb(I8259_M_MR); /* DUMMY */
+ outb(m_irq_mask,I8259_M_MR); /* disable */
+ outb(0x60+irq,I8259_M_CR); /* EOI */
+
+ } else {
+ if(s_irq_mask & (1<<(irq - 8))){
+ if(!mpc1211_irq_real(irq)){
+ irq_err_count++;
+ printk("spurious 8259A interrupt: IRQ %x\n",irq);
+ }
+ } else {
+ s_irq_mask |= (1<<(irq - 8));
+ }
+ inb(I8259_S_MR); /* DUMMY */
+ outb(s_irq_mask,I8259_S_MR); /* disable */
+ outb(0x60+(irq-8),I8259_S_CR); /* EOI */
+ outb(0x60+2,I8259_M_CR);
+ }
+ restore_flags(flags);
+}
+
+static void end_mpc1211_irq(unsigned int irq)
+{
+ enable_mpc1211_irq(irq);
+}
+
+static unsigned int startup_mpc1211_irq(unsigned int irq)
+{
+ enable_mpc1211_irq(irq);
+ return 0;
+}
+
+static void shutdown_mpc1211_irq(unsigned int irq)
+{
+ disable_mpc1211_irq(irq);
+}
+
+static struct hw_interrupt_type mpc1211_irq_type = {
+ .typename = "MPC1211-IRQ",
+ .startup = startup_mpc1211_irq,
+ .shutdown = shutdown_mpc1211_irq,
+ .enable = enable_mpc1211_irq,
+ .disable = disable_mpc1211_irq,
+ .ack = mask_and_ack_mpc1211,
+ .end = end_mpc1211_irq
+};
+
+static void make_mpc1211_irq(unsigned int irq)
+{
+ irq_desc[irq].handler = &mpc1211_irq_type;
+ irq_desc[irq].status = IRQ_DISABLED;
+ irq_desc[irq].action = 0;
+ irq_desc[irq].depth = 1;
+ disable_mpc1211_irq(irq);
+}
+
+int mpc1211_irq_demux(int irq)
+{
+ unsigned int poll;
+
+ if( irq == 2 ) {
+ outb(0x0c,I8259_M_CR);
+ poll = inb(I8259_M_CR);
+ if(poll & 0x80) {
+ irq = (poll & 0x07);
+ }
+ if( irq == 2) {
+ outb(0x0c,I8259_S_CR);
+ poll = inb(I8259_S_CR);
+ irq = (poll & 0x07) + 8;
+ }
+ }
+ return irq;
+}
+
+void __init init_mpc1211_IRQ(void)
+{
+ int i;
+ /*
+ * Super I/O (Just mimic PC):
+ * 1: keyboard
+ * 3: serial 1
+ * 4: serial 0
+ * 5: printer
+ * 6: floppy
+ * 8: rtc
+ * 10: lan
+ * 12: mouse
+ * 14: ide0
+ * 15: ide1
+ */
+
+ pci_write_config(0,0,0,0x54, 0xb0b0002d);
+ outb(0x11, I8259_M_CR); /* mater icw1 edge trigger */
+ outb(0x11, I8259_S_CR); /* slave icw1 edge trigger */
+ outb(0x20, I8259_M_MR); /* m icw2 base vec 0x08 */
+ outb(0x28, I8259_S_MR); /* s icw2 base vec 0x70 */
+ outb(0x04, I8259_M_MR); /* m icw3 slave irq2 */
+ outb(0x02, I8259_S_MR); /* s icw3 slave id */
+ outb(0x01, I8259_M_MR); /* m icw4 non buf normal eoi*/
+ outb(0x01, I8259_S_MR); /* s icw4 non buf normal eo1*/
+ outb(0xfb, I8259_M_MR); /* disable irq0--irq7 */
+ outb(0xff, I8259_S_MR); /* disable irq8--irq15 */
+
+ for ( i=0; i < 16; i++) {
+ if(i != 2) {
+ make_mpc1211_irq(i);
+ }
+ }
+}
+
+/*
+ Initialize the board
+*/
+
+
+static void delay (void)
+{
+ volatile unsigned short tmp;
+ tmp = *(volatile unsigned short *) 0xa0000000;
+}
+
+static void delay1000 (void)
+{
+ int i;
+
+ for (i=0; i<1000; i++)
+ delay ();
+}
+
+static int put_smb_blk(unsigned char *p, int address, int command, int no)
+{
+ int temp;
+ int timeout;
+ int i;
+
+ outb(0xff, SMBHSTSTS);
+ temp = inb(SMBHSTSTS);
+ for (timeout = 0; (timeout < MAX_TIMEOUT) && !(temp & ALI15X3_STS_IDLE); timeout++) {
+ delay1000();
+ temp = inb(SMBHSTSTS);
+ }
+ if (timeout >= MAX_TIMEOUT){
+ return -1;
+ }
+
+ outb(((address & 0x7f) << 1), SMBHSTADD);
+ outb(0xc0, SMBHSTCNT);
+ outb(command & 0xff, SMBHSTCMD);
+ outb(no & 0x1f, SMBHSTDAT0);
+
+ for(i = 1; i <= no; i++) {
+ outb(*p++, SMBBLKDAT);
+ }
+ outb(0xff, SMBHSTSTART);
+
+ temp = inb(SMBHSTSTS);
+ for (timeout = 0; (timeout < MAX_TIMEOUT) && !(temp & (ALI15X3_STS_ERR | ALI15X3_STS_DONE)); timeout++) {
+ delay1000();
+ temp = inb(SMBHSTSTS);
+ }
+ if (timeout >= MAX_TIMEOUT) {
+ return -2;
+ }
+ if ( temp & ALI15X3_STS_ERR ){
+ return -3;
+ }
+ return 0;
+}
+
+/*
+ * The Machine Vector
+ */
+
+struct sh_machine_vector mv_mpc1211 __initmv = {
+ .mv_nr_irqs = 48,
+ .mv_irq_demux = mpc1211_irq_demux,
+ .mv_init_irq = init_mpc1211_IRQ,
+
+#ifdef CONFIG_HEARTBEAT
+ .mv_heartbeat = heartbeat_mpc1211,
+#endif
+};
+
+ALIAS_MV(mpc1211)
+
+/* arch/sh/boards/mpc1211/rtc.c */
+void mpc1211_time_init(void);
+
+int __init platform_setup(void)
+{
+ unsigned char spd_buf[128];
+
+ __set_io_port_base(PA_PCI_IO);
+
+ pci_write_config(0,0,0,0x54, 0xb0b00000);
+
+ do {
+ outb(ALI15X3_ABORT, SMBHSTCNT);
+ spd_buf[0] = 0x0c;
+ spd_buf[1] = 0x43;
+ spd_buf[2] = 0x7f;
+ spd_buf[3] = 0x03;
+ spd_buf[4] = 0x00;
+ spd_buf[5] = 0x03;
+ spd_buf[6] = 0x00;
+ } while (put_smb_blk(spd_buf, 0x69, 0, 7) < 0);
+
+ board_time_init = mpc1211_time_init;
+
+ return 0;
+}
+
diff --git a/arch/sh/boards/overdrive/Makefile b/arch/sh/boards/overdrive/Makefile
new file mode 100644
index 000000000000..1762b59e9279
--- /dev/null
+++ b/arch/sh/boards/overdrive/Makefile
@@ -0,0 +1,8 @@
+#
+# Makefile for the STMicroelectronics Overdrive specific parts of the kernel
+#
+
+obj-y := mach.o setup.o io.o irq.o led.o time.o
+
+obj-$(CONFIG_PCI) += fpga.o galileo.o pcidma.o
+
diff --git a/arch/sh/boards/overdrive/fpga.c b/arch/sh/boards/overdrive/fpga.c
new file mode 100644
index 000000000000..3a1ec9403441
--- /dev/null
+++ b/arch/sh/boards/overdrive/fpga.c
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2000 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.
+ *
+ * This file handles programming up the Altera Flex10K that interfaces to
+ * the Galileo, and does the PS/2 keyboard and mouse
+ *
+ */
+
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+
+
+#include <asm/overdriver/gt64111.h>
+#include <asm/overdrive/overdrive.h>
+#include <asm/overdrive/fpga.h>
+
+#define FPGA_NotConfigHigh() (*FPGA_ControlReg) = (*FPGA_ControlReg) | ENABLE_FPGA_BIT
+#define FPGA_NotConfigLow() (*FPGA_ControlReg) = (*FPGA_ControlReg) & RESET_FPGA_MASK
+
+/* I need to find out what (if any) the real delay factor here is */
+/* The delay is definately not critical */
+#define long_delay() {int i;for(i=0;i<10000;i++);}
+#define short_delay() {int i;for(i=0;i<100;i++);}
+
+static void __init program_overdrive_fpga(const unsigned char *fpgacode,
+ int size)
+{
+ int timeout = 0;
+ int i, j;
+ unsigned char b;
+ static volatile unsigned char *FPGA_ControlReg =
+ (volatile unsigned char *) (OVERDRIVE_CTRL);
+ static volatile unsigned char *FPGA_ProgramReg =
+ (volatile unsigned char *) (FPGA_DCLK_ADDRESS);
+
+ printk("FPGA: Commencing FPGA Programming\n");
+
+ /* The PCI reset but MUST be low when programming the FPGA !!! */
+ b = (*FPGA_ControlReg) & RESET_PCI_MASK;
+
+ (*FPGA_ControlReg) = b;
+
+ /* Prepare FPGA to program */
+
+ FPGA_NotConfigHigh();
+ long_delay();
+
+ FPGA_NotConfigLow();
+ short_delay();
+
+ while ((*FPGA_ProgramReg & FPGA_NOT_STATUS) != 0) {
+ printk("FPGA: Waiting for NotStatus to go Low ... \n");
+ }
+
+ FPGA_NotConfigHigh();
+
+ /* Wait for FPGA "ready to be programmed" signal */
+ printk("FPGA: Waiting for NotStatus to go high (FPGA ready)... \n");
+
+ for (timeout = 0;
+ (((*FPGA_ProgramReg & FPGA_NOT_STATUS) == 0)
+ && (timeout < FPGA_TIMEOUT)); timeout++);
+
+ /* Check if timeout condition occured - i.e. an error */
+
+ if (timeout == FPGA_TIMEOUT) {
+ printk
+ ("FPGA: Failed to program - Timeout waiting for notSTATUS to go high\n");
+ return;
+ }
+
+ printk("FPGA: Copying data to FPGA ... %d bytes\n", size);
+
+ /* Copy array to FPGA - bit at a time */
+
+ for (i = 0; i < size; i++) {
+ volatile unsigned w = 0;
+
+ for (j = 0; j < 8; j++) {
+ *FPGA_ProgramReg = (fpgacode[i] >> j) & 0x01;
+ short_delay();
+ }
+ if ((i & 0x3ff) == 0) {
+ printk(".");
+ }
+ }
+
+ /* Waiting for CONFDONE to go high - means the program is complete */
+
+ for (timeout = 0;
+ (((*FPGA_ProgramReg & FPGA_CONFDONE) == 0)
+ && (timeout < FPGA_TIMEOUT)); timeout++) {
+
+ *FPGA_ProgramReg = 0x0;
+ long_delay();
+ }
+
+ if (timeout == FPGA_TIMEOUT) {
+ printk
+ ("FPGA: Failed to program - Timeout waiting for CONFDONE to go high\n");
+ return;
+ } else { /* Clock another 10 times - gets the device into a working state */
+ for (i = 0; i < 10; i++) {
+ *FPGA_ProgramReg = 0x0;
+ short_delay();
+ }
+ }
+
+ printk("FPGA: Programming complete\n");
+}
+
+
+static const unsigned char __init fpgacode[] = {
+#include "./overdrive.ttf" /* Code from maxplus2 compiler */
+ , 0, 0
+};
+
+
+int __init init_overdrive_fpga(void)
+{
+ program_overdrive_fpga(fpgacode, sizeof(fpgacode));
+
+ return 0;
+}
diff --git a/arch/sh/boards/overdrive/galileo.c b/arch/sh/boards/overdrive/galileo.c
new file mode 100644
index 000000000000..276fa11ee4ce
--- /dev/null
+++ b/arch/sh/boards/overdrive/galileo.c
@@ -0,0 +1,588 @@
+/*
+ * Copyright (C) 2000 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.
+ *
+ * This file contains the PCI routines required for the Galileo GT6411
+ * PCI bridge as used on the Orion and Overdrive boards.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/types.h>
+#include <linux/ioport.h>
+
+#include <asm/overdrive/overdrive.h>
+#include <asm/overdrive/gt64111.h>
+
+
+/* After boot, we shift the Galileo registers so that they appear
+ * in BANK6, along with IO space. This means we can have one contingous
+ * lump of PCI address space without these registers appearing in the
+ * middle of them
+ */
+
+#define GT64111_BASE_ADDRESS 0xbb000000
+#define GT64111_IO_BASE_ADDRESS 0x1000
+/* The GT64111 registers appear at this address to the SH4 after reset */
+#define RESET_GT64111_BASE_ADDRESS 0xb4000000
+
+/* Macros used to access the Galileo registers */
+#define RESET_GT64111_REG(x) (RESET_GT64111_BASE_ADDRESS+x)
+#define GT64111_REG(x) (GT64111_BASE_ADDRESS+x)
+
+#define RESET_GT_WRITE(x,v) writel((v),RESET_GT64111_REG(x))
+
+#define RESET_GT_READ(x) readl(RESET_GT64111_REG(x))
+
+#define GT_WRITE(x,v) writel((v),GT64111_REG(x))
+#define GT_WRITE_BYTE(x,v) writeb((v),GT64111_REG(x))
+#define GT_WRITE_SHORT(x,v) writew((v),GT64111_REG(x))
+
+#define GT_READ(x) readl(GT64111_REG(x))
+#define GT_READ_BYTE(x) readb(GT64111_REG(x))
+#define GT_READ_SHORT(x) readw(GT64111_REG(x))
+
+
+/* Where the various SH banks start at */
+#define SH_BANK4_ADR 0xb0000000
+#define SH_BANK5_ADR 0xb4000000
+#define SH_BANK6_ADR 0xb8000000
+
+/* Masks out everything but lines 28,27,26 */
+#define BANK_SELECT_MASK 0x1c000000
+
+#define SH4_TO_BANK(x) ( (x) & BANK_SELECT_MASK)
+
+/*
+ * Masks used for address conversaion. Bank 6 is used for IO and
+ * has all the address bits zeroed by the FPGA. Special case this
+ */
+#define MEMORY_BANK_MASK 0x1fffffff
+#define IO_BANK_MASK 0x03ffffff
+
+/* Mark bank 6 as the bank used for IO. You can change this in the FPGA code
+ * if you want
+ */
+#define IO_BANK_ADR PCI_GTIO_BASE
+
+/* Will select the correct mask to apply depending on the SH$ address */
+#define SELECT_BANK_MASK(x) \
+ ( (SH4_TO_BANK(x)==SH4_TO_BANK(IO_BANK_ADR)) ? IO_BANK_MASK : MEMORY_BANK_MASK)
+
+/* Converts between PCI space and P2 region */
+#define SH4_TO_PCI(x) ((x)&SELECT_BANK_MASK(x))
+
+/* Various macros for figuring out what to stick in the Galileo registers.
+ * You *really* don't want to figure this stuff out by hand, you always get
+ * it wrong
+ */
+#define GT_MEM_LO_ADR(x) ((((unsigned)((x)&SELECT_BANK_MASK(x)))>>21)&0x7ff)
+#define GT_MEM_HI_ADR(x) ((((unsigned)((x)&SELECT_BANK_MASK(x)))>>21)&0x7f)
+#define GT_MEM_SUB_ADR(x) ((((unsigned)((x)&SELECT_BANK_MASK(x)))>>20)&0xff)
+
+#define PROGRAM_HI_LO(block,a,s) \
+ GT_WRITE(block##_LO_DEC_ADR,GT_MEM_LO_ADR(a));\
+ GT_WRITE(block##_HI_DEC_ADR,GT_MEM_HI_ADR(a+s-1))
+
+#define PROGRAM_SUB_HI_LO(block,a,s) \
+ GT_WRITE(block##_LO_DEC_ADR,GT_MEM_SUB_ADR(a));\
+ GT_WRITE(block##_HI_DEC_ADR,GT_MEM_SUB_ADR(a+s-1))
+
+/* We need to set the size, and the offset register */
+
+#define GT_BAR_MASK(x) ((x)&~0xfff)
+
+/* Macro to set up the BAR in the Galileo. Essentially used for the DRAM */
+#define PROGRAM_GT_BAR(block,a,s) \
+ GT_WRITE(PCI_##block##_BANK_SIZE,GT_BAR_MASK((s-1)));\
+ write_config_to_galileo(PCI_CONFIG_##block##_BASE_ADR,\
+ GT_BAR_MASK(a))
+
+#define DISABLE_GT_BAR(block) \
+ GT_WRITE(PCI_##block##_BANK_SIZE,0),\
+ GT_CONFIG_WRITE(PCI_CONFIG_##block##_BASE_ADR,\
+ 0x80000000)
+
+/* Macros to disable things we are not going to use */
+#define DISABLE_DECODE(x) GT_WRITE(x##_LO_DEC_ADR,0x7ff);\
+ GT_WRITE(x##_HI_DEC_ADR,0x00)
+
+#define DISABLE_SUB_DECODE(x) GT_WRITE(x##_LO_DEC_ADR,0xff);\
+ GT_WRITE(x##_HI_DEC_ADR,0x00)
+
+static void __init reset_pci(void)
+{
+ /* Set RESET_PCI bit high */
+ writeb(readb(OVERDRIVE_CTRL) | ENABLE_PCI_BIT, OVERDRIVE_CTRL);
+ udelay(250);
+
+ /* Set RESET_PCI bit low */
+ writeb(readb(OVERDRIVE_CTRL) & RESET_PCI_MASK, OVERDRIVE_CTRL);
+ udelay(250);
+
+ writeb(readb(OVERDRIVE_CTRL) | ENABLE_PCI_BIT, OVERDRIVE_CTRL);
+ udelay(250);
+}
+
+static int write_config_to_galileo(int where, u32 val);
+#define GT_CONFIG_WRITE(where,val) write_config_to_galileo(where,val)
+
+#define ENABLE_PCI_DRAM
+
+
+#ifdef TEST_DRAM
+/* Test function to check out if the PCI DRAM is working OK */
+static int /* __init */ test_dram(unsigned *base, unsigned size)
+{
+ unsigned *p = base;
+ unsigned *end = (unsigned *) (((unsigned) base) + size);
+ unsigned w;
+
+ for (p = base; p < end; p++) {
+ *p = 0xffffffff;
+ if (*p != 0xffffffff) {
+ printk("AAARGH -write failed!!! at %p is %x\n", p,
+ *p);
+ return 0;
+ }
+ *p = 0x0;
+ if (*p != 0x0) {
+ printk("AAARGH -write failed!!!\n");
+ return 0;
+ }
+ }
+
+ for (p = base; p < end; p++) {
+ *p = (unsigned) p;
+ if (*p != (unsigned) p) {
+ printk("Failed at 0x%p, actually is 0x%x\n", p,
+ *p);
+ return 0;
+ }
+ }
+
+ for (p = base; p < end; p++) {
+ w = ((unsigned) p & 0xffff0000);
+ *p = w | (w >> 16);
+ }
+
+ for (p = base; p < end; p++) {
+ w = ((unsigned) p & 0xffff0000);
+ w |= (w >> 16);
+ if (*p != w) {
+ printk
+ ("Failed at 0x%p, should be 0x%x actually is 0x%x\n",
+ p, w, *p);
+ return 0;
+ }
+ }
+
+ return 1;
+}
+#endif
+
+
+/* Function to set up and initialise the galileo. This sets up the BARS,
+ * maps the DRAM into the address space etc,etc
+ */
+int __init galileo_init(void)
+{
+ reset_pci();
+
+ /* Now shift the galileo regs into this block */
+ RESET_GT_WRITE(INTERNAL_SPACE_DEC,
+ GT_MEM_LO_ADR(GT64111_BASE_ADDRESS));
+
+ /* Should have a sanity check here, that you can read back at the new
+ * address what you just wrote
+ */
+
+ /* Disable decode for all regions */
+ DISABLE_DECODE(RAS10);
+ DISABLE_DECODE(RAS32);
+ DISABLE_DECODE(CS20);
+ DISABLE_DECODE(CS3);
+ DISABLE_DECODE(PCI_IO);
+ DISABLE_DECODE(PCI_MEM0);
+ DISABLE_DECODE(PCI_MEM1);
+
+ /* Disable all BARS */
+ GT_WRITE(BAR_ENABLE_ADR, 0x1ff);
+ DISABLE_GT_BAR(RAS10);
+ DISABLE_GT_BAR(RAS32);
+ DISABLE_GT_BAR(CS20);
+ DISABLE_GT_BAR(CS3);
+
+ /* Tell the BAR where the IO registers now are */
+ GT_CONFIG_WRITE(PCI_CONFIG_INT_REG_IO_ADR,GT_BAR_MASK(
+ (GT64111_IO_BASE_ADDRESS &
+ IO_BANK_MASK)));
+ /* set up a 112 Mb decode */
+ PROGRAM_HI_LO(PCI_MEM0, SH_BANK4_ADR, 112 * 1024 * 1024);
+
+ /* Set up a 32 MB io space decode */
+ PROGRAM_HI_LO(PCI_IO, IO_BANK_ADR, 32 * 1024 * 1024);
+
+#ifdef ENABLE_PCI_DRAM
+ /* Program up the DRAM configuration - there is DRAM only in bank 0 */
+ /* Now set up the DRAM decode */
+ PROGRAM_HI_LO(RAS10, PCI_DRAM_BASE, PCI_DRAM_SIZE);
+ /* And the sub decode */
+ PROGRAM_SUB_HI_LO(RAS0, PCI_DRAM_BASE, PCI_DRAM_SIZE);
+
+ DISABLE_SUB_DECODE(RAS1);
+
+ /* Set refresh rate */
+ GT_WRITE(DRAM_BANK0_PARMS, 0x3f);
+ GT_WRITE(DRAM_CFG, 0x100);
+
+ /* we have to lob off the top bits rememeber!! */
+ PROGRAM_GT_BAR(RAS10, SH4_TO_PCI(PCI_DRAM_BASE), PCI_DRAM_SIZE);
+
+#endif
+
+ /* We are only interested in decoding RAS10 and the Galileo's internal
+ * registers (as IO) on the PCI bus
+ */
+#ifdef ENABLE_PCI_DRAM
+ GT_WRITE(BAR_ENABLE_ADR, (~((1 << 8) | (1 << 3))) & 0x1ff);
+#else
+ GT_WRITE(BAR_ENABLE_ADR, (~(1 << 3)) & 0x1ff);
+#endif
+
+ /* Change the class code to host bridge, it actually powers up
+ * as a memory controller
+ */
+ GT_CONFIG_WRITE(8, 0x06000011);
+
+ /* Allow the galileo to master the PCI bus */
+ GT_CONFIG_WRITE(PCI_COMMAND,
+ PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER |
+ PCI_COMMAND_IO);
+
+
+#if 0
+ printk("Testing PCI DRAM - ");
+ if(test_dram(PCI_DRAM_BASE,PCI_DRAM_SIZE)) {
+ printk("Passed\n");
+ }else {
+ printk("FAILED\n");
+ }
+#endif
+ return 0;
+
+}
+
+
+#define SET_CONFIG_BITS(bus,devfn,where)\
+ ((1<<31) | ((bus) << 16) | ((devfn) << 8) | ((where) & ~3))
+
+#define CONFIG_CMD(dev, where) SET_CONFIG_BITS((dev)->bus->number,(dev)->devfn,where)
+
+/* This write to the galileo config registers, unlike the functions below, can
+ * be used before the PCI subsystem has started up
+ */
+static int __init write_config_to_galileo(int where, u32 val)
+{
+ GT_WRITE(PCI_CFG_ADR, SET_CONFIG_BITS(0, 0, where));
+
+ GT_WRITE(PCI_CFG_DATA, val);
+ return 0;
+}
+
+/* We exclude the galileo and slot 31, the galileo because I don't know how to stop
+ * the setup code shagging up the setup I have done on it, and 31 because the whole
+ * thing locks up if you try to access that slot (which doesn't exist of course anyway
+ */
+
+#define EXCLUDED_DEV(dev) ((dev->bus->number==0) && ((PCI_SLOT(dev->devfn)==0) || (PCI_SLOT(dev->devfn) == 31)))
+
+static int galileo_read_config_byte(struct pci_dev *dev, int where,
+ u8 * val)
+{
+
+
+ /* I suspect this doesn't work because this drives a special cycle ? */
+ if (EXCLUDED_DEV(dev)) {
+ *val = 0xff;
+ return PCIBIOS_SUCCESSFUL;
+ }
+ /* Start the config cycle */
+ GT_WRITE(PCI_CFG_ADR, CONFIG_CMD(dev, where));
+ /* Read back the result */
+ *val = GT_READ_BYTE(PCI_CFG_DATA + (where & 3));
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+
+static int galileo_read_config_word(struct pci_dev *dev, int where,
+ u16 * val)
+{
+
+ if (EXCLUDED_DEV(dev)) {
+ *val = 0xffff;
+ return PCIBIOS_SUCCESSFUL;
+ }
+
+ GT_WRITE(PCI_CFG_ADR, CONFIG_CMD(dev, where));
+ *val = GT_READ_SHORT(PCI_CFG_DATA + (where & 2));
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+
+static int galileo_read_config_dword(struct pci_dev *dev, int where,
+ u32 * val)
+{
+ if (EXCLUDED_DEV(dev)) {
+ *val = 0xffffffff;
+ return PCIBIOS_SUCCESSFUL;
+ }
+
+ GT_WRITE(PCI_CFG_ADR, CONFIG_CMD(dev, where));
+ *val = GT_READ(PCI_CFG_DATA);
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int galileo_write_config_byte(struct pci_dev *dev, int where,
+ u8 val)
+{
+ GT_WRITE(PCI_CFG_ADR, CONFIG_CMD(dev, where));
+
+ GT_WRITE_BYTE(PCI_CFG_DATA + (where & 3), val);
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+
+static int galileo_write_config_word(struct pci_dev *dev, int where,
+ u16 val)
+{
+ GT_WRITE(PCI_CFG_ADR, CONFIG_CMD(dev, where));
+
+ GT_WRITE_SHORT(PCI_CFG_DATA + (where & 2), val);
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int galileo_write_config_dword(struct pci_dev *dev, int where,
+ u32 val)
+{
+ GT_WRITE(PCI_CFG_ADR, CONFIG_CMD(dev, where));
+
+ GT_WRITE(PCI_CFG_DATA, val);
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static struct pci_ops pci_config_ops = {
+ galileo_read_config_byte,
+ galileo_read_config_word,
+ galileo_read_config_dword,
+ galileo_write_config_byte,
+ galileo_write_config_word,
+ galileo_write_config_dword
+};
+
+
+/* Everything hangs off this */
+static struct pci_bus *pci_root_bus;
+
+
+static u8 __init no_swizzle(struct pci_dev *dev, u8 * pin)
+{
+ return PCI_SLOT(dev->devfn);
+}
+
+static int __init map_od_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+ /* Slot 1: Galileo
+ * Slot 2: PCI Slot 1
+ * Slot 3: PCI Slot 2
+ * Slot 4: ESS
+ */
+ switch (slot) {
+ case 2:
+ return OVERDRIVE_PCI_IRQ1;
+ case 3:
+ /* Note this assumes you have a hacked card in slot 2 */
+ return OVERDRIVE_PCI_IRQ2;
+ case 4:
+ return OVERDRIVE_ESS_IRQ;
+ default:
+ /* printk("PCI: Unexpected IRQ mapping request for slot %d\n", slot); */
+ return -1;
+ }
+}
+
+
+
+void __init
+pcibios_fixup_pbus_ranges(struct pci_bus *bus, struct pbus_set_ranges_data *ranges)
+{
+ ranges->io_start -= bus->resource[0]->start;
+ ranges->io_end -= bus->resource[0]->start;
+ ranges->mem_start -= bus->resource[1]->start;
+ ranges->mem_end -= bus->resource[1]->start;
+}
+
+static void __init pci_fixup_ide_bases(struct pci_dev *d)
+{
+ int i;
+
+ /*
+ * PCI IDE controllers use non-standard I/O port decoding, respect it.
+ */
+ if ((d->class >> 8) != PCI_CLASS_STORAGE_IDE)
+ return;
+ printk("PCI: IDE base address fixup for %s\n", pci_name(d));
+ for(i=0; i<4; i++) {
+ struct resource *r = &d->resource[i];
+ if ((r->start & ~0x80) == 0x374) {
+ r->start |= 2;
+ r->end = r->start;
+ }
+ }
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_ide_bases);
+
+void __init pcibios_init(void)
+{
+ static struct resource galio,galmem;
+
+ /* Allocate the registers used by the Galileo */
+ galio.flags = IORESOURCE_IO;
+ galio.name = "Galileo GT64011";
+ galmem.flags = IORESOURCE_MEM|IORESOURCE_PREFETCH;
+ galmem.name = "Galileo GT64011 DRAM";
+
+ allocate_resource(&ioport_resource, &galio, 256,
+ GT64111_IO_BASE_ADDRESS,GT64111_IO_BASE_ADDRESS+256, 256, NULL, NULL);
+ allocate_resource(&iomem_resource, &galmem,PCI_DRAM_SIZE,
+ PHYSADDR(PCI_DRAM_BASE), PHYSADDR(PCI_DRAM_BASE)+PCI_DRAM_SIZE,
+ PCI_DRAM_SIZE, NULL, NULL);
+
+ /* ok, do the scan man */
+ pci_root_bus = pci_scan_bus(0, &pci_config_ops, NULL);
+
+ pci_assign_unassigned_resources();
+ pci_fixup_irqs(no_swizzle, map_od_irq);
+
+#ifdef TEST_DRAM
+ printk("Testing PCI DRAM - ");
+ if(test_dram(PCI_DRAM_BASE,PCI_DRAM_SIZE)) {
+ printk("Passed\n");
+ }else {
+ printk("FAILED\n");
+ }
+#endif
+
+}
+
+char * __init pcibios_setup(char *str)
+{
+ return str;
+}
+
+
+
+int pcibios_enable_device(struct pci_dev *dev)
+{
+
+ u16 cmd, old_cmd;
+ int idx;
+ struct resource *r;
+
+ pci_read_config_word(dev, PCI_COMMAND, &cmd);
+ old_cmd = cmd;
+ for (idx = 0; idx < 6; idx++) {
+ r = dev->resource + idx;
+ if (!r->start && r->end) {
+ printk(KERN_ERR
+ "PCI: Device %s not available because"
+ " of resource collisions\n",
+ pci_name(dev));
+ return -EINVAL;
+ }
+ if (r->flags & IORESOURCE_IO)
+ cmd |= PCI_COMMAND_IO;
+ if (r->flags & IORESOURCE_MEM)
+ cmd |= PCI_COMMAND_MEMORY;
+ }
+ if (cmd != old_cmd) {
+ printk("PCI: enabling device %s (%04x -> %04x)\n",
+ pci_name(dev), old_cmd, cmd);
+ pci_write_config_word(dev, PCI_COMMAND, cmd);
+ }
+ return 0;
+
+}
+
+/* We should do some optimisation work here I think. Ok for now though */
+void __init pcibios_fixup_bus(struct pci_bus *bus)
+{
+
+}
+
+void pcibios_align_resource(void *data, struct resource *res,
+ unsigned long size)
+{
+}
+
+void __init pcibios_update_resource(struct pci_dev *dev, struct resource *root,
+ struct resource *res, int resource)
+{
+
+ unsigned long where, size;
+ u32 reg;
+
+
+ printk("PCI: Assigning %3s %08lx to %s\n",
+ res->flags & IORESOURCE_IO ? "IO" : "MEM",
+ res->start, dev->name);
+
+ where = PCI_BASE_ADDRESS_0 + resource * 4;
+ size = res->end - res->start;
+
+ pci_read_config_dword(dev, where, &reg);
+ reg = (reg & size) | (((u32) (res->start - root->start)) & ~size);
+ pci_write_config_dword(dev, where, reg);
+}
+
+
+void __init pcibios_update_irq(struct pci_dev *dev, int irq)
+{
+ printk("PCI: Assigning IRQ %02d to %s\n", irq, dev->name);
+ pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
+}
+
+/*
+ * If we set up a device for bus mastering, we need to check the latency
+ * timer as certain crappy BIOSes forget to set it properly.
+ */
+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("PCI: Setting latency timer of device %s to %d\n", pci_name(dev), lat);
+ pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat);
+}
diff --git a/arch/sh/boards/overdrive/io.c b/arch/sh/boards/overdrive/io.c
new file mode 100644
index 000000000000..65f3fd0563d3
--- /dev/null
+++ b/arch/sh/boards/overdrive/io.c
@@ -0,0 +1,173 @@
+/*
+ * Copyright (C) 2000 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.
+ *
+ * This file contains the I/O routines for use on the overdrive board
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/delay.h>
+#include <asm/processor.h>
+#include <asm/io.h>
+#include <asm/addrspace.h>
+
+#include <asm/overdrive/overdrive.h>
+
+/*
+ * readX/writeX() are used to access memory mapped devices. On some
+ * architectures the memory mapped IO stuff needs to be accessed
+ * differently. On the SuperH architecture, we just read/write the
+ * memory location directly.
+ */
+
+#define dprintk(x...)
+
+/* Translates an IO address to where it is mapped in memory */
+
+#define io_addr(x) (((unsigned)(x))|PCI_GTIO_BASE)
+
+unsigned char od_inb(unsigned long port)
+{
+dprintk("od_inb(%x)\n", port);
+ return readb(io_addr(port)) & 0xff;
+}
+
+
+unsigned short od_inw(unsigned long port)
+{
+dprintk("od_inw(%x)\n", port);
+ return readw(io_addr(port)) & 0xffff;
+}
+
+unsigned int od_inl(unsigned long port)
+{
+dprintk("od_inl(%x)\n", port);
+ return readl(io_addr(port));
+}
+
+void od_outb(unsigned char value, unsigned long port)
+{
+dprintk("od_outb(%x, %x)\n", value, port);
+ writeb(value, io_addr(port));
+}
+
+void od_outw(unsigned short value, unsigned long port)
+{
+dprintk("od_outw(%x, %x)\n", value, port);
+ writew(value, io_addr(port));
+}
+
+void od_outl(unsigned int value, unsigned long port)
+{
+dprintk("od_outl(%x, %x)\n", value, port);
+ writel(value, io_addr(port));
+}
+
+/* This is horrible at the moment - needs more work to do something sensible */
+#define IO_DELAY() udelay(10)
+
+#define OUT_DELAY(x,type) \
+void od_out##x##_p(unsigned type value,unsigned long port){out##x(value,port);IO_DELAY();}
+
+#define IN_DELAY(x,type) \
+unsigned type od_in##x##_p(unsigned long port) {unsigned type tmp=in##x(port);IO_DELAY();return tmp;}
+
+
+OUT_DELAY(b,char)
+OUT_DELAY(w,short)
+OUT_DELAY(l,int)
+
+IN_DELAY(b,char)
+IN_DELAY(w,short)
+IN_DELAY(l,int)
+
+
+/* Now for the string version of these functions */
+void od_outsb(unsigned long port, const void *addr, unsigned long count)
+{
+ int i;
+ unsigned char *p = (unsigned char *) addr;
+
+ for (i = 0; i < count; i++, p++) {
+ outb(*p, port);
+ }
+}
+
+
+void od_insb(unsigned long port, void *addr, unsigned long count)
+{
+ int i;
+ unsigned char *p = (unsigned char *) addr;
+
+ for (i = 0; i < count; i++, p++) {
+ *p = inb(port);
+ }
+}
+
+/* For the 16 and 32 bit string functions, we have to worry about alignment.
+ * The SH does not do unaligned accesses, so we have to read as bytes and
+ * then write as a word or dword.
+ * This can be optimised a lot more, especially in the case where the data
+ * is aligned
+ */
+
+void od_outsw(unsigned long port, const void *addr, unsigned long count)
+{
+ int i;
+ unsigned short tmp;
+ unsigned char *p = (unsigned char *) addr;
+
+ for (i = 0; i < count; i++, p += 2) {
+ tmp = (*p) | ((*(p + 1)) << 8);
+ outw(tmp, port);
+ }
+}
+
+
+void od_insw(unsigned long port, void *addr, unsigned long count)
+{
+ int i;
+ unsigned short tmp;
+ unsigned char *p = (unsigned char *) addr;
+
+ for (i = 0; i < count; i++, p += 2) {
+ tmp = inw(port);
+ p[0] = tmp & 0xff;
+ p[1] = (tmp >> 8) & 0xff;
+ }
+}
+
+
+void od_outsl(unsigned long port, const void *addr, unsigned long count)
+{
+ int i;
+ unsigned tmp;
+ unsigned char *p = (unsigned char *) addr;
+
+ for (i = 0; i < count; i++, p += 4) {
+ tmp = (*p) | ((*(p + 1)) << 8) | ((*(p + 2)) << 16) |
+ ((*(p + 3)) << 24);
+ outl(tmp, port);
+ }
+}
+
+
+void od_insl(unsigned long port, void *addr, unsigned long count)
+{
+ int i;
+ unsigned tmp;
+ unsigned char *p = (unsigned char *) addr;
+
+ for (i = 0; i < count; i++, p += 4) {
+ tmp = inl(port);
+ p[0] = tmp & 0xff;
+ p[1] = (tmp >> 8) & 0xff;
+ p[2] = (tmp >> 16) & 0xff;
+ p[3] = (tmp >> 24) & 0xff;
+
+ }
+}
diff --git a/arch/sh/boards/overdrive/irq.c b/arch/sh/boards/overdrive/irq.c
new file mode 100644
index 000000000000..23adc6be71e7
--- /dev/null
+++ b/arch/sh/boards/overdrive/irq.c
@@ -0,0 +1,192 @@
+/*
+ * Copyright (C) 2000 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.
+ *
+ * Looks after interrupts on the overdrive board.
+ *
+ * Bases on the IPR irq system
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+
+#include <asm/system.h>
+#include <asm/io.h>
+
+#include <asm/overdrive/overdrive.h>
+
+struct od_data {
+ int overdrive_irq;
+ int irq_mask;
+};
+
+#define NUM_EXTERNAL_IRQS 16
+#define EXTERNAL_IRQ_NOT_IN_USE (-1)
+#define EXTERNAL_IRQ_NOT_ASSIGNED (-1)
+
+/*
+ * This table is used to determine what to program into the FPGA's CT register
+ * for the specified Linux IRQ.
+ *
+ * The irq_mask gives the interrupt number from the PCI board (PCI_Int(6:0))
+ * but is one greater than that because the because the FPGA treats 0
+ * as disabled, a value of 1 asserts PCI_Int0, and so on.
+ *
+ * The overdrive_irq specifies which of the eight interrupt sources generates
+ * that interrupt, and but is multiplied by four to give the bit offset into
+ * the CT register.
+ *
+ * The seven interrupts levels (SH4 IRL's) we have available here is hardwired
+ * by the EPLD. The assignments here of which PCI interrupt generates each
+ * level is arbitary.
+ */
+static struct od_data od_data_table[NUM_EXTERNAL_IRQS] = {
+ /* overdrive_irq , irq_mask */
+ {EXTERNAL_IRQ_NOT_ASSIGNED, EXTERNAL_IRQ_NOT_IN_USE}, /* 0 */
+ {EXTERNAL_IRQ_NOT_ASSIGNED, 7}, /* 1 */
+ {EXTERNAL_IRQ_NOT_ASSIGNED, 6}, /* 2 */
+ {EXTERNAL_IRQ_NOT_ASSIGNED, EXTERNAL_IRQ_NOT_IN_USE}, /* 3 */
+ {EXTERNAL_IRQ_NOT_ASSIGNED, 5}, /* 4 */
+ {EXTERNAL_IRQ_NOT_ASSIGNED, EXTERNAL_IRQ_NOT_IN_USE}, /* 5 */
+ {EXTERNAL_IRQ_NOT_ASSIGNED, EXTERNAL_IRQ_NOT_IN_USE}, /* 6 */
+ {EXTERNAL_IRQ_NOT_ASSIGNED, 4}, /* 7 */
+ {EXTERNAL_IRQ_NOT_ASSIGNED, EXTERNAL_IRQ_NOT_IN_USE}, /* 8 */
+ {EXTERNAL_IRQ_NOT_ASSIGNED, EXTERNAL_IRQ_NOT_IN_USE}, /* 9 */
+ {EXTERNAL_IRQ_NOT_ASSIGNED, 3}, /* 10 */
+ {EXTERNAL_IRQ_NOT_ASSIGNED, 2}, /* 11 */
+ {EXTERNAL_IRQ_NOT_ASSIGNED, EXTERNAL_IRQ_NOT_IN_USE}, /* 12 */
+ {EXTERNAL_IRQ_NOT_ASSIGNED, 1}, /* 13 */
+ {EXTERNAL_IRQ_NOT_ASSIGNED, EXTERNAL_IRQ_NOT_IN_USE}, /* 14 */
+ {EXTERNAL_IRQ_NOT_ASSIGNED, EXTERNAL_IRQ_NOT_IN_USE} /* 15 */
+};
+
+static void set_od_data(int overdrive_irq, int irq)
+{
+ if (irq >= NUM_EXTERNAL_IRQS || irq < 0)
+ return;
+ od_data_table[irq].overdrive_irq = overdrive_irq << 2;
+}
+
+static void enable_od_irq(unsigned int irq);
+void disable_od_irq(unsigned int irq);
+
+/* shutdown is same as "disable" */
+#define shutdown_od_irq disable_od_irq
+
+static void mask_and_ack_od(unsigned int);
+static void end_od_irq(unsigned int irq);
+
+static unsigned int startup_od_irq(unsigned int irq)
+{
+ enable_od_irq(irq);
+ return 0; /* never anything pending */
+}
+
+static struct hw_interrupt_type od_irq_type = {
+ "Overdrive-IRQ",
+ startup_od_irq,
+ shutdown_od_irq,
+ enable_od_irq,
+ disable_od_irq,
+ mask_and_ack_od,
+ end_od_irq
+};
+
+static void disable_od_irq(unsigned int irq)
+{
+ unsigned val, flags;
+ int overdrive_irq;
+ unsigned mask;
+
+ /* Not a valid interrupt */
+ if (irq < 0 || irq >= NUM_EXTERNAL_IRQS)
+ return;
+
+ /* Is is necessary to use a cli here? Would a spinlock not be
+ * mroe efficient?
+ */
+ local_irq_save(flags);
+ overdrive_irq = od_data_table[irq].overdrive_irq;
+ if (overdrive_irq != EXTERNAL_IRQ_NOT_ASSIGNED) {
+ mask = ~(0x7 << overdrive_irq);
+ val = ctrl_inl(OVERDRIVE_INT_CT);
+ val &= mask;
+ ctrl_outl(val, OVERDRIVE_INT_CT);
+ }
+ local_irq_restore(flags);
+}
+
+static void enable_od_irq(unsigned int irq)
+{
+ unsigned val, flags;
+ int overdrive_irq;
+ unsigned mask;
+
+ /* Not a valid interrupt */
+ if (irq < 0 || irq >= NUM_EXTERNAL_IRQS)
+ return;
+
+ /* Set priority in OD back to original value */
+ local_irq_save(flags);
+ /* This one is not in use currently */
+ overdrive_irq = od_data_table[irq].overdrive_irq;
+ if (overdrive_irq != EXTERNAL_IRQ_NOT_ASSIGNED) {
+ val = ctrl_inl(OVERDRIVE_INT_CT);
+ mask = ~(0x7 << overdrive_irq);
+ val &= mask;
+ mask = od_data_table[irq].irq_mask << overdrive_irq;
+ val |= mask;
+ ctrl_outl(val, OVERDRIVE_INT_CT);
+ }
+ local_irq_restore(flags);
+}
+
+
+
+/* this functions sets the desired irq handler to be an overdrive type */
+static void __init make_od_irq(unsigned int irq)
+{
+ disable_irq_nosync(irq);
+ irq_desc[irq].handler = &od_irq_type;
+ disable_od_irq(irq);
+}
+
+
+static void mask_and_ack_od(unsigned int irq)
+{
+ disable_od_irq(irq);
+}
+
+static void end_od_irq(unsigned int irq)
+{
+ enable_od_irq(irq);
+}
+
+void __init init_overdrive_irq(void)
+{
+ int i;
+
+ /* Disable all interrupts */
+ ctrl_outl(0, OVERDRIVE_INT_CT);
+
+ /* Update interrupt pin mode to use encoded interrupts */
+ i = ctrl_inw(INTC_ICR);
+ i &= ~INTC_ICR_IRLM;
+ ctrl_outw(i, INTC_ICR);
+
+ for (i = 0; i < NUM_EXTERNAL_IRQS; i++) {
+ if (od_data_table[i].irq_mask != EXTERNAL_IRQ_NOT_IN_USE) {
+ make_od_irq(i);
+ } else if (i != 15) { // Cannot use imask on level 15
+ make_imask_irq(i);
+ }
+ }
+
+ /* Set up the interrupts */
+ set_od_data(OVERDRIVE_PCI_INTA, OVERDRIVE_PCI_IRQ1);
+ set_od_data(OVERDRIVE_PCI_INTB, OVERDRIVE_PCI_IRQ2);
+ set_od_data(OVERDRIVE_AUDIO_INT, OVERDRIVE_ESS_IRQ);
+}
diff --git a/arch/sh/boards/overdrive/led.c b/arch/sh/boards/overdrive/led.c
new file mode 100644
index 000000000000..734742e92279
--- /dev/null
+++ b/arch/sh/boards/overdrive/led.c
@@ -0,0 +1,59 @@
+/*
+ * linux/arch/sh/overdrive/led.c
+ *
+ * Copyright (C) 1999 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.
+ *
+ * This file contains an Overdrive specific LED feature.
+ */
+
+#include <linux/config.h>
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/overdrive/overdrive.h>
+
+static void mach_led(int position, int value)
+{
+ unsigned long flags;
+ unsigned long reg;
+
+ local_irq_save(flags);
+
+ reg = readl(OVERDRIVE_CTRL);
+ if (value) {
+ reg |= (1<<3);
+ } else {
+ reg &= ~(1<<3);
+ }
+ writel(reg, OVERDRIVE_CTRL);
+
+ local_irq_restore(flags);
+}
+
+#ifdef CONFIG_HEARTBEAT
+
+#include <linux/sched.h>
+
+/* acts like an actual heart beat -- ie thump-thump-pause... */
+void heartbeat_od(void)
+{
+ static unsigned 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;
+ }
+}
+#endif /* CONFIG_HEARTBEAT */
diff --git a/arch/sh/boards/overdrive/mach.c b/arch/sh/boards/overdrive/mach.c
new file mode 100644
index 000000000000..2834a03ae477
--- /dev/null
+++ b/arch/sh/boards/overdrive/mach.c
@@ -0,0 +1,62 @@
+/*
+ * linux/arch/sh/overdrive/mach.c
+ *
+ * Copyright (C) 2000 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 vector for the STMicroelectronics Overdrive
+ */
+
+#include <linux/init.h>
+
+#include <asm/machvec.h>
+#include <asm/rtc.h>
+#include <asm/machvec_init.h>
+
+#include <asm/io_unknown.h>
+#include <asm/io_generic.h>
+#include <asm/overdrive/io.h>
+
+void heartbeat_od(void);
+void init_overdrive_irq(void);
+void galileo_pcibios_init(void);
+
+/*
+ * The Machine Vector
+ */
+
+struct sh_machine_vector mv_od __initmv = {
+ .mv_nr_irqs = 48,
+
+ .mv_inb = od_inb,
+ .mv_inw = od_inw,
+ .mv_inl = od_inl,
+ .mv_outb = od_outb,
+ .mv_outw = od_outw,
+ .mv_outl = od_outl,
+
+ .mv_inb_p = od_inb_p,
+ .mv_inw_p = od_inw_p,
+ .mv_inl_p = od_inl_p,
+ .mv_outb_p = od_outb_p,
+ .mv_outw_p = od_outw_p,
+ .mv_outl_p = od_outl_p,
+
+ .mv_insb = od_insb,
+ .mv_insw = od_insw,
+ .mv_insl = od_insl,
+ .mv_outsb = od_outsb,
+ .mv_outsw = od_outsw,
+ .mv_outsl = od_outsl,
+
+#ifdef CONFIG_PCI
+ .mv_init_irq = init_overdrive_irq,
+#endif
+#ifdef CONFIG_HEARTBEAT
+ .mv_heartbeat = heartbeat_od,
+#endif
+};
+
+ALIAS_MV(od)
diff --git a/arch/sh/boards/overdrive/pcidma.c b/arch/sh/boards/overdrive/pcidma.c
new file mode 100644
index 000000000000..1c9bfeda00b7
--- /dev/null
+++ b/arch/sh/boards/overdrive/pcidma.c
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2000 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.
+ *
+ * Dynamic DMA mapping support.
+ *
+ * On the overdrive, we can only DMA from memory behind the PCI bus!
+ * this means that all DMA'able memory must come from there.
+ * this restriction will not apply to later boards.
+ */
+
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/string.h>
+#include <linux/pci.h>
+#include <asm/io.h>
+
+void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size,
+ dma_addr_t * dma_handle)
+{
+ void *ret;
+ int gfp = GFP_ATOMIC;
+
+ printk("BUG: pci_alloc_consistent() called - not yet supported\n");
+ /* We ALWAYS need DMA memory on the overdrive hardware,
+ * due to it's extreme weirdness
+ * Need to flush the cache here as well, since the memory
+ * can still be seen through the cache!
+ */
+ gfp |= GFP_DMA;
+ ret = (void *) __get_free_pages(gfp, get_order(size));
+
+ if (ret != NULL) {
+ memset(ret, 0, size);
+ *dma_handle = virt_to_bus(ret);
+ }
+ return ret;
+}
+
+void pci_free_consistent(struct pci_dev *hwdev, size_t size,
+ void *vaddr, dma_addr_t dma_handle)
+{
+ free_pages((unsigned long) vaddr, get_order(size));
+}
diff --git a/arch/sh/boards/overdrive/setup.c b/arch/sh/boards/overdrive/setup.c
new file mode 100644
index 000000000000..a36ce0284ed3
--- /dev/null
+++ b/arch/sh/boards/overdrive/setup.c
@@ -0,0 +1,41 @@
+/*
+ * arch/sh/overdrive/setup.c
+ *
+ * Copyright (C) 2000 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.
+ *
+ * STMicroelectronics Overdrive Support.
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <asm/io.h>
+
+#include <asm/overdrive/overdrive.h>
+#include <asm/overdrive/fpga.h>
+
+extern void od_time_init(void);
+
+const char *get_system_type(void)
+{
+ return "SH7750 Overdrive";
+}
+
+/*
+ * Initialize the board
+ */
+int __init platform_setup(void)
+{
+#ifdef CONFIG_PCI
+ init_overdrive_fpga();
+ galileo_init();
+#endif
+
+ board_time_init = od_time_init;
+
+ /* Enable RS232 receive buffers */
+ writel(0x1e, OVERDRIVE_CTRL);
+}
diff --git a/arch/sh/boards/overdrive/time.c b/arch/sh/boards/overdrive/time.c
new file mode 100644
index 000000000000..68533690e097
--- /dev/null
+++ b/arch/sh/boards/overdrive/time.c
@@ -0,0 +1,119 @@
+/*
+ * arch/sh/boards/overdrive/time.c
+ *
+ * Copyright (C) 2000 Stuart Menefy (stuart.menefy@st.com)
+ * Copyright (C) 2002 Paul Mundt (lethal@chaoticdreams.org)
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License. See linux/COPYING for more information.
+ *
+ * STMicroelectronics Overdrive Support.
+ */
+
+void od_time_init(void)
+{
+ struct frqcr_data {
+ unsigned short frqcr;
+ struct {
+ unsigned char multiplier;
+ unsigned char divisor;
+ } factor[3];
+ };
+
+ static struct frqcr_data st40_frqcr_table[] = {
+ { 0x000, {{1,1}, {1,1}, {1,2}}},
+ { 0x002, {{1,1}, {1,1}, {1,4}}},
+ { 0x004, {{1,1}, {1,1}, {1,8}}},
+ { 0x008, {{1,1}, {1,2}, {1,2}}},
+ { 0x00A, {{1,1}, {1,2}, {1,4}}},
+ { 0x00C, {{1,1}, {1,2}, {1,8}}},
+ { 0x011, {{1,1}, {2,3}, {1,6}}},
+ { 0x013, {{1,1}, {2,3}, {1,3}}},
+ { 0x01A, {{1,1}, {1,2}, {1,4}}},
+ { 0x01C, {{1,1}, {1,2}, {1,8}}},
+ { 0x023, {{1,1}, {2,3}, {1,3}}},
+ { 0x02C, {{1,1}, {1,2}, {1,8}}},
+ { 0x048, {{1,2}, {1,2}, {1,4}}},
+ { 0x04A, {{1,2}, {1,2}, {1,6}}},
+ { 0x04C, {{1,2}, {1,2}, {1,8}}},
+ { 0x05A, {{1,2}, {1,3}, {1,6}}},
+ { 0x05C, {{1,2}, {1,3}, {1,6}}},
+ { 0x063, {{1,2}, {1,4}, {1,4}}},
+ { 0x06C, {{1,2}, {1,4}, {1,8}}},
+ { 0x091, {{1,3}, {1,3}, {1,6}}},
+ { 0x093, {{1,3}, {1,3}, {1,6}}},
+ { 0x0A3, {{1,3}, {1,6}, {1,6}}},
+ { 0x0DA, {{1,4}, {1,4}, {1,8}}},
+ { 0x0DC, {{1,4}, {1,4}, {1,8}}},
+ { 0x0EC, {{1,4}, {1,8}, {1,8}}},
+ { 0x123, {{1,4}, {1,4}, {1,8}}},
+ { 0x16C, {{1,4}, {1,8}, {1,8}}},
+ };
+
+ struct memclk_data {
+ unsigned char multiplier;
+ unsigned char divisor;
+ };
+ static struct memclk_data st40_memclk_table[8] = {
+ {1,1}, // 000
+ {1,2}, // 001
+ {1,3}, // 010
+ {2,3}, // 011
+ {1,4}, // 100
+ {1,6}, // 101
+ {1,8}, // 110
+ {1,8} // 111
+ };
+
+ unsigned long pvr;
+
+ /*
+ * This should probably be moved into the SH3 probing code, and then
+ * use the processor structure to determine which CPU we are running
+ * on.
+ */
+ pvr = ctrl_inl(CCN_PVR);
+ printk("PVR %08x\n", pvr);
+
+ if (((pvr >> CCN_PVR_CHIP_SHIFT) & CCN_PVR_CHIP_MASK) == CCN_PVR_CHIP_ST40STB1) {
+ /*
+ * Unfortunatly the STB1 FRQCR values are different from the
+ * 7750 ones.
+ */
+ struct frqcr_data *d;
+ int a;
+ unsigned long memclkcr;
+ struct memclk_data *e;
+
+ for (a=0; a<ARRAY_SIZE(st40_frqcr_table); a++) {
+ d = &st40_frqcr_table[a];
+ if (d->frqcr == (frqcr & 0x1ff))
+ break;
+ }
+ if (a == ARRAY_SIZE(st40_frqcr_table)) {
+ d = st40_frqcr_table;
+ printk("ERROR: Unrecognised FRQCR value, using default multipliers\n");
+ }
+
+ memclkcr = ctrl_inl(CLOCKGEN_MEMCLKCR);
+ e = &st40_memclk_table[memclkcr & MEMCLKCR_RATIO_MASK];
+
+ printk("Clock multipliers: CPU: %d/%d Bus: %d/%d Mem: %d/%d Periph: %d/%d\n",
+ d->factor[0].multiplier, d->factor[0].divisor,
+ d->factor[1].multiplier, d->factor[1].divisor,
+ e->multiplier, e->divisor,
+ d->factor[2].multiplier, d->factor[2].divisor);
+
+ current_cpu_data.master_clock = current_cpu_data.module_clock *
+ d->factor[2].divisor /
+ d->factor[2].multiplier;
+ current_cpu_data.bus_clock = current_cpu_data.master_clock *
+ d->factor[1].multiplier /
+ d->factor[1].divisor;
+ current_cpu_data.memory_clock = current_cpu_data.master_clock *
+ e->multiplier / e->divisor;
+ current_cpu_data.cpu_clock = current_cpu_data.master_clock *
+ d->factor[0].multiplier /
+ d->factor[0].divisor;
+}
+
diff --git a/arch/sh/boards/renesas/edosk7705/Makefile b/arch/sh/boards/renesas/edosk7705/Makefile
new file mode 100644
index 000000000000..7fccbf2e4a1d
--- /dev/null
+++ b/arch/sh/boards/renesas/edosk7705/Makefile
@@ -0,0 +1,10 @@
+#
+# Makefile for the EDOSK7705 specific parts of the 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).
+#
+
+obj-y := setup.o io.o
+
diff --git a/arch/sh/boards/renesas/edosk7705/io.c b/arch/sh/boards/renesas/edosk7705/io.c
new file mode 100644
index 000000000000..541cea2a652f
--- /dev/null
+++ b/arch/sh/boards/renesas/edosk7705/io.c
@@ -0,0 +1,94 @@
+/*
+ * arch/sh/boards/renesas/edosk7705/io.c
+ *
+ * Copyright (C) 2001 Ian da Silva, Jeremy Siegel
+ * Based largely on io_se.c.
+ *
+ * I/O routines for Hitachi EDOSK7705 board.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <asm/io.h>
+#include <asm/edosk7705/io.h>
+#include <asm/addrspace.h>
+
+#define SMC_IOADDR 0xA2000000
+
+#define maybebadio(name,port) \
+ printk("bad PC-like io %s for port 0x%lx at 0x%08x\n", \
+ #name, (port), (__u32) __builtin_return_address(0))
+
+/* Map the Ethernet addresses as if it is at 0x300 - 0x320 */
+unsigned long sh_edosk7705_isa_port2addr(unsigned long port)
+{
+ if (port >= 0x300 && port < 0x320) {
+ /* SMC91C96 registers are 4 byte aligned rather than the
+ * usual 2 byte!
+ */
+ return SMC_IOADDR + ( (port - 0x300) * 2);
+ }
+
+ maybebadio(sh_edosk7705_isa_port2addr, port);
+ return port;
+}
+
+/* Trying to read / write bytes on odd-byte boundaries to the Ethernet
+ * registers causes problems. So we bit-shift the value and read / write
+ * in 2 byte chunks. Setting the low byte to 0 does not cause problems
+ * now as odd byte writes are only made on the bit mask / interrupt
+ * register. This may not be the case in future Mar-2003 SJD
+ */
+unsigned char sh_edosk7705_inb(unsigned long port)
+{
+ if (port >= 0x300 && port < 0x320 && port & 0x01) {
+ return (volatile unsigned char)(generic_inw(port -1) >> 8);
+ }
+ return *(volatile unsigned char *)sh_edosk7705_isa_port2addr(port);
+}
+
+unsigned int sh_edosk7705_inl(unsigned long port)
+{
+ return *(volatile unsigned long *)port;
+}
+
+void sh_edosk7705_outb(unsigned char value, unsigned long port)
+{
+ if (port >= 0x300 && port < 0x320 && port & 0x01) {
+ generic_outw(((unsigned short)value << 8), port -1);
+ return;
+ }
+ *(volatile unsigned char *)sh_edosk7705_isa_port2addr(port) = value;
+}
+
+void sh_edosk7705_outl(unsigned int value, unsigned long port)
+{
+ *(volatile unsigned long *)port = value;
+}
+
+void sh_edosk7705_insb(unsigned long port, void *addr, unsigned long count)
+{
+ unsigned char *p = addr;
+ while (count--) *p++ = sh_edosk7705_inb(port);
+}
+
+void sh_edosk7705_insl(unsigned long port, void *addr, unsigned long count)
+{
+ unsigned long *p = (unsigned long*)addr;
+ while (count--)
+ *p++ = *(volatile unsigned long *)port;
+}
+
+void sh_edosk7705_outsb(unsigned long port, const void *addr, unsigned long count)
+{
+ unsigned char *p = (unsigned char*)addr;
+ while (count--) sh_edosk7705_outb(*p++, port);
+}
+
+void sh_edosk7705_outsl(unsigned long port, const void *addr, unsigned long count)
+{
+ unsigned long *p = (unsigned long*)addr;
+ while (count--) sh_edosk7705_outl(*p++, port);
+}
+
diff --git a/arch/sh/boards/renesas/edosk7705/setup.c b/arch/sh/boards/renesas/edosk7705/setup.c
new file mode 100644
index 000000000000..8b6f0c2af092
--- /dev/null
+++ b/arch/sh/boards/renesas/edosk7705/setup.c
@@ -0,0 +1,60 @@
+/*
+ * arch/sh/boards/renesas/edosk7705/setup.c
+ *
+ * Copyright (C) 2000 Kazumoto Kojima
+ *
+ * Hitachi SolutionEngine Support.
+ *
+ * Modified for edosk7705 development
+ * board by S. Dunn, 2003.
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <asm/machvec.h>
+#include <asm/machvec_init.h>
+#include <asm/edosk7705/io.h>
+
+static void init_edosk7705(void);
+
+/*
+ * The Machine Vector
+ */
+
+struct sh_machine_vector mv_edosk7705 __initmv = {
+ .mv_nr_irqs = 80,
+
+ .mv_inb = sh_edosk7705_inb,
+ .mv_inl = sh_edosk7705_inl,
+ .mv_outb = sh_edosk7705_outb,
+ .mv_outl = sh_edosk7705_outl,
+
+ .mv_inl_p = sh_edosk7705_inl,
+ .mv_outl_p = sh_edosk7705_outl,
+
+ .mv_insb = sh_edosk7705_insb,
+ .mv_insl = sh_edosk7705_insl,
+ .mv_outsb = sh_edosk7705_outsb,
+ .mv_outsl = sh_edosk7705_outsl,
+
+ .mv_isa_port2addr = sh_edosk7705_isa_port2addr,
+ .mv_init_irq = init_edosk7705,
+};
+ALIAS_MV(edosk7705)
+
+static void __init init_edosk7705(void)
+{
+ /* This is the Ethernet interrupt */
+ make_imask_irq(0x09);
+}
+
+const char *get_system_type(void)
+{
+ return "EDOSK7705";
+}
+
+void __init platform_setup(void)
+{
+ /* Nothing .. */
+}
+
diff --git a/arch/sh/boards/renesas/hs7751rvoip/Makefile b/arch/sh/boards/renesas/hs7751rvoip/Makefile
new file mode 100644
index 000000000000..e8b4109ace11
--- /dev/null
+++ b/arch/sh/boards/renesas/hs7751rvoip/Makefile
@@ -0,0 +1,12 @@
+#
+# Makefile for the HS7751RVoIP specific parts of the 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).
+#
+
+obj-y := mach.o setup.o io.o irq.o led.o
+
+obj-$(CONFIG_PCI) += pci.o
+
diff --git a/arch/sh/boards/renesas/hs7751rvoip/io.c b/arch/sh/boards/renesas/hs7751rvoip/io.c
new file mode 100644
index 000000000000..456753d2649c
--- /dev/null
+++ b/arch/sh/boards/renesas/hs7751rvoip/io.c
@@ -0,0 +1,310 @@
+/*
+ * linux/arch/sh/kernel/io_hs7751rvoip.c
+ *
+ * Copyright (C) 2001 Ian da Silva, Jeremy Siegel
+ * Based largely on io_se.c.
+ *
+ * I/O routine for Renesas Technology sales HS7751RVoIP
+ *
+ * Initial version only to support LAN access; some
+ * placeholder code from io_hs7751rvoip.c left in with the
+ * expectation of later SuperIO and PCMCIA access.
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <asm/io.h>
+#include <asm/hs7751rvoip/hs7751rvoip.h>
+#include <asm/addrspace.h>
+
+#include <linux/module.h>
+#include <linux/pci.h>
+#include "../../../drivers/pci/pci-sh7751.h"
+
+extern void *area5_io8_base; /* Area 5 8bit I/O Base address */
+extern void *area6_io8_base; /* Area 6 8bit I/O Base address */
+extern void *area5_io16_base; /* Area 5 16bit I/O Base address */
+extern void *area6_io16_base; /* Area 6 16bit I/O Base address */
+
+/*
+ * The 7751R HS7751RVoIP uses the built-in PCI controller (PCIC)
+ * of the 7751R processor, and has a SuperIO accessible via the PCI.
+ * The board also includes a PCMCIA controller on its memory bus,
+ * like the other Solution Engine boards.
+ */
+
+#define PCIIOBR (volatile long *)PCI_REG(SH7751_PCIIOBR)
+#define PCIMBR (volatile long *)PCI_REG(SH7751_PCIMBR)
+#define PCI_IO_AREA SH7751_PCI_IO_BASE
+#define PCI_MEM_AREA SH7751_PCI_CONFIG_BASE
+
+#define PCI_IOMAP(adr) (PCI_IO_AREA + (adr & ~SH7751_PCIIOBR_MASK))
+
+#if defined(CONFIG_HS7751RVOIP_CODEC)
+#define CODEC_IO_BASE 0x1000
+#endif
+
+#define maybebadio(name,port) \
+ printk("bad PC-like io %s for port 0x%lx at 0x%08x\n", \
+ #name, (port), (__u32) __builtin_return_address(0))
+
+static inline void delay(void)
+{
+ ctrl_inw(0xa0000000);
+}
+
+static inline unsigned long port2adr(unsigned int port)
+{
+ if ((0x1f0 <= port && port < 0x1f8) || port == 0x3f6)
+ if (port == 0x3f6)
+ return ((unsigned long)area5_io16_base + 0x0c);
+ else
+ return ((unsigned long)area5_io16_base + 0x800 + ((port-0x1f0) << 1));
+ else
+ maybebadio(port2adr, (unsigned long)port);
+ return port;
+}
+
+/* The 7751R HS7751RVoIP seems to have everything hooked */
+/* up pretty normally (nothing on high-bytes only...) so this */
+/* shouldn't be needed */
+static inline int shifted_port(unsigned long port)
+{
+ /* For IDE registers, value is not shifted */
+ if ((0x1f0 <= port && port < 0x1f8) || port == 0x3f6)
+ return 0;
+ else
+ return 1;
+}
+
+#if defined(CONFIG_HS7751RVOIP_CODEC)
+static inline int
+codec_port(unsigned long port)
+{
+ if (CODEC_IO_BASE <= port && port < (CODEC_IO_BASE+0x20))
+ return 1;
+ else
+ return 0;
+}
+#endif
+
+/* In case someone configures the kernel w/o PCI support: in that */
+/* scenario, don't ever bother to check for PCI-window addresses */
+
+/* NOTE: WINDOW CHECK MAY BE A BIT OFF, HIGH PCIBIOS_MIN_IO WRAPS? */
+#if defined(CONFIG_PCI)
+#define CHECK_SH7751_PCIIO(port) \
+ ((port >= PCIBIOS_MIN_IO) && (port < (PCIBIOS_MIN_IO + SH7751_PCI_IO_SIZE)))
+#else
+#define CHECK_SH7751_PCIIO(port) (0)
+#endif
+
+/*
+ * General outline: remap really low stuff [eventually] to SuperIO,
+ * stuff in PCI IO space (at or above window at pci.h:PCIBIOS_MIN_IO)
+ * is mapped through the PCI IO window. Stuff with high bits (PXSEG)
+ * should be way beyond the window, and is used w/o translation for
+ * compatibility.
+ */
+unsigned char hs7751rvoip_inb(unsigned long port)
+{
+ if (PXSEG(port))
+ return *(volatile unsigned char *)port;
+#if defined(CONFIG_HS7751RVOIP_CODEC)
+ else if (codec_port(port))
+ return *(volatile unsigned char *)((unsigned long)area6_io8_base+(port-CODEC_IO_BASE));
+#endif
+ else if (CHECK_SH7751_PCIIO(port) || shifted_port(port))
+ return *(volatile unsigned char *)PCI_IOMAP(port);
+ else
+ return (*(volatile unsigned short *)port2adr(port) & 0xff);
+}
+
+unsigned char hs7751rvoip_inb_p(unsigned long port)
+{
+ unsigned char v;
+
+ if (PXSEG(port))
+ v = *(volatile unsigned char *)port;
+#if defined(CONFIG_HS7751RVOIP_CODEC)
+ else if (codec_port(port))
+ v = *(volatile unsigned char *)((unsigned long)area6_io8_base+(port-CODEC_IO_BASE));
+#endif
+ else if (CHECK_SH7751_PCIIO(port) || shifted_port(port))
+ v = *(volatile unsigned char *)PCI_IOMAP(port);
+ else
+ v = (*(volatile unsigned short *)port2adr(port) & 0xff);
+ delay();
+ return v;
+}
+
+unsigned short hs7751rvoip_inw(unsigned long port)
+{
+ if (PXSEG(port))
+ return *(volatile unsigned short *)port;
+ else if (CHECK_SH7751_PCIIO(port) || shifted_port(port))
+ return *(volatile unsigned short *)PCI_IOMAP(port);
+ else
+ maybebadio(inw, port);
+ return 0;
+}
+
+unsigned int hs7751rvoip_inl(unsigned long port)
+{
+ if (PXSEG(port))
+ return *(volatile unsigned long *)port;
+ else if (CHECK_SH7751_PCIIO(port) || shifted_port(port))
+ return *(volatile unsigned long *)PCI_IOMAP(port);
+ else
+ maybebadio(inl, port);
+ return 0;
+}
+
+void hs7751rvoip_outb(unsigned char value, unsigned long port)
+{
+
+ if (PXSEG(port))
+ *(volatile unsigned char *)port = value;
+#if defined(CONFIG_HS7751RVOIP_CODEC)
+ else if (codec_port(port))
+ *(volatile unsigned cjar *)((unsigned long)area6_io8_base+(port-CODEC_IO_BASE)) = value;
+#endif
+ else if (CHECK_SH7751_PCIIO(port) || shifted_port(port))
+ *(unsigned char *)PCI_IOMAP(port) = value;
+ else
+ *(volatile unsigned short *)port2adr(port) = value;
+}
+
+void hs7751rvoip_outb_p(unsigned char value, unsigned long port)
+{
+ if (PXSEG(port))
+ *(volatile unsigned char *)port = value;
+#if defined(CONFIG_HS7751RVOIP_CODEC)
+ else if (codec_port(port))
+ *(volatile unsigned cjar *)((unsigned long)area6_io8_base+(port-CODEC_IO_BASE)) = value;
+#endif
+ else if (CHECK_SH7751_PCIIO(port) || shifted_port(port))
+ *(unsigned char *)PCI_IOMAP(port) = value;
+ else
+ *(volatile unsigned short *)port2adr(port) = value;
+ delay();
+}
+
+void hs7751rvoip_outw(unsigned short value, unsigned long port)
+{
+ if (PXSEG(port))
+ *(volatile unsigned short *)port = value;
+ else if (CHECK_SH7751_PCIIO(port) || shifted_port(port))
+ *(unsigned short *)PCI_IOMAP(port) = value;
+ else
+ maybebadio(outw, port);
+}
+
+void hs7751rvoip_outl(unsigned int value, unsigned long port)
+{
+ if (PXSEG(port))
+ *(volatile unsigned long *)port = value;
+ else if (CHECK_SH7751_PCIIO(port) || shifted_port(port))
+ *((unsigned long *)PCI_IOMAP(port)) = value;
+ else
+ maybebadio(outl, port);
+}
+
+void hs7751rvoip_insb(unsigned long port, void *addr, unsigned long count)
+{
+ if (PXSEG(port))
+ while (count--) *((unsigned char *) addr)++ = *(volatile unsigned char *)port;
+#if defined(CONFIG_HS7751RVOIP_CODEC)
+ else if (codec_port(port))
+ while (count--) *((unsigned char *) addr)++ = *(volatile unsigned char *)((unsigned long)area6_io8_base+(port-CODEC_IO_BASE));
+#endif
+ else if (CHECK_SH7751_PCIIO(port) || shifted_port(port)) {
+ volatile __u8 *bp = (__u8 *)PCI_IOMAP(port);
+
+ while (count--) *((volatile unsigned char *) addr)++ = *bp;
+ } else {
+ volatile __u16 *p = (volatile unsigned short *)port2adr(port);
+
+ while (count--) *((unsigned char *) addr)++ = *p & 0xff;
+ }
+}
+
+void hs7751rvoip_insw(unsigned long port, void *addr, unsigned long count)
+{
+ volatile __u16 *p;
+
+ if (PXSEG(port))
+ p = (volatile unsigned short *)port;
+ else if (CHECK_SH7751_PCIIO(port) || shifted_port(port))
+ p = (volatile unsigned short *)PCI_IOMAP(port);
+ else
+ p = (volatile unsigned short *)port2adr(port);
+ while (count--) *((__u16 *) addr)++ = *p;
+}
+
+void hs7751rvoip_insl(unsigned long port, void *addr, unsigned long count)
+{
+ if (CHECK_SH7751_PCIIO(port) || shifted_port(port)) {
+ volatile __u32 *p = (__u32 *)PCI_IOMAP(port);
+
+ while (count--) *((__u32 *) addr)++ = *p;
+ } else
+ maybebadio(insl, port);
+}
+
+void hs7751rvoip_outsb(unsigned long port, const void *addr, unsigned long count)
+{
+ if (PXSEG(port))
+ while (count--) *(volatile unsigned char *)port = *((unsigned char *) addr)++;
+#if defined(CONFIG_HS7751RVOIP_CODEC)
+ else if (codec_port(port))
+ while (count--) *(volatile unsigned char *)((unsigned long)area6_io8_base+(port-CODEC_IO_BASE)) = *((unsigned char *) addr)++;
+#endif
+ else if (CHECK_SH7751_PCIIO(port) || shifted_port(port)) {
+ volatile __u8 *bp = (__u8 *)PCI_IOMAP(port);
+
+ while (count--) *bp = *((volatile unsigned char *) addr)++;
+ } else {
+ volatile __u16 *p = (volatile unsigned short *)port2adr(port);
+
+ while (count--) *p = *((unsigned char *) addr)++;
+ }
+}
+
+void hs7751rvoip_outsw(unsigned long port, const void *addr, unsigned long count)
+{
+ volatile __u16 *p;
+
+ if (PXSEG(port))
+ p = (volatile unsigned short *)port;
+ else if (CHECK_SH7751_PCIIO(port) || shifted_port(port))
+ p = (volatile unsigned short *)PCI_IOMAP(port);
+ else
+ p = (volatile unsigned short *)port2adr(port);
+ while (count--) *p = *((__u16 *) addr)++;
+}
+
+void hs7751rvoip_outsl(unsigned long port, const void *addr, unsigned long count)
+{
+ if (CHECK_SH7751_PCIIO(port) || shifted_port(port)) {
+ volatile __u32 *p = (__u32 *)PCI_IOMAP(port);
+
+ while (count--) *p = *((__u32 *) addr)++;
+ } else
+ maybebadio(outsl, port);
+}
+
+void *hs7751rvoip_ioremap(unsigned long offset, unsigned long size)
+{
+ if (offset >= 0xfd000000)
+ return (void *)offset;
+ else
+ return (void *)P2SEGADDR(offset);
+}
+EXPORT_SYMBOL(hs7751rvoip_ioremap);
+
+unsigned long hs7751rvoip_isa_port2addr(unsigned long offset)
+{
+ return port2adr(offset);
+}
diff --git a/arch/sh/boards/renesas/hs7751rvoip/irq.c b/arch/sh/boards/renesas/hs7751rvoip/irq.c
new file mode 100644
index 000000000000..a7921f67a35f
--- /dev/null
+++ b/arch/sh/boards/renesas/hs7751rvoip/irq.c
@@ -0,0 +1,122 @@
+/*
+ * linux/arch/sh/boards/renesas/hs7751rvoip/irq.c
+ *
+ * Copyright (C) 2000 Kazumoto Kojima
+ *
+ * Renesas Technology Sales HS7751RVoIP Support.
+ *
+ * Modified for HS7751RVoIP by
+ * Atom Create Engineering Co., Ltd. 2002.
+ * Lineo uSolutions, Inc. 2003.
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/hs7751rvoip/hs7751rvoip.h>
+
+static int mask_pos[] = {8, 9, 10, 11, 12, 13, 0, 1, 2, 3, 4, 5, 6, 7};
+
+static void enable_hs7751rvoip_irq(unsigned int irq);
+static void disable_hs7751rvoip_irq(unsigned int irq);
+
+/* shutdown is same as "disable" */
+#define shutdown_hs7751rvoip_irq disable_hs7751rvoip_irq
+
+static void ack_hs7751rvoip_irq(unsigned int irq);
+static void end_hs7751rvoip_irq(unsigned int irq);
+
+static unsigned int startup_hs7751rvoip_irq(unsigned int irq)
+{
+ enable_hs7751rvoip_irq(irq);
+ return 0; /* never anything pending */
+}
+
+static void disable_hs7751rvoip_irq(unsigned int irq)
+{
+ unsigned long flags;
+ unsigned short val;
+ unsigned short mask = 0xffff ^ (0x0001 << mask_pos[irq]);
+
+ /* Set the priority in IPR to 0 */
+ local_irq_save(flags);
+ val = ctrl_inw(IRLCNTR3);
+ val &= mask;
+ ctrl_outw(val, IRLCNTR3);
+ local_irq_restore(flags);
+}
+
+static void enable_hs7751rvoip_irq(unsigned int irq)
+{
+ unsigned long flags;
+ unsigned short val;
+ unsigned short value = (0x0001 << mask_pos[irq]);
+
+ /* Set priority in IPR back to original value */
+ local_irq_save(flags);
+ val = ctrl_inw(IRLCNTR3);
+ val |= value;
+ ctrl_outw(val, IRLCNTR3);
+ local_irq_restore(flags);
+}
+
+static void ack_hs7751rvoip_irq(unsigned int irq)
+{
+ disable_hs7751rvoip_irq(irq);
+}
+
+static void end_hs7751rvoip_irq(unsigned int irq)
+{
+ if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+ enable_hs7751rvoip_irq(irq);
+}
+
+static struct hw_interrupt_type hs7751rvoip_irq_type = {
+ "HS7751RVoIP IRQ",
+ startup_hs7751rvoip_irq,
+ shutdown_hs7751rvoip_irq,
+ enable_hs7751rvoip_irq,
+ disable_hs7751rvoip_irq,
+ ack_hs7751rvoip_irq,
+ end_hs7751rvoip_irq,
+};
+
+static void make_hs7751rvoip_irq(unsigned int irq)
+{
+ disable_irq_nosync(irq);
+ irq_desc[irq].handler = &hs7751rvoip_irq_type;
+ disable_hs7751rvoip_irq(irq);
+}
+
+/*
+ * Initialize IRQ setting
+ */
+void __init init_hs7751rvoip_IRQ(void)
+{
+ int i;
+
+ /* IRL0=ON HOOK1
+ * IRL1=OFF HOOK1
+ * IRL2=ON HOOK2
+ * IRL3=OFF HOOK2
+ * IRL4=Ringing Detection
+ * IRL5=CODEC
+ * IRL6=Ethernet
+ * IRL7=Ethernet Hub
+ * IRL8=USB Communication
+ * IRL9=USB Connection
+ * IRL10=USB DMA
+ * IRL11=CF Card
+ * IRL12=PCMCIA
+ * IRL13=PCI Slot
+ */
+ ctrl_outw(0x9876, IRLCNTR1);
+ ctrl_outw(0xdcba, IRLCNTR2);
+ ctrl_outw(0x0050, IRLCNTR4);
+ ctrl_outw(0x4321, IRLCNTR5);
+
+ for (i=0; i<14; i++)
+ make_hs7751rvoip_irq(i);
+}
diff --git a/arch/sh/boards/renesas/hs7751rvoip/led.c b/arch/sh/boards/renesas/hs7751rvoip/led.c
new file mode 100644
index 000000000000..18a13c8da8a4
--- /dev/null
+++ b/arch/sh/boards/renesas/hs7751rvoip/led.c
@@ -0,0 +1,27 @@
+/*
+ * linux/arch/sh/kernel/setup_hs7751rvoip.c
+ *
+ * Copyright (C) 2000 Kazumoto Kojima
+ *
+ * Renesas Technology Sales HS7751RVoIP Support.
+ *
+ * Modified for HS7751RVoIP by
+ * Atom Create Engineering Co., Ltd. 2002.
+ * Lineo uSolutions, Inc. 2003.
+ */
+
+#include <linux/config.h>
+#include <asm/io.h>
+#include <asm/hs7751rvoip/hs7751rvoip.h>
+
+extern unsigned int debug_counter;
+
+void debug_led_disp(void)
+{
+ unsigned short value;
+
+ value = (unsigned char)debug_counter++;
+ ctrl_outb((0xf0|value), PA_OUTPORTR);
+ if (value == 0x0f)
+ debug_counter = 0;
+}
diff --git a/arch/sh/boards/renesas/hs7751rvoip/mach.c b/arch/sh/boards/renesas/hs7751rvoip/mach.c
new file mode 100644
index 000000000000..8bbed60220ca
--- /dev/null
+++ b/arch/sh/boards/renesas/hs7751rvoip/mach.c
@@ -0,0 +1,55 @@
+/*
+ * linux/arch/sh/kernel/mach_hs7751rvoip.c
+ *
+ * Minor tweak of mach_se.c file to reference hs7751rvoip-specific items.
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License. See linux/COPYING for more information.
+ *
+ * Machine vector for the Renesas Technology sales HS7751RVoIP
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+
+#include <asm/machvec.h>
+#include <asm/rtc.h>
+#include <asm/irq.h>
+#include <asm/hs7751rvoip/io.h>
+
+extern void init_hs7751rvoip_IRQ(void);
+extern void *hs7751rvoip_ioremap(unsigned long, unsigned long);
+
+/*
+ * The Machine Vector
+ */
+
+struct sh_machine_vector mv_hs7751rvoip __initmv = {
+ .mv_nr_irqs = 72,
+
+ .mv_inb = hs7751rvoip_inb,
+ .mv_inw = hs7751rvoip_inw,
+ .mv_inl = hs7751rvoip_inl,
+ .mv_outb = hs7751rvoip_outb,
+ .mv_outw = hs7751rvoip_outw,
+ .mv_outl = hs7751rvoip_outl,
+
+ .mv_inb_p = hs7751rvoip_inb_p,
+ .mv_inw_p = hs7751rvoip_inw,
+ .mv_inl_p = hs7751rvoip_inl,
+ .mv_outb_p = hs7751rvoip_outb_p,
+ .mv_outw_p = hs7751rvoip_outw,
+ .mv_outl_p = hs7751rvoip_outl,
+
+ .mv_insb = hs7751rvoip_insb,
+ .mv_insw = hs7751rvoip_insw,
+ .mv_insl = hs7751rvoip_insl,
+ .mv_outsb = hs7751rvoip_outsb,
+ .mv_outsw = hs7751rvoip_outsw,
+ .mv_outsl = hs7751rvoip_outsl,
+
+ .mv_ioremap = hs7751rvoip_ioremap,
+ .mv_isa_port2addr = hs7751rvoip_isa_port2addr,
+ .mv_init_irq = init_hs7751rvoip_IRQ,
+};
+ALIAS_MV(hs7751rvoip)
diff --git a/arch/sh/boards/renesas/hs7751rvoip/pci.c b/arch/sh/boards/renesas/hs7751rvoip/pci.c
new file mode 100644
index 000000000000..7a442d1eca46
--- /dev/null
+++ b/arch/sh/boards/renesas/hs7751rvoip/pci.c
@@ -0,0 +1,150 @@
+/*
+ * linux/arch/sh/kernel/pci-hs7751rvoip.c
+ *
+ * Author: Ian DaSilva (idasilva@mvista.com)
+ *
+ * Highly leveraged from pci-bigsur.c, written by Dustin McIntire.
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License. See linux/COPYING for more information.
+ *
+ * PCI initialization for the Renesas SH7751R HS7751RVoIP board
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+#include <linux/module.h>
+
+#include <asm/io.h>
+#include "../../../drivers/pci/pci-sh7751.h"
+#include <asm/hs7751rvoip/hs7751rvoip.h>
+
+#define PCIMCR_MRSET_OFF 0xBFFFFFFF
+#define PCIMCR_RFSH_OFF 0xFFFFFFFB
+
+/*
+ * Only long word accesses of the PCIC's internal local registers and the
+ * configuration registers from the CPU is supported.
+ */
+#define PCIC_WRITE(x,v) writel((v), PCI_REG(x))
+#define PCIC_READ(x) readl(PCI_REG(x))
+
+/*
+ * Description: This function sets up and initializes the pcic, sets
+ * up the BARS, maps the DRAM into the address space etc, etc.
+ */
+int __init pcibios_init_platform(void)
+{
+ unsigned long bcr1, wcr1, wcr2, wcr3, mcr;
+ unsigned short bcr2, bcr3;
+
+ /*
+ * Initialize the slave bus controller on the pcic. The values used
+ * here should not be hardcoded, but they should be taken from the bsc
+ * on the processor, to make this function as generic as possible.
+ * (i.e. Another sbc may usr different SDRAM timing settings -- in order
+ * for the pcic to work, its settings need to be exactly the same.)
+ */
+ bcr1 = (*(volatile unsigned long *)(SH7751_BCR1));
+ bcr2 = (*(volatile unsigned short *)(SH7751_BCR2));
+ bcr3 = (*(volatile unsigned short *)(SH7751_BCR3));
+ wcr1 = (*(volatile unsigned long *)(SH7751_WCR1));
+ wcr2 = (*(volatile unsigned long *)(SH7751_WCR2));
+ wcr3 = (*(volatile unsigned long *)(SH7751_WCR3));
+ mcr = (*(volatile unsigned long *)(SH7751_MCR));
+
+ bcr1 = bcr1 | 0x00080000; /* Enable Bit 19, BREQEN */
+ (*(volatile unsigned long *)(SH7751_BCR1)) = bcr1;
+
+ bcr1 = bcr1 | 0x40080000; /* Enable Bit 19 BREQEN, set PCIC to slave */
+ PCIC_WRITE(SH7751_PCIBCR1, bcr1); /* PCIC BCR1 */
+ PCIC_WRITE(SH7751_PCIBCR2, bcr2); /* PCIC BCR2 */
+ PCIC_WRITE(SH7751_PCIBCR3, bcr3); /* PCIC BCR3 */
+ PCIC_WRITE(SH7751_PCIWCR1, wcr1); /* PCIC WCR1 */
+ PCIC_WRITE(SH7751_PCIWCR2, wcr2); /* PCIC WCR2 */
+ PCIC_WRITE(SH7751_PCIWCR3, wcr3); /* PCIC WCR3 */
+ mcr = (mcr & PCIMCR_MRSET_OFF) & PCIMCR_RFSH_OFF;
+ PCIC_WRITE(SH7751_PCIMCR, mcr); /* PCIC MCR */
+
+ /* Enable all interrupts, so we know what to fix */
+ PCIC_WRITE(SH7751_PCIINTM, 0x0000c3ff);
+ PCIC_WRITE(SH7751_PCIAINTM, 0x0000380f);
+
+ /* Set up standard PCI config registers */
+ PCIC_WRITE(SH7751_PCICONF1, 0xFB900047); /* Bus Master, Mem & I/O access */
+ PCIC_WRITE(SH7751_PCICONF2, 0x00000000); /* PCI Class code & Revision ID */
+ PCIC_WRITE(SH7751_PCICONF4, 0xab000001); /* PCI I/O address (local regs) */
+ PCIC_WRITE(SH7751_PCICONF5, 0x0c000000); /* PCI MEM address (local RAM) */
+ PCIC_WRITE(SH7751_PCICONF6, 0xd0000000); /* PCI MEM address (unused) */
+ PCIC_WRITE(SH7751_PCICONF11, 0x35051054); /* PCI Subsystem ID & Vendor ID */
+ PCIC_WRITE(SH7751_PCILSR0, 0x03f00000); /* MEM (full 64M exposed) */
+ PCIC_WRITE(SH7751_PCILSR1, 0x00000000); /* MEM (unused) */
+ PCIC_WRITE(SH7751_PCILAR0, 0x0c000000); /* MEM (direct map from PCI) */
+ PCIC_WRITE(SH7751_PCILAR1, 0x00000000); /* MEM (unused) */
+
+ /* Now turn it on... */
+ PCIC_WRITE(SH7751_PCICR, 0xa5000001);
+
+ /*
+ * Set PCIMBR and PCIIOBR here, assuming a single window
+ * (16M MEM, 256K IO) is enough. If a larger space is
+ * needed, the readx/writex and inx/outx functions will
+ * have to do more (e.g. setting registers for each call).
+ */
+
+ /*
+ * Set the MBR so PCI address is one-to-one with window,
+ * meaning all calls go straight through... use ifdef to
+ * catch erroneous assumption.
+ */
+ BUG_ON(PCIBIOS_MIN_MEM != SH7751_PCI_MEMORY_BASE);
+
+ PCIC_WRITE(SH7751_PCIMBR, PCIBIOS_MIN_MEM);
+
+ /* Set IOBR for window containing area specified in pci.h */
+ PCIC_WRITE(SH7751_PCIIOBR, (PCIBIOS_MIN_IO & SH7751_PCIIOBR_MASK));
+
+ /* All done, may as well say so... */
+ printk("SH7751R PCI: Finished initialization of the PCI controller\n");
+
+ return 1;
+}
+
+int __init pcibios_map_platform_irq(u8 slot, u8 pin)
+{
+ switch (slot) {
+ case 0: return IRQ_PCISLOT; /* PCI Extend slot */
+ case 1: return IRQ_PCMCIA; /* PCI Cardbus Bridge */
+ case 2: return IRQ_PCIETH; /* Realtek Ethernet controller */
+ case 3: return IRQ_PCIHUB; /* Realtek Ethernet Hub controller */
+ default:
+ printk("PCI: Bad IRQ mapping request for slot %d\n", slot);
+ return -1;
+ }
+}
+
+static struct resource sh7751_io_resource = {
+ .name = "SH7751_IO",
+ .start = 0x4000,
+ .end = 0x4000 + SH7751_PCI_IO_SIZE - 1,
+ .flags = IORESOURCE_IO
+};
+
+static struct resource sh7751_mem_resource = {
+ .name = "SH7751_mem",
+ .start = SH7751_PCI_MEMORY_BASE,
+ .end = SH7751_PCI_MEMORY_BASE + SH7751_PCI_MEM_SIZE - 1,
+ .flags = IORESOURCE_MEM
+};
+
+extern struct pci_ops sh7751_pci_ops;
+
+struct pci_channel board_pci_channels[] = {
+ { &sh7751_pci_ops, &sh7751_io_resource, &sh7751_mem_resource, 0, 0xff },
+ { NULL, NULL, NULL, 0, 0 },
+};
+EXPORT_SYMBOL(board_pci_channels);
diff --git a/arch/sh/boards/renesas/hs7751rvoip/setup.c b/arch/sh/boards/renesas/hs7751rvoip/setup.c
new file mode 100644
index 000000000000..f1a78b6c714c
--- /dev/null
+++ b/arch/sh/boards/renesas/hs7751rvoip/setup.c
@@ -0,0 +1,89 @@
+/*
+ * linux/arch/sh/kernel/setup_hs7751rvoip.c
+ *
+ * Copyright (C) 2000 Kazumoto Kojima
+ *
+ * Renesas Technology Sales HS7751RVoIP Support.
+ *
+ * Modified for HS7751RVoIP by
+ * Atom Create Engineering Co., Ltd. 2002.
+ * Lineo uSolutions, Inc. 2003.
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+
+#include <linux/hdreg.h>
+#include <linux/ide.h>
+#include <asm/io.h>
+#include <asm/hs7751rvoip/hs7751rvoip.h>
+
+#include <linux/mm.h>
+#include <linux/vmalloc.h>
+
+/* defined in mm/ioremap.c */
+extern void * p3_ioremap(unsigned long phys_addr, unsigned long size, unsigned long flags);
+
+unsigned int debug_counter;
+
+const char *get_system_type(void)
+{
+ return "HS7751RVoIP";
+}
+
+/*
+ * Initialize the board
+ */
+void __init platform_setup(void)
+{
+ printk(KERN_INFO "Renesas Technology Sales HS7751RVoIP-2 support.\n");
+ ctrl_outb(0xf0, PA_OUTPORTR);
+ debug_counter = 0;
+}
+
+void *area5_io8_base;
+void *area6_io8_base;
+void *area5_io16_base;
+void *area6_io16_base;
+
+int __init cf_init(void)
+{
+ pgprot_t prot;
+ unsigned long paddrbase, psize;
+
+ /* open I/O area window */
+ paddrbase = virt_to_phys((void *)(PA_AREA5_IO+0x00000800));
+ psize = PAGE_SIZE;
+ prot = PAGE_KERNEL_PCC(1, _PAGE_PCC_COM16);
+ area5_io16_base = p3_ioremap(paddrbase, psize, prot.pgprot);
+ if (!area5_io16_base) {
+ printk("allocate_cf_area : can't open CF I/O window!\n");
+ return -ENOMEM;
+ }
+
+ /* XXX : do we need attribute and common-memory area also? */
+
+ paddrbase = virt_to_phys((void *)PA_AREA6_IO);
+ psize = PAGE_SIZE;
+#if defined(CONFIG_HS7751RVOIP_CODEC)
+ prot = PAGE_KERNEL_PCC(0, _PAGE_PCC_COM8);
+#else
+ prot = PAGE_KERNEL_PCC(0, _PAGE_PCC_IO8);
+#endif
+ area6_io8_base = p3_ioremap(paddrbase, psize, prot.pgprot);
+ if (!area6_io8_base) {
+ printk("allocate_cf_area : can't open CODEC I/O 8bit window!\n");
+ return -ENOMEM;
+ }
+ prot = PAGE_KERNEL_PCC(0, _PAGE_PCC_IO16);
+ area6_io16_base = p3_ioremap(paddrbase, psize, prot.pgprot);
+ if (!area6_io16_base) {
+ printk("allocate_cf_area : can't open CODEC I/O 16bit window!\n");
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+__initcall (cf_init);
diff --git a/arch/sh/boards/renesas/rts7751r2d/Makefile b/arch/sh/boards/renesas/rts7751r2d/Makefile
new file mode 100644
index 000000000000..daa53334bdc3
--- /dev/null
+++ b/arch/sh/boards/renesas/rts7751r2d/Makefile
@@ -0,0 +1,10 @@
+#
+# Makefile for the RTS7751R2D specific parts of the 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).
+#
+
+obj-y := mach.o setup.o io.o irq.o led.o
+
diff --git a/arch/sh/boards/renesas/rts7751r2d/io.c b/arch/sh/boards/renesas/rts7751r2d/io.c
new file mode 100644
index 000000000000..c46f9154cfd5
--- /dev/null
+++ b/arch/sh/boards/renesas/rts7751r2d/io.c
@@ -0,0 +1,319 @@
+/*
+ * linux/arch/sh/kernel/io_rts7751r2d.c
+ *
+ * Copyright (C) 2001 Ian da Silva, Jeremy Siegel
+ * Based largely on io_se.c.
+ *
+ * I/O routine for Renesas Technology sales RTS7751R2D.
+ *
+ * Initial version only to support LAN access; some
+ * placeholder code from io_rts7751r2d.c left in with the
+ * expectation of later SuperIO and PCMCIA access.
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <asm/io.h>
+#include <asm/rts7751r2d/rts7751r2d.h>
+#include <asm/addrspace.h>
+
+#include <linux/module.h>
+#include <linux/pci.h>
+#include "../../../drivers/pci/pci-sh7751.h"
+
+/*
+ * The 7751R RTS7751R2D uses the built-in PCI controller (PCIC)
+ * of the 7751R processor, and has a SuperIO accessible via the PCI.
+ * The board also includes a PCMCIA controller on its memory bus,
+ * like the other Solution Engine boards.
+ */
+
+#define PCIIOBR (volatile long *)PCI_REG(SH7751_PCIIOBR)
+#define PCIMBR (volatile long *)PCI_REG(SH7751_PCIMBR)
+#define PCI_IO_AREA SH7751_PCI_IO_BASE
+#define PCI_MEM_AREA SH7751_PCI_CONFIG_BASE
+
+#define PCI_IOMAP(adr) (PCI_IO_AREA + (adr & ~SH7751_PCIIOBR_MASK))
+
+#define maybebadio(name,port) \
+ printk("bad PC-like io %s for port 0x%lx at 0x%08x\n", \
+ #name, (port), (__u32) __builtin_return_address(0))
+
+static inline void delay(void)
+{
+ ctrl_inw(0xa0000000);
+}
+
+static inline unsigned long port2adr(unsigned int port)
+{
+ if ((0x1f0 <= port && port < 0x1f8) || port == 0x3f6)
+ if (port == 0x3f6)
+ return (PA_AREA5_IO + 0x80c);
+ else
+ return (PA_AREA5_IO + 0x1000 + ((port-0x1f0) << 1));
+ else
+ maybebadio(port2adr, (unsigned long)port);
+
+ return port;
+}
+
+static inline unsigned long port88796l(unsigned int port, int flag)
+{
+ unsigned long addr;
+
+ if (flag)
+ addr = PA_AX88796L + ((port - AX88796L_IO_BASE) << 1);
+ else
+ addr = PA_AX88796L + ((port - AX88796L_IO_BASE) << 1) + 0x1000;
+
+ return addr;
+}
+
+/* The 7751R RTS7751R2D seems to have everything hooked */
+/* up pretty normally (nothing on high-bytes only...) so this */
+/* shouldn't be needed */
+static inline int shifted_port(unsigned long port)
+{
+ /* For IDE registers, value is not shifted */
+ if ((0x1f0 <= port && port < 0x1f8) || port == 0x3f6)
+ return 0;
+ else
+ return 1;
+}
+
+/* In case someone configures the kernel w/o PCI support: in that */
+/* scenario, don't ever bother to check for PCI-window addresses */
+
+/* NOTE: WINDOW CHECK MAY BE A BIT OFF, HIGH PCIBIOS_MIN_IO WRAPS? */
+#if defined(CONFIG_PCI)
+#define CHECK_SH7751_PCIIO(port) \
+ ((port >= PCIBIOS_MIN_IO) && (port < (PCIBIOS_MIN_IO + SH7751_PCI_IO_SIZE)))
+#else
+#define CHECK_SH7751_PCIIO(port) (0)
+#endif
+
+#if defined(CONFIG_NE2000) || defined(CONFIG_NE2000_MODULE)
+#define CHECK_AX88796L_PORT(port) \
+ ((port >= AX88796L_IO_BASE) && (port < (AX88796L_IO_BASE+0x20)))
+#else
+#define CHECK_AX88796L_PORT(port) (0)
+#endif
+
+/*
+ * General outline: remap really low stuff [eventually] to SuperIO,
+ * stuff in PCI IO space (at or above window at pci.h:PCIBIOS_MIN_IO)
+ * is mapped through the PCI IO window. Stuff with high bits (PXSEG)
+ * should be way beyond the window, and is used w/o translation for
+ * compatibility.
+ */
+unsigned char rts7751r2d_inb(unsigned long port)
+{
+ if (CHECK_AX88796L_PORT(port))
+ return (*(volatile unsigned short *)port88796l(port, 0)) & 0xff;
+ else if (PXSEG(port))
+ return *(volatile unsigned char *)port;
+ else if (CHECK_SH7751_PCIIO(port) || shifted_port(port))
+ return *(volatile unsigned char *)PCI_IOMAP(port);
+ else
+ return (*(volatile unsigned short *)port2adr(port) & 0xff);
+}
+
+unsigned char rts7751r2d_inb_p(unsigned long port)
+{
+ unsigned char v;
+
+ if (CHECK_AX88796L_PORT(port))
+ v = (*(volatile unsigned short *)port88796l(port, 0)) & 0xff;
+ else if (PXSEG(port))
+ v = *(volatile unsigned char *)port;
+ else if (CHECK_SH7751_PCIIO(port) || shifted_port(port))
+ v = *(volatile unsigned char *)PCI_IOMAP(port);
+ else
+ v = (*(volatile unsigned short *)port2adr(port) & 0xff);
+ delay();
+
+ return v;
+}
+
+unsigned short rts7751r2d_inw(unsigned long port)
+{
+ if (CHECK_AX88796L_PORT(port))
+ maybebadio(inw, port);
+ else if (PXSEG(port))
+ return *(volatile unsigned short *)port;
+ else if (CHECK_SH7751_PCIIO(port) || shifted_port(port))
+ return *(volatile unsigned short *)PCI_IOMAP(port);
+ else
+ maybebadio(inw, port);
+
+ return 0;
+}
+
+unsigned int rts7751r2d_inl(unsigned long port)
+{
+ if (CHECK_AX88796L_PORT(port))
+ maybebadio(inl, port);
+ else if (PXSEG(port))
+ return *(volatile unsigned long *)port;
+ else if (CHECK_SH7751_PCIIO(port) || shifted_port(port))
+ return *(volatile unsigned long *)PCI_IOMAP(port);
+ else
+ maybebadio(inl, port);
+
+ return 0;
+}
+
+void rts7751r2d_outb(unsigned char value, unsigned long port)
+{
+ if (CHECK_AX88796L_PORT(port))
+ *((volatile unsigned short *)port88796l(port, 0)) = value;
+ else if (PXSEG(port))
+ *(volatile unsigned char *)port = value;
+ else if (CHECK_SH7751_PCIIO(port) || shifted_port(port))
+ *(volatile unsigned char *)PCI_IOMAP(port) = value;
+ else
+ *(volatile unsigned short *)port2adr(port) = value;
+}
+
+void rts7751r2d_outb_p(unsigned char value, unsigned long port)
+{
+ if (CHECK_AX88796L_PORT(port))
+ *((volatile unsigned short *)port88796l(port, 0)) = value;
+ else if (PXSEG(port))
+ *(volatile unsigned char *)port = value;
+ else if (CHECK_SH7751_PCIIO(port) || shifted_port(port))
+ *(volatile unsigned char *)PCI_IOMAP(port) = value;
+ else
+ *(volatile unsigned short *)port2adr(port) = value;
+ delay();
+}
+
+void rts7751r2d_outw(unsigned short value, unsigned long port)
+{
+ if (CHECK_AX88796L_PORT(port))
+ maybebadio(outw, port);
+ else if (PXSEG(port))
+ *(volatile unsigned short *)port = value;
+ else if (CHECK_SH7751_PCIIO(port) || shifted_port(port))
+ *(volatile unsigned short *)PCI_IOMAP(port) = value;
+ else
+ maybebadio(outw, port);
+}
+
+void rts7751r2d_outl(unsigned int value, unsigned long port)
+{
+ if (CHECK_AX88796L_PORT(port))
+ maybebadio(outl, port);
+ else if (PXSEG(port))
+ *(volatile unsigned long *)port = value;
+ else if (CHECK_SH7751_PCIIO(port) || shifted_port(port))
+ *(volatile unsigned long *)PCI_IOMAP(port) = value;
+ else
+ maybebadio(outl, port);
+}
+
+void rts7751r2d_insb(unsigned long port, void *addr, unsigned long count)
+{
+ volatile __u8 *bp;
+ volatile __u16 *p;
+
+ if (CHECK_AX88796L_PORT(port)) {
+ p = (volatile unsigned short *)port88796l(port, 0);
+ while (count--) *((unsigned char *) addr)++ = *p & 0xff;
+ } else if (PXSEG(port))
+ while (count--) *((unsigned char *) addr)++ = *(volatile unsigned char *)port;
+ else if (CHECK_SH7751_PCIIO(port) || shifted_port(port)) {
+ bp = (__u8 *)PCI_IOMAP(port);
+ while (count--) *((volatile unsigned char *) addr)++ = *bp;
+ } else {
+ p = (volatile unsigned short *)port2adr(port);
+ while (count--) *((unsigned char *) addr)++ = *p & 0xff;
+ }
+}
+
+void rts7751r2d_insw(unsigned long port, void *addr, unsigned long count)
+{
+ volatile __u16 *p;
+
+ if (CHECK_AX88796L_PORT(port))
+ p = (volatile unsigned short *)port88796l(port, 1);
+ else if (PXSEG(port))
+ p = (volatile unsigned short *)port;
+ else if (CHECK_SH7751_PCIIO(port) || shifted_port(port))
+ p = (volatile unsigned short *)PCI_IOMAP(port);
+ else
+ p = (volatile unsigned short *)port2adr(port);
+ while (count--) *((__u16 *) addr)++ = *p;
+}
+
+void rts7751r2d_insl(unsigned long port, void *addr, unsigned long count)
+{
+ if (CHECK_AX88796L_PORT(port))
+ maybebadio(insl, port);
+ else if (CHECK_SH7751_PCIIO(port) || shifted_port(port)) {
+ volatile __u32 *p = (__u32 *)PCI_IOMAP(port);
+
+ while (count--) *((__u32 *) addr)++ = *p;
+ } else
+ maybebadio(insl, port);
+}
+
+void rts7751r2d_outsb(unsigned long port, const void *addr, unsigned long count)
+{
+ volatile __u8 *bp;
+ volatile __u16 *p;
+
+ if (CHECK_AX88796L_PORT(port)) {
+ p = (volatile unsigned short *)port88796l(port, 0);
+ while (count--) *p = *((unsigned char *) addr)++;
+ } else if (PXSEG(port))
+ while (count--) *(volatile unsigned char *)port = *((unsigned char *) addr)++;
+ else if (CHECK_SH7751_PCIIO(port) || shifted_port(port)) {
+ bp = (__u8 *)PCI_IOMAP(port);
+ while (count--) *bp = *((volatile unsigned char *) addr)++;
+ } else {
+ p = (volatile unsigned short *)port2adr(port);
+ while (count--) *p = *((unsigned char *) addr)++;
+ }
+}
+
+void rts7751r2d_outsw(unsigned long port, const void *addr, unsigned long count)
+{
+ volatile __u16 *p;
+
+ if (CHECK_AX88796L_PORT(port))
+ p = (volatile unsigned short *)port88796l(port, 1);
+ else if (PXSEG(port))
+ p = (volatile unsigned short *)port;
+ else if (CHECK_SH7751_PCIIO(port) || shifted_port(port))
+ p = (volatile unsigned short *)PCI_IOMAP(port);
+ else
+ p = (volatile unsigned short *)port2adr(port);
+ while (count--) *p = *((__u16 *) addr)++;
+}
+
+void rts7751r2d_outsl(unsigned long port, const void *addr, unsigned long count)
+{
+ if (CHECK_AX88796L_PORT(port))
+ maybebadio(outsl, port);
+ else if (CHECK_SH7751_PCIIO(port) || shifted_port(port)) {
+ volatile __u32 *p = (__u32 *)PCI_IOMAP(port);
+
+ while (count--) *p = *((__u32 *) addr)++;
+ } else
+ maybebadio(outsl, port);
+}
+
+void *rts7751r2d_ioremap(unsigned long offset, unsigned long size)
+{
+ if (offset >= 0xfd000000)
+ return (void *)offset;
+ else
+ return (void *)P2SEGADDR(offset);
+}
+EXPORT_SYMBOL(rts7751r2d_ioremap);
+
+unsigned long rts7751r2d_isa_port2addr(unsigned long offset)
+{
+ return port2adr(offset);
+}
diff --git a/arch/sh/boards/renesas/rts7751r2d/irq.c b/arch/sh/boards/renesas/rts7751r2d/irq.c
new file mode 100644
index 000000000000..95717f4f1e2d
--- /dev/null
+++ b/arch/sh/boards/renesas/rts7751r2d/irq.c
@@ -0,0 +1,135 @@
+/*
+ * linux/arch/sh/boards/renesas/rts7751r2d/irq.c
+ *
+ * Copyright (C) 2000 Kazumoto Kojima
+ *
+ * Renesas Technology Sales RTS7751R2D Support.
+ *
+ * Modified for RTS7751R2D by
+ * Atom Create Engineering Co., Ltd. 2002.
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/rts7751r2d/rts7751r2d.h>
+
+#if defined(CONFIG_RTS7751R2D_REV11)
+static int mask_pos[] = {11, 9, 8, 12, 10, 6, 5, 4, 7, 14, 13, 0, 0, 0, 0};
+#else
+static int mask_pos[] = {6, 11, 9, 8, 12, 10, 5, 4, 7, 14, 13, 0, 0, 0, 0};
+#endif
+
+extern int voyagergx_irq_demux(int irq);
+extern void setup_voyagergx_irq(void);
+
+static void enable_rts7751r2d_irq(unsigned int irq);
+static void disable_rts7751r2d_irq(unsigned int irq);
+
+/* shutdown is same as "disable" */
+#define shutdown_rts7751r2d_irq disable_rts7751r2d_irq
+
+static void ack_rts7751r2d_irq(unsigned int irq);
+static void end_rts7751r2d_irq(unsigned int irq);
+
+static unsigned int startup_rts7751r2d_irq(unsigned int irq)
+{
+ enable_rts7751r2d_irq(irq);
+ return 0; /* never anything pending */
+}
+
+static void disable_rts7751r2d_irq(unsigned int irq)
+{
+ unsigned long flags;
+ unsigned short val;
+ unsigned short mask = 0xffff ^ (0x0001 << mask_pos[irq]);
+
+ /* Set the priority in IPR to 0 */
+ local_irq_save(flags);
+ val = ctrl_inw(IRLCNTR1);
+ val &= mask;
+ ctrl_outw(val, IRLCNTR1);
+ local_irq_restore(flags);
+}
+
+static void enable_rts7751r2d_irq(unsigned int irq)
+{
+ unsigned long flags;
+ unsigned short val;
+ unsigned short value = (0x0001 << mask_pos[irq]);
+
+ /* Set priority in IPR back to original value */
+ local_irq_save(flags);
+ val = ctrl_inw(IRLCNTR1);
+ val |= value;
+ ctrl_outw(val, IRLCNTR1);
+ local_irq_restore(flags);
+}
+
+int rts7751r2d_irq_demux(int irq)
+{
+ int demux_irq;
+
+ demux_irq = voyagergx_irq_demux(irq);
+ return demux_irq;
+}
+
+static void ack_rts7751r2d_irq(unsigned int irq)
+{
+ disable_rts7751r2d_irq(irq);
+}
+
+static void end_rts7751r2d_irq(unsigned int irq)
+{
+ if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+ enable_rts7751r2d_irq(irq);
+}
+
+static struct hw_interrupt_type rts7751r2d_irq_type = {
+ "RTS7751R2D IRQ",
+ startup_rts7751r2d_irq,
+ shutdown_rts7751r2d_irq,
+ enable_rts7751r2d_irq,
+ disable_rts7751r2d_irq,
+ ack_rts7751r2d_irq,
+ end_rts7751r2d_irq,
+};
+
+static void make_rts7751r2d_irq(unsigned int irq)
+{
+ disable_irq_nosync(irq);
+ irq_desc[irq].handler = &rts7751r2d_irq_type;
+ disable_rts7751r2d_irq(irq);
+}
+
+/*
+ * Initialize IRQ setting
+ */
+void __init init_rts7751r2d_IRQ(void)
+{
+ int i;
+
+ /* IRL0=KEY Input
+ * IRL1=Ethernet
+ * IRL2=CF Card
+ * IRL3=CF Card Insert
+ * IRL4=PCMCIA
+ * IRL5=VOYAGER
+ * IRL6=RTC Alarm
+ * IRL7=RTC Timer
+ * IRL8=SD Card
+ * IRL9=PCI Slot #1
+ * IRL10=PCI Slot #2
+ * IRL11=Extention #0
+ * IRL12=Extention #1
+ * IRL13=Extention #2
+ * IRL14=Extention #3
+ */
+
+ for (i=0; i<15; i++)
+ make_rts7751r2d_irq(i);
+
+ setup_voyagergx_irq();
+}
diff --git a/arch/sh/boards/renesas/rts7751r2d/led.c b/arch/sh/boards/renesas/rts7751r2d/led.c
new file mode 100644
index 000000000000..9993259a894f
--- /dev/null
+++ b/arch/sh/boards/renesas/rts7751r2d/led.c
@@ -0,0 +1,67 @@
+/*
+ * linux/arch/sh/kernel/led_rts7751r2d.c
+ *
+ * Copyright (C) Atom Create Engineering Co., Ltd.
+ *
+ * May be copied or modified under the terms of GNU General Public
+ * License. See linux/COPYING for more information.
+ *
+ * This file contains Renesas Technology Sales RTS7751R2D specific LED code.
+ */
+
+#include <linux/config.h>
+#include <asm/io.h>
+#include <asm/rts7751r2d/rts7751r2d.h>
+
+extern unsigned int debug_counter;
+
+#ifdef CONFIG_HEARTBEAT
+
+#include <linux/sched.h>
+
+/* Cycle the LED's in the clasic Knightriger/Sun pattern */
+void heartbeat_rts7751r2d(void)
+{
+ static unsigned int cnt = 0, period = 0;
+ volatile unsigned short *p = (volatile unsigned short *)PA_OUTPORT;
+ static unsigned bit = 0, up = 1;
+
+ cnt += 1;
+ if (cnt < period)
+ return;
+
+ cnt = 0;
+
+ /* Go through the points (roughly!):
+ * f(0)=10, f(1)=16, f(2)=20, f(5)=35, f(int)->110
+ */
+ period = 110 - ((300 << FSHIFT)/((avenrun[0]/5) + (3<<FSHIFT)));
+
+ *p = 1 << bit;
+ if (up)
+ if (bit == 7) {
+ bit--;
+ up = 0;
+ } else
+ bit++;
+ else if (bit == 0)
+ up = 1;
+ else
+ bit--;
+}
+#endif /* CONFIG_HEARTBEAT */
+
+void rts7751r2d_led(unsigned short value)
+{
+ ctrl_outw(value, PA_OUTPORT);
+}
+
+void debug_led_disp(void)
+{
+ unsigned short value;
+
+ value = (unsigned short)debug_counter++;
+ rts7751r2d_led(value);
+ if (value == 0xff)
+ debug_counter = 0;
+}
diff --git a/arch/sh/boards/renesas/rts7751r2d/mach.c b/arch/sh/boards/renesas/rts7751r2d/mach.c
new file mode 100644
index 000000000000..1efc18e786d5
--- /dev/null
+++ b/arch/sh/boards/renesas/rts7751r2d/mach.c
@@ -0,0 +1,70 @@
+/*
+ * linux/arch/sh/kernel/mach_rts7751r2d.c
+ *
+ * Minor tweak of mach_se.c file to reference rts7751r2d-specific items.
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License. See linux/COPYING for more information.
+ *
+ * Machine vector for the Renesas Technology sales RTS7751R2D
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/types.h>
+
+#include <asm/machvec.h>
+#include <asm/rtc.h>
+#include <asm/irq.h>
+#include <asm/rts7751r2d/io.h>
+
+extern void heartbeat_rts7751r2d(void);
+extern void init_rts7751r2d_IRQ(void);
+extern void *rts7751r2d_ioremap(unsigned long, unsigned long);
+extern int rts7751r2d_irq_demux(int irq);
+
+extern void *voyagergx_consistent_alloc(struct device *, size_t, dma_addr_t *, int);
+extern int voyagergx_consistent_free(struct device *, size_t, void *, dma_addr_t);
+
+/*
+ * The Machine Vector
+ */
+
+struct sh_machine_vector mv_rts7751r2d __initmv = {
+ .mv_nr_irqs = 72,
+
+ .mv_inb = rts7751r2d_inb,
+ .mv_inw = rts7751r2d_inw,
+ .mv_inl = rts7751r2d_inl,
+ .mv_outb = rts7751r2d_outb,
+ .mv_outw = rts7751r2d_outw,
+ .mv_outl = rts7751r2d_outl,
+
+ .mv_inb_p = rts7751r2d_inb_p,
+ .mv_inw_p = rts7751r2d_inw,
+ .mv_inl_p = rts7751r2d_inl,
+ .mv_outb_p = rts7751r2d_outb_p,
+ .mv_outw_p = rts7751r2d_outw,
+ .mv_outl_p = rts7751r2d_outl,
+
+ .mv_insb = rts7751r2d_insb,
+ .mv_insw = rts7751r2d_insw,
+ .mv_insl = rts7751r2d_insl,
+ .mv_outsb = rts7751r2d_outsb,
+ .mv_outsw = rts7751r2d_outsw,
+ .mv_outsl = rts7751r2d_outsl,
+
+ .mv_ioremap = rts7751r2d_ioremap,
+ .mv_isa_port2addr = rts7751r2d_isa_port2addr,
+ .mv_init_irq = init_rts7751r2d_IRQ,
+#ifdef CONFIG_HEARTBEAT
+ .mv_heartbeat = heartbeat_rts7751r2d,
+#endif
+ .mv_irq_demux = rts7751r2d_irq_demux,
+
+#ifdef CONFIG_USB_OHCI_HCD
+ .mv_consistent_alloc = voyagergx_consistent_alloc,
+ .mv_consistent_free = voyagergx_consistent_free,
+#endif
+};
+ALIAS_MV(rts7751r2d)
diff --git a/arch/sh/boards/renesas/rts7751r2d/setup.c b/arch/sh/boards/renesas/rts7751r2d/setup.c
new file mode 100644
index 000000000000..2587fd1a0240
--- /dev/null
+++ b/arch/sh/boards/renesas/rts7751r2d/setup.c
@@ -0,0 +1,31 @@
+/*
+ * linux/arch/sh/kernel/setup_rts7751r2d.c
+ *
+ * Copyright (C) 2000 Kazumoto Kojima
+ *
+ * Renesas Technology Sales RTS7751R2D Support.
+ *
+ * Modified for RTS7751R2D by
+ * Atom Create Engineering Co., Ltd. 2002.
+ */
+
+#include <linux/init.h>
+#include <asm/io.h>
+#include <asm/rts7751r2d/rts7751r2d.h>
+
+unsigned int debug_counter;
+
+const char *get_system_type(void)
+{
+ return "RTS7751R2D";
+}
+
+/*
+ * Initialize the board
+ */
+void __init platform_setup(void)
+{
+ printk(KERN_INFO "Renesas Technology Sales RTS7751R2D support.\n");
+ ctrl_outw(0x0000, PA_OUTPORT);
+ debug_counter = 0;
+}
diff --git a/arch/sh/boards/renesas/systemh/Makefile b/arch/sh/boards/renesas/systemh/Makefile
new file mode 100644
index 000000000000..2cc6a23d9d39
--- /dev/null
+++ b/arch/sh/boards/renesas/systemh/Makefile
@@ -0,0 +1,13 @@
+#
+# Makefile for the SystemH specific parts of the kernel
+#
+
+obj-y := setup.o irq.o io.o
+
+# XXX: This wants to be consolidated in arch/sh/drivers/pci, and more
+# importantly, with the generic sh7751_pcic_init() code. For now, we'll
+# just abuse the hell out of kbuild, because we can..
+
+obj-$(CONFIG_PCI) += pci.o
+pci-y := ../../se/7751/pci.o
+
diff --git a/arch/sh/boards/renesas/systemh/io.c b/arch/sh/boards/renesas/systemh/io.c
new file mode 100644
index 000000000000..cf979011aa94
--- /dev/null
+++ b/arch/sh/boards/renesas/systemh/io.c
@@ -0,0 +1,283 @@
+/*
+ * linux/arch/sh/boards/systemh/io.c
+ *
+ * Copyright (C) 2001 Ian da Silva, Jeremy Siegel
+ * Based largely on io_se.c.
+ *
+ * I/O routine for Hitachi 7751 Systemh.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <asm/systemh/7751systemh.h>
+#include <asm/addrspace.h>
+#include <asm/io.h>
+
+#include <linux/pci.h>
+#include "../../drivers/pci/pci-sh7751.h"
+
+/*
+ * The 7751 SystemH Engine uses the built-in PCI controller (PCIC)
+ * of the 7751 processor, and has a SuperIO accessible on its memory
+ * bus.
+ */
+
+#define PCIIOBR (volatile long *)PCI_REG(SH7751_PCIIOBR)
+#define PCIMBR (volatile long *)PCI_REG(SH7751_PCIMBR)
+#define PCI_IO_AREA SH7751_PCI_IO_BASE
+#define PCI_MEM_AREA SH7751_PCI_CONFIG_BASE
+
+#define PCI_IOMAP(adr) (PCI_IO_AREA + (adr & ~SH7751_PCIIOBR_MASK))
+#define ETHER_IOMAP(adr) (0xB3000000 + (adr)) /*map to 16bits access area
+ of smc lan chip*/
+
+#define maybebadio(name,port) \
+ printk("bad PC-like io %s for port 0x%lx at 0x%08x\n", \
+ #name, (port), (__u32) __builtin_return_address(0))
+
+static inline void delay(void)
+{
+ ctrl_inw(0xa0000000);
+}
+
+static inline volatile __u16 *
+port2adr(unsigned int port)
+{
+ if (port >= 0x2000)
+ return (volatile __u16 *) (PA_MRSHPC + (port - 0x2000));
+#if 0
+ else
+ return (volatile __u16 *) (PA_SUPERIO + (port << 1));
+#endif
+ maybebadio(name,(unsigned long)port);
+ return (volatile __u16*)port;
+}
+
+/* In case someone configures the kernel w/o PCI support: in that */
+/* scenario, don't ever bother to check for PCI-window addresses */
+
+/* NOTE: WINDOW CHECK MAY BE A BIT OFF, HIGH PCIBIOS_MIN_IO WRAPS? */
+#if defined(CONFIG_PCI)
+#define CHECK_SH7751_PCIIO(port) \
+ ((port >= PCIBIOS_MIN_IO) && (port < (PCIBIOS_MIN_IO + SH7751_PCI_IO_SIZE)))
+#else
+#define CHECK_SH7751_PCIIO(port) (0)
+#endif
+
+/*
+ * General outline: remap really low stuff [eventually] to SuperIO,
+ * stuff in PCI IO space (at or above window at pci.h:PCIBIOS_MIN_IO)
+ * is mapped through the PCI IO window. Stuff with high bits (PXSEG)
+ * should be way beyond the window, and is used w/o translation for
+ * compatibility.
+ */
+unsigned char sh7751systemh_inb(unsigned long port)
+{
+ if (PXSEG(port))
+ return *(volatile unsigned char *)port;
+ else if (CHECK_SH7751_PCIIO(port))
+ return *(volatile unsigned char *)PCI_IOMAP(port);
+ else if (port <= 0x3F1)
+ return *(volatile unsigned char *)ETHER_IOMAP(port);
+ else
+ return (*port2adr(port))&0xff;
+}
+
+unsigned char sh7751systemh_inb_p(unsigned long port)
+{
+ unsigned char v;
+
+ if (PXSEG(port))
+ v = *(volatile unsigned char *)port;
+ else if (CHECK_SH7751_PCIIO(port))
+ v = *(volatile unsigned char *)PCI_IOMAP(port);
+ else if (port <= 0x3F1)
+ v = *(volatile unsigned char *)ETHER_IOMAP(port);
+ else
+ v = (*port2adr(port))&0xff;
+ delay();
+ return v;
+}
+
+unsigned short sh7751systemh_inw(unsigned long port)
+{
+ if (PXSEG(port))
+ return *(volatile unsigned short *)port;
+ else if (CHECK_SH7751_PCIIO(port))
+ return *(volatile unsigned short *)PCI_IOMAP(port);
+ else if (port >= 0x2000)
+ return *port2adr(port);
+ else if (port <= 0x3F1)
+ return *(volatile unsigned int *)ETHER_IOMAP(port);
+ else
+ maybebadio(inw, port);
+ return 0;
+}
+
+unsigned int sh7751systemh_inl(unsigned long port)
+{
+ if (PXSEG(port))
+ return *(volatile unsigned long *)port;
+ else if (CHECK_SH7751_PCIIO(port))
+ return *(volatile unsigned int *)PCI_IOMAP(port);
+ else if (port >= 0x2000)
+ return *port2adr(port);
+ else if (port <= 0x3F1)
+ return *(volatile unsigned int *)ETHER_IOMAP(port);
+ else
+ maybebadio(inl, port);
+ return 0;
+}
+
+void sh7751systemh_outb(unsigned char value, unsigned long port)
+{
+
+ if (PXSEG(port))
+ *(volatile unsigned char *)port = value;
+ else if (CHECK_SH7751_PCIIO(port))
+ *((unsigned char*)PCI_IOMAP(port)) = value;
+ else if (port <= 0x3F1)
+ *(volatile unsigned char *)ETHER_IOMAP(port) = value;
+ else
+ *(port2adr(port)) = value;
+}
+
+void sh7751systemh_outb_p(unsigned char value, unsigned long port)
+{
+ if (PXSEG(port))
+ *(volatile unsigned char *)port = value;
+ else if (CHECK_SH7751_PCIIO(port))
+ *((unsigned char*)PCI_IOMAP(port)) = value;
+ else if (port <= 0x3F1)
+ *(volatile unsigned char *)ETHER_IOMAP(port) = value;
+ else
+ *(port2adr(port)) = value;
+ delay();
+}
+
+void sh7751systemh_outw(unsigned short value, unsigned long port)
+{
+ if (PXSEG(port))
+ *(volatile unsigned short *)port = value;
+ else if (CHECK_SH7751_PCIIO(port))
+ *((unsigned short *)PCI_IOMAP(port)) = value;
+ else if (port >= 0x2000)
+ *port2adr(port) = value;
+ else if (port <= 0x3F1)
+ *(volatile unsigned short *)ETHER_IOMAP(port) = value;
+ else
+ maybebadio(outw, port);
+}
+
+void sh7751systemh_outl(unsigned int value, unsigned long port)
+{
+ if (PXSEG(port))
+ *(volatile unsigned long *)port = value;
+ else if (CHECK_SH7751_PCIIO(port))
+ *((unsigned long*)PCI_IOMAP(port)) = value;
+ else
+ maybebadio(outl, port);
+}
+
+void sh7751systemh_insb(unsigned long port, void *addr, unsigned long count)
+{
+ unsigned char *p = addr;
+ while (count--) *p++ = sh7751systemh_inb(port);
+}
+
+void sh7751systemh_insw(unsigned long port, void *addr, unsigned long count)
+{
+ unsigned short *p = addr;
+ while (count--) *p++ = sh7751systemh_inw(port);
+}
+
+void sh7751systemh_insl(unsigned long port, void *addr, unsigned long count)
+{
+ maybebadio(insl, port);
+}
+
+void sh7751systemh_outsb(unsigned long port, const void *addr, unsigned long count)
+{
+ unsigned char *p = (unsigned char*)addr;
+ while (count--) sh7751systemh_outb(*p++, port);
+}
+
+void sh7751systemh_outsw(unsigned long port, const void *addr, unsigned long count)
+{
+ unsigned short *p = (unsigned short*)addr;
+ while (count--) sh7751systemh_outw(*p++, port);
+}
+
+void sh7751systemh_outsl(unsigned long port, const void *addr, unsigned long count)
+{
+ maybebadio(outsw, port);
+}
+
+/* For read/write calls, just copy generic (pass-thru); PCIMBR is */
+/* already set up. For a larger memory space, these would need to */
+/* reset PCIMBR as needed on a per-call basis... */
+
+unsigned char sh7751systemh_readb(unsigned long addr)
+{
+ return *(volatile unsigned char*)addr;
+}
+
+unsigned short sh7751systemh_readw(unsigned long addr)
+{
+ return *(volatile unsigned short*)addr;
+}
+
+unsigned int sh7751systemh_readl(unsigned long addr)
+{
+ return *(volatile unsigned long*)addr;
+}
+
+void sh7751systemh_writeb(unsigned char b, unsigned long addr)
+{
+ *(volatile unsigned char*)addr = b;
+}
+
+void sh7751systemh_writew(unsigned short b, unsigned long addr)
+{
+ *(volatile unsigned short*)addr = b;
+}
+
+void sh7751systemh_writel(unsigned int b, unsigned long addr)
+{
+ *(volatile unsigned long*)addr = b;
+}
+
+
+
+/* Map ISA bus address to the real address. Only for PCMCIA. */
+
+/* ISA page descriptor. */
+static __u32 sh_isa_memmap[256];
+
+#if 0
+static int
+sh_isa_mmap(__u32 start, __u32 length, __u32 offset)
+{
+ int idx;
+
+ if (start >= 0x100000 || (start & 0xfff) || (length != 0x1000))
+ return -1;
+
+ idx = start >> 12;
+ sh_isa_memmap[idx] = 0xb8000000 + (offset &~ 0xfff);
+ printk("sh_isa_mmap: start %x len %x offset %x (idx %x paddr %x)\n",
+ start, length, offset, idx, sh_isa_memmap[idx]);
+ return 0;
+}
+#endif
+
+unsigned long
+sh7751systemh_isa_port2addr(unsigned long offset)
+{
+ int idx;
+
+ idx = (offset >> 12) & 0xff;
+ offset &= 0xfff;
+ return sh_isa_memmap[idx] + offset;
+}
diff --git a/arch/sh/boards/renesas/systemh/irq.c b/arch/sh/boards/renesas/systemh/irq.c
new file mode 100644
index 000000000000..5675a4134eee
--- /dev/null
+++ b/arch/sh/boards/renesas/systemh/irq.c
@@ -0,0 +1,111 @@
+/*
+ * linux/arch/sh/boards/systemh/irq.c
+ *
+ * Copyright (C) 2000 Kazumoto Kojima
+ *
+ * Hitachi SystemH Support.
+ *
+ * Modified for 7751 SystemH by
+ * Jonathan Short.
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+
+#include <linux/hdreg.h>
+#include <linux/ide.h>
+#include <asm/io.h>
+#include <asm/mach/7751systemh.h>
+#include <asm/smc37c93x.h>
+
+/* address of external interrupt mask register
+ * address must be set prior to use these (maybe in init_XXX_irq())
+ * XXX : is it better to use .config than specifying it in code? */
+static unsigned long *systemh_irq_mask_register = (unsigned long *)0xB3F10004;
+static unsigned long *systemh_irq_request_register = (unsigned long *)0xB3F10000;
+
+/* forward declaration */
+static unsigned int startup_systemh_irq(unsigned int irq);
+static void shutdown_systemh_irq(unsigned int irq);
+static void enable_systemh_irq(unsigned int irq);
+static void disable_systemh_irq(unsigned int irq);
+static void mask_and_ack_systemh(unsigned int);
+static void end_systemh_irq(unsigned int irq);
+
+/* hw_interrupt_type */
+static struct hw_interrupt_type systemh_irq_type = {
+ " SystemH Register",
+ startup_systemh_irq,
+ shutdown_systemh_irq,
+ enable_systemh_irq,
+ disable_systemh_irq,
+ mask_and_ack_systemh,
+ end_systemh_irq
+};
+
+static unsigned int startup_systemh_irq(unsigned int irq)
+{
+ enable_systemh_irq(irq);
+ return 0; /* never anything pending */
+}
+
+static void shutdown_systemh_irq(unsigned int irq)
+{
+ disable_systemh_irq(irq);
+}
+
+static void disable_systemh_irq(unsigned int irq)
+{
+ if (systemh_irq_mask_register) {
+ unsigned long flags;
+ unsigned long val, mask = 0x01 << 1;
+
+ /* Clear the "irq"th bit in the mask and set it in the request */
+ local_irq_save(flags);
+
+ val = ctrl_inl((unsigned long)systemh_irq_mask_register);
+ val &= ~mask;
+ ctrl_outl(val, (unsigned long)systemh_irq_mask_register);
+
+ val = ctrl_inl((unsigned long)systemh_irq_request_register);
+ val |= mask;
+ ctrl_outl(val, (unsigned long)systemh_irq_request_register);
+
+ local_irq_restore(flags);
+ }
+}
+
+static void enable_systemh_irq(unsigned int irq)
+{
+ if (systemh_irq_mask_register) {
+ unsigned long flags;
+ unsigned long val, mask = 0x01 << 1;
+
+ /* Set "irq"th bit in the mask register */
+ local_irq_save(flags);
+ val = ctrl_inl((unsigned long)systemh_irq_mask_register);
+ val |= mask;
+ ctrl_outl(val, (unsigned long)systemh_irq_mask_register);
+ local_irq_restore(flags);
+ }
+}
+
+static void mask_and_ack_systemh(unsigned int irq)
+{
+ disable_systemh_irq(irq);
+}
+
+static void end_systemh_irq(unsigned int irq)
+{
+ if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+ enable_systemh_irq(irq);
+}
+
+void make_systemh_irq(unsigned int irq)
+{
+ disable_irq_nosync(irq);
+ irq_desc[irq].handler = &systemh_irq_type;
+ disable_systemh_irq(irq);
+}
+
diff --git a/arch/sh/boards/renesas/systemh/setup.c b/arch/sh/boards/renesas/systemh/setup.c
new file mode 100644
index 000000000000..826fa3d7669c
--- /dev/null
+++ b/arch/sh/boards/renesas/systemh/setup.c
@@ -0,0 +1,80 @@
+/*
+ * linux/arch/sh/boards/systemh/setup.c
+ *
+ * Copyright (C) 2000 Kazumoto Kojima
+ * Copyright (C) 2003 Paul Mundt
+ *
+ * Hitachi SystemH Support.
+ *
+ * Modified for 7751 SystemH by Jonathan Short.
+ *
+ * Rewritten for 2.6 by 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 <asm/mach/7751systemh.h>
+#include <asm/mach/io.h>
+#include <asm/machvec.h>
+
+extern void make_systemh_irq(unsigned int irq);
+
+const char *get_system_type(void)
+{
+ return "7751 SystemH";
+}
+
+/*
+ * Initialize IRQ setting
+ */
+void __init init_7751systemh_IRQ(void)
+{
+/* make_ipr_irq(10, BCR_ILCRD, 1, 0x0f-10); LAN */
+/* make_ipr_irq(14, BCR_ILCRA, 2, 0x0f-4); */
+ make_systemh_irq(0xb); /* Ethernet interrupt */
+}
+
+struct sh_machine_vector mv_7751systemh __initmv = {
+ .mv_nr_irqs = 72,
+
+ .mv_inb = sh7751systemh_inb,
+ .mv_inw = sh7751systemh_inw,
+ .mv_inl = sh7751systemh_inl,
+ .mv_outb = sh7751systemh_outb,
+ .mv_outw = sh7751systemh_outw,
+ .mv_outl = sh7751systemh_outl,
+
+ .mv_inb_p = sh7751systemh_inb_p,
+ .mv_inw_p = sh7751systemh_inw,
+ .mv_inl_p = sh7751systemh_inl,
+ .mv_outb_p = sh7751systemh_outb_p,
+ .mv_outw_p = sh7751systemh_outw,
+ .mv_outl_p = sh7751systemh_outl,
+
+ .mv_insb = sh7751systemh_insb,
+ .mv_insw = sh7751systemh_insw,
+ .mv_insl = sh7751systemh_insl,
+ .mv_outsb = sh7751systemh_outsb,
+ .mv_outsw = sh7751systemh_outsw,
+ .mv_outsl = sh7751systemh_outsl,
+
+ .mv_readb = sh7751systemh_readb,
+ .mv_readw = sh7751systemh_readw,
+ .mv_readl = sh7751systemh_readl,
+ .mv_writeb = sh7751systemh_writeb,
+ .mv_writew = sh7751systemh_writew,
+ .mv_writel = sh7751systemh_writel,
+
+ .mv_isa_port2addr = sh7751systemh_isa_port2addr,
+
+ .mv_init_irq = init_7751systemh_IRQ,
+};
+ALIAS_MV(7751systemh)
+
+int __init platform_setup(void)
+{
+ return 0;
+}
+
diff --git a/arch/sh/boards/saturn/Makefile b/arch/sh/boards/saturn/Makefile
new file mode 100644
index 000000000000..75a3042e252e
--- /dev/null
+++ b/arch/sh/boards/saturn/Makefile
@@ -0,0 +1,8 @@
+#
+# Makefile for the Sega Saturn specific parts of the kernel
+#
+
+obj-y := setup.o io.o irq.o
+
+obj-$(CONFIG_SMP) += smp.o
+
diff --git a/arch/sh/boards/saturn/io.c b/arch/sh/boards/saturn/io.c
new file mode 100644
index 000000000000..c6e4f7f2e686
--- /dev/null
+++ b/arch/sh/boards/saturn/io.c
@@ -0,0 +1,26 @@
+/*
+ * arch/sh/boards/saturn/io.c
+ *
+ * I/O routines for the Sega Saturn.
+ *
+ * Copyright (C) 2002 Paul Mundt
+ *
+ * Released under the terms of the GNU GPL v2.0.
+ */
+#include <asm/saturn/io.h>
+#include <asm/machvec.h>
+
+unsigned long saturn_isa_port2addr(unsigned long offset)
+{
+ return offset;
+}
+
+void *saturn_ioremap(unsigned long offset, unsigned long size)
+{
+ return (void *)offset;
+}
+
+void saturn_iounmap(void *addr)
+{
+}
+
diff --git a/arch/sh/boards/saturn/irq.c b/arch/sh/boards/saturn/irq.c
new file mode 100644
index 000000000000..15d1d3f0f787
--- /dev/null
+++ b/arch/sh/boards/saturn/irq.c
@@ -0,0 +1,118 @@
+/*
+ * arch/sh/boards/saturn/irq.c
+ *
+ * Copyright (C) 2002 Paul Mundt
+ *
+ * Released under the terms of the GNU GPL v2.0.
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+
+/*
+ * Interrupts map out as follows:
+ *
+ * Vector Name Mask
+ *
+ * 64 VBLANKIN 0x0001
+ * 65 VBLANKOUT 0x0002
+ * 66 HBLANKIN 0x0004
+ * 67 TIMER0 0x0008
+ * 68 TIMER1 0x0010
+ * 69 DSPEND 0x0020
+ * 70 SOUNDREQUEST 0x0040
+ * 71 SYSTEMMANAGER 0x0080
+ * 72 PAD 0x0100
+ * 73 LEVEL2DMAEND 0x0200
+ * 74 LEVEL1DMAEND 0x0400
+ * 75 LEVEL0DMAEND 0x0800
+ * 76 DMAILLEGAL 0x1000
+ * 77 SRITEDRAWEND 0x2000
+ * 78 ABUS 0x8000
+ *
+ */
+#define SATURN_IRQ_MIN 64 /* VBLANKIN */
+#define SATURN_IRQ_MAX 78 /* ABUS */
+
+#define SATURN_IRQ_MASK 0xbfff
+
+static inline u32 saturn_irq_mask(unsigned int irq_nr)
+{
+ u32 mask;
+
+ mask = (1 << (irq_nr - SATURN_IRQ_MIN));
+ mask <<= (irq_nr == SATURN_IRQ_MAX);
+ mask &= SATURN_IRQ_MASK;
+
+ return mask;
+}
+
+static inline void mask_saturn_irq(unsigned int irq_nr)
+{
+ u32 mask;
+
+ mask = ctrl_inl(SATURN_IMR);
+ mask |= saturn_irq_mask(irq_nr);
+ ctrl_outl(mask, SATURN_IMR);
+}
+
+static inline void unmask_saturn_irq(unsigned int irq_nr)
+{
+ u32 mask;
+
+ mask = ctrl_inl(SATURN_IMR);
+ mask &= ~saturn_irq_mask(irq_nr);
+ ctrl_outl(mask, SATURN_IMR);
+}
+
+static void disable_saturn_irq(unsigned int irq_nr)
+{
+ mask_saturn_irq(irq_nr);
+}
+
+static void enable_saturn_irq(unsigned int irq_nr)
+{
+ unmask_saturn_irq(irq_nr);
+}
+
+static void mask_and_ack_saturn_irq(unsigned int irq_nr)
+{
+ mask_saturn_irq(irq_nr);
+}
+
+static void end_saturn_irq(unsigned int irq_nr)
+{
+ if (!(irq_desc[irq_nr].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
+ unmask_saturn_irq(irq_nr);
+}
+
+static unsigned int startup_saturn_irq(unsigned int irq_nr)
+{
+ unmask_saturn_irq(irq_nr);
+
+ return 0;
+}
+
+static void shutdown_saturn_irq(unsigned int irq_nr)
+{
+ mask_saturn_irq(irq_nr);
+}
+
+static struct hw_interrupt_type saturn_int = {
+ .typename = "Saturn",
+ .enable = enable_saturn_irq,
+ .disable = disable_saturn_irq,
+ .ack = mask_and_ack_saturn_irq,
+ .end = end_saturn_irq,
+ .startup = startup_saturn_irq,
+ .shutdown = shutdown_saturn_irq,
+};
+
+int saturn_irq_demux(int irq_nr)
+{
+ /* FIXME */
+ return irq_nr;
+}
+
diff --git a/arch/sh/boards/saturn/setup.c b/arch/sh/boards/saturn/setup.c
new file mode 100644
index 000000000000..bea6c572ad82
--- /dev/null
+++ b/arch/sh/boards/saturn/setup.c
@@ -0,0 +1,43 @@
+/*
+ * arch/sh/boards/saturn/setup.c
+ *
+ * Hardware support for the Sega Saturn.
+ *
+ * Copyright (c) 2002 Paul Mundt
+ *
+ * Released under the terms of the GNU GPL v2.0.
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+#include <asm/io.h>
+#include <asm/machvec.h>
+#include <asm/mach/io.h>
+
+extern int saturn_irq_demux(int irq_nr);
+
+const char *get_system_type(void)
+{
+ return "Sega Saturn";
+}
+
+/*
+ * The Machine Vector
+ */
+struct sh_machine_vector mv_saturn __initmv = {
+ .mv_nr_irqs = 80, /* Fix this later */
+
+ .mv_isa_port2addr = saturn_isa_port2addr,
+ .mv_irq_demux = saturn_irq_demux,
+
+ .mv_ioremap = saturn_ioremap,
+ .mv_iounmap = saturn_iounmap,
+};
+
+ALIAS_MV(saturn)
+
+int __init platform_setup(void)
+{
+ return 0;
+}
+
diff --git a/arch/sh/boards/saturn/smp.c b/arch/sh/boards/saturn/smp.c
new file mode 100644
index 000000000000..76460918c9cd
--- /dev/null
+++ b/arch/sh/boards/saturn/smp.c
@@ -0,0 +1,68 @@
+/*
+ * arch/sh/boards/saturn/smp.c
+ *
+ * SMP support for the Sega Saturn.
+ *
+ * Copyright (c) 2002 Paul Mundt
+ *
+ * Released under the terms of the GNU GPL v2.0.
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/smp.h>
+
+#include <asm/saturn/smpc.h>
+
+extern void start_secondary(void);
+
+void __smp_send_ipi(unsigned int cpu, unsigned int action)
+{
+ /* Nothing here yet .. */
+}
+
+unsigned int __smp_probe_cpus(void)
+{
+ /*
+ * This is just a straightforward master/slave configuration,
+ * and probing isn't really supported..
+ */
+ return 2;
+}
+
+/*
+ * We're only allowed to do byte-access to SMPC registers. In
+ * addition to which, we treat them as write-only, since
+ * reading from them will return undefined data.
+ */
+static inline void smpc_slave_stop(unsigned int cpu)
+{
+ smpc_barrier();
+ ctrl_outb(1, SMPC_STATUS);
+
+ ctrl_outb(SMPC_CMD_SSHOFF, SMPC_COMMAND);
+ smpc_barrier();
+}
+
+static inline void smpc_slave_start(unsigned int cpu)
+{
+ ctrl_outb(1, SMPC_STATUS);
+ ctrl_outb(SMPC_CMD_SSHON, SMPC_COMMAND);
+
+ smpc_barrier();
+}
+
+void __smp_slave_init(unsigned int cpu)
+{
+ register unsigned long vbr;
+ void **entry;
+
+ __asm__ __volatile__ ("stc vbr, %0\n\t" : "=r" (vbr));
+ entry = (void **)(vbr + 0x310 + 0x94);
+
+ smpc_slave_stop(cpu);
+
+ *(void **)entry = (void *)start_secondary;
+
+ smpc_slave_start(cpu);
+}
+
diff --git a/arch/sh/boards/se/7300/Makefile b/arch/sh/boards/se/7300/Makefile
new file mode 100644
index 000000000000..0fbd4f47815c
--- /dev/null
+++ b/arch/sh/boards/se/7300/Makefile
@@ -0,0 +1,7 @@
+#
+# Makefile for the 7300 SolutionEngine specific parts of the kernel
+#
+
+obj-y := setup.o io.o irq.o
+
+obj-$(CONFIG_HEARTBEAT) += led.o
diff --git a/arch/sh/boards/se/7300/io.c b/arch/sh/boards/se/7300/io.c
new file mode 100644
index 000000000000..3c89def46480
--- /dev/null
+++ b/arch/sh/boards/se/7300/io.c
@@ -0,0 +1,265 @@
+/*
+ * arch/sh/boards/se/7300/io.c
+ *
+ * Copyright (C) 2003 YOSHII Takashi <yoshii-takashi@hitachi-ul.co.jp>
+ * Based on arch/sh/kernel/io_shmse.c
+ *
+ * I/O routine for SH-Mobile3 73180 SolutionEngine.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <asm/mach/se7300.h>
+#include <asm/io.h>
+
+#define badio(fn, a) panic("bad i/o operation %s for %08lx.", #fn, a)
+
+struct iop {
+ unsigned long start, end;
+ unsigned long base;
+ struct iop *(*check) (struct iop * p, unsigned long port);
+ unsigned char (*inb) (struct iop * p, unsigned long port);
+ unsigned short (*inw) (struct iop * p, unsigned long port);
+ void (*outb) (struct iop * p, unsigned char value, unsigned long port);
+ void (*outw) (struct iop * p, unsigned short value, unsigned long port);
+};
+
+struct iop *
+simple_check(struct iop *p, unsigned long port)
+{
+ if ((p->start <= port) && (port <= p->end))
+ return p;
+ else
+ badio(check, port);
+}
+
+struct iop *
+ide_check(struct iop *p, unsigned long port)
+{
+ if (((0x1f0 <= port) && (port <= 0x1f7)) || (port == 0x3f7))
+ return p;
+ return NULL;
+}
+
+unsigned char
+simple_inb(struct iop *p, unsigned long port)
+{
+ return *(unsigned char *) (p->base + port);
+}
+
+unsigned short
+simple_inw(struct iop *p, unsigned long port)
+{
+ return *(unsigned short *) (p->base + port);
+}
+
+void
+simple_outb(struct iop *p, unsigned char value, unsigned long port)
+{
+ *(unsigned char *) (p->base + port) = value;
+}
+
+void
+simple_outw(struct iop *p, unsigned short value, unsigned long port)
+{
+ *(unsigned short *) (p->base + port) = value;
+}
+
+unsigned char
+pcc_inb(struct iop *p, unsigned long port)
+{
+ unsigned long addr = p->base + port + 0x40000;
+ unsigned long v;
+
+ if (port & 1)
+ addr += 0x00400000;
+ v = *(volatile unsigned char *) addr;
+ return v;
+}
+
+void
+pcc_outb(struct iop *p, unsigned char value, unsigned long port)
+{
+ unsigned long addr = p->base + port + 0x40000;
+
+ if (port & 1)
+ addr += 0x00400000;
+ *(volatile unsigned char *) addr = value;
+}
+
+unsigned char
+bad_inb(struct iop *p, unsigned long port)
+{
+ badio(inb, port);
+}
+
+void
+bad_outb(struct iop *p, unsigned char value, unsigned long port)
+{
+ badio(inw, port);
+}
+
+/* MSTLANEX01 LAN at 0xb400:0000 */
+static struct iop laniop = {
+ .start = 0x300,
+ .end = 0x30f,
+ .base = 0xb4000000,
+ .check = simple_check,
+ .inb = simple_inb,
+ .inw = simple_inw,
+ .outb = simple_outb,
+ .outw = simple_outw,
+};
+
+/* NE2000 pc card NIC */
+static struct iop neiop = {
+ .start = 0x280,
+ .end = 0x29f,
+ .base = 0xb0600000 + 0x80, /* soft 0x280 -> hard 0x300 */
+ .check = simple_check,
+ .inb = pcc_inb,
+ .inw = simple_inw,
+ .outb = pcc_outb,
+ .outw = simple_outw,
+};
+
+/* CF in CF slot */
+static struct iop cfiop = {
+ .base = 0xb0600000,
+ .check = ide_check,
+ .inb = pcc_inb,
+ .inw = simple_inw,
+ .outb = pcc_outb,
+ .outw = simple_outw,
+};
+
+static __inline__ struct iop *
+port2iop(unsigned long port)
+{
+ if (0) ;
+#if defined(CONFIG_SMC91111)
+ else if (laniop.check(&laniop, port))
+ return &laniop;
+#endif
+#if defined(CONFIG_NE2000)
+ else if (neiop.check(&neiop, port))
+ return &neiop;
+#endif
+#if defined(CONFIG_IDE)
+ else if (cfiop.check(&cfiop, port))
+ return &cfiop;
+#endif
+ else
+ return &neiop; /* fallback */
+}
+
+static inline void
+delay(void)
+{
+ ctrl_inw(0xac000000);
+ ctrl_inw(0xac000000);
+}
+
+unsigned char
+sh7300se_inb(unsigned long port)
+{
+ struct iop *p = port2iop(port);
+ return (p->inb) (p, port);
+}
+
+unsigned char
+sh7300se_inb_p(unsigned long port)
+{
+ unsigned char v = sh7300se_inb(port);
+ delay();
+ return v;
+}
+
+unsigned short
+sh7300se_inw(unsigned long port)
+{
+ struct iop *p = port2iop(port);
+ return (p->inw) (p, port);
+}
+
+unsigned int
+sh7300se_inl(unsigned long port)
+{
+ badio(inl, port);
+}
+
+void
+sh7300se_outb(unsigned char value, unsigned long port)
+{
+ struct iop *p = port2iop(port);
+ (p->outb) (p, value, port);
+}
+
+void
+sh7300se_outb_p(unsigned char value, unsigned long port)
+{
+ sh7300se_outb(value, port);
+ delay();
+}
+
+void
+sh7300se_outw(unsigned short value, unsigned long port)
+{
+ struct iop *p = port2iop(port);
+ (p->outw) (p, value, port);
+}
+
+void
+sh7300se_outl(unsigned int value, unsigned long port)
+{
+ badio(outl, port);
+}
+
+void
+sh7300se_insb(unsigned long port, void *addr, unsigned long count)
+{
+ unsigned char *a = addr;
+ struct iop *p = port2iop(port);
+ while (count--)
+ *a++ = (p->inb) (p, port);
+}
+
+void
+sh7300se_insw(unsigned long port, void *addr, unsigned long count)
+{
+ unsigned short *a = addr;
+ struct iop *p = port2iop(port);
+ while (count--)
+ *a++ = (p->inw) (p, port);
+}
+
+void
+sh7300se_insl(unsigned long port, void *addr, unsigned long count)
+{
+ badio(insl, port);
+}
+
+void
+sh7300se_outsb(unsigned long port, const void *addr, unsigned long count)
+{
+ unsigned char *a = (unsigned char *) addr;
+ struct iop *p = port2iop(port);
+ while (count--)
+ (p->outb) (p, *a++, port);
+}
+
+void
+sh7300se_outsw(unsigned long port, const void *addr, unsigned long count)
+{
+ unsigned short *a = (unsigned short *) addr;
+ struct iop *p = port2iop(port);
+ while (count--)
+ (p->outw) (p, *a++, port);
+}
+
+void
+sh7300se_outsl(unsigned long port, const void *addr, unsigned long count)
+{
+ badio(outsw, port);
+}
diff --git a/arch/sh/boards/se/7300/irq.c b/arch/sh/boards/se/7300/irq.c
new file mode 100644
index 000000000000..96c8c23d6c93
--- /dev/null
+++ b/arch/sh/boards/se/7300/irq.c
@@ -0,0 +1,37 @@
+/*
+ * linux/arch/sh/boards/se/7300/irq.c
+ *
+ * Copyright (C) 2003 Takashi Kusuda <kusuda-takashi@hitachi-ul.co.jp>
+ *
+ * SH-Mobile SolutionEngine 7300 Support.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+#include <asm/mach/se7300.h>
+
+/*
+ * Initialize IRQ setting
+ */
+void __init
+init_7300se_IRQ(void)
+{
+ ctrl_outw(0x0028, PA_EPLD_MODESET); /* mode set IRQ0,1 active low. */
+ ctrl_outw(0xa000, INTC_ICR1); /* IRQ mode; IRQ0,1 enable. */
+ ctrl_outw(0x0000, PORT_PFCR); /* use F for IRQ[3:0] and SIU. */
+
+ /* PC_IRQ[0-3] -> IRQ0 (32) */
+ make_ipr_irq(IRQ0_IRQ, IRQ0_IPR_ADDR, IRQ0_IPR_POS, 0x0f - IRQ0_IRQ);
+ /* A_IRQ[0-3] -> IRQ1 (33) */
+ make_ipr_irq(IRQ1_IRQ, IRQ1_IPR_ADDR, IRQ1_IPR_POS, 0x0f - IRQ1_IRQ);
+ make_ipr_irq(SIOF0_IRQ, SIOF0_IPR_ADDR, SIOF0_IPR_POS, SIOF0_PRIORITY);
+ make_ipr_irq(DMTE2_IRQ, DMA1_IPR_ADDR, DMA1_IPR_POS, DMA1_PRIORITY);
+ make_ipr_irq(DMTE3_IRQ, DMA1_IPR_ADDR, DMA1_IPR_POS, DMA1_PRIORITY);
+ make_ipr_irq(VIO_IRQ, VIO_IPR_ADDR, VIO_IPR_POS, VIO_PRIORITY);
+
+ ctrl_outw(0x2000, PA_MRSHPC + 0x0c); /* mrshpc irq enable */
+}
diff --git a/arch/sh/boards/se/7300/led.c b/arch/sh/boards/se/7300/led.c
new file mode 100644
index 000000000000..02c7f846c84c
--- /dev/null
+++ b/arch/sh/boards/se/7300/led.c
@@ -0,0 +1,69 @@
+/*
+ * linux/arch/sh/boards/se/7300/led.c
+ *
+ * Derived from linux/arch/sh/boards/se/770x/led.c
+ *
+ * Copyright (C) 2000 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.
+ *
+ * This file contains Solution Engine specific LED code.
+ */
+
+#include <linux/config.h>
+#include <linux/sched.h>
+#include <asm/mach/se7300.h>
+
+static void
+mach_led(int position, int value)
+{
+ volatile unsigned short *p = (volatile unsigned short *) PA_LED;
+
+ if (value) {
+ *p |= (1 << 8);
+ } else {
+ *p &= ~(1 << 8);
+ }
+}
+
+
+/* Cycle the LED's in the clasic Knightrider/Sun pattern */
+void
+heartbeat_7300se(void)
+{
+ static unsigned int cnt = 0, period = 0;
+ volatile unsigned short *p = (volatile unsigned short *) PA_LED;
+ static unsigned bit = 0, up = 1;
+
+ cnt += 1;
+ if (cnt < period) {
+ return;
+ }
+
+ cnt = 0;
+
+ /* Go through the points (roughly!):
+ * f(0)=10, f(1)=16, f(2)=20, f(5)=35,f(inf)->110
+ */
+ period = 110 - ((300 << FSHIFT) / ((avenrun[0] / 5) + (3 << FSHIFT)));
+
+ if (up) {
+ if (bit == 7) {
+ bit--;
+ up = 0;
+ } else {
+ bit++;
+ }
+ } else {
+ if (bit == 0) {
+ bit++;
+ up = 1;
+ } else {
+ bit--;
+ }
+ }
+ *p = 1 << (bit + 8);
+
+}
+
diff --git a/arch/sh/boards/se/7300/setup.c b/arch/sh/boards/se/7300/setup.c
new file mode 100644
index 000000000000..08536bc224dc
--- /dev/null
+++ b/arch/sh/boards/se/7300/setup.c
@@ -0,0 +1,66 @@
+/*
+ * linux/arch/sh/boards/se/7300/setup.c
+ *
+ * Copyright (C) 2003 Takashi Kusuda <kusuda-takashi@hitachi-ul.co.jp>
+ *
+ * SH-Mobile SolutionEngine 7300 Support.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <asm/machvec.h>
+#include <asm/machvec_init.h>
+#include <asm/mach/io.h>
+
+void heartbeat_7300se(void);
+void init_7300se_IRQ(void);
+
+const char *
+get_system_type(void)
+{
+ return "SolutionEngine 7300";
+}
+
+/*
+ * The Machine Vector
+ */
+
+struct sh_machine_vector mv_7300se __initmv = {
+ .mv_nr_irqs = 109,
+ .mv_inb = sh7300se_inb,
+ .mv_inw = sh7300se_inw,
+ .mv_inl = sh7300se_inl,
+ .mv_outb = sh7300se_outb,
+ .mv_outw = sh7300se_outw,
+ .mv_outl = sh7300se_outl,
+
+ .mv_inb_p = sh7300se_inb_p,
+ .mv_inw_p = sh7300se_inw,
+ .mv_inl_p = sh7300se_inl,
+ .mv_outb_p = sh7300se_outb_p,
+ .mv_outw_p = sh7300se_outw,
+ .mv_outl_p = sh7300se_outl,
+
+ .mv_insb = sh7300se_insb,
+ .mv_insw = sh7300se_insw,
+ .mv_insl = sh7300se_insl,
+ .mv_outsb = sh7300se_outsb,
+ .mv_outsw = sh7300se_outsw,
+ .mv_outsl = sh7300se_outsl,
+
+ .mv_init_irq = init_7300se_IRQ,
+#ifdef CONFIG_HEARTBEAT
+ .mv_heartbeat = heartbeat_7300se,
+#endif
+};
+
+ALIAS_MV(7300se)
+/*
+ * Initialize the board
+ */
+void __init
+platform_setup(void)
+{
+
+}
diff --git a/arch/sh/boards/se/73180/Makefile b/arch/sh/boards/se/73180/Makefile
new file mode 100644
index 000000000000..8f63886a0f3f
--- /dev/null
+++ b/arch/sh/boards/se/73180/Makefile
@@ -0,0 +1,7 @@
+#
+# Makefile for the 73180 SolutionEngine specific parts of the kernel
+#
+
+obj-y := setup.o io.o irq.o
+
+obj-$(CONFIG_HEARTBEAT) += led.o
diff --git a/arch/sh/boards/se/73180/io.c b/arch/sh/boards/se/73180/io.c
new file mode 100644
index 000000000000..73648cbe3678
--- /dev/null
+++ b/arch/sh/boards/se/73180/io.c
@@ -0,0 +1,265 @@
+/*
+ * arch/sh/boards/se/73180/io.c
+ *
+ * Copyright (C) 2003 YOSHII Takashi <yoshii-takashi@hitachi-ul.co.jp>
+ * Based on arch/sh/boards/se/7300/io.c
+ *
+ * I/O routine for SH-Mobile3 73180 SolutionEngine.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <asm/mach/se73180.h>
+#include <asm/io.h>
+
+#define badio(fn, a) panic("bad i/o operation %s for %08lx.", #fn, a)
+
+struct iop {
+ unsigned long start, end;
+ unsigned long base;
+ struct iop *(*check) (struct iop * p, unsigned long port);
+ unsigned char (*inb) (struct iop * p, unsigned long port);
+ unsigned short (*inw) (struct iop * p, unsigned long port);
+ void (*outb) (struct iop * p, unsigned char value, unsigned long port);
+ void (*outw) (struct iop * p, unsigned short value, unsigned long port);
+};
+
+struct iop *
+simple_check(struct iop *p, unsigned long port)
+{
+ if ((p->start <= port) && (port <= p->end))
+ return p;
+ else
+ badio(check, port);
+}
+
+struct iop *
+ide_check(struct iop *p, unsigned long port)
+{
+ if (((0x1f0 <= port) && (port <= 0x1f7)) || (port == 0x3f7))
+ return p;
+ return NULL;
+}
+
+unsigned char
+simple_inb(struct iop *p, unsigned long port)
+{
+ return *(unsigned char *) (p->base + port);
+}
+
+unsigned short
+simple_inw(struct iop *p, unsigned long port)
+{
+ return *(unsigned short *) (p->base + port);
+}
+
+void
+simple_outb(struct iop *p, unsigned char value, unsigned long port)
+{
+ *(unsigned char *) (p->base + port) = value;
+}
+
+void
+simple_outw(struct iop *p, unsigned short value, unsigned long port)
+{
+ *(unsigned short *) (p->base + port) = value;
+}
+
+unsigned char
+pcc_inb(struct iop *p, unsigned long port)
+{
+ unsigned long addr = p->base + port + 0x40000;
+ unsigned long v;
+
+ if (port & 1)
+ addr += 0x00400000;
+ v = *(volatile unsigned char *) addr;
+ return v;
+}
+
+void
+pcc_outb(struct iop *p, unsigned char value, unsigned long port)
+{
+ unsigned long addr = p->base + port + 0x40000;
+
+ if (port & 1)
+ addr += 0x00400000;
+ *(volatile unsigned char *) addr = value;
+}
+
+unsigned char
+bad_inb(struct iop *p, unsigned long port)
+{
+ badio(inb, port);
+}
+
+void
+bad_outb(struct iop *p, unsigned char value, unsigned long port)
+{
+ badio(inw, port);
+}
+
+/* MSTLANEX01 LAN at 0xb400:0000 */
+static struct iop laniop = {
+ .start = 0x300,
+ .end = 0x30f,
+ .base = 0xb4000000,
+ .check = simple_check,
+ .inb = simple_inb,
+ .inw = simple_inw,
+ .outb = simple_outb,
+ .outw = simple_outw,
+};
+
+/* NE2000 pc card NIC */
+static struct iop neiop = {
+ .start = 0x280,
+ .end = 0x29f,
+ .base = 0xb0600000 + 0x80, /* soft 0x280 -> hard 0x300 */
+ .check = simple_check,
+ .inb = pcc_inb,
+ .inw = simple_inw,
+ .outb = pcc_outb,
+ .outw = simple_outw,
+};
+
+/* CF in CF slot */
+static struct iop cfiop = {
+ .base = 0xb0600000,
+ .check = ide_check,
+ .inb = pcc_inb,
+ .inw = simple_inw,
+ .outb = pcc_outb,
+ .outw = simple_outw,
+};
+
+static __inline__ struct iop *
+port2iop(unsigned long port)
+{
+ if (0) ;
+#if defined(CONFIG_SMC91111)
+ else if (laniop.check(&laniop, port))
+ return &laniop;
+#endif
+#if defined(CONFIG_NE2000)
+ else if (neiop.check(&neiop, port))
+ return &neiop;
+#endif
+#if defined(CONFIG_IDE)
+ else if (cfiop.check(&cfiop, port))
+ return &cfiop;
+#endif
+ else
+ return &neiop; /* fallback */
+}
+
+static inline void
+delay(void)
+{
+ ctrl_inw(0xac000000);
+ ctrl_inw(0xac000000);
+}
+
+unsigned char
+sh73180se_inb(unsigned long port)
+{
+ struct iop *p = port2iop(port);
+ return (p->inb) (p, port);
+}
+
+unsigned char
+sh73180se_inb_p(unsigned long port)
+{
+ unsigned char v = sh73180se_inb(port);
+ delay();
+ return v;
+}
+
+unsigned short
+sh73180se_inw(unsigned long port)
+{
+ struct iop *p = port2iop(port);
+ return (p->inw) (p, port);
+}
+
+unsigned int
+sh73180se_inl(unsigned long port)
+{
+ badio(inl, port);
+}
+
+void
+sh73180se_outb(unsigned char value, unsigned long port)
+{
+ struct iop *p = port2iop(port);
+ (p->outb) (p, value, port);
+}
+
+void
+sh73180se_outb_p(unsigned char value, unsigned long port)
+{
+ sh73180se_outb(value, port);
+ delay();
+}
+
+void
+sh73180se_outw(unsigned short value, unsigned long port)
+{
+ struct iop *p = port2iop(port);
+ (p->outw) (p, value, port);
+}
+
+void
+sh73180se_outl(unsigned int value, unsigned long port)
+{
+ badio(outl, port);
+}
+
+void
+sh73180se_insb(unsigned long port, void *addr, unsigned long count)
+{
+ unsigned char *a = addr;
+ struct iop *p = port2iop(port);
+ while (count--)
+ *a++ = (p->inb) (p, port);
+}
+
+void
+sh73180se_insw(unsigned long port, void *addr, unsigned long count)
+{
+ unsigned short *a = addr;
+ struct iop *p = port2iop(port);
+ while (count--)
+ *a++ = (p->inw) (p, port);
+}
+
+void
+sh73180se_insl(unsigned long port, void *addr, unsigned long count)
+{
+ badio(insl, port);
+}
+
+void
+sh73180se_outsb(unsigned long port, const void *addr, unsigned long count)
+{
+ unsigned char *a = (unsigned char *) addr;
+ struct iop *p = port2iop(port);
+ while (count--)
+ (p->outb) (p, *a++, port);
+}
+
+void
+sh73180se_outsw(unsigned long port, const void *addr, unsigned long count)
+{
+ unsigned short *a = (unsigned short *) addr;
+ struct iop *p = port2iop(port);
+ while (count--)
+ (p->outw) (p, *a++, port);
+}
+
+void
+sh73180se_outsl(unsigned long port, const void *addr, unsigned long count)
+{
+ badio(outsw, port);
+}
diff --git a/arch/sh/boards/se/73180/irq.c b/arch/sh/boards/se/73180/irq.c
new file mode 100644
index 000000000000..70f04caad9a4
--- /dev/null
+++ b/arch/sh/boards/se/73180/irq.c
@@ -0,0 +1,137 @@
+/*
+ * arch/sh/boards/se/73180/irq.c
+ *
+ * Copyright (C) 2003 Takashi Kusuda <kusuda-takashi@hitachi-ul.co.jp>
+ * Based on arch/sh/boards/se/7300/irq.c
+ *
+ * Modified for SH-Mobile SolutionEngine 73180 Support
+ * by YOSHII Takashi <yoshii-takashi@hitachi-ul.co.jp>
+ *
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+#include <asm/mach/se73180.h>
+
+static int
+intreq2irq(int i)
+{
+ if (i == 5)
+ return 10;
+ return 32 + 7 - i;
+}
+
+static int
+irq2intreq(int irq)
+{
+ if (irq == 10)
+ return 5;
+ return 7 - (irq - 32);
+}
+
+static void
+disable_intreq_irq(unsigned int irq)
+{
+ ctrl_outb(1 << (7 - irq2intreq(irq)), INTMSK0);
+}
+
+static void
+enable_intreq_irq(unsigned int irq)
+{
+ ctrl_outb(1 << (7 - irq2intreq(irq)), INTMSKCLR0);
+}
+
+static void
+mask_and_ack_intreq_irq(unsigned int irq)
+{
+ disable_intreq_irq(irq);
+}
+
+static unsigned int
+startup_intreq_irq(unsigned int irq)
+{
+ enable_intreq_irq(irq);
+ return 0;
+}
+
+static void
+shutdown_intreq_irq(unsigned int irq)
+{
+ disable_intreq_irq(irq);
+}
+
+static void
+end_intreq_irq(unsigned int irq)
+{
+ if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
+ enable_intreq_irq(irq);
+}
+
+static struct hw_interrupt_type intreq_irq_type = {
+ .typename = "intreq",
+ .startup = startup_intreq_irq,
+ .shutdown = shutdown_intreq_irq,
+ .enable = enable_intreq_irq,
+ .disable = disable_intreq_irq,
+ .ack = mask_and_ack_intreq_irq,
+ .end = end_intreq_irq
+};
+
+void
+make_intreq_irq(unsigned int irq)
+{
+ disable_irq_nosync(irq);
+ irq_desc[irq].handler = &intreq_irq_type;
+ disable_intreq_irq(irq);
+}
+
+int
+shmse_irq_demux(int irq)
+{
+ if (irq == IRQ5_IRQ)
+ return 10;
+ return irq;
+}
+
+/*
+ * Initialize IRQ setting
+ */
+void __init
+init_73180se_IRQ(void)
+{
+ make_ipr_irq(SIOF0_IRQ, SIOF0_IPR_ADDR, SIOF0_IPR_POS, SIOF0_PRIORITY);
+
+ ctrl_outw(0x2000, 0xb03fffec); /* mrshpc irq enable */
+ ctrl_outw(0x2000, 0xb07fffec); /* mrshpc irq enable */
+ ctrl_outl(3 << ((7 - 5) * 4), INTC_INTPRI0); /* irq5 pri=3 */
+ ctrl_outw(2 << ((7 - 5) * 2), INTC_ICR1); /* low-level irq */
+ make_intreq_irq(10);
+
+ make_ipr_irq(VPU_IRQ, VPU_IPR_ADDR, VPU_IPR_POS, 8);
+
+ ctrl_outb(0x0f, INTC_IMCR5); /* enable SCIF IRQ */
+
+ make_ipr_irq(DMTE2_IRQ, DMA1_IPR_ADDR, DMA1_IPR_POS, DMA1_PRIORITY);
+ make_ipr_irq(DMTE3_IRQ, DMA1_IPR_ADDR, DMA1_IPR_POS, DMA1_PRIORITY);
+ make_ipr_irq(DMTE4_IRQ, DMA2_IPR_ADDR, DMA2_IPR_POS, DMA2_PRIORITY);
+ make_ipr_irq(IIC0_ALI_IRQ, IIC0_IPR_ADDR, IIC0_IPR_POS, IIC0_PRIORITY);
+ make_ipr_irq(IIC0_TACKI_IRQ, IIC0_IPR_ADDR, IIC0_IPR_POS,
+ IIC0_PRIORITY);
+ make_ipr_irq(IIC0_WAITI_IRQ, IIC0_IPR_ADDR, IIC0_IPR_POS,
+ IIC0_PRIORITY);
+ make_ipr_irq(IIC0_DTEI_IRQ, IIC0_IPR_ADDR, IIC0_IPR_POS, IIC0_PRIORITY);
+ make_ipr_irq(SIOF0_IRQ, SIOF0_IPR_ADDR, SIOF0_IPR_POS, SIOF0_PRIORITY);
+ make_ipr_irq(SIU_IRQ, SIU_IPR_ADDR, SIU_IPR_POS, SIU_PRIORITY);
+
+ /* VIO interrupt */
+ make_ipr_irq(CEU_IRQ, VIO_IPR_ADDR, VIO_IPR_POS, VIO_PRIORITY);
+ make_ipr_irq(BEU_IRQ, VIO_IPR_ADDR, VIO_IPR_POS, VIO_PRIORITY);
+ make_ipr_irq(VEU_IRQ, VIO_IPR_ADDR, VIO_IPR_POS, VIO_PRIORITY);
+
+ make_ipr_irq(LCDC_IRQ, LCDC_IPR_ADDR, LCDC_IPR_POS, LCDC_PRIORITY);
+ ctrl_outw(0x2000, PA_MRSHPC + 0x0c); /* mrshpc irq enable */
+}
diff --git a/arch/sh/boards/se/73180/led.c b/arch/sh/boards/se/73180/led.c
new file mode 100644
index 000000000000..1e8f1cf3e10f
--- /dev/null
+++ b/arch/sh/boards/se/73180/led.c
@@ -0,0 +1,67 @@
+/*
+ * arch/sh/boards/se/73180/led.c
+ *
+ * Derived from arch/sh/boards/se/770x/led.c
+ *
+ * Copyright (C) 2000 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.
+ *
+ * This file contains Solution Engine specific LED code.
+ */
+
+#include <linux/config.h>
+#include <linux/sched.h>
+#include <asm/mach/se73180.h>
+
+static void
+mach_led(int position, int value)
+{
+ volatile unsigned short *p = (volatile unsigned short *) PA_LED;
+
+ if (value) {
+ *p |= (1 << LED_SHIFT);
+ } else {
+ *p &= ~(1 << LED_SHIFT);
+ }
+}
+
+/* Cycle the LED's in the clasic Knightrider/Sun pattern */
+void
+heartbeat_73180se(void)
+{
+ static unsigned int cnt = 0, period = 0;
+ volatile unsigned short *p = (volatile unsigned short *) PA_LED;
+ static unsigned bit = 0, up = 1;
+
+ cnt += 1;
+ if (cnt < period) {
+ return;
+ }
+
+ cnt = 0;
+
+ /* Go through the points (roughly!):
+ * f(0)=10, f(1)=16, f(2)=20, f(5)=35,f(inf)->110
+ */
+ period = 110 - ((300 << FSHIFT) / ((avenrun[0] / 5) + (3 << FSHIFT)));
+
+ if (up) {
+ if (bit == 7) {
+ bit--;
+ up = 0;
+ } else {
+ bit++;
+ }
+ } else {
+ if (bit == 0) {
+ bit++;
+ up = 1;
+ } else {
+ bit--;
+ }
+ }
+ *p = 1 << (bit + LED_SHIFT);
+
+}
diff --git a/arch/sh/boards/se/73180/setup.c b/arch/sh/boards/se/73180/setup.c
new file mode 100644
index 000000000000..07fa90c38a06
--- /dev/null
+++ b/arch/sh/boards/se/73180/setup.c
@@ -0,0 +1,68 @@
+/*
+ * arch/sh/boards/se/73180/setup.c
+ *
+ * Copyright (C) 2003 Takashi Kusuda <kusuda-takashi@hitachi-ul.co.jp>
+ * Based on arch/sh/setup_shmse.c
+ *
+ * Modified for 73180 SolutionEngine
+ * by YOSHII Takashi <yoshii-takashi@hitachi-ul.co.jp>
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <asm/machvec.h>
+#include <asm/machvec_init.h>
+#include <asm/mach/io.h>
+
+void heartbeat_73180se(void);
+void init_73180se_IRQ(void);
+
+const char *
+get_system_type(void)
+{
+ return "SolutionEngine 73180";
+}
+
+/*
+ * The Machine Vector
+ */
+
+struct sh_machine_vector mv_73180se __initmv = {
+ .mv_nr_irqs = 108,
+ .mv_inb = sh73180se_inb,
+ .mv_inw = sh73180se_inw,
+ .mv_inl = sh73180se_inl,
+ .mv_outb = sh73180se_outb,
+ .mv_outw = sh73180se_outw,
+ .mv_outl = sh73180se_outl,
+
+ .mv_inb_p = sh73180se_inb_p,
+ .mv_inw_p = sh73180se_inw,
+ .mv_inl_p = sh73180se_inl,
+ .mv_outb_p = sh73180se_outb_p,
+ .mv_outw_p = sh73180se_outw,
+ .mv_outl_p = sh73180se_outl,
+
+ .mv_insb = sh73180se_insb,
+ .mv_insw = sh73180se_insw,
+ .mv_insl = sh73180se_insl,
+ .mv_outsb = sh73180se_outsb,
+ .mv_outsw = sh73180se_outsw,
+ .mv_outsl = sh73180se_outsl,
+
+ .mv_init_irq = init_73180se_IRQ,
+#ifdef CONFIG_HEARTBEAT
+ .mv_heartbeat = heartbeat_73180se,
+#endif
+};
+
+ALIAS_MV(73180se)
+/*
+ * Initialize the board
+ */
+void __init
+platform_setup(void)
+{
+
+}
diff --git a/arch/sh/boards/se/770x/Makefile b/arch/sh/boards/se/770x/Makefile
new file mode 100644
index 000000000000..be89a73cc418
--- /dev/null
+++ b/arch/sh/boards/se/770x/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for the 770x SolutionEngine specific parts of the kernel
+#
+
+obj-y := mach.o setup.o io.o irq.o led.o
+
diff --git a/arch/sh/boards/se/770x/io.c b/arch/sh/boards/se/770x/io.c
new file mode 100644
index 000000000000..9a39ee963143
--- /dev/null
+++ b/arch/sh/boards/se/770x/io.c
@@ -0,0 +1,226 @@
+/* $Id: io.c,v 1.5 2004/02/22 23:08:43 kkojima Exp $
+ *
+ * linux/arch/sh/kernel/io_se.c
+ *
+ * Copyright (C) 2000 Kazumoto Kojima
+ *
+ * I/O routine for Hitachi SolutionEngine.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <asm/io.h>
+#include <asm/se/se.h>
+
+/* SH pcmcia io window base, start and end. */
+int sh_pcic_io_wbase = 0xb8400000;
+int sh_pcic_io_start;
+int sh_pcic_io_stop;
+int sh_pcic_io_type;
+int sh_pcic_io_dummy;
+
+static inline void delay(void)
+{
+ ctrl_inw(0xa0000000);
+}
+
+/* MS7750 requires special versions of in*, out* routines, since
+ PC-like io ports are located at upper half byte of 16-bit word which
+ can be accessed only with 16-bit wide. */
+
+static inline volatile __u16 *
+port2adr(unsigned int port)
+{
+ if (port >= 0x2000)
+ return (volatile __u16 *) (PA_MRSHPC + (port - 0x2000));
+ else if (port >= 0x1000)
+ return (volatile __u16 *) (PA_83902 + (port << 1));
+ else if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop)
+ return (volatile __u16 *) (sh_pcic_io_wbase + (port &~ 1));
+ else
+ return (volatile __u16 *) (PA_SUPERIO + (port << 1));
+}
+
+static inline int
+shifted_port(unsigned long port)
+{
+ /* For IDE registers, value is not shifted */
+ if ((0x1f0 <= port && port < 0x1f8) || port == 0x3f6)
+ return 0;
+ else
+ return 1;
+}
+
+#define maybebadio(name,port) \
+ printk("bad PC-like io %s for port 0x%lx at 0x%08x\n", \
+ #name, (port), (__u32) __builtin_return_address(0))
+
+unsigned char se_inb(unsigned long port)
+{
+ if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop)
+ return *(__u8 *) (sh_pcic_io_wbase + 0x40000 + port);
+ else if (shifted_port(port))
+ return (*port2adr(port) >> 8);
+ else
+ return (*port2adr(port))&0xff;
+}
+
+unsigned char se_inb_p(unsigned long port)
+{
+ unsigned long v;
+
+ if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop)
+ v = *(__u8 *) (sh_pcic_io_wbase + 0x40000 + port);
+ else if (shifted_port(port))
+ v = (*port2adr(port) >> 8);
+ else
+ v = (*port2adr(port))&0xff;
+ delay();
+ return v;
+}
+
+unsigned short se_inw(unsigned long port)
+{
+ if (port >= 0x2000 ||
+ (sh_pcic_io_start <= port && port <= sh_pcic_io_stop))
+ return *port2adr(port);
+ else
+ maybebadio(inw, port);
+ return 0;
+}
+
+unsigned int se_inl(unsigned long port)
+{
+ maybebadio(inl, port);
+ return 0;
+}
+
+void se_outb(unsigned char value, unsigned long port)
+{
+ if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop)
+ *(__u8 *)(sh_pcic_io_wbase + port) = value;
+ else if (shifted_port(port))
+ *(port2adr(port)) = value << 8;
+ else
+ *(port2adr(port)) = value;
+}
+
+void se_outb_p(unsigned char value, unsigned long port)
+{
+ if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop)
+ *(__u8 *)(sh_pcic_io_wbase + port) = value;
+ else if (shifted_port(port))
+ *(port2adr(port)) = value << 8;
+ else
+ *(port2adr(port)) = value;
+ delay();
+}
+
+void se_outw(unsigned short value, unsigned long port)
+{
+ if (port >= 0x2000 ||
+ (sh_pcic_io_start <= port && port <= sh_pcic_io_stop))
+ *port2adr(port) = value;
+ else
+ maybebadio(outw, port);
+}
+
+void se_outl(unsigned int value, unsigned long port)
+{
+ maybebadio(outl, port);
+}
+
+void se_insb(unsigned long port, void *addr, unsigned long count)
+{
+ volatile __u16 *p = port2adr(port);
+ __u8 *ap = addr;
+
+ if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop) {
+ volatile __u8 *bp = (__u8 *) (sh_pcic_io_wbase + 0x40000 + port);
+ while (count--)
+ *ap++ = *bp;
+ } else if (shifted_port(port)) {
+ while (count--)
+ *ap++ = *p >> 8;
+ } else {
+ while (count--)
+ *ap++ = *p;
+ }
+}
+
+void se_insw(unsigned long port, void *addr, unsigned long count)
+{
+ volatile __u16 *p = port2adr(port);
+ __u16 *ap = addr;
+ while (count--)
+ *ap++ = *p;
+}
+
+void se_insl(unsigned long port, void *addr, unsigned long count)
+{
+ maybebadio(insl, port);
+}
+
+void se_outsb(unsigned long port, const void *addr, unsigned long count)
+{
+ volatile __u16 *p = port2adr(port);
+ const __u8 *ap = addr;
+
+ if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop) {
+ volatile __u8 *bp = (__u8 *) (sh_pcic_io_wbase + port);
+ while (count--)
+ *bp = *ap++;
+ } else if (shifted_port(port)) {
+ while (count--)
+ *p = *ap++ << 8;
+ } else {
+ while (count--)
+ *p = *ap++;
+ }
+}
+
+void se_outsw(unsigned long port, const void *addr, unsigned long count)
+{
+ volatile __u16 *p = port2adr(port);
+ const __u16 *ap = addr;
+ while (count--)
+ *p = *ap++;
+}
+
+void se_outsl(unsigned long port, const void *addr, unsigned long count)
+{
+ maybebadio(outsw, port);
+}
+
+/* Map ISA bus address to the real address. Only for PCMCIA. */
+
+/* ISA page descriptor. */
+static __u32 sh_isa_memmap[256];
+
+static int
+sh_isa_mmap(__u32 start, __u32 length, __u32 offset)
+{
+ int idx;
+
+ if (start >= 0x100000 || (start & 0xfff) || (length != 0x1000))
+ return -1;
+
+ idx = start >> 12;
+ sh_isa_memmap[idx] = 0xb8000000 + (offset &~ 0xfff);
+#if 0
+ printk("sh_isa_mmap: start %x len %x offset %x (idx %x paddr %x)\n",
+ start, length, offset, idx, sh_isa_memmap[idx]);
+#endif
+ return 0;
+}
+
+unsigned long
+se_isa_port2addr(unsigned long offset)
+{
+ int idx;
+
+ idx = (offset >> 12) & 0xff;
+ offset &= 0xfff;
+ return sh_isa_memmap[idx] + offset;
+}
diff --git a/arch/sh/boards/se/770x/irq.c b/arch/sh/boards/se/770x/irq.c
new file mode 100644
index 000000000000..210897b315f4
--- /dev/null
+++ b/arch/sh/boards/se/770x/irq.c
@@ -0,0 +1,80 @@
+/*
+ * linux/arch/sh/boards/se/770x/irq.c
+ *
+ * Copyright (C) 2000 Kazumoto Kojima
+ *
+ * Hitachi SolutionEngine Support.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+#include <asm/se/se.h>
+
+/*
+ * Initialize IRQ setting
+ */
+void __init init_se_IRQ(void)
+{
+ /*
+ * Super I/O (Just mimic PC):
+ * 1: keyboard
+ * 3: serial 0
+ * 4: serial 1
+ * 5: printer
+ * 6: floppy
+ * 8: rtc
+ * 12: mouse
+ * 14: ide0
+ */
+#if defined(CONFIG_CPU_SUBTYPE_SH7705)
+ /* Disable all interrupts */
+ ctrl_outw(0, BCR_ILCRA);
+ ctrl_outw(0, BCR_ILCRB);
+ ctrl_outw(0, BCR_ILCRC);
+ ctrl_outw(0, BCR_ILCRD);
+ ctrl_outw(0, BCR_ILCRE);
+ ctrl_outw(0, BCR_ILCRF);
+ ctrl_outw(0, BCR_ILCRG);
+ /* This is default value */
+ make_ipr_irq(0xf-0x2, BCR_ILCRA, 2, 0x2);
+ make_ipr_irq(0xf-0xa, BCR_ILCRA, 1, 0xa);
+ make_ipr_irq(0xf-0x5, BCR_ILCRB, 0, 0x5);
+ make_ipr_irq(0xf-0x8, BCR_ILCRC, 1, 0x8);
+ make_ipr_irq(0xf-0xc, BCR_ILCRC, 0, 0xc);
+ make_ipr_irq(0xf-0xe, BCR_ILCRD, 3, 0xe);
+ make_ipr_irq(0xf-0x3, BCR_ILCRD, 1, 0x3); /* LAN */
+ make_ipr_irq(0xf-0xd, BCR_ILCRE, 2, 0xd);
+ make_ipr_irq(0xf-0x9, BCR_ILCRE, 1, 0x9);
+ make_ipr_irq(0xf-0x1, BCR_ILCRE, 0, 0x1);
+ make_ipr_irq(0xf-0xf, BCR_ILCRF, 3, 0xf);
+ make_ipr_irq(0xf-0xb, BCR_ILCRF, 1, 0xb);
+ make_ipr_irq(0xf-0x7, BCR_ILCRG, 3, 0x7);
+ make_ipr_irq(0xf-0x6, BCR_ILCRG, 2, 0x6);
+ make_ipr_irq(0xf-0x4, BCR_ILCRG, 1, 0x4);
+#else
+ make_ipr_irq(14, BCR_ILCRA, 2, 0x0f-14);
+ make_ipr_irq(12, BCR_ILCRA, 1, 0x0f-12);
+ make_ipr_irq( 8, BCR_ILCRB, 1, 0x0f- 8);
+ make_ipr_irq( 6, BCR_ILCRC, 3, 0x0f- 6);
+ make_ipr_irq( 5, BCR_ILCRC, 2, 0x0f- 5);
+ make_ipr_irq( 4, BCR_ILCRC, 1, 0x0f- 4);
+ make_ipr_irq( 3, BCR_ILCRC, 0, 0x0f- 3);
+ make_ipr_irq( 1, BCR_ILCRD, 3, 0x0f- 1);
+
+ make_ipr_irq(10, BCR_ILCRD, 1, 0x0f-10); /* LAN */
+
+ make_ipr_irq( 0, BCR_ILCRE, 3, 0x0f- 0); /* PCIRQ3 */
+ make_ipr_irq(11, BCR_ILCRE, 2, 0x0f-11); /* PCIRQ2 */
+ make_ipr_irq( 9, BCR_ILCRE, 1, 0x0f- 9); /* PCIRQ1 */
+ make_ipr_irq( 7, BCR_ILCRE, 0, 0x0f- 7); /* PCIRQ0 */
+
+ /* #2, #13 are allocated for SLOT IRQ #1 and #2 (for now) */
+ /* NOTE: #2 and #13 are not used on PC */
+ make_ipr_irq(13, BCR_ILCRG, 1, 0x0f-13); /* SLOTIRQ2 */
+ make_ipr_irq( 2, BCR_ILCRG, 0, 0x0f- 2); /* SLOTIRQ1 */
+#endif
+}
diff --git a/arch/sh/boards/se/770x/led.c b/arch/sh/boards/se/770x/led.c
new file mode 100644
index 000000000000..5c64e8ab2cfb
--- /dev/null
+++ b/arch/sh/boards/se/770x/led.c
@@ -0,0 +1,68 @@
+/*
+ * linux/arch/sh/kernel/led_se.c
+ *
+ * Copyright (C) 2000 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.
+ *
+ * This file contains Solution Engine specific LED code.
+ */
+
+#include <linux/config.h>
+#include <asm/se/se.h>
+
+static void mach_led(int position, int value)
+{
+ volatile unsigned short* p = (volatile unsigned short*)PA_LED;
+
+ if (value) {
+ *p |= (1<<8);
+ } else {
+ *p &= ~(1<<8);
+ }
+}
+
+#ifdef CONFIG_HEARTBEAT
+
+#include <linux/sched.h>
+
+/* Cycle the LED's in the clasic Knightrider/Sun pattern */
+void heartbeat_se(void)
+{
+ static unsigned int cnt = 0, period = 0;
+ volatile unsigned short* p = (volatile unsigned short*)PA_LED;
+ static unsigned bit = 0, up = 1;
+
+ cnt += 1;
+ if (cnt < period) {
+ return;
+ }
+
+ cnt = 0;
+
+ /* Go through the points (roughly!):
+ * f(0)=10, f(1)=16, f(2)=20, f(5)=35,f(inf)->110
+ */
+ period = 110 - ( (300<<FSHIFT)/
+ ((avenrun[0]/5) + (3<<FSHIFT)) );
+
+ if (up) {
+ if (bit == 7) {
+ bit--;
+ up=0;
+ } else {
+ bit ++;
+ }
+ } else {
+ if (bit == 0) {
+ bit++;
+ up=1;
+ } else {
+ bit--;
+ }
+ }
+ *p = 1<<(bit+8);
+
+}
+#endif /* CONFIG_HEARTBEAT */
diff --git a/arch/sh/boards/se/770x/mach.c b/arch/sh/boards/se/770x/mach.c
new file mode 100644
index 000000000000..f9b4c56cc47e
--- /dev/null
+++ b/arch/sh/boards/se/770x/mach.c
@@ -0,0 +1,68 @@
+/*
+ * linux/arch/sh/kernel/mach_se.c
+ *
+ * Copyright (C) 2000 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 vector for the Hitachi SolutionEngine
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+
+#include <asm/machvec.h>
+#include <asm/rtc.h>
+#include <asm/machvec_init.h>
+
+#include <asm/se/io.h>
+
+void heartbeat_se(void);
+void setup_se(void);
+void init_se_IRQ(void);
+
+/*
+ * The Machine Vector
+ */
+
+struct sh_machine_vector mv_se __initmv = {
+#if defined(CONFIG_CPU_SH4)
+ .mv_nr_irqs = 48,
+#elif defined(CONFIG_CPU_SUBTYPE_SH7708)
+ .mv_nr_irqs = 32,
+#elif defined(CONFIG_CPU_SUBTYPE_SH7709)
+ .mv_nr_irqs = 61,
+#elif defined(CONFIG_CPU_SUBTYPE_SH7705)
+ .mv_nr_irqs = 86,
+#endif
+
+ .mv_inb = se_inb,
+ .mv_inw = se_inw,
+ .mv_inl = se_inl,
+ .mv_outb = se_outb,
+ .mv_outw = se_outw,
+ .mv_outl = se_outl,
+
+ .mv_inb_p = se_inb_p,
+ .mv_inw_p = se_inw,
+ .mv_inl_p = se_inl,
+ .mv_outb_p = se_outb_p,
+ .mv_outw_p = se_outw,
+ .mv_outl_p = se_outl,
+
+ .mv_insb = se_insb,
+ .mv_insw = se_insw,
+ .mv_insl = se_insl,
+ .mv_outsb = se_outsb,
+ .mv_outsw = se_outsw,
+ .mv_outsl = se_outsl,
+
+ .mv_isa_port2addr = se_isa_port2addr,
+
+ .mv_init_irq = init_se_IRQ,
+#ifdef CONFIG_HEARTBEAT
+ .mv_heartbeat = heartbeat_se,
+#endif
+};
+ALIAS_MV(se)
diff --git a/arch/sh/boards/se/770x/setup.c b/arch/sh/boards/se/770x/setup.c
new file mode 100644
index 000000000000..2bed46fb607d
--- /dev/null
+++ b/arch/sh/boards/se/770x/setup.c
@@ -0,0 +1,85 @@
+/* $Id: setup.c,v 1.1.2.4 2002/03/02 21:57:07 lethal Exp $
+ *
+ * linux/arch/sh/boards/se/770x/setup.c
+ *
+ * Copyright (C) 2000 Kazumoto Kojima
+ *
+ * Hitachi SolutionEngine Support.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+
+#include <linux/hdreg.h>
+#include <linux/ide.h>
+#include <asm/io.h>
+#include <asm/se/se.h>
+#include <asm/se/smc37c93x.h>
+
+/*
+ * Configure the Super I/O chip
+ */
+static void __init smsc_config(int index, int data)
+{
+ outb_p(index, INDEX_PORT);
+ outb_p(data, DATA_PORT);
+}
+
+static void __init init_smsc(void)
+{
+ outb_p(CONFIG_ENTER, CONFIG_PORT);
+ outb_p(CONFIG_ENTER, CONFIG_PORT);
+
+ /* FDC */
+ smsc_config(CURRENT_LDN_INDEX, LDN_FDC);
+ smsc_config(ACTIVATE_INDEX, 0x01);
+ smsc_config(IRQ_SELECT_INDEX, 6); /* IRQ6 */
+
+ /* IDE1 */
+ smsc_config(CURRENT_LDN_INDEX, LDN_IDE1);
+ smsc_config(ACTIVATE_INDEX, 0x01);
+ smsc_config(IRQ_SELECT_INDEX, 14); /* IRQ14 */
+
+ /* AUXIO (GPIO): to use IDE1 */
+ smsc_config(CURRENT_LDN_INDEX, LDN_AUXIO);
+ smsc_config(GPIO46_INDEX, 0x00); /* nIOROP */
+ smsc_config(GPIO47_INDEX, 0x00); /* nIOWOP */
+
+ /* COM1 */
+ smsc_config(CURRENT_LDN_INDEX, LDN_COM1);
+ smsc_config(ACTIVATE_INDEX, 0x01);
+ smsc_config(IO_BASE_HI_INDEX, 0x03);
+ smsc_config(IO_BASE_LO_INDEX, 0xf8);
+ smsc_config(IRQ_SELECT_INDEX, 4); /* IRQ4 */
+
+ /* COM2 */
+ smsc_config(CURRENT_LDN_INDEX, LDN_COM2);
+ smsc_config(ACTIVATE_INDEX, 0x01);
+ smsc_config(IO_BASE_HI_INDEX, 0x02);
+ smsc_config(IO_BASE_LO_INDEX, 0xf8);
+ smsc_config(IRQ_SELECT_INDEX, 3); /* IRQ3 */
+
+ /* RTC */
+ smsc_config(CURRENT_LDN_INDEX, LDN_RTC);
+ smsc_config(ACTIVATE_INDEX, 0x01);
+ smsc_config(IRQ_SELECT_INDEX, 8); /* IRQ8 */
+
+ /* XXX: PARPORT, KBD, and MOUSE will come here... */
+ outb_p(CONFIG_EXIT, CONFIG_PORT);
+}
+
+const char *get_system_type(void)
+{
+ return "SolutionEngine";
+}
+
+/*
+ * Initialize the board
+ */
+void __init platform_setup(void)
+{
+ init_smsc();
+ /* XXX: RTC setting comes here */
+}
diff --git a/arch/sh/boards/se/7751/Makefile b/arch/sh/boards/se/7751/Makefile
new file mode 100644
index 000000000000..ce7ca247f84d
--- /dev/null
+++ b/arch/sh/boards/se/7751/Makefile
@@ -0,0 +1,8 @@
+#
+# Makefile for the 7751 SolutionEngine specific parts of the kernel
+#
+
+obj-y := mach.o setup.o io.o irq.o led.o
+
+obj-$(CONFIG_PCI) += pci.o
+
diff --git a/arch/sh/boards/se/7751/io.c b/arch/sh/boards/se/7751/io.c
new file mode 100644
index 000000000000..99041b269261
--- /dev/null
+++ b/arch/sh/boards/se/7751/io.c
@@ -0,0 +1,244 @@
+/*
+ * linux/arch/sh/kernel/io_7751se.c
+ *
+ * Copyright (C) 2001 Ian da Silva, Jeremy Siegel
+ * Based largely on io_se.c.
+ *
+ * I/O routine for Hitachi 7751 SolutionEngine.
+ *
+ * Initial version only to support LAN access; some
+ * placeholder code from io_se.c left in with the
+ * expectation of later SuperIO and PCMCIA access.
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <asm/io.h>
+#include <asm/se7751/se7751.h>
+#include <asm/addrspace.h>
+
+#include <linux/pci.h>
+#include "../../../drivers/pci/pci-sh7751.h"
+
+#if 0
+/******************************************************************
+ * Variables from io_se.c, related to PCMCIA (not PCI); we're not
+ * compiling them in, and have removed references from functions
+ * which follow. [Many checked for IO ports in the range bounded
+ * by sh_pcic_io_start/stop, and used sh_pcic_io_wbase as offset.
+ * As start/stop are uninitialized, only port 0x0 would match?]
+ * When used, remember to adjust names to avoid clash with io_se?
+ *****************************************************************/
+/* SH pcmcia io window base, start and end. */
+int sh_pcic_io_wbase = 0xb8400000;
+int sh_pcic_io_start;
+int sh_pcic_io_stop;
+int sh_pcic_io_type;
+int sh_pcic_io_dummy;
+/*************************************************************/
+#endif
+
+/*
+ * The 7751 Solution Engine uses the built-in PCI controller (PCIC)
+ * of the 7751 processor, and has a SuperIO accessible via the PCI.
+ * The board also includes a PCMCIA controller on its memory bus,
+ * like the other Solution Engine boards.
+ */
+
+#define PCIIOBR (volatile long *)PCI_REG(SH7751_PCIIOBR)
+#define PCIMBR (volatile long *)PCI_REG(SH7751_PCIMBR)
+#define PCI_IO_AREA SH7751_PCI_IO_BASE
+#define PCI_MEM_AREA SH7751_PCI_CONFIG_BASE
+
+#define PCI_IOMAP(adr) (PCI_IO_AREA + (adr & ~SH7751_PCIIOBR_MASK))
+
+#define maybebadio(name,port) \
+ printk("bad PC-like io %s for port 0x%lx at 0x%08x\n", \
+ #name, (port), (__u32) __builtin_return_address(0))
+
+static inline void delay(void)
+{
+ ctrl_inw(0xa0000000);
+}
+
+static inline volatile __u16 *
+port2adr(unsigned int port)
+{
+ if (port >= 0x2000)
+ return (volatile __u16 *) (PA_MRSHPC + (port - 0x2000));
+#if 0
+ else
+ return (volatile __u16 *) (PA_SUPERIO + (port << 1));
+#endif
+ maybebadio(name,(unsigned long)port);
+ return (volatile __u16*)port;
+}
+
+#if 0
+/* The 7751 Solution Engine seems to have everything hooked */
+/* up pretty normally (nothing on high-bytes only...) so this */
+/* shouldn't be needed */
+static inline int
+shifted_port(unsigned long port)
+{
+ /* For IDE registers, value is not shifted */
+ if ((0x1f0 <= port && port < 0x1f8) || port == 0x3f6)
+ return 0;
+ else
+ return 1;
+}
+#endif
+
+/* In case someone configures the kernel w/o PCI support: in that */
+/* scenario, don't ever bother to check for PCI-window addresses */
+
+/* NOTE: WINDOW CHECK MAY BE A BIT OFF, HIGH PCIBIOS_MIN_IO WRAPS? */
+#if defined(CONFIG_PCI)
+#define CHECK_SH7751_PCIIO(port) \
+ ((port >= PCIBIOS_MIN_IO) && (port < (PCIBIOS_MIN_IO + SH7751_PCI_IO_SIZE)))
+#else
+#define CHECK_SH7751_PCIIO(port) (0)
+#endif
+
+/*
+ * General outline: remap really low stuff [eventually] to SuperIO,
+ * stuff in PCI IO space (at or above window at pci.h:PCIBIOS_MIN_IO)
+ * is mapped through the PCI IO window. Stuff with high bits (PXSEG)
+ * should be way beyond the window, and is used w/o translation for
+ * compatibility.
+ */
+unsigned char sh7751se_inb(unsigned long port)
+{
+ if (PXSEG(port))
+ return *(volatile unsigned char *)port;
+ else if (CHECK_SH7751_PCIIO(port))
+ return *(volatile unsigned char *)PCI_IOMAP(port);
+ else
+ return (*port2adr(port))&0xff;
+}
+
+unsigned char sh7751se_inb_p(unsigned long port)
+{
+ unsigned char v;
+
+ if (PXSEG(port))
+ v = *(volatile unsigned char *)port;
+ else if (CHECK_SH7751_PCIIO(port))
+ v = *(volatile unsigned char *)PCI_IOMAP(port);
+ else
+ v = (*port2adr(port))&0xff;
+ delay();
+ return v;
+}
+
+unsigned short sh7751se_inw(unsigned long port)
+{
+ if (PXSEG(port))
+ return *(volatile unsigned short *)port;
+ else if (CHECK_SH7751_PCIIO(port))
+ return *(volatile unsigned short *)PCI_IOMAP(port);
+ else if (port >= 0x2000)
+ return *port2adr(port);
+ else
+ maybebadio(inw, port);
+ return 0;
+}
+
+unsigned int sh7751se_inl(unsigned long port)
+{
+ if (PXSEG(port))
+ return *(volatile unsigned long *)port;
+ else if (CHECK_SH7751_PCIIO(port))
+ return *(volatile unsigned int *)PCI_IOMAP(port);
+ else if (port >= 0x2000)
+ return *port2adr(port);
+ else
+ maybebadio(inl, port);
+ return 0;
+}
+
+void sh7751se_outb(unsigned char value, unsigned long port)
+{
+
+ if (PXSEG(port))
+ *(volatile unsigned char *)port = value;
+ else if (CHECK_SH7751_PCIIO(port))
+ *((unsigned char*)PCI_IOMAP(port)) = value;
+ else
+ *(port2adr(port)) = value;
+}
+
+void sh7751se_outb_p(unsigned char value, unsigned long port)
+{
+ if (PXSEG(port))
+ *(volatile unsigned char *)port = value;
+ else if (CHECK_SH7751_PCIIO(port))
+ *((unsigned char*)PCI_IOMAP(port)) = value;
+ else
+ *(port2adr(port)) = value;
+ delay();
+}
+
+void sh7751se_outw(unsigned short value, unsigned long port)
+{
+ if (PXSEG(port))
+ *(volatile unsigned short *)port = value;
+ else if (CHECK_SH7751_PCIIO(port))
+ *((unsigned short *)PCI_IOMAP(port)) = value;
+ else if (port >= 0x2000)
+ *port2adr(port) = value;
+ else
+ maybebadio(outw, port);
+}
+
+void sh7751se_outl(unsigned int value, unsigned long port)
+{
+ if (PXSEG(port))
+ *(volatile unsigned long *)port = value;
+ else if (CHECK_SH7751_PCIIO(port))
+ *((unsigned long*)PCI_IOMAP(port)) = value;
+ else
+ maybebadio(outl, port);
+}
+
+void sh7751se_insl(unsigned long port, void *addr, unsigned long count)
+{
+ maybebadio(insl, port);
+}
+
+void sh7751se_outsl(unsigned long port, const void *addr, unsigned long count)
+{
+ maybebadio(outsw, port);
+}
+
+/* Map ISA bus address to the real address. Only for PCMCIA. */
+
+/* ISA page descriptor. */
+static __u32 sh_isa_memmap[256];
+
+#if 0
+static int
+sh_isa_mmap(__u32 start, __u32 length, __u32 offset)
+{
+ int idx;
+
+ if (start >= 0x100000 || (start & 0xfff) || (length != 0x1000))
+ return -1;
+
+ idx = start >> 12;
+ sh_isa_memmap[idx] = 0xb8000000 + (offset &~ 0xfff);
+ printk("sh_isa_mmap: start %x len %x offset %x (idx %x paddr %x)\n",
+ start, length, offset, idx, sh_isa_memmap[idx]);
+ return 0;
+}
+#endif
+
+unsigned long
+sh7751se_isa_port2addr(unsigned long offset)
+{
+ int idx;
+
+ idx = (offset >> 12) & 0xff;
+ offset &= 0xfff;
+ return sh_isa_memmap[idx] + offset;
+}
diff --git a/arch/sh/boards/se/7751/irq.c b/arch/sh/boards/se/7751/irq.c
new file mode 100644
index 000000000000..ad71f3e66c11
--- /dev/null
+++ b/arch/sh/boards/se/7751/irq.c
@@ -0,0 +1,67 @@
+/*
+ * linux/arch/sh/boards/se/7751/irq.c
+ *
+ * Copyright (C) 2000 Kazumoto Kojima
+ *
+ * Hitachi SolutionEngine Support.
+ *
+ * Modified for 7751 Solution Engine by
+ * Ian da Silva and Jeremy Siegel, 2001.
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <asm/irq.h>
+#include <asm/se7751/se7751.h>
+
+/*
+ * Initialize IRQ setting
+ */
+void __init init_7751se_IRQ(void)
+{
+
+ /* Leave old Solution Engine code in for reference. */
+#if defined(CONFIG_SH_SOLUTION_ENGINE)
+ /*
+ * Super I/O (Just mimic PC):
+ * 1: keyboard
+ * 3: serial 0
+ * 4: serial 1
+ * 5: printer
+ * 6: floppy
+ * 8: rtc
+ * 12: mouse
+ * 14: ide0
+ */
+ make_ipr_irq(14, BCR_ILCRA, 2, 0x0f-14);
+ make_ipr_irq(12, BCR_ILCRA, 1, 0x0f-12);
+ make_ipr_irq( 8, BCR_ILCRB, 1, 0x0f- 8);
+ make_ipr_irq( 6, BCR_ILCRC, 3, 0x0f- 6);
+ make_ipr_irq( 5, BCR_ILCRC, 2, 0x0f- 5);
+ make_ipr_irq( 4, BCR_ILCRC, 1, 0x0f- 4);
+ make_ipr_irq( 3, BCR_ILCRC, 0, 0x0f- 3);
+ make_ipr_irq( 1, BCR_ILCRD, 3, 0x0f- 1);
+
+ make_ipr_irq(10, BCR_ILCRD, 1, 0x0f-10); /* LAN */
+
+ make_ipr_irq( 0, BCR_ILCRE, 3, 0x0f- 0); /* PCIRQ3 */
+ make_ipr_irq(11, BCR_ILCRE, 2, 0x0f-11); /* PCIRQ2 */
+ make_ipr_irq( 9, BCR_ILCRE, 1, 0x0f- 9); /* PCIRQ1 */
+ make_ipr_irq( 7, BCR_ILCRE, 0, 0x0f- 7); /* PCIRQ0 */
+
+ /* #2, #13 are allocated for SLOT IRQ #1 and #2 (for now) */
+ /* NOTE: #2 and #13 are not used on PC */
+ make_ipr_irq(13, BCR_ILCRG, 1, 0x0f-13); /* SLOTIRQ2 */
+ make_ipr_irq( 2, BCR_ILCRG, 0, 0x0f- 2); /* SLOTIRQ1 */
+
+#elif defined(CONFIG_SH_7751_SOLUTION_ENGINE)
+
+ make_ipr_irq(13, BCR_ILCRD, 3, 2);
+
+ /* Add additional calls to make_ipr_irq() as drivers are added
+ * and tested.
+ */
+#endif
+
+}
diff --git a/arch/sh/boards/se/7751/led.c b/arch/sh/boards/se/7751/led.c
new file mode 100644
index 000000000000..0c788230cf8f
--- /dev/null
+++ b/arch/sh/boards/se/7751/led.c
@@ -0,0 +1,68 @@
+/*
+ * linux/arch/sh/kernel/led_se.c
+ *
+ * Copyright (C) 2000 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.
+ *
+ * This file contains Solution Engine specific LED code.
+ */
+
+#include <linux/config.h>
+#include <asm/se7751/se7751.h>
+
+static void mach_led(int position, int value)
+{
+ volatile unsigned short* p = (volatile unsigned short*)PA_LED;
+
+ if (value) {
+ *p |= (1<<8);
+ } else {
+ *p &= ~(1<<8);
+ }
+}
+
+#ifdef CONFIG_HEARTBEAT
+
+#include <linux/sched.h>
+
+/* Cycle the LED's in the clasic Knightrider/Sun pattern */
+void heartbeat_7751se(void)
+{
+ static unsigned int cnt = 0, period = 0;
+ volatile unsigned short* p = (volatile unsigned short*)PA_LED;
+ static unsigned bit = 0, up = 1;
+
+ cnt += 1;
+ if (cnt < period) {
+ return;
+ }
+
+ cnt = 0;
+
+ /* Go through the points (roughly!):
+ * f(0)=10, f(1)=16, f(2)=20, f(5)=35,f(inf)->110
+ */
+ period = 110 - ( (300<<FSHIFT)/
+ ((avenrun[0]/5) + (3<<FSHIFT)) );
+
+ if (up) {
+ if (bit == 7) {
+ bit--;
+ up=0;
+ } else {
+ bit ++;
+ }
+ } else {
+ if (bit == 0) {
+ bit++;
+ up=1;
+ } else {
+ bit--;
+ }
+ }
+ *p = 1<<(bit+8);
+
+}
+#endif /* CONFIG_HEARTBEAT */
diff --git a/arch/sh/boards/se/7751/mach.c b/arch/sh/boards/se/7751/mach.c
new file mode 100644
index 000000000000..16d386b7e3bf
--- /dev/null
+++ b/arch/sh/boards/se/7751/mach.c
@@ -0,0 +1,55 @@
+/*
+ * linux/arch/sh/kernel/mach_7751se.c
+ *
+ * Minor tweak of mach_se.c file to reference 7751se-specific items.
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License. See linux/COPYING for more information.
+ *
+ * Machine vector for the Hitachi 7751 SolutionEngine
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+
+#include <asm/machvec.h>
+#include <asm/rtc.h>
+#include <asm/machvec_init.h>
+
+#include <asm/se7751/io.h>
+
+void heartbeat_7751se(void);
+void init_7751se_IRQ(void);
+
+/*
+ * The Machine Vector
+ */
+
+struct sh_machine_vector mv_7751se __initmv = {
+ .mv_nr_irqs = 72,
+
+ .mv_inb = sh7751se_inb,
+ .mv_inw = sh7751se_inw,
+ .mv_inl = sh7751se_inl,
+ .mv_outb = sh7751se_outb,
+ .mv_outw = sh7751se_outw,
+ .mv_outl = sh7751se_outl,
+
+ .mv_inb_p = sh7751se_inb_p,
+ .mv_inw_p = sh7751se_inw,
+ .mv_inl_p = sh7751se_inl,
+ .mv_outb_p = sh7751se_outb_p,
+ .mv_outw_p = sh7751se_outw,
+ .mv_outl_p = sh7751se_outl,
+
+ .mv_insl = sh7751se_insl,
+ .mv_outsl = sh7751se_outsl,
+
+ .mv_isa_port2addr = sh7751se_isa_port2addr,
+
+ .mv_init_irq = init_7751se_IRQ,
+#ifdef CONFIG_HEARTBEAT
+ .mv_heartbeat = heartbeat_7751se,
+#endif
+};
+ALIAS_MV(7751se)
diff --git a/arch/sh/boards/se/7751/pci.c b/arch/sh/boards/se/7751/pci.c
new file mode 100644
index 000000000000..1f273efd2cf5
--- /dev/null
+++ b/arch/sh/boards/se/7751/pci.c
@@ -0,0 +1,148 @@
+/*
+ * linux/arch/sh/kernel/pci-7751se.c
+ *
+ * Author: Ian DaSilva (idasilva@mvista.com)
+ *
+ * Highly leveraged from pci-bigsur.c, written by Dustin McIntire.
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License. See linux/COPYING for more information.
+ *
+ * PCI initialization for the Hitachi SH7751 Solution Engine board (MS7751SE01)
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+
+#include <asm/io.h>
+#include "../../../drivers/pci/pci-sh7751.h"
+
+#define PCIMCR_MRSET_OFF 0xBFFFFFFF
+#define PCIMCR_RFSH_OFF 0xFFFFFFFB
+
+/*
+ * Only long word accesses of the PCIC's internal local registers and the
+ * configuration registers from the CPU is supported.
+ */
+#define PCIC_WRITE(x,v) writel((v), PCI_REG(x))
+#define PCIC_READ(x) readl(PCI_REG(x))
+
+/*
+ * Description: This function sets up and initializes the pcic, sets
+ * up the BARS, maps the DRAM into the address space etc, etc.
+ */
+int __init pcibios_init_platform(void)
+{
+ unsigned long bcr1, wcr1, wcr2, wcr3, mcr;
+ unsigned short bcr2;
+
+ /*
+ * Initialize the slave bus controller on the pcic. The values used
+ * here should not be hardcoded, but they should be taken from the bsc
+ * on the processor, to make this function as generic as possible.
+ * (i.e. Another sbc may usr different SDRAM timing settings -- in order
+ * for the pcic to work, its settings need to be exactly the same.)
+ */
+ bcr1 = (*(volatile unsigned long*)(SH7751_BCR1));
+ bcr2 = (*(volatile unsigned short*)(SH7751_BCR2));
+ wcr1 = (*(volatile unsigned long*)(SH7751_WCR1));
+ wcr2 = (*(volatile unsigned long*)(SH7751_WCR2));
+ wcr3 = (*(volatile unsigned long*)(SH7751_WCR3));
+ mcr = (*(volatile unsigned long*)(SH7751_MCR));
+
+ bcr1 = bcr1 | 0x00080000; /* Enable Bit 19, BREQEN */
+ (*(volatile unsigned long*)(SH7751_BCR1)) = bcr1;
+
+ bcr1 = bcr1 | 0x40080000; /* Enable Bit 19 BREQEN, set PCIC to slave */
+ PCIC_WRITE(SH7751_PCIBCR1, bcr1); /* PCIC BCR1 */
+ PCIC_WRITE(SH7751_PCIBCR2, bcr2); /* PCIC BCR2 */
+ PCIC_WRITE(SH7751_PCIWCR1, wcr1); /* PCIC WCR1 */
+ PCIC_WRITE(SH7751_PCIWCR2, wcr2); /* PCIC WCR2 */
+ PCIC_WRITE(SH7751_PCIWCR3, wcr3); /* PCIC WCR3 */
+ mcr = (mcr & PCIMCR_MRSET_OFF) & PCIMCR_RFSH_OFF;
+ PCIC_WRITE(SH7751_PCIMCR, mcr); /* PCIC MCR */
+
+
+ /* Enable all interrupts, so we know what to fix */
+ PCIC_WRITE(SH7751_PCIINTM, 0x0000c3ff);
+ PCIC_WRITE(SH7751_PCIAINTM, 0x0000380f);
+
+ /* Set up standard PCI config registers */
+ PCIC_WRITE(SH7751_PCICONF1, 0xF39000C7); /* Bus Master, Mem & I/O access */
+ PCIC_WRITE(SH7751_PCICONF2, 0x00000000); /* PCI Class code & Revision ID */
+ PCIC_WRITE(SH7751_PCICONF4, 0xab000001); /* PCI I/O address (local regs) */
+ PCIC_WRITE(SH7751_PCICONF5, 0x0c000000); /* PCI MEM address (local RAM) */
+ PCIC_WRITE(SH7751_PCICONF6, 0xd0000000); /* PCI MEM address (unused) */
+ PCIC_WRITE(SH7751_PCICONF11, 0x35051054); /* PCI Subsystem ID & Vendor ID */
+ PCIC_WRITE(SH7751_PCILSR0, 0x03f00000); /* MEM (full 64M exposed) */
+ PCIC_WRITE(SH7751_PCILSR1, 0x00000000); /* MEM (unused) */
+ PCIC_WRITE(SH7751_PCILAR0, 0x0c000000); /* MEM (direct map from PCI) */
+ PCIC_WRITE(SH7751_PCILAR1, 0x00000000); /* MEM (unused) */
+
+ /* Now turn it on... */
+ PCIC_WRITE(SH7751_PCICR, 0xa5000001);
+
+ /*
+ * Set PCIMBR and PCIIOBR here, assuming a single window
+ * (16M MEM, 256K IO) is enough. If a larger space is
+ * needed, the readx/writex and inx/outx functions will
+ * have to do more (e.g. setting registers for each call).
+ */
+
+ /*
+ * Set the MBR so PCI address is one-to-one with window,
+ * meaning all calls go straight through... use BUG_ON to
+ * catch erroneous assumption.
+ */
+ BUG_ON(PCIBIOS_MIN_MEM != SH7751_PCI_MEMORY_BASE);
+
+ PCIC_WRITE(SH7751_PCIMBR, PCIBIOS_MIN_MEM);
+
+ /* Set IOBR for window containing area specified in pci.h */
+ PCIC_WRITE(SH7751_PCIIOBR, (PCIBIOS_MIN_IO & SH7751_PCIIOBR_MASK));
+
+ /* All done, may as well say so... */
+ printk("SH7751 PCI: Finished initialization of the PCI controller\n");
+
+ return 1;
+}
+
+int __init pcibios_map_platform_irq(u8 slot, u8 pin)
+{
+ switch (slot) {
+ case 0: return 13;
+ case 1: return 13; /* AMD Ethernet controller */
+ case 2: return -1;
+ case 3: return -1;
+ case 4: return -1;
+ default:
+ printk("PCI: Bad IRQ mapping request for slot %d\n", slot);
+ return -1;
+ }
+}
+
+static struct resource sh7751_io_resource = {
+ .name = "SH7751 IO",
+ .start = SH7751_PCI_IO_BASE,
+ .end = SH7751_PCI_IO_BASE + SH7751_PCI_IO_SIZE - 1,
+ .flags = IORESOURCE_IO
+};
+
+static struct resource sh7751_mem_resource = {
+ .name = "SH7751 mem",
+ .start = SH7751_PCI_MEMORY_BASE,
+ .end = SH7751_PCI_MEMORY_BASE + SH7751_PCI_MEM_SIZE - 1,
+ .flags = IORESOURCE_MEM
+};
+
+extern struct pci_ops sh7751_pci_ops;
+
+struct pci_channel board_pci_channels[] = {
+ { &sh7751_pci_ops, &sh7751_io_resource, &sh7751_mem_resource, 0, 0xff },
+ { NULL, NULL, NULL, 0, 0 },
+};
+
diff --git a/arch/sh/boards/se/7751/setup.c b/arch/sh/boards/se/7751/setup.c
new file mode 100644
index 000000000000..9d111bb884f9
--- /dev/null
+++ b/arch/sh/boards/se/7751/setup.c
@@ -0,0 +1,228 @@
+/*
+ * linux/arch/sh/kernel/setup_7751se.c
+ *
+ * Copyright (C) 2000 Kazumoto Kojima
+ *
+ * Hitachi SolutionEngine Support.
+ *
+ * Modified for 7751 Solution Engine by
+ * Ian da Silva and Jeremy Siegel, 2001.
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+
+#include <linux/hdreg.h>
+#include <linux/ide.h>
+#include <asm/io.h>
+#include <asm/se7751/se7751.h>
+
+#ifdef CONFIG_SH_KGDB
+#include <asm/kgdb.h>
+#endif
+
+/*
+ * Configure the Super I/O chip
+ */
+#if 0
+/* Leftover code from regular Solution Engine, for reference. */
+/* The SH7751 Solution Engine has a different SuperIO. */
+static void __init smsc_config(int index, int data)
+{
+ outb_p(index, INDEX_PORT);
+ outb_p(data, DATA_PORT);
+}
+
+static void __init init_smsc(void)
+{
+ outb_p(CONFIG_ENTER, CONFIG_PORT);
+ outb_p(CONFIG_ENTER, CONFIG_PORT);
+
+ /* FDC */
+ smsc_config(CURRENT_LDN_INDEX, LDN_FDC);
+ smsc_config(ACTIVATE_INDEX, 0x01);
+ smsc_config(IRQ_SELECT_INDEX, 6); /* IRQ6 */
+
+ /* IDE1 */
+ smsc_config(CURRENT_LDN_INDEX, LDN_IDE1);
+ smsc_config(ACTIVATE_INDEX, 0x01);
+ smsc_config(IRQ_SELECT_INDEX, 14); /* IRQ14 */
+
+ /* AUXIO (GPIO): to use IDE1 */
+ smsc_config(CURRENT_LDN_INDEX, LDN_AUXIO);
+ smsc_config(GPIO46_INDEX, 0x00); /* nIOROP */
+ smsc_config(GPIO47_INDEX, 0x00); /* nIOWOP */
+
+ /* COM1 */
+ smsc_config(CURRENT_LDN_INDEX, LDN_COM1);
+ smsc_config(ACTIVATE_INDEX, 0x01);
+ smsc_config(IO_BASE_HI_INDEX, 0x03);
+ smsc_config(IO_BASE_LO_INDEX, 0xf8);
+ smsc_config(IRQ_SELECT_INDEX, 4); /* IRQ4 */
+
+ /* COM2 */
+ smsc_config(CURRENT_LDN_INDEX, LDN_COM2);
+ smsc_config(ACTIVATE_INDEX, 0x01);
+ smsc_config(IO_BASE_HI_INDEX, 0x02);
+ smsc_config(IO_BASE_LO_INDEX, 0xf8);
+ smsc_config(IRQ_SELECT_INDEX, 3); /* IRQ3 */
+
+ /* RTC */
+ smsc_config(CURRENT_LDN_INDEX, LDN_RTC);
+ smsc_config(ACTIVATE_INDEX, 0x01);
+ smsc_config(IRQ_SELECT_INDEX, 8); /* IRQ8 */
+
+ /* XXX: PARPORT, KBD, and MOUSE will come here... */
+ outb_p(CONFIG_EXIT, CONFIG_PORT);
+}
+#endif
+
+const char *get_system_type(void)
+{
+ return "7751 SolutionEngine";
+}
+
+#ifdef CONFIG_SH_KGDB
+static int kgdb_uart_setup(void);
+static struct kgdb_sermap kgdb_uart_sermap =
+{ "ttyS", 0, kgdb_uart_setup, NULL };
+#endif
+
+/*
+ * Initialize the board
+ */
+void __init platform_setup(void)
+{
+ /* Call init_smsc() replacement to set up SuperIO. */
+ /* XXX: RTC setting comes here */
+#ifdef CONFIG_SH_KGDB
+ kgdb_register_sermap(&kgdb_uart_sermap);
+#endif
+}
+
+/*********************************************************************
+ * Currently a hack (e.g. does not interact well w/serial.c, lots of *
+ * hardcoded stuff) but may be useful if SCI/F needs debugging. *
+ * Mostly copied from x86 code (see files asm-i386/kgdb_local.h and *
+ * arch/i386/lib/kgdb_serial.c). *
+ *********************************************************************/
+
+#ifdef CONFIG_SH_KGDB
+#include <linux/types.h>
+#include <linux/serial.h>
+#include <linux/serialP.h>
+#include <linux/serial_reg.h>
+
+#define COM1_PORT 0x3f8 /* Base I/O address */
+#define COM1_IRQ 4 /* IRQ not used yet */
+#define COM2_PORT 0x2f8 /* Base I/O address */
+#define COM2_IRQ 3 /* IRQ not used yet */
+
+#define SB_CLOCK 1843200 /* Serial baud clock */
+#define SB_BASE (SB_CLOCK/16)
+#define SB_MCR UART_MCR_OUT2 | UART_MCR_DTR | UART_MCR_RTS
+
+struct uart_port {
+ int base;
+};
+#define UART_NPORTS 2
+struct uart_port uart_ports[] = {
+ { COM1_PORT },
+ { COM2_PORT },
+};
+struct uart_port *kgdb_uart_port;
+
+#define UART_IN(reg) inb_p(kgdb_uart_port->base + reg)
+#define UART_OUT(reg,v) outb_p((v), kgdb_uart_port->base + reg)
+
+/* Basic read/write functions for the UART */
+#define UART_LSR_RXCERR (UART_LSR_BI | UART_LSR_FE | UART_LSR_PE)
+static int kgdb_uart_getchar(void)
+{
+ int lsr;
+ int c = -1;
+
+ while (c == -1) {
+ lsr = UART_IN(UART_LSR);
+ if (lsr & UART_LSR_DR)
+ c = UART_IN(UART_RX);
+ if ((lsr & UART_LSR_RXCERR))
+ c = -1;
+ }
+ return c;
+}
+
+static void kgdb_uart_putchar(int c)
+{
+ while ((UART_IN(UART_LSR) & UART_LSR_THRE) == 0)
+ ;
+ UART_OUT(UART_TX, c);
+}
+
+/*
+ * Initialize UART to configured/requested values.
+ * (But we don't interrupts yet, or interact w/serial.c)
+ */
+static int kgdb_uart_setup(void)
+{
+ int port;
+ int lcr = 0;
+ int bdiv = 0;
+
+ if (kgdb_portnum >= UART_NPORTS) {
+ KGDB_PRINTK("uart port %d invalid.\n", kgdb_portnum);
+ return -1;
+ }
+
+ kgdb_uart_port = &uart_ports[kgdb_portnum];
+
+ /* Init sequence from gdb_hook_interrupt */
+ UART_IN(UART_RX);
+ UART_OUT(UART_IER, 0);
+
+ UART_IN(UART_RX); /* Serial driver comments say */
+ UART_IN(UART_IIR); /* this clears interrupt regs */
+ UART_IN(UART_MSR);
+
+ /* Figure basic LCR values */
+ switch (kgdb_bits) {
+ case '7':
+ lcr |= UART_LCR_WLEN7;
+ break;
+ default: case '8':
+ lcr |= UART_LCR_WLEN8;
+ break;
+ }
+ switch (kgdb_parity) {
+ case 'O':
+ lcr |= UART_LCR_PARITY;
+ break;
+ case 'E':
+ lcr |= (UART_LCR_PARITY | UART_LCR_EPAR);
+ break;
+ default: break;
+ }
+
+ /* Figure the baud rate divisor */
+ bdiv = (SB_BASE/kgdb_baud);
+
+ /* Set the baud rate and LCR values */
+ UART_OUT(UART_LCR, (lcr | UART_LCR_DLAB));
+ UART_OUT(UART_DLL, (bdiv & 0xff));
+ UART_OUT(UART_DLM, ((bdiv >> 8) & 0xff));
+ UART_OUT(UART_LCR, lcr);
+
+ /* Set the MCR */
+ UART_OUT(UART_MCR, SB_MCR);
+
+ /* Turn off FIFOs for now */
+ UART_OUT(UART_FCR, 0);
+
+ /* Setup complete: initialize function pointers */
+ kgdb_getchar = kgdb_uart_getchar;
+ kgdb_putchar = kgdb_uart_putchar;
+
+ return 0;
+}
+#endif /* CONFIG_SH_KGDB */
diff --git a/arch/sh/boards/sh03/Makefile b/arch/sh/boards/sh03/Makefile
new file mode 100644
index 000000000000..321be50e36a5
--- /dev/null
+++ b/arch/sh/boards/sh03/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for the Interface (CTP/PCI-SH03) specific parts of the kernel
+#
+
+obj-y := setup.o rtc.o
+obj-$(CONFIG_HEARTBEAT) += led.o
diff --git a/arch/sh/boards/sh03/led.c b/arch/sh/boards/sh03/led.c
new file mode 100644
index 000000000000..c851b0bec80f
--- /dev/null
+++ b/arch/sh/boards/sh03/led.c
@@ -0,0 +1,49 @@
+/*
+ * linux/arch/sh/boards/sh03/led.c
+ *
+ * Copyright (C) 2004 Saito.K Interface Corporation.
+ *
+ * This file contains Interface CTP/PCI-SH03 specific LED code.
+ */
+
+#include <linux/config.h>
+#include <linux/sched.h>
+
+/* Cycle the LED's in the clasic Knightrider/Sun pattern */
+void heartbeat_sh03(void)
+{
+ static unsigned int cnt = 0, period = 0;
+ volatile unsigned char* p = (volatile unsigned char*)0xa0800000;
+ static unsigned bit = 0, up = 1;
+
+ cnt += 1;
+ if (cnt < period) {
+ return;
+ }
+
+ cnt = 0;
+
+ /* Go through the points (roughly!):
+ * f(0)=10, f(1)=16, f(2)=20, f(5)=35,f(inf)->110
+ */
+ period = 110 - ( (300<<FSHIFT)/
+ ((avenrun[0]/5) + (3<<FSHIFT)) );
+
+ if (up) {
+ if (bit == 7) {
+ bit--;
+ up=0;
+ } else {
+ bit ++;
+ }
+ } else {
+ if (bit == 0) {
+ bit++;
+ up=1;
+ } else {
+ bit--;
+ }
+ }
+ *p = 1<<bit;
+
+}
diff --git a/arch/sh/boards/sh03/rtc.c b/arch/sh/boards/sh03/rtc.c
new file mode 100644
index 000000000000..cbeca7037ba5
--- /dev/null
+++ b/arch/sh/boards/sh03/rtc.c
@@ -0,0 +1,144 @@
+/*
+ * linux/arch/sh/boards/sh03/rtc.c -- CTP/PCI-SH03 on-chip RTC support
+ *
+ * Copyright (C) 2004 Saito.K & Jeanne(ksaito@interface.co.jp)
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <asm/io.h>
+#include <linux/rtc.h>
+#include <linux/spinlock.h>
+
+#define RTC_BASE 0xb0000000
+#define RTC_SEC1 (RTC_BASE + 0)
+#define RTC_SEC10 (RTC_BASE + 1)
+#define RTC_MIN1 (RTC_BASE + 2)
+#define RTC_MIN10 (RTC_BASE + 3)
+#define RTC_HOU1 (RTC_BASE + 4)
+#define RTC_HOU10 (RTC_BASE + 5)
+#define RTC_WEE1 (RTC_BASE + 6)
+#define RTC_DAY1 (RTC_BASE + 7)
+#define RTC_DAY10 (RTC_BASE + 8)
+#define RTC_MON1 (RTC_BASE + 9)
+#define RTC_MON10 (RTC_BASE + 10)
+#define RTC_YEA1 (RTC_BASE + 11)
+#define RTC_YEA10 (RTC_BASE + 12)
+#define RTC_YEA100 (RTC_BASE + 13)
+#define RTC_YEA1000 (RTC_BASE + 14)
+#define RTC_CTL (RTC_BASE + 15)
+#define RTC_BUSY 1
+#define RTC_STOP 2
+
+#ifndef BCD_TO_BIN
+#define BCD_TO_BIN(val) ((val)=((val)&15) + ((val)>>4)*10)
+#endif
+
+#ifndef BIN_TO_BCD
+#define BIN_TO_BCD(val) ((val)=(((val)/10)<<4) + (val)%10)
+#endif
+
+extern void (*rtc_get_time)(struct timespec *);
+extern int (*rtc_set_time)(const time_t);
+extern spinlock_t rtc_lock;
+
+unsigned long get_cmos_time(void)
+{
+ unsigned int year, mon, day, hour, min, sec;
+ int i;
+
+ spin_lock(&rtc_lock);
+ again:
+ for (i = 0 ; i < 1000000 ; i++) /* may take up to 1 second... */
+ if (!(ctrl_inb(RTC_CTL) & RTC_BUSY))
+ break;
+ do {
+ sec = (ctrl_inb(RTC_SEC1) & 0xf) + (ctrl_inb(RTC_SEC10) & 0x7) * 10;
+ min = (ctrl_inb(RTC_MIN1) & 0xf) + (ctrl_inb(RTC_MIN10) & 0xf) * 10;
+ hour = (ctrl_inb(RTC_HOU1) & 0xf) + (ctrl_inb(RTC_HOU10) & 0xf) * 10;
+ day = (ctrl_inb(RTC_DAY1) & 0xf) + (ctrl_inb(RTC_DAY10) & 0xf) * 10;
+ mon = (ctrl_inb(RTC_MON1) & 0xf) + (ctrl_inb(RTC_MON10) & 0xf) * 10;
+ year = (ctrl_inb(RTC_YEA1) & 0xf) + (ctrl_inb(RTC_YEA10) & 0xf) * 10
+ + (ctrl_inb(RTC_YEA100 ) & 0xf) * 100
+ + (ctrl_inb(RTC_YEA1000) & 0xf) * 1000;
+ } while (sec != (ctrl_inb(RTC_SEC1) & 0xf) + (ctrl_inb(RTC_SEC10) & 0x7) * 10);
+ if (year == 0 || mon < 1 || mon > 12 || day > 31 || day < 1 ||
+ hour > 23 || min > 59 || sec > 59) {
+ printk(KERN_ERR
+ "SH-03 RTC: invalid value, resetting to 1 Jan 2000\n");
+ printk("year=%d, mon=%d, day=%d, hour=%d, min=%d, sec=%d\n",
+ year, mon, day, hour, min, sec);
+
+ ctrl_outb(0, RTC_SEC1); ctrl_outb(0, RTC_SEC10);
+ ctrl_outb(0, RTC_MIN1); ctrl_outb(0, RTC_MIN10);
+ ctrl_outb(0, RTC_HOU1); ctrl_outb(0, RTC_HOU10);
+ ctrl_outb(6, RTC_WEE1);
+ ctrl_outb(1, RTC_DAY1); ctrl_outb(0, RTC_DAY10);
+ ctrl_outb(1, RTC_MON1); ctrl_outb(0, RTC_MON10);
+ ctrl_outb(0, RTC_YEA1); ctrl_outb(0, RTC_YEA10);
+ ctrl_outb(0, RTC_YEA100);
+ ctrl_outb(2, RTC_YEA1000);
+ ctrl_outb(0, RTC_CTL);
+ goto again;
+ }
+
+ spin_unlock(&rtc_lock);
+ return mktime(year, mon, day, hour, min, sec);
+}
+
+void sh03_rtc_gettimeofday(struct timespec *tv)
+{
+
+ tv->tv_sec = get_cmos_time();
+ tv->tv_nsec = 0;
+}
+
+static int set_rtc_mmss(unsigned long nowtime)
+{
+ int retval = 0;
+ int real_seconds, real_minutes, cmos_minutes;
+ int i;
+
+ /* gets recalled with irq locally disabled */
+ spin_lock(&rtc_lock);
+ for (i = 0 ; i < 1000000 ; i++) /* may take up to 1 second... */
+ if (!(ctrl_inb(RTC_CTL) & RTC_BUSY))
+ break;
+ cmos_minutes = (ctrl_inb(RTC_MIN1) & 0xf) + (ctrl_inb(RTC_MIN10) & 0xf) * 10;
+ real_seconds = nowtime % 60;
+ real_minutes = nowtime / 60;
+ if (((abs(real_minutes - cmos_minutes) + 15)/30) & 1)
+ real_minutes += 30; /* correct for half hour time zone */
+ real_minutes %= 60;
+
+ if (abs(real_minutes - cmos_minutes) < 30) {
+ ctrl_outb(real_seconds % 10, RTC_SEC1);
+ ctrl_outb(real_seconds / 10, RTC_SEC10);
+ ctrl_outb(real_minutes % 10, RTC_MIN1);
+ ctrl_outb(real_minutes / 10, RTC_MIN10);
+ } else {
+ printk(KERN_WARNING
+ "set_rtc_mmss: can't update from %d to %d\n",
+ cmos_minutes, real_minutes);
+ retval = -1;
+ }
+ spin_unlock(&rtc_lock);
+
+ return retval;
+}
+
+int sh03_rtc_settimeofday(const time_t secs)
+{
+ unsigned long nowtime = secs;
+
+ return set_rtc_mmss(nowtime);
+}
+
+void sh03_time_init(void)
+{
+ rtc_get_time = sh03_rtc_gettimeofday;
+ rtc_set_time = sh03_rtc_settimeofday;
+}
diff --git a/arch/sh/boards/sh03/setup.c b/arch/sh/boards/sh03/setup.c
new file mode 100644
index 000000000000..d2a08ca5eb85
--- /dev/null
+++ b/arch/sh/boards/sh03/setup.c
@@ -0,0 +1,72 @@
+/*
+ * linux/arch/sh/boards/sh03/setup.c
+ *
+ * Copyright (C) 2004 Interface Co.,Ltd. Saito.K
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/hdreg.h>
+#include <linux/ide.h>
+#include <asm/io.h>
+#include <asm/sh03/io.h>
+#include <asm/sh03/sh03.h>
+#include <asm/addrspace.h>
+#include "../../drivers/pci/pci-sh7751.h"
+
+extern void (*board_time_init)(void);
+
+const char *get_system_type(void)
+{
+ return "Interface CTP/PCI-SH03)";
+}
+
+void init_sh03_IRQ(void)
+{
+ ctrl_outw(ctrl_inw(INTC_ICR) | INTC_ICR_IRLM, INTC_ICR);
+
+ make_ipr_irq(IRL0_IRQ, IRL0_IPR_ADDR, IRL0_IPR_POS, IRL0_PRIORITY);
+ make_ipr_irq(IRL1_IRQ, IRL1_IPR_ADDR, IRL1_IPR_POS, IRL1_PRIORITY);
+ make_ipr_irq(IRL2_IRQ, IRL2_IPR_ADDR, IRL2_IPR_POS, IRL2_PRIORITY);
+ make_ipr_irq(IRL3_IRQ, IRL3_IPR_ADDR, IRL3_IPR_POS, IRL3_PRIORITY);
+}
+
+extern void *cf_io_base;
+
+unsigned long sh03_isa_port2addr(unsigned long port)
+{
+ if (PXSEG(port))
+ return port;
+ /* CompactFlash (IDE) */
+ if (((port >= 0x1f0) && (port <= 0x1f7)) || (port == 0x3f6)) {
+ return (unsigned long)cf_io_base + port;
+ }
+ return port + SH7751_PCI_IO_BASE;
+}
+
+/*
+ * The Machine Vector
+ */
+
+struct sh_machine_vector mv_sh03 __initmv = {
+ .mv_nr_irqs = 48,
+ .mv_isa_port2addr = sh03_isa_port2addr,
+ .mv_init_irq = init_sh03_IRQ,
+
+#ifdef CONFIG_HEARTBEAT
+ .mv_heartbeat = heartbeat_sh03,
+#endif
+};
+
+ALIAS_MV(sh03)
+
+/* arch/sh/boards/sh03/rtc.c */
+void sh03_time_init(void);
+
+int __init platform_setup(void)
+{
+ board_time_init = sh03_time_init;
+ return 0;
+}
diff --git a/arch/sh/boards/sh2000/Makefile b/arch/sh/boards/sh2000/Makefile
new file mode 100644
index 000000000000..05d390c3599c
--- /dev/null
+++ b/arch/sh/boards/sh2000/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for the SH2000 specific parts of the kernel
+#
+
+obj-y := setup.o
+
diff --git a/arch/sh/boards/sh2000/setup.c b/arch/sh/boards/sh2000/setup.c
new file mode 100644
index 000000000000..a290b1d09fb2
--- /dev/null
+++ b/arch/sh/boards/sh2000/setup.c
@@ -0,0 +1,71 @@
+/*
+ * linux/arch/sh/kernel/setup_sh2000.c
+ *
+ * Copyright (C) 2001 SUGIOKA Tochinobu
+ *
+ * SH-2000 Support.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+
+#include <asm/io.h>
+#include <asm/machvec.h>
+#include <asm/mach/sh2000.h>
+
+#define CF_CIS_BASE 0xb4200000
+
+#define PORT_PECR 0xa4000108
+#define PORT_PHCR 0xa400010E
+#define PORT_ICR1 0xa4000010
+#define PORT_IRR0 0xa4000004
+
+#define IDE_OFFSET 0xb6200000
+#define NIC_OFFSET 0xb6000000
+#define EXTBUS_OFFSET 0xba000000
+
+
+const char *get_system_type(void)
+{
+ return "sh2000";
+}
+
+static unsigned long sh2000_isa_port2addr(unsigned long offset)
+{
+ if((offset & ~7) == 0x1f0 || offset == 0x3f6)
+ return IDE_OFFSET + offset;
+ else if((offset & ~0x1f) == 0x300)
+ return NIC_OFFSET + offset;
+ return EXTBUS_OFFSET + offset;
+}
+
+/*
+ * The Machine Vector
+ */
+struct sh_machine_vector mv_sh2000 __initmv = {
+ .mv_nr_irqs = 80,
+ .mv_isa_port2addr = sh2000_isa_port2addr,
+};
+ALIAS_MV(sh2000)
+
+/*
+ * Initialize the board
+ */
+int __init platform_setup(void)
+{
+ /* XXX: RTC setting comes here */
+
+ /* These should be done by BIOS/IPL ... */
+ /* Enable nCE2A, nCE2B output */
+ ctrl_outw(ctrl_inw(PORT_PECR) & ~0xf00, PORT_PECR);
+ /* Enable the Compact Flash card, and set the level interrupt */
+ ctrl_outw(0x0042, CF_CIS_BASE+0x0200);
+ /* Enable interrupt */
+ ctrl_outw(ctrl_inw(PORT_PHCR) & ~0x03f3, PORT_PHCR);
+ ctrl_outw(1, PORT_ICR1);
+ ctrl_outw(ctrl_inw(PORT_IRR0) & ~0xff3f, PORT_IRR0);
+ printk(KERN_INFO "SH-2000 Setup...done\n");
+ return 0;
+}
diff --git a/arch/sh/boards/snapgear/Makefile b/arch/sh/boards/snapgear/Makefile
new file mode 100644
index 000000000000..59fc976bfc2f
--- /dev/null
+++ b/arch/sh/boards/snapgear/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for the SnapGear specific parts of the kernel
+#
+
+obj-y := setup.o io.o rtc.o
+
diff --git a/arch/sh/boards/snapgear/io.c b/arch/sh/boards/snapgear/io.c
new file mode 100644
index 000000000000..e2eb78fc381d
--- /dev/null
+++ b/arch/sh/boards/snapgear/io.c
@@ -0,0 +1,226 @@
+/*
+ * linux/arch/sh/kernel/io_7751se.c
+ *
+ * Copyright (C) 2002 David McCullough <davidm@snapgear.com>
+ * Copyright (C) 2001 Ian da Silva, Jeremy Siegel
+ * Based largely on io_se.c.
+ *
+ * I/O routine for Hitachi 7751 SolutionEngine.
+ *
+ * Initial version only to support LAN access; some
+ * placeholder code from io_se.c left in with the
+ * expectation of later SuperIO and PCMCIA access.
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <asm/io.h>
+#include <asm/addrspace.h>
+
+#include <asm/pci.h>
+#include "../../drivers/pci/pci-sh7751.h"
+
+#ifdef CONFIG_SH_SECUREEDGE5410
+unsigned short secureedge5410_ioport;
+#endif
+
+/*
+ * The SnapGear uses the built-in PCI controller (PCIC)
+ * of the 7751 processor
+ */
+
+#define PCIIOBR (volatile long *)PCI_REG(SH7751_PCIIOBR)
+#define PCIMBR (volatile long *)PCI_REG(SH7751_PCIMBR)
+#define PCI_IO_AREA SH7751_PCI_IO_BASE
+#define PCI_MEM_AREA SH7751_PCI_CONFIG_BASE
+
+
+#define PCI_IOMAP(adr) (PCI_IO_AREA + (adr & ~SH7751_PCIIOBR_MASK))
+
+
+#define maybebadio(name,port) \
+ printk("bad PC-like io %s for port 0x%lx at 0x%08x\n", \
+ #name, (port), (__u32) __builtin_return_address(0))
+
+
+static inline void delay(void)
+{
+ ctrl_inw(0xa0000000);
+}
+
+
+static inline volatile __u16 *port2adr(unsigned int port)
+{
+#if 0
+ if (port >= 0x2000)
+ return (volatile __u16 *) (PA_MRSHPC + (port - 0x2000));
+#endif
+ maybebadio(name,(unsigned long)port);
+ return (volatile __u16*)port;
+}
+
+
+/* In case someone configures the kernel w/o PCI support: in that */
+/* scenario, don't ever bother to check for PCI-window addresses */
+
+/* NOTE: WINDOW CHECK MAY BE A BIT OFF, HIGH PCIBIOS_MIN_IO WRAPS? */
+#if defined(CONFIG_PCI)
+#define CHECK_SH7751_PCIIO(port) \
+ ((port >= PCIBIOS_MIN_IO) && (port < (PCIBIOS_MIN_IO + SH7751_PCI_IO_SIZE)))
+#else
+#define CHECK_SH7751_PCIIO(port) (0)
+#endif
+
+/*
+ * General outline: remap really low stuff [eventually] to SuperIO,
+ * stuff in PCI IO space (at or above window at pci.h:PCIBIOS_MIN_IO)
+ * is mapped through the PCI IO window. Stuff with high bits (PXSEG)
+ * should be way beyond the window, and is used w/o translation for
+ * compatibility.
+ */
+
+unsigned char snapgear_inb(unsigned long port)
+{
+ if (PXSEG(port))
+ return *(volatile unsigned char *)port;
+ else if (CHECK_SH7751_PCIIO(port))
+ return *(volatile unsigned char *)PCI_IOMAP(port);
+ else
+ return (*port2adr(port))&0xff;
+}
+
+
+unsigned char snapgear_inb_p(unsigned long port)
+{
+ unsigned char v;
+
+ if (PXSEG(port))
+ v = *(volatile unsigned char *)port;
+ else if (CHECK_SH7751_PCIIO(port))
+ v = *(volatile unsigned char *)PCI_IOMAP(port);
+ else
+ v = (*port2adr(port))&0xff;
+ delay();
+ return v;
+}
+
+
+unsigned short snapgear_inw(unsigned long port)
+{
+ if (PXSEG(port))
+ return *(volatile unsigned short *)port;
+ else if (CHECK_SH7751_PCIIO(port))
+ return *(volatile unsigned short *)PCI_IOMAP(port);
+ else if (port >= 0x2000)
+ return *port2adr(port);
+ else
+ maybebadio(inw, port);
+ return 0;
+}
+
+
+unsigned int snapgear_inl(unsigned long port)
+{
+ if (PXSEG(port))
+ return *(volatile unsigned long *)port;
+ else if (CHECK_SH7751_PCIIO(port))
+ return *(volatile unsigned int *)PCI_IOMAP(port);
+ else if (port >= 0x2000)
+ return *port2adr(port);
+ else
+ maybebadio(inl, port);
+ return 0;
+}
+
+
+void snapgear_outb(unsigned char value, unsigned long port)
+{
+
+ if (PXSEG(port))
+ *(volatile unsigned char *)port = value;
+ else if (CHECK_SH7751_PCIIO(port))
+ *((unsigned char*)PCI_IOMAP(port)) = value;
+ else
+ *(port2adr(port)) = value;
+}
+
+
+void snapgear_outb_p(unsigned char value, unsigned long port)
+{
+ if (PXSEG(port))
+ *(volatile unsigned char *)port = value;
+ else if (CHECK_SH7751_PCIIO(port))
+ *((unsigned char*)PCI_IOMAP(port)) = value;
+ else
+ *(port2adr(port)) = value;
+ delay();
+}
+
+
+void snapgear_outw(unsigned short value, unsigned long port)
+{
+ if (PXSEG(port))
+ *(volatile unsigned short *)port = value;
+ else if (CHECK_SH7751_PCIIO(port))
+ *((unsigned short *)PCI_IOMAP(port)) = value;
+ else if (port >= 0x2000)
+ *port2adr(port) = value;
+ else
+ maybebadio(outw, port);
+}
+
+
+void snapgear_outl(unsigned int value, unsigned long port)
+{
+ if (PXSEG(port))
+ *(volatile unsigned long *)port = value;
+ else if (CHECK_SH7751_PCIIO(port))
+ *((unsigned long*)PCI_IOMAP(port)) = value;
+ else
+ maybebadio(outl, port);
+}
+
+void snapgear_insl(unsigned long port, void *addr, unsigned long count)
+{
+ maybebadio(insl, port);
+}
+
+void snapgear_outsl(unsigned long port, const void *addr, unsigned long count)
+{
+ maybebadio(outsw, port);
+}
+
+/* Map ISA bus address to the real address. Only for PCMCIA. */
+
+
+/* ISA page descriptor. */
+static __u32 sh_isa_memmap[256];
+
+
+#if 0
+static int sh_isa_mmap(__u32 start, __u32 length, __u32 offset)
+{
+ int idx;
+
+ if (start >= 0x100000 || (start & 0xfff) || (length != 0x1000))
+ return -1;
+
+ idx = start >> 12;
+ sh_isa_memmap[idx] = 0xb8000000 + (offset &~ 0xfff);
+#if 0
+ printk("sh_isa_mmap: start %x len %x offset %x (idx %x paddr %x)\n",
+ start, length, offset, idx, sh_isa_memmap[idx]);
+#endif
+ return 0;
+}
+#endif
+
+unsigned long snapgear_isa_port2addr(unsigned long offset)
+{
+ int idx;
+
+ idx = (offset >> 12) & 0xff;
+ offset &= 0xfff;
+ return sh_isa_memmap[idx] + offset;
+}
diff --git a/arch/sh/boards/snapgear/rtc.c b/arch/sh/boards/snapgear/rtc.c
new file mode 100644
index 000000000000..b71e009da35c
--- /dev/null
+++ b/arch/sh/boards/snapgear/rtc.c
@@ -0,0 +1,333 @@
+/****************************************************************************/
+/*
+ * linux/arch/sh/boards/snapgear/rtc.c -- Secureedge5410 RTC code
+ *
+ * Copyright (C) 2002 David McCullough <davidm@snapgear.com>
+ * Copyright (C) 2003 Paul Mundt <lethal@linux-sh.org>
+ *
+ * The SecureEdge5410 can have one of 2 real time clocks, the SH
+ * built in version or the preferred external DS1302. Here we work out
+ * each to see what we have and then run with it.
+ */
+/****************************************************************************/
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/rtc.h>
+#include <linux/mc146818rtc.h>
+
+#include <asm/io.h>
+#include <asm/rtc.h>
+#include <asm/mc146818rtc.h>
+
+/****************************************************************************/
+
+static int use_ds1302 = 0;
+
+/****************************************************************************/
+/*
+ * we need to implement a DS1302 driver here that can operate in
+ * conjunction with the builtin rtc driver which is already quite friendly
+ */
+/*****************************************************************************/
+
+#define RTC_CMD_READ 0x81 /* Read command */
+#define RTC_CMD_WRITE 0x80 /* Write command */
+
+#define RTC_ADDR_YEAR 0x06 /* Address of year register */
+#define RTC_ADDR_DAY 0x05 /* Address of day of week register */
+#define RTC_ADDR_MON 0x04 /* Address of month register */
+#define RTC_ADDR_DATE 0x03 /* Address of day of month register */
+#define RTC_ADDR_HOUR 0x02 /* Address of hour register */
+#define RTC_ADDR_MIN 0x01 /* Address of minute register */
+#define RTC_ADDR_SEC 0x00 /* Address of second register */
+
+#define RTC_RESET 0x1000
+#define RTC_IODATA 0x0800
+#define RTC_SCLK 0x0400
+
+#define set_dirp(x)
+#define get_dirp(x) 0
+#define set_dp(x) SECUREEDGE_WRITE_IOPORT(x, 0x1c00)
+#define get_dp(x) SECUREEDGE_READ_IOPORT()
+
+static void ds1302_sendbits(unsigned int val)
+{
+ int i;
+
+ for (i = 8; (i); i--, val >>= 1) {
+ set_dp((get_dp() & ~RTC_IODATA) | ((val & 0x1) ? RTC_IODATA : 0));
+ set_dp(get_dp() | RTC_SCLK); // clock high
+ set_dp(get_dp() & ~RTC_SCLK); // clock low
+ }
+}
+
+static unsigned int ds1302_recvbits(void)
+{
+ unsigned int val;
+ int i;
+
+ for (i = 0, val = 0; (i < 8); i++) {
+ val |= (((get_dp() & RTC_IODATA) ? 1 : 0) << i);
+ set_dp(get_dp() | RTC_SCLK); // clock high
+ set_dp(get_dp() & ~RTC_SCLK); // clock low
+ }
+ return(val);
+}
+
+static unsigned int ds1302_readbyte(unsigned int addr)
+{
+ unsigned int val;
+ unsigned long flags;
+
+#if 0
+ printk("SnapGear RTC: ds1302_readbyte(addr=%x)\n", addr);
+#endif
+
+ local_irq_save(flags);
+ set_dirp(get_dirp() | RTC_RESET | RTC_IODATA | RTC_SCLK);
+ set_dp(get_dp() & ~(RTC_RESET | RTC_IODATA | RTC_SCLK));
+
+ set_dp(get_dp() | RTC_RESET);
+ ds1302_sendbits(((addr & 0x3f) << 1) | RTC_CMD_READ);
+ set_dirp(get_dirp() & ~RTC_IODATA);
+ val = ds1302_recvbits();
+ set_dp(get_dp() & ~RTC_RESET);
+ local_irq_restore(flags);
+
+ return(val);
+}
+
+static void ds1302_writebyte(unsigned int addr, unsigned int val)
+{
+ unsigned long flags;
+
+#if 0
+ printk("SnapGear RTC: ds1302_writebyte(addr=%x)\n", addr);
+#endif
+
+ local_irq_save(flags);
+ set_dirp(get_dirp() | RTC_RESET | RTC_IODATA | RTC_SCLK);
+ set_dp(get_dp() & ~(RTC_RESET | RTC_IODATA | RTC_SCLK));
+ set_dp(get_dp() | RTC_RESET);
+ ds1302_sendbits(((addr & 0x3f) << 1) | RTC_CMD_WRITE);
+ ds1302_sendbits(val);
+ set_dp(get_dp() & ~RTC_RESET);
+ local_irq_restore(flags);
+}
+
+static void ds1302_reset(void)
+{
+ unsigned long flags;
+ /* Hardware dependant reset/init */
+ local_irq_save(flags);
+ set_dirp(get_dirp() | RTC_RESET | RTC_IODATA | RTC_SCLK);
+ set_dp(get_dp() & ~(RTC_RESET | RTC_IODATA | RTC_SCLK));
+ local_irq_restore(flags);
+}
+
+/*****************************************************************************/
+
+static inline int bcd2int(int val)
+{
+ return((((val & 0xf0) >> 4) * 10) + (val & 0xf));
+}
+
+static inline int int2bcd(int val)
+{
+ return(((val / 10) << 4) + (val % 10));
+}
+
+/*****************************************************************************/
+/*
+ * Write and Read some RAM in the DS1302, if it works assume it's there
+ * Otherwise use the SH4 internal RTC
+ */
+
+void snapgear_rtc_gettimeofday(struct timespec *);
+int snapgear_rtc_settimeofday(const time_t);
+
+void __init secureedge5410_rtc_init(void)
+{
+ unsigned char *test = "snapgear";
+ int i;
+
+ ds1302_reset();
+
+ use_ds1302 = 1;
+
+ for (i = 0; test[i]; i++)
+ ds1302_writebyte(32 + i, test[i]);
+
+ for (i = 0; test[i]; i++)
+ if (ds1302_readbyte(32 + i) != test[i]) {
+ use_ds1302 = 0;
+ break;
+ }
+
+ if (use_ds1302) {
+ rtc_get_time = snapgear_rtc_gettimeofday;
+ rtc_set_time = snapgear_rtc_settimeofday;
+ } else {
+ rtc_get_time = sh_rtc_gettimeofday;
+ rtc_set_time = sh_rtc_settimeofday;
+ }
+
+ printk("SnapGear RTC: using %s rtc.\n", use_ds1302 ? "ds1302" : "internal");
+}
+
+/****************************************************************************/
+/*
+ * our generic interface that chooses the correct code to use
+ */
+
+void snapgear_rtc_gettimeofday(struct timespec *ts)
+{
+ unsigned int sec, min, hr, day, mon, yr;
+
+ if (!use_ds1302) {
+ sh_rtc_gettimeofday(ts);
+ return;
+ }
+
+ sec = bcd2int(ds1302_readbyte(RTC_ADDR_SEC));
+ min = bcd2int(ds1302_readbyte(RTC_ADDR_MIN));
+ hr = bcd2int(ds1302_readbyte(RTC_ADDR_HOUR));
+ day = bcd2int(ds1302_readbyte(RTC_ADDR_DATE));
+ mon = bcd2int(ds1302_readbyte(RTC_ADDR_MON));
+ yr = bcd2int(ds1302_readbyte(RTC_ADDR_YEAR));
+
+bad_time:
+ if (yr > 99 || mon < 1 || mon > 12 || day > 31 || day < 1 ||
+ hr > 23 || min > 59 || sec > 59) {
+ printk(KERN_ERR
+ "SnapGear RTC: invalid value, resetting to 1 Jan 2000\n");
+ ds1302_writebyte(RTC_ADDR_MIN, min = 0);
+ ds1302_writebyte(RTC_ADDR_HOUR, hr = 0);
+ ds1302_writebyte(RTC_ADDR_DAY, 7);
+ ds1302_writebyte(RTC_ADDR_DATE, day = 1);
+ ds1302_writebyte(RTC_ADDR_MON, mon = 1);
+ ds1302_writebyte(RTC_ADDR_YEAR, yr = 0);
+ ds1302_writebyte(RTC_ADDR_SEC, sec = 0);
+ }
+
+ ts->tv_sec = mktime(2000 + yr, mon, day, hr, min, sec);
+ if (ts->tv_sec < 0) {
+#if 0
+ printk("BAD TIME %d %d %d %d %d %d\n", yr, mon, day, hr, min, sec);
+#endif
+ yr = 100;
+ goto bad_time;
+ }
+ ts->tv_nsec = 0;
+}
+
+int snapgear_rtc_settimeofday(const time_t secs)
+{
+ int retval = 0;
+ int real_seconds, real_minutes, cmos_minutes;
+ unsigned long nowtime;
+
+ if (!use_ds1302)
+ return sh_rtc_settimeofday(secs);
+
+/*
+ * This is called direct from the kernel timer handling code.
+ * It is supposed to synchronize the kernel clock to the RTC.
+ */
+
+ nowtime = secs;
+
+#if 1
+ printk("SnapGear RTC: snapgear_rtc_settimeofday(nowtime=%ld)\n", nowtime);
+#endif
+
+ /* STOP RTC */
+ ds1302_writebyte(RTC_ADDR_SEC, ds1302_readbyte(RTC_ADDR_SEC) | 0x80);
+
+ cmos_minutes = bcd2int(ds1302_readbyte(RTC_ADDR_MIN));
+
+ /*
+ * since we're only adjusting minutes and seconds,
+ * don't interfere with hour overflow. This avoids
+ * messing with unknown time zones but requires your
+ * RTC not to be off by more than 15 minutes
+ */
+ real_seconds = nowtime % 60;
+ real_minutes = nowtime / 60;
+ if (((abs(real_minutes - cmos_minutes) + 15)/30) & 1)
+ real_minutes += 30; /* correct for half hour time zone */
+ real_minutes %= 60;
+
+ if (abs(real_minutes - cmos_minutes) < 30) {
+ ds1302_writebyte(RTC_ADDR_MIN, int2bcd(real_minutes));
+ ds1302_writebyte(RTC_ADDR_SEC, int2bcd(real_seconds));
+ } else {
+ printk(KERN_WARNING
+ "SnapGear RTC: can't update from %d to %d\n",
+ cmos_minutes, real_minutes);
+ retval = -1;
+ }
+
+ /* START RTC */
+ ds1302_writebyte(RTC_ADDR_SEC, ds1302_readbyte(RTC_ADDR_SEC) & ~0x80);
+ return(0);
+}
+
+unsigned char secureedge5410_cmos_read(int addr)
+{
+ unsigned char val = 0;
+
+ if (!use_ds1302)
+ return(__CMOS_READ(addr, w));
+
+ switch(addr) {
+ case RTC_SECONDS: val = ds1302_readbyte(RTC_ADDR_SEC); break;
+ case RTC_SECONDS_ALARM: break;
+ case RTC_MINUTES: val = ds1302_readbyte(RTC_ADDR_MIN); break;
+ case RTC_MINUTES_ALARM: break;
+ case RTC_HOURS: val = ds1302_readbyte(RTC_ADDR_HOUR); break;
+ case RTC_HOURS_ALARM: break;
+ case RTC_DAY_OF_WEEK: val = ds1302_readbyte(RTC_ADDR_DAY); break;
+ case RTC_DAY_OF_MONTH: val = ds1302_readbyte(RTC_ADDR_DATE); break;
+ case RTC_MONTH: val = ds1302_readbyte(RTC_ADDR_MON); break;
+ case RTC_YEAR: val = ds1302_readbyte(RTC_ADDR_YEAR); break;
+ case RTC_REG_A: /* RTC_FREQ_SELECT */ break;
+ case RTC_REG_B: /* RTC_CONTROL */ break;
+ case RTC_REG_C: /* RTC_INTR_FLAGS */ break;
+ case RTC_REG_D: val = RTC_VRT /* RTC_VALID */; break;
+ default: break;
+ }
+
+ return(val);
+}
+
+void secureedge5410_cmos_write(unsigned char val, int addr)
+{
+ if (!use_ds1302) {
+ __CMOS_WRITE(val, addr, w);
+ return;
+ }
+
+ switch(addr) {
+ case RTC_SECONDS: ds1302_writebyte(RTC_ADDR_SEC, val); break;
+ case RTC_SECONDS_ALARM: break;
+ case RTC_MINUTES: ds1302_writebyte(RTC_ADDR_MIN, val); break;
+ case RTC_MINUTES_ALARM: break;
+ case RTC_HOURS: ds1302_writebyte(RTC_ADDR_HOUR, val); break;
+ case RTC_HOURS_ALARM: break;
+ case RTC_DAY_OF_WEEK: ds1302_writebyte(RTC_ADDR_DAY, val); break;
+ case RTC_DAY_OF_MONTH: ds1302_writebyte(RTC_ADDR_DATE, val); break;
+ case RTC_MONTH: ds1302_writebyte(RTC_ADDR_MON, val); break;
+ case RTC_YEAR: ds1302_writebyte(RTC_ADDR_YEAR, val); break;
+ case RTC_REG_A: /* RTC_FREQ_SELECT */ break;
+ case RTC_REG_B: /* RTC_CONTROL */ break;
+ case RTC_REG_C: /* RTC_INTR_FLAGS */ break;
+ case RTC_REG_D: /* RTC_VALID */ break;
+ default: break;
+ }
+}
+
+/****************************************************************************/
diff --git a/arch/sh/boards/snapgear/setup.c b/arch/sh/boards/snapgear/setup.c
new file mode 100644
index 000000000000..08fc98342a0b
--- /dev/null
+++ b/arch/sh/boards/snapgear/setup.c
@@ -0,0 +1,216 @@
+/****************************************************************************/
+/*
+ * linux/arch/sh/boards/snapgear/setup.c
+ *
+ * Copyright (C) 2002 David McCullough <davidm@snapgear.com>
+ * Copyright (C) 2003 Paul Mundt <lethal@linux-sh.org>
+ *
+ * Based on files with the following comments:
+ *
+ * Copyright (C) 2000 Kazumoto Kojima
+ *
+ * Modified for 7751 Solution Engine by
+ * Ian da Silva and Jeremy Siegel, 2001.
+ */
+/****************************************************************************/
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/timer.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+
+#include <asm/machvec.h>
+#include <asm/mach/io.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+#include <asm/cpu/timer.h>
+
+extern void (*board_time_init)(void);
+extern void secureedge5410_rtc_init(void);
+extern void pcibios_init(void);
+
+/****************************************************************************/
+/*
+ * EraseConfig handling functions
+ */
+
+static irqreturn_t eraseconfig_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ volatile char dummy __attribute__((unused)) = * (volatile char *) 0xb8000000;
+
+ printk("SnapGear: erase switch interrupt!\n");
+
+ return IRQ_HANDLED;
+}
+
+static int __init eraseconfig_init(void)
+{
+ printk("SnapGear: EraseConfig init\n");
+ /* Setup "EraseConfig" switch on external IRQ 0 */
+ if (request_irq(IRL0_IRQ, eraseconfig_interrupt, SA_INTERRUPT,
+ "Erase Config", NULL))
+ printk("SnapGear: failed to register IRQ%d for Reset witch\n",
+ IRL0_IRQ);
+ else
+ printk("SnapGear: registered EraseConfig switch on IRQ%d\n",
+ IRL0_IRQ);
+ return(0);
+}
+
+module_init(eraseconfig_init);
+
+/****************************************************************************/
+/*
+ * Initialize IRQ setting
+ *
+ * IRL0 = erase switch
+ * IRL1 = eth0
+ * IRL2 = eth1
+ * IRL3 = crypto
+ */
+
+static void __init init_snapgear_IRQ(void)
+{
+ /* enable individual interrupt mode for externals */
+ ctrl_outw(ctrl_inw(INTC_ICR) | INTC_ICR_IRLM, INTC_ICR);
+
+ printk("Setup SnapGear IRQ/IPR ...\n");
+
+ make_ipr_irq(IRL0_IRQ, IRL0_IPR_ADDR, IRL0_IPR_POS, IRL0_PRIORITY);
+ make_ipr_irq(IRL1_IRQ, IRL1_IPR_ADDR, IRL1_IPR_POS, IRL1_PRIORITY);
+ make_ipr_irq(IRL2_IRQ, IRL2_IPR_ADDR, IRL2_IPR_POS, IRL2_PRIORITY);
+ make_ipr_irq(IRL3_IRQ, IRL3_IPR_ADDR, IRL3_IPR_POS, IRL3_PRIORITY);
+}
+
+/****************************************************************************/
+/*
+ * Fast poll interrupt simulator.
+ */
+
+/*
+ * Leave all of the fast timer/fast poll stuff commented out for now, since
+ * it's not clear whether it actually works or not. Since it wasn't being used
+ * at all in 2.4, we'll assume it's not sane for 2.6 either.. -- PFM
+ */
+#if 0
+#define FAST_POLL 1000
+//#define FAST_POLL_INTR
+
+#define FASTTIMER_IRQ 17
+#define FASTTIMER_IPR_ADDR INTC_IPRA
+#define FASTTIMER_IPR_POS 2
+#define FASTTIMER_PRIORITY 3
+
+#ifdef FAST_POLL_INTR
+#define TMU1_TCR_INIT 0x0020
+#else
+#define TMU1_TCR_INIT 0
+#endif
+#define TMU_TSTR_INIT 1
+#define TMU1_TCR_CALIB 0x0000
+
+
+#ifdef FAST_POLL_INTR
+static void fast_timer_irq(int irq, void *dev_instance, struct pt_regs *regs)
+{
+ unsigned long timer_status;
+ timer_status = ctrl_inw(TMU1_TCR);
+ timer_status &= ~0x100;
+ ctrl_outw(timer_status, TMU1_TCR);
+}
+#endif
+
+/*
+ * return the current ticks on the fast timer
+ */
+
+unsigned long fast_timer_count(void)
+{
+ return(ctrl_inl(TMU1_TCNT));
+}
+
+/*
+ * setup a fast timer for profiling etc etc
+ */
+
+static void setup_fast_timer()
+{
+ unsigned long interval;
+
+#ifdef FAST_POLL_INTR
+ interval = (current_cpu_data.module_clock/4 + FAST_POLL/2) / FAST_POLL;
+
+ make_ipr_irq(FASTTIMER_IRQ, FASTTIMER_IPR_ADDR, FASTTIMER_IPR_POS,
+ FASTTIMER_PRIORITY);
+
+ printk("SnapGear: %dHz fast timer on IRQ %d\n",FAST_POLL,FASTTIMER_IRQ);
+
+ if (request_irq(FASTTIMER_IRQ, fast_timer_irq, 0, "SnapGear fast timer",
+ NULL) != 0)
+ printk("%s(%d): request_irq() failed?\n", __FILE__, __LINE__);
+#else
+ printk("SnapGear: fast timer running\n",FAST_POLL,FASTTIMER_IRQ);
+ interval = 0xffffffff;
+#endif
+
+ ctrl_outb(ctrl_inb(TMU_TSTR) & ~0x2, TMU_TSTR); /* disable timer 1 */
+ ctrl_outw(TMU1_TCR_INIT, TMU1_TCR);
+ ctrl_outl(interval, TMU1_TCOR);
+ ctrl_outl(interval, TMU1_TCNT);
+ ctrl_outb(ctrl_inb(TMU_TSTR) | 0x2, TMU_TSTR); /* enable timer 1 */
+
+ printk("Timer count 1 = 0x%x\n", fast_timer_count());
+ udelay(1000);
+ printk("Timer count 2 = 0x%x\n", fast_timer_count());
+}
+#endif
+
+/****************************************************************************/
+
+const char *get_system_type(void)
+{
+ return "SnapGear SecureEdge5410";
+}
+
+/*
+ * The Machine Vector
+ */
+
+struct sh_machine_vector mv_snapgear __initmv = {
+ .mv_nr_irqs = 72,
+
+ .mv_inb = snapgear_inb,
+ .mv_inw = snapgear_inw,
+ .mv_inl = snapgear_inl,
+ .mv_outb = snapgear_outb,
+ .mv_outw = snapgear_outw,
+ .mv_outl = snapgear_outl,
+
+ .mv_inb_p = snapgear_inb_p,
+ .mv_inw_p = snapgear_inw,
+ .mv_inl_p = snapgear_inl,
+ .mv_outb_p = snapgear_outb_p,
+ .mv_outw_p = snapgear_outw,
+ .mv_outl_p = snapgear_outl,
+
+ .mv_isa_port2addr = snapgear_isa_port2addr,
+
+ .mv_init_irq = init_snapgear_IRQ,
+};
+ALIAS_MV(snapgear)
+
+/*
+ * Initialize the board
+ */
+
+int __init platform_setup(void)
+{
+ board_time_init = secureedge5410_rtc_init;
+
+ return 0;
+}
+
diff --git a/arch/sh/boards/superh/microdev/Makefile b/arch/sh/boards/superh/microdev/Makefile
new file mode 100644
index 000000000000..1387dd6c85eb
--- /dev/null
+++ b/arch/sh/boards/superh/microdev/Makefile
@@ -0,0 +1,8 @@
+#
+# Makefile for the SuperH MicroDev specific parts of the kernel
+#
+
+obj-y := setup.o irq.o io.o
+
+obj-$(CONFIG_HEARTBEAT) += led.o
+
diff --git a/arch/sh/boards/superh/microdev/io.c b/arch/sh/boards/superh/microdev/io.c
new file mode 100644
index 000000000000..fe83b2c03076
--- /dev/null
+++ b/arch/sh/boards/superh/microdev/io.c
@@ -0,0 +1,370 @@
+/*
+ * linux/arch/sh/kernel/io_microdev.c
+ *
+ * Copyright (C) 2003 Sean McGoogan (Sean.McGoogan@superh.com)
+ * Copyright (C) 2003, 2004 SuperH, Inc.
+ * Copyright (C) 2004 Paul Mundt
+ *
+ * SuperH SH4-202 MicroDev board support.
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License. See linux/COPYING for more information.
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/wait.h>
+#include <asm/io.h>
+#include <asm/mach/io.h>
+
+ /*
+ * we need to have a 'safe' address to re-direct all I/O requests
+ * that we do not explicitly wish to handle. This safe address
+ * must have the following properies:
+ *
+ * * writes are ignored (no exception)
+ * * reads are benign (no side-effects)
+ * * accesses of width 1, 2 and 4-bytes are all valid.
+ *
+ * The Processor Version Register (PVR) has these properties.
+ */
+#define PVR 0xff000030 /* Processor Version Register */
+
+
+#define IO_IDE2_BASE 0x170ul /* I/O base for SMSC FDC37C93xAPM IDE #2 */
+#define IO_IDE1_BASE 0x1f0ul /* I/O base for SMSC FDC37C93xAPM IDE #1 */
+#define IO_ISP1161_BASE 0x290ul /* I/O port for Philips ISP1161x USB chip */
+#define IO_SERIAL2_BASE 0x2f8ul /* I/O base for SMSC FDC37C93xAPM Serial #2 */
+#define IO_LAN91C111_BASE 0x300ul /* I/O base for SMSC LAN91C111 Ethernet chip */
+#define IO_IDE2_MISC 0x376ul /* I/O misc for SMSC FDC37C93xAPM IDE #2 */
+#define IO_SUPERIO_BASE 0x3f0ul /* I/O base for SMSC FDC37C93xAPM SuperIO chip */
+#define IO_IDE1_MISC 0x3f6ul /* I/O misc for SMSC FDC37C93xAPM IDE #1 */
+#define IO_SERIAL1_BASE 0x3f8ul /* I/O base for SMSC FDC37C93xAPM Serial #1 */
+
+#define IO_ISP1161_EXTENT 0x04ul /* I/O extent for Philips ISP1161x USB chip */
+#define IO_LAN91C111_EXTENT 0x10ul /* I/O extent for SMSC LAN91C111 Ethernet chip */
+#define IO_SUPERIO_EXTENT 0x02ul /* I/O extent for SMSC FDC37C93xAPM SuperIO chip */
+#define IO_IDE_EXTENT 0x08ul /* I/O extent for IDE Task Register set */
+#define IO_SERIAL_EXTENT 0x10ul
+
+#define IO_LAN91C111_PHYS 0xa7500000ul /* Physical address of SMSC LAN91C111 Ethernet chip */
+#define IO_ISP1161_PHYS 0xa7700000ul /* Physical address of Philips ISP1161x USB chip */
+#define IO_SUPERIO_PHYS 0xa7800000ul /* Physical address of SMSC FDC37C93xAPM SuperIO chip */
+
+#define PORT2ADDR(x) (microdev_isa_port2addr(x))
+
+
+static inline void delay(void)
+{
+#if defined(CONFIG_PCI)
+ /* System board present, just make a dummy SRAM access. (CS0 will be
+ mapped to PCI memory, probably good to avoid it.) */
+ ctrl_inw(0xa6800000);
+#else
+ /* CS0 will be mapped to flash, ROM etc so safe to access it. */
+ ctrl_inw(0xa0000000);
+#endif
+}
+
+unsigned char microdev_inb(unsigned long port)
+{
+#ifdef CONFIG_PCI
+ if (port >= PCIBIOS_MIN_IO)
+ return microdev_pci_inb(port);
+#endif
+ return *(volatile unsigned char*)PORT2ADDR(port);
+}
+
+unsigned short microdev_inw(unsigned long port)
+{
+#ifdef CONFIG_PCI
+ if (port >= PCIBIOS_MIN_IO)
+ return microdev_pci_inw(port);
+#endif
+ return *(volatile unsigned short*)PORT2ADDR(port);
+}
+
+unsigned int microdev_inl(unsigned long port)
+{
+#ifdef CONFIG_PCI
+ if (port >= PCIBIOS_MIN_IO)
+ return microdev_pci_inl(port);
+#endif
+ return *(volatile unsigned int*)PORT2ADDR(port);
+}
+
+void microdev_outb(unsigned char b, unsigned long port)
+{
+#ifdef CONFIG_PCI
+ if (port >= PCIBIOS_MIN_IO) {
+ microdev_pci_outb(b, port);
+ return;
+ }
+#endif
+
+ /*
+ * There is a board feature with the current SH4-202 MicroDev in
+ * that the 2 byte enables (nBE0 and nBE1) are tied together (and
+ * to the Chip Select Line (Ethernet_CS)). Due to this conectivity,
+ * it is not possible to safely perform 8-bit writes to the
+ * Ethernet registers, as 16-bits will be consumed from the Data
+ * lines (corrupting the other byte). Hence, this function is
+ * written to impliment 16-bit read/modify/write for all byte-wide
+ * acceses.
+ *
+ * Note: there is no problem with byte READS (even or odd).
+ *
+ * Sean McGoogan - 16th June 2003.
+ */
+ if ((port >= IO_LAN91C111_BASE) &&
+ (port < IO_LAN91C111_BASE + IO_LAN91C111_EXTENT)) {
+ /*
+ * Then are trying to perform a byte-write to the
+ * LAN91C111. This needs special care.
+ */
+ if (port % 2 == 1) { /* is the port odd ? */
+ /* unset bit-0, i.e. make even */
+ const unsigned long evenPort = port-1;
+ unsigned short word;
+
+ /*
+ * do a 16-bit read/write to write to 'port',
+ * preserving even byte.
+ *
+ * Even addresses are bits 0-7
+ * Odd addresses are bits 8-15
+ */
+ word = microdev_inw(evenPort);
+ word = (word & 0xffu) | (b << 8);
+ microdev_outw(word, evenPort);
+ } else {
+ /* else, we are trying to do an even byte write */
+ unsigned short word;
+
+ /*
+ * do a 16-bit read/write to write to 'port',
+ * preserving odd byte.
+ *
+ * Even addresses are bits 0-7
+ * Odd addresses are bits 8-15
+ */
+ word = microdev_inw(port);
+ word = (word & 0xff00u) | (b);
+ microdev_outw(word, port);
+ }
+ } else {
+ *(volatile unsigned char*)PORT2ADDR(port) = b;
+ }
+}
+
+void microdev_outw(unsigned short b, unsigned long port)
+{
+#ifdef CONFIG_PCI
+ if (port >= PCIBIOS_MIN_IO) {
+ microdev_pci_outw(b, port);
+ return;
+ }
+#endif
+ *(volatile unsigned short*)PORT2ADDR(port) = b;
+}
+
+void microdev_outl(unsigned int b, unsigned long port)
+{
+#ifdef CONFIG_PCI
+ if (port >= PCIBIOS_MIN_IO) {
+ microdev_pci_outl(b, port);
+ return;
+ }
+#endif
+ *(volatile unsigned int*)PORT2ADDR(port) = b;
+}
+
+unsigned char microdev_inb_p(unsigned long port)
+{
+ unsigned char v = microdev_inb(port);
+ delay();
+ return v;
+}
+
+unsigned short microdev_inw_p(unsigned long port)
+{
+ unsigned short v = microdev_inw(port);
+ delay();
+ return v;
+}
+
+unsigned int microdev_inl_p(unsigned long port)
+{
+ unsigned int v = microdev_inl(port);
+ delay();
+ return v;
+}
+
+void microdev_outb_p(unsigned char b, unsigned long port)
+{
+ microdev_outb(b, port);
+ delay();
+}
+
+void microdev_outw_p(unsigned short b, unsigned long port)
+{
+ microdev_outw(b, port);
+ delay();
+}
+
+void microdev_outl_p(unsigned int b, unsigned long port)
+{
+ microdev_outl(b, port);
+ delay();
+}
+
+void microdev_insb(unsigned long port, void *buffer, unsigned long count)
+{
+ volatile unsigned char *port_addr;
+ unsigned char *buf = buffer;
+
+ port_addr = (volatile unsigned char *)PORT2ADDR(port);
+
+ while (count--)
+ *buf++ = *port_addr;
+}
+
+void microdev_insw(unsigned long port, void *buffer, unsigned long count)
+{
+ volatile unsigned short *port_addr;
+ unsigned short *buf = buffer;
+
+ port_addr = (volatile unsigned short *)PORT2ADDR(port);
+
+ while (count--)
+ *buf++ = *port_addr;
+}
+
+void microdev_insl(unsigned long port, void *buffer, unsigned long count)
+{
+ volatile unsigned long *port_addr;
+ unsigned int *buf = buffer;
+
+ port_addr = (volatile unsigned long *)PORT2ADDR(port);
+
+ while (count--)
+ *buf++ = *port_addr;
+}
+
+void microdev_outsb(unsigned long port, const void *buffer, unsigned long count)
+{
+ volatile unsigned char *port_addr;
+ const unsigned char *buf = buffer;
+
+ port_addr = (volatile unsigned char *)PORT2ADDR(port);
+
+ while (count--)
+ *port_addr = *buf++;
+}
+
+void microdev_outsw(unsigned long port, const void *buffer, unsigned long count)
+{
+ volatile unsigned short *port_addr;
+ const unsigned short *buf = buffer;
+
+ port_addr = (volatile unsigned short *)PORT2ADDR(port);
+
+ while (count--)
+ *port_addr = *buf++;
+}
+
+void microdev_outsl(unsigned long port, const void *buffer, unsigned long count)
+{
+ volatile unsigned long *port_addr;
+ const unsigned int *buf = buffer;
+
+ port_addr = (volatile unsigned long *)PORT2ADDR(port);
+
+ while (count--)
+ *port_addr = *buf++;
+}
+
+/*
+ * map I/O ports to memory-mapped addresses
+ */
+unsigned long microdev_isa_port2addr(unsigned long offset)
+{
+ unsigned long result;
+
+ if ((offset >= IO_LAN91C111_BASE) &&
+ (offset < IO_LAN91C111_BASE + IO_LAN91C111_EXTENT)) {
+ /*
+ * SMSC LAN91C111 Ethernet chip
+ */
+ result = IO_LAN91C111_PHYS + offset - IO_LAN91C111_BASE;
+ } else if ((offset >= IO_SUPERIO_BASE) &&
+ (offset < IO_SUPERIO_BASE + IO_SUPERIO_EXTENT)) {
+ /*
+ * SMSC FDC37C93xAPM SuperIO chip
+ *
+ * Configuration Registers
+ */
+ result = IO_SUPERIO_PHYS + (offset << 1);
+#if 0
+ } else if (offset == KBD_DATA_REG || offset == KBD_CNTL_REG ||
+ offset == KBD_STATUS_REG) {
+ /*
+ * SMSC FDC37C93xAPM SuperIO chip
+ *
+ * PS/2 Keyboard + Mouse (ports 0x60 and 0x64).
+ */
+ result = IO_SUPERIO_PHYS + (offset << 1);
+#endif
+ } else if (((offset >= IO_IDE1_BASE) &&
+ (offset < IO_IDE1_BASE + IO_IDE_EXTENT)) ||
+ (offset == IO_IDE1_MISC)) {
+ /*
+ * SMSC FDC37C93xAPM SuperIO chip
+ *
+ * IDE #1
+ */
+ result = IO_SUPERIO_PHYS + (offset << 1);
+ } else if (((offset >= IO_IDE2_BASE) &&
+ (offset < IO_IDE2_BASE + IO_IDE_EXTENT)) ||
+ (offset == IO_IDE2_MISC)) {
+ /*
+ * SMSC FDC37C93xAPM SuperIO chip
+ *
+ * IDE #2
+ */
+ result = IO_SUPERIO_PHYS + (offset << 1);
+ } else if ((offset >= IO_SERIAL1_BASE) &&
+ (offset < IO_SERIAL1_BASE + IO_SERIAL_EXTENT)) {
+ /*
+ * SMSC FDC37C93xAPM SuperIO chip
+ *
+ * Serial #1
+ */
+ result = IO_SUPERIO_PHYS + (offset << 1);
+ } else if ((offset >= IO_SERIAL2_BASE) &&
+ (offset < IO_SERIAL2_BASE + IO_SERIAL_EXTENT)) {
+ /*
+ * SMSC FDC37C93xAPM SuperIO chip
+ *
+ * Serial #2
+ */
+ result = IO_SUPERIO_PHYS + (offset << 1);
+ } else if ((offset >= IO_ISP1161_BASE) &&
+ (offset < IO_ISP1161_BASE + IO_ISP1161_EXTENT)) {
+ /*
+ * Philips USB ISP1161x chip
+ */
+ result = IO_ISP1161_PHYS + offset - IO_ISP1161_BASE;
+ } else {
+ /*
+ * safe default.
+ */
+ printk("Warning: unexpected port in %s( offset = 0x%lx )\n",
+ __FUNCTION__, offset);
+ result = PVR;
+ }
+
+ return result;
+}
+
diff --git a/arch/sh/boards/superh/microdev/irq.c b/arch/sh/boards/superh/microdev/irq.c
new file mode 100644
index 000000000000..1298883eca4b
--- /dev/null
+++ b/arch/sh/boards/superh/microdev/irq.c
@@ -0,0 +1,200 @@
+/*
+ * arch/sh/boards/superh/microdev/irq.c
+ *
+ * Copyright (C) 2003 Sean McGoogan (Sean.McGoogan@superh.com)
+ *
+ * SuperH SH4-202 MicroDev board support.
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License. See linux/COPYING for more information.
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/mach/irq.h>
+
+#define NUM_EXTERNAL_IRQS 16 /* IRL0 .. IRL15 */
+
+
+static const struct {
+ unsigned char fpgaIrq;
+ unsigned char mapped;
+ const char *name;
+} fpgaIrqTable[NUM_EXTERNAL_IRQS] = {
+ { 0, 0, "unused" }, /* IRQ #0 IRL=15 0x200 */
+ { MICRODEV_FPGA_IRQ_KEYBOARD, 1, "keyboard" }, /* IRQ #1 IRL=14 0x220 */
+ { MICRODEV_FPGA_IRQ_SERIAL1, 1, "Serial #1"}, /* IRQ #2 IRL=13 0x240 */
+ { MICRODEV_FPGA_IRQ_ETHERNET, 1, "Ethernet" }, /* IRQ #3 IRL=12 0x260 */
+ { MICRODEV_FPGA_IRQ_SERIAL2, 0, "Serial #2"}, /* IRQ #4 IRL=11 0x280 */
+ { 0, 0, "unused" }, /* IRQ #5 IRL=10 0x2a0 */
+ { 0, 0, "unused" }, /* IRQ #6 IRL=9 0x2c0 */
+ { MICRODEV_FPGA_IRQ_USB_HC, 1, "USB" }, /* IRQ #7 IRL=8 0x2e0 */
+ { MICRODEV_IRQ_PCI_INTA, 1, "PCI INTA" }, /* IRQ #8 IRL=7 0x300 */
+ { MICRODEV_IRQ_PCI_INTB, 1, "PCI INTB" }, /* IRQ #9 IRL=6 0x320 */
+ { MICRODEV_IRQ_PCI_INTC, 1, "PCI INTC" }, /* IRQ #10 IRL=5 0x340 */
+ { MICRODEV_IRQ_PCI_INTD, 1, "PCI INTD" }, /* IRQ #11 IRL=4 0x360 */
+ { MICRODEV_FPGA_IRQ_MOUSE, 1, "mouse" }, /* IRQ #12 IRL=3 0x380 */
+ { MICRODEV_FPGA_IRQ_IDE2, 1, "IDE #2" }, /* IRQ #13 IRL=2 0x3a0 */
+ { MICRODEV_FPGA_IRQ_IDE1, 1, "IDE #1" }, /* IRQ #14 IRL=1 0x3c0 */
+ { 0, 0, "unused" }, /* IRQ #15 IRL=0 0x3e0 */
+};
+
+#if (MICRODEV_LINUX_IRQ_KEYBOARD != 1)
+# error Inconsistancy in defining the IRQ# for Keyboard!
+#endif
+
+#if (MICRODEV_LINUX_IRQ_ETHERNET != 3)
+# error Inconsistancy in defining the IRQ# for Ethernet!
+#endif
+
+#if (MICRODEV_LINUX_IRQ_USB_HC != 7)
+# error Inconsistancy in defining the IRQ# for USB!
+#endif
+
+#if (MICRODEV_LINUX_IRQ_MOUSE != 12)
+# error Inconsistancy in defining the IRQ# for PS/2 Mouse!
+#endif
+
+#if (MICRODEV_LINUX_IRQ_IDE2 != 13)
+# error Inconsistancy in defining the IRQ# for secondary IDE!
+#endif
+
+#if (MICRODEV_LINUX_IRQ_IDE1 != 14)
+# error Inconsistancy in defining the IRQ# for primary IDE!
+#endif
+
+static void enable_microdev_irq(unsigned int irq);
+static void disable_microdev_irq(unsigned int irq);
+
+ /* shutdown is same as "disable" */
+#define shutdown_microdev_irq disable_microdev_irq
+
+static void mask_and_ack_microdev(unsigned int);
+static void end_microdev_irq(unsigned int irq);
+
+static unsigned int startup_microdev_irq(unsigned int irq)
+{
+ enable_microdev_irq(irq);
+ return 0; /* never anything pending */
+}
+
+static struct hw_interrupt_type microdev_irq_type = {
+ "MicroDev-IRQ",
+ startup_microdev_irq,
+ shutdown_microdev_irq,
+ enable_microdev_irq,
+ disable_microdev_irq,
+ mask_and_ack_microdev,
+ end_microdev_irq
+};
+
+static void disable_microdev_irq(unsigned int irq)
+{
+ unsigned int flags;
+ unsigned int fpgaIrq;
+
+ if (irq >= NUM_EXTERNAL_IRQS) return;
+ if (!fpgaIrqTable[irq].mapped) return;
+
+ fpgaIrq = fpgaIrqTable[irq].fpgaIrq;
+
+ /* disable interrupts */
+ local_irq_save(flags);
+
+ /* disable interupts on the FPGA INTC register */
+ ctrl_outl(MICRODEV_FPGA_INTC_MASK(fpgaIrq), MICRODEV_FPGA_INTDSB_REG);
+
+ /* restore interrupts */
+ local_irq_restore(flags);
+}
+
+static void enable_microdev_irq(unsigned int irq)
+{
+ unsigned long priorityReg, priorities, pri;
+ unsigned int flags;
+ unsigned int fpgaIrq;
+
+
+ if (irq >= NUM_EXTERNAL_IRQS) return;
+ if (!fpgaIrqTable[irq].mapped) return;
+
+ pri = 15 - irq;
+
+ fpgaIrq = fpgaIrqTable[irq].fpgaIrq;
+ priorityReg = MICRODEV_FPGA_INTPRI_REG(fpgaIrq);
+
+ /* disable interrupts */
+ local_irq_save(flags);
+
+ /* set priority for the interrupt */
+ priorities = ctrl_inl(priorityReg);
+ priorities &= ~MICRODEV_FPGA_INTPRI_MASK(fpgaIrq);
+ priorities |= MICRODEV_FPGA_INTPRI_LEVEL(fpgaIrq, pri);
+ ctrl_outl(priorities, priorityReg);
+
+ /* enable interupts on the FPGA INTC register */
+ ctrl_outl(MICRODEV_FPGA_INTC_MASK(fpgaIrq), MICRODEV_FPGA_INTENB_REG);
+
+ /* restore interrupts */
+ local_irq_restore(flags);
+}
+
+ /* This functions sets the desired irq handler to be a MicroDev type */
+static void __init make_microdev_irq(unsigned int irq)
+{
+ disable_irq_nosync(irq);
+ irq_desc[irq].handler = &microdev_irq_type;
+ disable_microdev_irq(irq);
+}
+
+static void mask_and_ack_microdev(unsigned int irq)
+{
+ disable_microdev_irq(irq);
+}
+
+static void end_microdev_irq(unsigned int irq)
+{
+ if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+ {
+ enable_microdev_irq(irq);
+ }
+}
+
+extern void __init init_microdev_irq(void)
+{
+ int i;
+
+ /* disable interupts on the FPGA INTC register */
+ ctrl_outl(~0ul, MICRODEV_FPGA_INTDSB_REG);
+
+ for (i = 0; i < NUM_EXTERNAL_IRQS; i++)
+ {
+ make_microdev_irq(i);
+ }
+}
+
+extern void microdev_print_fpga_intc_status(void)
+{
+ volatile unsigned int * const intenb = (unsigned int*)MICRODEV_FPGA_INTENB_REG;
+ volatile unsigned int * const intdsb = (unsigned int*)MICRODEV_FPGA_INTDSB_REG;
+ volatile unsigned int * const intpria = (unsigned int*)MICRODEV_FPGA_INTPRI_REG(0);
+ volatile unsigned int * const intprib = (unsigned int*)MICRODEV_FPGA_INTPRI_REG(8);
+ volatile unsigned int * const intpric = (unsigned int*)MICRODEV_FPGA_INTPRI_REG(16);
+ volatile unsigned int * const intprid = (unsigned int*)MICRODEV_FPGA_INTPRI_REG(24);
+ volatile unsigned int * const intsrc = (unsigned int*)MICRODEV_FPGA_INTSRC_REG;
+ volatile unsigned int * const intreq = (unsigned int*)MICRODEV_FPGA_INTREQ_REG;
+
+ printk("-------------------------- microdev_print_fpga_intc_status() ------------------\n");
+ printk("FPGA_INTENB = 0x%08x\n", *intenb);
+ printk("FPGA_INTDSB = 0x%08x\n", *intdsb);
+ printk("FPGA_INTSRC = 0x%08x\n", *intsrc);
+ printk("FPGA_INTREQ = 0x%08x\n", *intreq);
+ printk("FPGA_INTPRI[3..0] = %08x:%08x:%08x:%08x\n", *intprid, *intpric, *intprib, *intpria);
+ printk("-------------------------------------------------------------------------------\n");
+}
+
+
diff --git a/arch/sh/boards/superh/microdev/led.c b/arch/sh/boards/superh/microdev/led.c
new file mode 100644
index 000000000000..52a98e69d3f0
--- /dev/null
+++ b/arch/sh/boards/superh/microdev/led.c
@@ -0,0 +1,102 @@
+/*
+ * linux/arch/sh/kernel/led_microdev.c
+ *
+ * Copyright (C) 2002 Stuart Menefy <stuart.menefy@st.com>
+ * Copyright (C) 2003 Richard Curnow (Richard.Curnow@superh.com)
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License. See linux/COPYING for more information.
+ *
+ */
+
+#include <linux/config.h>
+#include <asm/io.h>
+
+#define LED_REGISTER 0xa6104d20
+
+static void mach_led_d9(int value)
+{
+ unsigned long reg;
+ reg = ctrl_inl(LED_REGISTER);
+ reg &= ~1;
+ reg |= (value & 1);
+ ctrl_outl(reg, LED_REGISTER);
+ return;
+}
+
+static void mach_led_d10(int value)
+{
+ unsigned long reg;
+ reg = ctrl_inl(LED_REGISTER);
+ reg &= ~2;
+ reg |= ((value & 1) << 1);
+ ctrl_outl(reg, LED_REGISTER);
+ return;
+}
+
+
+#ifdef CONFIG_HEARTBEAT
+#include <linux/sched.h>
+
+static unsigned char banner_table[] = {
+ 0x11, 0x01, 0x11, 0x01, 0x11, 0x03,
+ 0x11, 0x01, 0x11, 0x01, 0x13, 0x03,
+ 0x11, 0x01, 0x13, 0x01, 0x13, 0x01, 0x11, 0x03,
+ 0x11, 0x03,
+ 0x11, 0x01, 0x13, 0x01, 0x11, 0x03,
+ 0x11, 0x01, 0x11, 0x01, 0x11, 0x01, 0x11, 0x07,
+ 0x13, 0x01, 0x13, 0x03,
+ 0x11, 0x01, 0x11, 0x03,
+ 0x13, 0x01, 0x11, 0x01, 0x13, 0x01, 0x11, 0x03,
+ 0x11, 0x01, 0x13, 0x01, 0x11, 0x03,
+ 0x13, 0x01, 0x13, 0x01, 0x13, 0x03,
+ 0x13, 0x01, 0x11, 0x01, 0x11, 0x03,
+ 0x11, 0x03,
+ 0x11, 0x01, 0x11, 0x01, 0x11, 0x01, 0x13, 0x07,
+ 0xff
+};
+
+static void banner(void)
+{
+ static int pos = 0;
+ static int count = 0;
+
+ if (count) {
+ count--;
+ } else {
+ int val = banner_table[pos];
+ if (val == 0xff) {
+ pos = 0;
+ val = banner_table[pos];
+ }
+ pos++;
+ mach_led_d10((val >> 4) & 1);
+ count = 10 * (val & 0xf);
+ }
+}
+
+/* From heartbeat_harp in the stboards directory */
+/* acts like an actual heart beat -- ie thump-thump-pause... */
+void microdev_heartbeat(void)
+{
+ static unsigned cnt = 0, period = 0, dist = 0;
+
+ if (cnt == 0 || cnt == dist)
+ mach_led_d9(1);
+ else if (cnt == 7 || cnt == dist+7)
+ mach_led_d9(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;
+ }
+
+ banner();
+}
+
+#endif
diff --git a/arch/sh/boards/superh/microdev/setup.c b/arch/sh/boards/superh/microdev/setup.c
new file mode 100644
index 000000000000..c18919941ec0
--- /dev/null
+++ b/arch/sh/boards/superh/microdev/setup.c
@@ -0,0 +1,278 @@
+/*
+ * arch/sh/boards/superh/microdev/setup.c
+ *
+ * Copyright (C) 2003 Sean McGoogan (Sean.McGoogan@superh.com)
+ * Copyright (C) 2003, 2004 SuperH, Inc.
+ * Copyright (C) 2004 Paul Mundt
+ *
+ * SuperH SH4-202 MicroDev board support.
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License. See linux/COPYING for more information.
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/ioport.h>
+#include <asm/io.h>
+#include <asm/mach/irq.h>
+#include <asm/mach/io.h>
+#include <asm/machvec.h>
+#include <asm/machvec_init.h>
+
+extern void microdev_heartbeat(void);
+
+/*
+ * The Machine Vector
+ */
+
+struct sh_machine_vector mv_sh4202_microdev __initmv = {
+ .mv_nr_irqs = 72, /* QQQ need to check this - use the MACRO */
+
+ .mv_inb = microdev_inb,
+ .mv_inw = microdev_inw,
+ .mv_inl = microdev_inl,
+ .mv_outb = microdev_outb,
+ .mv_outw = microdev_outw,
+ .mv_outl = microdev_outl,
+
+ .mv_inb_p = microdev_inb_p,
+ .mv_inw_p = microdev_inw_p,
+ .mv_inl_p = microdev_inl_p,
+ .mv_outb_p = microdev_outb_p,
+ .mv_outw_p = microdev_outw_p,
+ .mv_outl_p = microdev_outl_p,
+
+ .mv_insb = microdev_insb,
+ .mv_insw = microdev_insw,
+ .mv_insl = microdev_insl,
+ .mv_outsb = microdev_outsb,
+ .mv_outsw = microdev_outsw,
+ .mv_outsl = microdev_outsl,
+
+ .mv_isa_port2addr = microdev_isa_port2addr,
+
+ .mv_init_irq = init_microdev_irq,
+
+#ifdef CONFIG_HEARTBEAT
+ .mv_heartbeat = microdev_heartbeat,
+#endif
+};
+ALIAS_MV(sh4202_microdev)
+
+/****************************************************************************/
+
+
+ /*
+ * Setup for the SMSC FDC37C93xAPM
+ */
+#define SMSC_CONFIG_PORT_ADDR (0x3F0)
+#define SMSC_INDEX_PORT_ADDR SMSC_CONFIG_PORT_ADDR
+#define SMSC_DATA_PORT_ADDR (SMSC_INDEX_PORT_ADDR + 1)
+
+#define SMSC_ENTER_CONFIG_KEY 0x55
+#define SMSC_EXIT_CONFIG_KEY 0xaa
+
+#define SMCS_LOGICAL_DEV_INDEX 0x07 /* Logical Device Number */
+#define SMSC_DEVICE_ID_INDEX 0x20 /* Device ID */
+#define SMSC_DEVICE_REV_INDEX 0x21 /* Device Revision */
+#define SMSC_ACTIVATE_INDEX 0x30 /* Activate */
+#define SMSC_PRIMARY_BASE_INDEX 0x60 /* Primary Base Address */
+#define SMSC_SECONDARY_BASE_INDEX 0x62 /* Secondary Base Address */
+#define SMSC_PRIMARY_INT_INDEX 0x70 /* Primary Interrupt Select */
+#define SMSC_SECONDARY_INT_INDEX 0x72 /* Secondary Interrupt Select */
+#define SMSC_HDCS0_INDEX 0xf0 /* HDCS0 Address Decoder */
+#define SMSC_HDCS1_INDEX 0xf1 /* HDCS1 Address Decoder */
+
+#define SMSC_IDE1_DEVICE 1 /* IDE #1 logical device */
+#define SMSC_IDE2_DEVICE 2 /* IDE #2 logical device */
+#define SMSC_PARALLEL_DEVICE 3 /* Parallel Port logical device */
+#define SMSC_SERIAL1_DEVICE 4 /* Serial #1 logical device */
+#define SMSC_SERIAL2_DEVICE 5 /* Serial #2 logical device */
+#define SMSC_KEYBOARD_DEVICE 7 /* Keyboard logical device */
+#define SMSC_CONFIG_REGISTERS 8 /* Configuration Registers (Aux I/O) */
+
+#define SMSC_READ_INDEXED(index) ({ \
+ outb((index), SMSC_INDEX_PORT_ADDR); \
+ inb(SMSC_DATA_PORT_ADDR); })
+#define SMSC_WRITE_INDEXED(val, index) ({ \
+ outb((index), SMSC_INDEX_PORT_ADDR); \
+ outb((val), SMSC_DATA_PORT_ADDR); })
+
+#define IDE1_PRIMARY_BASE 0x01f0 /* Task File Registe base for IDE #1 */
+#define IDE1_SECONDARY_BASE 0x03f6 /* Miscellaneous AT registers for IDE #1 */
+#define IDE2_PRIMARY_BASE 0x0170 /* Task File Registe base for IDE #2 */
+#define IDE2_SECONDARY_BASE 0x0376 /* Miscellaneous AT registers for IDE #2 */
+
+#define SERIAL1_PRIMARY_BASE 0x03f8
+#define SERIAL2_PRIMARY_BASE 0x02f8
+
+#define MSB(x) ( (x) >> 8 )
+#define LSB(x) ( (x) & 0xff )
+
+ /* General-Purpose base address on CPU-board FPGA */
+#define MICRODEV_FPGA_GP_BASE 0xa6100000ul
+
+ /* assume a Keyboard Controller is present */
+int microdev_kbd_controller_present = 1;
+
+const char *get_system_type(void)
+{
+ return "SH4-202 MicroDev";
+}
+
+static struct resource smc91x_resources[] = {
+ [0] = {
+ .start = 0x300,
+ .end = 0x300 + 0x0001000 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = MICRODEV_LINUX_IRQ_ETHERNET,
+ .end = MICRODEV_LINUX_IRQ_ETHERNET,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device smc91x_device = {
+ .name = "smc91x",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(smc91x_resources),
+ .resource = smc91x_resources,
+};
+
+static int __init smc91x_setup(void)
+{
+ return platform_device_register(&smc91x_device);
+}
+
+__initcall(smc91x_setup);
+
+ /*
+ * Initialize the board
+ */
+void __init platform_setup(void)
+{
+ int * const fpgaRevisionRegister = (int*)(MICRODEV_FPGA_GP_BASE + 0x8ul);
+ const int fpgaRevision = *fpgaRevisionRegister;
+ int * const CacheControlRegister = (int*)CCR;
+
+ printk("SuperH %s board (FPGA rev: 0x%0x, CCR: 0x%0x)\n",
+ get_system_type(), fpgaRevision, *CacheControlRegister);
+}
+
+
+/****************************************************************************/
+
+
+ /*
+ * Setup for the SMSC FDC37C93xAPM
+ */
+static int __init smsc_superio_setup(void)
+{
+
+ unsigned char devid, devrev;
+
+ /* Initially the chip is in run state */
+ /* Put it into configuration state */
+ outb(SMSC_ENTER_CONFIG_KEY, SMSC_CONFIG_PORT_ADDR);
+
+ /* Read device ID info */
+ devid = SMSC_READ_INDEXED(SMSC_DEVICE_ID_INDEX);
+ devrev = SMSC_READ_INDEXED(SMSC_DEVICE_REV_INDEX);
+ if ( (devid==0x30) && (devrev==0x01) )
+ {
+ printk("SMSC FDC37C93xAPM SuperIO device detected\n");
+ }
+ else
+ { /* not the device identity we expected */
+ printk("Not detected a SMSC FDC37C93xAPM SuperIO device (devid=0x%02x, rev=0x%02x)\n",
+ devid, devrev);
+ /* inform the keyboard driver that we have no keyboard controller */
+ microdev_kbd_controller_present = 0;
+ /* little point in doing anything else in this functon */
+ return 0;
+ }
+
+ /* Select the keyboard device */
+ SMSC_WRITE_INDEXED(SMSC_KEYBOARD_DEVICE, SMCS_LOGICAL_DEV_INDEX);
+ /* enable it */
+ SMSC_WRITE_INDEXED(1, SMSC_ACTIVATE_INDEX);
+ /* enable the interrupts */
+ SMSC_WRITE_INDEXED(MICRODEV_FPGA_IRQ_KEYBOARD, SMSC_PRIMARY_INT_INDEX);
+ SMSC_WRITE_INDEXED(MICRODEV_FPGA_IRQ_MOUSE, SMSC_SECONDARY_INT_INDEX);
+
+ /* Select the Serial #1 device */
+ SMSC_WRITE_INDEXED(SMSC_SERIAL1_DEVICE, SMCS_LOGICAL_DEV_INDEX);
+ /* enable it */
+ SMSC_WRITE_INDEXED(1, SMSC_ACTIVATE_INDEX);
+ /* program with port addresses */
+ SMSC_WRITE_INDEXED(MSB(SERIAL1_PRIMARY_BASE), SMSC_PRIMARY_BASE_INDEX+0);
+ SMSC_WRITE_INDEXED(LSB(SERIAL1_PRIMARY_BASE), SMSC_PRIMARY_BASE_INDEX+1);
+ SMSC_WRITE_INDEXED(0x00, SMSC_HDCS0_INDEX);
+ /* enable the interrupts */
+ SMSC_WRITE_INDEXED(MICRODEV_FPGA_IRQ_SERIAL1, SMSC_PRIMARY_INT_INDEX);
+
+ /* Select the Serial #2 device */
+ SMSC_WRITE_INDEXED(SMSC_SERIAL2_DEVICE, SMCS_LOGICAL_DEV_INDEX);
+ /* enable it */
+ SMSC_WRITE_INDEXED(1, SMSC_ACTIVATE_INDEX);
+ /* program with port addresses */
+ SMSC_WRITE_INDEXED(MSB(SERIAL2_PRIMARY_BASE), SMSC_PRIMARY_BASE_INDEX+0);
+ SMSC_WRITE_INDEXED(LSB(SERIAL2_PRIMARY_BASE), SMSC_PRIMARY_BASE_INDEX+1);
+ SMSC_WRITE_INDEXED(0x00, SMSC_HDCS0_INDEX);
+ /* enable the interrupts */
+ SMSC_WRITE_INDEXED(MICRODEV_FPGA_IRQ_SERIAL2, SMSC_PRIMARY_INT_INDEX);
+
+ /* Select the IDE#1 device */
+ SMSC_WRITE_INDEXED(SMSC_IDE1_DEVICE, SMCS_LOGICAL_DEV_INDEX);
+ /* enable it */
+ SMSC_WRITE_INDEXED(1, SMSC_ACTIVATE_INDEX);
+ /* program with port addresses */
+ SMSC_WRITE_INDEXED(MSB(IDE1_PRIMARY_BASE), SMSC_PRIMARY_BASE_INDEX+0);
+ SMSC_WRITE_INDEXED(LSB(IDE1_PRIMARY_BASE), SMSC_PRIMARY_BASE_INDEX+1);
+ SMSC_WRITE_INDEXED(MSB(IDE1_SECONDARY_BASE), SMSC_SECONDARY_BASE_INDEX+0);
+ SMSC_WRITE_INDEXED(LSB(IDE1_SECONDARY_BASE), SMSC_SECONDARY_BASE_INDEX+1);
+ SMSC_WRITE_INDEXED(0x0c, SMSC_HDCS0_INDEX);
+ SMSC_WRITE_INDEXED(0x00, SMSC_HDCS1_INDEX);
+ /* select the interrupt */
+ SMSC_WRITE_INDEXED(MICRODEV_FPGA_IRQ_IDE1, SMSC_PRIMARY_INT_INDEX);
+
+ /* Select the IDE#2 device */
+ SMSC_WRITE_INDEXED(SMSC_IDE2_DEVICE, SMCS_LOGICAL_DEV_INDEX);
+ /* enable it */
+ SMSC_WRITE_INDEXED(1, SMSC_ACTIVATE_INDEX);
+ /* program with port addresses */
+ SMSC_WRITE_INDEXED(MSB(IDE2_PRIMARY_BASE), SMSC_PRIMARY_BASE_INDEX+0);
+ SMSC_WRITE_INDEXED(LSB(IDE2_PRIMARY_BASE), SMSC_PRIMARY_BASE_INDEX+1);
+ SMSC_WRITE_INDEXED(MSB(IDE2_SECONDARY_BASE), SMSC_SECONDARY_BASE_INDEX+0);
+ SMSC_WRITE_INDEXED(LSB(IDE2_SECONDARY_BASE), SMSC_SECONDARY_BASE_INDEX+1);
+ /* select the interrupt */
+ SMSC_WRITE_INDEXED(MICRODEV_FPGA_IRQ_IDE2, SMSC_PRIMARY_INT_INDEX);
+
+ /* Select the configuration registers */
+ SMSC_WRITE_INDEXED(SMSC_CONFIG_REGISTERS, SMCS_LOGICAL_DEV_INDEX);
+ /* enable the appropriate GPIO pins for IDE functionality:
+ * bit[0] In/Out 1==input; 0==output
+ * bit[1] Polarity 1==invert; 0==no invert
+ * bit[2] Int Enb #1 1==Enable Combined IRQ #1; 0==disable
+ * bit[3:4] Function Select 00==original; 01==Alternate Function #1
+ */
+ SMSC_WRITE_INDEXED(0x00, 0xc2); /* GP42 = nIDE1_OE */
+ SMSC_WRITE_INDEXED(0x01, 0xc5); /* GP45 = IDE1_IRQ */
+ SMSC_WRITE_INDEXED(0x00, 0xc6); /* GP46 = nIOROP */
+ SMSC_WRITE_INDEXED(0x00, 0xc7); /* GP47 = nIOWOP */
+ SMSC_WRITE_INDEXED(0x08, 0xe8); /* GP20 = nIDE2_OE */
+
+ /* Exit the configuraton state */
+ outb(SMSC_EXIT_CONFIG_KEY, SMSC_CONFIG_PORT_ADDR);
+
+ return 0;
+}
+
+
+/* This is grotty, but, because kernel is always referenced on the link line
+ * before any devices, this is safe.
+ */
+__initcall(smsc_superio_setup);
diff --git a/arch/sh/boards/unknown/Makefile b/arch/sh/boards/unknown/Makefile
new file mode 100644
index 000000000000..cffc21031e71
--- /dev/null
+++ b/arch/sh/boards/unknown/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for unknown SH boards
+#
+
+obj-y := mach.o io.o setup.o
+
diff --git a/arch/sh/boards/unknown/io.c b/arch/sh/boards/unknown/io.c
new file mode 100644
index 000000000000..8f3f17267bd9
--- /dev/null
+++ b/arch/sh/boards/unknown/io.c
@@ -0,0 +1,46 @@
+/*
+ * linux/arch/sh/kernel/io_unknown.c
+ *
+ * Copyright (C) 2000 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.
+ *
+ * I/O routine for unknown hardware.
+ */
+
+static unsigned int unknown_handler(void)
+{
+ return 0;
+}
+
+#define UNKNOWN_ALIAS(fn) \
+ void unknown_##fn(void) __attribute__ ((alias ("unknown_handler")));
+
+UNKNOWN_ALIAS(inb)
+UNKNOWN_ALIAS(inw)
+UNKNOWN_ALIAS(inl)
+UNKNOWN_ALIAS(outb)
+UNKNOWN_ALIAS(outw)
+UNKNOWN_ALIAS(outl)
+UNKNOWN_ALIAS(inb_p)
+UNKNOWN_ALIAS(inw_p)
+UNKNOWN_ALIAS(inl_p)
+UNKNOWN_ALIAS(outb_p)
+UNKNOWN_ALIAS(outw_p)
+UNKNOWN_ALIAS(outl_p)
+UNKNOWN_ALIAS(insb)
+UNKNOWN_ALIAS(insw)
+UNKNOWN_ALIAS(insl)
+UNKNOWN_ALIAS(outsb)
+UNKNOWN_ALIAS(outsw)
+UNKNOWN_ALIAS(outsl)
+UNKNOWN_ALIAS(readb)
+UNKNOWN_ALIAS(readw)
+UNKNOWN_ALIAS(readl)
+UNKNOWN_ALIAS(writeb)
+UNKNOWN_ALIAS(writew)
+UNKNOWN_ALIAS(writel)
+UNKNOWN_ALIAS(isa_port2addr)
+UNKNOWN_ALIAS(ioremap)
+UNKNOWN_ALIAS(iounmap)
diff --git a/arch/sh/boards/unknown/mach.c b/arch/sh/boards/unknown/mach.c
new file mode 100644
index 000000000000..ad0bcc60a640
--- /dev/null
+++ b/arch/sh/boards/unknown/mach.c
@@ -0,0 +1,67 @@
+/*
+ * linux/arch/sh/kernel/mach_unknown.c
+ *
+ * Copyright (C) 2000 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 specific code for an unknown machine (internal peripherials only)
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+
+#include <asm/machvec.h>
+#include <asm/machvec_init.h>
+
+#include <asm/io_unknown.h>
+
+#include <asm/rtc.h>
+/*
+ * The Machine Vector
+ */
+
+struct sh_machine_vector mv_unknown __initmv = {
+#if defined(CONFIG_CPU_SH4)
+ .mv_nr_irqs = 48,
+#elif defined(CONFIG_CPU_SUBTYPE_SH7708)
+ .mv_nr_irqs = 32,
+#elif defined(CONFIG_CPU_SUBTYPE_SH7709)
+ .mv_nr_irqs = 61,
+#endif
+
+ .mv_inb = unknown_inb,
+ .mv_inw = unknown_inw,
+ .mv_inl = unknown_inl,
+ .mv_outb = unknown_outb,
+ .mv_outw = unknown_outw,
+ .mv_outl = unknown_outl,
+
+ .mv_inb_p = unknown_inb_p,
+ .mv_inw_p = unknown_inw_p,
+ .mv_inl_p = unknown_inl_p,
+ .mv_outb_p = unknown_outb_p,
+ .mv_outw_p = unknown_outw_p,
+ .mv_outl_p = unknown_outl_p,
+
+ .mv_insb = unknown_insb,
+ .mv_insw = unknown_insw,
+ .mv_insl = unknown_insl,
+ .mv_outsb = unknown_outsb,
+ .mv_outsw = unknown_outsw,
+ .mv_outsl = unknown_outsl,
+
+ .mv_readb = unknown_readb,
+ .mv_readw = unknown_readw,
+ .mv_readl = unknown_readl,
+ .mv_writeb = unknown_writeb,
+ .mv_writew = unknown_writew,
+ .mv_writel = unknown_writel,
+
+ .mv_ioremap = unknown_ioremap,
+ .mv_iounmap = unknown_iounmap,
+
+ .mv_isa_port2addr = unknown_isa_port2addr,
+};
+ALIAS_MV(unknown)
diff --git a/arch/sh/boards/unknown/setup.c b/arch/sh/boards/unknown/setup.c
new file mode 100644
index 000000000000..7d772a6f8865
--- /dev/null
+++ b/arch/sh/boards/unknown/setup.c
@@ -0,0 +1,23 @@
+/*
+ * linux/arch/sh/boards/unknown/setup.c
+ *
+ * Copyright (C) 2002 Paul Mundt
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License. See linux/COPYING for more information.
+ *
+ * Setup code for an unknown machine (internal peripherials only)
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+
+const char *get_system_type(void)
+{
+ return "Unknown";
+}
+
+void __init platform_setup(void)
+{
+}
+
diff --git a/arch/sh/boot/Makefile b/arch/sh/boot/Makefile
new file mode 100644
index 000000000000..60797b31089c
--- /dev/null
+++ b/arch/sh/boot/Makefile
@@ -0,0 +1,20 @@
+#
+# arch/sh/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) 1999 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 $@
+
diff --git a/arch/sh/boot/compressed/Makefile b/arch/sh/boot/compressed/Makefile
new file mode 100644
index 000000000000..75a6876bf6c6
--- /dev/null
+++ b/arch/sh/boot/compressed/Makefile
@@ -0,0 +1,41 @@
+#
+# linux/arch/sh/boot/compressed/Makefile
+#
+# create a compressed vmlinux image from the original vmlinux
+#
+
+targets := vmlinux vmlinux.bin vmlinux.bin.gz head.o misc.o piggy.o
+EXTRA_AFLAGS := -traditional
+
+OBJECTS = $(obj)/head.o $(obj)/misc.o
+
+ifdef CONFIG_SH_STANDARD_BIOS
+OBJECTS += $(obj)/../../kernel/sh_bios.o
+endif
+
+#
+# IMAGE_OFFSET is the load offset of the compression loader
+# Assign dummy values if these 2 variables are not defined,
+# in order to suppress error message.
+#
+CONFIG_MEMORY_START ?= 0x0c000000
+CONFIG_BOOT_LINK_OFFSET ?= 0x00800000
+IMAGE_OFFSET := $(shell printf "0x%8x" $$[0x80000000+$(CONFIG_MEMORY_START)+$(CONFIG_BOOT_LINK_OFFSET)])
+
+LDFLAGS_vmlinux := -Ttext $(IMAGE_OFFSET) -e startup -T $(obj)/../../kernel/vmlinux.lds
+
+$(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-sh-linux -T
+OBJCOPYFLAGS += -R .empty_zero_page
+
+$(obj)/piggy.o: $(obj)/vmlinux.scr $(obj)/vmlinux.bin.gz FORCE
+ $(call if_changed,ld)
diff --git a/arch/sh/boot/compressed/head.S b/arch/sh/boot/compressed/head.S
new file mode 100644
index 000000000000..88db04d325fb
--- /dev/null
+++ b/arch/sh/boot/compressed/head.S
@@ -0,0 +1,120 @@
+/*
+ * linux/arch/sh/boot/compressed/head.S
+ *
+ * Copyright (C) 1999 Stuart Menefy
+ * Copyright (C) 2003 SUGIOKA Toshinobu
+ */
+
+.text
+
+#include <linux/config.h>
+#include <linux/linkage.h>
+
+ .global startup
+startup:
+ /* Load initial status register */
+ mov.l init_sr, r1
+ ldc r1, sr
+
+ /* Move myself to proper location if necessary */
+ mova 1f, r0
+ mov.l 1f, r2
+ cmp/eq r2, r0
+ bt clear_bss
+ sub r0, r2
+ mov.l bss_start_addr, r0
+ mov #0xe0, r1
+ and r1, r0 ! align cache line
+ mov.l text_start_addr, r3
+ mov r0, r1
+ sub r2, r1
+3:
+ mov.l @r1, r4
+ mov.l @(4,r1), r5
+ mov.l @(8,r1), r6
+ mov.l @(12,r1), r7
+ mov.l @(16,r1), r8
+ mov.l @(20,r1), r9
+ mov.l @(24,r1), r10
+ mov.l @(28,r1), r11
+ mov.l r4, @r0
+ mov.l r5, @(4,r0)
+ mov.l r6, @(8,r0)
+ mov.l r7, @(12,r0)
+ mov.l r8, @(16,r0)
+ mov.l r9, @(20,r0)
+ mov.l r10, @(24,r0)
+ mov.l r11, @(28,r0)
+#ifdef CONFIG_CPU_SH4
+ ocbwb @r0
+#endif
+ cmp/hi r3, r0
+ add #-32, r0
+ bt/s 3b
+ add #-32, r1
+ mov.l 2f, r0
+ jmp @r0
+ nop
+
+ .align 2
+1: .long 1b
+2: .long clear_bss
+text_start_addr:
+ .long startup
+
+ /* Clear BSS */
+clear_bss:
+ mov.l end_addr, r1
+ mov.l bss_start_addr, r2
+ mov #0, r0
+l1:
+ mov.l r0, @-r1
+ cmp/eq r1,r2
+ bf l1
+
+ /* Set the initial pointer. */
+ mov.l init_stack_addr, r0
+ mov.l @r0, r15
+
+ /* Decompress the kernel */
+ mov.l decompress_kernel_addr, r0
+ jsr @r0
+ nop
+
+ /* Jump to the start of the decompressed kernel */
+ mov.l kernel_start_addr, r0
+ jmp @r0
+ nop
+
+ .align 2
+bss_start_addr:
+ .long __bss_start
+end_addr:
+ .long _end
+init_sr:
+ .long 0x400000F0 /* Privileged mode, Bank=0, Block=0, IMASK=0xF */
+init_stack_addr:
+ .long stack_start
+decompress_kernel_addr:
+ .long decompress_kernel
+kernel_start_addr:
+ .long _text+0x1000
+
+ .align 9
+fake_headers_as_bzImage:
+ .word 0
+ .ascii "HdrS" ! header signature
+ .word 0x0202 ! header version number (>= 0x0105)
+ ! or else old loadlin-1.5 will fail)
+ .word 0 ! default_switch
+ .word 0 ! SETUPSEG
+ .word 0x1000
+ .word 0 ! pointing to kernel version string
+ .byte 0 ! = 0, old one (LILO, Loadlin,
+ ! 0xTV: T=0 for LILO
+ ! V = version
+ .byte 1 ! Load flags bzImage=1
+ .word 0x8000 ! size to move, when setup is not
+ .long 0x100000 ! 0x100000 = default for big kernel
+ .long 0 ! address of loaded ramdisk image
+ .long 0 # its size in bytes
diff --git a/arch/sh/boot/compressed/install.sh b/arch/sh/boot/compressed/install.sh
new file mode 100644
index 000000000000..90589f0fec12
--- /dev/null
+++ b/arch/sh/boot/compressed/install.sh
@@ -0,0 +1,56 @@
+#!/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
diff --git a/arch/sh/boot/compressed/misc.c b/arch/sh/boot/compressed/misc.c
new file mode 100644
index 000000000000..211e9110074f
--- /dev/null
+++ b/arch/sh/boot/compressed/misc.c
@@ -0,0 +1,240 @@
+/*
+ * arch/sh/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 SH by Stuart Menefy, Aug 1999
+ *
+ * Modified to use standard LinuxSH BIOS by Greg Banks 7Jul2000
+ */
+
+#include <linux/config.h>
+#include <asm/uaccess.h>
+#ifdef CONFIG_SH_STANDARD_BIOS
+#include <asm/sh_bios.h>
+#endif
+
+/*
+ * 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 **);
+
+int 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");
+ if (free_mem_ptr == 0) error("Memory error");
+
+ 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("Out of memory");
+
+ 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;
+}
+
+#ifdef CONFIG_SH_STANDARD_BIOS
+size_t strlen(const char *s)
+{
+ int i = 0;
+
+ while (*s++)
+ i++;
+ return i;
+}
+
+int puts(const char *s)
+{
+ int len = strlen(s);
+ sh_bios_console_write(s, len);
+ return len;
+}
+#else
+int puts(const char *s)
+{
+ /* This should be updated to use the sh-sci routines */
+ return 0;
+}
+#endif
+
+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");
+ }
+
+ 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;
+}
+
+static void error(char *x)
+{
+ puts("\n\n");
+ puts(x);
+ puts("\n\n -- System halted");
+
+ while(1); /* Halt */
+}
+
+#define STACK_SIZE (4096)
+long user_stack [STACK_SIZE];
+long* stack_start = &user_stack[STACK_SIZE];
+
+void decompress_kernel(void)
+{
+ output_data = 0;
+ output_ptr = (unsigned long)&_text+0x20001000;
+ free_mem_ptr = (unsigned long)&_end;
+ free_mem_end_ptr = free_mem_ptr + HEAP_SIZE;
+
+ makecrc();
+ puts("Uncompressing Linux... ");
+ gunzip();
+ puts("Ok, booting the kernel.\n");
+}
diff --git a/arch/sh/boot/compressed/vmlinux.scr b/arch/sh/boot/compressed/vmlinux.scr
new file mode 100644
index 000000000000..1ed9d791f863
--- /dev/null
+++ b/arch/sh/boot/compressed/vmlinux.scr
@@ -0,0 +1,9 @@
+SECTIONS
+{
+ .data : {
+ input_len = .;
+ LONG(input_data_end - input_data) input_data = .;
+ *(.data)
+ input_data_end = .;
+ }
+}
diff --git a/arch/sh/cchips/Kconfig b/arch/sh/cchips/Kconfig
new file mode 100644
index 000000000000..155d139884c3
--- /dev/null
+++ b/arch/sh/cchips/Kconfig
@@ -0,0 +1,96 @@
+menu "Companion Chips"
+
+config VOYAGERGX
+ bool "VoyagerGX chip support"
+ depends on SH_RTS7751R2D
+ help
+ Selecting this option will support Silicon Motion, Inc. SM501.
+ Designed to complement needs for the embedded industry, it
+ provides video and 2D capability. To reduce system cost a
+ wide variety of include I/O is supported, including analog RGB
+ and digital LCD Panel interface, 8-bit parallel interface, USB,
+ UART, IrDA, Zoom Video, AC97 or I2S, SSP, PWM, and I2C. There
+ are additional GPIO bits that can be used to interface to
+ external as well.
+
+# A board must have defined HD6446X_SERIES in order to see these
+config HD6446X_SERIES
+ bool "HD6446x support"
+ default n
+
+choice
+ prompt "HD6446x options"
+ depends on HD6446X_SERIES
+ default HD64461
+
+config HD64461
+ bool "Hitachi HD64461 companion chip support"
+ depends on CPU_SUBTYPE_SH7709
+ ---help---
+ The Hitachi HD64461 provides an interface for
+ the SH7709 CPU, supporting a LCD controller,
+ CRT color controller, IrDA up to 4 Mbps, and a
+ PCMCIA controller supporting 2 slots.
+
+ More information is available at
+ <http://semiconductor.hitachi.com/windowsce/superh/sld013.htm>.
+
+ Say Y if you want support for the HD64461.
+ Otherwise, say N.
+
+config HD64465
+ bool "Hitachi HD64465 companion chip support"
+ depends on CPU_SUBTYPE_SH7750
+ ---help---
+ The Hitachi HD64465 provides an interface for
+ the SH7750 CPU, supporting a LCD controller,
+ CRT color controller, IrDA, USB, PCMCIA,
+ keyboard controller, and a printer interface.
+
+ More information is available at
+ <http://global.hitachi.com/New/cnews/E/1998/981019B.html>.
+
+ Say Y if you want support for the HD64465.
+ Otherwise, say N.
+
+endchoice
+
+# These will also be split into the Kconfig's below
+config HD64461_IRQ
+ int "HD64461 IRQ"
+ depends on HD64461
+ default "36"
+ help
+ The default setting of the HD64461 IRQ is 36.
+
+ Do not change this unless you know what you are doing.
+
+config HD64461_ENABLER
+ bool "HD64461 PCMCIA enabler"
+ depends on HD64461
+ help
+ Say Y here if you want to enable PCMCIA support
+ via the HD64461 companion chip.
+ Otherwise, say N.
+
+
+config HD64465_IOBASE
+ hex "HD64465 start address"
+ depends on HD64465
+ default "0xb0000000"
+ help
+ The default setting of the HD64465 IO base address is 0xb0000000.
+
+ Do not change this unless you know what you are doing.
+
+config HD64465_IRQ
+ int "HD64465 IRQ"
+ depends on HD64465
+ default "5"
+ help
+ The default setting of the HD64465 IRQ is 5.
+
+ Do not change this unless you know what you are doing.
+
+endmenu
+
diff --git a/arch/sh/cchips/hd6446x/hd64461/Makefile b/arch/sh/cchips/hd6446x/hd64461/Makefile
new file mode 100644
index 000000000000..bff4b92e388c
--- /dev/null
+++ b/arch/sh/cchips/hd6446x/hd64461/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for the HD64461
+#
+
+obj-y := setup.o io.o
+
diff --git a/arch/sh/cchips/hd6446x/hd64461/io.c b/arch/sh/cchips/hd6446x/hd64461/io.c
new file mode 100644
index 000000000000..4c062d6b7a97
--- /dev/null
+++ b/arch/sh/cchips/hd6446x/hd64461/io.c
@@ -0,0 +1,157 @@
+/*
+ * $Id: io.c,v 1.6 2004/03/16 00:07:50 lethal Exp $
+ * Copyright (C) 2000 YAEGASHI Takeshi
+ * Typical I/O routines for HD64461 system.
+ */
+
+#include <linux/config.h>
+#include <asm/io.h>
+#include <asm/hd64461/hd64461.h>
+
+#define MEM_BASE (CONFIG_HD64461_IOBASE - HD64461_STBCR)
+
+static __inline__ unsigned long PORT2ADDR(unsigned long port)
+{
+ /* 16550A: HD64461 internal */
+ if (0x3f8<=port && port<=0x3ff)
+ return CONFIG_HD64461_IOBASE + 0x8000 + ((port-0x3f8)<<1);
+ if (0x2f8<=port && port<=0x2ff)
+ return CONFIG_HD64461_IOBASE + 0x7000 + ((port-0x2f8)<<1);
+
+#ifdef CONFIG_HD64461_ENABLER
+ /* NE2000: HD64461 PCMCIA channel 0 (I/O) */
+ if (0x300<=port && port<=0x31f)
+ return 0xba000000 + port;
+
+ /* ide0: HD64461 PCMCIA channel 1 (memory) */
+ /* On HP690, CF in slot 1 is configured as a memory card
+ device. See CF+ and CompactFlash Specification for the
+ detail of CF's memory mapped addressing. */
+ if (0x1f0<=port && port<=0x1f7) return 0xb5000000 + port;
+ if (port == 0x3f6) return 0xb50001fe;
+ if (port == 0x3f7) return 0xb50001ff;
+
+ /* ide1 */
+ if (0x170<=port && port<=0x177) return 0xba000000 + port;
+ if (port == 0x376) return 0xba000376;
+ if (port == 0x377) return 0xba000377;
+#endif
+
+ /* ??? */
+ if (port < 0xf000) return 0xa0000000 + port;
+ /* PCMCIA channel 0, I/O (0xba000000) */
+ if (port < 0x10000) return 0xba000000 + port - 0xf000;
+
+ /* HD64461 internal devices (0xb0000000) */
+ if (port < 0x20000) return CONFIG_HD64461_IOBASE + port - 0x10000;
+
+ /* PCMCIA channel 0, I/O (0xba000000) */
+ if (port < 0x30000) return 0xba000000 + port - 0x20000;
+
+ /* PCMCIA channel 1, memory (0xb5000000) */
+ if (port < 0x40000) return 0xb5000000 + port - 0x30000;
+
+ /* Whole physical address space (0xa0000000) */
+ return 0xa0000000 + (port & 0x1fffffff);
+}
+
+static inline void delay(void)
+{
+ ctrl_inw(0xa0000000);
+}
+
+unsigned char hd64461_inb(unsigned long port)
+{
+ return *(volatile unsigned char*)PORT2ADDR(port);
+}
+
+unsigned char hd64461_inb_p(unsigned long port)
+{
+ unsigned long v = *(volatile unsigned char*)PORT2ADDR(port);
+ delay();
+ return v;
+}
+
+unsigned short hd64461_inw(unsigned long port)
+{
+ return *(volatile unsigned short*)PORT2ADDR(port);
+}
+
+unsigned int hd64461_inl(unsigned long port)
+{
+ return *(volatile unsigned long*)PORT2ADDR(port);
+}
+
+void hd64461_outb(unsigned char b, unsigned long port)
+{
+ *(volatile unsigned char*)PORT2ADDR(port) = b;
+}
+
+void hd64461_outb_p(unsigned char b, unsigned long port)
+{
+ *(volatile unsigned char*)PORT2ADDR(port) = b;
+ delay();
+}
+
+void hd64461_outw(unsigned short b, unsigned long port)
+{
+ *(volatile unsigned short*)PORT2ADDR(port) = b;
+}
+
+void hd64461_outl(unsigned int b, unsigned long port)
+{
+ *(volatile unsigned long*)PORT2ADDR(port) = b;
+}
+
+void hd64461_insb(unsigned long port, void *buffer, unsigned long count)
+{
+ volatile unsigned char* addr=(volatile unsigned char*)PORT2ADDR(port);
+ unsigned char *buf=buffer;
+ while(count--) *buf++=*addr;
+}
+
+void hd64461_insw(unsigned long port, void *buffer, unsigned long count)
+{
+ volatile unsigned short* addr=(volatile unsigned short*)PORT2ADDR(port);
+ unsigned short *buf=buffer;
+ while(count--) *buf++=*addr;
+}
+
+void hd64461_insl(unsigned long port, void *buffer, unsigned long count)
+{
+ volatile unsigned long* addr=(volatile unsigned long*)PORT2ADDR(port);
+ unsigned long *buf=buffer;
+ while(count--) *buf++=*addr;
+}
+
+void hd64461_outsb(unsigned long port, const void *buffer, unsigned long count)
+{
+ volatile unsigned char* addr=(volatile unsigned char*)PORT2ADDR(port);
+ const unsigned char *buf=buffer;
+ while(count--) *addr=*buf++;
+}
+
+void hd64461_outsw(unsigned long port, const void *buffer, unsigned long count)
+{
+ volatile unsigned short* addr=(volatile unsigned short*)PORT2ADDR(port);
+ const unsigned short *buf=buffer;
+ while(count--) *addr=*buf++;
+}
+
+void hd64461_outsl(unsigned long port, const void *buffer, unsigned long count)
+{
+ volatile unsigned long* addr=(volatile unsigned long*)PORT2ADDR(port);
+ const unsigned long *buf=buffer;
+ while(count--) *addr=*buf++;
+}
+
+unsigned short hd64461_readw(unsigned long addr)
+{
+ return *(volatile unsigned short*)(MEM_BASE+addr);
+}
+
+void hd64461_writew(unsigned short b, unsigned long addr)
+{
+ *(volatile unsigned short*)(MEM_BASE+addr) = b;
+}
+
diff --git a/arch/sh/cchips/hd6446x/hd64461/setup.c b/arch/sh/cchips/hd6446x/hd64461/setup.c
new file mode 100644
index 000000000000..f014b9bf6922
--- /dev/null
+++ b/arch/sh/cchips/hd6446x/hd64461/setup.c
@@ -0,0 +1,171 @@
+/*
+ * $Id: setup.c,v 1.5 2004/03/16 00:07:50 lethal Exp $
+ * Copyright (C) 2000 YAEGASHI Takeshi
+ * Hitachi HD64461 companion chip support
+ */
+
+#include <linux/config.h>
+#include <linux/sched.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/param.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+
+#include <asm/hd64461/hd64461.h>
+
+static void disable_hd64461_irq(unsigned int irq)
+{
+ unsigned long flags;
+ unsigned short nimr;
+ unsigned short mask = 1 << (irq - HD64461_IRQBASE);
+
+ local_irq_save(flags);
+ nimr = inw(HD64461_NIMR);
+ nimr |= mask;
+ outw(nimr, HD64461_NIMR);
+ local_irq_restore(flags);
+}
+
+static void enable_hd64461_irq(unsigned int irq)
+{
+ unsigned long flags;
+ unsigned short nimr;
+ unsigned short mask = 1 << (irq - HD64461_IRQBASE);
+
+ local_irq_save(flags);
+ nimr = inw(HD64461_NIMR);
+ nimr &= ~mask;
+ outw(nimr, HD64461_NIMR);
+ local_irq_restore(flags);
+}
+
+static void mask_and_ack_hd64461(unsigned int irq)
+{
+ disable_hd64461_irq(irq);
+#ifdef CONFIG_HD64461_ENABLER
+ if (irq == HD64461_IRQBASE + 13)
+ outb(0x00, HD64461_PCC1CSCR);
+#endif
+}
+
+static void end_hd64461_irq(unsigned int irq)
+{
+ if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+ enable_hd64461_irq(irq);
+}
+
+static unsigned int startup_hd64461_irq(unsigned int irq)
+{
+ enable_hd64461_irq(irq);
+ return 0;
+}
+
+static void shutdown_hd64461_irq(unsigned int irq)
+{
+ disable_hd64461_irq(irq);
+}
+
+static struct hw_interrupt_type hd64461_irq_type = {
+ .typename = "HD64461-IRQ",
+ .startup = startup_hd64461_irq,
+ .shutdown = shutdown_hd64461_irq,
+ .enable = enable_hd64461_irq,
+ .disable = disable_hd64461_irq,
+ .ack = mask_and_ack_hd64461,
+ .end = end_hd64461_irq,
+};
+
+static irqreturn_t hd64461_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ printk(KERN_INFO
+ "HD64461: spurious interrupt, nirr: 0x%x nimr: 0x%x\n",
+ inw(HD64461_NIRR), inw(HD64461_NIMR));
+
+ return IRQ_NONE;
+}
+
+static struct {
+ int (*func) (int, void *);
+ void *dev;
+} hd64461_demux[HD64461_IRQ_NUM];
+
+void hd64461_register_irq_demux(int irq,
+ int (*demux) (int irq, void *dev), void *dev)
+{
+ hd64461_demux[irq - HD64461_IRQBASE].func = demux;
+ hd64461_demux[irq - HD64461_IRQBASE].dev = dev;
+}
+
+EXPORT_SYMBOL(hd64461_register_irq_demux);
+
+void hd64461_unregister_irq_demux(int irq)
+{
+ hd64461_demux[irq - HD64461_IRQBASE].func = 0;
+}
+
+EXPORT_SYMBOL(hd64461_unregister_irq_demux);
+
+int hd64461_irq_demux(int irq)
+{
+ if (irq == CONFIG_HD64461_IRQ) {
+ unsigned short bit;
+ unsigned short nirr = inw(HD64461_NIRR);
+ unsigned short nimr = inw(HD64461_NIMR);
+ int i;
+
+ nirr &= ~nimr;
+ for (bit = 1, i = 0; i < 16; bit <<= 1, i++)
+ if (nirr & bit)
+ break;
+ if (i == 16)
+ irq = CONFIG_HD64461_IRQ;
+ else {
+ irq = HD64461_IRQBASE + i;
+ if (hd64461_demux[i].func != 0) {
+ irq = hd64461_demux[i].func(irq, hd64461_demux[i].dev);
+ }
+ }
+ }
+ return __irq_demux(irq);
+}
+
+static struct irqaction irq0 = { hd64461_interrupt, SA_INTERRUPT, CPU_MASK_NONE, "HD64461", NULL, NULL };
+
+int __init setup_hd64461(void)
+{
+ int i;
+
+ if (!MACH_HD64461)
+ return 0;
+
+ printk(KERN_INFO
+ "HD64461 configured at 0x%x on irq %d(mapped into %d to %d)\n",
+ CONFIG_HD64461_IOBASE, CONFIG_HD64461_IRQ, HD64461_IRQBASE,
+ HD64461_IRQBASE + 15);
+
+#if defined(CONFIG_CPU_SUBTYPE_SH7709) /* Should be at processor specific part.. */
+ outw(0x2240, INTC_ICR1);
+#endif
+ outw(0xffff, HD64461_NIMR);
+
+ for (i = HD64461_IRQBASE; i < HD64461_IRQBASE + 16; i++) {
+ irq_desc[i].handler = &hd64461_irq_type;
+ }
+
+ setup_irq(CONFIG_HD64461_IRQ, &irq0);
+
+#ifdef CONFIG_HD64461_ENABLER
+ printk(KERN_INFO "HD64461: enabling PCMCIA devices\n");
+ outb(0x4c, HD64461_PCC1CSCIER);
+ outb(0x00, HD64461_PCC1CSCR);
+#endif
+
+ return 0;
+}
+
+module_init(setup_hd64461);
diff --git a/arch/sh/cchips/hd6446x/hd64465/Makefile b/arch/sh/cchips/hd6446x/hd64465/Makefile
new file mode 100644
index 000000000000..f66edcb52c5b
--- /dev/null
+++ b/arch/sh/cchips/hd6446x/hd64465/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for the HD64465
+#
+
+obj-y := setup.o io.o gpio.o
+
diff --git a/arch/sh/cchips/hd6446x/hd64465/gpio.c b/arch/sh/cchips/hd6446x/hd64465/gpio.c
new file mode 100644
index 000000000000..9785fdef868e
--- /dev/null
+++ b/arch/sh/cchips/hd6446x/hd64465/gpio.c
@@ -0,0 +1,196 @@
+/*
+ * $Id: gpio.c,v 1.4 2003/05/19 22:24:18 lethal Exp $
+ * by Greg Banks <gbanks@pocketpenguins.com>
+ * (c) 2000 PocketPenguins Inc
+ *
+ * GPIO pin support for HD64465 companion chip.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/ioport.h>
+#include <asm/io.h>
+#include <asm/hd64465/gpio.h>
+
+#define _PORTOF(portpin) (((portpin)>>3)&0x7)
+#define _PINOF(portpin) ((portpin)&0x7)
+
+/* Register addresses parametrised on port */
+#define GPIO_CR(port) (HD64465_REG_GPACR+((port)<<1))
+#define GPIO_DR(port) (HD64465_REG_GPADR+((port)<<1))
+#define GPIO_ICR(port) (HD64465_REG_GPAICR+((port)<<1))
+#define GPIO_ISR(port) (HD64465_REG_GPAISR+((port)<<1))
+
+#define GPIO_NPORTS 5
+
+#define MODNAME "hd64465_gpio"
+
+EXPORT_SYMBOL(hd64465_gpio_configure);
+EXPORT_SYMBOL(hd64465_gpio_get_pin);
+EXPORT_SYMBOL(hd64465_gpio_get_port);
+EXPORT_SYMBOL(hd64465_gpio_register_irq);
+EXPORT_SYMBOL(hd64465_gpio_set_pin);
+EXPORT_SYMBOL(hd64465_gpio_set_port);
+EXPORT_SYMBOL(hd64465_gpio_unregister_irq);
+
+/* TODO: each port should be protected with a spinlock */
+
+
+void hd64465_gpio_configure(int portpin, int direction)
+{
+ unsigned short cr;
+ unsigned int shift = (_PINOF(portpin)<<1);
+
+ cr = inw(GPIO_CR(_PORTOF(portpin)));
+ cr &= ~(3<<shift);
+ cr |= direction<<shift;
+ outw(cr, GPIO_CR(_PORTOF(portpin)));
+}
+
+void hd64465_gpio_set_pin(int portpin, unsigned int value)
+{
+ unsigned short d;
+ unsigned short mask = 1<<(_PINOF(portpin));
+
+ d = inw(GPIO_DR(_PORTOF(portpin)));
+ if (value)
+ d |= mask;
+ else
+ d &= ~mask;
+ outw(d, GPIO_DR(_PORTOF(portpin)));
+}
+
+unsigned int hd64465_gpio_get_pin(int portpin)
+{
+ return inw(GPIO_DR(_PORTOF(portpin))) & (1<<(_PINOF(portpin)));
+}
+
+/* TODO: for cleaner atomicity semantics, add a mask to this routine */
+
+void hd64465_gpio_set_port(int port, unsigned int value)
+{
+ outw(value, GPIO_DR(port));
+}
+
+unsigned int hd64465_gpio_get_port(int port)
+{
+ return inw(GPIO_DR(port));
+}
+
+
+static struct {
+ void (*func)(int portpin, void *dev);
+ void *dev;
+} handlers[GPIO_NPORTS * 8];
+
+static irqreturn_t hd64465_gpio_interrupt(int irq, void *dev, struct pt_regs *regs)
+{
+ unsigned short port, pin, isr, mask, portpin;
+
+ for (port=0 ; port<GPIO_NPORTS ; port++) {
+ isr = inw(GPIO_ISR(port));
+
+ for (pin=0 ; pin<8 ; pin++) {
+ mask = 1<<pin;
+ if (isr & mask) {
+ portpin = (port<<3)|pin;
+ if (handlers[portpin].func != 0)
+ handlers[portpin].func(portpin, handlers[portpin].dev);
+ else
+ printk(KERN_NOTICE "unexpected GPIO interrupt, pin %c%d\n",
+ port+'A', (int)pin);
+ }
+ }
+
+ /* Write 1s back to ISR to clear it? That's what the manual says.. */
+ outw(isr, GPIO_ISR(port));
+ }
+
+ return IRQ_HANDLED;
+}
+
+void hd64465_gpio_register_irq(int portpin, int mode,
+ void (*handler)(int portpin, void *dev), void *dev)
+{
+ unsigned long flags;
+ unsigned short icr, mask;
+
+ if (handler == 0)
+ return;
+
+ local_irq_save(flags);
+
+ handlers[portpin].func = handler;
+ handlers[portpin].dev = dev;
+
+ /*
+ * Configure Interrupt Control Register
+ */
+ icr = inw(GPIO_ICR(_PORTOF(portpin)));
+ mask = (1<<_PINOF(portpin));
+
+ /* unmask interrupt */
+ icr &= ~mask;
+
+ /* set TS bit */
+ mask <<= 8;
+ icr &= ~mask;
+ if (mode == HD64465_GPIO_RISING)
+ icr |= mask;
+
+ outw(icr, GPIO_ICR(_PORTOF(portpin)));
+
+ local_irq_restore(flags);
+}
+
+void hd64465_gpio_unregister_irq(int portpin)
+{
+ unsigned long flags;
+ unsigned short icr;
+
+ local_irq_save(flags);
+
+ /*
+ * Configure Interrupt Control Register
+ */
+ icr = inw(GPIO_ICR(_PORTOF(portpin)));
+ icr |= (1<<_PINOF(portpin)); /* mask interrupt */
+ outw(icr, GPIO_ICR(_PORTOF(portpin)));
+
+ handlers[portpin].func = 0;
+ handlers[portpin].dev = 0;
+
+ local_irq_restore(flags);
+}
+
+static int __init hd64465_gpio_init(void)
+{
+ if (!request_region(HD64465_REG_GPACR, 0x1000, MODNAME))
+ return -EBUSY;
+ if (request_irq(HD64465_IRQ_GPIO, hd64465_gpio_interrupt,
+ SA_INTERRUPT, MODNAME, 0))
+ goto out_irqfailed;
+
+ printk("HD64465 GPIO layer on irq %d\n", HD64465_IRQ_GPIO);
+
+ return 0;
+
+out_irqfailed:
+ release_region(HD64465_REG_GPACR, 0x1000);
+
+ return -EINVAL;
+}
+
+static void __exit hd64465_gpio_exit(void)
+{
+ release_region(HD64465_REG_GPACR, 0x1000);
+ free_irq(HD64465_IRQ_GPIO, 0);
+}
+
+module_init(hd64465_gpio_init);
+module_exit(hd64465_gpio_exit);
+
+MODULE_LICENSE("GPL");
+
diff --git a/arch/sh/cchips/hd6446x/hd64465/io.c b/arch/sh/cchips/hd6446x/hd64465/io.c
new file mode 100644
index 000000000000..99ac709c550e
--- /dev/null
+++ b/arch/sh/cchips/hd6446x/hd64465/io.c
@@ -0,0 +1,216 @@
+/*
+ * $Id: io.c,v 1.4 2003/08/03 03:05:10 lethal Exp $
+ * by Greg Banks <gbanks@pocketpenguins.com>
+ * (c) 2000 PocketPenguins Inc
+ *
+ * Derived from io_hd64461.c, which bore the message:
+ * Copyright (C) 2000 YAEGASHI Takeshi
+ *
+ * Typical I/O routines for HD64465 system.
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <asm/io.h>
+#include <asm/hd64465/hd64465.h>
+
+
+#define HD64465_DEBUG 0
+
+#if HD64465_DEBUG
+#define DPRINTK(args...) printk(args)
+#define DIPRINTK(n, args...) if (hd64465_io_debug>(n)) printk(args)
+#else
+#define DPRINTK(args...)
+#define DIPRINTK(n, args...)
+#endif
+
+
+
+/* This is a hack suitable only for debugging IO port problems */
+int hd64465_io_debug;
+EXPORT_SYMBOL(hd64465_io_debug);
+
+/* Low iomap maps port 0-1K to addresses in 8byte chunks */
+#define HD64465_IOMAP_LO_THRESH 0x400
+#define HD64465_IOMAP_LO_SHIFT 3
+#define HD64465_IOMAP_LO_MASK ((1<<HD64465_IOMAP_LO_SHIFT)-1)
+#define HD64465_IOMAP_LO_NMAP (HD64465_IOMAP_LO_THRESH>>HD64465_IOMAP_LO_SHIFT)
+static unsigned long hd64465_iomap_lo[HD64465_IOMAP_LO_NMAP];
+static unsigned char hd64465_iomap_lo_shift[HD64465_IOMAP_LO_NMAP];
+
+/* High iomap maps port 1K-64K to addresses in 1K chunks */
+#define HD64465_IOMAP_HI_THRESH 0x10000
+#define HD64465_IOMAP_HI_SHIFT 10
+#define HD64465_IOMAP_HI_MASK ((1<<HD64465_IOMAP_HI_SHIFT)-1)
+#define HD64465_IOMAP_HI_NMAP (HD64465_IOMAP_HI_THRESH>>HD64465_IOMAP_HI_SHIFT)
+static unsigned long hd64465_iomap_hi[HD64465_IOMAP_HI_NMAP];
+static unsigned char hd64465_iomap_hi_shift[HD64465_IOMAP_HI_NMAP];
+
+#ifndef MAX
+#define MAX(a,b) ((a)>(b)?(a):(b))
+#endif
+
+#define PORT2ADDR(x) (sh_mv.mv_isa_port2addr(x))
+
+void hd64465_port_map(unsigned short baseport, unsigned int nports,
+ unsigned long addr, unsigned char shift)
+{
+ unsigned int port, endport = baseport + nports;
+
+ DPRINTK("hd64465_port_map(base=0x%04hx, n=0x%04hx, addr=0x%08lx,endport=0x%04x)\n",
+ baseport, nports, addr,endport);
+
+ for (port = baseport ;
+ port < endport && port < HD64465_IOMAP_LO_THRESH ;
+ port += (1<<HD64465_IOMAP_LO_SHIFT)) {
+ DPRINTK(" maplo[0x%x] = 0x%08lx\n", port, addr);
+ hd64465_iomap_lo[port>>HD64465_IOMAP_LO_SHIFT] = addr;
+ hd64465_iomap_lo_shift[port>>HD64465_IOMAP_LO_SHIFT] = shift;
+ addr += (1<<(HD64465_IOMAP_LO_SHIFT));
+ }
+
+ for (port = MAX(baseport, HD64465_IOMAP_LO_THRESH) ;
+ port < endport && port < HD64465_IOMAP_HI_THRESH ;
+ port += (1<<HD64465_IOMAP_HI_SHIFT)) {
+ DPRINTK(" maphi[0x%x] = 0x%08lx\n", port, addr);
+ hd64465_iomap_hi[port>>HD64465_IOMAP_HI_SHIFT] = addr;
+ hd64465_iomap_hi_shift[port>>HD64465_IOMAP_HI_SHIFT] = shift;
+ addr += (1<<(HD64465_IOMAP_HI_SHIFT));
+ }
+}
+EXPORT_SYMBOL(hd64465_port_map);
+
+void hd64465_port_unmap(unsigned short baseport, unsigned int nports)
+{
+ unsigned int port, endport = baseport + nports;
+
+ DPRINTK("hd64465_port_unmap(base=0x%04hx, n=0x%04hx)\n",
+ baseport, nports);
+
+ for (port = baseport ;
+ port < endport && port < HD64465_IOMAP_LO_THRESH ;
+ port += (1<<HD64465_IOMAP_LO_SHIFT)) {
+ hd64465_iomap_lo[port>>HD64465_IOMAP_LO_SHIFT] = 0;
+ }
+
+ for (port = MAX(baseport, HD64465_IOMAP_LO_THRESH) ;
+ port < endport && port < HD64465_IOMAP_HI_THRESH ;
+ port += (1<<HD64465_IOMAP_HI_SHIFT)) {
+ hd64465_iomap_hi[port>>HD64465_IOMAP_HI_SHIFT] = 0;
+ }
+}
+EXPORT_SYMBOL(hd64465_port_unmap);
+
+unsigned long hd64465_isa_port2addr(unsigned long port)
+{
+ unsigned long addr = 0;
+ unsigned char shift;
+
+ /* handle remapping of low IO ports */
+ if (port < HD64465_IOMAP_LO_THRESH) {
+ addr = hd64465_iomap_lo[port >> HD64465_IOMAP_LO_SHIFT];
+ shift = hd64465_iomap_lo_shift[port >> HD64465_IOMAP_LO_SHIFT];
+ if (addr != 0)
+ addr += (port & HD64465_IOMAP_LO_MASK) << shift;
+ else
+ printk(KERN_NOTICE "io_hd64465: access to un-mapped port %lx\n", port);
+ } else if (port < HD64465_IOMAP_HI_THRESH) {
+ addr = hd64465_iomap_hi[port >> HD64465_IOMAP_HI_SHIFT];
+ shift = hd64465_iomap_hi_shift[port >> HD64465_IOMAP_HI_SHIFT];
+ if (addr != 0)
+ addr += (port & HD64465_IOMAP_HI_MASK) << shift;
+ else
+ printk(KERN_NOTICE "io_hd64465: access to un-mapped port %lx\n", port);
+ }
+
+ /* HD64465 internal devices (0xb0000000) */
+ else if (port < 0x20000)
+ addr = CONFIG_HD64465_IOBASE + port - 0x10000;
+
+ /* Whole physical address space (0xa0000000) */
+ else
+ addr = P2SEGADDR(port);
+
+ DIPRINTK(2, "PORT2ADDR(0x%08lx) = 0x%08lx\n", port, addr);
+
+ return addr;
+}
+
+static inline void delay(void)
+{
+ ctrl_inw(0xa0000000);
+}
+
+unsigned char hd64465_inb(unsigned long port)
+{
+ unsigned long addr = PORT2ADDR(port);
+ unsigned long b = (addr == 0 ? 0 : *(volatile unsigned char*)addr);
+
+ DIPRINTK(0, "inb(%08lx) = %02x\n", addr, (unsigned)b);
+ return b;
+}
+
+unsigned char hd64465_inb_p(unsigned long port)
+{
+ unsigned long v;
+ unsigned long addr = PORT2ADDR(port);
+
+ v = (addr == 0 ? 0 : *(volatile unsigned char*)addr);
+ delay();
+ DIPRINTK(0, "inb_p(%08lx) = %02x\n", addr, (unsigned)v);
+ return v;
+}
+
+unsigned short hd64465_inw(unsigned long port)
+{
+ unsigned long addr = PORT2ADDR(port);
+ unsigned long b = (addr == 0 ? 0 : *(volatile unsigned short*)addr);
+ DIPRINTK(0, "inw(%08lx) = %04lx\n", addr, b);
+ return b;
+}
+
+unsigned int hd64465_inl(unsigned long port)
+{
+ unsigned long addr = PORT2ADDR(port);
+ unsigned int b = (addr == 0 ? 0 : *(volatile unsigned long*)addr);
+ DIPRINTK(0, "inl(%08lx) = %08x\n", addr, b);
+ return b;
+}
+
+void hd64465_outb(unsigned char b, unsigned long port)
+{
+ unsigned long addr = PORT2ADDR(port);
+
+ DIPRINTK(0, "outb(%02x, %08lx)\n", (unsigned)b, addr);
+ if (addr != 0)
+ *(volatile unsigned char*)addr = b;
+}
+
+void hd64465_outb_p(unsigned char b, unsigned long port)
+{
+ unsigned long addr = PORT2ADDR(port);
+
+ DIPRINTK(0, "outb_p(%02x, %08lx)\n", (unsigned)b, addr);
+ if (addr != 0)
+ *(volatile unsigned char*)addr = b;
+ delay();
+}
+
+void hd64465_outw(unsigned short b, unsigned long port)
+{
+ unsigned long addr = PORT2ADDR(port);
+ DIPRINTK(0, "outw(%04x, %08lx)\n", (unsigned)b, addr);
+ if (addr != 0)
+ *(volatile unsigned short*)addr = b;
+}
+
+void hd64465_outl(unsigned int b, unsigned long port)
+{
+ unsigned long addr = PORT2ADDR(port);
+ DIPRINTK(0, "outl(%08x, %08lx)\n", b, addr);
+ if (addr != 0)
+ *(volatile unsigned long*)addr = b;
+}
+
diff --git a/arch/sh/cchips/hd6446x/hd64465/setup.c b/arch/sh/cchips/hd6446x/hd64465/setup.c
new file mode 100644
index 000000000000..68e4c4e4283d
--- /dev/null
+++ b/arch/sh/cchips/hd6446x/hd64465/setup.c
@@ -0,0 +1,202 @@
+/*
+ * $Id: setup.c,v 1.4 2003/08/03 03:05:10 lethal Exp $
+ *
+ * Setup and IRQ handling code for the HD64465 companion chip.
+ * by Greg Banks <gbanks@pocketpenguins.com>
+ * Copyright (c) 2000 PocketPenguins Inc
+ *
+ * Derived from setup_hd64461.c which bore the message:
+ * Copyright (C) 2000 YAEGASHI Takeshi
+ */
+
+#include <linux/config.h>
+#include <linux/sched.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/param.h>
+#include <linux/ioport.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+
+#include <asm/hd64465/hd64465.h>
+
+static void disable_hd64465_irq(unsigned int irq)
+{
+ unsigned long flags;
+ unsigned short nimr;
+ unsigned short mask = 1 << (irq - HD64465_IRQ_BASE);
+
+ pr_debug("disable_hd64465_irq(%d): mask=%x\n", irq, mask);
+ local_irq_save(flags);
+ nimr = inw(HD64465_REG_NIMR);
+ nimr |= mask;
+ outw(nimr, HD64465_REG_NIMR);
+ local_irq_restore(flags);
+}
+
+
+static void enable_hd64465_irq(unsigned int irq)
+{
+ unsigned long flags;
+ unsigned short nimr;
+ unsigned short mask = 1 << (irq - HD64465_IRQ_BASE);
+
+ pr_debug("enable_hd64465_irq(%d): mask=%x\n", irq, mask);
+ local_irq_save(flags);
+ nimr = inw(HD64465_REG_NIMR);
+ nimr &= ~mask;
+ outw(nimr, HD64465_REG_NIMR);
+ local_irq_restore(flags);
+}
+
+
+static void mask_and_ack_hd64465(unsigned int irq)
+{
+ disable_hd64465_irq(irq);
+}
+
+
+static void end_hd64465_irq(unsigned int irq)
+{
+ if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+ enable_hd64465_irq(irq);
+}
+
+
+static unsigned int startup_hd64465_irq(unsigned int irq)
+{
+ enable_hd64465_irq(irq);
+ return 0;
+}
+
+
+static void shutdown_hd64465_irq(unsigned int irq)
+{
+ disable_hd64465_irq(irq);
+}
+
+
+static struct hw_interrupt_type hd64465_irq_type = {
+ .typename = "HD64465-IRQ",
+ .startup = startup_hd64465_irq,
+ .shutdown = shutdown_hd64465_irq,
+ .enable = enable_hd64465_irq,
+ .disable = disable_hd64465_irq,
+ .ack = mask_and_ack_hd64465,
+ .end = end_hd64465_irq,
+};
+
+
+static irqreturn_t hd64465_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ printk(KERN_INFO
+ "HD64465: spurious interrupt, nirr: 0x%x nimr: 0x%x\n",
+ inw(HD64465_REG_NIRR), inw(HD64465_REG_NIMR));
+
+ return IRQ_NONE;
+}
+
+
+/*====================================================*/
+
+/*
+ * Support for a secondary IRQ demux step. This is necessary
+ * because the HD64465 presents a very thin interface to the
+ * PCMCIA bus; a lot of features (such as remapping interrupts)
+ * normally done in hardware by other PCMCIA host bridges is
+ * instead done in software.
+ */
+static struct
+{
+ int (*func)(int, void *);
+ void *dev;
+} hd64465_demux[HD64465_IRQ_NUM];
+
+void hd64465_register_irq_demux(int irq,
+ int (*demux)(int irq, void *dev), void *dev)
+{
+ hd64465_demux[irq - HD64465_IRQ_BASE].func = demux;
+ hd64465_demux[irq - HD64465_IRQ_BASE].dev = dev;
+}
+EXPORT_SYMBOL(hd64465_register_irq_demux);
+
+void hd64465_unregister_irq_demux(int irq)
+{
+ hd64465_demux[irq - HD64465_IRQ_BASE].func = 0;
+}
+EXPORT_SYMBOL(hd64465_unregister_irq_demux);
+
+
+
+int hd64465_irq_demux(int irq)
+{
+ if (irq == CONFIG_HD64465_IRQ) {
+ unsigned short i, bit;
+ unsigned short nirr = inw(HD64465_REG_NIRR);
+ unsigned short nimr = inw(HD64465_REG_NIMR);
+
+ pr_debug("hd64465_irq_demux, nirr=%04x, nimr=%04x\n", nirr, nimr);
+ nirr &= ~nimr;
+ for (bit = 1, i = 0 ; i < HD64465_IRQ_NUM ; bit <<= 1, i++)
+ if (nirr & bit)
+ break;
+
+ if (i < HD64465_IRQ_NUM) {
+ irq = HD64465_IRQ_BASE + i;
+ if (hd64465_demux[i].func != 0)
+ irq = hd64465_demux[i].func(irq, hd64465_demux[i].dev);
+ }
+ }
+ return irq;
+}
+
+static struct irqaction irq0 = { hd64465_interrupt, SA_INTERRUPT, CPU_MASK_NONE, "HD64465", NULL, NULL};
+
+
+static int __init setup_hd64465(void)
+{
+ int i;
+ unsigned short rev;
+ unsigned short smscr;
+
+ if (!MACH_HD64465)
+ return 0;
+
+ printk(KERN_INFO "HD64465 configured at 0x%x on irq %d(mapped into %d to %d)\n",
+ CONFIG_HD64465_IOBASE,
+ CONFIG_HD64465_IRQ,
+ HD64465_IRQ_BASE,
+ HD64465_IRQ_BASE+HD64465_IRQ_NUM-1);
+
+ if (inw(HD64465_REG_SDID) != HD64465_SDID) {
+ printk(KERN_ERR "HD64465 device ID not found, check base address\n");
+ }
+
+ rev = inw(HD64465_REG_SRR);
+ printk(KERN_INFO "HD64465 hardware revision %d.%d\n", (rev >> 8) & 0xff, rev & 0xff);
+
+ outw(0xffff, HD64465_REG_NIMR); /* mask all interrupts */
+
+ for (i = 0; i < HD64465_IRQ_NUM ; i++) {
+ irq_desc[HD64465_IRQ_BASE + i].handler = &hd64465_irq_type;
+ }
+
+ setup_irq(CONFIG_HD64465_IRQ, &irq0);
+
+#ifdef CONFIG_SERIAL
+ /* wake up the UART from STANDBY at this point */
+ smscr = inw(HD64465_REG_SMSCR);
+ outw(smscr & (~HD64465_SMSCR_UARTST), HD64465_REG_SMSCR);
+
+ /* remap IO ports for first ISA serial port to HD64465 UART */
+ hd64465_port_map(0x3f8, 8, CONFIG_HD64465_IOBASE + 0x8000, 1);
+#endif
+
+ return 0;
+}
+
+module_init(setup_hd64465);
diff --git a/arch/sh/cchips/voyagergx/Makefile b/arch/sh/cchips/voyagergx/Makefile
new file mode 100644
index 000000000000..085de72fd327
--- /dev/null
+++ b/arch/sh/cchips/voyagergx/Makefile
@@ -0,0 +1,8 @@
+#
+# Makefile for VoyagerGX
+#
+
+obj-y := irq.o setup.o
+
+obj-$(CONFIG_USB_OHCI_HCD) += consistent.o
+
diff --git a/arch/sh/cchips/voyagergx/consistent.c b/arch/sh/cchips/voyagergx/consistent.c
new file mode 100644
index 000000000000..5b92585a38d2
--- /dev/null
+++ b/arch/sh/cchips/voyagergx/consistent.c
@@ -0,0 +1,126 @@
+/*
+ * arch/sh/cchips/voyagergx/consistent.c
+ *
+ * Copyright (C) 2004 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/mm.h>
+#include <linux/dma-mapping.h>
+#include <linux/slab.h>
+#include <linux/list.h>
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <asm/io.h>
+#include <asm/bus-sh.h>
+
+struct voya_alloc_entry {
+ struct list_head list;
+ unsigned long ofs;
+ unsigned long len;
+};
+
+static DEFINE_SPINLOCK(voya_list_lock);
+static LIST_HEAD(voya_alloc_list);
+
+#define OHCI_SRAM_START 0xb0000000
+#define OHCI_HCCA_SIZE 0x100
+#define OHCI_SRAM_SIZE 0x10000
+
+void *voyagergx_consistent_alloc(struct device *dev, size_t size,
+ dma_addr_t *handle, int flag)
+{
+ struct list_head *list = &voya_alloc_list;
+ struct voya_alloc_entry *entry;
+ struct sh_dev *shdev = to_sh_dev(dev);
+ unsigned long start, end;
+ unsigned long flags;
+
+ /*
+ * The SM501 contains an integrated 8051 with its own SRAM.
+ * Devices within the cchip can all hook into the 8051 SRAM.
+ * We presently use this for the OHCI.
+ *
+ * Everything else goes through consistent_alloc().
+ */
+ if (!dev || dev->bus != &sh_bus_types[SH_BUS_VIRT] ||
+ (dev->bus == &sh_bus_types[SH_BUS_VIRT] &&
+ shdev->dev_id != SH_DEV_ID_USB_OHCI))
+ return NULL;
+
+ start = OHCI_SRAM_START + OHCI_HCCA_SIZE;
+
+ entry = kmalloc(sizeof(struct voya_alloc_entry), GFP_ATOMIC);
+ if (!entry)
+ return ERR_PTR(-ENOMEM);
+
+ entry->len = (size + 15) & ~15;
+
+ /*
+ * The basis for this allocator is dwmw2's malloc.. the
+ * Matrox allocator :-)
+ */
+ spin_lock_irqsave(&voya_list_lock, flags);
+ list_for_each(list, &voya_alloc_list) {
+ struct voya_alloc_entry *p;
+
+ p = list_entry(list, struct voya_alloc_entry, list);
+
+ if (p->ofs - start >= size)
+ goto out;
+
+ start = p->ofs + p->len;
+ }
+
+ end = start + (OHCI_SRAM_SIZE - OHCI_HCCA_SIZE);
+ list = &voya_alloc_list;
+
+ if (end - start >= size) {
+out:
+ entry->ofs = start;
+ list_add_tail(&entry->list, list);
+ spin_unlock_irqrestore(&voya_list_lock, flags);
+
+ *handle = start;
+ return (void *)start;
+ }
+
+ kfree(entry);
+ spin_unlock_irqrestore(&voya_list_lock, flags);
+
+ return ERR_PTR(-EINVAL);
+}
+
+int voyagergx_consistent_free(struct device *dev, size_t size,
+ void *vaddr, dma_addr_t handle)
+{
+ struct voya_alloc_entry *entry;
+ struct sh_dev *shdev = to_sh_dev(dev);
+ unsigned long flags;
+
+ if (!dev || dev->bus != &sh_bus_types[SH_BUS_VIRT] ||
+ (dev->bus == &sh_bus_types[SH_BUS_VIRT] &&
+ shdev->dev_id != SH_DEV_ID_USB_OHCI))
+ return -EINVAL;
+
+ spin_lock_irqsave(&voya_list_lock, flags);
+ list_for_each_entry(entry, &voya_alloc_list, list) {
+ if (entry->ofs != handle)
+ continue;
+
+ list_del(&entry->list);
+ kfree(entry);
+
+ break;
+ }
+ spin_unlock_irqrestore(&voya_list_lock, flags);
+
+ return 0;
+}
+
+EXPORT_SYMBOL(voyagergx_consistent_alloc);
+EXPORT_SYMBOL(voyagergx_consistent_free);
+
diff --git a/arch/sh/cchips/voyagergx/irq.c b/arch/sh/cchips/voyagergx/irq.c
new file mode 100644
index 000000000000..3079234cb65b
--- /dev/null
+++ b/arch/sh/cchips/voyagergx/irq.c
@@ -0,0 +1,194 @@
+/* -------------------------------------------------------------------- */
+/* setup_voyagergx.c: */
+/* -------------------------------------------------------------------- */
+/* This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ Copyright 2003 (c) Lineo uSolutions,Inc.
+*/
+/* -------------------------------------------------------------------- */
+
+#undef DEBUG
+
+#include <linux/config.h>
+#include <linux/sched.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/param.h>
+#include <linux/ioport.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/rts7751r2d/rts7751r2d.h>
+#include <asm/rts7751r2d/voyagergx_reg.h>
+
+static void disable_voyagergx_irq(unsigned int irq)
+{
+ unsigned long flags, val;
+ unsigned long mask = 1 << (irq - VOYAGER_IRQ_BASE);
+
+ pr_debug("disable_voyagergx_irq(%d): mask=%x\n", irq, mask);
+ local_irq_save(flags);
+ val = inl(VOYAGER_INT_MASK);
+ val &= ~mask;
+ outl(val, VOYAGER_INT_MASK);
+ local_irq_restore(flags);
+}
+
+
+static void enable_voyagergx_irq(unsigned int irq)
+{
+ unsigned long flags, val;
+ unsigned long mask = 1 << (irq - VOYAGER_IRQ_BASE);
+
+ pr_debug("disable_voyagergx_irq(%d): mask=%x\n", irq, mask);
+ local_irq_save(flags);
+ val = inl(VOYAGER_INT_MASK);
+ val |= mask;
+ outl(val, VOYAGER_INT_MASK);
+ local_irq_restore(flags);
+}
+
+
+static void mask_and_ack_voyagergx(unsigned int irq)
+{
+ disable_voyagergx_irq(irq);
+}
+
+static void end_voyagergx_irq(unsigned int irq)
+{
+ if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+ enable_voyagergx_irq(irq);
+}
+
+static unsigned int startup_voyagergx_irq(unsigned int irq)
+{
+ enable_voyagergx_irq(irq);
+ return 0;
+}
+
+static void shutdown_voyagergx_irq(unsigned int irq)
+{
+ disable_voyagergx_irq(irq);
+}
+
+static struct hw_interrupt_type voyagergx_irq_type = {
+ "VOYAGERGX-IRQ",
+ startup_voyagergx_irq,
+ shutdown_voyagergx_irq,
+ enable_voyagergx_irq,
+ disable_voyagergx_irq,
+ mask_and_ack_voyagergx,
+ end_voyagergx_irq,
+};
+
+static irqreturn_t voyagergx_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ printk(KERN_INFO
+ "VoyagerGX: spurious interrupt, status: 0x%x\n",
+ inl(INT_STATUS));
+ return IRQ_HANDLED;
+}
+
+
+/*====================================================*/
+
+static struct {
+ int (*func)(int, void *);
+ void *dev;
+} voyagergx_demux[VOYAGER_IRQ_NUM];
+
+void voyagergx_register_irq_demux(int irq,
+ int (*demux)(int irq, void *dev), void *dev)
+{
+ voyagergx_demux[irq - VOYAGER_IRQ_BASE].func = demux;
+ voyagergx_demux[irq - VOYAGER_IRQ_BASE].dev = dev;
+}
+
+void voyagergx_unregister_irq_demux(int irq)
+{
+ voyagergx_demux[irq - VOYAGER_IRQ_BASE].func = 0;
+}
+
+int voyagergx_irq_demux(int irq)
+{
+
+ if (irq == IRQ_VOYAGER ) {
+ unsigned long i = 0, bit __attribute__ ((unused));
+ unsigned long val = inl(INT_STATUS);
+#if 1
+ if ( val & ( 1 << 1 )){
+ i = 1;
+ } else if ( val & ( 1 << 2 )){
+ i = 2;
+ } else if ( val & ( 1 << 6 )){
+ i = 6;
+ } else if( val & ( 1 << 10 )){
+ i = 10;
+ } else if( val & ( 1 << 11 )){
+ i = 11;
+ } else if( val & ( 1 << 12 )){
+ i = 12;
+ } else if( val & ( 1 << 17 )){
+ i = 17;
+ } else {
+ printk("Unexpected IRQ irq = %d status = 0x%08lx\n", irq, val);
+ }
+ pr_debug("voyagergx_irq_demux %d \n", i);
+#else
+ for (bit = 1, i = 0 ; i < VOYAGER_IRQ_NUM ; bit <<= 1, i++)
+ if (val & bit)
+ break;
+#endif
+ if (i < VOYAGER_IRQ_NUM) {
+ irq = VOYAGER_IRQ_BASE + i;
+ if (voyagergx_demux[i].func != 0)
+ irq = voyagergx_demux[i].func(irq, voyagergx_demux[i].dev);
+ }
+ }
+ return irq;
+}
+
+static struct irqaction irq0 = { voyagergx_interrupt, SA_INTERRUPT, 0, "VOYAGERGX", NULL, NULL};
+
+void __init setup_voyagergx_irq(void)
+{
+ int i, flag;
+
+ printk(KERN_INFO "VoyagerGX configured at 0x%x on irq %d(mapped into %d to %d)\n",
+ VOYAGER_BASE,
+ IRQ_VOYAGER,
+ VOYAGER_IRQ_BASE,
+ VOYAGER_IRQ_BASE + VOYAGER_IRQ_NUM - 1);
+
+ for (i=0; i<VOYAGER_IRQ_NUM; i++) {
+ flag = 0;
+ switch (VOYAGER_IRQ_BASE + i) {
+ case VOYAGER_USBH_IRQ:
+ case VOYAGER_8051_IRQ:
+ case VOYAGER_UART0_IRQ:
+ case VOYAGER_UART1_IRQ:
+ case VOYAGER_AC97_IRQ:
+ flag = 1;
+ }
+ if (flag == 1)
+ irq_desc[VOYAGER_IRQ_BASE + i].handler = &voyagergx_irq_type;
+ }
+
+ setup_irq(IRQ_VOYAGER, &irq0);
+}
+
diff --git a/arch/sh/cchips/voyagergx/setup.c b/arch/sh/cchips/voyagergx/setup.c
new file mode 100644
index 000000000000..139ca88ac9e6
--- /dev/null
+++ b/arch/sh/cchips/voyagergx/setup.c
@@ -0,0 +1,37 @@
+/*
+ * arch/sh/cchips/voyagergx/setup.c
+ *
+ * Setup routines for VoyagerGX cchip.
+ *
+ * Copyright (C) 2003 Lineo uSolutions, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+#include <linux/init.h>
+#include <linux/module.h>
+#include <asm/io.h>
+#include <asm/rts7751r2d/voyagergx_reg.h>
+
+static int __init setup_voyagergx(void)
+{
+ unsigned long val;
+
+ val = inl(DRAM_CTRL);
+ val |= (DRAM_CTRL_CPU_COLUMN_SIZE_256 |
+ DRAM_CTRL_CPU_ACTIVE_PRECHARGE |
+ DRAM_CTRL_CPU_RESET |
+ DRAM_CTRL_REFRESH_COMMAND |
+ DRAM_CTRL_BLOCK_WRITE_TIME |
+ DRAM_CTRL_BLOCK_WRITE_PRECHARGE |
+ DRAM_CTRL_ACTIVE_PRECHARGE |
+ DRAM_CTRL_RESET |
+ DRAM_CTRL_REMAIN_ACTIVE);
+ outl(val, DRAM_CTRL);
+
+ return 0;
+}
+
+module_init(setup_voyagergx);
diff --git a/arch/sh/configs/adx_defconfig b/arch/sh/configs/adx_defconfig
new file mode 100644
index 000000000000..353bfdc457d4
--- /dev/null
+++ b/arch/sh/configs/adx_defconfig
@@ -0,0 +1,539 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11-sh
+# Wed Mar 2 15:09:26 2005
+#
+CONFIG_SUPERH=y
+CONFIG_UID16=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_SWAP=y
+# CONFIG_SYSVIPC is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_SYSCTL is not set
+# CONFIG_AUDIT is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_HOTPLUG is not set
+# CONFIG_IKCONFIG is not set
+# CONFIG_EMBEDDED is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+
+#
+# Loadable module support
+#
+# CONFIG_MODULES is not set
+
+#
+# System type
+#
+# CONFIG_SH_SOLUTION_ENGINE is not set
+# CONFIG_SH_7751_SOLUTION_ENGINE is not set
+# CONFIG_SH_7300_SOLUTION_ENGINE is not set
+# CONFIG_SH_73180_SOLUTION_ENGINE is not set
+# CONFIG_SH_7751_SYSTEMH is not set
+# CONFIG_SH_STB1_HARP is not set
+# CONFIG_SH_STB1_OVERDRIVE is not set
+# CONFIG_SH_HP620 is not set
+# CONFIG_SH_HP680 is not set
+# CONFIG_SH_HP690 is not set
+# CONFIG_SH_CQREEK is not set
+# CONFIG_SH_DMIDA is not set
+# CONFIG_SH_EC3104 is not set
+# CONFIG_SH_SATURN is not set
+# CONFIG_SH_DREAMCAST is not set
+# CONFIG_SH_CAT68701 is not set
+# CONFIG_SH_BIGSUR is not set
+# CONFIG_SH_SH2000 is not set
+CONFIG_SH_ADX=y
+# CONFIG_SH_MPC1211 is not set
+# CONFIG_SH_SH03 is not set
+# CONFIG_SH_SECUREEDGE5410 is not set
+# CONFIG_SH_HS7751RVOIP is not set
+# CONFIG_SH_RTS7751R2D is not set
+# CONFIG_SH_EDOSK7705 is not set
+# CONFIG_SH_SH4202_MICRODEV is not set
+# CONFIG_SH_UNKNOWN is not set
+# CONFIG_CPU_SH2 is not set
+# CONFIG_CPU_SH3 is not set
+CONFIG_CPU_SH4=y
+# CONFIG_CPU_SUBTYPE_SH7604 is not set
+# CONFIG_CPU_SUBTYPE_SH7300 is not set
+# CONFIG_CPU_SUBTYPE_SH7705 is not set
+# CONFIG_CPU_SUBTYPE_SH7707 is not set
+# CONFIG_CPU_SUBTYPE_SH7708 is not set
+# CONFIG_CPU_SUBTYPE_SH7709 is not set
+CONFIG_CPU_SUBTYPE_SH7750=y
+# CONFIG_CPU_SUBTYPE_SH7751 is not set
+# CONFIG_CPU_SUBTYPE_SH7760 is not set
+# CONFIG_CPU_SUBTYPE_SH73180 is not set
+# CONFIG_CPU_SUBTYPE_ST40STB1 is not set
+# CONFIG_CPU_SUBTYPE_ST40GX1 is not set
+# CONFIG_CPU_SUBTYPE_SH4_202 is not set
+CONFIG_MMU=y
+# CONFIG_CMDLINE_BOOL is not set
+CONFIG_MEMORY_START=0x08000000
+CONFIG_MEMORY_SIZE=0x00400000
+CONFIG_MEMORY_SET=y
+# CONFIG_MEMORY_OVERRIDE is not set
+CONFIG_CF_ENABLER=y
+# CONFIG_CF_AREA5 is not set
+CONFIG_CF_AREA6=y
+CONFIG_CF_BASE_ADDR=0xb8000000
+CONFIG_SH_RTC=y
+CONFIG_SH_FPU=y
+CONFIG_ZERO_PAGE_OFFSET=0x00001000
+CONFIG_BOOT_LINK_OFFSET=0x00800000
+CONFIG_CPU_LITTLE_ENDIAN=y
+# CONFIG_PREEMPT is not set
+# CONFIG_UBC_WAKEUP is not set
+# CONFIG_SH_WRITETHROUGH is not set
+# CONFIG_SH_OCRAM is not set
+# CONFIG_SH_STORE_QUEUES is not set
+# CONFIG_SMP is not set
+CONFIG_SH_PCLK_CALC=y
+CONFIG_SH_PCLK_FREQ=50000000
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# DMA support
+#
+# CONFIG_SH_DMA is not set
+
+#
+# Companion Chips
+#
+# CONFIG_HD6446X_SERIES is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
+#
+# CONFIG_PCI is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PC-card bridges
+#
+
+#
+# PCI Hotplug Support
+#
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_FLAT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# SH initrd options
+#
+# CONFIG_EMBEDDED_RAMDISK is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_LBD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_IDE_MAX_HWIFS=4
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+CONFIG_IDE_SH=y
+# CONFIG_IDE_ARM is not set
+# CONFIG_BLK_DEV_IDEDMA is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# Networking support
+#
+# CONFIG_NET is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_SH_SCI is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+CONFIG_VGA_CONSOLE=y
+CONFIG_DUMMY_CONSOLE=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB_ARCH_HAS_HCD is not set
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+
+#
+# XFS support
+#
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+# CONFIG_PROC_KCORE is not set
+CONFIG_SYSFS=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVPTS_FS_XATTR is not set
+# CONFIG_TMPFS is not set
+# CONFIG_HUGETLBFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_FRAME_POINTER is not set
+CONFIG_SH_STANDARD_BIOS=y
+# CONFIG_EARLY_SCIF_CONSOLE is not set
+# CONFIG_EARLY_PRINTK is not set
+# CONFIG_KGDB is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC32 is not set
+# CONFIG_LIBCRC32C is not set
diff --git a/arch/sh/configs/cqreek_defconfig b/arch/sh/configs/cqreek_defconfig
new file mode 100644
index 000000000000..614662ae5789
--- /dev/null
+++ b/arch/sh/configs/cqreek_defconfig
@@ -0,0 +1,533 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11-sh
+# Wed Mar 2 15:09:38 2005
+#
+CONFIG_SUPERH=y
+CONFIG_UID16=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_SWAP=y
+# CONFIG_SYSVIPC is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_SYSCTL is not set
+# CONFIG_AUDIT is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_HOTPLUG is not set
+# CONFIG_IKCONFIG is not set
+# CONFIG_EMBEDDED is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+
+#
+# Loadable module support
+#
+# CONFIG_MODULES is not set
+
+#
+# System type
+#
+# CONFIG_SH_SOLUTION_ENGINE is not set
+# CONFIG_SH_7751_SOLUTION_ENGINE is not set
+# CONFIG_SH_7300_SOLUTION_ENGINE is not set
+# CONFIG_SH_73180_SOLUTION_ENGINE is not set
+# CONFIG_SH_7751_SYSTEMH is not set
+# CONFIG_SH_STB1_HARP is not set
+# CONFIG_SH_STB1_OVERDRIVE is not set
+# CONFIG_SH_HP620 is not set
+# CONFIG_SH_HP680 is not set
+# CONFIG_SH_HP690 is not set
+CONFIG_SH_CQREEK=y
+# CONFIG_SH_DMIDA is not set
+# CONFIG_SH_EC3104 is not set
+# CONFIG_SH_SATURN is not set
+# CONFIG_SH_DREAMCAST is not set
+# CONFIG_SH_CAT68701 is not set
+# CONFIG_SH_BIGSUR is not set
+# CONFIG_SH_SH2000 is not set
+# CONFIG_SH_ADX is not set
+# CONFIG_SH_MPC1211 is not set
+# CONFIG_SH_SH03 is not set
+# CONFIG_SH_SECUREEDGE5410 is not set
+# CONFIG_SH_HS7751RVOIP is not set
+# CONFIG_SH_RTS7751R2D is not set
+# CONFIG_SH_EDOSK7705 is not set
+# CONFIG_SH_SH4202_MICRODEV is not set
+# CONFIG_SH_UNKNOWN is not set
+# CONFIG_CPU_SH2 is not set
+CONFIG_CPU_SH3=y
+# CONFIG_CPU_SH4 is not set
+# CONFIG_CPU_SUBTYPE_SH7604 is not set
+# CONFIG_CPU_SUBTYPE_SH7300 is not set
+# CONFIG_CPU_SUBTYPE_SH7705 is not set
+# CONFIG_CPU_SUBTYPE_SH7707 is not set
+CONFIG_CPU_SUBTYPE_SH7708=y
+# CONFIG_CPU_SUBTYPE_SH7709 is not set
+# CONFIG_CPU_SUBTYPE_SH7750 is not set
+# CONFIG_CPU_SUBTYPE_SH7751 is not set
+# CONFIG_CPU_SUBTYPE_SH7760 is not set
+# CONFIG_CPU_SUBTYPE_SH73180 is not set
+# CONFIG_CPU_SUBTYPE_ST40STB1 is not set
+# CONFIG_CPU_SUBTYPE_ST40GX1 is not set
+# CONFIG_CPU_SUBTYPE_SH4_202 is not set
+CONFIG_MMU=y
+# CONFIG_CMDLINE_BOOL is not set
+CONFIG_MEMORY_START=0x0c000000
+CONFIG_MEMORY_SIZE=0x00400000
+# CONFIG_MEMORY_OVERRIDE is not set
+CONFIG_SH_RTC=y
+CONFIG_SH_DSP=y
+CONFIG_SH_ADC=y
+CONFIG_ZERO_PAGE_OFFSET=0x00001000
+CONFIG_BOOT_LINK_OFFSET=0x00800000
+CONFIG_CPU_LITTLE_ENDIAN=y
+# CONFIG_PREEMPT is not set
+# CONFIG_UBC_WAKEUP is not set
+# CONFIG_SH_WRITETHROUGH is not set
+# CONFIG_SH_OCRAM is not set
+# CONFIG_SMP is not set
+CONFIG_SH_PCLK_CALC=y
+CONFIG_SH_PCLK_FREQ=1193182
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# DMA support
+#
+# CONFIG_SH_DMA is not set
+
+#
+# Companion Chips
+#
+# CONFIG_HD6446X_SERIES is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
+#
+# CONFIG_PCI is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PC-card bridges
+#
+
+#
+# PCI Hotplug Support
+#
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_FLAT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# SH initrd options
+#
+# CONFIG_EMBEDDED_RAMDISK is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_LBD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_IDE_MAX_HWIFS=4
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+CONFIG_IDE_SH=y
+# CONFIG_IDE_ARM is not set
+# CONFIG_BLK_DEV_IDEDMA is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# Networking support
+#
+# CONFIG_NET is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_SH_SCI is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+CONFIG_VGA_CONSOLE=y
+CONFIG_DUMMY_CONSOLE=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB_ARCH_HAS_HCD is not set
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+
+#
+# XFS support
+#
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+# CONFIG_PROC_KCORE is not set
+CONFIG_SYSFS=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVPTS_FS_XATTR is not set
+# CONFIG_TMPFS is not set
+# CONFIG_HUGETLBFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_FRAME_POINTER is not set
+CONFIG_SH_STANDARD_BIOS=y
+# CONFIG_EARLY_PRINTK is not set
+# CONFIG_KGDB is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC32 is not set
+# CONFIG_LIBCRC32C is not set
diff --git a/arch/sh/configs/dreamcast_defconfig b/arch/sh/configs/dreamcast_defconfig
new file mode 100644
index 000000000000..776c1909bee3
--- /dev/null
+++ b/arch/sh/configs/dreamcast_defconfig
@@ -0,0 +1,794 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11-sh
+# Wed Mar 2 15:09:40 2005
+#
+CONFIG_SUPERH=y
+CONFIG_UID16=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_HOTPLUG=y
+CONFIG_KOBJECT_UEVENT=y
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# System type
+#
+# CONFIG_SH_SOLUTION_ENGINE is not set
+# CONFIG_SH_7751_SOLUTION_ENGINE is not set
+# CONFIG_SH_7300_SOLUTION_ENGINE is not set
+# CONFIG_SH_73180_SOLUTION_ENGINE is not set
+# CONFIG_SH_7751_SYSTEMH is not set
+# CONFIG_SH_STB1_HARP is not set
+# CONFIG_SH_STB1_OVERDRIVE is not set
+# CONFIG_SH_HP620 is not set
+# CONFIG_SH_HP680 is not set
+# CONFIG_SH_HP690 is not set
+# CONFIG_SH_CQREEK is not set
+# CONFIG_SH_DMIDA is not set
+# CONFIG_SH_EC3104 is not set
+# CONFIG_SH_SATURN is not set
+CONFIG_SH_DREAMCAST=y
+# CONFIG_SH_CAT68701 is not set
+# CONFIG_SH_BIGSUR is not set
+# CONFIG_SH_SH2000 is not set
+# CONFIG_SH_ADX is not set
+# CONFIG_SH_MPC1211 is not set
+# CONFIG_SH_SH03 is not set
+# CONFIG_SH_SECUREEDGE5410 is not set
+# CONFIG_SH_HS7751RVOIP is not set
+# CONFIG_SH_RTS7751R2D is not set
+# CONFIG_SH_EDOSK7705 is not set
+# CONFIG_SH_SH4202_MICRODEV is not set
+# CONFIG_SH_UNKNOWN is not set
+# CONFIG_CPU_SH2 is not set
+# CONFIG_CPU_SH3 is not set
+CONFIG_CPU_SH4=y
+# CONFIG_CPU_SUBTYPE_SH7604 is not set
+# CONFIG_CPU_SUBTYPE_SH7300 is not set
+# CONFIG_CPU_SUBTYPE_SH7705 is not set
+# CONFIG_CPU_SUBTYPE_SH7707 is not set
+# CONFIG_CPU_SUBTYPE_SH7708 is not set
+# CONFIG_CPU_SUBTYPE_SH7709 is not set
+CONFIG_CPU_SUBTYPE_SH7750=y
+# CONFIG_CPU_SUBTYPE_SH7751 is not set
+# CONFIG_CPU_SUBTYPE_SH7760 is not set
+# CONFIG_CPU_SUBTYPE_SH73180 is not set
+# CONFIG_CPU_SUBTYPE_ST40STB1 is not set
+# CONFIG_CPU_SUBTYPE_ST40GX1 is not set
+# CONFIG_CPU_SUBTYPE_SH4_202 is not set
+CONFIG_MMU=y
+CONFIG_HUGETLB_PAGE_SIZE_64K=y
+# CONFIG_HUGETLB_PAGE_SIZE_1MB is not set
+# CONFIG_CMDLINE_BOOL is not set
+CONFIG_MEMORY_START=0x0c000000
+CONFIG_MEMORY_SIZE=0x01000000
+CONFIG_MEMORY_SET=y
+# CONFIG_MEMORY_OVERRIDE is not set
+CONFIG_SH_FPU=y
+CONFIG_ZERO_PAGE_OFFSET=0x00001000
+CONFIG_BOOT_LINK_OFFSET=0x00800000
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_PREEMPT=y
+# CONFIG_UBC_WAKEUP is not set
+# CONFIG_SH_WRITETHROUGH is not set
+CONFIG_SH_OCRAM=y
+CONFIG_SH_STORE_QUEUES=y
+# CONFIG_SMP is not set
+CONFIG_SH_PCLK_CALC=y
+CONFIG_SH_PCLK_FREQ=49876504
+
+#
+# CPU Frequency scaling
+#
+CONFIG_CPU_FREQ=y
+# CONFIG_CPU_FREQ_DEBUG is not set
+CONFIG_CPU_FREQ_STAT=y
+# CONFIG_CPU_FREQ_STAT_DETAILS is not set
+CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y
+# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set
+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+# CONFIG_CPU_FREQ_GOV_ONDEMAND is not set
+CONFIG_CPU_FREQ_TABLE=y
+CONFIG_SH_CPU_FREQ=y
+
+#
+# DMA support
+#
+CONFIG_SH_DMA=y
+CONFIG_NR_ONCHIP_DMA_CHANNELS=4
+CONFIG_NR_DMA_CHANNELS_BOOL=y
+CONFIG_NR_DMA_CHANNELS=9
+
+#
+# Companion Chips
+#
+# CONFIG_HD6446X_SERIES is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
+#
+CONFIG_MAPLE=y
+CONFIG_PCI=y
+# CONFIG_SH_PCIDMA_NONCOHERENT is not set
+CONFIG_PCI_AUTO=y
+CONFIG_PCI_LEGACY_PROC=y
+CONFIG_PCI_NAMES=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PC-card bridges
+#
+
+#
+# PCI Hotplug Support
+#
+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_FLAT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# SH initrd options
+#
+# CONFIG_EMBEDDED_RAMDISK is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+# CONFIG_STANDALONE is not set
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=1024
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_LBD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+# CONFIG_NETLINK_DEV is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_IP_TCPDIAG=y
+# CONFIG_IP_TCPDIAG_IPV6 is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_STNIC is not set
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_SMC91X is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+CONFIG_NET_PCI=y
+# CONFIG_PCNET32 is not set
+# CONFIG_AMD8111_ETH is not set
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_B44 is not set
+# CONFIG_FORCEDETH is not set
+# CONFIG_DGRS is not set
+# CONFIG_EEPRO100 is not set
+# CONFIG_E100 is not set
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+# CONFIG_8139CP is not set
+CONFIG_8139TOO=y
+# CONFIG_8139TOO_PIO is not set
+# CONFIG_8139TOO_TUNE_TWISTER is not set
+# CONFIG_8139TOO_8129 is not set
+# CONFIG_8139_OLD_RX_RESET is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
+# CONFIG_TIGON3 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+# CONFIG_SERIO_SERPORT is not set
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_PCIPS2 is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_MAPLE is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_MAPLE is not set
+# CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_SH_SCI=y
+CONFIG_SERIAL_SH_SCI_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_SH_WDT=y
+
+#
+# PCI-based Watchdog Cards
+#
+# CONFIG_PCIPCWATCHDOG is not set
+# CONFIG_WDTPCI is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+CONFIG_FB=y
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+# CONFIG_FB_CIRRUS is not set
+# CONFIG_FB_PM2 is not set
+# CONFIG_FB_CYBER2000 is not set
+# CONFIG_FB_ASILIANT is not set
+# CONFIG_FB_IMSTT is not set
+CONFIG_FB_PVR2=y
+# CONFIG_FB_EPSON1355 is not set
+# CONFIG_FB_RIVA is not set
+# CONFIG_FB_MATROX is not set
+# CONFIG_FB_RADEON_OLD is not set
+# CONFIG_FB_RADEON is not set
+# CONFIG_FB_ATY128 is not set
+# CONFIG_FB_ATY is not set
+# CONFIG_FB_SAVAGE is not set
+# CONFIG_FB_SIS is not set
+# CONFIG_FB_NEOMAGIC is not set
+# CONFIG_FB_KYRO is not set
+# CONFIG_FB_3DFX is not set
+# CONFIG_FB_VOODOO1 is not set
+# CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FONTS=y
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+# CONFIG_FONT_6x11 is not set
+# CONFIG_FONT_PEARL_8x8 is not set
+# CONFIG_FONT_ACORN_8x8 is not set
+# CONFIG_FONT_MINI_4x6 is not set
+# CONFIG_FONT_SUN8x16 is not set
+# CONFIG_FONT_SUN12x22 is not set
+
+#
+# Logo configuration
+#
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+# CONFIG_LOGO_LINUX_CLUT224 is not set
+# CONFIG_LOGO_SUPERH_MONO is not set
+# CONFIG_LOGO_SUPERH_VGA16 is not set
+CONFIG_LOGO_SUPERH_CLUT224=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# File systems
+#
+# CONFIG_EXT2_FS is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+
+#
+# XFS support
+#
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+CONFIG_ROMFS_FS=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+CONFIG_DEVFS_FS=y
+CONFIG_DEVFS_MOUNT=y
+# CONFIG_DEVFS_DEBUG is not set
+# CONFIG_DEVPTS_FS_XATTR is not set
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_XATTR is not set
+CONFIG_HUGETLBFS=y
+CONFIG_HUGETLB_PAGE=y
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_CRAMFS=y
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Profiling support
+#
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=y
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_DEBUG_PREEMPT=y
+# CONFIG_FRAME_POINTER is not set
+# CONFIG_SH_STANDARD_BIOS is not set
+# CONFIG_EARLY_SCIF_CONSOLE is not set
+# CONFIG_KGDB is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
diff --git a/arch/sh/configs/hp680_defconfig b/arch/sh/configs/hp680_defconfig
new file mode 100644
index 000000000000..c85d3655b53c
--- /dev/null
+++ b/arch/sh/configs/hp680_defconfig
@@ -0,0 +1,554 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11-sh
+# Wed Mar 2 15:09:41 2005
+#
+CONFIG_SUPERH=y
+CONFIG_UID16=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+# CONFIG_CLEAN_COMPILE is not set
+CONFIG_BROKEN=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_SWAP=y
+# CONFIG_SYSVIPC is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_SYSCTL is not set
+# CONFIG_AUDIT is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_HOTPLUG is not set
+# CONFIG_IKCONFIG is not set
+# CONFIG_EMBEDDED is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+
+#
+# Loadable module support
+#
+# CONFIG_MODULES is not set
+
+#
+# System type
+#
+# CONFIG_SH_SOLUTION_ENGINE is not set
+# CONFIG_SH_7751_SOLUTION_ENGINE is not set
+# CONFIG_SH_7300_SOLUTION_ENGINE is not set
+# CONFIG_SH_73180_SOLUTION_ENGINE is not set
+# CONFIG_SH_7751_SYSTEMH is not set
+# CONFIG_SH_STB1_HARP is not set
+# CONFIG_SH_STB1_OVERDRIVE is not set
+# CONFIG_SH_HP620 is not set
+CONFIG_SH_HP680=y
+# CONFIG_SH_HP690 is not set
+# CONFIG_SH_CQREEK is not set
+# CONFIG_SH_DMIDA is not set
+# CONFIG_SH_EC3104 is not set
+# CONFIG_SH_SATURN is not set
+# CONFIG_SH_DREAMCAST is not set
+# CONFIG_SH_CAT68701 is not set
+# CONFIG_SH_BIGSUR is not set
+# CONFIG_SH_SH2000 is not set
+# CONFIG_SH_ADX is not set
+# CONFIG_SH_MPC1211 is not set
+# CONFIG_SH_SH03 is not set
+# CONFIG_SH_SECUREEDGE5410 is not set
+# CONFIG_SH_HS7751RVOIP is not set
+# CONFIG_SH_RTS7751R2D is not set
+# CONFIG_SH_EDOSK7705 is not set
+# CONFIG_SH_SH4202_MICRODEV is not set
+# CONFIG_SH_UNKNOWN is not set
+# CONFIG_CPU_SH2 is not set
+CONFIG_CPU_SH3=y
+# CONFIG_CPU_SH4 is not set
+# CONFIG_CPU_SUBTYPE_SH7604 is not set
+# CONFIG_CPU_SUBTYPE_SH7300 is not set
+# CONFIG_CPU_SUBTYPE_SH7705 is not set
+# CONFIG_CPU_SUBTYPE_SH7707 is not set
+# CONFIG_CPU_SUBTYPE_SH7708 is not set
+CONFIG_CPU_SUBTYPE_SH7709=y
+# CONFIG_CPU_SUBTYPE_SH7750 is not set
+# CONFIG_CPU_SUBTYPE_SH7751 is not set
+# CONFIG_CPU_SUBTYPE_SH7760 is not set
+# CONFIG_CPU_SUBTYPE_SH73180 is not set
+# CONFIG_CPU_SUBTYPE_ST40STB1 is not set
+# CONFIG_CPU_SUBTYPE_ST40GX1 is not set
+# CONFIG_CPU_SUBTYPE_SH4_202 is not set
+CONFIG_MMU=y
+# CONFIG_CMDLINE_BOOL is not set
+CONFIG_MEMORY_START=0x0c000000
+CONFIG_MEMORY_SIZE=0x00400000
+CONFIG_MEMORY_SET=y
+# CONFIG_MEMORY_OVERRIDE is not set
+CONFIG_SH_RTC=y
+# CONFIG_SH_DSP is not set
+CONFIG_SH_ADC=y
+CONFIG_SH_HP600=y
+CONFIG_ZERO_PAGE_OFFSET=0x00001000
+CONFIG_BOOT_LINK_OFFSET=0x00800000
+CONFIG_CPU_LITTLE_ENDIAN=y
+# CONFIG_PREEMPT is not set
+# CONFIG_UBC_WAKEUP is not set
+# CONFIG_SH_WRITETHROUGH is not set
+# CONFIG_SH_OCRAM is not set
+# CONFIG_SMP is not set
+CONFIG_SH_PCLK_CALC=y
+CONFIG_SH_PCLK_FREQ=1193182
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# DMA support
+#
+# CONFIG_SH_DMA is not set
+
+#
+# Companion Chips
+#
+CONFIG_HD6446X_SERIES=y
+CONFIG_HD64461=y
+# CONFIG_HD64465 is not set
+CONFIG_HD64461_IRQ=36
+# CONFIG_HD64461_ENABLER is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
+#
+# CONFIG_PCI is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PC-card bridges
+#
+
+#
+# PCI Hotplug Support
+#
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_FLAT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# SH initrd options
+#
+# CONFIG_EMBEDDED_RAMDISK is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+# CONFIG_STANDALONE is not set
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_LBD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_IDE_MAX_HWIFS=4
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+CONFIG_IDE_SH=y
+# CONFIG_IDE_ARM is not set
+# CONFIG_BLK_DEV_IDEDMA is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+
+#
+# Networking support
+#
+# CONFIG_NET is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+# CONFIG_SERIO_SERPORT is not set
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_RAW is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_SH_SCI is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+
+#
+# Graphics support
+#
+CONFIG_FB=y
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+# CONFIG_FB_EPSON1355 is not set
+CONFIG_FB_HIT=y
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FONTS=y
+# CONFIG_FONT_8x8 is not set
+# CONFIG_FONT_8x16 is not set
+# CONFIG_FONT_6x11 is not set
+CONFIG_FONT_PEARL_8x8=y
+# CONFIG_FONT_ACORN_8x8 is not set
+# CONFIG_FONT_MINI_4x6 is not set
+# CONFIG_FONT_SUN8x16 is not set
+# CONFIG_FONT_SUN12x22 is not set
+
+#
+# Logo configuration
+#
+# CONFIG_LOGO is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB_ARCH_HAS_HCD is not set
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+
+#
+# XFS support
+#
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+CONFIG_DEVFS_FS=y
+CONFIG_DEVFS_MOUNT=y
+# CONFIG_DEVFS_DEBUG is not set
+# CONFIG_DEVPTS_FS_XATTR is not set
+# CONFIG_TMPFS is not set
+# CONFIG_HUGETLBFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_FRAME_POINTER is not set
+# CONFIG_SH_STANDARD_BIOS is not set
+# CONFIG_KGDB is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
diff --git a/arch/sh/configs/microdev_defconfig b/arch/sh/configs/microdev_defconfig
new file mode 100644
index 000000000000..a3bd280b53d6
--- /dev/null
+++ b/arch/sh/configs/microdev_defconfig
@@ -0,0 +1,734 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11-sh
+# Wed Mar 2 15:09:41 2005
+#
+CONFIG_SUPERH=y
+CONFIG_UID16=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_SWAP=y
+# CONFIG_SYSVIPC is not set
+# CONFIG_POSIX_MQUEUE is not set
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_HOTPLUG=y
+CONFIG_KOBJECT_UEVENT=y
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+
+#
+# Loadable module support
+#
+# CONFIG_MODULES is not set
+
+#
+# System type
+#
+# CONFIG_SH_SOLUTION_ENGINE is not set
+# CONFIG_SH_7751_SOLUTION_ENGINE is not set
+# CONFIG_SH_7300_SOLUTION_ENGINE is not set
+# CONFIG_SH_73180_SOLUTION_ENGINE is not set
+# CONFIG_SH_7751_SYSTEMH is not set
+# CONFIG_SH_STB1_HARP is not set
+# CONFIG_SH_STB1_OVERDRIVE is not set
+# CONFIG_SH_HP620 is not set
+# CONFIG_SH_HP680 is not set
+# CONFIG_SH_HP690 is not set
+# CONFIG_SH_CQREEK is not set
+# CONFIG_SH_DMIDA is not set
+# CONFIG_SH_EC3104 is not set
+# CONFIG_SH_SATURN is not set
+# CONFIG_SH_DREAMCAST is not set
+# CONFIG_SH_CAT68701 is not set
+# CONFIG_SH_BIGSUR is not set
+# CONFIG_SH_SH2000 is not set
+# CONFIG_SH_ADX is not set
+# CONFIG_SH_MPC1211 is not set
+# CONFIG_SH_SH03 is not set
+# CONFIG_SH_SECUREEDGE5410 is not set
+# CONFIG_SH_HS7751RVOIP is not set
+# CONFIG_SH_RTS7751R2D is not set
+# CONFIG_SH_EDOSK7705 is not set
+CONFIG_SH_SH4202_MICRODEV=y
+# CONFIG_SH_UNKNOWN is not set
+# CONFIG_CPU_SH2 is not set
+# CONFIG_CPU_SH3 is not set
+CONFIG_CPU_SH4=y
+# CONFIG_CPU_SUBTYPE_SH7604 is not set
+# CONFIG_CPU_SUBTYPE_SH7300 is not set
+# CONFIG_CPU_SUBTYPE_SH7705 is not set
+# CONFIG_CPU_SUBTYPE_SH7707 is not set
+# CONFIG_CPU_SUBTYPE_SH7708 is not set
+# CONFIG_CPU_SUBTYPE_SH7709 is not set
+# CONFIG_CPU_SUBTYPE_SH7750 is not set
+# CONFIG_CPU_SUBTYPE_SH7751 is not set
+# CONFIG_CPU_SUBTYPE_SH7760 is not set
+# CONFIG_CPU_SUBTYPE_SH73180 is not set
+# CONFIG_CPU_SUBTYPE_ST40STB1 is not set
+# CONFIG_CPU_SUBTYPE_ST40GX1 is not set
+CONFIG_CPU_SUBTYPE_SH4_202=y
+CONFIG_MMU=y
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="console=ttySC0,115200"
+CONFIG_MEMORY_START=0x08000000
+CONFIG_MEMORY_SIZE=0x04000000
+CONFIG_MEMORY_SET=y
+# CONFIG_MEMORY_OVERRIDE is not set
+CONFIG_SH_RTC=y
+CONFIG_SH_FPU=y
+CONFIG_ZERO_PAGE_OFFSET=0x00001000
+CONFIG_BOOT_LINK_OFFSET=0x00800000
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_PREEMPT=y
+# CONFIG_UBC_WAKEUP is not set
+# CONFIG_SH_WRITETHROUGH is not set
+# CONFIG_SH_OCRAM is not set
+# CONFIG_SH_STORE_QUEUES is not set
+# CONFIG_SMP is not set
+CONFIG_SH_PCLK_CALC=y
+CONFIG_SH_PCLK_FREQ=65986048
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# DMA support
+#
+CONFIG_SH_DMA=y
+CONFIG_NR_ONCHIP_DMA_CHANNELS=4
+# CONFIG_NR_DMA_CHANNELS_BOOL is not set
+
+#
+# Companion Chips
+#
+# CONFIG_HD6446X_SERIES is not set
+CONFIG_HEARTBEAT=y
+
+#
+# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
+#
+CONFIG_ISA=y
+# CONFIG_PCI is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PC-card bridges
+#
+CONFIG_PCMCIA_PROBE=y
+
+#
+# PCI Hotplug Support
+#
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_FLAT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# SH initrd options
+#
+# CONFIG_EMBEDDED_RAMDISK is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+# CONFIG_PNP is not set
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_XD is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_LBD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_IDE_MAX_HWIFS=1
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+CONFIG_BLK_DEV_IDECD=y
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+CONFIG_IDE_SH=y
+# CONFIG_IDE_ARM is not set
+# CONFIG_IDE_CHIPSETS is not set
+# CONFIG_BLK_DEV_IDEDMA is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Old CD-ROM drivers (not SCSI, not IDE)
+#
+# CONFIG_CD_NO_IDESCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_PACKET is not set
+# CONFIG_NETLINK_DEV is not set
+# CONFIG_UNIX is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_IP_TCPDIAG=y
+# CONFIG_IP_TCPDIAG_IPV6 is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_STNIC is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_LANCE is not set
+# CONFIG_NET_VENDOR_SMC is not set
+CONFIG_SMC91X=y
+# CONFIG_NET_VENDOR_RACAL is not set
+# CONFIG_AT1700 is not set
+# CONFIG_DEPCA is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_ISA is not set
+# CONFIG_NET_PCI is not set
+# CONFIG_NET_POCKET is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+# CONFIG_INPUT is not set
+
+#
+# Userland interfaces
+#
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+# CONFIG_SERIO is not set
+# CONFIG_SERIO_I8042 is not set
+
+#
+# Input Device Drivers
+#
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_SH_SCI=y
+CONFIG_SERIAL_SH_SCI_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+CONFIG_RTC=y
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB_ARCH_HAS_HCD is not set
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+
+#
+# XFS support
+#
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+# CONFIG_MSDOS_FS is not set
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+CONFIG_DEVFS_FS=y
+CONFIG_DEVFS_MOUNT=y
+# CONFIG_DEVFS_DEBUG is not set
+CONFIG_DEVPTS_FS_XATTR=y
+# CONFIG_DEVPTS_FS_SECURITY is not set
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_XATTR is not set
+# CONFIG_HUGETLBFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+CONFIG_NFS_V4=y
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_SUNRPC=y
+CONFIG_SUNRPC_GSS=y
+CONFIG_RPCSEC_GSS_KRB5=y
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_DEBUG_PREEMPT=y
+# CONFIG_FRAME_POINTER is not set
+# CONFIG_SH_STANDARD_BIOS is not set
+# CONFIG_EARLY_SCIF_CONSOLE is not set
+# CONFIG_KGDB is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_WP512 is not set
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
diff --git a/arch/sh/configs/rts7751r2d_defconfig b/arch/sh/configs/rts7751r2d_defconfig
new file mode 100644
index 000000000000..e43cf57326bd
--- /dev/null
+++ b/arch/sh/configs/rts7751r2d_defconfig
@@ -0,0 +1,847 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11-sh
+# Wed Mar 2 15:09:42 2005
+#
+CONFIG_SUPERH=y
+CONFIG_UID16=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_HOTPLUG=y
+CONFIG_KOBJECT_UEVENT=y
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+# CONFIG_MODULE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+# CONFIG_KMOD is not set
+
+#
+# System type
+#
+# CONFIG_SH_SOLUTION_ENGINE is not set
+# CONFIG_SH_7751_SOLUTION_ENGINE is not set
+# CONFIG_SH_7300_SOLUTION_ENGINE is not set
+# CONFIG_SH_73180_SOLUTION_ENGINE is not set
+# CONFIG_SH_7751_SYSTEMH is not set
+# CONFIG_SH_STB1_HARP is not set
+# CONFIG_SH_STB1_OVERDRIVE is not set
+# CONFIG_SH_HP620 is not set
+# CONFIG_SH_HP680 is not set
+# CONFIG_SH_HP690 is not set
+# CONFIG_SH_CQREEK is not set
+# CONFIG_SH_DMIDA is not set
+# CONFIG_SH_EC3104 is not set
+# CONFIG_SH_SATURN is not set
+# CONFIG_SH_DREAMCAST is not set
+# CONFIG_SH_CAT68701 is not set
+# CONFIG_SH_BIGSUR is not set
+# CONFIG_SH_SH2000 is not set
+# CONFIG_SH_ADX is not set
+# CONFIG_SH_MPC1211 is not set
+# CONFIG_SH_SH03 is not set
+# CONFIG_SH_SECUREEDGE5410 is not set
+# CONFIG_SH_HS7751RVOIP is not set
+CONFIG_SH_RTS7751R2D=y
+# CONFIG_SH_EDOSK7705 is not set
+# CONFIG_SH_SH4202_MICRODEV is not set
+# CONFIG_SH_UNKNOWN is not set
+# CONFIG_CPU_SH2 is not set
+# CONFIG_CPU_SH3 is not set
+CONFIG_CPU_SH4=y
+# CONFIG_CPU_SUBTYPE_SH7604 is not set
+# CONFIG_CPU_SUBTYPE_SH7300 is not set
+# CONFIG_CPU_SUBTYPE_SH7705 is not set
+# CONFIG_CPU_SUBTYPE_SH7707 is not set
+# CONFIG_CPU_SUBTYPE_SH7708 is not set
+# CONFIG_CPU_SUBTYPE_SH7709 is not set
+# CONFIG_CPU_SUBTYPE_SH7750 is not set
+CONFIG_CPU_SUBTYPE_SH7751=y
+# CONFIG_CPU_SUBTYPE_SH7760 is not set
+# CONFIG_CPU_SUBTYPE_SH73180 is not set
+# CONFIG_CPU_SUBTYPE_ST40STB1 is not set
+# CONFIG_CPU_SUBTYPE_ST40GX1 is not set
+# CONFIG_CPU_SUBTYPE_SH4_202 is not set
+CONFIG_MMU=y
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="mem=64M console=ttySC0,115200 root=/dev/hda1"
+CONFIG_MEMORY_START=0x0c000000
+CONFIG_MEMORY_SIZE=0x04000000
+CONFIG_MEMORY_SET=y
+# CONFIG_MEMORY_OVERRIDE is not set
+CONFIG_SH_RTC=y
+CONFIG_SH_FPU=y
+CONFIG_ZERO_PAGE_OFFSET=0x00010000
+CONFIG_BOOT_LINK_OFFSET=0x00800000
+CONFIG_CPU_LITTLE_ENDIAN=y
+# CONFIG_PREEMPT is not set
+# CONFIG_UBC_WAKEUP is not set
+# CONFIG_SH_WRITETHROUGH is not set
+# CONFIG_SH_OCRAM is not set
+# CONFIG_SH_STORE_QUEUES is not set
+# CONFIG_SMP is not set
+CONFIG_RTS7751R2D_REV11=y
+CONFIG_SH_PCLK_CALC=y
+CONFIG_SH_PCLK_FREQ=60000000
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# DMA support
+#
+CONFIG_SH_DMA=y
+CONFIG_NR_ONCHIP_DMA_CHANNELS=8
+# CONFIG_NR_DMA_CHANNELS_BOOL is not set
+
+#
+# Companion Chips
+#
+CONFIG_VOYAGERGX=y
+# CONFIG_HD6446X_SERIES is not set
+CONFIG_HEARTBEAT=y
+CONFIG_RTC_9701JE=y
+
+#
+# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
+#
+CONFIG_PCI=y
+CONFIG_SH_PCIDMA_NONCOHERENT=y
+CONFIG_PCI_AUTO=y
+CONFIG_PCI_AUTO_UPDATE_RESOURCES=y
+# CONFIG_PCI_LEGACY_PROC is not set
+CONFIG_PCI_NAMES=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PC-card bridges
+#
+
+#
+# PCI Hotplug Support
+#
+CONFIG_HOTPLUG_PCI=y
+# CONFIG_HOTPLUG_PCI_FAKE is not set
+# CONFIG_HOTPLUG_PCI_CPCI is not set
+# CONFIG_HOTPLUG_PCI_SHPC is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_FLAT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+# CONFIG_BLK_DEV_INITRD is not set
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_LBD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_IDE_MAX_HWIFS=4
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+# CONFIG_BLK_DEV_IDEPCI is not set
+CONFIG_IDE_SH=y
+# CONFIG_IDE_ARM is not set
+# CONFIG_BLK_DEV_IDEDMA is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+# CONFIG_NETLINK_DEV is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+# CONFIG_IP_PNP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_IP_TCPDIAG=y
+# CONFIG_IP_TCPDIAG_IPV6 is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_STNIC is not set
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_SMC91X is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+CONFIG_NET_PCI=y
+# CONFIG_PCNET32 is not set
+# CONFIG_AMD8111_ETH is not set
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_B44 is not set
+# CONFIG_FORCEDETH is not set
+# CONFIG_DGRS is not set
+# CONFIG_EEPRO100 is not set
+# CONFIG_E100 is not set
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+# CONFIG_8139CP is not set
+CONFIG_8139TOO=y
+# CONFIG_8139TOO_PIO is not set
+# CONFIG_8139TOO_TUNE_TWISTER is not set
+# CONFIG_8139TOO_8129 is not set
+# CONFIG_8139_OLD_RX_RESET is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
+# CONFIG_TIGON3 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+CONFIG_NET_RADIO=y
+
+#
+# Obsolete Wireless cards support (pre-802.11)
+#
+# CONFIG_STRIP is not set
+
+#
+# Wireless 802.11b ISA/PCI cards support
+#
+CONFIG_HERMES=m
+# CONFIG_PLX_HERMES is not set
+# CONFIG_TMD_HERMES is not set
+# CONFIG_PCI_HERMES is not set
+# CONFIG_ATMEL is not set
+
+#
+# Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support
+#
+# CONFIG_PRISM54 is not set
+CONFIG_NET_WIRELESS=y
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+# CONFIG_INPUT is not set
+
+#
+# Userland interfaces
+#
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+# CONFIG_SERIO is not set
+# CONFIG_SERIO_I8042 is not set
+
+#
+# Input Device Drivers
+#
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_SH_SCI is not set
+# CONFIG_UNIX98_PTYS is not set
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+CONFIG_SOUND=y
+
+#
+# Advanced Linux Sound Architecture
+#
+CONFIG_SND=m
+CONFIG_SND_TIMER=m
+CONFIG_SND_PCM=m
+CONFIG_SND_HWDEP=m
+CONFIG_SND_RAWMIDI=m
+# CONFIG_SND_SEQUENCER is not set
+# CONFIG_SND_MIXER_OSS is not set
+# CONFIG_SND_PCM_OSS is not set
+# CONFIG_SND_VERBOSE_PRINTK is not set
+# CONFIG_SND_DEBUG is not set
+
+#
+# Generic devices
+#
+CONFIG_SND_MPU401_UART=m
+CONFIG_SND_OPL3_LIB=m
+# CONFIG_SND_DUMMY is not set
+# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_SERIAL_U16550 is not set
+# CONFIG_SND_MPU401 is not set
+
+#
+# PCI devices
+#
+CONFIG_SND_AC97_CODEC=m
+# CONFIG_SND_ALI5451 is not set
+# CONFIG_SND_ATIIXP is not set
+# CONFIG_SND_ATIIXP_MODEM is not set
+# CONFIG_SND_AU8810 is not set
+# CONFIG_SND_AU8820 is not set
+# CONFIG_SND_AU8830 is not set
+# CONFIG_SND_AZT3328 is not set
+# CONFIG_SND_BT87X is not set
+# CONFIG_SND_CS46XX is not set
+# CONFIG_SND_CS4281 is not set
+# CONFIG_SND_EMU10K1 is not set
+# CONFIG_SND_EMU10K1X is not set
+# CONFIG_SND_CA0106 is not set
+# CONFIG_SND_KORG1212 is not set
+# CONFIG_SND_MIXART is not set
+# CONFIG_SND_NM256 is not set
+# CONFIG_SND_RME32 is not set
+# CONFIG_SND_RME96 is not set
+# CONFIG_SND_RME9652 is not set
+# CONFIG_SND_HDSP is not set
+# CONFIG_SND_TRIDENT is not set
+CONFIG_SND_YMFPCI=m
+# CONFIG_SND_ALS4000 is not set
+# CONFIG_SND_CMIPCI is not set
+# CONFIG_SND_ENS1370 is not set
+# CONFIG_SND_ENS1371 is not set
+# CONFIG_SND_ES1938 is not set
+# CONFIG_SND_ES1968 is not set
+# CONFIG_SND_MAESTRO3 is not set
+# CONFIG_SND_FM801 is not set
+# CONFIG_SND_ICE1712 is not set
+# CONFIG_SND_ICE1724 is not set
+# CONFIG_SND_INTEL8X0 is not set
+# CONFIG_SND_INTEL8X0M is not set
+# CONFIG_SND_SONICVIBES is not set
+# CONFIG_SND_VIA82XX is not set
+# CONFIG_SND_VIA82XX_MODEM is not set
+# CONFIG_SND_VX222 is not set
+
+#
+# Open Sound System
+#
+CONFIG_SOUND_PRIME=m
+# CONFIG_SOUND_BT878 is not set
+CONFIG_SOUND_CMPCI=m
+# CONFIG_SOUND_EMU10K1 is not set
+# CONFIG_SOUND_FUSION is not set
+# CONFIG_SOUND_CS4281 is not set
+# CONFIG_SOUND_ES1370 is not set
+# CONFIG_SOUND_ES1371 is not set
+# CONFIG_SOUND_ESSSOLO1 is not set
+# CONFIG_SOUND_MAESTRO is not set
+# CONFIG_SOUND_MAESTRO3 is not set
+# CONFIG_SOUND_ICH is not set
+# CONFIG_SOUND_SONICVIBES is not set
+# CONFIG_SOUND_TRIDENT is not set
+# CONFIG_SOUND_MSNDCLAS is not set
+# CONFIG_SOUND_MSNDPIN is not set
+# CONFIG_SOUND_VIA82CXXX is not set
+# CONFIG_SOUND_OSS is not set
+# CONFIG_SOUND_ALI5455 is not set
+# CONFIG_SOUND_FORTE is not set
+# CONFIG_SOUND_RME96XX is not set
+# CONFIG_SOUND_AD1980 is not set
+CONFIG_SOUND_VOYAGERGX=m
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+
+#
+# XFS support
+#
+# CONFIG_XFS_FS is not set
+CONFIG_MINIX_FS=y
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_TMPFS is not set
+# CONFIG_HUGETLBFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+# CONFIG_NFS_FS is not set
+# CONFIG_NFSD is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+CONFIG_NLS_CODEPAGE_932=y
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Profiling support
+#
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=y
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_FRAME_POINTER is not set
+# CONFIG_SH_STANDARD_BIOS is not set
+# CONFIG_EARLY_SCIF_CONSOLE is not set
+# CONFIG_KGDB is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
diff --git a/arch/sh/configs/se7300_defconfig b/arch/sh/configs/se7300_defconfig
new file mode 100644
index 000000000000..4b71cd692fa5
--- /dev/null
+++ b/arch/sh/configs/se7300_defconfig
@@ -0,0 +1,531 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11-sh
+# Wed Mar 2 15:09:43 2005
+#
+CONFIG_SUPERH=y
+CONFIG_UID16=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+# CONFIG_SWAP is not set
+# CONFIG_SYSVIPC is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_HOTPLUG is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+# CONFIG_KALLSYMS is not set
+# CONFIG_FUTEX is not set
+# CONFIG_EPOLL is not set
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+
+#
+# Loadable module support
+#
+# CONFIG_MODULES is not set
+
+#
+# System type
+#
+# CONFIG_SH_SOLUTION_ENGINE is not set
+# CONFIG_SH_7751_SOLUTION_ENGINE is not set
+CONFIG_SH_7300_SOLUTION_ENGINE=y
+# CONFIG_SH_73180_SOLUTION_ENGINE is not set
+# CONFIG_SH_7751_SYSTEMH is not set
+# CONFIG_SH_STB1_HARP is not set
+# CONFIG_SH_STB1_OVERDRIVE is not set
+# CONFIG_SH_HP620 is not set
+# CONFIG_SH_HP680 is not set
+# CONFIG_SH_HP690 is not set
+# CONFIG_SH_CQREEK is not set
+# CONFIG_SH_DMIDA is not set
+# CONFIG_SH_EC3104 is not set
+# CONFIG_SH_SATURN is not set
+# CONFIG_SH_DREAMCAST is not set
+# CONFIG_SH_CAT68701 is not set
+# CONFIG_SH_BIGSUR is not set
+# CONFIG_SH_SH2000 is not set
+# CONFIG_SH_ADX is not set
+# CONFIG_SH_MPC1211 is not set
+# CONFIG_SH_SH03 is not set
+# CONFIG_SH_SECUREEDGE5410 is not set
+# CONFIG_SH_HS7751RVOIP is not set
+# CONFIG_SH_RTS7751R2D is not set
+# CONFIG_SH_EDOSK7705 is not set
+# CONFIG_SH_SH4202_MICRODEV is not set
+# CONFIG_SH_UNKNOWN is not set
+# CONFIG_CPU_SH2 is not set
+CONFIG_CPU_SH3=y
+# CONFIG_CPU_SH4 is not set
+# CONFIG_CPU_SUBTYPE_SH7604 is not set
+CONFIG_CPU_SUBTYPE_SH7300=y
+# CONFIG_CPU_SUBTYPE_SH7705 is not set
+# CONFIG_CPU_SUBTYPE_SH7707 is not set
+# CONFIG_CPU_SUBTYPE_SH7708 is not set
+# CONFIG_CPU_SUBTYPE_SH7709 is not set
+# CONFIG_CPU_SUBTYPE_SH7750 is not set
+# CONFIG_CPU_SUBTYPE_SH7751 is not set
+# CONFIG_CPU_SUBTYPE_SH7760 is not set
+# CONFIG_CPU_SUBTYPE_SH73180 is not set
+# CONFIG_CPU_SUBTYPE_ST40STB1 is not set
+# CONFIG_CPU_SUBTYPE_ST40GX1 is not set
+# CONFIG_CPU_SUBTYPE_SH4_202 is not set
+CONFIG_MMU=y
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="console=ttySC0,38400 root=/dev/ram0"
+CONFIG_MEMORY_START=0x0c000000
+CONFIG_MEMORY_SIZE=0x04000000
+# CONFIG_MEMORY_OVERRIDE is not set
+CONFIG_SH_DSP=y
+# CONFIG_SH_ADC is not set
+CONFIG_ZERO_PAGE_OFFSET=0x00001000
+CONFIG_BOOT_LINK_OFFSET=0x00210000
+CONFIG_CPU_LITTLE_ENDIAN=y
+# CONFIG_PREEMPT is not set
+# CONFIG_UBC_WAKEUP is not set
+# CONFIG_SH_WRITETHROUGH is not set
+# CONFIG_SH_OCRAM is not set
+# CONFIG_SMP is not set
+# CONFIG_SH_PCLK_CALC is not set
+CONFIG_SH_PCLK_FREQ=33333333
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# DMA support
+#
+# CONFIG_SH_DMA is not set
+
+#
+# Companion Chips
+#
+# CONFIG_HD6446X_SERIES is not set
+CONFIG_HEARTBEAT=y
+
+#
+# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
+#
+# CONFIG_PCI is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PC-card bridges
+#
+
+#
+# PCI Hotplug Support
+#
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_FLAT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# SH initrd options
+#
+CONFIG_EMBEDDED_RAMDISK=y
+CONFIG_EMBEDDED_RAMDISK_IMAGE="ramdisk.gz"
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_LBD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# Networking support
+#
+# CONFIG_NET is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+# CONFIG_SERIO_SERPORT is not set
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_LIBPS2 is not set
+# CONFIG_SERIO_RAW is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_SH_SCI=y
+CONFIG_SERIAL_SH_SCI_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_UNIX98_PTYS is not set
+# CONFIG_LEGACY_PTYS is not set
+
+#
+# IPMI
+#
+CONFIG_IPMI_HANDLER=y
+# CONFIG_IPMI_PANIC_EVENT is not set
+CONFIG_IPMI_DEVICE_INTERFACE=y
+# CONFIG_IPMI_SI is not set
+CONFIG_IPMI_WATCHDOG=y
+# CONFIG_IPMI_POWEROFF is not set
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+CONFIG_SOFT_WATCHDOG=y
+# CONFIG_SH_WDT is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB_ARCH_HAS_HCD is not set
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+
+#
+# XFS support
+#
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+CONFIG_DEVFS_FS=y
+CONFIG_DEVFS_MOUNT=y
+# CONFIG_DEVFS_DEBUG is not set
+# CONFIG_TMPFS is not set
+# CONFIG_HUGETLBFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_FRAME_POINTER is not set
+CONFIG_SH_STANDARD_BIOS=y
+CONFIG_EARLY_PRINTK=y
+CONFIG_KGDB=y
+
+#
+# KGDB configuration options
+#
+# CONFIG_MORE_COMPILE_OPTIONS is not set
+# CONFIG_KGDB_NMI is not set
+# CONFIG_KGDB_THREAD is not set
+# CONFIG_SH_KGDB_CONSOLE is not set
+# CONFIG_KGDB_SYSRQ is not set
+# CONFIG_KGDB_KERNEL_ASSERTS is not set
+
+#
+# Serial port setup
+#
+CONFIG_KGDB_DEFPORT=1
+CONFIG_KGDB_DEFBAUD=115200
+CONFIG_KGDB_DEFPARITY_N=y
+# CONFIG_KGDB_DEFPARITY_E is not set
+# CONFIG_KGDB_DEFPARITY_O is not set
+CONFIG_KGDB_DEFBITS_8=y
+# CONFIG_KGDB_DEFBITS_7 is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
diff --git a/arch/sh/configs/se73180_defconfig b/arch/sh/configs/se73180_defconfig
new file mode 100644
index 000000000000..d217e44c89a6
--- /dev/null
+++ b/arch/sh/configs/se73180_defconfig
@@ -0,0 +1,496 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11-sh
+# Wed Mar 2 15:09:44 2005
+#
+CONFIG_SUPERH=y
+CONFIG_UID16=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_SWAP=y
+# CONFIG_SYSVIPC is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_SYSCTL is not set
+# CONFIG_AUDIT is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_HOTPLUG is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+# CONFIG_KALLSYMS is not set
+# CONFIG_FUTEX is not set
+# CONFIG_EPOLL is not set
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+# CONFIG_MODULE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+# CONFIG_KMOD is not set
+
+#
+# System type
+#
+# CONFIG_SH_SOLUTION_ENGINE is not set
+# CONFIG_SH_7751_SOLUTION_ENGINE is not set
+# CONFIG_SH_7300_SOLUTION_ENGINE is not set
+CONFIG_SH_73180_SOLUTION_ENGINE=y
+# CONFIG_SH_7751_SYSTEMH is not set
+# CONFIG_SH_STB1_HARP is not set
+# CONFIG_SH_STB1_OVERDRIVE is not set
+# CONFIG_SH_HP620 is not set
+# CONFIG_SH_HP680 is not set
+# CONFIG_SH_HP690 is not set
+# CONFIG_SH_CQREEK is not set
+# CONFIG_SH_DMIDA is not set
+# CONFIG_SH_EC3104 is not set
+# CONFIG_SH_SATURN is not set
+# CONFIG_SH_DREAMCAST is not set
+# CONFIG_SH_CAT68701 is not set
+# CONFIG_SH_BIGSUR is not set
+# CONFIG_SH_SH2000 is not set
+# CONFIG_SH_ADX is not set
+# CONFIG_SH_MPC1211 is not set
+# CONFIG_SH_SH03 is not set
+# CONFIG_SH_SECUREEDGE5410 is not set
+# CONFIG_SH_HS7751RVOIP is not set
+# CONFIG_SH_RTS7751R2D is not set
+# CONFIG_SH_EDOSK7705 is not set
+# CONFIG_SH_SH4202_MICRODEV is not set
+# CONFIG_SH_UNKNOWN is not set
+# CONFIG_CPU_SH2 is not set
+# CONFIG_CPU_SH3 is not set
+CONFIG_CPU_SH4=y
+# CONFIG_CPU_SUBTYPE_SH7604 is not set
+# CONFIG_CPU_SUBTYPE_SH7300 is not set
+# CONFIG_CPU_SUBTYPE_SH7705 is not set
+# CONFIG_CPU_SUBTYPE_SH7707 is not set
+# CONFIG_CPU_SUBTYPE_SH7708 is not set
+# CONFIG_CPU_SUBTYPE_SH7709 is not set
+# CONFIG_CPU_SUBTYPE_SH7750 is not set
+# CONFIG_CPU_SUBTYPE_SH7751 is not set
+# CONFIG_CPU_SUBTYPE_SH7760 is not set
+CONFIG_CPU_SUBTYPE_SH73180=y
+# CONFIG_CPU_SUBTYPE_ST40STB1 is not set
+# CONFIG_CPU_SUBTYPE_ST40GX1 is not set
+# CONFIG_CPU_SUBTYPE_SH4_202 is not set
+CONFIG_MMU=y
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="console=ttySC0,38400 root=/dev/ram"
+CONFIG_MEMORY_START=0x0c000000
+CONFIG_MEMORY_SIZE=0x02000000
+# CONFIG_MEMORY_OVERRIDE is not set
+# CONFIG_SH_FPU is not set
+CONFIG_ZERO_PAGE_OFFSET=0x00010000
+CONFIG_BOOT_LINK_OFFSET=0x00800000
+CONFIG_CPU_LITTLE_ENDIAN=y
+# CONFIG_PREEMPT is not set
+# CONFIG_UBC_WAKEUP is not set
+# CONFIG_SH_WRITETHROUGH is not set
+# CONFIG_SH_OCRAM is not set
+# CONFIG_SH_STORE_QUEUES is not set
+# CONFIG_SMP is not set
+# CONFIG_SH_PCLK_CALC is not set
+CONFIG_SH_PCLK_FREQ=27000000
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# DMA support
+#
+# CONFIG_SH_DMA is not set
+
+#
+# Companion Chips
+#
+# CONFIG_HD6446X_SERIES is not set
+CONFIG_HEARTBEAT=y
+
+#
+# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
+#
+# CONFIG_PCI is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PC-card bridges
+#
+
+#
+# PCI Hotplug Support
+#
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_FLAT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# SH initrd options
+#
+CONFIG_EMBEDDED_RAMDISK=y
+CONFIG_EMBEDDED_RAMDISK_IMAGE="ramdisk.gz"
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_LBD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# Networking support
+#
+# CONFIG_NET is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+# CONFIG_INPUT is not set
+
+#
+# Userland interfaces
+#
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+# CONFIG_SERIO is not set
+# CONFIG_SERIO_I8042 is not set
+
+#
+# Input Device Drivers
+#
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_SH_SCI=y
+CONFIG_SERIAL_SH_SCI_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_UNIX98_PTYS is not set
+# CONFIG_LEGACY_PTYS is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+# CONFIG_SH_WDT is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB_ARCH_HAS_HCD is not set
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+
+#
+# XFS support
+#
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+# CONFIG_SYSFS is not set
+CONFIG_DEVFS_FS=y
+CONFIG_DEVFS_MOUNT=y
+# CONFIG_DEVFS_DEBUG is not set
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_XATTR is not set
+# CONFIG_HUGETLBFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_FRAME_POINTER is not set
+CONFIG_SH_STANDARD_BIOS=y
+# CONFIG_EARLY_SCIF_CONSOLE is not set
+# CONFIG_EARLY_PRINTK is not set
+# CONFIG_KGDB is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
diff --git a/arch/sh/configs/se7705_defconfig b/arch/sh/configs/se7705_defconfig
new file mode 100644
index 000000000000..e4a14602b169
--- /dev/null
+++ b/arch/sh/configs/se7705_defconfig
@@ -0,0 +1,714 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11-sh
+# Wed Mar 2 15:09:45 2005
+#
+CONFIG_SUPERH=y
+CONFIG_UID16=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+# CONFIG_SWAP is not set
+# CONFIG_SYSVIPC is not set
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_SYSCTL is not set
+# CONFIG_AUDIT is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_HOTPLUG is not set
+CONFIG_KOBJECT_UEVENT=y
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+# CONFIG_KALLSYMS is not set
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+# CONFIG_MODULE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# System type
+#
+CONFIG_SH_SOLUTION_ENGINE=y
+# CONFIG_SH_7751_SOLUTION_ENGINE is not set
+# CONFIG_SH_7300_SOLUTION_ENGINE is not set
+# CONFIG_SH_73180_SOLUTION_ENGINE is not set
+# CONFIG_SH_7751_SYSTEMH is not set
+# CONFIG_SH_STB1_HARP is not set
+# CONFIG_SH_STB1_OVERDRIVE is not set
+# CONFIG_SH_HP620 is not set
+# CONFIG_SH_HP680 is not set
+# CONFIG_SH_HP690 is not set
+# CONFIG_SH_CQREEK is not set
+# CONFIG_SH_DMIDA is not set
+# CONFIG_SH_EC3104 is not set
+# CONFIG_SH_SATURN is not set
+# CONFIG_SH_DREAMCAST is not set
+# CONFIG_SH_CAT68701 is not set
+# CONFIG_SH_BIGSUR is not set
+# CONFIG_SH_SH2000 is not set
+# CONFIG_SH_ADX is not set
+# CONFIG_SH_MPC1211 is not set
+# CONFIG_SH_SH03 is not set
+# CONFIG_SH_SECUREEDGE5410 is not set
+# CONFIG_SH_HS7751RVOIP is not set
+# CONFIG_SH_RTS7751R2D is not set
+# CONFIG_SH_EDOSK7705 is not set
+# CONFIG_SH_SH4202_MICRODEV is not set
+# CONFIG_SH_UNKNOWN is not set
+# CONFIG_CPU_SH2 is not set
+CONFIG_CPU_SH3=y
+# CONFIG_CPU_SH4 is not set
+# CONFIG_CPU_SUBTYPE_SH7604 is not set
+# CONFIG_CPU_SUBTYPE_SH7300 is not set
+CONFIG_CPU_SUBTYPE_SH7705=y
+# CONFIG_CPU_SUBTYPE_SH7707 is not set
+# CONFIG_CPU_SUBTYPE_SH7708 is not set
+# CONFIG_CPU_SUBTYPE_SH7709 is not set
+# CONFIG_CPU_SUBTYPE_SH7750 is not set
+# CONFIG_CPU_SUBTYPE_SH7751 is not set
+# CONFIG_CPU_SUBTYPE_SH7760 is not set
+# CONFIG_CPU_SUBTYPE_SH73180 is not set
+# CONFIG_CPU_SUBTYPE_ST40STB1 is not set
+# CONFIG_CPU_SUBTYPE_ST40GX1 is not set
+# CONFIG_CPU_SUBTYPE_SH4_202 is not set
+CONFIG_SH7705_CACHE_32KB=y
+CONFIG_MMU=y
+# CONFIG_CMDLINE_BOOL is not set
+CONFIG_MEMORY_START=0x0c000000
+CONFIG_MEMORY_SIZE=0x02000000
+CONFIG_MEMORY_SET=y
+# CONFIG_MEMORY_OVERRIDE is not set
+# CONFIG_CF_ENABLER is not set
+CONFIG_SH_RTC=y
+# CONFIG_SH_DSP is not set
+# CONFIG_SH_ADC is not set
+CONFIG_ZERO_PAGE_OFFSET=0x00001000
+CONFIG_BOOT_LINK_OFFSET=0x00800000
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_PREEMPT=y
+# CONFIG_UBC_WAKEUP is not set
+# CONFIG_SH_WRITETHROUGH is not set
+# CONFIG_SH_OCRAM is not set
+# CONFIG_SMP is not set
+CONFIG_SH_PCLK_CALC=y
+CONFIG_SH_PCLK_FREQ=33333333
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# DMA support
+#
+# CONFIG_SH_DMA is not set
+
+#
+# Companion Chips
+#
+# CONFIG_HD6446X_SERIES is not set
+CONFIG_HEARTBEAT=y
+
+#
+# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
+#
+# CONFIG_PCI is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PC-card bridges
+#
+
+#
+# PCI Hotplug Support
+#
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_FLAT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# SH initrd options
+#
+# CONFIG_EMBEDDED_RAMDISK is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_CONCAT is not set
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_CFI_INTELEXT is not set
+CONFIG_MTD_CFI_AMDSTD=y
+CONFIG_MTD_CFI_AMDSTD_RETRY=0
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PHYSMAP is not set
+CONFIG_MTD_SOLUTIONENGINE=y
+CONFIG_MTD_SUPERH_RESERVE=0x300000
+# CONFIG_MTD_MPC1211 is not set
+# CONFIG_MTD_RTS7751R2D is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLKMTD is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_LBD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+# CONFIG_NETLINK_DEV is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_IP_TCPDIAG=y
+# CONFIG_IP_TCPDIAG_IPV6 is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+CONFIG_STNIC=y
+# CONFIG_SMC91X is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+
+#
+# Token Ring devices
+#
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+CONFIG_PPP=y
+# CONFIG_PPP_MULTILINK is not set
+# CONFIG_PPP_FILTER is not set
+CONFIG_PPP_ASYNC=y
+# CONFIG_PPP_SYNC_TTY is not set
+CONFIG_PPP_DEFLATE=y
+# CONFIG_PPP_BSDCOMP is not set
+# CONFIG_PPPOE is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+# CONFIG_SERIO_SERPORT is not set
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_LIBPS2 is not set
+# CONFIG_SERIO_RAW is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_SH_SCI=y
+CONFIG_SERIAL_SH_SCI_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB_ARCH_HAS_HCD is not set
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+
+#
+# XFS support
+#
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+# CONFIG_SYSFS is not set
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVPTS_FS_XATTR is not set
+# CONFIG_TMPFS is not set
+# CONFIG_HUGETLBFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+# CONFIG_JFFS2_FS_NAND is not set
+# CONFIG_JFFS2_FS_NOR_ECC is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_DEBUG_PREEMPT=y
+# CONFIG_FRAME_POINTER is not set
+# CONFIG_SH_STANDARD_BIOS is not set
+# CONFIG_KGDB is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=y
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
diff --git a/arch/sh/configs/se7750_defconfig b/arch/sh/configs/se7750_defconfig
new file mode 100644
index 000000000000..6dc31584752a
--- /dev/null
+++ b/arch/sh/configs/se7750_defconfig
@@ -0,0 +1,713 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11-sh
+# Wed Mar 2 15:09:46 2005
+#
+CONFIG_SUPERH=y
+CONFIG_UID16=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_HOTPLUG is not set
+CONFIG_KOBJECT_UEVENT=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+# CONFIG_MODULE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# System type
+#
+CONFIG_SH_SOLUTION_ENGINE=y
+# CONFIG_SH_7751_SOLUTION_ENGINE is not set
+# CONFIG_SH_7300_SOLUTION_ENGINE is not set
+# CONFIG_SH_73180_SOLUTION_ENGINE is not set
+# CONFIG_SH_7751_SYSTEMH is not set
+# CONFIG_SH_STB1_HARP is not set
+# CONFIG_SH_STB1_OVERDRIVE is not set
+# CONFIG_SH_HP620 is not set
+# CONFIG_SH_HP680 is not set
+# CONFIG_SH_HP690 is not set
+# CONFIG_SH_CQREEK is not set
+# CONFIG_SH_DMIDA is not set
+# CONFIG_SH_EC3104 is not set
+# CONFIG_SH_SATURN is not set
+# CONFIG_SH_DREAMCAST is not set
+# CONFIG_SH_CAT68701 is not set
+# CONFIG_SH_BIGSUR is not set
+# CONFIG_SH_SH2000 is not set
+# CONFIG_SH_ADX is not set
+# CONFIG_SH_MPC1211 is not set
+# CONFIG_SH_SH03 is not set
+# CONFIG_SH_SECUREEDGE5410 is not set
+# CONFIG_SH_HS7751RVOIP is not set
+# CONFIG_SH_RTS7751R2D is not set
+# CONFIG_SH_EDOSK7705 is not set
+# CONFIG_SH_SH4202_MICRODEV is not set
+# CONFIG_SH_UNKNOWN is not set
+# CONFIG_CPU_SH2 is not set
+# CONFIG_CPU_SH3 is not set
+CONFIG_CPU_SH4=y
+# CONFIG_CPU_SUBTYPE_SH7604 is not set
+# CONFIG_CPU_SUBTYPE_SH7300 is not set
+# CONFIG_CPU_SUBTYPE_SH7705 is not set
+# CONFIG_CPU_SUBTYPE_SH7707 is not set
+# CONFIG_CPU_SUBTYPE_SH7708 is not set
+# CONFIG_CPU_SUBTYPE_SH7709 is not set
+CONFIG_CPU_SUBTYPE_SH7750=y
+# CONFIG_CPU_SUBTYPE_SH7751 is not set
+# CONFIG_CPU_SUBTYPE_SH7760 is not set
+# CONFIG_CPU_SUBTYPE_SH73180 is not set
+# CONFIG_CPU_SUBTYPE_ST40STB1 is not set
+# CONFIG_CPU_SUBTYPE_ST40GX1 is not set
+# CONFIG_CPU_SUBTYPE_SH4_202 is not set
+CONFIG_MMU=y
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="console=ttySC1,38400 root=/dev/nfs ip=bootp"
+CONFIG_MEMORY_START=0x0c000000
+CONFIG_MEMORY_SIZE=0x02000000
+CONFIG_MEMORY_SET=y
+# CONFIG_MEMORY_OVERRIDE is not set
+CONFIG_CF_ENABLER=y
+# CONFIG_CF_AREA5 is not set
+CONFIG_CF_AREA6=y
+CONFIG_CF_BASE_ADDR=0xb8000000
+CONFIG_SH_RTC=y
+CONFIG_SH_FPU=y
+CONFIG_ZERO_PAGE_OFFSET=0x00001000
+CONFIG_BOOT_LINK_OFFSET=0x00800000
+CONFIG_CPU_LITTLE_ENDIAN=y
+# CONFIG_PREEMPT is not set
+# CONFIG_UBC_WAKEUP is not set
+# CONFIG_SH_WRITETHROUGH is not set
+# CONFIG_SH_OCRAM is not set
+# CONFIG_SH_STORE_QUEUES is not set
+# CONFIG_SMP is not set
+CONFIG_SH_PCLK_CALC=y
+CONFIG_SH_PCLK_FREQ=49876504
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# DMA support
+#
+# CONFIG_SH_DMA is not set
+
+#
+# Companion Chips
+#
+# CONFIG_HD6446X_SERIES is not set
+CONFIG_HEARTBEAT=y
+
+#
+# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
+#
+# CONFIG_PCI is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PC-card bridges
+#
+
+#
+# PCI Hotplug Support
+#
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_FLAT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_CONCAT is not set
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_CFI_INTELEXT is not set
+CONFIG_MTD_CFI_AMDSTD=y
+CONFIG_MTD_CFI_AMDSTD_RETRY=0
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+CONFIG_MTD_ROM=y
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PHYSMAP is not set
+CONFIG_MTD_SOLUTIONENGINE=y
+CONFIG_MTD_SUPERH_RESERVE=0x00010000
+# CONFIG_MTD_MPC1211 is not set
+# CONFIG_MTD_RTS7751R2D is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLKMTD is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_RAM is not set
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_LBD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+# CONFIG_NETLINK_DEV is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_IP_TCPDIAG=y
+# CONFIG_IP_TCPDIAG_IPV6 is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+CONFIG_STNIC=y
+# CONFIG_SMC91X is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+
+#
+# Token Ring devices
+#
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+# CONFIG_INPUT is not set
+
+#
+# Userland interfaces
+#
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+# CONFIG_SERIO is not set
+# CONFIG_SERIO_I8042 is not set
+
+#
+# Input Device Drivers
+#
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+# CONFIG_SERIAL_8250_CONSOLE is not set
+CONFIG_SERIAL_8250_NR_UARTS=2
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_SH_SCI=y
+CONFIG_SERIAL_SH_SCI_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_SH_WDT=y
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB_ARCH_HAS_HCD is not set
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# File systems
+#
+# CONFIG_EXT2_FS is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+
+#
+# XFS support
+#
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVPTS_FS_XATTR is not set
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_XATTR is not set
+# CONFIG_HUGETLBFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+# CONFIG_JFFS2_FS_NAND is not set
+# CONFIG_JFFS2_FS_NOR_ECC is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+# CONFIG_MSDOS_PARTITION is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_FRAME_POINTER is not set
+# CONFIG_SH_STANDARD_BIOS is not set
+# CONFIG_EARLY_SCIF_CONSOLE is not set
+# CONFIG_KGDB is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
diff --git a/arch/sh/configs/se7751_defconfig b/arch/sh/configs/se7751_defconfig
new file mode 100644
index 000000000000..1ce028947459
--- /dev/null
+++ b/arch/sh/configs/se7751_defconfig
@@ -0,0 +1,777 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11-sh
+# Wed Mar 2 15:09:48 2005
+#
+CONFIG_SUPERH=y
+CONFIG_UID16=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_HOTPLUG is not set
+CONFIG_KOBJECT_UEVENT=y
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+# CONFIG_MODULE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+# CONFIG_KMOD is not set
+
+#
+# System type
+#
+# CONFIG_SH_SOLUTION_ENGINE is not set
+CONFIG_SH_7751_SOLUTION_ENGINE=y
+# CONFIG_SH_7300_SOLUTION_ENGINE is not set
+# CONFIG_SH_73180_SOLUTION_ENGINE is not set
+# CONFIG_SH_7751_SYSTEMH is not set
+# CONFIG_SH_STB1_HARP is not set
+# CONFIG_SH_STB1_OVERDRIVE is not set
+# CONFIG_SH_HP620 is not set
+# CONFIG_SH_HP680 is not set
+# CONFIG_SH_HP690 is not set
+# CONFIG_SH_CQREEK is not set
+# CONFIG_SH_DMIDA is not set
+# CONFIG_SH_EC3104 is not set
+# CONFIG_SH_SATURN is not set
+# CONFIG_SH_DREAMCAST is not set
+# CONFIG_SH_CAT68701 is not set
+# CONFIG_SH_BIGSUR is not set
+# CONFIG_SH_SH2000 is not set
+# CONFIG_SH_ADX is not set
+# CONFIG_SH_MPC1211 is not set
+# CONFIG_SH_SH03 is not set
+# CONFIG_SH_SECUREEDGE5410 is not set
+# CONFIG_SH_HS7751RVOIP is not set
+# CONFIG_SH_RTS7751R2D is not set
+# CONFIG_SH_EDOSK7705 is not set
+# CONFIG_SH_SH4202_MICRODEV is not set
+# CONFIG_SH_UNKNOWN is not set
+# CONFIG_CPU_SH2 is not set
+# CONFIG_CPU_SH3 is not set
+CONFIG_CPU_SH4=y
+# CONFIG_CPU_SUBTYPE_SH7604 is not set
+# CONFIG_CPU_SUBTYPE_SH7300 is not set
+# CONFIG_CPU_SUBTYPE_SH7705 is not set
+# CONFIG_CPU_SUBTYPE_SH7707 is not set
+# CONFIG_CPU_SUBTYPE_SH7708 is not set
+# CONFIG_CPU_SUBTYPE_SH7709 is not set
+# CONFIG_CPU_SUBTYPE_SH7750 is not set
+CONFIG_CPU_SUBTYPE_SH7751=y
+# CONFIG_CPU_SUBTYPE_SH7760 is not set
+# CONFIG_CPU_SUBTYPE_SH73180 is not set
+# CONFIG_CPU_SUBTYPE_ST40STB1 is not set
+# CONFIG_CPU_SUBTYPE_ST40GX1 is not set
+# CONFIG_CPU_SUBTYPE_SH4_202 is not set
+CONFIG_MMU=y
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="console=ttySC1,38400"
+CONFIG_MEMORY_START=0x0c000000
+CONFIG_MEMORY_SIZE=0x04000000
+CONFIG_MEMORY_SET=y
+# CONFIG_MEMORY_OVERRIDE is not set
+CONFIG_SH_RTC=y
+CONFIG_SH_FPU=y
+CONFIG_ZERO_PAGE_OFFSET=0x00010000
+CONFIG_BOOT_LINK_OFFSET=0x00800000
+CONFIG_CPU_LITTLE_ENDIAN=y
+# CONFIG_PREEMPT is not set
+# CONFIG_UBC_WAKEUP is not set
+# CONFIG_SH_WRITETHROUGH is not set
+# CONFIG_SH_OCRAM is not set
+# CONFIG_SH_STORE_QUEUES is not set
+# CONFIG_SMP is not set
+CONFIG_SH_PCLK_CALC=y
+CONFIG_SH_PCLK_FREQ=60013568
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# DMA support
+#
+# CONFIG_SH_DMA is not set
+
+#
+# Companion Chips
+#
+# CONFIG_HD6446X_SERIES is not set
+CONFIG_HEARTBEAT=y
+
+#
+# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
+#
+CONFIG_PCI=y
+# CONFIG_SH_PCIDMA_NONCOHERENT is not set
+CONFIG_PCI_AUTO=y
+CONFIG_PCI_AUTO_UPDATE_RESOURCES=y
+# CONFIG_PCI_LEGACY_PROC is not set
+# CONFIG_PCI_NAMES is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PC-card bridges
+#
+
+#
+# PCI Hotplug Support
+#
+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_FLAT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# SH initrd options
+#
+# CONFIG_EMBEDDED_RAMDISK is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_CONCAT is not set
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+# CONFIG_MTD_CHAR is not set
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_CFI_INTELEXT is not set
+CONFIG_MTD_CFI_AMDSTD=y
+CONFIG_MTD_CFI_AMDSTD_RETRY=0
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+CONFIG_MTD_RAM=y
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_SOLUTIONENGINE is not set
+# CONFIG_MTD_MPC1211 is not set
+# CONFIG_MTD_RTS7751R2D is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLKMTD is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_LBD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_NETLINK_DEV=y
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_IP_TCPDIAG=y
+# CONFIG_IP_TCPDIAG_IPV6 is not set
+
+#
+# IP: Virtual Server Configuration
+#
+# CONFIG_IP_VS is not set
+# CONFIG_IPV6 is not set
+CONFIG_NETFILTER=y
+CONFIG_NETFILTER_DEBUG=y
+
+#
+# IP: Netfilter Configuration
+#
+# CONFIG_IP_NF_CONNTRACK is not set
+# CONFIG_IP_NF_CONNTRACK_MARK is not set
+CONFIG_IP_NF_QUEUE=y
+# CONFIG_IP_NF_IPTABLES is not set
+# CONFIG_IP_NF_ARPTABLES is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_ETHERTAP is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_STNIC is not set
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_SMC91X is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+CONFIG_NET_PCI=y
+CONFIG_PCNET32=y
+# CONFIG_AMD8111_ETH is not set
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_B44 is not set
+# CONFIG_FORCEDETH is not set
+# CONFIG_DGRS is not set
+# CONFIG_EEPRO100 is not set
+# CONFIG_E100 is not set
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+# CONFIG_8139CP is not set
+# CONFIG_8139TOO is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
+# CONFIG_TIGON3 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+# CONFIG_INPUT is not set
+
+#
+# Userland interfaces
+#
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+# CONFIG_SERIO is not set
+# CONFIG_SERIO_I8042 is not set
+
+#
+# Input Device Drivers
+#
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_SH_SCI is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+# CONFIG_SH_WDT is not set
+
+#
+# PCI-based Watchdog Cards
+#
+# CONFIG_PCIPCWATCHDOG is not set
+# CONFIG_WDTPCI is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+
+#
+# XFS support
+#
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVPTS_FS_XATTR is not set
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_XATTR is not set
+# CONFIG_HUGETLBFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+# CONFIG_JFFS2_FS_NAND is not set
+# CONFIG_JFFS2_FS_NOR_ECC is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+# CONFIG_NFS_FS is not set
+# CONFIG_NFSD is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_FRAME_POINTER is not set
+# CONFIG_SH_STANDARD_BIOS is not set
+# CONFIG_EARLY_SCIF_CONSOLE is not set
+# CONFIG_KGDB is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
diff --git a/arch/sh/configs/sh03_defconfig b/arch/sh/configs/sh03_defconfig
new file mode 100644
index 000000000000..078f78c7fe53
--- /dev/null
+++ b/arch/sh/configs/sh03_defconfig
@@ -0,0 +1,924 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11-sh
+# Wed Mar 2 15:09:49 2005
+#
+CONFIG_SUPERH=y
+CONFIG_UID16=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+# CONFIG_CLEAN_COMPILE is not set
+CONFIG_BROKEN=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_HOTPLUG=y
+CONFIG_KOBJECT_UEVENT=y
+# CONFIG_IKCONFIG is not set
+# CONFIG_EMBEDDED is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_OBSOLETE_MODPARM=y
+CONFIG_MODVERSIONS=y
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# System type
+#
+# CONFIG_SH_SOLUTION_ENGINE is not set
+# CONFIG_SH_7751_SOLUTION_ENGINE is not set
+# CONFIG_SH_7300_SOLUTION_ENGINE is not set
+# CONFIG_SH_73180_SOLUTION_ENGINE is not set
+# CONFIG_SH_7751_SYSTEMH is not set
+# CONFIG_SH_STB1_HARP is not set
+# CONFIG_SH_STB1_OVERDRIVE is not set
+# CONFIG_SH_HP620 is not set
+# CONFIG_SH_HP680 is not set
+# CONFIG_SH_HP690 is not set
+# CONFIG_SH_CQREEK is not set
+# CONFIG_SH_DMIDA is not set
+# CONFIG_SH_EC3104 is not set
+# CONFIG_SH_SATURN is not set
+# CONFIG_SH_DREAMCAST is not set
+# CONFIG_SH_CAT68701 is not set
+# CONFIG_SH_BIGSUR is not set
+# CONFIG_SH_SH2000 is not set
+# CONFIG_SH_ADX is not set
+# CONFIG_SH_MPC1211 is not set
+CONFIG_SH_SH03=y
+# CONFIG_SH_SECUREEDGE5410 is not set
+# CONFIG_SH_HS7751RVOIP is not set
+# CONFIG_SH_RTS7751R2D is not set
+# CONFIG_SH_EDOSK7705 is not set
+# CONFIG_SH_SH4202_MICRODEV is not set
+# CONFIG_SH_UNKNOWN is not set
+# CONFIG_CPU_SH2 is not set
+# CONFIG_CPU_SH3 is not set
+CONFIG_CPU_SH4=y
+# CONFIG_CPU_SUBTYPE_SH7604 is not set
+# CONFIG_CPU_SUBTYPE_SH7300 is not set
+# CONFIG_CPU_SUBTYPE_SH7705 is not set
+# CONFIG_CPU_SUBTYPE_SH7707 is not set
+# CONFIG_CPU_SUBTYPE_SH7708 is not set
+# CONFIG_CPU_SUBTYPE_SH7709 is not set
+# CONFIG_CPU_SUBTYPE_SH7750 is not set
+CONFIG_CPU_SUBTYPE_SH7751=y
+# CONFIG_CPU_SUBTYPE_SH7760 is not set
+# CONFIG_CPU_SUBTYPE_SH73180 is not set
+# CONFIG_CPU_SUBTYPE_ST40STB1 is not set
+# CONFIG_CPU_SUBTYPE_ST40GX1 is not set
+# CONFIG_CPU_SUBTYPE_SH4_202 is not set
+CONFIG_MMU=y
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="console=ttySC1,115200 mem=64M root=/dev/nfs"
+CONFIG_MEMORY_START=0x08000000
+CONFIG_MEMORY_SIZE=0x08000000
+CONFIG_MEMORY_SET=y
+# CONFIG_MEMORY_OVERRIDE is not set
+CONFIG_CF_ENABLER=y
+CONFIG_CF_AREA5=y
+# CONFIG_CF_AREA6 is not set
+CONFIG_CF_BASE_ADDR=0xb4000000
+CONFIG_SH_RTC=y
+CONFIG_SH_FPU=y
+CONFIG_ZERO_PAGE_OFFSET=0x00004000
+CONFIG_BOOT_LINK_OFFSET=0x00800000
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_PREEMPT=y
+# CONFIG_UBC_WAKEUP is not set
+# CONFIG_SH_WRITETHROUGH is not set
+# CONFIG_SH_OCRAM is not set
+# CONFIG_SH_STORE_QUEUES is not set
+# CONFIG_SMP is not set
+CONFIG_SH_PCLK_CALC=y
+CONFIG_SH_PCLK_FREQ=49876504
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# DMA support
+#
+# CONFIG_SH_DMA is not set
+
+#
+# Companion Chips
+#
+# CONFIG_HD6446X_SERIES is not set
+CONFIG_HEARTBEAT=y
+
+#
+# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
+#
+CONFIG_PCI=y
+CONFIG_SH_PCIDMA_NONCOHERENT=y
+CONFIG_PCI_AUTO=y
+CONFIG_PCI_AUTO_UPDATE_RESOURCES=y
+CONFIG_PCI_LEGACY_PROC=y
+CONFIG_PCI_NAMES=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PC-card bridges
+#
+
+#
+# PCI Hotplug Support
+#
+CONFIG_HOTPLUG_PCI=m
+# CONFIG_HOTPLUG_PCI_FAKE is not set
+# CONFIG_HOTPLUG_PCI_CPCI is not set
+# CONFIG_HOTPLUG_PCI_SHPC is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_FLAT is not set
+CONFIG_BINFMT_MISC=y
+
+#
+# SH initrd options
+#
+# CONFIG_EMBEDDED_RAMDISK is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+# CONFIG_STANDALONE is not set
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+# CONFIG_FW_LOADER is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+CONFIG_BLK_DEV_NBD=y
+# CONFIG_BLK_DEV_SX8 is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_LBD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_IDE_MAX_HWIFS=4
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=y
+CONFIG_IDEDISK_MULTI_MODE=y
+CONFIG_BLK_DEV_IDECD=m
+CONFIG_BLK_DEV_IDETAPE=m
+CONFIG_BLK_DEV_IDEFLOPPY=m
+# CONFIG_BLK_DEV_IDESCSI is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+# CONFIG_BLK_DEV_IDEPCI is not set
+CONFIG_IDE_SH=y
+# CONFIG_IDE_ARM is not set
+# CONFIG_BLK_DEV_IDEDMA is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI=m
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=m
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+CONFIG_BLK_DEV_SR=m
+CONFIG_BLK_DEV_SR_VENDOR=y
+CONFIG_CHR_DEV_SG=m
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI Transport Attributes
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_SCSI_ADVANSYS is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_CPQFCTS is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_EATA is not set
+# CONFIG_SCSI_EATA_PIO is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GDTH is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_PCI2000 is not set
+# CONFIG_SCSI_PCI2220I is not set
+# CONFIG_SCSI_QLOGIC_ISP is not set
+# CONFIG_SCSI_QLOGIC_FC is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+CONFIG_SCSI_QLA2XXX=m
+# CONFIG_SCSI_QLA21XX is not set
+# CONFIG_SCSI_QLA22XX is not set
+# CONFIG_SCSI_QLA2300 is not set
+# CONFIG_SCSI_QLA2322 is not set
+# CONFIG_SCSI_QLA6312 is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+# CONFIG_NETLINK_DEV is not set
+CONFIG_UNIX=y
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_IP_TCPDIAG=y
+# CONFIG_IP_TCPDIAG_IPV6 is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_STNIC is not set
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_SMC91X is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+CONFIG_NET_PCI=y
+# CONFIG_PCNET32 is not set
+# CONFIG_AMD8111_ETH is not set
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_B44 is not set
+# CONFIG_FORCEDETH is not set
+# CONFIG_DGRS is not set
+# CONFIG_EEPRO100 is not set
+# CONFIG_E100 is not set
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+CONFIG_8139CP=y
+# CONFIG_8139TOO is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
+# CONFIG_TIGON3 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NET_FC is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+# CONFIG_SERIO is not set
+# CONFIG_SERIO_I8042 is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=m
+CONFIG_SERIAL_8250_NR_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_SH_SCI=y
+CONFIG_SERIAL_SH_SCI_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_SH_WDT=m
+
+#
+# PCI-based Watchdog Cards
+#
+# CONFIG_PCIPCWATCHDOG is not set
+# CONFIG_WDTPCI is not set
+# CONFIG_RTC is not set
+CONFIG_SH03_RTC=y
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+# CONFIG_EXT2_FS_POSIX_ACL is not set
+# CONFIG_EXT2_FS_SECURITY is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+
+#
+# XFS support
+#
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+CONFIG_AUTOFS_FS=y
+CONFIG_AUTOFS4_FS=y
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_ZISOFS_FS=m
+CONFIG_UDF_FS=m
+CONFIG_UDF_NLS=y
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVPTS_FS_XATTR is not set
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_XATTR is not set
+# CONFIG_HUGETLBFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+CONFIG_NFS_V4=y
+# CONFIG_NFS_DIRECTIO is not set
+CONFIG_NFSD=y
+CONFIG_NFSD_V3=y
+# CONFIG_NFSD_V4 is not set
+CONFIG_NFSD_TCP=y
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=y
+CONFIG_SUNRPC=y
+CONFIG_SUNRPC_GSS=y
+CONFIG_RPCSEC_GSS_KRB5=y
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+CONFIG_NLS=m
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=m
+CONFIG_NLS_CODEPAGE_737=m
+CONFIG_NLS_CODEPAGE_775=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_855=m
+CONFIG_NLS_CODEPAGE_857=m
+CONFIG_NLS_CODEPAGE_860=m
+CONFIG_NLS_CODEPAGE_861=m
+CONFIG_NLS_CODEPAGE_862=m
+CONFIG_NLS_CODEPAGE_863=m
+CONFIG_NLS_CODEPAGE_864=m
+CONFIG_NLS_CODEPAGE_865=m
+CONFIG_NLS_CODEPAGE_866=m
+CONFIG_NLS_CODEPAGE_869=m
+CONFIG_NLS_CODEPAGE_936=m
+CONFIG_NLS_CODEPAGE_950=m
+CONFIG_NLS_CODEPAGE_932=m
+CONFIG_NLS_CODEPAGE_949=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_CODEPAGE_1250=m
+CONFIG_NLS_CODEPAGE_1251=m
+CONFIG_NLS_ASCII=m
+CONFIG_NLS_ISO8859_1=m
+CONFIG_NLS_ISO8859_2=m
+CONFIG_NLS_ISO8859_3=m
+CONFIG_NLS_ISO8859_4=m
+CONFIG_NLS_ISO8859_5=m
+CONFIG_NLS_ISO8859_6=m
+CONFIG_NLS_ISO8859_7=m
+CONFIG_NLS_ISO8859_9=m
+CONFIG_NLS_ISO8859_13=m
+CONFIG_NLS_ISO8859_14=m
+CONFIG_NLS_ISO8859_15=m
+CONFIG_NLS_KOI8_R=m
+CONFIG_NLS_KOI8_U=m
+CONFIG_NLS_UTF8=m
+
+#
+# Profiling support
+#
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=m
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_DEBUG_PREEMPT=y
+# CONFIG_FRAME_POINTER is not set
+CONFIG_SH_STANDARD_BIOS=y
+# CONFIG_EARLY_SCIF_CONSOLE is not set
+# CONFIG_EARLY_PRINTK is not set
+# CONFIG_KGDB is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_SHA1=y
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_WP512 is not set
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+CONFIG_CRYPTO_DEFLATE=y
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=y
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
diff --git a/arch/sh/configs/snapgear_defconfig b/arch/sh/configs/snapgear_defconfig
new file mode 100644
index 000000000000..69cf02a24761
--- /dev/null
+++ b/arch/sh/configs/snapgear_defconfig
@@ -0,0 +1,699 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11-sh
+# Wed Mar 2 15:09:51 2005
+#
+CONFIG_SUPERH=y
+CONFIG_UID16=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_SWAP=y
+# CONFIG_SYSVIPC is not set
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_SYSCTL is not set
+# CONFIG_AUDIT is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_HOTPLUG is not set
+CONFIG_KOBJECT_UEVENT=y
+# CONFIG_IKCONFIG is not set
+# CONFIG_EMBEDDED is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+
+#
+# Loadable module support
+#
+# CONFIG_MODULES is not set
+
+#
+# System type
+#
+# CONFIG_SH_SOLUTION_ENGINE is not set
+# CONFIG_SH_7751_SOLUTION_ENGINE is not set
+# CONFIG_SH_7300_SOLUTION_ENGINE is not set
+# CONFIG_SH_73180_SOLUTION_ENGINE is not set
+# CONFIG_SH_7751_SYSTEMH is not set
+# CONFIG_SH_STB1_HARP is not set
+# CONFIG_SH_STB1_OVERDRIVE is not set
+# CONFIG_SH_HP620 is not set
+# CONFIG_SH_HP680 is not set
+# CONFIG_SH_HP690 is not set
+# CONFIG_SH_CQREEK is not set
+# CONFIG_SH_DMIDA is not set
+# CONFIG_SH_EC3104 is not set
+# CONFIG_SH_SATURN is not set
+# CONFIG_SH_DREAMCAST is not set
+# CONFIG_SH_CAT68701 is not set
+# CONFIG_SH_BIGSUR is not set
+# CONFIG_SH_SH2000 is not set
+# CONFIG_SH_ADX is not set
+# CONFIG_SH_MPC1211 is not set
+# CONFIG_SH_SH03 is not set
+CONFIG_SH_SECUREEDGE5410=y
+# CONFIG_SH_HS7751RVOIP is not set
+# CONFIG_SH_RTS7751R2D is not set
+# CONFIG_SH_EDOSK7705 is not set
+# CONFIG_SH_SH4202_MICRODEV is not set
+# CONFIG_SH_UNKNOWN is not set
+# CONFIG_CPU_SH2 is not set
+# CONFIG_CPU_SH3 is not set
+CONFIG_CPU_SH4=y
+# CONFIG_CPU_SUBTYPE_SH7604 is not set
+# CONFIG_CPU_SUBTYPE_SH7300 is not set
+# CONFIG_CPU_SUBTYPE_SH7705 is not set
+# CONFIG_CPU_SUBTYPE_SH7707 is not set
+# CONFIG_CPU_SUBTYPE_SH7708 is not set
+# CONFIG_CPU_SUBTYPE_SH7709 is not set
+# CONFIG_CPU_SUBTYPE_SH7750 is not set
+CONFIG_CPU_SUBTYPE_SH7751=y
+# CONFIG_CPU_SUBTYPE_SH7760 is not set
+# CONFIG_CPU_SUBTYPE_SH73180 is not set
+# CONFIG_CPU_SUBTYPE_ST40STB1 is not set
+# CONFIG_CPU_SUBTYPE_ST40GX1 is not set
+# CONFIG_CPU_SUBTYPE_SH4_202 is not set
+CONFIG_MMU=y
+# CONFIG_CMDLINE_BOOL is not set
+CONFIG_MEMORY_START=0x08000000
+CONFIG_MEMORY_SIZE=0x01000000
+CONFIG_MEMORY_SET=y
+# CONFIG_MEMORY_OVERRIDE is not set
+CONFIG_SH_RTC=y
+CONFIG_SH_FPU=y
+CONFIG_ZERO_PAGE_OFFSET=0x00001000
+CONFIG_BOOT_LINK_OFFSET=0x00800000
+CONFIG_CPU_LITTLE_ENDIAN=y
+# CONFIG_PREEMPT is not set
+# CONFIG_UBC_WAKEUP is not set
+# CONFIG_SH_WRITETHROUGH is not set
+# CONFIG_SH_OCRAM is not set
+# CONFIG_SH_STORE_QUEUES is not set
+# CONFIG_SMP is not set
+CONFIG_SH_PCLK_CALC=y
+CONFIG_SH_PCLK_FREQ=60013568
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# DMA support
+#
+CONFIG_SH_DMA=y
+CONFIG_NR_ONCHIP_DMA_CHANNELS=4
+# CONFIG_NR_DMA_CHANNELS_BOOL is not set
+
+#
+# Companion Chips
+#
+# CONFIG_HD6446X_SERIES is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
+#
+CONFIG_PCI=y
+# CONFIG_SH_PCIDMA_NONCOHERENT is not set
+CONFIG_PCI_AUTO=y
+CONFIG_PCI_AUTO_UPDATE_RESOURCES=y
+# CONFIG_PCI_LEGACY_PROC is not set
+CONFIG_PCI_NAMES=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PC-card bridges
+#
+
+#
+# PCI Hotplug Support
+#
+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_FLAT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# SH initrd options
+#
+# CONFIG_EMBEDDED_RAMDISK is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_LBD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_PACKET is not set
+# CONFIG_NETLINK_DEV is not set
+# CONFIG_UNIX is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_IP_TCPDIAG=y
+# CONFIG_IP_TCPDIAG_IPV6 is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_STNIC is not set
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_SMC91X is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+CONFIG_NET_PCI=y
+# CONFIG_PCNET32 is not set
+# CONFIG_AMD8111_ETH is not set
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_B44 is not set
+# CONFIG_FORCEDETH is not set
+# CONFIG_DGRS is not set
+# CONFIG_EEPRO100 is not set
+# CONFIG_E100 is not set
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+# CONFIG_8139CP is not set
+CONFIG_8139TOO=y
+# CONFIG_8139TOO_PIO is not set
+# CONFIG_8139TOO_TUNE_TWISTER is not set
+# CONFIG_8139TOO_8129 is not set
+# CONFIG_8139_OLD_RX_RESET is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
+# CONFIG_TIGON3 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_PCIPS2 is not set
+# CONFIG_SERIO_RAW is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_SH_SCI is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+CONFIG_VGA_CONSOLE=y
+CONFIG_DUMMY_CONSOLE=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+
+#
+# XFS support
+#
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+CONFIG_ROMFS_FS=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+# CONFIG_PROC_KCORE is not set
+CONFIG_SYSFS=y
+CONFIG_DEVFS_FS=y
+CONFIG_DEVFS_MOUNT=y
+# CONFIG_DEVFS_DEBUG is not set
+# CONFIG_DEVPTS_FS_XATTR is not set
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_XATTR is not set
+# CONFIG_HUGETLBFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_CRAMFS=y
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_FRAME_POINTER is not set
+# CONFIG_SH_STANDARD_BIOS is not set
+# CONFIG_EARLY_SCIF_CONSOLE is not set
+# CONFIG_KGDB is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
diff --git a/arch/sh/configs/systemh_defconfig b/arch/sh/configs/systemh_defconfig
new file mode 100644
index 000000000000..431c9c9da165
--- /dev/null
+++ b/arch/sh/configs/systemh_defconfig
@@ -0,0 +1,509 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11-sh
+# Wed Mar 2 15:09:53 2005
+#
+CONFIG_SUPERH=y
+CONFIG_UID16=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+# CONFIG_CLEAN_COMPILE is not set
+CONFIG_BROKEN=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_SWAP=y
+# CONFIG_SYSVIPC is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_SYSCTL is not set
+# CONFIG_AUDIT is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_HOTPLUG is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+# CONFIG_KMOD is not set
+
+#
+# System type
+#
+# CONFIG_SH_SOLUTION_ENGINE is not set
+# CONFIG_SH_7751_SOLUTION_ENGINE is not set
+# CONFIG_SH_7300_SOLUTION_ENGINE is not set
+# CONFIG_SH_73180_SOLUTION_ENGINE is not set
+CONFIG_SH_7751_SYSTEMH=y
+# CONFIG_SH_STB1_HARP is not set
+# CONFIG_SH_STB1_OVERDRIVE is not set
+# CONFIG_SH_HP620 is not set
+# CONFIG_SH_HP680 is not set
+# CONFIG_SH_HP690 is not set
+# CONFIG_SH_CQREEK is not set
+# CONFIG_SH_DMIDA is not set
+# CONFIG_SH_EC3104 is not set
+# CONFIG_SH_SATURN is not set
+# CONFIG_SH_DREAMCAST is not set
+# CONFIG_SH_CAT68701 is not set
+# CONFIG_SH_BIGSUR is not set
+# CONFIG_SH_SH2000 is not set
+# CONFIG_SH_ADX is not set
+# CONFIG_SH_MPC1211 is not set
+# CONFIG_SH_SH03 is not set
+# CONFIG_SH_SECUREEDGE5410 is not set
+# CONFIG_SH_HS7751RVOIP is not set
+# CONFIG_SH_RTS7751R2D is not set
+# CONFIG_SH_EDOSK7705 is not set
+# CONFIG_SH_SH4202_MICRODEV is not set
+# CONFIG_SH_UNKNOWN is not set
+# CONFIG_CPU_SH2 is not set
+# CONFIG_CPU_SH3 is not set
+CONFIG_CPU_SH4=y
+# CONFIG_CPU_SUBTYPE_SH7604 is not set
+# CONFIG_CPU_SUBTYPE_SH7300 is not set
+# CONFIG_CPU_SUBTYPE_SH7705 is not set
+# CONFIG_CPU_SUBTYPE_SH7707 is not set
+# CONFIG_CPU_SUBTYPE_SH7708 is not set
+# CONFIG_CPU_SUBTYPE_SH7709 is not set
+# CONFIG_CPU_SUBTYPE_SH7750 is not set
+CONFIG_CPU_SUBTYPE_SH7751=y
+# CONFIG_CPU_SUBTYPE_SH7760 is not set
+# CONFIG_CPU_SUBTYPE_SH73180 is not set
+# CONFIG_CPU_SUBTYPE_ST40STB1 is not set
+# CONFIG_CPU_SUBTYPE_ST40GX1 is not set
+# CONFIG_CPU_SUBTYPE_SH4_202 is not set
+CONFIG_MMU=y
+# CONFIG_CMDLINE_BOOL is not set
+CONFIG_MEMORY_START=0x0c000000
+CONFIG_MEMORY_SIZE=0x00400000
+# CONFIG_MEMORY_OVERRIDE is not set
+CONFIG_SH_RTC=y
+CONFIG_SH_FPU=y
+CONFIG_ZERO_PAGE_OFFSET=0x00001000
+CONFIG_BOOT_LINK_OFFSET=0x00800000
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_PREEMPT=y
+# CONFIG_UBC_WAKEUP is not set
+# CONFIG_SH_WRITETHROUGH is not set
+# CONFIG_SH_OCRAM is not set
+# CONFIG_SH_STORE_QUEUES is not set
+# CONFIG_SMP is not set
+CONFIG_SH_PCLK_CALC=y
+CONFIG_SH_PCLK_FREQ=49876504
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# DMA support
+#
+# CONFIG_SH_DMA is not set
+
+#
+# Companion Chips
+#
+# CONFIG_HD6446X_SERIES is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
+#
+CONFIG_PCI=y
+# CONFIG_SH_PCIDMA_NONCOHERENT is not set
+CONFIG_PCI_AUTO=y
+CONFIG_PCI_AUTO_UPDATE_RESOURCES=y
+CONFIG_PCI_LEGACY_PROC=y
+CONFIG_PCI_NAMES=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PC-card bridges
+#
+
+#
+# PCI Hotplug Support
+#
+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_FLAT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# SH initrd options
+#
+# CONFIG_EMBEDDED_RAMDISK is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+# CONFIG_STANDALONE is not set
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_SX8 is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=1024
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_LBD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Networking support
+#
+# CONFIG_NET is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+# CONFIG_INPUT is not set
+
+#
+# Userland interfaces
+#
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+# CONFIG_SERIO_SERPORT is not set
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_PCIPS2 is not set
+# CONFIG_SERIO_LIBPS2 is not set
+# CONFIG_SERIO_RAW is not set
+
+#
+# Input Device Drivers
+#
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_SH_SCI is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# File systems
+#
+# CONFIG_EXT2_FS is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+
+#
+# XFS support
+#
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+CONFIG_ROMFS_FS=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+CONFIG_DEVFS_FS=y
+CONFIG_DEVFS_MOUNT=y
+# CONFIG_DEVFS_DEBUG is not set
+# CONFIG_DEVPTS_FS_XATTR is not set
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_XATTR is not set
+# CONFIG_HUGETLBFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_CRAMFS=y
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_DEBUG_PREEMPT=y
+# CONFIG_FRAME_POINTER is not set
+# CONFIG_SH_STANDARD_BIOS is not set
+# CONFIG_EARLY_SCIF_CONSOLE is not set
+# CONFIG_KGDB is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
diff --git a/arch/sh/drivers/Makefile b/arch/sh/drivers/Makefile
new file mode 100644
index 000000000000..bd6726cde398
--- /dev/null
+++ b/arch/sh/drivers/Makefile
@@ -0,0 +1,7 @@
+#
+# Makefile for the Linux SuperH-specific device drivers.
+#
+
+obj-$(CONFIG_PCI) += pci/
+obj-$(CONFIG_SH_DMA) += dma/
+
diff --git a/arch/sh/drivers/dma/Kconfig b/arch/sh/drivers/dma/Kconfig
new file mode 100644
index 000000000000..0f15216cd39d
--- /dev/null
+++ b/arch/sh/drivers/dma/Kconfig
@@ -0,0 +1,55 @@
+menu "DMA support"
+
+config SH_DMA
+ bool "DMA controller (DMAC) support"
+ help
+ Selecting this option will provide same API as PC's Direct Memory
+ Access Controller(8237A) for SuperH DMAC.
+
+ If unsure, say N.
+
+config NR_ONCHIP_DMA_CHANNELS
+ depends on SH_DMA
+ int "Number of on-chip DMAC channels"
+ default "4"
+ help
+ This allows you to specify the number of channels that the on-chip
+ DMAC supports. This will be 4 for SH7750/SH7751 and 8 for the
+ SH7750R/SH7751R.
+
+config NR_DMA_CHANNELS_BOOL
+ depends on SH_DMA
+ bool "Override default number of maximum DMA channels"
+ help
+ This allows you to forcibly update the maximum number of supported
+ DMA channels for a given board. If this is unset, this will default
+ to the number of channels that the on-chip DMAC has.
+
+config NR_DMA_CHANNELS
+ int "Maximum number of DMA channels"
+ depends on SH_DMA && NR_DMA_CHANNELS_BOOL
+ default NR_ONCHIP_DMA_CHANNELS
+ help
+ This allows you to specify the maximum number of DMA channels to
+ support. Setting this to a higher value allows for cascading DMACs
+ with additional channels.
+
+config DMA_PAGE_OPS
+ bool "Use DMAC for page copy/clear"
+ depends on SH_DMA && BROKEN
+ help
+ Selecting this option will use a dual-address mode configured channel
+ in the SH DMAC for copy_page()/clear_page(). Primarily a performance
+ hack.
+
+config DMA_PAGE_OPS_CHANNEL
+ depends on DMA_PAGE_OPS
+ int "DMA channel for sh memory-manager page copy/clear"
+ default "3"
+ help
+ This allows the specification of the dual address dma channel,
+ in case channel 3 is unavailable. On the SH4, channels 1,2, and 3
+ are dual-address capable.
+
+endmenu
+
diff --git a/arch/sh/drivers/dma/Makefile b/arch/sh/drivers/dma/Makefile
new file mode 100644
index 000000000000..065d4c90970e
--- /dev/null
+++ b/arch/sh/drivers/dma/Makefile
@@ -0,0 +1,9 @@
+#
+# Makefile for the SuperH DMA specific kernel interface routines under Linux.
+#
+
+obj-y += dma-api.o dma-isa.o
+obj-$(CONFIG_SYSFS) += dma-sysfs.o
+obj-$(CONFIG_SH_DMA) += dma-sh.o
+obj-$(CONFIG_SH_DREAMCAST) += dma-pvr2.o dma-g2.o
+
diff --git a/arch/sh/drivers/dma/dma-api.c b/arch/sh/drivers/dma/dma-api.c
new file mode 100644
index 000000000000..96e3036ec2bb
--- /dev/null
+++ b/arch/sh/drivers/dma/dma-api.c
@@ -0,0 +1,292 @@
+/*
+ * arch/sh/drivers/dma/dma-api.c
+ *
+ * SuperH-specific DMA management API
+ *
+ * Copyright (C) 2003, 2004 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/spinlock.h>
+#include <linux/proc_fs.h>
+#include <linux/list.h>
+#include <asm/dma.h>
+
+DEFINE_SPINLOCK(dma_spin_lock);
+static LIST_HEAD(registered_dmac_list);
+
+/*
+ * A brief note about the reasons for this API as it stands.
+ *
+ * For starters, the old ISA DMA API didn't work for us for a number of
+ * reasons, for one, the vast majority of channels on the SH DMAC are
+ * dual-address mode only, and both the new and the old DMA APIs are after the
+ * concept of managing a DMA buffer, which doesn't overly fit this model very
+ * well. In addition to which, the new API is largely geared at IOMMUs and
+ * GARTs, and doesn't even support the channel notion very well.
+ *
+ * The other thing that's a marginal issue, is the sheer number of random DMA
+ * engines that are present (ie, in boards like the Dreamcast), some of which
+ * cascade off of the SH DMAC, and others do not. As such, there was a real
+ * need for a scalable subsystem that could deal with both single and
+ * dual-address mode usage, in addition to interoperating with cascaded DMACs.
+ *
+ * There really isn't any reason why this needs to be SH specific, though I'm
+ * not aware of too many other processors (with the exception of some MIPS)
+ * that have the same concept of a dual address mode, or any real desire to
+ * actually make use of the DMAC even if such a subsystem were exposed
+ * elsewhere.
+ *
+ * The idea for this was derived from the ARM port, which acted as an excellent
+ * reference when trying to address these issues.
+ *
+ * It should also be noted that the decision to add Yet Another DMA API(tm) to
+ * the kernel wasn't made easily, and was only decided upon after conferring
+ * with jejb with regards to the state of the old and new APIs as they applied
+ * to these circumstances. Philip Blundell was also a great help in figuring
+ * out some single-address mode DMA semantics that were otherwise rather
+ * confusing.
+ */
+
+struct dma_info *get_dma_info(unsigned int chan)
+{
+ struct list_head *pos, *tmp;
+ unsigned int total = 0;
+
+ /*
+ * Look for each DMAC's range to determine who the owner of
+ * the channel is.
+ */
+ list_for_each_safe(pos, tmp, &registered_dmac_list) {
+ struct dma_info *info = list_entry(pos, struct dma_info, list);
+
+ total += info->nr_channels;
+ if (chan > total)
+ continue;
+
+ return info;
+ }
+
+ return NULL;
+}
+
+struct dma_channel *get_dma_channel(unsigned int chan)
+{
+ struct dma_info *info = get_dma_info(chan);
+
+ if (!info)
+ return ERR_PTR(-EINVAL);
+
+ return info->channels + chan;
+}
+
+int get_dma_residue(unsigned int chan)
+{
+ struct dma_info *info = get_dma_info(chan);
+ struct dma_channel *channel = &info->channels[chan];
+
+ if (info->ops->get_residue)
+ return info->ops->get_residue(channel);
+
+ return 0;
+}
+
+int request_dma(unsigned int chan, const char *dev_id)
+{
+ struct dma_info *info = get_dma_info(chan);
+ struct dma_channel *channel = &info->channels[chan];
+
+ down(&channel->sem);
+
+ if (!info->ops || chan >= MAX_DMA_CHANNELS) {
+ up(&channel->sem);
+ return -EINVAL;
+ }
+
+ atomic_set(&channel->busy, 1);
+
+ strlcpy(channel->dev_id, dev_id, sizeof(channel->dev_id));
+
+ up(&channel->sem);
+
+ if (info->ops->request)
+ return info->ops->request(channel);
+
+ return 0;
+}
+
+void free_dma(unsigned int chan)
+{
+ struct dma_info *info = get_dma_info(chan);
+ struct dma_channel *channel = &info->channels[chan];
+
+ if (info->ops->free)
+ info->ops->free(channel);
+
+ atomic_set(&channel->busy, 0);
+}
+
+void dma_wait_for_completion(unsigned int chan)
+{
+ struct dma_info *info = get_dma_info(chan);
+ struct dma_channel *channel = &info->channels[chan];
+
+ if (channel->flags & DMA_TEI_CAPABLE) {
+ wait_event(channel->wait_queue,
+ (info->ops->get_residue(channel) == 0));
+ return;
+ }
+
+ while (info->ops->get_residue(channel))
+ cpu_relax();
+}
+
+void dma_configure_channel(unsigned int chan, unsigned long flags)
+{
+ struct dma_info *info = get_dma_info(chan);
+ struct dma_channel *channel = &info->channels[chan];
+
+ if (info->ops->configure)
+ info->ops->configure(channel, flags);
+}
+
+int dma_xfer(unsigned int chan, unsigned long from,
+ unsigned long to, size_t size, unsigned int mode)
+{
+ struct dma_info *info = get_dma_info(chan);
+ struct dma_channel *channel = &info->channels[chan];
+
+ channel->sar = from;
+ channel->dar = to;
+ channel->count = size;
+ channel->mode = mode;
+
+ return info->ops->xfer(channel);
+}
+
+#ifdef CONFIG_PROC_FS
+static int dma_read_proc(char *buf, char **start, off_t off,
+ int len, int *eof, void *data)
+{
+ struct list_head *pos, *tmp;
+ char *p = buf;
+
+ if (list_empty(&registered_dmac_list))
+ return 0;
+
+ /*
+ * Iterate over each registered DMAC
+ */
+ list_for_each_safe(pos, tmp, &registered_dmac_list) {
+ struct dma_info *info = list_entry(pos, struct dma_info, list);
+ int i;
+
+ /*
+ * Iterate over each channel
+ */
+ for (i = 0; i < info->nr_channels; i++) {
+ struct dma_channel *channel = info->channels + i;
+
+ if (!(channel->flags & DMA_CONFIGURED))
+ continue;
+
+ p += sprintf(p, "%2d: %14s %s\n", i,
+ info->name, channel->dev_id);
+ }
+ }
+
+ return p - buf;
+}
+#endif
+
+
+int __init register_dmac(struct dma_info *info)
+{
+ int i;
+
+ INIT_LIST_HEAD(&info->list);
+
+ printk(KERN_INFO "DMA: Registering %s handler (%d channel%s).\n",
+ info->name, info->nr_channels,
+ info->nr_channels > 1 ? "s" : "");
+
+ BUG_ON((info->flags & DMAC_CHANNELS_CONFIGURED) && !info->channels);
+
+ /*
+ * Don't touch pre-configured channels
+ */
+ if (!(info->flags & DMAC_CHANNELS_CONFIGURED)) {
+ unsigned int size;
+
+ size = sizeof(struct dma_channel) * info->nr_channels;
+
+ info->channels = kmalloc(size, GFP_KERNEL);
+ if (!info->channels)
+ return -ENOMEM;
+
+ memset(info->channels, 0, size);
+ }
+
+ for (i = 0; i < info->nr_channels; i++) {
+ struct dma_channel *chan = info->channels + i;
+
+ chan->chan = i;
+
+ memcpy(chan->dev_id, "Unused", 7);
+
+ if (info->flags & DMAC_CHANNELS_TEI_CAPABLE)
+ chan->flags |= DMA_TEI_CAPABLE;
+
+ init_MUTEX(&chan->sem);
+ init_waitqueue_head(&chan->wait_queue);
+
+#ifdef CONFIG_SYSFS
+ dma_create_sysfs_files(chan);
+#endif
+ }
+
+ list_add(&info->list, &registered_dmac_list);
+
+ return 0;
+}
+
+void __exit unregister_dmac(struct dma_info *info)
+{
+ if (!(info->flags & DMAC_CHANNELS_CONFIGURED))
+ kfree(info->channels);
+
+ list_del(&info->list);
+}
+
+static int __init dma_api_init(void)
+{
+ printk("DMA: Registering DMA API.\n");
+
+#ifdef CONFIG_PROC_FS
+ create_proc_read_entry("dma", 0, 0, dma_read_proc, 0);
+#endif
+
+ return 0;
+}
+
+subsys_initcall(dma_api_init);
+
+MODULE_AUTHOR("Paul Mundt <lethal@linux-sh.org>");
+MODULE_DESCRIPTION("DMA API for SuperH");
+MODULE_LICENSE("GPL");
+
+EXPORT_SYMBOL(request_dma);
+EXPORT_SYMBOL(free_dma);
+EXPORT_SYMBOL(register_dmac);
+EXPORT_SYMBOL(get_dma_residue);
+EXPORT_SYMBOL(get_dma_info);
+EXPORT_SYMBOL(get_dma_channel);
+EXPORT_SYMBOL(dma_xfer);
+EXPORT_SYMBOL(dma_wait_for_completion);
+EXPORT_SYMBOL(dma_configure_channel);
+
diff --git a/arch/sh/drivers/dma/dma-g2.c b/arch/sh/drivers/dma/dma-g2.c
new file mode 100644
index 000000000000..231e3f6fb28f
--- /dev/null
+++ b/arch/sh/drivers/dma/dma-g2.c
@@ -0,0 +1,171 @@
+/*
+ * arch/sh/drivers/dma/dma-g2.c
+ *
+ * G2 bus DMA support
+ *
+ * Copyright (C) 2003, 2004 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/kernel.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+
+#include <asm/mach/sysasic.h>
+#include <asm/mach/dma.h>
+#include <asm/dma.h>
+
+struct g2_channel {
+ unsigned long g2_addr; /* G2 bus address */
+ unsigned long root_addr; /* Root bus (SH-4) address */
+ unsigned long size; /* Size (in bytes), 32-byte aligned */
+ unsigned long direction; /* Transfer direction */
+ unsigned long ctrl; /* Transfer control */
+ unsigned long chan_enable; /* Channel enable */
+ unsigned long xfer_enable; /* Transfer enable */
+ unsigned long xfer_stat; /* Transfer status */
+} __attribute__ ((aligned(32)));
+
+struct g2_status {
+ unsigned long g2_addr;
+ unsigned long root_addr;
+ unsigned long size;
+ unsigned long status;
+} __attribute__ ((aligned(16)));
+
+struct g2_dma_info {
+ struct g2_channel channel[G2_NR_DMA_CHANNELS];
+ unsigned long pad1[G2_NR_DMA_CHANNELS];
+ unsigned long wait_state;
+ unsigned long pad2[10];
+ unsigned long magic;
+ struct g2_status status[G2_NR_DMA_CHANNELS];
+} __attribute__ ((aligned(256)));
+
+static volatile struct g2_dma_info *g2_dma = (volatile struct g2_dma_info *)0xa05f7800;
+
+static irqreturn_t g2_dma_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ /* FIXME: Do some meaningful completion work here.. */
+ return IRQ_HANDLED;
+}
+
+static struct irqaction g2_dma_irq = {
+ .name = "g2 DMA handler",
+ .handler = g2_dma_interrupt,
+ .flags = SA_INTERRUPT,
+};
+
+static int g2_enable_dma(struct dma_channel *chan)
+{
+ unsigned int chan_nr = chan->chan;
+
+ g2_dma->channel[chan_nr].chan_enable = 1;
+ g2_dma->channel[chan_nr].xfer_enable = 1;
+
+ return 0;
+}
+
+static int g2_disable_dma(struct dma_channel *chan)
+{
+ unsigned int chan_nr = chan->chan;
+
+ g2_dma->channel[chan_nr].chan_enable = 0;
+ g2_dma->channel[chan_nr].xfer_enable = 0;
+
+ return 0;
+}
+
+static int g2_xfer_dma(struct dma_channel *chan)
+{
+ unsigned int chan_nr = chan->chan;
+
+ if (chan->sar & 31) {
+ printk("g2dma: unaligned source 0x%lx\n", chan->sar);
+ return -EINVAL;
+ }
+
+ if (chan->dar & 31) {
+ printk("g2dma: unaligned dest 0x%lx\n", chan->dar);
+ return -EINVAL;
+ }
+
+ /* Align the count */
+ if (chan->count & 31)
+ chan->count = (chan->count + (32 - 1)) & ~(32 - 1);
+
+ /* Fixup destination */
+ chan->dar += 0xa0800000;
+
+ /* Fixup direction */
+ chan->mode = !chan->mode;
+
+ flush_icache_range((unsigned long)chan->sar, chan->count);
+
+ g2_disable_dma(chan);
+
+ g2_dma->channel[chan_nr].g2_addr = chan->dar & 0x1fffffe0;
+ g2_dma->channel[chan_nr].root_addr = chan->sar & 0x1fffffe0;
+ g2_dma->channel[chan_nr].size = (chan->count & ~31) | 0x80000000;
+ g2_dma->channel[chan_nr].direction = chan->mode;
+
+ /*
+ * bit 0 - ???
+ * bit 1 - if set, generate a hardware event on transfer completion
+ * bit 2 - ??? something to do with suspend?
+ */
+ g2_dma->channel[chan_nr].ctrl = 5; /* ?? */
+
+ g2_enable_dma(chan);
+
+ /* debug cruft */
+ pr_debug("count, sar, dar, mode, ctrl, chan, xfer: %ld, 0x%08lx, "
+ "0x%08lx, %ld, %ld, %ld, %ld\n",
+ g2_dma->channel[chan_nr].size,
+ g2_dma->channel[chan_nr].root_addr,
+ g2_dma->channel[chan_nr].g2_addr,
+ g2_dma->channel[chan_nr].direction,
+ g2_dma->channel[chan_nr].ctrl,
+ g2_dma->channel[chan_nr].chan_enable,
+ g2_dma->channel[chan_nr].xfer_enable);
+
+ return 0;
+}
+
+static struct dma_ops g2_dma_ops = {
+ .xfer = g2_xfer_dma,
+};
+
+static struct dma_info g2_dma_info = {
+ .name = "G2 DMA",
+ .nr_channels = 4,
+ .ops = &g2_dma_ops,
+ .flags = DMAC_CHANNELS_TEI_CAPABLE,
+};
+
+static int __init g2_dma_init(void)
+{
+ setup_irq(HW_EVENT_G2_DMA, &g2_dma_irq);
+
+ /* Magic */
+ g2_dma->wait_state = 27;
+ g2_dma->magic = 0x4659404f;
+
+ return register_dmac(&g2_dma_info);
+}
+
+static void __exit g2_dma_exit(void)
+{
+ free_irq(HW_EVENT_G2_DMA, 0);
+}
+
+subsys_initcall(g2_dma_init);
+module_exit(g2_dma_exit);
+
+MODULE_AUTHOR("Paul Mundt <lethal@linux-sh.org>");
+MODULE_DESCRIPTION("G2 bus DMA driver");
+MODULE_LICENSE("GPL");
+
diff --git a/arch/sh/drivers/dma/dma-isa.c b/arch/sh/drivers/dma/dma-isa.c
new file mode 100644
index 000000000000..1c9bc45b8bcb
--- /dev/null
+++ b/arch/sh/drivers/dma/dma-isa.c
@@ -0,0 +1,106 @@
+/*
+ * arch/sh/drivers/dma/dma-isa.c
+ *
+ * Generic ISA DMA wrapper for SH DMA API
+ *
+ * Copyright (C) 2003, 2004 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/kernel.h>
+#include <linux/module.h>
+#include <asm/dma.h>
+
+/*
+ * This implements a small wrapper set to make code using the old ISA DMA API
+ * work with the SH DMA API. Since most of the work in the new API happens
+ * at ops->xfer() time, we simply use the various set_dma_xxx() routines to
+ * fill in per-channel info, and then hand hand this off to ops->xfer() at
+ * enable_dma() time.
+ *
+ * For channels that are doing on-demand data transfer via cascading, the
+ * channel itself will still need to be configured through the new API. As
+ * such, this code is meant for only the simplest of tasks (and shouldn't be
+ * used in any new drivers at all).
+ *
+ * It should also be noted that various functions here are labelled as
+ * being deprecated. This is due to the fact that the ops->xfer() method is
+ * the preferred way of doing things (as well as just grabbing the spinlock
+ * directly). As such, any users of this interface will be warned rather
+ * loudly.
+ */
+
+unsigned long __deprecated claim_dma_lock(void)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&dma_spin_lock, flags);
+
+ return flags;
+}
+EXPORT_SYMBOL(claim_dma_lock);
+
+void __deprecated release_dma_lock(unsigned long flags)
+{
+ spin_unlock_irqrestore(&dma_spin_lock, flags);
+}
+EXPORT_SYMBOL(release_dma_lock);
+
+void __deprecated disable_dma(unsigned int chan)
+{
+ /* Nothing */
+}
+EXPORT_SYMBOL(disable_dma);
+
+void __deprecated enable_dma(unsigned int chan)
+{
+ struct dma_info *info = get_dma_info(chan);
+ struct dma_channel *channel = &info->channels[chan];
+
+ info->ops->xfer(channel);
+}
+EXPORT_SYMBOL(enable_dma);
+
+void clear_dma_ff(unsigned int chan)
+{
+ /* Nothing */
+}
+EXPORT_SYMBOL(clear_dma_ff);
+
+void set_dma_mode(unsigned int chan, char mode)
+{
+ struct dma_info *info = get_dma_info(chan);
+ struct dma_channel *channel = &info->channels[chan];
+
+ channel->mode = mode;
+}
+EXPORT_SYMBOL(set_dma_mode);
+
+void set_dma_addr(unsigned int chan, unsigned int addr)
+{
+ struct dma_info *info = get_dma_info(chan);
+ struct dma_channel *channel = &info->channels[chan];
+
+ /*
+ * Single address mode is the only thing supported through
+ * this interface.
+ */
+ if ((channel->mode & DMA_MODE_MASK) == DMA_MODE_READ) {
+ channel->sar = addr;
+ } else {
+ channel->dar = addr;
+ }
+}
+EXPORT_SYMBOL(set_dma_addr);
+
+void set_dma_count(unsigned int chan, unsigned int count)
+{
+ struct dma_info *info = get_dma_info(chan);
+ struct dma_channel *channel = &info->channels[chan];
+
+ channel->count = count;
+}
+EXPORT_SYMBOL(set_dma_count);
+
diff --git a/arch/sh/drivers/dma/dma-pvr2.c b/arch/sh/drivers/dma/dma-pvr2.c
new file mode 100644
index 000000000000..2e1d58f2d1b9
--- /dev/null
+++ b/arch/sh/drivers/dma/dma-pvr2.c
@@ -0,0 +1,109 @@
+/*
+ * arch/sh/boards/dreamcast/dma-pvr2.c
+ *
+ * NEC PowerVR 2 (Dreamcast) DMA support
+ *
+ * Copyright (C) 2003, 2004 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/kernel.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <asm/mach/sysasic.h>
+#include <asm/mach/dma.h>
+#include <asm/dma.h>
+#include <asm/io.h>
+
+static unsigned int xfer_complete = 0;
+static int count = 0;
+
+static irqreturn_t pvr2_dma_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ if (get_dma_residue(PVR2_CASCADE_CHAN)) {
+ printk(KERN_WARNING "DMA: SH DMAC did not complete transfer "
+ "on channel %d, waiting..\n", PVR2_CASCADE_CHAN);
+ dma_wait_for_completion(PVR2_CASCADE_CHAN);
+ }
+
+ if (count++ < 10)
+ pr_debug("Got a pvr2 dma interrupt for channel %d\n",
+ irq - HW_EVENT_PVR2_DMA);
+
+ xfer_complete = 1;
+
+ return IRQ_HANDLED;
+}
+
+static int pvr2_request_dma(struct dma_channel *chan)
+{
+ if (ctrl_inl(PVR2_DMA_MODE) != 0)
+ return -EBUSY;
+
+ ctrl_outl(0, PVR2_DMA_LMMODE0);
+
+ return 0;
+}
+
+static int pvr2_get_dma_residue(struct dma_channel *chan)
+{
+ return xfer_complete == 0;
+}
+
+static int pvr2_xfer_dma(struct dma_channel *chan)
+{
+ if (chan->sar || !chan->dar)
+ return -EINVAL;
+
+ xfer_complete = 0;
+
+ ctrl_outl(chan->dar, PVR2_DMA_ADDR);
+ ctrl_outl(chan->count, PVR2_DMA_COUNT);
+ ctrl_outl(chan->mode & DMA_MODE_MASK, PVR2_DMA_MODE);
+
+ return 0;
+}
+
+static struct irqaction pvr2_dma_irq = {
+ .name = "pvr2 DMA handler",
+ .handler = pvr2_dma_interrupt,
+ .flags = SA_INTERRUPT,
+};
+
+static struct dma_ops pvr2_dma_ops = {
+ .request = pvr2_request_dma,
+ .get_residue = pvr2_get_dma_residue,
+ .xfer = pvr2_xfer_dma,
+};
+
+static struct dma_info pvr2_dma_info = {
+ .name = "PowerVR 2 DMA",
+ .nr_channels = 1,
+ .ops = &pvr2_dma_ops,
+ .flags = DMAC_CHANNELS_TEI_CAPABLE,
+};
+
+static int __init pvr2_dma_init(void)
+{
+ setup_irq(HW_EVENT_PVR2_DMA, &pvr2_dma_irq);
+ request_dma(PVR2_CASCADE_CHAN, "pvr2 cascade");
+
+ return register_dmac(&pvr2_dma_info);
+}
+
+static void __exit pvr2_dma_exit(void)
+{
+ free_dma(PVR2_CASCADE_CHAN);
+ free_irq(HW_EVENT_PVR2_DMA, 0);
+}
+
+subsys_initcall(pvr2_dma_init);
+module_exit(pvr2_dma_exit);
+
+MODULE_AUTHOR("Paul Mundt <lethal@linux-sh.org>");
+MODULE_DESCRIPTION("NEC PowerVR 2 DMA driver");
+MODULE_LICENSE("GPL");
+
diff --git a/arch/sh/drivers/dma/dma-sh.c b/arch/sh/drivers/dma/dma-sh.c
new file mode 100644
index 000000000000..31dacd4444b2
--- /dev/null
+++ b/arch/sh/drivers/dma/dma-sh.c
@@ -0,0 +1,267 @@
+/*
+ * arch/sh/drivers/dma/dma-sh.c
+ *
+ * SuperH On-chip DMAC Support
+ *
+ * Copyright (C) 2000 Takashi YOSHII
+ * Copyright (C) 2003, 2004 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/config.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <asm/signal.h>
+#include <asm/irq.h>
+#include <asm/dma.h>
+#include <asm/io.h>
+#include "dma-sh.h"
+
+/*
+ * The SuperH DMAC supports a number of transmit sizes, we list them here,
+ * with their respective values as they appear in the CHCR registers.
+ *
+ * Defaults to a 64-bit transfer size.
+ */
+enum {
+ XMIT_SZ_64BIT,
+ XMIT_SZ_8BIT,
+ XMIT_SZ_16BIT,
+ XMIT_SZ_32BIT,
+ XMIT_SZ_256BIT,
+};
+
+/*
+ * The DMA count is defined as the number of bytes to transfer.
+ */
+static unsigned int ts_shift[] = {
+ [XMIT_SZ_64BIT] = 3,
+ [XMIT_SZ_8BIT] = 0,
+ [XMIT_SZ_16BIT] = 1,
+ [XMIT_SZ_32BIT] = 2,
+ [XMIT_SZ_256BIT] = 5,
+};
+
+static inline unsigned int get_dmte_irq(unsigned int chan)
+{
+ unsigned int irq;
+
+ /*
+ * Normally we could just do DMTE0_IRQ + chan outright, though in the
+ * case of the 7751R, the DMTE IRQs for channels > 4 start right above
+ * the SCIF
+ */
+
+ if (chan < 4) {
+ irq = DMTE0_IRQ + chan;
+ } else {
+ irq = DMTE4_IRQ + chan - 4;
+ }
+
+ return irq;
+}
+
+/*
+ * We determine the correct shift size based off of the CHCR transmit size
+ * for the given channel. Since we know that it will take:
+ *
+ * info->count >> ts_shift[transmit_size]
+ *
+ * iterations to complete the transfer.
+ */
+static inline unsigned int calc_xmit_shift(struct dma_channel *chan)
+{
+ u32 chcr = ctrl_inl(CHCR[chan->chan]);
+
+ chcr >>= 4;
+
+ return ts_shift[chcr & 0x0007];
+}
+
+/*
+ * The transfer end interrupt must read the chcr register to end the
+ * hardware interrupt active condition.
+ * Besides that it needs to waken any waiting process, which should handle
+ * setting up the next transfer.
+ */
+static irqreturn_t dma_tei(int irq, void *dev_id, struct pt_regs *regs)
+{
+ struct dma_channel *chan = (struct dma_channel *)dev_id;
+ u32 chcr;
+
+ chcr = ctrl_inl(CHCR[chan->chan]);
+
+ if (!(chcr & CHCR_TE))
+ return IRQ_NONE;
+
+ chcr &= ~(CHCR_IE | CHCR_DE);
+ ctrl_outl(chcr, CHCR[chan->chan]);
+
+ wake_up(&chan->wait_queue);
+
+ return IRQ_HANDLED;
+}
+
+static int sh_dmac_request_dma(struct dma_channel *chan)
+{
+ return request_irq(get_dmte_irq(chan->chan), dma_tei,
+ SA_INTERRUPT, "DMAC Transfer End", chan);
+}
+
+static void sh_dmac_free_dma(struct dma_channel *chan)
+{
+ free_irq(get_dmte_irq(chan->chan), chan);
+}
+
+static void sh_dmac_configure_channel(struct dma_channel *chan, unsigned long chcr)
+{
+ if (!chcr)
+ chcr = RS_DUAL;
+
+ ctrl_outl(chcr, CHCR[chan->chan]);
+
+ chan->flags |= DMA_CONFIGURED;
+}
+
+static void sh_dmac_enable_dma(struct dma_channel *chan)
+{
+ int irq = get_dmte_irq(chan->chan);
+ u32 chcr;
+
+ chcr = ctrl_inl(CHCR[chan->chan]);
+ chcr |= CHCR_DE | CHCR_IE;
+ ctrl_outl(chcr, CHCR[chan->chan]);
+
+ enable_irq(irq);
+}
+
+static void sh_dmac_disable_dma(struct dma_channel *chan)
+{
+ int irq = get_dmte_irq(chan->chan);
+ u32 chcr;
+
+ disable_irq(irq);
+
+ chcr = ctrl_inl(CHCR[chan->chan]);
+ chcr &= ~(CHCR_DE | CHCR_TE | CHCR_IE);
+ ctrl_outl(chcr, CHCR[chan->chan]);
+}
+
+static int sh_dmac_xfer_dma(struct dma_channel *chan)
+{
+ /*
+ * If we haven't pre-configured the channel with special flags, use
+ * the defaults.
+ */
+ if (!(chan->flags & DMA_CONFIGURED))
+ sh_dmac_configure_channel(chan, 0);
+
+ sh_dmac_disable_dma(chan);
+
+ /*
+ * Single-address mode usage note!
+ *
+ * It's important that we don't accidentally write any value to SAR/DAR
+ * (this includes 0) that hasn't been directly specified by the user if
+ * we're in single-address mode.
+ *
+ * In this case, only one address can be defined, anything else will
+ * result in a DMA address error interrupt (at least on the SH-4),
+ * which will subsequently halt the transfer.
+ *
+ * Channel 2 on the Dreamcast is a special case, as this is used for
+ * cascading to the PVR2 DMAC. In this case, we still need to write
+ * SAR and DAR, regardless of value, in order for cascading to work.
+ */
+ if (chan->sar || (mach_is_dreamcast() && chan->chan == 2))
+ ctrl_outl(chan->sar, SAR[chan->chan]);
+ if (chan->dar || (mach_is_dreamcast() && chan->chan == 2))
+ ctrl_outl(chan->dar, DAR[chan->chan]);
+
+ ctrl_outl(chan->count >> calc_xmit_shift(chan), DMATCR[chan->chan]);
+
+ sh_dmac_enable_dma(chan);
+
+ return 0;
+}
+
+static int sh_dmac_get_dma_residue(struct dma_channel *chan)
+{
+ if (!(ctrl_inl(CHCR[chan->chan]) & CHCR_DE))
+ return 0;
+
+ return ctrl_inl(DMATCR[chan->chan]) << calc_xmit_shift(chan);
+}
+
+#if defined(CONFIG_CPU_SH4)
+static irqreturn_t dma_err(int irq, void *dev_id, struct pt_regs *regs)
+{
+ unsigned long dmaor = ctrl_inl(DMAOR);
+
+ printk("DMAE: DMAOR=%lx\n", dmaor);
+
+ ctrl_outl(ctrl_inl(DMAOR)&~DMAOR_NMIF, DMAOR);
+ ctrl_outl(ctrl_inl(DMAOR)&~DMAOR_AE, DMAOR);
+ ctrl_outl(ctrl_inl(DMAOR)|DMAOR_DME, DMAOR);
+
+ disable_irq(irq);
+
+ return IRQ_HANDLED;
+}
+#endif
+
+static struct dma_ops sh_dmac_ops = {
+ .request = sh_dmac_request_dma,
+ .free = sh_dmac_free_dma,
+ .get_residue = sh_dmac_get_dma_residue,
+ .xfer = sh_dmac_xfer_dma,
+ .configure = sh_dmac_configure_channel,
+};
+
+static struct dma_info sh_dmac_info = {
+ .name = "SuperH DMAC",
+ .nr_channels = 4,
+ .ops = &sh_dmac_ops,
+ .flags = DMAC_CHANNELS_TEI_CAPABLE,
+};
+
+static int __init sh_dmac_init(void)
+{
+ struct dma_info *info = &sh_dmac_info;
+ int i;
+
+#ifdef CONFIG_CPU_SH4
+ make_ipr_irq(DMAE_IRQ, DMA_IPR_ADDR, DMA_IPR_POS, DMA_PRIORITY);
+ i = request_irq(DMAE_IRQ, dma_err, SA_INTERRUPT, "DMAC Address Error", 0);
+ if (i < 0)
+ return i;
+#endif
+
+ for (i = 0; i < info->nr_channels; i++) {
+ int irq = get_dmte_irq(i);
+
+ make_ipr_irq(irq, DMA_IPR_ADDR, DMA_IPR_POS, DMA_PRIORITY);
+ }
+
+ ctrl_outl(0x8000 | DMAOR_DME, DMAOR);
+
+ return register_dmac(info);
+}
+
+static void __exit sh_dmac_exit(void)
+{
+#ifdef CONFIG_CPU_SH4
+ free_irq(DMAE_IRQ, 0);
+#endif
+}
+
+subsys_initcall(sh_dmac_init);
+module_exit(sh_dmac_exit);
+
+MODULE_LICENSE("GPL");
+
diff --git a/arch/sh/drivers/dma/dma-sh.h b/arch/sh/drivers/dma/dma-sh.h
new file mode 100644
index 000000000000..dd9d547539a2
--- /dev/null
+++ b/arch/sh/drivers/dma/dma-sh.h
@@ -0,0 +1,52 @@
+/*
+ * arch/sh/drivers/dma/dma-sh.h
+ *
+ * Copyright (C) 2000 Takashi YOSHII
+ * 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.
+ */
+#ifndef __DMA_SH_H
+#define __DMA_SH_H
+
+/* Definitions for the SuperH DMAC */
+#define REQ_L 0x00000000
+#define REQ_E 0x00080000
+#define RACK_H 0x00000000
+#define RACK_L 0x00040000
+#define ACK_R 0x00000000
+#define ACK_W 0x00020000
+#define ACK_H 0x00000000
+#define ACK_L 0x00010000
+#define DM_INC 0x00004000
+#define DM_DEC 0x00008000
+#define SM_INC 0x00001000
+#define SM_DEC 0x00002000
+#define RS_IN 0x00000200
+#define RS_OUT 0x00000300
+#define TM_BURST 0x0000080
+#define TS_8 0x00000010
+#define TS_16 0x00000020
+#define TS_32 0x00000030
+#define TS_64 0x00000000
+#define TS_BLK 0x00000040
+#define CHCR_DE 0x00000001
+#define CHCR_TE 0x00000002
+#define CHCR_IE 0x00000004
+
+/* Define the default configuration for dual address memory-memory transfer.
+ * The 0x400 value represents auto-request, external->external.
+ */
+#define RS_DUAL (DM_INC | SM_INC | 0x400 | TS_32)
+
+#define DMAOR_COD 0x00000008
+#define DMAOR_AE 0x00000004
+#define DMAOR_NMIF 0x00000002
+#define DMAOR_DME 0x00000001
+
+#define MAX_DMAC_CHANNELS (CONFIG_NR_ONCHIP_DMA_CHANNELS)
+
+#endif /* __DMA_SH_H */
+
diff --git a/arch/sh/drivers/dma/dma-sysfs.c b/arch/sh/drivers/dma/dma-sysfs.c
new file mode 100644
index 000000000000..71a6d4e7809f
--- /dev/null
+++ b/arch/sh/drivers/dma/dma-sysfs.c
@@ -0,0 +1,133 @@
+/*
+ * arch/sh/drivers/dma/dma-sysfs.c
+ *
+ * sysfs interface for SH DMA API
+ *
+ * Copyright (C) 2004 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/kernel.h>
+#include <linux/init.h>
+#include <linux/sysdev.h>
+#include <linux/module.h>
+#include <asm/dma.h>
+
+static struct sysdev_class dma_sysclass = {
+ set_kset_name("dma"),
+};
+
+EXPORT_SYMBOL(dma_sysclass);
+
+static ssize_t dma_show_devices(struct sys_device *dev, char *buf)
+{
+ ssize_t len = 0;
+ int i;
+
+ for (i = 0; i < MAX_DMA_CHANNELS; i++) {
+ struct dma_info *info = get_dma_info(i);
+ struct dma_channel *channel = &info->channels[i];
+
+ len += sprintf(buf + len, "%2d: %14s %s\n",
+ channel->chan, info->name,
+ channel->dev_id);
+ }
+
+ return len;
+}
+
+static SYSDEV_ATTR(devices, S_IRUGO, dma_show_devices, NULL);
+
+static int __init dma_sysclass_init(void)
+{
+ int ret;
+
+ ret = sysdev_class_register(&dma_sysclass);
+ if (ret == 0)
+ sysfs_create_file(&dma_sysclass.kset.kobj, &attr_devices.attr);
+
+ return ret;
+}
+
+postcore_initcall(dma_sysclass_init);
+
+static ssize_t dma_show_dev_id(struct sys_device *dev, char *buf)
+{
+ struct dma_channel *channel = to_dma_channel(dev);
+ return sprintf(buf, "%s\n", channel->dev_id);
+}
+
+static ssize_t dma_store_dev_id(struct sys_device *dev,
+ const char *buf, size_t count)
+{
+ struct dma_channel *channel = to_dma_channel(dev);
+ strcpy(channel->dev_id, buf);
+ return count;
+}
+
+static SYSDEV_ATTR(dev_id, S_IRUGO | S_IWUSR, dma_show_dev_id, dma_store_dev_id);
+
+static ssize_t dma_store_config(struct sys_device *dev,
+ const char *buf, size_t count)
+{
+ struct dma_channel *channel = to_dma_channel(dev);
+ unsigned long config;
+
+ config = simple_strtoul(buf, NULL, 0);
+ dma_configure_channel(channel->chan, config);
+
+ return count;
+}
+
+static SYSDEV_ATTR(config, S_IWUSR, NULL, dma_store_config);
+
+static ssize_t dma_show_mode(struct sys_device *dev, char *buf)
+{
+ struct dma_channel *channel = to_dma_channel(dev);
+ return sprintf(buf, "0x%08x\n", channel->mode);
+}
+
+static ssize_t dma_store_mode(struct sys_device *dev,
+ const char *buf, size_t count)
+{
+ struct dma_channel *channel = to_dma_channel(dev);
+ channel->mode = simple_strtoul(buf, NULL, 0);
+ return count;
+}
+
+static SYSDEV_ATTR(mode, S_IRUGO | S_IWUSR, dma_show_mode, dma_store_mode);
+
+#define dma_ro_attr(field, fmt) \
+static ssize_t dma_show_##field(struct sys_device *dev, char *buf) \
+{ \
+ struct dma_channel *channel = to_dma_channel(dev); \
+ return sprintf(buf, fmt, channel->field); \
+} \
+static SYSDEV_ATTR(field, S_IRUGO, dma_show_##field, NULL);
+
+dma_ro_attr(count, "0x%08x\n");
+dma_ro_attr(flags, "0x%08lx\n");
+
+int __init dma_create_sysfs_files(struct dma_channel *chan)
+{
+ struct sys_device *dev = &chan->dev;
+ int ret;
+
+ dev->id = chan->chan;
+ dev->cls = &dma_sysclass;
+
+ ret = sysdev_register(dev);
+ if (ret)
+ return ret;
+
+ sysdev_create_file(dev, &attr_dev_id);
+ sysdev_create_file(dev, &attr_count);
+ sysdev_create_file(dev, &attr_mode);
+ sysdev_create_file(dev, &attr_flags);
+ sysdev_create_file(dev, &attr_config);
+
+ return 0;
+}
+
diff --git a/arch/sh/drivers/pci/Kconfig b/arch/sh/drivers/pci/Kconfig
new file mode 100644
index 000000000000..6d1cbbe6745c
--- /dev/null
+++ b/arch/sh/drivers/pci/Kconfig
@@ -0,0 +1,41 @@
+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. 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'.
+
+# This is also board-specific
+config PCI_AUTO
+ bool
+ depends on PCI
+ default y
+
+config PCI_AUTO_UPDATE_RESOURCES
+ bool
+ depends on PCI_AUTO
+ default y if !SH_DREAMCAST
+ help
+ Selecting this option will cause the PCI auto code to leave your
+ BAR values alone. Otherwise they will be updated automatically. If
+ for some reason, you have a board that simply refuses to work
+ with its resources updated beyond what they are when the device
+ is powered up, set this to N. Everyone else will want this as Y.
+
diff --git a/arch/sh/drivers/pci/Makefile b/arch/sh/drivers/pci/Makefile
new file mode 100644
index 000000000000..365bc16a4a83
--- /dev/null
+++ b/arch/sh/drivers/pci/Makefile
@@ -0,0 +1,16 @@
+#
+# Makefile for the PCI specific kernel interface routines under Linux.
+#
+
+obj-y += pci.o
+obj-$(CONFIG_PCI_AUTO) += pci-auto.o
+
+obj-$(CONFIG_CPU_SUBTYPE_ST40STB1) += pci-st40.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7751) += pci-sh7751.o
+
+obj-$(CONFIG_SH_DREAMCAST) += ops-dreamcast.o fixups-dreamcast.o \
+ dma-dreamcast.o
+obj-$(CONFIG_SH_SECUREEDGE5410) += ops-snapgear.o
+obj-$(CONFIG_SH_BIGSUR) += ops-bigsur.o
+obj-$(CONFIG_SH_RTS7751R2D) += ops-rts7751r2d.o fixups-rts7751r2d.o
+obj-$(CONFIG_SH_SH03) += ops-sh03.o fixups-sh03.o
diff --git a/arch/sh/drivers/pci/dma-dreamcast.c b/arch/sh/drivers/pci/dma-dreamcast.c
new file mode 100644
index 000000000000..83de7ef4e7df
--- /dev/null
+++ b/arch/sh/drivers/pci/dma-dreamcast.c
@@ -0,0 +1,71 @@
+/*
+ * arch/sh/pci/dma-dreamcast.c
+ *
+ * PCI DMA support for the Sega Dreamcast
+ *
+ * Copyright (C) 2001, 2002 M. R. Brown
+ * Copyright (C) 2002, 2003 Paul Mundt
+ *
+ * This file originally bore the message (with enclosed-$):
+ * Id: pci.c,v 1.3 2003/05/04 19:29:46 lethal Exp
+ * Dreamcast PCI: Supports SEGA Broadband Adaptor only.
+ *
+ * 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/config.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/param.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/pci.h>
+#include <linux/dma-mapping.h>
+#include <linux/device.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/mach/pci.h>
+
+static int gapspci_dma_used = 0;
+
+void *dreamcast_consistent_alloc(struct device *dev, size_t size,
+ dma_addr_t *dma_handle, int flag)
+{
+ unsigned long buf;
+
+ if (dev && dev->bus != &pci_bus_type)
+ return NULL;
+
+ if (gapspci_dma_used + size > GAPSPCI_DMA_SIZE)
+ return ERR_PTR(-EINVAL);
+
+ buf = GAPSPCI_DMA_BASE + gapspci_dma_used;
+
+ gapspci_dma_used = PAGE_ALIGN(gapspci_dma_used+size);
+
+ *dma_handle = (dma_addr_t)buf;
+
+ buf = P2SEGADDR(buf);
+
+ /* Flush the dcache before we hand off the buffer */
+ dma_cache_wback_inv((void *)buf, size);
+
+ return (void *)buf;
+}
+
+int dreamcast_consistent_free(struct device *dev, size_t size,
+ void *vaddr, dma_addr_t dma_handle)
+{
+ if (dev && dev->bus != &pci_bus_type)
+ return -EINVAL;
+
+ /* XXX */
+ gapspci_dma_used = 0;
+
+ return 0;
+}
+
diff --git a/arch/sh/drivers/pci/fixups-dreamcast.c b/arch/sh/drivers/pci/fixups-dreamcast.c
new file mode 100644
index 000000000000..cf30e2fa51be
--- /dev/null
+++ b/arch/sh/drivers/pci/fixups-dreamcast.c
@@ -0,0 +1,81 @@
+/*
+ * arch/sh/pci/fixups-dreamcast.c
+ *
+ * PCI fixups for the Sega Dreamcast
+ *
+ * Copyright (C) 2001, 2002 M. R. Brown
+ * Copyright (C) 2002, 2003 Paul Mundt
+ *
+ * This file originally bore the message (with enclosed-$):
+ * Id: pci.c,v 1.3 2003/05/04 19:29:46 lethal Exp
+ * Dreamcast PCI: Supports SEGA Broadband Adaptor only.
+ *
+ * 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/config.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/param.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/pci.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/mach/pci.h>
+
+static void __init gapspci_fixup_resources(struct pci_dev *dev)
+{
+ struct pci_channel *p = board_pci_channels;
+
+ printk(KERN_NOTICE "PCI: Fixing up device %s\n", pci_name(dev));
+
+ switch (dev->device) {
+ case PCI_DEVICE_ID_SEGA_BBA:
+ /*
+ * We also assume that dev->devfn == 0
+ */
+ dev->resource[1].start = p->io_resource->start + 0x100;
+ dev->resource[1].end = dev->resource[1].start + 0x200 - 1;
+ break;
+ default:
+ printk("PCI: Failed resource fixup\n");
+ }
+}
+
+DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, gapspci_fixup_resources);
+
+void __init pcibios_fixup_bus(struct pci_bus *bus)
+{
+ /*
+ * We don't have any sub bus to fix up, and this is a rather
+ * stupid place to put general device fixups. Don't do it.
+ * Use the pcibios_fixups table or suffer the consequences.
+ */
+}
+
+void __init pcibios_fixup_irqs(void)
+{
+ struct pci_dev *dev = 0;
+
+ for_each_pci_dev(dev) {
+ /*
+ * The interrupt routing semantics here are quite trivial.
+ *
+ * We basically only support one interrupt, so we only bother
+ * updating a device's interrupt line with this single shared
+ * interrupt. Keeps routing quite simple, doesn't it?
+ */
+ printk(KERN_NOTICE "PCI: Fixing up IRQ routing for device %s\n",
+ pci_name(dev));
+
+ dev->irq = GAPSPCI_IRQ;
+
+ pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
+ }
+}
+
diff --git a/arch/sh/drivers/pci/fixups-rts7751r2d.c b/arch/sh/drivers/pci/fixups-rts7751r2d.c
new file mode 100644
index 000000000000..0c590fc7a081
--- /dev/null
+++ b/arch/sh/drivers/pci/fixups-rts7751r2d.c
@@ -0,0 +1,43 @@
+/*
+ * arch/sh/drivers/pci/fixups-rts7751r2d.c
+ *
+ * RTS7751R2D PCI fixups
+ *
+ * Copyright (C) 2003 Lineo uSolutions, Inc.
+ * Copyright (C) 2004 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 "pci-sh7751.h"
+#include <asm/io.h>
+
+#define PCIMCR_MRSET_OFF 0xBFFFFFFF
+#define PCIMCR_RFSH_OFF 0xFFFFFFFB
+
+int pci_fixup_pcic(void)
+{
+ unsigned long bcr1, mcr;
+
+ bcr1 = inl(SH7751_BCR1);
+ bcr1 |= 0x40080000; /* Enable Bit 19 BREQEN, set PCIC to slave */
+ outl(bcr1, PCI_REG(SH7751_PCIBCR1));
+
+ /* Enable all interrupts, so we known what to fix */
+ outl(0x0000c3ff, PCI_REG(SH7751_PCIINTM));
+ outl(0x0000380f, PCI_REG(SH7751_PCIAINTM));
+
+ outl(0xfb900047, PCI_REG(SH7751_PCICONF1));
+ outl(0xab000001, PCI_REG(SH7751_PCICONF4));
+
+ mcr = inl(SH7751_MCR);
+ mcr = (mcr & PCIMCR_MRSET_OFF) & PCIMCR_RFSH_OFF;
+ outl(mcr, PCI_REG(SH7751_PCIMCR));
+
+ outl(0x0c000000, PCI_REG(SH7751_PCICONF5));
+ outl(0xd0000000, PCI_REG(SH7751_PCICONF6));
+ outl(0x0c000000, PCI_REG(SH7751_PCILAR0));
+ outl(0x00000000, PCI_REG(SH7751_PCILAR1));
+ return 0;
+}
diff --git a/arch/sh/drivers/pci/fixups-sh03.c b/arch/sh/drivers/pci/fixups-sh03.c
new file mode 100644
index 000000000000..57ac26c2171f
--- /dev/null
+++ b/arch/sh/drivers/pci/fixups-sh03.c
@@ -0,0 +1,61 @@
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+
+/*
+ * IRQ functions
+ */
+
+int __init pcibios_map_platform_irq(u8 slot, u8 pin, struct pci_dev *dev)
+{
+ int irq;
+
+ if (dev->bus->number == 0) {
+ switch (slot) {
+ case 4: return 5; /* eth0 */
+ case 8: return 5; /* eth1 */
+ case 6: return 2; /* PCI bridge */
+ default:
+ printk("PCI: Bad IRQ mapping request for slot %d\n", slot);
+ return 2;
+ }
+ } else {
+ switch (pin) {
+ case 0: irq = 2; break;
+ case 1: irq = 2; break;
+ case 2: irq = 2; break;
+ case 3: irq = 2; break;
+ case 4: irq = 2; break;
+ default: irq = -1; break;
+ }
+ }
+ return irq;
+}
+
+static u8 __init sh03_no_swizzle(struct pci_dev *dev, u8 *pin)
+{
+ /* no swizzling */
+ return PCI_SLOT(dev->devfn);
+}
+
+static int sh03_pci_lookup_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+ int irq = -1;
+
+ /* now lookup the actual IRQ on a platform specific basis (pci-'platform'.c) */
+ irq = pcibios_map_platform_irq(slot, pin, dev);
+ if( irq < 0 ) {
+ pr_debug("PCI: Error mapping IRQ on device %s\n", pci_name(dev));
+ return irq;
+ }
+
+ pr_debug("Setting IRQ for slot %s to %d\n", pci_name(dev), irq);
+
+ return irq;
+}
+
+void __init pcibios_fixup_irqs(void)
+{
+ pci_fixup_irqs(sh03_no_swizzle, sh03_pci_lookup_irq);
+}
diff --git a/arch/sh/drivers/pci/ops-bigsur.c b/arch/sh/drivers/pci/ops-bigsur.c
new file mode 100644
index 000000000000..9b43da67804b
--- /dev/null
+++ b/arch/sh/drivers/pci/ops-bigsur.c
@@ -0,0 +1,88 @@
+/*
+ * linux/arch/sh/kernel/pci-bigsur.c
+ *
+ * By Dustin McIntire (dustin@sensoria.com) (c)2001
+ *
+ * Ported to new API by 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.
+ *
+ * PCI initialization for the Hitachi Big Sur Evaluation Board
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+
+#include <asm/io.h>
+#include "pci-sh7751.h"
+#include <asm/bigsur/bigsur.h>
+
+#define BIGSUR_PCI_IO 0x4000
+#define BIGSUR_PCI_MEM 0xfd000000
+
+static struct resource sh7751_io_resource = {
+ .name = "SH7751 IO",
+ .start = BIGSUR_PCI_IO,
+ .end = BIGSUR_PCI_IO + (64*1024) - 1,
+ .flags = IORESOURCE_IO,
+};
+
+static struct resource sh7751_mem_resource = {
+ .name = "SH7751 mem",
+ .start = BIGSUR_PCI_MEM,
+ .end = BIGSUR_PCI_MEM + (64*1024*1024) - 1,
+ .flags = IORESOURCE_MEM,
+};
+
+extern struct pci_ops sh7751_pci_ops;
+
+struct pci_channel board_pci_channels[] = {
+ { &sh7751_pci_ops, &sh7751_io_resource, &sh7751_mem_resource, 0, 0xff },
+ { 0, }
+};
+
+static struct sh7751_pci_address_map sh7751_pci_map = {
+ .window0 = {
+ .base = SH7751_CS3_BASE_ADDR,
+ .size = BIGSUR_LSR0_SIZE,
+ },
+
+ .window1 = {
+ .base = SH7751_CS3_BASE_ADDR,
+ .size = BIGSUR_LSR1_SIZE,
+ },
+};
+
+/*
+ * Initialize the Big Sur PCI interface
+ * Setup hardware to be Central Funtion
+ * Copy the BSR regs to the PCI interface
+ * Setup PCI windows into local RAM
+ */
+int __init pcibios_init_platform(void)
+{
+ return sh7751_pcic_init(&sh7751_pci_map);
+}
+
+int pcibios_map_platform_irq(u8 slot, u8 pin)
+{
+ /*
+ * The Big Sur can be used in a CPCI chassis, but the SH7751 PCI
+ * interface is on the wrong end of the board so that it can also
+ * support a V320 CPI interface chip... Therefor the IRQ mapping is
+ * somewhat use dependent... I'l assume a linear map for now, i.e.
+ * INTA=slot0,pin0... INTD=slot3,pin0...
+ */
+ int irq = (slot + pin-1) % 4 + BIGSUR_SH7751_PCI_IRQ_BASE;
+
+ PCIDBG(2, "PCI: Mapping Big Sur IRQ for slot %d, pin %c to irq %d\n",
+ slot, pin-1+'A', irq);
+
+ return irq;
+}
+
diff --git a/arch/sh/drivers/pci/ops-dreamcast.c b/arch/sh/drivers/pci/ops-dreamcast.c
new file mode 100644
index 000000000000..69af80b93e3f
--- /dev/null
+++ b/arch/sh/drivers/pci/ops-dreamcast.c
@@ -0,0 +1,169 @@
+/*
+ * arch/sh/pci/ops-dreamcast.c
+ *
+ * PCI operations for the Sega Dreamcast
+ *
+ * Copyright (C) 2001, 2002 M. R. Brown
+ * Copyright (C) 2002, 2003 Paul Mundt
+ *
+ * This file originally bore the message (with enclosed-$):
+ * Id: pci.c,v 1.3 2003/05/04 19:29:46 lethal Exp
+ * Dreamcast PCI: Supports SEGA Broadband Adaptor only.
+ *
+ * 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/config.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/param.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/pci.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/mach/pci.h>
+
+static struct resource gapspci_io_resource = {
+ .name = "GAPSPCI IO",
+ .start = GAPSPCI_BBA_CONFIG,
+ .end = GAPSPCI_BBA_CONFIG + GAPSPCI_BBA_CONFIG_SIZE - 1,
+ .flags = IORESOURCE_IO,
+};
+
+static struct resource gapspci_mem_resource = {
+ .name = "GAPSPCI mem",
+ .start = GAPSPCI_DMA_BASE,
+ .end = GAPSPCI_DMA_BASE + GAPSPCI_DMA_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+};
+
+static struct pci_ops gapspci_pci_ops;
+
+struct pci_channel board_pci_channels[] = {
+ { &gapspci_pci_ops, &gapspci_io_resource,
+ &gapspci_mem_resource, 0, 1 },
+ { 0, }
+};
+
+/*
+ * The !gapspci_config_access case really shouldn't happen, ever, unless
+ * someone implicitly messes around with the last devfn value.. otherwise we
+ * only support a single device anyways, and if we didn't have a BBA, we
+ * wouldn't make it terribly far through the PCI setup anyways.
+ *
+ * Also, we could very easily support both Type 0 and Type 1 configurations
+ * here, but since it doesn't seem that there is any such implementation in
+ * existance, we don't bother.
+ *
+ * I suppose if someone actually gets around to ripping the chip out of
+ * the BBA and hanging some more devices off of it, then this might be
+ * something to take into consideration. However, due to the cost of the BBA,
+ * and the general lack of activity by DC hardware hackers, this doesn't seem
+ * likely to happen anytime soon.
+ */
+static int gapspci_config_access(unsigned char bus, unsigned int devfn)
+{
+ return (bus == 0) && (devfn == 0);
+}
+
+/*
+ * We can also actually read and write in b/w/l sizes! Thankfully this part
+ * was at least done right, and we don't have to do the stupid masking and
+ * shifting that we do on the 7751! Small wonders never cease to amaze.
+ */
+static int gapspci_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *val)
+{
+ *val = 0xffffffff;
+
+ if (!gapspci_config_access(bus->number, devfn))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ switch (size) {
+ case 1: *val = inb(GAPSPCI_BBA_CONFIG+where); break;
+ case 2: *val = inw(GAPSPCI_BBA_CONFIG+where); break;
+ case 4: *val = inl(GAPSPCI_BBA_CONFIG+where); break;
+ }
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int gapspci_write(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 val)
+{
+ if (!gapspci_config_access(bus->number, devfn))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ switch (size) {
+ case 1: outb(( u8)val, GAPSPCI_BBA_CONFIG+where); break;
+ case 2: outw((u16)val, GAPSPCI_BBA_CONFIG+where); break;
+ case 4: outl((u32)val, GAPSPCI_BBA_CONFIG+where); break;
+ }
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static struct pci_ops gapspci_pci_ops = {
+ .read = gapspci_read,
+ .write = gapspci_write,
+};
+
+/*
+ * gapspci init
+ */
+
+int __init gapspci_init(void)
+{
+ char idbuf[16];
+ int i;
+
+ /*
+ * FIXME: All of this wants documenting to some degree,
+ * even some basic register definitions would be nice.
+ *
+ * I haven't seen anything this ugly since.. maple.
+ */
+
+ for (i=0; i<16; i++)
+ idbuf[i] = inb(GAPSPCI_REGS+i);
+
+ if (strncmp(idbuf, "GAPSPCI_BRIDGE_2", 16))
+ return -ENODEV;
+
+ outl(0x5a14a501, GAPSPCI_REGS+0x18);
+
+ for (i=0; i<1000000; i++)
+ ;
+
+ if (inl(GAPSPCI_REGS+0x18) != 1)
+ return -EINVAL;
+
+ outl(0x01000000, GAPSPCI_REGS+0x20);
+ outl(0x01000000, GAPSPCI_REGS+0x24);
+
+ outl(GAPSPCI_DMA_BASE, GAPSPCI_REGS+0x28);
+ outl(GAPSPCI_DMA_BASE+GAPSPCI_DMA_SIZE, GAPSPCI_REGS+0x2c);
+
+ outl(1, GAPSPCI_REGS+0x14);
+ outl(1, GAPSPCI_REGS+0x34);
+
+ /* Setting Broadband Adapter */
+ outw(0xf900, GAPSPCI_BBA_CONFIG+0x06);
+ outl(0x00000000, GAPSPCI_BBA_CONFIG+0x30);
+ outb(0x00, GAPSPCI_BBA_CONFIG+0x3c);
+ outb(0xf0, GAPSPCI_BBA_CONFIG+0x0d);
+ outw(0x0006, GAPSPCI_BBA_CONFIG+0x04);
+ outl(0x00002001, GAPSPCI_BBA_CONFIG+0x10);
+ outl(0x01000000, GAPSPCI_BBA_CONFIG+0x14);
+
+ return 0;
+}
+
+/* Haven't done anything here as yet */
+char * __devinit pcibios_setup(char *str)
+{
+ return str;
+}
diff --git a/arch/sh/drivers/pci/ops-rts7751r2d.c b/arch/sh/drivers/pci/ops-rts7751r2d.c
new file mode 100644
index 000000000000..beafa11f4d0c
--- /dev/null
+++ b/arch/sh/drivers/pci/ops-rts7751r2d.c
@@ -0,0 +1,79 @@
+/*
+ * linux/arch/sh/kernel/pci-rts7751r2d.c
+ *
+ * Author: Ian DaSilva (idasilva@mvista.com)
+ *
+ * Highly leveraged from pci-bigsur.c, written by Dustin McIntire.
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License. See linux/COPYING for more information.
+ *
+ * PCI initialization for the Renesas SH7751R RTS7751R2D board
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+#include <linux/module.h>
+
+#include <asm/io.h>
+#include "pci-sh7751.h"
+#include <asm/rts7751r2d/rts7751r2d.h>
+
+int __init pcibios_map_platform_irq(u8 slot, u8 pin)
+{
+ switch (slot) {
+ case 0: return IRQ_PCISLOT1; /* PCI Extend slot #1 */
+ case 1: return IRQ_PCISLOT2; /* PCI Extend slot #2 */
+ case 2: return IRQ_PCMCIA; /* PCI Cardbus Bridge */
+ case 3: return IRQ_PCIETH; /* Realtek Ethernet controller */
+ default:
+ printk("PCI: Bad IRQ mapping request for slot %d\n", slot);
+ return -1;
+ }
+}
+
+static struct resource sh7751_io_resource = {
+ .name = "SH7751_IO",
+ .start = 0x4000,
+ .end = 0x4000 + SH7751_PCI_IO_SIZE - 1,
+ .flags = IORESOURCE_IO
+};
+
+static struct resource sh7751_mem_resource = {
+ .name = "SH7751_mem",
+ .start = SH7751_PCI_MEMORY_BASE,
+ .end = SH7751_PCI_MEMORY_BASE + SH7751_PCI_MEM_SIZE - 1,
+ .flags = IORESOURCE_MEM
+};
+
+extern struct pci_ops sh7751_pci_ops;
+
+struct pci_channel board_pci_channels[] = {
+ { &sh7751_pci_ops, &sh7751_io_resource, &sh7751_mem_resource, 0, 0xff },
+ { NULL, NULL, NULL, 0, 0 },
+};
+EXPORT_SYMBOL(board_pci_channels);
+
+static struct sh7751_pci_address_map sh7751_pci_map = {
+ .window0 = {
+ .base = SH7751_CS3_BASE_ADDR,
+ .size = 0x04000000,
+ },
+
+ .window1 = {
+ .base = 0x00000000, /* Unused */
+ .size = 0x00000000, /* Unused */
+ },
+
+ .flags = SH7751_PCIC_NO_RESET,
+};
+
+int __init pcibios_init_platform(void)
+{
+ return sh7751_pcic_init(&sh7751_pci_map);
+}
+
diff --git a/arch/sh/drivers/pci/ops-sh03.c b/arch/sh/drivers/pci/ops-sh03.c
new file mode 100644
index 000000000000..df2199732348
--- /dev/null
+++ b/arch/sh/drivers/pci/ops-sh03.c
@@ -0,0 +1,45 @@
+/*
+ * linux/arch/sh/drivers/pci/ops-sh03.c
+ *
+ * PCI initialization for the Interface CTP/PCI-SH03 board
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+#include <asm/io.h>
+#include "pci-sh7751.h"
+
+/*
+ * Description: This function sets up and initializes the pcic, sets
+ * up the BARS, maps the DRAM into the address space etc, etc.
+ */
+int __init pcibios_init_platform(void)
+{
+ return 1;
+}
+
+static struct resource sh7751_io_resource = {
+ .name = "SH03 IO",
+ .start = SH7751_PCI_IO_BASE,
+ .end = SH7751_PCI_IO_BASE + SH7751_PCI_IO_SIZE - 1,
+ .flags = IORESOURCE_IO
+};
+
+static struct resource sh7751_mem_resource = {
+ .name = "SH03 mem",
+ .start = SH7751_PCI_MEMORY_BASE,
+ .end = SH7751_PCI_MEMORY_BASE + SH7751_PCI_MEM_SIZE - 1,
+ .flags = IORESOURCE_MEM
+};
+
+extern struct pci_ops sh7751_pci_ops;
+
+struct pci_channel board_pci_channels[] = {
+ { &sh7751_pci_ops, &sh7751_io_resource, &sh7751_mem_resource, 0, 0xff },
+ { NULL, NULL, NULL, 0, 0 },
+};
+
diff --git a/arch/sh/drivers/pci/ops-snapgear.c b/arch/sh/drivers/pci/ops-snapgear.c
new file mode 100644
index 000000000000..6fdb9765c99a
--- /dev/null
+++ b/arch/sh/drivers/pci/ops-snapgear.c
@@ -0,0 +1,102 @@
+/*
+ * arch/sh/drivers/pci/ops-snapgear.c
+ *
+ * Author: David McCullough <davidm@snapgear.com>
+ *
+ * Ported to new API by Paul Mundt <lethal@linux-sh.org>
+ *
+ * Highly leveraged from pci-bigsur.c, written by Dustin McIntire.
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License. See linux/COPYING for more information.
+ *
+ * PCI initialization for the SnapGear boards
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+
+#include <asm/io.h>
+#include "pci-sh7751.h"
+
+#define SNAPGEAR_PCI_IO 0x4000
+#define SNAPGEAR_PCI_MEM 0xfd000000
+
+/* PCI: default LOCAL memory window sizes (seen from PCI bus) */
+#define SNAPGEAR_LSR0_SIZE (64*(1<<20)) //64MB
+#define SNAPGEAR_LSR1_SIZE (64*(1<<20)) //64MB
+
+static struct resource sh7751_io_resource = {
+ .name = "SH7751 IO",
+ .start = SNAPGEAR_PCI_IO,
+ .end = SNAPGEAR_PCI_IO + (64*1024) - 1, /* 64KiB I/O */
+ .flags = IORESOURCE_IO,
+};
+
+static struct resource sh7751_mem_resource = {
+ .name = "SH7751 mem",
+ .start = SNAPGEAR_PCI_MEM,
+ .end = SNAPGEAR_PCI_MEM + (64*1024*1024) - 1, /* 64MiB mem */
+ .flags = IORESOURCE_MEM,
+};
+
+extern struct pci_ops sh7751_pci_ops;
+
+struct pci_channel board_pci_channels[] = {
+ { &sh7751_pci_ops, &sh7751_io_resource, &sh7751_mem_resource, 0, 0xff },
+ { 0, }
+};
+
+static struct sh7751_pci_address_map sh7751_pci_map = {
+ .window0 = {
+ .base = SH7751_CS2_BASE_ADDR,
+ .size = SNAPGEAR_LSR0_SIZE,
+ },
+
+ .window1 = {
+ .base = SH7751_CS2_BASE_ADDR,
+ .size = SNAPGEAR_LSR1_SIZE,
+ },
+
+ .flags = SH7751_PCIC_NO_RESET,
+};
+
+/*
+ * Initialize the SnapGear PCI interface
+ * Setup hardware to be Central Funtion
+ * Copy the BSR regs to the PCI interface
+ * Setup PCI windows into local RAM
+ */
+int __init pcibios_init_platform(void)
+{
+ return sh7751_pcic_init(&sh7751_pci_map);
+}
+
+int __init pcibios_map_platform_irq(u8 slot, u8 pin)
+{
+ int irq = -1;
+
+ switch (slot) {
+ case 8: /* the PCI bridge */ break;
+ case 11: irq = 8; break; /* USB */
+ case 12: irq = 11; break; /* PCMCIA */
+ case 13: irq = 5; break; /* eth0 */
+ case 14: irq = 8; break; /* eth1 */
+ case 15: irq = 11; break; /* safenet (unused) */
+ }
+
+ printk("PCI: Mapping SnapGear IRQ for slot %d, pin %c to irq %d\n",
+ slot, pin - 1 + 'A', irq);
+
+ return irq;
+}
+
+void __init pcibios_fixup(void)
+{
+ /* Nothing to fixup .. */
+}
+
diff --git a/arch/sh/drivers/pci/pci-auto.c b/arch/sh/drivers/pci/pci-auto.c
new file mode 100644
index 000000000000..4cef4d1d8c84
--- /dev/null
+++ b/arch/sh/drivers/pci/pci-auto.c
@@ -0,0 +1,555 @@
+/*
+ * PCI autoconfiguration library
+ *
+ * Author: Matt Porter <mporter@mvista.com>
+ *
+ * Copyright 2000, 2001 MontaVista Software Inc.
+ * Copyright 2001 Bradley D. LaRonde <brad@ltc.com>
+ * Copyright 2003 Paul Mundt <lethal@linux-sh.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+/*
+ * Modified for MIPS by Jun Sun, jsun@mvista.com
+ *
+ * . Simplify the interface between pci_auto and the rest: a single function.
+ * . Assign resources from low address to upper address.
+ * . change most int to u32.
+ *
+ * Further modified to include it as mips generic code, ppopov@mvista.com.
+ *
+ * 2001-10-26 Bradley D. LaRonde <brad@ltc.com>
+ * - Add a top_bus argument to the "early config" functions so that
+ * they can set a fake parent bus pointer to convince the underlying
+ * pci ops to use type 1 configuration for sub busses.
+ * - Set bridge base and limit registers correctly.
+ * - Align io and memory base properly before and after bridge setup.
+ * - Don't fall through to pci_setup_bars for bridge.
+ * - Reformat the debug output to look more like lspci's output.
+ *
+ * Cloned for SuperH by M. R. Brown, mrbrown@0xd6.org
+ *
+ * 2003-08-05 Paul Mundt <lethal@linux-sh.org>
+ * - Don't update the BAR values on systems that already have valid addresses
+ * and don't want these updated for whatever reason, by way of a new config
+ * option check. However, we still read in the old BAR values so that they
+ * can still be reported through the debug output.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+
+#undef DEBUG
+#ifdef DEBUG
+#define DBG(x...) printk(x)
+#else
+#define DBG(x...)
+#endif
+
+/*
+ * These functions are used early on before PCI scanning is done
+ * and all of the pci_dev and pci_bus structures have been created.
+ */
+static struct pci_dev *fake_pci_dev(struct pci_channel *hose,
+ int top_bus, int busnr, int devfn)
+{
+ static struct pci_dev dev;
+ static struct pci_bus bus;
+
+ dev.bus = &bus;
+ dev.sysdata = hose;
+ dev.devfn = devfn;
+ bus.number = busnr;
+ bus.ops = hose->pci_ops;
+
+ if(busnr != top_bus)
+ /* Fake a parent bus structure. */
+ bus.parent = &bus;
+ else
+ bus.parent = NULL;
+
+ return &dev;
+}
+
+#define EARLY_PCI_OP(rw, size, type) \
+int early_##rw##_config_##size(struct pci_channel *hose, \
+ int top_bus, int bus, int devfn, int offset, type value) \
+{ \
+ return pci_##rw##_config_##size( \
+ fake_pci_dev(hose, top_bus, bus, devfn), \
+ offset, value); \
+}
+
+EARLY_PCI_OP(read, byte, u8 *)
+EARLY_PCI_OP(read, word, u16 *)
+EARLY_PCI_OP(read, dword, u32 *)
+EARLY_PCI_OP(write, byte, u8)
+EARLY_PCI_OP(write, word, u16)
+EARLY_PCI_OP(write, dword, u32)
+
+static struct resource *io_resource_inuse;
+static struct resource *mem_resource_inuse;
+
+static u32 pciauto_lower_iospc;
+static u32 pciauto_upper_iospc;
+
+static u32 pciauto_lower_memspc;
+static u32 pciauto_upper_memspc;
+
+static void __init
+pciauto_setup_bars(struct pci_channel *hose,
+ int top_bus,
+ int current_bus,
+ int pci_devfn,
+ int bar_limit)
+{
+ u32 bar_response, bar_size, bar_value;
+ u32 bar, addr_mask, bar_nr = 0;
+ u32 * upper_limit;
+ u32 * lower_limit;
+ int found_mem64 = 0;
+
+ for (bar = PCI_BASE_ADDRESS_0; bar <= bar_limit; bar+=4) {
+#if !defined(CONFIG_SH_HS7751RVOIP) && !defined(CONFIG_SH_RTS7751R2D)
+ u32 bar_addr;
+
+ /* Read the old BAR value */
+ early_read_config_dword(hose, top_bus,
+ current_bus,
+ pci_devfn,
+ bar,
+ &bar_addr);
+#endif
+
+ /* Tickle the BAR and get the response */
+ early_write_config_dword(hose, top_bus,
+ current_bus,
+ pci_devfn,
+ bar,
+ 0xffffffff);
+
+ early_read_config_dword(hose, top_bus,
+ current_bus,
+ pci_devfn,
+ bar,
+ &bar_response);
+
+#if !defined(CONFIG_SH_HS7751RVOIP) && !defined(CONFIG_SH_RTS7751R2D)
+ /*
+ * Write the old BAR value back out, only update the BAR
+ * if we implicitly want resources to be updated, which
+ * is done by the generic code further down. -- PFM.
+ */
+ early_write_config_dword(hose, top_bus,
+ current_bus,
+ pci_devfn,
+ bar,
+ bar_addr);
+#endif
+
+ /* If BAR is not implemented go to the next BAR */
+ if (!bar_response)
+ continue;
+
+ /*
+ * Workaround for a BAR that doesn't use its upper word,
+ * like the ALi 1535D+ PCI DC-97 Controller Modem (M5457).
+ * bdl <brad@ltc.com>
+ */
+ if (!(bar_response & 0xffff0000))
+ bar_response |= 0xffff0000;
+
+retry:
+ /* Check the BAR type and set our address mask */
+ if (bar_response & PCI_BASE_ADDRESS_SPACE) {
+ addr_mask = PCI_BASE_ADDRESS_IO_MASK;
+ upper_limit = &pciauto_upper_iospc;
+ lower_limit = &pciauto_lower_iospc;
+ DBG(" I/O");
+ } else {
+ if ((bar_response & PCI_BASE_ADDRESS_MEM_TYPE_MASK) ==
+ PCI_BASE_ADDRESS_MEM_TYPE_64)
+ found_mem64 = 1;
+
+ addr_mask = PCI_BASE_ADDRESS_MEM_MASK;
+ upper_limit = &pciauto_upper_memspc;
+ lower_limit = &pciauto_lower_memspc;
+ DBG(" Mem");
+ }
+
+
+ /* Calculate requested size */
+ bar_size = ~(bar_response & addr_mask) + 1;
+
+ /* Allocate a base address */
+ bar_value = ((*lower_limit - 1) & ~(bar_size - 1)) + bar_size;
+
+ if ((bar_value + bar_size) > *upper_limit) {
+ if (bar_response & PCI_BASE_ADDRESS_SPACE) {
+ if (io_resource_inuse->child) {
+ io_resource_inuse =
+ io_resource_inuse->child;
+ pciauto_lower_iospc =
+ io_resource_inuse->start;
+ pciauto_upper_iospc =
+ io_resource_inuse->end + 1;
+ goto retry;
+ }
+
+ } else {
+ if (mem_resource_inuse->child) {
+ mem_resource_inuse =
+ mem_resource_inuse->child;
+ pciauto_lower_memspc =
+ mem_resource_inuse->start;
+ pciauto_upper_memspc =
+ mem_resource_inuse->end + 1;
+ goto retry;
+ }
+ }
+ DBG(" unavailable -- skipping, value %x size %x\n",
+ bar_value, bar_size);
+ continue;
+ }
+
+#ifdef CONFIG_PCI_AUTO_UPDATE_RESOURCES
+ /* Write it out and update our limit */
+ early_write_config_dword(hose, top_bus, current_bus, pci_devfn,
+ bar, bar_value);
+#endif
+
+ *lower_limit = bar_value + bar_size;
+
+ /*
+ * If we are a 64-bit decoder then increment to the
+ * upper 32 bits of the bar and force it to locate
+ * in the lower 4GB of memory.
+ */
+ if (found_mem64) {
+ bar += 4;
+ early_write_config_dword(hose, top_bus,
+ current_bus,
+ pci_devfn,
+ bar,
+ 0x00000000);
+ }
+
+ DBG(" at 0x%.8x [size=0x%x]\n", bar_value, bar_size);
+
+ bar_nr++;
+ }
+
+}
+
+static void __init
+pciauto_prescan_setup_bridge(struct pci_channel *hose,
+ int top_bus,
+ int current_bus,
+ int pci_devfn,
+ int sub_bus)
+{
+ /* Configure bus number registers */
+ early_write_config_byte(hose, top_bus, current_bus, pci_devfn,
+ PCI_PRIMARY_BUS, current_bus);
+ early_write_config_byte(hose, top_bus, current_bus, pci_devfn,
+ PCI_SECONDARY_BUS, sub_bus + 1);
+ early_write_config_byte(hose, top_bus, current_bus, pci_devfn,
+ PCI_SUBORDINATE_BUS, 0xff);
+
+ /* Align memory and I/O to 1MB and 4KB boundaries. */
+ pciauto_lower_memspc = (pciauto_lower_memspc + (0x100000 - 1))
+ & ~(0x100000 - 1);
+ pciauto_lower_iospc = (pciauto_lower_iospc + (0x1000 - 1))
+ & ~(0x1000 - 1);
+
+ /* Set base (lower limit) of address range behind bridge. */
+ early_write_config_word(hose, top_bus, current_bus, pci_devfn,
+ PCI_MEMORY_BASE, pciauto_lower_memspc >> 16);
+ early_write_config_byte(hose, top_bus, current_bus, pci_devfn,
+ PCI_IO_BASE, (pciauto_lower_iospc & 0x0000f000) >> 8);
+ early_write_config_word(hose, top_bus, current_bus, pci_devfn,
+ PCI_IO_BASE_UPPER16, pciauto_lower_iospc >> 16);
+
+ /* We don't support prefetchable memory for now, so disable */
+ early_write_config_word(hose, top_bus, current_bus, pci_devfn,
+ PCI_PREF_MEMORY_BASE, 0);
+ early_write_config_word(hose, top_bus, current_bus, pci_devfn,
+ PCI_PREF_MEMORY_LIMIT, 0);
+}
+
+static void __init
+pciauto_postscan_setup_bridge(struct pci_channel *hose,
+ int top_bus,
+ int current_bus,
+ int pci_devfn,
+ int sub_bus)
+{
+ u32 temp;
+
+ /*
+ * [jsun] we always bump up baselines a little, so that if there
+ * nothing behind P2P bridge, we don't wind up overlapping IO/MEM
+ * spaces.
+ */
+ pciauto_lower_memspc += 1;
+ pciauto_lower_iospc += 1;
+
+ /* Configure bus number registers */
+ early_write_config_byte(hose, top_bus, current_bus, pci_devfn,
+ PCI_SUBORDINATE_BUS, sub_bus);
+
+ /* Set upper limit of address range behind bridge. */
+ early_write_config_word(hose, top_bus, current_bus, pci_devfn,
+ PCI_MEMORY_LIMIT, pciauto_lower_memspc >> 16);
+ early_write_config_byte(hose, top_bus, current_bus, pci_devfn,
+ PCI_IO_LIMIT, (pciauto_lower_iospc & 0x0000f000) >> 8);
+ early_write_config_word(hose, top_bus, current_bus, pci_devfn,
+ PCI_IO_LIMIT_UPPER16, pciauto_lower_iospc >> 16);
+
+ /* Align memory and I/O to 1MB and 4KB boundaries. */
+ pciauto_lower_memspc = (pciauto_lower_memspc + (0x100000 - 1))
+ & ~(0x100000 - 1);
+ pciauto_lower_iospc = (pciauto_lower_iospc + (0x1000 - 1))
+ & ~(0x1000 - 1);
+
+ /* Enable memory and I/O accesses, enable bus master */
+ early_read_config_dword(hose, top_bus, current_bus, pci_devfn,
+ PCI_COMMAND, &temp);
+ early_write_config_dword(hose, top_bus, current_bus, pci_devfn,
+ PCI_COMMAND, temp | PCI_COMMAND_IO | PCI_COMMAND_MEMORY
+ | PCI_COMMAND_MASTER);
+}
+
+static void __init
+pciauto_prescan_setup_cardbus_bridge(struct pci_channel *hose,
+ int top_bus,
+ int current_bus,
+ int pci_devfn,
+ int sub_bus)
+{
+ /* Configure bus number registers */
+ early_write_config_byte(hose, top_bus, current_bus, pci_devfn,
+ PCI_PRIMARY_BUS, current_bus);
+ early_write_config_byte(hose, top_bus, current_bus, pci_devfn,
+ PCI_SECONDARY_BUS, sub_bus + 1);
+ early_write_config_byte(hose, top_bus, current_bus, pci_devfn,
+ PCI_SUBORDINATE_BUS, 0xff);
+
+ /* Align memory and I/O to 4KB and 4 byte boundaries. */
+ pciauto_lower_memspc = (pciauto_lower_memspc + (0x1000 - 1))
+ & ~(0x1000 - 1);
+ pciauto_lower_iospc = (pciauto_lower_iospc + (0x4 - 1))
+ & ~(0x4 - 1);
+
+ early_write_config_dword(hose, top_bus, current_bus, pci_devfn,
+ PCI_CB_MEMORY_BASE_0, pciauto_lower_memspc);
+ early_write_config_dword(hose, top_bus, current_bus, pci_devfn,
+ PCI_CB_IO_BASE_0, pciauto_lower_iospc);
+}
+
+static void __init
+pciauto_postscan_setup_cardbus_bridge(struct pci_channel *hose,
+ int top_bus,
+ int current_bus,
+ int pci_devfn,
+ int sub_bus)
+{
+ u32 temp;
+
+#if !defined(CONFIG_SH_HS7751RVOIP) && !defined(CONFIG_SH_RTS7751R2D)
+ /*
+ * [jsun] we always bump up baselines a little, so that if there
+ * nothing behind P2P bridge, we don't wind up overlapping IO/MEM
+ * spaces.
+ */
+ pciauto_lower_memspc += 1;
+ pciauto_lower_iospc += 1;
+#endif
+
+ /*
+ * Configure subordinate bus number. The PCI subsystem
+ * bus scan will renumber buses (reserving three additional
+ * for this PCI<->CardBus bridge for the case where a CardBus
+ * adapter contains a P2P or CB2CB bridge.
+ */
+
+ early_write_config_byte(hose, top_bus, current_bus, pci_devfn,
+ PCI_SUBORDINATE_BUS, sub_bus);
+
+ /*
+ * Reserve an additional 4MB for mem space and 16KB for
+ * I/O space. This should cover any additional space
+ * requirement of unusual CardBus devices with
+ * additional bridges that can consume more address space.
+ *
+ * Although pcmcia-cs currently will reprogram bridge
+ * windows, the goal is to add an option to leave them
+ * alone and use the bridge window ranges as the regions
+ * that are searched for free resources upon hot-insertion
+ * of a device. This will allow a PCI<->CardBus bridge
+ * configured by this routine to happily live behind a
+ * P2P bridge in a system.
+ */
+#if defined(CONFIG_SH_HS7751RVOIP) || defined(CONFIG_SH_RTS7751R2D)
+ pciauto_lower_memspc += 0x00400000;
+ pciauto_lower_iospc += 0x00004000;
+#endif
+
+ /* Align memory and I/O to 4KB and 4 byte boundaries. */
+ pciauto_lower_memspc = (pciauto_lower_memspc + (0x1000 - 1))
+ & ~(0x1000 - 1);
+ pciauto_lower_iospc = (pciauto_lower_iospc + (0x4 - 1))
+ & ~(0x4 - 1);
+ /* Set up memory and I/O filter limits, assume 32-bit I/O space */
+ early_write_config_dword(hose, top_bus, current_bus, pci_devfn,
+ PCI_CB_MEMORY_LIMIT_0, pciauto_lower_memspc - 1);
+ early_write_config_dword(hose, top_bus, current_bus, pci_devfn,
+ PCI_CB_IO_LIMIT_0, pciauto_lower_iospc - 1);
+
+ /* Enable memory and I/O accesses, enable bus master */
+ early_read_config_dword(hose, top_bus, current_bus, pci_devfn,
+ PCI_COMMAND, &temp);
+ early_write_config_dword(hose, top_bus, current_bus, pci_devfn,
+ PCI_COMMAND, temp | PCI_COMMAND_IO | PCI_COMMAND_MEMORY |
+ PCI_COMMAND_MASTER);
+}
+
+#define PCIAUTO_IDE_MODE_MASK 0x05
+
+static int __init
+pciauto_bus_scan(struct pci_channel *hose, int top_bus, int current_bus)
+{
+ int sub_bus;
+ u32 pci_devfn, pci_class, cmdstat, found_multi=0;
+ unsigned short vid, did;
+ unsigned char header_type;
+ int devfn_start = 0;
+ int devfn_stop = 0xff;
+
+ sub_bus = current_bus;
+
+ if (hose->first_devfn)
+ devfn_start = hose->first_devfn;
+ if (hose->last_devfn)
+ devfn_stop = hose->last_devfn;
+
+ for (pci_devfn=devfn_start; pci_devfn<devfn_stop; pci_devfn++) {
+
+ if (PCI_FUNC(pci_devfn) && !found_multi)
+ continue;
+
+ early_read_config_word(hose, top_bus, current_bus, pci_devfn,
+ PCI_VENDOR_ID, &vid);
+
+ if (vid == 0xffff) continue;
+
+ early_read_config_byte(hose, top_bus, current_bus, pci_devfn,
+ PCI_HEADER_TYPE, &header_type);
+
+ if (!PCI_FUNC(pci_devfn))
+ found_multi = header_type & 0x80;
+
+ early_read_config_word(hose, top_bus, current_bus, pci_devfn,
+ PCI_DEVICE_ID, &did);
+
+ early_read_config_dword(hose, top_bus, current_bus, pci_devfn,
+ PCI_CLASS_REVISION, &pci_class);
+
+ DBG("%.2x:%.2x.%x Class %.4x: %.4x:%.4x",
+ current_bus, PCI_SLOT(pci_devfn), PCI_FUNC(pci_devfn),
+ pci_class >> 16, vid, did);
+ if (pci_class & 0xff)
+ DBG(" (rev %.2x)", pci_class & 0xff);
+ DBG("\n");
+
+ if ((pci_class >> 16) == PCI_CLASS_BRIDGE_PCI) {
+ DBG(" Bridge: primary=%.2x, secondary=%.2x\n",
+ current_bus, sub_bus + 1);
+#if defined(CONFIG_SH_HS7751RVOIP) || defined(CONFIG_SH_RTS7751R2D)
+ pciauto_setup_bars(hose, top_bus, current_bus, pci_devfn, PCI_BASE_ADDRESS_1);
+#endif
+ pciauto_prescan_setup_bridge(hose, top_bus, current_bus,
+ pci_devfn, sub_bus);
+ DBG("Scanning sub bus %.2x, I/O 0x%.8x, Mem 0x%.8x\n",
+ sub_bus + 1,
+ pciauto_lower_iospc, pciauto_lower_memspc);
+ sub_bus = pciauto_bus_scan(hose, top_bus, sub_bus+1);
+ DBG("Back to bus %.2x\n", current_bus);
+ pciauto_postscan_setup_bridge(hose, top_bus, current_bus,
+ pci_devfn, sub_bus);
+ continue;
+ } else if ((pci_class >> 16) == PCI_CLASS_BRIDGE_CARDBUS) {
+ DBG(" CARDBUS Bridge: primary=%.2x, secondary=%.2x\n",
+ current_bus, sub_bus + 1);
+ DBG("PCI Autoconfig: Found CardBus bridge, device %d function %d\n", PCI_SLOT(pci_devfn), PCI_FUNC(pci_devfn));
+ /* Place CardBus Socket/ExCA registers */
+ pciauto_setup_bars(hose, top_bus, current_bus, pci_devfn, PCI_BASE_ADDRESS_0);
+
+ pciauto_prescan_setup_cardbus_bridge(hose, top_bus,
+ current_bus, pci_devfn, sub_bus);
+
+ DBG("Scanning sub bus %.2x, I/O 0x%.8x, Mem 0x%.8x\n",
+ sub_bus + 1,
+ pciauto_lower_iospc, pciauto_lower_memspc);
+ sub_bus = pciauto_bus_scan(hose, top_bus, sub_bus+1);
+ DBG("Back to bus %.2x, sub_bus is %x\n", current_bus, sub_bus);
+ pciauto_postscan_setup_cardbus_bridge(hose, top_bus,
+ current_bus, pci_devfn, sub_bus);
+ continue;
+ } else if ((pci_class >> 16) == PCI_CLASS_STORAGE_IDE) {
+
+ unsigned char prg_iface;
+
+ early_read_config_byte(hose, top_bus, current_bus,
+ pci_devfn, PCI_CLASS_PROG, &prg_iface);
+ if (!(prg_iface & PCIAUTO_IDE_MODE_MASK)) {
+ DBG("Skipping legacy mode IDE controller\n");
+ continue;
+ }
+ }
+
+ /*
+ * Found a peripheral, enable some standard
+ * settings
+ */
+ early_read_config_dword(hose, top_bus, current_bus, pci_devfn,
+ PCI_COMMAND, &cmdstat);
+ early_write_config_dword(hose, top_bus, current_bus, pci_devfn,
+ PCI_COMMAND, cmdstat | PCI_COMMAND_IO |
+ PCI_COMMAND_MEMORY |
+ PCI_COMMAND_MASTER);
+#if !defined(CONFIG_SH_HS7751RVOIP) && !defined(CONFIG_SH_RTS7751R2D)
+ early_write_config_byte(hose, top_bus, current_bus, pci_devfn,
+ PCI_LATENCY_TIMER, 0x80);
+#endif
+
+ /* Allocate PCI I/O and/or memory space */
+ pciauto_setup_bars(hose, top_bus, current_bus, pci_devfn, PCI_BASE_ADDRESS_5);
+ }
+ return sub_bus;
+}
+
+int __init
+pciauto_assign_resources(int busno, struct pci_channel *hose)
+{
+ /* setup resource limits */
+ io_resource_inuse = hose->io_resource;
+ mem_resource_inuse = hose->mem_resource;
+
+ pciauto_lower_iospc = io_resource_inuse->start;
+ pciauto_upper_iospc = io_resource_inuse->end + 1;
+ pciauto_lower_memspc = mem_resource_inuse->start;
+ pciauto_upper_memspc = mem_resource_inuse->end + 1;
+ DBG("Autoconfig PCI channel 0x%p\n", hose);
+ DBG("Scanning bus %.2x, I/O 0x%.8x:0x%.8x, Mem 0x%.8x:0x%.8x\n",
+ busno, pciauto_lower_iospc, pciauto_upper_iospc,
+ pciauto_lower_memspc, pciauto_upper_memspc);
+
+ return pciauto_bus_scan(hose, busno, busno);
+}
diff --git a/arch/sh/drivers/pci/pci-sh7751.c b/arch/sh/drivers/pci/pci-sh7751.c
new file mode 100644
index 000000000000..30b14ac7ae5a
--- /dev/null
+++ b/arch/sh/drivers/pci/pci-sh7751.c
@@ -0,0 +1,417 @@
+/*
+ * Low-Level PCI Support for the SH7751
+ *
+ * Dustin McIntire (dustin@sensoria.com)
+ * Derived from arch/i386/kernel/pci-*.c which bore the message:
+ * (c) 1999--2000 Martin Mares <mj@ucw.cz>
+ *
+ * Ported to the new API by Paul Mundt <lethal@linux-sh.org>
+ * With cleanup by Paul van Gool <pvangool@mimotech.com>
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License. See linux/COPYING for more information.
+ *
+ */
+
+#undef DEBUG
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/sched.h>
+#include <linux/ioport.h>
+#include <linux/errno.h>
+#include <linux/irq.h>
+#include <linux/delay.h>
+
+#include <asm/machvec.h>
+#include <asm/io.h>
+#include "pci-sh7751.h"
+
+static unsigned int pci_probe = PCI_PROBE_CONF1;
+extern int pci_fixup_pcic(void);
+
+void pcibios_fixup_irqs(void) __attribute__ ((weak));
+
+/*
+ * Direct access to PCI hardware...
+ */
+
+#define CONFIG_CMD(bus, devfn, where) (0x80000000 | (bus->number << 16) | (devfn << 8) | (where & ~3))
+
+/*
+ * Functions for accessing PCI configuration space with type 1 accesses
+ */
+static int sh7751_pci_read(struct pci_bus *bus, unsigned int devfn,
+ int where, int size, u32 *val)
+{
+ unsigned long flags;
+ u32 data;
+
+ /*
+ * PCIPDR may only be accessed as 32 bit words,
+ * so we must do byte alignment by hand
+ */
+ local_irq_save(flags);
+ outl(CONFIG_CMD(bus,devfn,where), PCI_REG(SH7751_PCIPAR));
+ data = inl(PCI_REG(SH7751_PCIPDR));
+ local_irq_restore(flags);
+
+ switch (size) {
+ case 1:
+ *val = (data >> ((where & 3) << 3)) & 0xff;
+ break;
+ case 2:
+ *val = (data >> ((where & 2) << 3)) & 0xffff;
+ break;
+ case 4:
+ *val = data;
+ break;
+ default:
+ return PCIBIOS_FUNC_NOT_SUPPORTED;
+ }
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+/*
+ * Since SH7751 only does 32bit access we'll have to do a read,
+ * mask,write operation.
+ * We'll allow an odd byte offset, though it should be illegal.
+ */
+static int sh7751_pci_write(struct pci_bus *bus, unsigned int devfn,
+ int where, int size, u32 val)
+{
+ unsigned long flags;
+ int shift;
+ u32 data;
+
+ local_irq_save(flags);
+ outl(CONFIG_CMD(bus,devfn,where), PCI_REG(SH7751_PCIPAR));
+ data = inl(PCI_REG(SH7751_PCIPDR));
+ local_irq_restore(flags);
+
+ switch (size) {
+ case 1:
+ shift = (where & 3) << 3;
+ data &= ~(0xff << shift);
+ data |= ((val & 0xff) << shift);
+ break;
+ case 2:
+ shift = (where & 2) << 3;
+ data &= ~(0xffff << shift);
+ data |= ((val & 0xffff) << shift);
+ break;
+ case 4:
+ data = val;
+ break;
+ default:
+ return PCIBIOS_FUNC_NOT_SUPPORTED;
+ }
+
+ outl(data, PCI_REG(SH7751_PCIPDR));
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+#undef CONFIG_CMD
+
+struct pci_ops sh7751_pci_ops = {
+ .read = sh7751_pci_read,
+ .write = sh7751_pci_write,
+};
+
+static int __init pci_check_direct(void)
+{
+ unsigned int tmp, id;
+
+ /* check for SH7751/SH7751R hardware */
+ id = inl(SH7751_PCIREG_BASE+SH7751_PCICONF0);
+ if (id != ((SH7751_DEVICE_ID << 16) | SH7751_VENDOR_ID) &&
+ id != ((SH7751R_DEVICE_ID << 16) | SH7751_VENDOR_ID)) {
+ pr_debug("PCI: This is not an SH7751(R) (%x)\n", id);
+ return -ENODEV;
+ }
+
+ /*
+ * Check if configuration works.
+ */
+ if (pci_probe & PCI_PROBE_CONF1) {
+ tmp = inl (PCI_REG(SH7751_PCIPAR));
+ outl (0x80000000, PCI_REG(SH7751_PCIPAR));
+ if (inl (PCI_REG(SH7751_PCIPAR)) == 0x80000000) {
+ outl (tmp, PCI_REG(SH7751_PCIPAR));
+ printk(KERN_INFO "PCI: Using configuration type 1\n");
+ request_region(PCI_REG(SH7751_PCIPAR), 8, "PCI conf1");
+ return 0;
+ }
+ outl (tmp, PCI_REG(SH7751_PCIPAR));
+ }
+
+ pr_debug("PCI: pci_check_direct failed\n");
+ return -EINVAL;
+}
+
+/***************************************************************************************/
+
+/*
+ * Handle bus scanning and fixups ....
+ */
+
+static void __init pci_fixup_ide_bases(struct pci_dev *d)
+{
+ int i;
+
+ /*
+ * PCI IDE controllers use non-standard I/O port decoding, respect it.
+ */
+ if ((d->class >> 8) != PCI_CLASS_STORAGE_IDE)
+ return;
+ pr_debug("PCI: IDE base address fixup for %s\n", pci_name(d));
+ for(i=0; i<4; i++) {
+ struct resource *r = &d->resource[i];
+ if ((r->start & ~0x80) == 0x374) {
+ r->start |= 2;
+ r->end = r->start;
+ }
+ }
+}
+
+DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_ide_bases);
+
+/*
+ * Called after each bus is probed, but before its children
+ * are examined.
+ */
+
+void __init pcibios_fixup_bus(struct pci_bus *b)
+{
+ pci_read_bridge_bases(b);
+}
+
+/*
+ * Initialization. Try all known PCI access methods. Note that we support
+ * using both PCI BIOS and direct access: in such cases, we use I/O ports
+ * to access config space.
+ *
+ * Note that the platform specific initialization (BSC registers, and memory
+ * space mapping) will be called via the machine vectors (sh_mv.mv_pci_init()) if it
+ * exitst and via the platform defined function pcibios_init_platform().
+ * See pci_bigsur.c for implementation;
+ *
+ * The BIOS version of the pci functions is not yet implemented but it is left
+ * in for completeness. Currently an error will be genereated at compile time.
+ */
+
+static int __init sh7751_pci_init(void)
+{
+ int ret;
+
+ pr_debug("PCI: Starting intialization.\n");
+ if ((ret = pci_check_direct()) != 0)
+ return ret;
+
+ return pcibios_init_platform();
+}
+
+subsys_initcall(sh7751_pci_init);
+
+static int __init __area_sdram_check(unsigned int area)
+{
+ u32 word;
+
+ word = inl(SH7751_BCR1);
+ /* check BCR for SDRAM in area */
+ if(((word >> area) & 1) == 0) {
+ printk("PCI: Area %d is not configured for SDRAM. BCR1=0x%x\n",
+ area, word);
+ return 0;
+ }
+ outl(word, PCI_REG(SH7751_PCIBCR1));
+
+ word = (u16)inw(SH7751_BCR2);
+ /* check BCR2 for 32bit SDRAM interface*/
+ if(((word >> (area << 1)) & 0x3) != 0x3) {
+ printk("PCI: Area %d is not 32 bit SDRAM. BCR2=0x%x\n",
+ area, word);
+ return 0;
+ }
+ outl(word, PCI_REG(SH7751_PCIBCR2));
+
+ return 1;
+}
+
+int __init sh7751_pcic_init(struct sh7751_pci_address_map *map)
+{
+ u32 reg;
+ u32 word;
+
+ /* Set the BCR's to enable PCI access */
+ reg = inl(SH7751_BCR1);
+ reg |= 0x80000;
+ outl(reg, SH7751_BCR1);
+
+ /* Turn the clocks back on (not done in reset)*/
+ outl(0, PCI_REG(SH7751_PCICLKR));
+ /* Clear Powerdown IRQ's (not done in reset) */
+ word = SH7751_PCIPINT_D3 | SH7751_PCIPINT_D0;
+ outl(word, PCI_REG(SH7751_PCIPINT));
+
+ /*
+ * This code is unused for some boards as it is done in the
+ * bootloader and doing it here means the MAC addresses loaded
+ * by the bootloader get lost.
+ */
+ if (!(map->flags & SH7751_PCIC_NO_RESET)) {
+ /* toggle PCI reset pin */
+ word = SH7751_PCICR_PREFIX | SH7751_PCICR_PRST;
+ outl(word,PCI_REG(SH7751_PCICR));
+ /* Wait for a long time... not 1 sec. but long enough */
+ mdelay(100);
+ word = SH7751_PCICR_PREFIX;
+ outl(word,PCI_REG(SH7751_PCICR));
+ }
+
+ /* set the command/status bits to:
+ * Wait Cycle Control + Parity Enable + Bus Master +
+ * Mem space enable
+ */
+ word = SH7751_PCICONF1_WCC | SH7751_PCICONF1_PER |
+ SH7751_PCICONF1_BUM | SH7751_PCICONF1_MES;
+ outl(word, PCI_REG(SH7751_PCICONF1));
+
+ /* define this host as the host bridge */
+ word = SH7751_PCI_HOST_BRIDGE << 24;
+ outl(word, PCI_REG(SH7751_PCICONF2));
+
+ /* Set IO and Mem windows to local address
+ * Make PCI and local address the same for easy 1 to 1 mapping
+ * Window0 = map->window0.size @ non-cached area base = SDRAM
+ * Window1 = map->window1.size @ cached area base = SDRAM
+ */
+ word = map->window0.size - 1;
+ outl(word, PCI_REG(SH7751_PCILSR0));
+ word = map->window1.size - 1;
+ outl(word, PCI_REG(SH7751_PCILSR1));
+ /* Set the values on window 0 PCI config registers */
+ word = P2SEGADDR(map->window0.base);
+ outl(word, PCI_REG(SH7751_PCILAR0));
+ outl(word, PCI_REG(SH7751_PCICONF5));
+ /* Set the values on window 1 PCI config registers */
+ word = PHYSADDR(map->window1.base);
+ outl(word, PCI_REG(SH7751_PCILAR1));
+ outl(word, PCI_REG(SH7751_PCICONF6));
+
+ /* Set the local 16MB PCI memory space window to
+ * the lowest PCI mapped address
+ */
+ word = PCIBIOS_MIN_MEM & SH7751_PCIMBR_MASK;
+ PCIDBG(2,"PCI: Setting upper bits of Memory window to 0x%x\n", word);
+ outl(word , PCI_REG(SH7751_PCIMBR));
+
+ /* Map IO space into PCI IO window
+ * The IO window is 64K-PCIBIOS_MIN_IO in size
+ * IO addresses will be translated to the
+ * PCI IO window base address
+ */
+ PCIDBG(3,"PCI: Mapping IO address 0x%x - 0x%x to base 0x%x\n", PCIBIOS_MIN_IO,
+ (64*1024), SH7751_PCI_IO_BASE+PCIBIOS_MIN_IO);
+
+ /*
+ * XXX: For now, leave this board-specific. In the event we have other
+ * boards that need to do similar work, this can be wrapped.
+ */
+#ifdef CONFIG_SH_BIGSUR
+ bigsur_port_map(PCIBIOS_MIN_IO, (64*1024), SH7751_PCI_IO_BASE+PCIBIOS_MIN_IO,0);
+#endif
+
+ /* Make sure the MSB's of IO window are set to access PCI space correctly */
+ word = PCIBIOS_MIN_IO & SH7751_PCIIOBR_MASK;
+ PCIDBG(2,"PCI: Setting upper bits of IO window to 0x%x\n", word);
+ outl(word, PCI_REG(SH7751_PCIIOBR));
+
+ /* Set PCI WCRx, BCRx's, copy from BSC locations */
+
+ /* check BCR for SDRAM in specified area */
+ switch (map->window0.base) {
+ case SH7751_CS0_BASE_ADDR: word = __area_sdram_check(0); break;
+ case SH7751_CS1_BASE_ADDR: word = __area_sdram_check(1); break;
+ case SH7751_CS2_BASE_ADDR: word = __area_sdram_check(2); break;
+ case SH7751_CS3_BASE_ADDR: word = __area_sdram_check(3); break;
+ case SH7751_CS4_BASE_ADDR: word = __area_sdram_check(4); break;
+ case SH7751_CS5_BASE_ADDR: word = __area_sdram_check(5); break;
+ case SH7751_CS6_BASE_ADDR: word = __area_sdram_check(6); break;
+ }
+
+ if (!word)
+ return 0;
+
+ /* configure the wait control registers */
+ word = inl(SH7751_WCR1);
+ outl(word, PCI_REG(SH7751_PCIWCR1));
+ word = inl(SH7751_WCR2);
+ outl(word, PCI_REG(SH7751_PCIWCR2));
+ word = inl(SH7751_WCR3);
+ outl(word, PCI_REG(SH7751_PCIWCR3));
+ word = inl(SH7751_MCR);
+ outl(word, PCI_REG(SH7751_PCIMCR));
+
+ /* NOTE: I'm ignoring the PCI error IRQs for now..
+ * TODO: add support for the internal error interrupts and
+ * DMA interrupts...
+ */
+
+#ifdef CONFIG_SH_RTS7751R2D
+ pci_fixup_pcic();
+#endif
+
+ /* SH7751 init done, set central function init complete */
+ /* use round robin mode to stop a device starving/overruning */
+ word = SH7751_PCICR_PREFIX | SH7751_PCICR_CFIN | SH7751_PCICR_ARBM;
+ outl(word,PCI_REG(SH7751_PCICR));
+
+ return 1;
+}
+
+char * __init pcibios_setup(char *str)
+{
+ if (!strcmp(str, "off")) {
+ pci_probe = 0;
+ return NULL;
+ }
+
+ return str;
+}
+
+/*
+ * IRQ functions
+ */
+static u8 __init sh7751_no_swizzle(struct pci_dev *dev, u8 *pin)
+{
+ /* no swizzling */
+ return PCI_SLOT(dev->devfn);
+}
+
+static int sh7751_pci_lookup_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+ int irq = -1;
+
+ /* now lookup the actual IRQ on a platform specific basis (pci-'platform'.c) */
+ irq = pcibios_map_platform_irq(slot,pin);
+ if( irq < 0 ) {
+ pr_debug("PCI: Error mapping IRQ on device %s\n", pci_name(dev));
+ return irq;
+ }
+
+ pr_debug("Setting IRQ for slot %s to %d\n", pci_name(dev), irq);
+
+ return irq;
+}
+
+void __init pcibios_fixup_irqs(void)
+{
+ pci_fixup_irqs(sh7751_no_swizzle, sh7751_pci_lookup_irq);
+}
+
diff --git a/arch/sh/drivers/pci/pci-sh7751.h b/arch/sh/drivers/pci/pci-sh7751.h
new file mode 100644
index 000000000000..1fee5cae10d1
--- /dev/null
+++ b/arch/sh/drivers/pci/pci-sh7751.h
@@ -0,0 +1,303 @@
+/*
+ * Low-Level PCI Support for SH7751 targets
+ *
+ * Dustin McIntire (dustin@sensoria.com) (c) 2001
+ * Paul Mundt (lethal@linux-sh.org) (c) 2003
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License. See linux/COPYING for more information.
+ *
+ */
+
+#ifndef _PCI_SH7751_H_
+#define _PCI_SH7751_H_
+
+#include <linux/pci.h>
+
+/* set debug level 4=verbose...1=terse */
+//#define DEBUG_PCI 3
+#undef DEBUG_PCI
+
+#ifdef DEBUG_PCI
+#define PCIDBG(n, x...) { if(DEBUG_PCI>=n) printk(x); }
+#else
+#define PCIDBG(n, x...)
+#endif
+
+/* startup values */
+#define PCI_PROBE_BIOS 1
+#define PCI_PROBE_CONF1 2
+#define PCI_PROBE_CONF2 4
+#define PCI_NO_SORT 0x100
+#define PCI_BIOS_SORT 0x200
+#define PCI_NO_CHECKS 0x400
+#define PCI_ASSIGN_ROMS 0x1000
+#define PCI_BIOS_IRQ_SCAN 0x2000
+
+/* Platform Specific Values */
+#define SH7751_VENDOR_ID 0x1054
+#define SH7751_DEVICE_ID 0x3505
+#define SH7751R_DEVICE_ID 0x350e
+
+/* SH7751 Specific Values */
+#define SH7751_PCI_CONFIG_BASE 0xFD000000 /* Config space base addr */
+#define SH7751_PCI_CONFIG_SIZE 0x1000000 /* Config space size */
+#define SH7751_PCI_MEMORY_BASE 0xFD000000 /* Memory space base addr */
+#define SH7751_PCI_MEM_SIZE 0x01000000 /* Size of Memory window */
+#define SH7751_PCI_IO_BASE 0xFE240000 /* IO space base address */
+#define SH7751_PCI_IO_SIZE 0x40000 /* Size of IO window */
+
+#define SH7751_PCIREG_BASE 0xFE200000 /* PCI regs base address */
+#define PCI_REG(n) (SH7751_PCIREG_BASE+ n)
+
+#define SH7751_PCICONF0 0x0 /* PCI Config Reg 0 */
+ #define SH7751_PCICONF0_DEVID 0xFFFF0000 /* Device ID */
+ #define SH7751_PCICONF0_VNDID 0x0000FFFF /* Vendor ID */
+#define SH7751_PCICONF1 0x4 /* PCI Config Reg 1 */
+ #define SH7751_PCICONF1_DPE 0x80000000 /* Data Parity Error */
+ #define SH7751_PCICONF1_SSE 0x40000000 /* System Error Status */
+ #define SH7751_PCICONF1_RMA 0x20000000 /* Master Abort */
+ #define SH7751_PCICONF1_RTA 0x10000000 /* Target Abort Rx Status */
+ #define SH7751_PCICONF1_STA 0x08000000 /* Target Abort Exec Status */
+ #define SH7751_PCICONF1_DEV 0x06000000 /* Timing Status */
+ #define SH7751_PCICONF1_DPD 0x01000000 /* Data Parity Status */
+ #define SH7751_PCICONF1_FBBC 0x00800000 /* Back 2 Back Status */
+ #define SH7751_PCICONF1_UDF 0x00400000 /* User Defined Status */
+ #define SH7751_PCICONF1_66M 0x00200000 /* 66Mhz Operation Status */
+ #define SH7751_PCICONF1_PM 0x00100000 /* Power Management Status */
+ #define SH7751_PCICONF1_PBBE 0x00000200 /* Back 2 Back Control */
+ #define SH7751_PCICONF1_SER 0x00000100 /* SERR Output Control */
+ #define SH7751_PCICONF1_WCC 0x00000080 /* Wait Cycle Control */
+ #define SH7751_PCICONF1_PER 0x00000040 /* Parity Error Response */
+ #define SH7751_PCICONF1_VPS 0x00000020 /* VGA Pallet Snoop */
+ #define SH7751_PCICONF1_MWIE 0x00000010 /* Memory Write+Invalidate */
+ #define SH7751_PCICONF1_SPC 0x00000008 /* Special Cycle Control */
+ #define SH7751_PCICONF1_BUM 0x00000004 /* Bus Master Control */
+ #define SH7751_PCICONF1_MES 0x00000002 /* Memory Space Control */
+ #define SH7751_PCICONF1_IOS 0x00000001 /* I/O Space Control */
+#define SH7751_PCICONF2 0x8 /* PCI Config Reg 2 */
+ #define SH7751_PCICONF2_BCC 0xFF000000 /* Base Class Code */
+ #define SH7751_PCICONF2_SCC 0x00FF0000 /* Sub-Class Code */
+ #define SH7751_PCICONF2_RLPI 0x0000FF00 /* Programming Interface */
+ #define SH7751_PCICONF2_REV 0x000000FF /* Revision ID */
+#define SH7751_PCICONF3 0xC /* PCI Config Reg 3 */
+ #define SH7751_PCICONF3_BIST7 0x80000000 /* Bist Supported */
+ #define SH7751_PCICONF3_BIST6 0x40000000 /* Bist Executing */
+ #define SH7751_PCICONF3_BIST3_0 0x0F000000 /* Bist Passed */
+ #define SH7751_PCICONF3_HD7 0x00800000 /* Single Funtion device */
+ #define SH7751_PCICONF3_HD6_0 0x007F0000 /* Configuration Layout */
+ #define SH7751_PCICONF3_LAT 0x0000FF00 /* Latency Timer */
+ #define SH7751_PCICONF3_CLS 0x000000FF /* Cache Line Size */
+#define SH7751_PCICONF4 0x10 /* PCI Config Reg 4 */
+ #define SH7751_PCICONF4_BASE 0xFFFFFFFC /* I/O Space Base Addr */
+ #define SH7751_PCICONF4_ASI 0x00000001 /* Address Space Type */
+#define SH7751_PCICONF5 0x14 /* PCI Config Reg 5 */
+ #define SH7751_PCICONF5_BASE 0xFFFFFFF0 /* Mem Space Base Addr */
+ #define SH7751_PCICONF5_LAP 0x00000008 /* Prefetch Enabled */
+ #define SH7751_PCICONF5_LAT 0x00000006 /* Local Memory type */
+ #define SH7751_PCICONF5_ASI 0x00000001 /* Address Space Type */
+#define SH7751_PCICONF6 0x18 /* PCI Config Reg 6 */
+ #define SH7751_PCICONF6_BASE 0xFFFFFFF0 /* Mem Space Base Addr */
+ #define SH7751_PCICONF6_LAP 0x00000008 /* Prefetch Enabled */
+ #define SH7751_PCICONF6_LAT 0x00000006 /* Local Memory type */
+ #define SH7751_PCICONF6_ASI 0x00000001 /* Address Space Type */
+/* PCICONF7 - PCICONF10 are undefined */
+#define SH7751_PCICONF11 0x2C /* PCI Config Reg 11 */
+ #define SH7751_PCICONF11_SSID 0xFFFF0000 /* Subsystem ID */
+ #define SH7751_PCICONF11_SVID 0x0000FFFF /* Subsystem Vendor ID */
+/* PCICONF12 is undefined */
+#define SH7751_PCICONF13 0x34 /* PCI Config Reg 13 */
+ #define SH7751_PCICONF13_CPTR 0x000000FF /* PM function pointer */
+/* PCICONF14 is undefined */
+#define SH7751_PCICONF15 0x3C /* PCI Config Reg 15 */
+ #define SH7751_PCICONF15_IPIN 0x000000FF /* Interrupt Pin */
+#define SH7751_PCICONF16 0x40 /* PCI Config Reg 16 */
+ #define SH7751_PCICONF16_PMES 0xF8000000 /* PME Support */
+ #define SH7751_PCICONF16_D2S 0x04000000 /* D2 Support */
+ #define SH7751_PCICONF16_D1S 0x02000000 /* D1 Support */
+ #define SH7751_PCICONF16_DSI 0x00200000 /* Bit Device Init. */
+ #define SH7751_PCICONF16_PMCK 0x00080000 /* Clock for PME req. */
+ #define SH7751_PCICONF16_VER 0x00070000 /* PM Version */
+ #define SH7751_PCICONF16_NIP 0x0000FF00 /* Next Item Pointer */
+ #define SH7751_PCICONF16_CID 0x000000FF /* Capability Identifier */
+#define SH7751_PCICONF17 0x44 /* PCI Config Reg 17 */
+ #define SH7751_PCICONF17_DATA 0xFF000000 /* Data field for PM */
+ #define SH7751_PCICONF17_PMES 0x00800000 /* PME Status */
+ #define SH7751_PCICONF17_DSCL 0x00600000 /* Data Scaling Value */
+ #define SH7751_PCICONF17_DSEL 0x001E0000 /* Data Select */
+ #define SH7751_PCICONF17_PMEN 0x00010000 /* PME Enable */
+ #define SH7751_PCICONF17_PWST 0x00000003 /* Power State */
+/* SH7715 Internal PCI Registers */
+#define SH7751_PCICR 0x100 /* PCI Control Register */
+ #define SH7751_PCICR_PREFIX 0xA5000000 /* CR prefix for write */
+ #define SH7751_PCICR_TRSB 0x00000200 /* Target Read Single */
+ #define SH7751_PCICR_BSWP 0x00000100 /* Target Byte Swap */
+ #define SH7751_PCICR_PLUP 0x00000080 /* Enable PCI Pullup */
+ #define SH7751_PCICR_ARBM 0x00000040 /* PCI Arbitration Mode */
+ #define SH7751_PCICR_MD 0x00000030 /* MD9 and MD10 status */
+ #define SH7751_PCICR_SERR 0x00000008 /* SERR output assert */
+ #define SH7751_PCICR_INTA 0x00000004 /* INTA output assert */
+ #define SH7751_PCICR_PRST 0x00000002 /* PCI Reset Assert */
+ #define SH7751_PCICR_CFIN 0x00000001 /* Central Fun. Init Done */
+#define SH7751_PCILSR0 0x104 /* PCI Local Space Register0 */
+#define SH7751_PCILSR1 0x108 /* PCI Local Space Register1 */
+#define SH7751_PCILAR0 0x10C /* PCI Local Address Register1 */
+#define SH7751_PCILAR1 0x110 /* PCI Local Address Register1 */
+#define SH7751_PCIINT 0x114 /* PCI Interrupt Register */
+ #define SH7751_PCIINT_MLCK 0x00008000 /* Master Lock Error */
+ #define SH7751_PCIINT_TABT 0x00004000 /* Target Abort Error */
+ #define SH7751_PCIINT_TRET 0x00000200 /* Target Retry Error */
+ #define SH7751_PCIINT_MFDE 0x00000100 /* Master Func. Disable Error */
+ #define SH7751_PCIINT_PRTY 0x00000080 /* Address Parity Error */
+ #define SH7751_PCIINT_SERR 0x00000040 /* SERR Detection Error */
+ #define SH7751_PCIINT_TWDP 0x00000020 /* Tgt. Write Parity Error */
+ #define SH7751_PCIINT_TRDP 0x00000010 /* Tgt. Read Parity Error Det. */
+ #define SH7751_PCIINT_MTABT 0x00000008 /* Master-Tgt. Abort Error */
+ #define SH7751_PCIINT_MMABT 0x00000004 /* Master-Master Abort Error */
+ #define SH7751_PCIINT_MWPD 0x00000002 /* Master Write PERR Detect */
+ #define SH7751_PCIINT_MRPD 0x00000002 /* Master Read PERR Detect */
+#define SH7751_PCIINTM 0x118 /* PCI Interrupt Mask Register */
+#define SH7751_PCIALR 0x11C /* Error Address Register */
+#define SH7751_PCICLR 0x120 /* Error Command/Data Register */
+ #define SH7751_PCICLR_MPIO 0x80000000 /* Error Command/Data Register */
+ #define SH7751_PCICLR_MDMA0 0x40000000 /* DMA0 Transfer Error */
+ #define SH7751_PCICLR_MDMA1 0x20000000 /* DMA1 Transfer Error */
+ #define SH7751_PCICLR_MDMA2 0x10000000 /* DMA2 Transfer Error */
+ #define SH7751_PCICLR_MDMA3 0x08000000 /* DMA3 Transfer Error */
+ #define SH7751_PCICLR_TGT 0x04000000 /* Target Transfer Error */
+ #define SH7751_PCICLR_CMDL 0x0000000F /* PCI Command at Error */
+#define SH7751_PCIAINT 0x130 /* Arbiter Interrupt Register */
+ #define SH7751_PCIAINT_MBKN 0x00002000 /* Master Broken Interrupt */
+ #define SH7751_PCIAINT_TBTO 0x00001000 /* Target Bus Time Out */
+ #define SH7751_PCIAINT_MBTO 0x00001000 /* Master Bus Time Out */
+ #define SH7751_PCIAINT_TABT 0x00000008 /* Target Abort */
+ #define SH7751_PCIAINT_MABT 0x00000004 /* Master Abort */
+ #define SH7751_PCIAINT_RDPE 0x00000002 /* Read Data Parity Error */
+ #define SH7751_PCIAINT_WDPE 0x00000002 /* Write Data Parity Error */
+#define SH7751_PCIAINTM 0x134 /* Arbiter Int. Mask Register */
+#define SH7751_PCIBMLR 0x138 /* Error Bus Master Register */
+ #define SH7751_PCIBMLR_REQ4 0x00000010 /* REQ4 bus master at error */
+ #define SH7751_PCIBMLR_REQ3 0x00000008 /* REQ3 bus master at error */
+ #define SH7751_PCIBMLR_REQ2 0x00000004 /* REQ2 bus master at error */
+ #define SH7751_PCIBMLR_REQ1 0x00000002 /* REQ1 bus master at error */
+ #define SH7751_PCIBMLR_REQ0 0x00000001 /* REQ0 bus master at error */
+#define SH7751_PCIDMABT 0x140 /* DMA Transfer Arb. Register */
+ #define SH7751_PCIDMABT_RRBN 0x00000001 /* DMA Arbitor Round-Robin */
+#define SH7751_PCIDPA0 0x180 /* DMA0 Transfer Addr. Register */
+#define SH7751_PCIDLA0 0x184 /* DMA0 Local Addr. Register */
+#define SH7751_PCIDTC0 0x188 /* DMA0 Transfer Cnt. Register */
+#define SH7751_PCIDCR0 0x18C /* DMA0 Control Register */
+ #define SH7751_PCIDCR_ALGN 0x00000600 /* DMA Alignment Mode */
+ #define SH7751_PCIDCR_MAST 0x00000100 /* DMA Termination Type */
+ #define SH7751_PCIDCR_INTM 0x00000080 /* DMA Interrupt Done Mask*/
+ #define SH7751_PCIDCR_INTS 0x00000040 /* DMA Interrupt Done Status */
+ #define SH7751_PCIDCR_LHLD 0x00000020 /* Local Address Control */
+ #define SH7751_PCIDCR_PHLD 0x00000010 /* PCI Address Control*/
+ #define SH7751_PCIDCR_IOSEL 0x00000008 /* PCI Address Space Type */
+ #define SH7751_PCIDCR_DIR 0x00000004 /* DMA Transfer Direction */
+ #define SH7751_PCIDCR_STOP 0x00000002 /* Force DMA Stop */
+ #define SH7751_PCIDCR_STRT 0x00000001 /* DMA Start */
+#define SH7751_PCIDPA1 0x190 /* DMA1 Transfer Addr. Register */
+#define SH7751_PCIDLA1 0x194 /* DMA1 Local Addr. Register */
+#define SH7751_PCIDTC1 0x198 /* DMA1 Transfer Cnt. Register */
+#define SH7751_PCIDCR1 0x19C /* DMA1 Control Register */
+#define SH7751_PCIDPA2 0x1A0 /* DMA2 Transfer Addr. Register */
+#define SH7751_PCIDLA2 0x1A4 /* DMA2 Local Addr. Register */
+#define SH7751_PCIDTC2 0x1A8 /* DMA2 Transfer Cnt. Register */
+#define SH7751_PCIDCR2 0x1AC /* DMA2 Control Register */
+#define SH7751_PCIDPA3 0x1B0 /* DMA3 Transfer Addr. Register */
+#define SH7751_PCIDLA3 0x1B4 /* DMA3 Local Addr. Register */
+#define SH7751_PCIDTC3 0x1B8 /* DMA3 Transfer Cnt. Register */
+#define SH7751_PCIDCR3 0x1BC /* DMA3 Control Register */
+#define SH7751_PCIPAR 0x1C0 /* PIO Address Register */
+ #define SH7751_PCIPAR_CFGEN 0x80000000 /* Configuration Enable */
+ #define SH7751_PCIPAR_BUSNO 0x00FF0000 /* Config. Bus Number */
+ #define SH7751_PCIPAR_DEVNO 0x0000FF00 /* Config. Device Number */
+ #define SH7751_PCIPAR_REGAD 0x000000FC /* Register Address Number */
+#define SH7751_PCIMBR 0x1C4 /* Memory Base Address Register */
+ #define SH7751_PCIMBR_MASK 0xFF000000 /* Memory Space Mask */
+ #define SH7751_PCIMBR_LOCK 0x00000001 /* Lock Memory Space */
+#define SH7751_PCIIOBR 0x1C8 /* I/O Base Address Register */
+ #define SH7751_PCIIOBR_MASK 0xFFFC0000 /* IO Space Mask */
+ #define SH7751_PCIIOBR_LOCK 0x00000001 /* Lock IO Space */
+#define SH7751_PCIPINT 0x1CC /* Power Mgmnt Int. Register */
+ #define SH7751_PCIPINT_D3 0x00000002 /* D3 Pwr Mgmt. Interrupt */
+ #define SH7751_PCIPINT_D0 0x00000001 /* D0 Pwr Mgmt. Interrupt */
+#define SH7751_PCIPINTM 0x1D0 /* Power Mgmnt Mask Register */
+#define SH7751_PCICLKR 0x1D4 /* Clock Ctrl. Register */
+ #define SH7751_PCICLKR_PCSTP 0x00000002 /* PCI Clock Stop */
+ #define SH7751_PCICLKR_BCSTP 0x00000002 /* BCLK Clock Stop */
+/* For definitions of BCR, MCR see ... */
+#define SH7751_PCIBCR1 0x1E0 /* Memory BCR1 Register */
+#define SH7751_PCIBCR2 0x1E4 /* Memory BCR2 Register */
+#define SH7751_PCIWCR1 0x1E8 /* Wait Control 1 Register */
+#define SH7751_PCIWCR2 0x1EC /* Wait Control 2 Register */
+#define SH7751_PCIWCR3 0x1F0 /* Wait Control 3 Register */
+#define SH7751_PCIMCR 0x1F4 /* Memory Control Register */
+#define SH7751_PCIBCR3 0x1f8 /* Memory BCR3 Register */
+#define SH7751_PCIPCTR 0x200 /* Port Control Register */
+ #define SH7751_PCIPCTR_P2EN 0x000400000 /* Port 2 Enable */
+ #define SH7751_PCIPCTR_P1EN 0x000200000 /* Port 1 Enable */
+ #define SH7751_PCIPCTR_P0EN 0x000100000 /* Port 0 Enable */
+ #define SH7751_PCIPCTR_P2UP 0x000000020 /* Port2 Pull Up Enable */
+ #define SH7751_PCIPCTR_P2IO 0x000000010 /* Port2 Output Enable */
+ #define SH7751_PCIPCTR_P1UP 0x000000008 /* Port1 Pull Up Enable */
+ #define SH7751_PCIPCTR_P1IO 0x000000004 /* Port1 Output Enable */
+ #define SH7751_PCIPCTR_P0UP 0x000000002 /* Port0 Pull Up Enable */
+ #define SH7751_PCIPCTR_P0IO 0x000000001 /* Port0 Output Enable */
+#define SH7751_PCIPDTR 0x204 /* Port Data Register */
+ #define SH7751_PCIPDTR_PB5 0x000000020 /* Port 5 Enable */
+ #define SH7751_PCIPDTR_PB4 0x000000010 /* Port 4 Enable */
+ #define SH7751_PCIPDTR_PB3 0x000000008 /* Port 3 Enable */
+ #define SH7751_PCIPDTR_PB2 0x000000004 /* Port 2 Enable */
+ #define SH7751_PCIPDTR_PB1 0x000000002 /* Port 1 Enable */
+ #define SH7751_PCIPDTR_PB0 0x000000001 /* Port 0 Enable */
+#define SH7751_PCIPDR 0x220 /* Port IO Data Register */
+
+/* Memory Control Registers */
+#define SH7751_BCR1 0xFF800000 /* Memory BCR1 Register */
+#define SH7751_BCR2 0xFF800004 /* Memory BCR2 Register */
+#define SH7751_BCR3 0xFF800050 /* Memory BCR3 Register */
+#define SH7751_BCR4 0xFE0A00F0 /* Memory BCR4 Register */
+#define SH7751_WCR1 0xFF800008 /* Wait Control 1 Register */
+#define SH7751_WCR2 0xFF80000C /* Wait Control 2 Register */
+#define SH7751_WCR3 0xFF800010 /* Wait Control 3 Register */
+#define SH7751_MCR 0xFF800014 /* Memory Control Register */
+
+/* General Memory Config Addresses */
+#define SH7751_CS0_BASE_ADDR 0x0
+#define SH7751_MEM_REGION_SIZE 0x04000000
+#define SH7751_CS1_BASE_ADDR (SH7751_CS0_BASE_ADDR + SH7751_MEM_REGION_SIZE)
+#define SH7751_CS2_BASE_ADDR (SH7751_CS1_BASE_ADDR + SH7751_MEM_REGION_SIZE)
+#define SH7751_CS3_BASE_ADDR (SH7751_CS2_BASE_ADDR + SH7751_MEM_REGION_SIZE)
+#define SH7751_CS4_BASE_ADDR (SH7751_CS3_BASE_ADDR + SH7751_MEM_REGION_SIZE)
+#define SH7751_CS5_BASE_ADDR (SH7751_CS4_BASE_ADDR + SH7751_MEM_REGION_SIZE)
+#define SH7751_CS6_BASE_ADDR (SH7751_CS5_BASE_ADDR + SH7751_MEM_REGION_SIZE)
+
+/* General PCI values */
+#define SH7751_PCI_HOST_BRIDGE 0x6
+
+/* Flags */
+#define SH7751_PCIC_NO_RESET 0x0001
+
+/* External functions defined per platform i.e. Big Sur, SE... (these could be routed
+ * through the machine vectors... */
+extern int pcibios_init_platform(void);
+extern int pcibios_map_platform_irq(u8 slot, u8 pin);
+
+struct sh7751_pci_address_space {
+ unsigned long base;
+ unsigned long size;
+};
+
+struct sh7751_pci_address_map {
+ struct sh7751_pci_address_space window0;
+ struct sh7751_pci_address_space window1;
+ unsigned long flags;
+};
+
+/* arch/sh/drivers/pci/pci-sh7751.c */
+extern int sh7751_pcic_init(struct sh7751_pci_address_map *map);
+
+#endif /* _PCI_SH7751_H_ */
+
diff --git a/arch/sh/drivers/pci/pci-st40.c b/arch/sh/drivers/pci/pci-st40.c
new file mode 100644
index 000000000000..cb6752131156
--- /dev/null
+++ b/arch/sh/drivers/pci/pci-st40.c
@@ -0,0 +1,509 @@
+/*
+ * 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.
+ *
+ * Support functions for the ST40 PCI hardware.
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/types.h>
+#include <asm/pci.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h> /* irqreturn_t */
+
+#include "pci-st40.h"
+
+/* This is in P2 of course */
+#define ST40PCI_BASE_ADDRESS (0xb0000000)
+#define ST40PCI_MEM_ADDRESS (ST40PCI_BASE_ADDRESS+0x0)
+#define ST40PCI_IO_ADDRESS (ST40PCI_BASE_ADDRESS+0x06000000)
+#define ST40PCI_REG_ADDRESS (ST40PCI_BASE_ADDRESS+0x07000000)
+
+#define ST40PCI_REG(x) (ST40PCI_REG_ADDRESS+(ST40PCI_##x))
+#define ST40PCI_REG_INDEXED(reg, index) \
+ (ST40PCI_REG(reg##0) + \
+ ((ST40PCI_REG(reg##1) - ST40PCI_REG(reg##0))*index))
+
+#define ST40PCI_WRITE(reg,val) writel((val),ST40PCI_REG(reg))
+#define ST40PCI_WRITE_SHORT(reg,val) writew((val),ST40PCI_REG(reg))
+#define ST40PCI_WRITE_BYTE(reg,val) writeb((val),ST40PCI_REG(reg))
+#define ST40PCI_WRITE_INDEXED(reg, index, val) \
+ writel((val), ST40PCI_REG_INDEXED(reg, index));
+
+#define ST40PCI_READ(reg) readl(ST40PCI_REG(reg))
+#define ST40PCI_READ_SHORT(reg) readw(ST40PCI_REG(reg))
+#define ST40PCI_READ_BYTE(reg) readb(ST40PCI_REG(reg))
+
+#define ST40PCI_SERR_IRQ 64
+#define ST40PCI_ERR_IRQ 65
+
+
+/* Macros to extract PLL params */
+#define PLL_MDIV(reg) ( ((unsigned)reg) & 0xff )
+#define PLL_NDIV(reg) ( (((unsigned)reg)>>8) & 0xff )
+#define PLL_PDIV(reg) ( (((unsigned)reg)>>16) & 0x3 )
+#define PLL_SETUP(reg) ( (((unsigned)reg)>>19) & 0x1ff )
+
+/* Build up the appropriate settings */
+#define PLL_SET(mdiv,ndiv,pdiv,setup) \
+( ((mdiv)&0xff) | (((ndiv)&0xff)<<8) | (((pdiv)&3)<<16)| (((setup)&0x1ff)<<19))
+
+#define PLLPCICR (0xbb040000+0x10)
+
+#define PLLPCICR_POWERON (1<<28)
+#define PLLPCICR_OUT_EN (1<<29)
+#define PLLPCICR_LOCKSELECT (1<<30)
+#define PLLPCICR_LOCK (1<<31)
+
+
+#define PLL_25MHZ 0x793c8512
+#define PLL_33MHZ PLL_SET(18,88,3,295)
+
+static void pci_set_rbar_region(unsigned int region, unsigned long localAddr,
+ unsigned long pciOffset, unsigned long regionSize);
+
+/*
+ * The pcibios_map_platform_irq function is defined in the appropriate
+ * board specific code and referenced here
+ */
+extern int __init pcibios_map_platform_irq(struct pci_dev *dev, u8 slot, u8 pin);
+
+static __init void SetPCIPLL(void)
+{
+ {
+ /* Lets play with the PLL values */
+ unsigned long pll1cr1;
+ unsigned long mdiv, ndiv, pdiv;
+ unsigned long muxcr;
+ unsigned int muxcr_ratios[4] = { 8, 16, 21, 1 };
+ unsigned int freq;
+
+#define CLKGENA 0xbb040000
+#define CLKGENA_PLL2_MUXCR CLKGENA + 0x48
+ pll1cr1 = ctrl_inl(PLLPCICR);
+ printk("PLL1CR1 %08lx\n", pll1cr1);
+ mdiv = PLL_MDIV(pll1cr1);
+ ndiv = PLL_NDIV(pll1cr1);
+ pdiv = PLL_PDIV(pll1cr1);
+ printk("mdiv %02lx ndiv %02lx pdiv %02lx\n", mdiv, ndiv, pdiv);
+ freq = ((2*27*ndiv)/mdiv) / (1 << pdiv);
+ printk("PLL freq %dMHz\n", freq);
+ muxcr = ctrl_inl(CLKGENA_PLL2_MUXCR);
+ printk("PCI freq %dMhz\n", freq / muxcr_ratios[muxcr & 3]);
+ }
+}
+
+
+struct pci_err {
+ unsigned mask;
+ const char *error_string;
+};
+
+static struct pci_err int_error[]={
+ { INT_MNLTDIM,"MNLTDIM: Master non-lock transfer"},
+ { INT_TTADI, "TTADI: Illegal byte enable in I/O transfer"},
+ { INT_TMTO, "TMTO: Target memory read/write timeout"},
+ { INT_MDEI, "MDEI: Master function disable error"},
+ { INT_APEDI, "APEDI: Address parity error"},
+ { INT_SDI, "SDI: SERR detected"},
+ { INT_DPEITW, "DPEITW: Data parity error target write"},
+ { INT_PEDITR, "PEDITR: PERR detected"},
+ { INT_TADIM, "TADIM: Target abort detected"},
+ { INT_MADIM, "MADIM: Master abort detected"},
+ { INT_MWPDI, "MWPDI: PERR from target at data write"},
+ { INT_MRDPEI, "MRDPEI: Master read data parity error"}
+};
+#define NUM_PCI_INT_ERRS (sizeof(int_error)/sizeof(struct pci_err))
+
+static struct pci_err aint_error[]={
+ { AINT_MBI, "MBI: Master broken"},
+ { AINT_TBTOI, "TBTOI: Target bus timeout"},
+ { AINT_MBTOI, "MBTOI: Master bus timeout"},
+ { AINT_TAI, "TAI: Target abort"},
+ { AINT_MAI, "MAI: Master abort"},
+ { AINT_RDPEI, "RDPEI: Read data parity"},
+ { AINT_WDPE, "WDPE: Write data parity"}
+};
+
+#define NUM_PCI_AINT_ERRS (sizeof(aint_error)/sizeof(struct pci_err))
+
+static void print_pci_errors(unsigned reg,struct pci_err *error,int num_errors)
+{
+ int i;
+
+ for(i=0;i<num_errors;i++) {
+ if(reg & error[i].mask) {
+ printk("%s\n",error[i].error_string);
+ }
+ }
+
+}
+
+
+static char * pci_commands[16]={
+ "Int Ack",
+ "Special Cycle",
+ "I/O Read",
+ "I/O Write",
+ "Reserved",
+ "Reserved",
+ "Memory Read",
+ "Memory Write",
+ "Reserved",
+ "Reserved",
+ "Configuration Read",
+ "Configuration Write",
+ "Memory Read Multiple",
+ "Dual Address Cycle",
+ "Memory Read Line",
+ "Memory Write-and-Invalidate"
+};
+
+static irqreturn_t st40_pci_irq(int irq, void *dev_instance, struct pt_regs *regs)
+{
+ unsigned pci_int, pci_air, pci_cir, pci_aint;
+ static int count=0;
+
+
+ pci_int = ST40PCI_READ(INT);pci_aint = ST40PCI_READ(AINT);
+ pci_cir = ST40PCI_READ(CIR);pci_air = ST40PCI_READ(AIR);
+
+ /* Reset state to stop multiple interrupts */
+ ST40PCI_WRITE(INT, ~0); ST40PCI_WRITE(AINT, ~0);
+
+
+ if(++count>1) return IRQ_HANDLED;
+
+ printk("** PCI ERROR **\n");
+
+ if(pci_int) {
+ printk("** INT register status\n");
+ print_pci_errors(pci_int,int_error,NUM_PCI_INT_ERRS);
+ }
+
+ if(pci_aint) {
+ printk("** AINT register status\n");
+ print_pci_errors(pci_aint,aint_error,NUM_PCI_AINT_ERRS);
+ }
+
+ printk("** Address and command info\n");
+
+ printk("** Command %s : Address 0x%x\n",
+ pci_commands[pci_cir&0xf],pci_air);
+
+ if(pci_cir&CIR_PIOTEM) {
+ printk("CIR_PIOTEM:PIO transfer error for master\n");
+ }
+ if(pci_cir&CIR_RWTET) {
+ printk("CIR_RWTET:Read/Write transfer error for target\n");
+ }
+
+ return IRQ_HANDLED;
+}
+
+
+/* Rounds a number UP to the nearest power of two. Used for
+ * sizing the PCI window.
+ */
+static u32 r2p2(u32 num)
+{
+ int i = 31;
+ u32 tmp = num;
+
+ if (num == 0)
+ return 0;
+
+ do {
+ if (tmp & (1 << 31))
+ break;
+ i--;
+ tmp <<= 1;
+ } while (i >= 0);
+
+ tmp = 1 << i;
+ /* If the original number isn't a power of 2, round it up */
+ if (tmp != num)
+ tmp <<= 1;
+
+ return tmp;
+}
+
+static void __init pci_fixup_ide_bases(struct pci_dev *d)
+{
+ int i;
+
+ /*
+ * PCI IDE controllers use non-standard I/O port decoding, respect it.
+ */
+ if ((d->class >> 8) != PCI_CLASS_STORAGE_IDE)
+ return;
+ printk("PCI: IDE base address fixup for %s\n", pci_name(d));
+ for(i=0; i<4; i++) {
+ struct resource *r = &d->resource[i];
+ if ((r->start & ~0x80) == 0x374) {
+ r->start |= 2;
+ r->end = r->start;
+ }
+ }
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_ide_bases);
+
+int __init st40pci_init(unsigned memStart, unsigned memSize)
+{
+ u32 lsr0;
+
+ SetPCIPLL();
+
+ /* Initialises the ST40 pci subsystem, performing a reset, then programming
+ * up the address space decoders appropriately
+ */
+
+ /* Should reset core here as well methink */
+
+ ST40PCI_WRITE(CR, CR_LOCK_MASK | CR_SOFT_RESET);
+
+ /* Loop while core resets */
+ while (ST40PCI_READ(CR) & CR_SOFT_RESET);
+
+ /* Switch off interrupts */
+ ST40PCI_WRITE(INTM, 0);
+ ST40PCI_WRITE(AINT, 0);
+
+ /* Now, lets reset all the cards on the bus with extreme prejudice */
+ ST40PCI_WRITE(CR, CR_LOCK_MASK | CR_RSTCTL);
+ udelay(250);
+
+ /* Set bus active, take it out of reset */
+ ST40PCI_WRITE(CR, CR_LOCK_MASK | CR_BMAM | CR_CFINT | CR_PFCS | CR_PFE);
+
+ /* The PCI spec says that no access must be made to the bus until 1 second
+ * after reset. This seem ludicrously long, but some delay is needed here
+ */
+ mdelay(1000);
+
+ /* Switch off interrupts */
+ ST40PCI_WRITE(INTM, 0);
+ ST40PCI_WRITE(AINT, 0);
+
+ /* Allow it to be a master */
+
+ ST40PCI_WRITE_SHORT(CSR_CMD,
+ PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER |
+ PCI_COMMAND_IO);
+
+ /* Accesse to the 0xb0000000 -> 0xb6000000 area will go through to 0x10000000 -> 0x16000000
+ * on the PCI bus. This allows a nice 1-1 bus to phys mapping.
+ */
+
+
+ ST40PCI_WRITE(MBR, 0x10000000);
+ /* Always set the max size 128M (actually, it is only 96MB wide) */
+ ST40PCI_WRITE(MBMR, 0x07ff0000);
+
+ /* I/O addresses are mapped at 0xb6000000 -> 0xb7000000. These are changed to 0, to
+ * allow cards that have legacy io such as vga to function correctly. This gives a
+ * maximum of 64K of io/space as only the bottom 16 bits of the address are copied
+ * over to the bus when the transaction is made. 64K of io space is more than enough
+ */
+ ST40PCI_WRITE(IOBR, 0x0);
+ /* Set up the 64K window */
+ ST40PCI_WRITE(IOBMR, 0x0);
+
+ /* Now we set up the mbars so the PCI bus can see the local memory */
+ /* Expose a 256M window starting at PCI address 0... */
+ ST40PCI_WRITE(CSR_MBAR0, 0);
+ ST40PCI_WRITE(LSR0, 0x0fff0001);
+
+ /* ... and set up the initial incomming window to expose all of RAM */
+ pci_set_rbar_region(7, memStart, memStart, memSize);
+
+ /* Maximise timeout values */
+ ST40PCI_WRITE_BYTE(CSR_TRDY, 0xff);
+ ST40PCI_WRITE_BYTE(CSR_RETRY, 0xff);
+ ST40PCI_WRITE_BYTE(CSR_MIT, 0xff);
+
+ ST40PCI_WRITE_BYTE(PERF,PERF_MASTER_WRITE_POSTING);
+
+ return 1;
+}
+
+char * __init pcibios_setup(char *str)
+{
+ return str;
+}
+
+
+#define SET_CONFIG_BITS(bus,devfn,where)\
+ (((bus) << 16) | ((devfn) << 8) | ((where) & ~3) | (bus!=0))
+
+#define CONFIG_CMD(bus, devfn, where) SET_CONFIG_BITS(bus->number,devfn,where)
+
+
+static int CheckForMasterAbort(void)
+{
+ if (ST40PCI_READ(INT) & INT_MADIM) {
+ /* Should we clear config space version as well ??? */
+ ST40PCI_WRITE(INT, INT_MADIM);
+ ST40PCI_WRITE_SHORT(CSR_STATUS, 0);
+ return 1;
+ }
+
+ return 0;
+}
+
+/* Write to config register */
+static int st40pci_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 * val)
+{
+ ST40PCI_WRITE(PAR, CONFIG_CMD(bus, devfn, where));
+ switch (size) {
+ case 1:
+ *val = (u8)ST40PCI_READ_BYTE(PDR + (where & 3));
+ break;
+ case 2:
+ *val = (u16)ST40PCI_READ_SHORT(PDR + (where & 2));
+ break;
+ case 4:
+ *val = ST40PCI_READ(PDR);
+ break;
+ }
+
+ if (CheckForMasterAbort()){
+ switch (size) {
+ case 1:
+ *val = (u8)0xff;
+ break;
+ case 2:
+ *val = (u16)0xffff;
+ break;
+ case 4:
+ *val = 0xffffffff;
+ break;
+ }
+ }
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int st40pci_write(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 val)
+{
+ ST40PCI_WRITE(PAR, CONFIG_CMD(bus, devfn, where));
+
+ switch (size) {
+ case 1:
+ ST40PCI_WRITE_BYTE(PDR + (where & 3), (u8)val);
+ break;
+ case 2:
+ ST40PCI_WRITE_SHORT(PDR + (where & 2), (u16)val);
+ break;
+ case 4:
+ ST40PCI_WRITE(PDR, val);
+ break;
+ }
+
+ CheckForMasterAbort();
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+struct pci_ops st40pci_config_ops = {
+ .read = st40pci_read,
+ .write = st40pci_write,
+};
+
+
+/* Everything hangs off this */
+static struct pci_bus *pci_root_bus;
+
+
+static u8 __init no_swizzle(struct pci_dev *dev, u8 * pin)
+{
+ return PCI_SLOT(dev->devfn);
+}
+
+
+static int __init pcibios_init(void)
+{
+ extern unsigned long memory_start, memory_end;
+
+ printk(KERN_ALERT "pci-st40.c: pcibios_init\n");
+
+ if (sh_mv.mv_init_pci != NULL) {
+ sh_mv.mv_init_pci();
+ }
+
+ /* The pci subsytem needs to know where memory is and how much
+ * of it there is. I've simply made these globals. A better mechanism
+ * is probably needed.
+ */
+ st40pci_init(PHYSADDR(memory_start),
+ PHYSADDR(memory_end) - PHYSADDR(memory_start));
+
+ if (request_irq(ST40PCI_ERR_IRQ, st40_pci_irq,
+ SA_INTERRUPT, "st40pci", NULL)) {
+ printk(KERN_ERR "st40pci: Cannot hook interrupt\n");
+ return -EIO;
+ }
+
+ /* Enable the PCI interrupts on the device */
+ ST40PCI_WRITE(INTM, ~0);
+ ST40PCI_WRITE(AINT, ~0);
+
+ /* Map the io address apprioately */
+#ifdef CONFIG_HD64465
+ hd64465_port_map(PCIBIOS_MIN_IO, (64 * 1024) - PCIBIOS_MIN_IO + 1,
+ ST40_IO_ADDR + PCIBIOS_MIN_IO, 0);
+#endif
+
+ /* ok, do the scan man */
+ pci_root_bus = pci_scan_bus(0, &st40pci_config_ops, NULL);
+ pci_assign_unassigned_resources();
+ pci_fixup_irqs(no_swizzle, pcibios_map_platform_irq);
+
+ return 0;
+}
+
+subsys_initcall(pcibios_init);
+
+void __init pcibios_fixup_bus(struct pci_bus *bus)
+{
+}
+
+/*
+ * Publish a region of local address space over the PCI bus
+ * to other devices.
+ */
+static void pci_set_rbar_region(unsigned int region, unsigned long localAddr,
+ unsigned long pciOffset, unsigned long regionSize)
+{
+ unsigned long mask;
+
+ if (region > 7)
+ return;
+
+ if (regionSize > (512 * 1024 * 1024))
+ return;
+
+ mask = r2p2(regionSize) - 0x10000;
+
+ /* Diable the region (in case currently in use, should never happen) */
+ ST40PCI_WRITE_INDEXED(RSR, region, 0);
+
+ /* Start of local address space to publish */
+ ST40PCI_WRITE_INDEXED(RLAR, region, PHYSADDR(localAddr) );
+
+ /* Start of region in PCI address space as an offset from MBAR0 */
+ ST40PCI_WRITE_INDEXED(RBAR, region, pciOffset);
+
+ /* Size of region */
+ ST40PCI_WRITE_INDEXED(RSR, region, mask | 1);
+}
+
diff --git a/arch/sh/drivers/pci/pci-st40.h b/arch/sh/drivers/pci/pci-st40.h
new file mode 100644
index 000000000000..d729e0c2d5fe
--- /dev/null
+++ b/arch/sh/drivers/pci/pci-st40.h
@@ -0,0 +1,136 @@
+/*
+ * 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 ST40 PCI hardware.
+ */
+
+#ifndef __PCI_ST40_H__
+#define __PCI_ST40_H__
+
+#define ST40PCI_VCR_STATUS 0x00
+
+#define ST40PCI_VCR_VERSION 0x08
+
+#define ST40PCI_CR 0x10
+
+#define CR_SOFT_RESET (1<<12)
+#define CR_PFCS (1<<11)
+#define CR_PFE (1<<9)
+#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 0x5a000000
+
+
+#define ST40PCI_LSR0 0X14
+#define ST40PCI_LAR0 0x1c
+
+#define ST40PCI_INT 0x24
+#define INT_MNLTDIM (1<<15)
+#define INT_TTADI (1<<14)
+#define INT_TMTO (1<<9)
+#define INT_MDEI (1<<8)
+#define INT_APEDI (1<<7)
+#define INT_SDI (1<<6)
+#define INT_DPEITW (1<<5)
+#define INT_PEDITR (1<<4)
+#define INT_TADIM (1<<3)
+#define INT_MADIM (1<<2)
+#define INT_MWPDI (1<<1)
+#define INT_MRDPEI (1<<0)
+
+
+#define ST40PCI_INTM 0x28
+#define ST40PCI_AIR 0x2c
+
+#define ST40PCI_CIR 0x30
+#define CIR_PIOTEM (1<<31)
+#define CIR_RWTET (1<<26)
+
+#define ST40PCI_AINT 0x40
+#define AINT_MBI (1<<13)
+#define AINT_TBTOI (1<<12)
+#define AINT_MBTOI (1<<11)
+#define AINT_TAI (1<<3)
+#define AINT_MAI (1<<2)
+#define AINT_RDPEI (1<<1)
+#define AINT_WDPE (1<<0)
+
+#define ST40PCI_AINTM 0x44
+#define ST40PCI_BMIR 0x48
+#define ST40PCI_PAR 0x4c
+#define ST40PCI_MBR 0x50
+#define ST40PCI_IOBR 0x54
+#define ST40PCI_PINT 0x58
+#define ST40PCI_PINTM 0x5c
+#define ST40PCI_MBMR 0x70
+#define ST40PCI_IOBMR 0x74
+#define ST40PCI_PDR 0x78
+
+/* H8 specific registers start here */
+#define ST40PCI_WCBAR 0x7c
+#define ST40PCI_LOCCFG_UNLOCK 0x34
+
+#define ST40PCI_RBAR0 0x100
+#define ST40PCI_RSR0 0x104
+#define ST40PCI_RLAR0 0x108
+
+#define ST40PCI_RBAR1 0x110
+#define ST40PCI_RSR1 0x114
+#define ST40PCI_RLAR1 0x118
+
+
+#define ST40PCI_RBAR2 0x120
+#define ST40PCI_RSR2 0x124
+#define ST40PCI_RLAR2 0x128
+
+#define ST40PCI_RBAR3 0x130
+#define ST40PCI_RSR3 0x134
+#define ST40PCI_RLAR3 0x138
+
+#define ST40PCI_RBAR4 0x140
+#define ST40PCI_RSR4 0x144
+#define ST40PCI_RLAR4 0x148
+
+#define ST40PCI_RBAR5 0x150
+#define ST40PCI_RSR5 0x154
+#define ST40PCI_RLAR5 0x158
+
+#define ST40PCI_RBAR6 0x160
+#define ST40PCI_RSR6 0x164
+#define ST40PCI_RLAR6 0x168
+
+#define ST40PCI_RBAR7 0x170
+#define ST40PCI_RSR7 0x174
+#define ST40PCI_RLAR7 0x178
+
+
+#define ST40PCI_RBAR(n) (0x100+(0x10*(n)))
+#define ST40PCI_RSR(n) (0x104+(0x10*(n)))
+#define ST40PCI_RLAR(n) (0x108+(0x10*(n)))
+
+#define ST40PCI_PERF 0x80
+#define PERF_MASTER_WRITE_POSTING (1<<4)
+/* H8 specific registers end here */
+
+
+/* These are configs space registers */
+#define ST40PCI_CSR_VID 0x10000
+#define ST40PCI_CSR_DID 0x10002
+#define ST40PCI_CSR_CMD 0x10004
+#define ST40PCI_CSR_STATUS 0x10006
+#define ST40PCI_CSR_MBAR0 0x10010
+#define ST40PCI_CSR_TRDY 0x10040
+#define ST40PCI_CSR_RETRY 0x10041
+#define ST40PCI_CSR_MIT 0x1000d
+
+#define ST40_IO_ADDR 0xb6000000
+
+#endif /* __PCI_ST40_H__ */
diff --git a/arch/sh/drivers/pci/pci.c b/arch/sh/drivers/pci/pci.c
new file mode 100644
index 000000000000..c1669905abe4
--- /dev/null
+++ b/arch/sh/drivers/pci/pci.c
@@ -0,0 +1,155 @@
+/* arch/sh/kernel/pci.c
+ * $Id: pci.c,v 1.1 2003/08/24 19:15:45 lethal Exp $
+ *
+ * Copyright (c) 2002 M. R. Brown <mrbrown@linux-sh.org>
+ *
+ *
+ * These functions are collected here to reduce duplication of common
+ * code amongst the many platform-specific PCI support code files.
+ *
+ * These routines require the following board-specific routines:
+ * void pcibios_fixup_irqs();
+ *
+ * See include/asm-sh/pci.h for more information.
+ */
+
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+
+static int __init pcibios_init(void)
+{
+ struct pci_channel *p;
+ struct pci_bus *bus;
+ int busno;
+
+#ifdef CONFIG_PCI_AUTO
+ /* assign resources */
+ busno = 0;
+ for (p = board_pci_channels; p->pci_ops != NULL; p++) {
+ busno = pciauto_assign_resources(busno, p) + 1;
+ }
+#endif
+
+ /* scan the buses */
+ busno = 0;
+ for (p= board_pci_channels; p->pci_ops != NULL; p++) {
+ bus = pci_scan_bus(busno, p->pci_ops, p);
+ busno = bus->subordinate+1;
+ }
+
+ /* board-specific fixups */
+ pcibios_fixup_irqs();
+
+ return 0;
+}
+
+subsys_initcall(pcibios_init);
+
+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 |= IORESOURCE_ROM_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", pci_name(dev), resource,
+ new, check);
+ }
+}
+
+void pcibios_align_resource(void *data, struct resource *res,
+ unsigned long size, unsigned long align)
+ __attribute__ ((weak));
+
+/*
+ * 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;
+ }
+ }
+}
+
+int pcibios_enable_device(struct pci_dev *dev, int mask)
+{
+ u16 cmd, old_cmd;
+ int idx;
+ struct resource *r;
+
+ 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", pci_name(dev));
+ 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);
+}
diff --git a/arch/sh/kernel/Makefile b/arch/sh/kernel/Makefile
new file mode 100644
index 000000000000..8b819698df14
--- /dev/null
+++ b/arch/sh/kernel/Makefile
@@ -0,0 +1,22 @@
+#
+# Makefile for the Linux/SuperH kernel.
+#
+
+extra-y := head.o init_task.o vmlinux.lds
+
+obj-y := process.o signal.o entry.o traps.o irq.o \
+ ptrace.o setup.o time.o sys_sh.o semaphore.o \
+ io.o io_generic.o sh_ksyms.o
+
+obj-y += cpu/
+
+obj-$(CONFIG_SMP) += smp.o
+obj-$(CONFIG_CF_ENABLER) += cf-enabler.o
+obj-$(CONFIG_SH_STANDARD_BIOS) += sh_bios.o
+obj-$(CONFIG_SH_KGDB) += kgdb_stub.o kgdb_jmp.o
+obj-$(CONFIG_SH_CPU_FREQ) += cpufreq.o
+obj-$(CONFIG_MODULES) += module.o
+obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
+
+USE_STANDARD_AS_RULE := true
+
diff --git a/arch/sh/kernel/asm-offsets.c b/arch/sh/kernel/asm-offsets.c
new file mode 100644
index 000000000000..dc6725c51a89
--- /dev/null
+++ b/arch/sh/kernel/asm-offsets.c
@@ -0,0 +1,32 @@
+/*
+ * 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_CPU, offsetof(struct thread_info, cpu));
+ DEFINE(TI_PRE_COUNT, offsetof(struct thread_info, preempt_count));
+ DEFINE(TI_RESTART_BLOCK,offsetof(struct thread_info, restart_block));
+
+ return 0;
+}
diff --git a/arch/sh/kernel/cf-enabler.c b/arch/sh/kernel/cf-enabler.c
new file mode 100644
index 000000000000..7a3b18faa277
--- /dev/null
+++ b/arch/sh/kernel/cf-enabler.c
@@ -0,0 +1,158 @@
+/* $Id: cf-enabler.c,v 1.4 2004/02/22 22:44:36 kkojima Exp $
+ *
+ * linux/drivers/block/cf-enabler.c
+ *
+ * Copyright (C) 1999 Niibe Yutaka
+ * Copyright (C) 2000 Toshiharu Nozawa
+ * Copyright (C) 2001 A&D Co., Ltd.
+ *
+ * Enable the CF configuration.
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+
+/*
+ * You can connect Compact Flash directly to the bus of SuperH.
+ * This is the enabler for that.
+ *
+ * SIM: How generic is this really? It looks pretty board, or at
+ * least SH sub-type, specific to me.
+ * I know it doesn't work on the Overdrive!
+ */
+
+/*
+ * 0xB8000000 : Attribute
+ * 0xB8001000 : Common Memory
+ * 0xBA000000 : I/O
+ */
+#if defined(CONFIG_IDE) && defined(CONFIG_CPU_SH4)
+/* SH4 can't access PCMCIA interface through P2 area.
+ * we must remap it with appropreate attribute bit of the page set.
+ * this part is based on Greg Banks' hd64465_ss.c implementation - Masahiro Abe */
+#include <linux/mm.h>
+#include <linux/vmalloc.h>
+
+#if defined(CONFIG_CF_AREA6)
+#define slot_no 0
+#else
+#define slot_no 1
+#endif
+
+/* defined in mm/ioremap.c */
+extern void * p3_ioremap(unsigned long phys_addr, unsigned long size, unsigned long flags);
+
+/* use this pointer to access to directly connected compact flash io area*/
+void *cf_io_base;
+
+static int __init allocate_cf_area(void)
+{
+ pgprot_t prot;
+ unsigned long paddrbase, psize;
+
+ /* open I/O area window */
+ paddrbase = virt_to_phys((void*)CONFIG_CF_BASE_ADDR);
+ psize = PAGE_SIZE;
+ prot = PAGE_KERNEL_PCC(slot_no, _PAGE_PCC_IO16);
+ cf_io_base = p3_ioremap(paddrbase, psize, prot.pgprot);
+ if (!cf_io_base) {
+ printk("allocate_cf_area : can't open CF I/O window!\n");
+ return -ENOMEM;
+ }
+/* printk("p3_ioremap(paddr=0x%08lx, psize=0x%08lx, prot=0x%08lx)=0x%08lx\n",
+ paddrbase, psize, prot.pgprot, cf_io_base);*/
+
+ /* XXX : do we need attribute and common-memory area also? */
+
+ return 0;
+}
+#endif
+
+static int __init cf_init_default(void)
+{
+/* You must have enabled the card, and set the level interrupt
+ * before reaching this point. Possibly in boot ROM or boot loader.
+ */
+#if defined(CONFIG_IDE) && defined(CONFIG_CPU_SH4)
+ allocate_cf_area();
+#endif
+#if defined(CONFIG_SH_UNKNOWN)
+ /* This should be done in each board's init_xxx_irq. */
+ make_imask_irq(14);
+ disable_irq(14);
+#endif
+ return 0;
+}
+
+#if defined(CONFIG_SH_SOLUTION_ENGINE)
+#include <asm/se/se.h>
+
+/*
+ * SolutionEngine
+ *
+ * 0xB8400000 : Common Memory
+ * 0xB8500000 : Attribute
+ * 0xB8600000 : I/O
+ */
+
+static int __init cf_init_se(void)
+{
+ if ((ctrl_inw(MRSHPC_CSR) & 0x000c) != 0)
+ return 0; /* Not detected */
+
+ if ((ctrl_inw(MRSHPC_CSR) & 0x0080) == 0) {
+ ctrl_outw(0x0674, MRSHPC_CPWCR); /* Card Vcc is 3.3v? */
+ } else {
+ ctrl_outw(0x0678, MRSHPC_CPWCR); /* Card Vcc is 5V */
+ }
+
+ /*
+ * PC-Card window open
+ * flag == COMMON/ATTRIBUTE/IO
+ */
+ /* common window open */
+ ctrl_outw(0x8a84, MRSHPC_MW0CR1);/* window 0xb8400000 */
+ if((ctrl_inw(MRSHPC_CSR) & 0x4000) != 0)
+ /* common mode & bus width 16bit SWAP = 1*/
+ ctrl_outw(0x0b00, MRSHPC_MW0CR2);
+ else
+ /* common mode & bus width 16bit SWAP = 0*/
+ ctrl_outw(0x0300, MRSHPC_MW0CR2);
+
+ /* attribute window open */
+ ctrl_outw(0x8a85, MRSHPC_MW1CR1);/* window 0xb8500000 */
+ if ((ctrl_inw(MRSHPC_CSR) & 0x4000) != 0)
+ /* attribute mode & bus width 16bit SWAP = 1*/
+ ctrl_outw(0x0a00, MRSHPC_MW1CR2);
+ else
+ /* attribute mode & bus width 16bit SWAP = 0*/
+ ctrl_outw(0x0200, MRSHPC_MW1CR2);
+
+ /* I/O window open */
+ ctrl_outw(0x8a86, MRSHPC_IOWCR1);/* I/O window 0xb8600000 */
+ ctrl_outw(0x0008, MRSHPC_CDCR); /* I/O card mode */
+ if ((ctrl_inw(MRSHPC_CSR) & 0x4000) != 0)
+ ctrl_outw(0x0a00, MRSHPC_IOWCR2); /* bus width 16bit SWAP = 1*/
+ else
+ ctrl_outw(0x0200, MRSHPC_IOWCR2); /* bus width 16bit SWAP = 0*/
+
+ ctrl_outw(0x2000, MRSHPC_ICR);
+ ctrl_outb(0x00, PA_MRSHPC_MW2 + 0x206);
+ ctrl_outb(0x42, PA_MRSHPC_MW2 + 0x200);
+ return 0;
+}
+#endif
+
+int __init cf_init(void)
+{
+#if defined(CONFIG_SH_SOLUTION_ENGINE)
+ if (MACH_SE)
+ return cf_init_se();
+#endif
+ return cf_init_default();
+}
+
+__initcall (cf_init);
diff --git a/arch/sh/kernel/cpu/Makefile b/arch/sh/kernel/cpu/Makefile
new file mode 100644
index 000000000000..cd43714df61a
--- /dev/null
+++ b/arch/sh/kernel/cpu/Makefile
@@ -0,0 +1,16 @@
+#
+# Makefile for the Linux/SuperH CPU-specifc backends.
+#
+
+obj-y := irq_ipr.o irq_imask.o init.o bus.o
+
+obj-$(CONFIG_CPU_SH2) += sh2/
+obj-$(CONFIG_CPU_SH3) += sh3/
+obj-$(CONFIG_CPU_SH4) += sh4/
+
+obj-$(CONFIG_SH_RTC) += rtc.o
+obj-$(CONFIG_UBC_WAKEUP) += ubc.o
+obj-$(CONFIG_SH_ADC) += adc.o
+
+USE_STANDARD_AS_RULE := true
+
diff --git a/arch/sh/kernel/cpu/adc.c b/arch/sh/kernel/cpu/adc.c
new file mode 100644
index 000000000000..da3d6877f93d
--- /dev/null
+++ b/arch/sh/kernel/cpu/adc.c
@@ -0,0 +1,36 @@
+/*
+ * linux/arch/sh/kernel/adc.c -- SH3 on-chip ADC support
+ *
+ * Copyright (C) 2004 Andriy Skulysh <askulysh@image.kiev.ua>
+ */
+
+#include <linux/module.h>
+#include <asm/adc.h>
+#include <asm/io.h>
+
+
+int adc_single(unsigned int channel)
+{
+ int off;
+ unsigned char csr;
+
+ if (channel >= 8) return -1;
+
+ off = (channel & 0x03) << 2;
+
+ csr = ctrl_inb(ADCSR);
+ csr = channel | ADCSR_ADST | ADCSR_CKS;
+ ctrl_outb(csr, ADCSR);
+
+ do {
+ csr = ctrl_inb(ADCSR);
+ } while ((csr & ADCSR_ADF) == 0);
+
+ csr &= ~(ADCSR_ADF | ADCSR_ADST);
+ ctrl_outb(csr, ADCSR);
+
+ return (((ctrl_inb(ADDRAH + off) << 8) |
+ ctrl_inb(ADDRAL + off)) >> 6);
+}
+
+EXPORT_SYMBOL(adc_single);
diff --git a/arch/sh/kernel/cpu/bus.c b/arch/sh/kernel/cpu/bus.c
new file mode 100644
index 000000000000..ace82f4b4a59
--- /dev/null
+++ b/arch/sh/kernel/cpu/bus.c
@@ -0,0 +1,195 @@
+/*
+ * arch/sh/kernel/cpu/bus.c
+ *
+ * Virtual bus for SuperH.
+ *
+ * Copyright (C) 2004 Paul Mundt
+ *
+ * Shamelessly cloned from arch/arm/mach-omap/bus.c, which was written
+ * by:
+ *
+ * Copyright (C) 2003 - 2004 Nokia Corporation
+ * Written by Tony Lindgren <tony@atomide.com>
+ * Portions of code based on sa1111.c.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <asm/bus-sh.h>
+
+static int sh_bus_match(struct device *dev, struct device_driver *drv)
+{
+ struct sh_driver *shdrv = to_sh_driver(drv);
+ struct sh_dev *shdev = to_sh_dev(dev);
+
+ return shdev->dev_id == shdrv->dev_id;
+}
+
+static int sh_bus_suspend(struct device *dev, u32 state)
+{
+ struct sh_dev *shdev = to_sh_dev(dev);
+ struct sh_driver *shdrv = to_sh_driver(dev->driver);
+
+ if (shdrv && shdrv->suspend)
+ return shdrv->suspend(shdev, state);
+
+ return 0;
+}
+
+static int sh_bus_resume(struct device *dev)
+{
+ struct sh_dev *shdev = to_sh_dev(dev);
+ struct sh_driver *shdrv = to_sh_driver(dev->driver);
+
+ if (shdrv && shdrv->resume)
+ return shdrv->resume(shdev);
+
+ return 0;
+}
+
+static struct device sh_bus_devices[SH_NR_BUSES] = {
+ {
+ .bus_id = SH_BUS_NAME_VIRT,
+ },
+};
+
+struct bus_type sh_bus_types[SH_NR_BUSES] = {
+ {
+ .name = SH_BUS_NAME_VIRT,
+ .match = sh_bus_match,
+ .suspend = sh_bus_suspend,
+ .resume = sh_bus_resume,
+ },
+};
+
+static int sh_device_probe(struct device *dev)
+{
+ struct sh_dev *shdev = to_sh_dev(dev);
+ struct sh_driver *shdrv = to_sh_driver(dev->driver);
+
+ if (shdrv && shdrv->probe)
+ return shdrv->probe(shdev);
+
+ return -ENODEV;
+}
+
+static int sh_device_remove(struct device *dev)
+{
+ struct sh_dev *shdev = to_sh_dev(dev);
+ struct sh_driver *shdrv = to_sh_driver(dev->driver);
+
+ if (shdrv && shdrv->remove)
+ return shdrv->remove(shdev);
+
+ return 0;
+}
+
+int sh_device_register(struct sh_dev *dev)
+{
+ if (!dev)
+ return -EINVAL;
+
+ if (dev->bus_id < 0 || dev->bus_id >= SH_NR_BUSES) {
+ printk(KERN_ERR "%s: bus_id invalid: %s bus: %d\n",
+ __FUNCTION__, dev->name, dev->bus_id);
+ return -EINVAL;
+ }
+
+ dev->dev.parent = &sh_bus_devices[dev->bus_id];
+ dev->dev.bus = &sh_bus_types[dev->bus_id];
+
+ /* This is needed for USB OHCI to work */
+ if (dev->dma_mask)
+ dev->dev.dma_mask = dev->dma_mask;
+
+ snprintf(dev->dev.bus_id, BUS_ID_SIZE, "%s%u",
+ dev->name, dev->dev_id);
+
+ printk(KERN_INFO "Registering SH device '%s'. Parent at %s\n",
+ dev->dev.bus_id, dev->dev.parent->bus_id);
+
+ return device_register(&dev->dev);
+}
+
+void sh_device_unregister(struct sh_dev *dev)
+{
+ device_unregister(&dev->dev);
+}
+
+int sh_driver_register(struct sh_driver *drv)
+{
+ if (!drv)
+ return -EINVAL;
+
+ if (drv->bus_id < 0 || drv->bus_id >= SH_NR_BUSES) {
+ printk(KERN_ERR "%s: bus_id invalid: bus: %d device %d\n",
+ __FUNCTION__, drv->bus_id, drv->dev_id);
+ return -EINVAL;
+ }
+
+ drv->drv.probe = sh_device_probe;
+ drv->drv.remove = sh_device_remove;
+ drv->drv.bus = &sh_bus_types[drv->bus_id];
+
+ return driver_register(&drv->drv);
+}
+
+void sh_driver_unregister(struct sh_driver *drv)
+{
+ driver_unregister(&drv->drv);
+}
+
+static int __init sh_bus_init(void)
+{
+ int i, ret = 0;
+
+ for (i = 0; i < SH_NR_BUSES; i++) {
+ ret = device_register(&sh_bus_devices[i]);
+ if (ret != 0) {
+ printk(KERN_ERR "Unable to register bus device %s\n",
+ sh_bus_devices[i].bus_id);
+ continue;
+ }
+
+ ret = bus_register(&sh_bus_types[i]);
+ if (ret != 0) {
+ printk(KERN_ERR "Unable to register bus %s\n",
+ sh_bus_types[i].name);
+ device_unregister(&sh_bus_devices[i]);
+ }
+ }
+
+ printk(KERN_INFO "SH Virtual Bus initialized\n");
+
+ return ret;
+}
+
+static void __exit sh_bus_exit(void)
+{
+ int i;
+
+ for (i = 0; i < SH_NR_BUSES; i++) {
+ bus_unregister(&sh_bus_types[i]);
+ device_unregister(&sh_bus_devices[i]);
+ }
+}
+
+module_init(sh_bus_init);
+module_exit(sh_bus_exit);
+
+MODULE_AUTHOR("Paul Mundt <lethal@linux-sh.org>");
+MODULE_DESCRIPTION("SH Virtual Bus");
+MODULE_LICENSE("GPL");
+
+EXPORT_SYMBOL(sh_bus_types);
+EXPORT_SYMBOL(sh_device_register);
+EXPORT_SYMBOL(sh_device_unregister);
+EXPORT_SYMBOL(sh_driver_register);
+EXPORT_SYMBOL(sh_driver_unregister);
+
diff --git a/arch/sh/kernel/cpu/init.c b/arch/sh/kernel/cpu/init.c
new file mode 100644
index 000000000000..cf94e8ef17c5
--- /dev/null
+++ b/arch/sh/kernel/cpu/init.c
@@ -0,0 +1,222 @@
+/*
+ * arch/sh/kernel/cpu/init.c
+ *
+ * CPU init code
+ *
+ * Copyright (C) 2002, 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/kernel.h>
+#include <asm/processor.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+#include <asm/cacheflush.h>
+#include <asm/cache.h>
+#include <asm/io.h>
+
+extern void detect_cpu_and_cache_system(void);
+
+/*
+ * Generic wrapper for command line arguments to disable on-chip
+ * peripherals (nofpu, nodsp, and so forth).
+ */
+#define onchip_setup(x) \
+static int x##_disabled __initdata = 0; \
+ \
+static int __init x##_setup(char *opts) \
+{ \
+ x##_disabled = 1; \
+ return 0; \
+} \
+__setup("no" __stringify(x), x##_setup);
+
+onchip_setup(fpu);
+onchip_setup(dsp);
+
+/*
+ * Generic first-level cache init
+ */
+static void __init cache_init(void)
+{
+ unsigned long ccr, flags;
+
+ if (cpu_data->type == CPU_SH_NONE)
+ panic("Unknown CPU");
+
+ jump_to_P2();
+ ccr = ctrl_inl(CCR);
+
+ /*
+ * If the cache is already enabled .. flush it.
+ */
+ if (ccr & CCR_CACHE_ENABLE) {
+ unsigned long ways, waysize, addrstart;
+
+ waysize = cpu_data->dcache.sets;
+
+ /*
+ * If the OC is already in RAM mode, we only have
+ * half of the entries to flush..
+ */
+ if (ccr & CCR_CACHE_ORA)
+ waysize >>= 1;
+
+ waysize <<= cpu_data->dcache.entry_shift;
+
+#ifdef CCR_CACHE_EMODE
+ /* If EMODE is not set, we only have 1 way to flush. */
+ if (!(ccr & CCR_CACHE_EMODE))
+ ways = 1;
+ else
+#endif
+ ways = cpu_data->dcache.ways;
+
+ addrstart = CACHE_OC_ADDRESS_ARRAY;
+ do {
+ unsigned long addr;
+
+ for (addr = addrstart;
+ addr < addrstart + waysize;
+ addr += cpu_data->dcache.linesz)
+ ctrl_outl(0, addr);
+
+ addrstart += cpu_data->dcache.way_incr;
+ } while (--ways);
+ }
+
+ /*
+ * Default CCR values .. enable the caches
+ * and invalidate them immediately..
+ */
+ flags = CCR_CACHE_ENABLE | CCR_CACHE_INVALIDATE;
+
+#ifdef CCR_CACHE_EMODE
+ /* Force EMODE if possible */
+ if (cpu_data->dcache.ways > 1)
+ flags |= CCR_CACHE_EMODE;
+#endif
+
+#ifdef CONFIG_SH_WRITETHROUGH
+ /* Turn on Write-through caching */
+ flags |= CCR_CACHE_WT;
+#else
+ /* .. or default to Write-back */
+ flags |= CCR_CACHE_CB;
+#endif
+
+#ifdef CONFIG_SH_OCRAM
+ /* Turn on OCRAM -- halve the OC */
+ flags |= CCR_CACHE_ORA;
+ cpu_data->dcache.sets >>= 1;
+#endif
+
+ ctrl_outl(flags, CCR);
+ back_to_P1();
+}
+
+#ifdef CONFIG_SH_DSP
+static void __init release_dsp(void)
+{
+ unsigned long sr;
+
+ /* Clear SR.DSP bit */
+ __asm__ __volatile__ (
+ "stc\tsr, %0\n\t"
+ "and\t%1, %0\n\t"
+ "ldc\t%0, sr\n\t"
+ : "=&r" (sr)
+ : "r" (~SR_DSP)
+ );
+}
+
+static void __init dsp_init(void)
+{
+ unsigned long sr;
+
+ /*
+ * Set the SR.DSP bit, wait for one instruction, and then read
+ * back the SR value.
+ */
+ __asm__ __volatile__ (
+ "stc\tsr, %0\n\t"
+ "or\t%1, %0\n\t"
+ "ldc\t%0, sr\n\t"
+ "nop\n\t"
+ "stc\tsr, %0\n\t"
+ : "=&r" (sr)
+ : "r" (SR_DSP)
+ );
+
+ /* If the DSP bit is still set, this CPU has a DSP */
+ if (sr & SR_DSP)
+ cpu_data->flags |= CPU_HAS_DSP;
+
+ /* Now that we've determined the DSP status, clear the DSP bit. */
+ release_dsp();
+}
+#endif /* CONFIG_SH_DSP */
+
+/**
+ * sh_cpu_init
+ *
+ * This is our initial entry point for each CPU, and is invoked on the boot
+ * CPU prior to calling start_kernel(). For SMP, a combination of this and
+ * start_secondary() will bring up each processor to a ready state prior
+ * to hand forking the idle loop.
+ *
+ * We do all of the basic processor init here, including setting up the
+ * caches, FPU, DSP, kicking the UBC, etc. By the time start_kernel() is
+ * hit (and subsequently platform_setup()) things like determining the
+ * CPU subtype and initial configuration will all be done.
+ *
+ * Each processor family is still responsible for doing its own probing
+ * and cache configuration in detect_cpu_and_cache_system().
+ */
+asmlinkage void __init sh_cpu_init(void)
+{
+ /* First, probe the CPU */
+ detect_cpu_and_cache_system();
+
+ /* Init the cache */
+ cache_init();
+
+ /* Disable the FPU */
+ if (fpu_disabled) {
+ printk("FPU Disabled\n");
+ cpu_data->flags &= ~CPU_HAS_FPU;
+ disable_fpu();
+ }
+
+ /* FPU initialization */
+ if ((cpu_data->flags & CPU_HAS_FPU)) {
+ clear_thread_flag(TIF_USEDFPU);
+ clear_used_math();
+ }
+
+#ifdef CONFIG_SH_DSP
+ /* Probe for DSP */
+ dsp_init();
+
+ /* Disable the DSP */
+ if (dsp_disabled) {
+ printk("DSP Disabled\n");
+ cpu_data->flags &= ~CPU_HAS_DSP;
+ release_dsp();
+ }
+#endif
+
+#ifdef CONFIG_UBC_WAKEUP
+ /*
+ * Some brain-damaged loaders decided it would be a good idea to put
+ * the UBC to sleep. This causes some issues when it comes to things
+ * like PTRACE_SINGLESTEP or doing hardware watchpoints in GDB. So ..
+ * we wake it up and hope that all is well.
+ */
+ ubc_wakeup();
+#endif
+}
+
diff --git a/arch/sh/kernel/cpu/irq_imask.c b/arch/sh/kernel/cpu/irq_imask.c
new file mode 100644
index 000000000000..f76901e732fb
--- /dev/null
+++ b/arch/sh/kernel/cpu/irq_imask.c
@@ -0,0 +1,116 @@
+/* $Id: irq_imask.c,v 1.1.2.1 2002/11/17 10:53:43 mrbrown Exp $
+ *
+ * linux/arch/sh/kernel/irq_imask.c
+ *
+ * Copyright (C) 1999, 2000 Niibe Yutaka
+ *
+ * Simple interrupt handling using IMASK of SR register.
+ *
+ */
+
+/* NOTE: Will not work on level 15 */
+
+
+#include <linux/ptrace.h>
+#include <linux/errno.h>
+#include <linux/kernel_stat.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/bitops.h>
+
+#include <asm/system.h>
+#include <asm/irq.h>
+
+#include <linux/spinlock.h>
+#include <linux/cache.h>
+#include <linux/irq.h>
+
+/* Bitmap of IRQ masked */
+static unsigned long imask_mask = 0x7fff;
+static int interrupt_priority = 0;
+
+static void enable_imask_irq(unsigned int irq);
+static void disable_imask_irq(unsigned int irq);
+static void shutdown_imask_irq(unsigned int irq);
+static void mask_and_ack_imask(unsigned int);
+static void end_imask_irq(unsigned int irq);
+
+#define IMASK_PRIORITY 15
+
+static unsigned int startup_imask_irq(unsigned int irq)
+{
+ /* Nothing to do */
+ return 0; /* never anything pending */
+}
+
+static struct hw_interrupt_type imask_irq_type = {
+ "SR.IMASK",
+ startup_imask_irq,
+ shutdown_imask_irq,
+ enable_imask_irq,
+ disable_imask_irq,
+ mask_and_ack_imask,
+ end_imask_irq
+};
+
+void static inline set_interrupt_registers(int ip)
+{
+ unsigned long __dummy;
+
+ asm volatile("ldc %2, r6_bank\n\t"
+ "stc sr, %0\n\t"
+ "and #0xf0, %0\n\t"
+ "shlr2 %0\n\t"
+ "cmp/eq #0x3c, %0\n\t"
+ "bt/s 1f ! CLI-ed\n\t"
+ " stc sr, %0\n\t"
+ "and %1, %0\n\t"
+ "or %2, %0\n\t"
+ "ldc %0, sr\n"
+ "1:"
+ : "=&z" (__dummy)
+ : "r" (~0xf0), "r" (ip << 4)
+ : "t");
+}
+
+static void disable_imask_irq(unsigned int irq)
+{
+ clear_bit(irq, &imask_mask);
+ if (interrupt_priority < IMASK_PRIORITY - irq)
+ interrupt_priority = IMASK_PRIORITY - irq;
+
+ set_interrupt_registers(interrupt_priority);
+}
+
+static void enable_imask_irq(unsigned int irq)
+{
+ set_bit(irq, &imask_mask);
+ interrupt_priority = IMASK_PRIORITY - ffz(imask_mask);
+
+ set_interrupt_registers(interrupt_priority);
+}
+
+static void mask_and_ack_imask(unsigned int irq)
+{
+ disable_imask_irq(irq);
+}
+
+static void end_imask_irq(unsigned int irq)
+{
+ if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+ enable_imask_irq(irq);
+}
+
+static void shutdown_imask_irq(unsigned int irq)
+{
+ /* Nothing to do */
+}
+
+void make_imask_irq(unsigned int irq)
+{
+ disable_irq_nosync(irq);
+ irq_desc[irq].handler = &imask_irq_type;
+ enable_irq(irq);
+}
diff --git a/arch/sh/kernel/cpu/irq_ipr.c b/arch/sh/kernel/cpu/irq_ipr.c
new file mode 100644
index 000000000000..7ea3d2d030e5
--- /dev/null
+++ b/arch/sh/kernel/cpu/irq_ipr.c
@@ -0,0 +1,339 @@
+/* $Id: irq_ipr.c,v 1.1.2.1 2002/11/17 10:53:43 mrbrown Exp $
+ *
+ * linux/arch/sh/kernel/irq_ipr.c
+ *
+ * Copyright (C) 1999 Niibe Yutaka & Takeshi Yaegashi
+ * Copyright (C) 2000 Kazumoto Kojima
+ * Copyright (C) 2003 Takashi Kusuda <kusuda-takashi@hitachi-ul.co.jp>
+ *
+ * Interrupt handling for IPR-based IRQ.
+ *
+ * Supported system:
+ * On-chip supporting modules (TMU, RTC, etc.).
+ * On-chip supporting modules for SH7709/SH7709A/SH7729/SH7300.
+ * Hitachi SolutionEngine external I/O:
+ * MS7709SE01, MS7709ASE01, and MS7750SE01
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/module.h>
+
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/machvec.h>
+
+struct ipr_data {
+ unsigned int addr; /* Address of Interrupt Priority Register */
+ int shift; /* Shifts of the 16-bit data */
+ int priority; /* The priority */
+};
+static struct ipr_data ipr_data[NR_IRQS];
+
+static void enable_ipr_irq(unsigned int irq);
+static void disable_ipr_irq(unsigned int irq);
+
+/* shutdown is same as "disable" */
+#define shutdown_ipr_irq disable_ipr_irq
+
+static void mask_and_ack_ipr(unsigned int);
+static void end_ipr_irq(unsigned int irq);
+
+static unsigned int startup_ipr_irq(unsigned int irq)
+{
+ enable_ipr_irq(irq);
+ return 0; /* never anything pending */
+}
+
+static struct hw_interrupt_type ipr_irq_type = {
+ "IPR-IRQ",
+ startup_ipr_irq,
+ shutdown_ipr_irq,
+ enable_ipr_irq,
+ disable_ipr_irq,
+ mask_and_ack_ipr,
+ end_ipr_irq
+};
+
+static void disable_ipr_irq(unsigned int irq)
+{
+ unsigned long val, flags;
+ unsigned int addr = ipr_data[irq].addr;
+ unsigned short mask = 0xffff ^ (0x0f << ipr_data[irq].shift);
+
+ /* Set the priority in IPR to 0 */
+ local_irq_save(flags);
+ val = ctrl_inw(addr);
+ val &= mask;
+ ctrl_outw(val, addr);
+ local_irq_restore(flags);
+}
+
+static void enable_ipr_irq(unsigned int irq)
+{
+ unsigned long val, flags;
+ unsigned int addr = ipr_data[irq].addr;
+ int priority = ipr_data[irq].priority;
+ unsigned short value = (priority << ipr_data[irq].shift);
+
+ /* Set priority in IPR back to original value */
+ local_irq_save(flags);
+ val = ctrl_inw(addr);
+ val |= value;
+ ctrl_outw(val, addr);
+ local_irq_restore(flags);
+}
+
+static void mask_and_ack_ipr(unsigned int irq)
+{
+ disable_ipr_irq(irq);
+
+#if defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7709) || \
+ defined(CONFIG_CPU_SUBTYPE_SH7300) || defined(CONFIG_CPU_SUBTYPE_SH7705)
+ /* This is needed when we use edge triggered setting */
+ /* XXX: Is it really needed? */
+ if (IRQ0_IRQ <= irq && irq <= IRQ5_IRQ) {
+ /* Clear external interrupt request */
+ int a = ctrl_inb(INTC_IRR0);
+ a &= ~(1 << (irq - IRQ0_IRQ));
+ ctrl_outb(a, INTC_IRR0);
+ }
+#endif
+}
+
+static void end_ipr_irq(unsigned int irq)
+{
+ if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+ enable_ipr_irq(irq);
+}
+
+void make_ipr_irq(unsigned int irq, unsigned int addr, int pos, int priority)
+{
+ disable_irq_nosync(irq);
+ ipr_data[irq].addr = addr;
+ ipr_data[irq].shift = pos*4; /* POSition (0-3) x 4 means shift */
+ ipr_data[irq].priority = priority;
+
+ irq_desc[irq].handler = &ipr_irq_type;
+ disable_ipr_irq(irq);
+}
+
+#if defined(CONFIG_CPU_SUBTYPE_SH7705) || \
+ defined(CONFIG_CPU_SUBTYPE_SH7707) || \
+ defined(CONFIG_CPU_SUBTYPE_SH7709)
+static unsigned char pint_map[256];
+static unsigned long portcr_mask = 0;
+
+static void enable_pint_irq(unsigned int irq);
+static void disable_pint_irq(unsigned int irq);
+
+/* shutdown is same as "disable" */
+#define shutdown_pint_irq disable_pint_irq
+
+static void mask_and_ack_pint(unsigned int);
+static void end_pint_irq(unsigned int irq);
+
+static unsigned int startup_pint_irq(unsigned int irq)
+{
+ enable_pint_irq(irq);
+ return 0; /* never anything pending */
+}
+
+static struct hw_interrupt_type pint_irq_type = {
+ "PINT-IRQ",
+ startup_pint_irq,
+ shutdown_pint_irq,
+ enable_pint_irq,
+ disable_pint_irq,
+ mask_and_ack_pint,
+ end_pint_irq
+};
+
+static void disable_pint_irq(unsigned int irq)
+{
+ unsigned long val, flags;
+
+ local_irq_save(flags);
+ val = ctrl_inw(INTC_INTER);
+ val &= ~(1 << (irq - PINT_IRQ_BASE));
+ ctrl_outw(val, INTC_INTER); /* disable PINTn */
+ portcr_mask &= ~(3 << (irq - PINT_IRQ_BASE)*2);
+ local_irq_restore(flags);
+}
+
+static void enable_pint_irq(unsigned int irq)
+{
+ unsigned long val, flags;
+
+ local_irq_save(flags);
+ val = ctrl_inw(INTC_INTER);
+ val |= 1 << (irq - PINT_IRQ_BASE);
+ ctrl_outw(val, INTC_INTER); /* enable PINTn */
+ portcr_mask |= 3 << (irq - PINT_IRQ_BASE)*2;
+ local_irq_restore(flags);
+}
+
+static void mask_and_ack_pint(unsigned int irq)
+{
+ disable_pint_irq(irq);
+}
+
+static void end_pint_irq(unsigned int irq)
+{
+ if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+ enable_pint_irq(irq);
+}
+
+void make_pint_irq(unsigned int irq)
+{
+ disable_irq_nosync(irq);
+ irq_desc[irq].handler = &pint_irq_type;
+ disable_pint_irq(irq);
+}
+#endif
+
+void __init init_IRQ(void)
+{
+#if defined(CONFIG_CPU_SUBTYPE_SH7705) || \
+ defined(CONFIG_CPU_SUBTYPE_SH7707) || \
+ defined(CONFIG_CPU_SUBTYPE_SH7709)
+ int i;
+#endif
+
+ make_ipr_irq(TIMER_IRQ, TIMER_IPR_ADDR, TIMER_IPR_POS, TIMER_PRIORITY);
+ make_ipr_irq(TIMER1_IRQ, TIMER1_IPR_ADDR, TIMER1_IPR_POS, TIMER1_PRIORITY);
+#if defined(CONFIG_SH_RTC)
+ make_ipr_irq(RTC_IRQ, RTC_IPR_ADDR, RTC_IPR_POS, RTC_PRIORITY);
+#endif
+
+#ifdef SCI_ERI_IRQ
+ make_ipr_irq(SCI_ERI_IRQ, SCI_IPR_ADDR, SCI_IPR_POS, SCI_PRIORITY);
+ make_ipr_irq(SCI_RXI_IRQ, SCI_IPR_ADDR, SCI_IPR_POS, SCI_PRIORITY);
+ make_ipr_irq(SCI_TXI_IRQ, SCI_IPR_ADDR, SCI_IPR_POS, SCI_PRIORITY);
+#endif
+
+#ifdef SCIF1_ERI_IRQ
+ make_ipr_irq(SCIF1_ERI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY);
+ make_ipr_irq(SCIF1_RXI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY);
+ make_ipr_irq(SCIF1_BRI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY);
+ make_ipr_irq(SCIF1_TXI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY);
+#endif
+
+#if defined(CONFIG_CPU_SUBTYPE_SH7300)
+ make_ipr_irq(SCIF0_IRQ, SCIF0_IPR_ADDR, SCIF0_IPR_POS, SCIF0_PRIORITY);
+ make_ipr_irq(DMTE2_IRQ, DMA1_IPR_ADDR, DMA1_IPR_POS, DMA1_PRIORITY);
+ make_ipr_irq(DMTE3_IRQ, DMA1_IPR_ADDR, DMA1_IPR_POS, DMA1_PRIORITY);
+ make_ipr_irq(VIO_IRQ, VIO_IPR_ADDR, VIO_IPR_POS, VIO_PRIORITY);
+#endif
+
+#ifdef SCIF_ERI_IRQ
+ make_ipr_irq(SCIF_ERI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY);
+ make_ipr_irq(SCIF_RXI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY);
+ make_ipr_irq(SCIF_BRI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY);
+ make_ipr_irq(SCIF_TXI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY);
+#endif
+
+#ifdef IRDA_ERI_IRQ
+ make_ipr_irq(IRDA_ERI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY);
+ make_ipr_irq(IRDA_RXI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY);
+ make_ipr_irq(IRDA_BRI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY);
+ make_ipr_irq(IRDA_TXI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY);
+#endif
+
+#if defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7709) || \
+ defined(CONFIG_CPU_SUBTYPE_SH7300) || defined(CONFIG_CPU_SUBTYPE_SH7705)
+ /*
+ * Initialize the Interrupt Controller (INTC)
+ * registers to their power on values
+ */
+
+ /*
+ * Enable external irq (INTC IRQ mode).
+ * You should set corresponding bits of PFC to "00"
+ * to enable these interrupts.
+ */
+ make_ipr_irq(IRQ0_IRQ, IRQ0_IPR_ADDR, IRQ0_IPR_POS, IRQ0_PRIORITY);
+ make_ipr_irq(IRQ1_IRQ, IRQ1_IPR_ADDR, IRQ1_IPR_POS, IRQ1_PRIORITY);
+ make_ipr_irq(IRQ2_IRQ, IRQ2_IPR_ADDR, IRQ2_IPR_POS, IRQ2_PRIORITY);
+ make_ipr_irq(IRQ3_IRQ, IRQ3_IPR_ADDR, IRQ3_IPR_POS, IRQ3_PRIORITY);
+ make_ipr_irq(IRQ4_IRQ, IRQ4_IPR_ADDR, IRQ4_IPR_POS, IRQ4_PRIORITY);
+ make_ipr_irq(IRQ5_IRQ, IRQ5_IPR_ADDR, IRQ5_IPR_POS, IRQ5_PRIORITY);
+#if !defined(CONFIG_CPU_SUBTYPE_SH7300)
+ make_ipr_irq(PINT0_IRQ, PINT0_IPR_ADDR, PINT0_IPR_POS, PINT0_PRIORITY);
+ make_ipr_irq(PINT8_IRQ, PINT8_IPR_ADDR, PINT8_IPR_POS, PINT8_PRIORITY);
+ enable_ipr_irq(PINT0_IRQ);
+ enable_ipr_irq(PINT8_IRQ);
+
+ for(i = 0; i < 16; i++)
+ make_pint_irq(PINT_IRQ_BASE + i);
+ for(i = 0; i < 256; i++)
+ {
+ if(i & 1) pint_map[i] = 0;
+ else if(i & 2) pint_map[i] = 1;
+ else if(i & 4) pint_map[i] = 2;
+ else if(i & 8) pint_map[i] = 3;
+ else if(i & 0x10) pint_map[i] = 4;
+ else if(i & 0x20) pint_map[i] = 5;
+ else if(i & 0x40) pint_map[i] = 6;
+ else if(i & 0x80) pint_map[i] = 7;
+ }
+#endif /* !CONFIG_CPU_SUBTYPE_SH7300 */
+#endif /* CONFIG_CPU_SUBTYPE_SH7707 || CONFIG_CPU_SUBTYPE_SH7709 || CONFIG_CPU_SUBTYPE_SH7300*/
+
+#ifdef CONFIG_CPU_SUBTYPE_ST40
+ init_IRQ_intc2();
+#endif
+
+ /* Perform the machine specific initialisation */
+ if (sh_mv.mv_init_irq != NULL) {
+ sh_mv.mv_init_irq();
+ }
+}
+#if defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7709) || \
+ defined(CONFIG_CPU_SUBTYPE_SH7300) || defined(CONFIG_CPU_SUBTYPE_SH7705)
+int ipr_irq_demux(int irq)
+{
+#if !defined(CONFIG_CPU_SUBTYPE_SH7300)
+ unsigned long creg, dreg, d, sav;
+
+ if(irq == PINT0_IRQ)
+ {
+#if defined(CONFIG_CPU_SUBTYPE_SH7707)
+ creg = PORT_PACR;
+ dreg = PORT_PADR;
+#else
+ creg = PORT_PCCR;
+ dreg = PORT_PCDR;
+#endif
+ sav = ctrl_inw(creg);
+ ctrl_outw(sav | portcr_mask, creg);
+ d = (~ctrl_inb(dreg) ^ ctrl_inw(INTC_ICR2)) & ctrl_inw(INTC_INTER) & 0xff;
+ ctrl_outw(sav, creg);
+ if(d == 0) return irq;
+ return PINT_IRQ_BASE + pint_map[d];
+ }
+ else if(irq == PINT8_IRQ)
+ {
+#if defined(CONFIG_CPU_SUBTYPE_SH7707)
+ creg = PORT_PBCR;
+ dreg = PORT_PBDR;
+#else
+ creg = PORT_PFCR;
+ dreg = PORT_PFDR;
+#endif
+ sav = ctrl_inw(creg);
+ ctrl_outw(sav | (portcr_mask >> 16), creg);
+ d = (~ctrl_inb(dreg) ^ (ctrl_inw(INTC_ICR2) >> 8)) & (ctrl_inw(INTC_INTER) >> 8) & 0xff;
+ ctrl_outw(sav, creg);
+ if(d == 0) return irq;
+ return PINT_IRQ_BASE + 8 + pint_map[d];
+ }
+#endif
+ return irq;
+}
+#endif
+
+EXPORT_SYMBOL(make_ipr_irq);
+
diff --git a/arch/sh/kernel/cpu/rtc.c b/arch/sh/kernel/cpu/rtc.c
new file mode 100644
index 000000000000..f8361f5e788b
--- /dev/null
+++ b/arch/sh/kernel/cpu/rtc.c
@@ -0,0 +1,136 @@
+/*
+ * linux/arch/sh/kernel/rtc.c -- SH3 / SH4 on-chip RTC support
+ *
+ * Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>
+ * Copyright (C) 1999 Tetsuya Okada & Niibe Yutaka
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+
+#include <asm/io.h>
+#include <asm/rtc.h>
+
+#ifndef BCD_TO_BIN
+#define BCD_TO_BIN(val) ((val)=((val)&15) + ((val)>>4)*10)
+#endif
+
+#ifndef BIN_TO_BCD
+#define BIN_TO_BCD(val) ((val)=(((val)/10)<<4) + (val)%10)
+#endif
+
+void sh_rtc_gettimeofday(struct timespec *ts)
+{
+ unsigned int sec128, sec, sec2, min, hr, wk, day, mon, yr, yr100, cf_bit;
+ unsigned long flags;
+
+ again:
+ do {
+ local_irq_save(flags);
+ ctrl_outb(0, RCR1); /* Clear CF-bit */
+ sec128 = ctrl_inb(R64CNT);
+ sec = ctrl_inb(RSECCNT);
+ min = ctrl_inb(RMINCNT);
+ hr = ctrl_inb(RHRCNT);
+ wk = ctrl_inb(RWKCNT);
+ day = ctrl_inb(RDAYCNT);
+ mon = ctrl_inb(RMONCNT);
+#if defined(CONFIG_CPU_SH4)
+ yr = ctrl_inw(RYRCNT);
+ yr100 = (yr >> 8);
+ yr &= 0xff;
+#else
+ yr = ctrl_inb(RYRCNT);
+ yr100 = (yr == 0x99) ? 0x19 : 0x20;
+#endif
+ sec2 = ctrl_inb(R64CNT);
+ cf_bit = ctrl_inb(RCR1) & RCR1_CF;
+ local_irq_restore(flags);
+ } while (cf_bit != 0 || ((sec128 ^ sec2) & RTC_BIT_INVERTED) != 0);
+
+ BCD_TO_BIN(yr100);
+ BCD_TO_BIN(yr);
+ BCD_TO_BIN(mon);
+ BCD_TO_BIN(day);
+ BCD_TO_BIN(hr);
+ BCD_TO_BIN(min);
+ BCD_TO_BIN(sec);
+
+ if (yr > 99 || mon < 1 || mon > 12 || day > 31 || day < 1 ||
+ hr > 23 || min > 59 || sec > 59) {
+ printk(KERN_ERR
+ "SH RTC: invalid value, resetting to 1 Jan 2000\n");
+ local_irq_save(flags);
+ ctrl_outb(RCR2_RESET, RCR2); /* Reset & Stop */
+ ctrl_outb(0, RSECCNT);
+ ctrl_outb(0, RMINCNT);
+ ctrl_outb(0, RHRCNT);
+ ctrl_outb(6, RWKCNT);
+ ctrl_outb(1, RDAYCNT);
+ ctrl_outb(1, RMONCNT);
+#if defined(CONFIG_CPU_SH4)
+ ctrl_outw(0x2000, RYRCNT);
+#else
+ ctrl_outb(0, RYRCNT);
+#endif
+ ctrl_outb(RCR2_RTCEN|RCR2_START, RCR2); /* Start */
+ goto again;
+ }
+
+#if RTC_BIT_INVERTED != 0
+ if ((sec128 & RTC_BIT_INVERTED))
+ sec--;
+#endif
+
+ ts->tv_sec = mktime(yr100 * 100 + yr, mon, day, hr, min, sec);
+ ts->tv_nsec = ((sec128 * 1000000) / 128) * 1000;
+}
+
+/*
+ * Changed to only care about tv_sec, and not the full timespec struct
+ * (i.e. tv_nsec). It can easily be switched to timespec for future cpus
+ * that support setting usec or nsec RTC values.
+ */
+int sh_rtc_settimeofday(const time_t secs)
+{
+ int retval = 0;
+ int real_seconds, real_minutes, cmos_minutes;
+ unsigned long flags;
+
+ local_irq_save(flags);
+ ctrl_outb(RCR2_RESET, RCR2); /* Reset pre-scaler & stop RTC */
+
+ cmos_minutes = ctrl_inb(RMINCNT);
+ BCD_TO_BIN(cmos_minutes);
+
+ /*
+ * since we're only adjusting minutes and seconds,
+ * don't interfere with hour overflow. This avoids
+ * messing with unknown time zones but requires your
+ * RTC not to be off by more than 15 minutes
+ */
+ real_seconds = secs % 60;
+ real_minutes = secs / 60;
+ if (((abs(real_minutes - cmos_minutes) + 15)/30) & 1)
+ real_minutes += 30; /* correct for half hour time zone */
+ real_minutes %= 60;
+
+ if (abs(real_minutes - cmos_minutes) < 30) {
+ BIN_TO_BCD(real_seconds);
+ BIN_TO_BCD(real_minutes);
+ ctrl_outb(real_seconds, RSECCNT);
+ ctrl_outb(real_minutes, RMINCNT);
+ } else {
+ printk(KERN_WARNING
+ "set_rtc_time: can't update from %d to %d\n",
+ cmos_minutes, real_minutes);
+ retval = -1;
+ }
+
+ ctrl_outb(RCR2_RTCEN|RCR2_START, RCR2); /* Start RTC */
+ local_irq_restore(flags);
+
+ return retval;
+}
diff --git a/arch/sh/kernel/cpu/sh2/Makefile b/arch/sh/kernel/cpu/sh2/Makefile
new file mode 100644
index 000000000000..389353fba608
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh2/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for the Linux/SuperH SH-2 backends.
+#
+
+obj-y := probe.o
+
diff --git a/arch/sh/kernel/cpu/sh2/probe.c b/arch/sh/kernel/cpu/sh2/probe.c
new file mode 100644
index 000000000000..f17a2a0d588e
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh2/probe.c
@@ -0,0 +1,39 @@
+/*
+ * arch/sh/kernel/cpu/sh2/probe.c
+ *
+ * CPU Subtype Probing for SH-2.
+ *
+ * Copyright (C) 2002 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 <asm/processor.h>
+#include <asm/cache.h>
+
+int __init detect_cpu_and_cache_system(void)
+{
+ /*
+ * For now, assume SH7604 .. fix this later.
+ */
+ cpu_data->type = CPU_SH7604;
+ cpu_data->dcache.ways = 4;
+ cpu_data->dcache.way_shift = 6;
+ cpu_data->dcache.sets = 64;
+ cpu_data->dcache.entry_shift = 4;
+ cpu_data->dcache.linesz = L1_CACHE_BYTES;
+ cpu_data->dcache.flags = 0;
+
+ /*
+ * SH-2 doesn't have separate caches
+ */
+ cpu_data->dcache.flags |= SH_CACHE_COMBINED;
+ cpu_data->icache = cpu_data->dcache;
+
+ return 0;
+}
+
diff --git a/arch/sh/kernel/cpu/sh3/Makefile b/arch/sh/kernel/cpu/sh3/Makefile
new file mode 100644
index 000000000000..a64532e4dc63
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh3/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for the Linux/SuperH SH-3 backends.
+#
+
+obj-y := ex.o probe.o
+
diff --git a/arch/sh/kernel/cpu/sh3/ex.S b/arch/sh/kernel/cpu/sh3/ex.S
new file mode 100644
index 000000000000..966c0858b714
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh3/ex.S
@@ -0,0 +1,199 @@
+/*
+ * arch/sh/kernel/cpu/sh3/ex.S
+ *
+ * The SH-3 exception vector table.
+
+ * Copyright (C) 1999, 2000, 2002 Niibe Yutaka
+ * 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/linkage.h>
+#include <linux/config.h>
+
+ .align 2
+ .data
+
+ENTRY(exception_handling_table)
+ .long exception_error /* 000 */
+ .long exception_error
+#if defined(CONFIG_MMU)
+ .long tlb_miss_load /* 040 */
+ .long tlb_miss_store
+ .long initial_page_write
+ .long tlb_protection_violation_load
+ .long tlb_protection_violation_store
+ .long address_error_load
+ .long address_error_store /* 100 */
+#else
+ .long exception_error ! tlb miss load /* 040 */
+ .long exception_error ! tlb miss store
+ .long exception_error ! initial page write
+ .long exception_error ! tlb prot violation load
+ .long exception_error ! tlb prot violation store
+ .long exception_error ! address error load
+ .long exception_error ! address error store /* 100 */
+#endif
+ .long exception_error ! fpu_exception /* 120 */
+ .long exception_error /* 140 */
+ .long system_call ! Unconditional Trap /* 160 */
+ .long exception_error ! reserved_instruction (filled by trap_init) /* 180 */
+ .long exception_error ! illegal_slot_instruction (filled by trap_init) /*1A0*/
+ENTRY(nmi_slot)
+#if defined (CONFIG_KGDB_NMI)
+ .long debug_enter /* 1C0 */ ! Allow trap to debugger
+#else
+ .long exception_none /* 1C0 */ ! Not implemented yet
+#endif
+ENTRY(user_break_point_trap)
+ .long break_point_trap /* 1E0 */
+ENTRY(interrupt_table)
+ ! external hardware
+ .long do_IRQ ! 0000 /* 200 */
+ .long do_IRQ ! 0001
+ .long do_IRQ ! 0010
+ .long do_IRQ ! 0011
+ .long do_IRQ ! 0100
+ .long do_IRQ ! 0101
+ .long do_IRQ ! 0110
+ .long do_IRQ ! 0111
+ .long do_IRQ ! 1000 /* 300 */
+ .long do_IRQ ! 1001
+ .long do_IRQ ! 1010
+ .long do_IRQ ! 1011
+ .long do_IRQ ! 1100
+ .long do_IRQ ! 1101
+ .long do_IRQ ! 1110
+ .long exception_error
+ ! Internal hardware
+ .long do_IRQ ! TMU0 tuni0 /* 400 */
+ .long do_IRQ ! TMU1 tuni1
+ .long do_IRQ ! TMU2 tuni2
+ .long do_IRQ ! ticpi2
+ .long do_IRQ ! RTC ati
+ .long do_IRQ ! pri
+ .long do_IRQ ! cui
+ .long do_IRQ ! SCI eri
+ .long do_IRQ ! rxi /* 500 */
+ .long do_IRQ ! txi
+ .long do_IRQ ! tei
+ .long do_IRQ ! WDT iti /* 560 */
+ .long do_IRQ ! REF rcmi
+ .long do_IRQ ! rovi
+ .long do_IRQ
+ .long do_IRQ /* 5E0 */
+#if defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7709) || \
+ defined(CONFIG_CPU_SUBTYPE_SH7300) || defined(CONFIG_CPU_SUBTYPE_SH7705)
+ .long do_IRQ ! 32 IRQ irq0 /* 600 */
+ .long do_IRQ ! 33 irq1
+ .long do_IRQ ! 34 irq2
+ .long do_IRQ ! 35 irq3
+ .long do_IRQ ! 36 irq4
+ .long do_IRQ ! 37 irq5
+ .long do_IRQ ! 38
+ .long do_IRQ ! 39
+ .long do_IRQ ! 40 PINT pint0-7 /* 700 */
+ .long do_IRQ ! 41 pint8-15
+ .long do_IRQ ! 42
+ .long do_IRQ ! 43
+ .long do_IRQ ! 44
+ .long do_IRQ ! 45
+ .long do_IRQ ! 46
+ .long do_IRQ ! 47
+ .long do_IRQ ! 48 DMAC dei0 /* 800 */
+ .long do_IRQ ! 49 dei1
+ .long do_IRQ ! 50 dei2
+ .long do_IRQ ! 51 dei3
+ .long do_IRQ ! 52 IrDA eri1
+ .long do_IRQ ! 53 rxi1
+ .long do_IRQ ! 54 bri1
+ .long do_IRQ ! 55 txi1
+ .long do_IRQ ! 56 SCIF eri2
+ .long do_IRQ ! 57 rxi2
+ .long do_IRQ ! 58 bri2
+ .long do_IRQ ! 59 txi2
+ .long do_IRQ ! 60 ADC adi /* 980 */
+#if defined(CONFIG_CPU_SUBTYPE_SH7705)
+ .long exception_none ! 61 /* 9A0 */
+ .long exception_none ! 62
+ .long exception_none ! 63
+ .long exception_none ! 64 /* A00 */
+ .long do_IRQ ! 65 USB usi0
+ .long do_IRQ ! 66 usi1
+ .long exception_none ! 67
+ .long exception_none ! 68
+ .long exception_none ! 69
+ .long exception_none ! 70
+ .long exception_none ! 71
+ .long exception_none ! 72 /* B00 */
+ .long exception_none ! 73
+ .long exception_none ! 74
+ .long exception_none ! 75
+ .long exception_none ! 76
+ .long exception_none ! 77
+ .long exception_none ! 78
+ .long exception_none ! 79
+ .long do_IRQ ! 80 TPU0 tpi0 /* C00 */
+ .long do_IRQ ! 81 TPU1 tpi1
+ .long exception_none ! 82
+ .long exception_none ! 83
+ .long do_IRQ ! 84 TPU2 tpi2
+ .long do_IRQ ! 85 TPU3 tpi3 /* CA0 */
+#endif
+#if defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7300)
+ .long do_IRQ ! 61 LCDC lcdi /* 9A0 */
+ .long do_IRQ ! 62 PCC pcc0i
+ .long do_IRQ ! 63 pcc1i /* 9E0 */
+#endif
+#if defined(CONFIG_CPU_SUBTYPE_SH7300)
+ .long do_IRQ ! 64
+ .long do_IRQ ! 65
+ .long do_IRQ ! 66
+ .long do_IRQ ! 67
+ .long do_IRQ ! 68
+ .long do_IRQ ! 69
+ .long do_IRQ ! 70
+ .long do_IRQ ! 71
+ .long do_IRQ ! 72
+ .long do_IRQ ! 73
+ .long do_IRQ ! 74
+ .long do_IRQ ! 75
+ .long do_IRQ ! 76
+ .long do_IRQ ! 77
+ .long do_IRQ ! 78
+ .long do_IRQ ! 79
+ .long do_IRQ ! 80 SCIF0(SH7300)
+ .long do_IRQ ! 81
+ .long do_IRQ ! 82
+ .long do_IRQ ! 83
+ .long do_IRQ ! 84
+ .long do_IRQ ! 85
+ .long do_IRQ ! 86
+ .long do_IRQ ! 87
+ .long do_IRQ ! 88
+ .long do_IRQ ! 89
+ .long do_IRQ ! 90
+ .long do_IRQ ! 91
+ .long do_IRQ ! 92
+ .long do_IRQ ! 93
+ .long do_IRQ ! 94
+ .long do_IRQ ! 95
+ .long do_IRQ ! 96
+ .long do_IRQ ! 97
+ .long do_IRQ ! 98
+ .long do_IRQ ! 99
+ .long do_IRQ ! 100
+ .long do_IRQ ! 101
+ .long do_IRQ ! 102
+ .long do_IRQ ! 103
+ .long do_IRQ ! 104
+ .long do_IRQ ! 105
+ .long do_IRQ ! 106
+ .long do_IRQ ! 107
+ .long do_IRQ ! 108
+#endif
+#endif
+
diff --git a/arch/sh/kernel/cpu/sh3/probe.c b/arch/sh/kernel/cpu/sh3/probe.c
new file mode 100644
index 000000000000..5cdc88638601
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh3/probe.c
@@ -0,0 +1,97 @@
+/*
+ * arch/sh/kernel/cpu/sh3/probe.c
+ *
+ * CPU Subtype Probing for SH-3.
+ *
+ * Copyright (C) 1999, 2000 Niibe Yutaka
+ * Copyright (C) 2002 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 <asm/processor.h>
+#include <asm/cache.h>
+#include <asm/io.h>
+
+int __init detect_cpu_and_cache_system(void)
+{
+ unsigned long addr0, addr1, data0, data1, data2, data3;
+
+ jump_to_P2();
+ /*
+ * Check if the entry shadows or not.
+ * When shadowed, it's 128-entry system.
+ * Otherwise, it's 256-entry system.
+ */
+ addr0 = CACHE_OC_ADDRESS_ARRAY + (3 << 12);
+ addr1 = CACHE_OC_ADDRESS_ARRAY + (1 << 12);
+
+ /* First, write back & invalidate */
+ data0 = ctrl_inl(addr0);
+ ctrl_outl(data0&~(SH_CACHE_VALID|SH_CACHE_UPDATED), addr0);
+ data1 = ctrl_inl(addr1);
+ ctrl_outl(data1&~(SH_CACHE_VALID|SH_CACHE_UPDATED), addr1);
+
+ /* Next, check if there's shadow or not */
+ data0 = ctrl_inl(addr0);
+ data0 ^= SH_CACHE_VALID;
+ ctrl_outl(data0, addr0);
+ data1 = ctrl_inl(addr1);
+ data2 = data1 ^ SH_CACHE_VALID;
+ ctrl_outl(data2, addr1);
+ data3 = ctrl_inl(addr0);
+
+ /* Lastly, invaliate them. */
+ ctrl_outl(data0&~SH_CACHE_VALID, addr0);
+ ctrl_outl(data2&~SH_CACHE_VALID, addr1);
+
+ back_to_P1();
+
+ cpu_data->dcache.ways = 4;
+ cpu_data->dcache.entry_shift = 4;
+ cpu_data->dcache.linesz = L1_CACHE_BYTES;
+ cpu_data->dcache.flags = 0;
+
+ /*
+ * 7709A/7729 has 16K cache (256-entry), while 7702 has only
+ * 2K(direct) 7702 is not supported (yet)
+ */
+ if (data0 == data1 && data2 == data3) { /* Shadow */
+ cpu_data->dcache.way_incr = (1 << 11);
+ cpu_data->dcache.entry_mask = 0x7f0;
+ cpu_data->dcache.sets = 128;
+ cpu_data->type = CPU_SH7708;
+
+ cpu_data->flags |= CPU_HAS_MMU_PAGE_ASSOC;
+ } else { /* 7709A or 7729 */
+ cpu_data->dcache.way_incr = (1 << 12);
+ cpu_data->dcache.entry_mask = 0xff0;
+ cpu_data->dcache.sets = 256;
+ cpu_data->type = CPU_SH7729;
+
+#if defined(CONFIG_CPU_SUBTYPE_SH7705)
+ cpu_data->type = CPU_SH7705;
+
+#if defined(CONFIG_SH7705_CACHE_32KB)
+ cpu_data->dcache.way_incr = (1 << 13);
+ cpu_data->dcache.entry_mask = 0x1ff0;
+ cpu_data->dcache.sets = 512;
+ ctrl_outl(CCR_CACHE_32KB, CCR3);
+#else
+ ctrl_outl(CCR_CACHE_16KB, CCR3);
+#endif
+#endif
+ }
+
+ /*
+ * SH-3 doesn't have separate caches
+ */
+ cpu_data->dcache.flags |= SH_CACHE_COMBINED;
+ cpu_data->icache = cpu_data->dcache;
+
+ return 0;
+}
+
diff --git a/arch/sh/kernel/cpu/sh4/Makefile b/arch/sh/kernel/cpu/sh4/Makefile
new file mode 100644
index 000000000000..ead1071eac73
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh4/Makefile
@@ -0,0 +1,10 @@
+#
+# Makefile for the Linux/SuperH SH-4 backends.
+#
+
+obj-y := ex.o probe.o
+
+obj-$(CONFIG_SH_FPU) += fpu.o
+obj-$(CONFIG_CPU_SUBTYPE_ST40STB1) += irq_intc2.o
+obj-$(CONFIG_SH_STORE_QUEUES) += sq.o
+
diff --git a/arch/sh/kernel/cpu/sh4/ex.S b/arch/sh/kernel/cpu/sh4/ex.S
new file mode 100644
index 000000000000..8221e9d15515
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh4/ex.S
@@ -0,0 +1,384 @@
+/*
+ * arch/sh/kernel/cpu/sh4/ex.S
+ *
+ * The SH-4 exception vector table.
+
+ * Copyright (C) 1999, 2000, 2002 Niibe Yutaka
+ * 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/linkage.h>
+#include <linux/config.h>
+
+ .align 2
+ .data
+
+ENTRY(exception_handling_table)
+ .long exception_error /* 000 */
+ .long exception_error
+#if defined(CONFIG_MMU)
+ .long tlb_miss_load /* 040 */
+ .long tlb_miss_store
+ .long initial_page_write
+ .long tlb_protection_violation_load
+ .long tlb_protection_violation_store
+ .long address_error_load
+ .long address_error_store /* 100 */
+#else
+ .long exception_error ! tlb miss load /* 040 */
+ .long exception_error ! tlb miss store
+ .long exception_error ! initial page write
+ .long exception_error ! tlb prot violation load
+ .long exception_error ! tlb prot violation store
+ .long exception_error ! address error load
+ .long exception_error ! address error store /* 100 */
+#endif
+#if defined(CONFIG_SH_FPU)
+ .long do_fpu_error /* 120 */
+#else
+ .long exception_error /* 120 */
+#endif
+ .long exception_error /* 140 */
+ .long system_call ! Unconditional Trap /* 160 */
+ .long exception_error ! reserved_instruction (filled by trap_init) /* 180 */
+ .long exception_error ! illegal_slot_instruction (filled by trap_init) /*1A0*/
+ENTRY(nmi_slot)
+#if defined (CONFIG_KGDB_NMI)
+ .long debug_enter /* 1C0 */ ! Allow trap to debugger
+#else
+ .long exception_none /* 1C0 */ ! Not implemented yet
+#endif
+ENTRY(user_break_point_trap)
+ .long break_point_trap /* 1E0 */
+ENTRY(interrupt_table)
+ ! external hardware
+ .long do_IRQ ! 0000 /* 200 */
+ .long do_IRQ ! 0001
+ .long do_IRQ ! 0010
+ .long do_IRQ ! 0011
+ .long do_IRQ ! 0100
+ .long do_IRQ ! 0101
+ .long do_IRQ ! 0110
+ .long do_IRQ ! 0111
+ .long do_IRQ ! 1000 /* 300 */
+ .long do_IRQ ! 1001
+ .long do_IRQ ! 1010
+ .long do_IRQ ! 1011
+ .long do_IRQ ! 1100
+ .long do_IRQ ! 1101
+ .long do_IRQ ! 1110
+ .long exception_error
+ ! Internal hardware
+ .long do_IRQ ! TMU0 tuni0 /* 400 */
+ .long do_IRQ ! TMU1 tuni1
+ .long do_IRQ ! TMU2 tuni2
+ .long do_IRQ ! ticpi2
+#if defined(CONFIG_CPU_SUBTYPE_SH7760)
+ .long exception_error
+ .long exception_error
+ .long exception_error
+ .long exception_error
+ .long exception_error /* 500 */
+ .long exception_error
+ .long exception_error
+#else
+ .long do_IRQ ! RTC ati
+ .long do_IRQ ! pri
+ .long do_IRQ ! cui
+ .long do_IRQ ! SCI eri
+ .long do_IRQ ! rxi /* 500 */
+ .long do_IRQ ! txi
+ .long do_IRQ ! tei
+#endif
+ .long do_IRQ ! WDT iti /* 560 */
+ .long do_IRQ ! REF rcmi
+ .long do_IRQ ! rovi
+ .long do_IRQ
+ .long do_IRQ /* 5E0 */
+ .long do_IRQ ! 32 Hitachi UDI /* 600 */
+ .long do_IRQ ! 33 GPIO
+ .long do_IRQ ! 34 DMAC dmte0
+ .long do_IRQ ! 35 dmte1
+ .long do_IRQ ! 36 dmte2
+ .long do_IRQ ! 37 dmte3
+ .long do_IRQ ! 38 dmae
+ .long exception_error ! 39 /* 6E0 */
+#if defined(CONFIG_CPU_SUBTYPE_SH7760)
+ .long exception_error /* 700 */
+ .long exception_error
+ .long exception_error
+ .long exception_error /* 760 */
+#else
+ .long do_IRQ ! 40 SCIF eri /* 700 */
+ .long do_IRQ ! 41 rxi
+ .long do_IRQ ! 42 bri
+ .long do_IRQ ! 43 txi
+#endif
+#if CONFIG_NR_ONCHIP_DMA_CHANNELS == 8
+ .long do_IRQ ! 44 DMAC dmte4 /* 780 */
+ .long do_IRQ ! 45 dmte5
+ .long do_IRQ ! 46 dmte6
+ .long do_IRQ ! 47 dmte7 /* 7E0 */
+#else
+ .long exception_error ! 44 /* 780 */
+ .long exception_error ! 45
+ .long exception_error ! 46
+ .long exception_error ! 47
+#endif
+#if defined(CONFIG_SH_FPU)
+ .long do_fpu_state_restore ! 48 /* 800 */
+ .long do_fpu_state_restore ! 49 /* 820 */
+#else
+ .long exception_error
+ .long exception_error
+#endif
+#if defined(CONFIG_CPU_SUBTYPE_SH7751)
+ .long exception_error /* 840 */
+ .long exception_error
+ .long exception_error
+ .long exception_error
+ .long exception_error
+ .long exception_error
+ .long exception_error /* 900 */
+ .long exception_error
+ .long exception_error
+ .long exception_error
+ .long exception_error
+ .long exception_error
+ .long exception_error
+ .long exception_error
+ .long do_IRQ ! PCI serr /* A00 */
+ .long do_IRQ ! dma3
+ .long do_IRQ ! dma2
+ .long do_IRQ ! dma1
+ .long do_IRQ ! dma0
+ .long do_IRQ ! pwon
+ .long do_IRQ ! pwdwn
+ .long do_IRQ ! err
+ .long do_IRQ ! TMU3 tuni3 /* B00 */
+ .long exception_error
+ .long exception_error
+ .long exception_error
+ .long do_IRQ ! TMU4 tuni4 /* B80 */
+#elif defined(CONFIG_CPU_SUBTYPE_SH7760)
+ .long do_IRQ ! IRQ irq6 /* 840 */
+ .long do_IRQ ! irq7
+ .long do_IRQ ! SCIF eri0
+ .long do_IRQ ! rxi0
+ .long do_IRQ ! bri0
+ .long do_IRQ ! txi0
+ .long do_IRQ ! HCAN2 cani0 /* 900 */
+ .long do_IRQ ! cani1
+ .long do_IRQ ! SSI ssii0
+ .long do_IRQ ! ssii1
+ .long do_IRQ ! HAC haci0
+ .long do_IRQ ! haci1
+ .long do_IRQ ! IIC iici0
+ .long do_IRQ ! iici1
+ .long do_IRQ ! USB usbi /* A00 */
+ .long do_IRQ ! LCDC vint
+ .long exception_error
+ .long exception_error
+ .long do_IRQ ! DMABRG dmabrgi0
+ .long do_IRQ ! dmabrgi1
+ .long do_IRQ ! dmabrgi2
+ .long exception_error
+ .long do_IRQ ! SCIF eri1 /* B00 */
+ .long do_IRQ ! rxi1
+ .long do_IRQ ! bri1
+ .long do_IRQ ! txi1
+ .long do_IRQ ! eri2
+ .long do_IRQ ! rxi2
+ .long do_IRQ ! bri2
+ .long do_IRQ ! txi2
+ .long do_IRQ ! SIM simeri /* C00 */
+ .long do_IRQ ! simrxi
+ .long do_IRQ ! simtxi
+ .long do_IRQ ! simtei
+ .long do_IRQ ! HSPI spii
+ .long exception_error
+ .long exception_error
+ .long exception_error
+ .long do_IRQ ! MMCIF mmci0 /* D00 */
+ .long do_IRQ ! mmci1
+ .long do_IRQ ! mmci2
+ .long do_IRQ ! mmci3
+ .long exception_error
+ .long exception_error
+ .long exception_error
+ .long exception_error
+ .long exception_error /* E00 */
+ .long exception_error
+ .long exception_error
+ .long exception_error
+ .long do_IRQ ! MFI mfii
+ .long exception_error
+ .long exception_error
+ .long exception_error
+ .long exception_error /* F00 */
+ .long exception_error
+ .long exception_error
+ .long exception_error
+ .long do_IRQ ! ADC adi
+ .long do_IRQ ! CMT cmti /* FA0 */
+#elif defined(CONFIG_CPU_SUBTYPE_SH73180)
+ .long do_IRQ ! 50 0x840
+ .long do_IRQ ! 51 0x860
+ .long do_IRQ ! 52 0x880
+ .long do_IRQ ! 53 0x8a0
+ .long do_IRQ ! 54 0x8c0
+ .long do_IRQ ! 55 0x8e0
+ .long do_IRQ ! 56 0x900
+ .long do_IRQ ! 57 0x920
+ .long do_IRQ ! 58 0x940
+ .long do_IRQ ! 59 0x960
+ .long do_IRQ ! 60 0x980
+ .long do_IRQ ! 61 0x9a0
+ .long do_IRQ ! 62 0x9c0
+ .long do_IRQ ! 63 0x9e0
+ .long do_IRQ ! 64 0xa00
+ .long do_IRQ ! 65 0xa20
+ .long do_IRQ ! 66 0xa40
+ .long do_IRQ ! 67 0xa60
+ .long do_IRQ ! 68 0xa80
+ .long do_IRQ ! 69 0xaa0
+ .long do_IRQ ! 70 0xac0
+ .long do_IRQ ! 71 0xae0
+ .long do_IRQ ! 72 0xb00
+ .long do_IRQ ! 73 0xb20
+ .long do_IRQ ! 74 0xb40
+ .long do_IRQ ! 75 0xb60
+ .long do_IRQ ! 76 0xb80
+ .long do_IRQ ! 77 0xba0
+ .long do_IRQ ! 78 0xbc0
+ .long do_IRQ ! 79 0xbe0
+ .long do_IRQ ! 80 0xc00
+ .long do_IRQ ! 81 0xc20
+ .long do_IRQ ! 82 0xc40
+ .long do_IRQ ! 83 0xc60
+ .long do_IRQ ! 84 0xc80
+ .long do_IRQ ! 85 0xca0
+ .long do_IRQ ! 86 0xcc0
+ .long do_IRQ ! 87 0xce0
+ .long do_IRQ ! 88 0xd00
+ .long do_IRQ ! 89 0xd20
+ .long do_IRQ ! 90 0xd40
+ .long do_IRQ ! 91 0xd60
+ .long do_IRQ ! 92 0xd80
+ .long do_IRQ ! 93 0xda0
+ .long do_IRQ ! 94 0xdc0
+ .long do_IRQ ! 95 0xde0
+ .long do_IRQ ! 96 0xe00
+ .long do_IRQ ! 97 0xe20
+ .long do_IRQ ! 98 0xe40
+ .long do_IRQ ! 99 0xe60
+ .long do_IRQ ! 100 0xe80
+ .long do_IRQ ! 101 0xea0
+ .long do_IRQ ! 102 0xec0
+ .long do_IRQ ! 103 0xee0
+ .long do_IRQ ! 104 0xf00
+ .long do_IRQ ! 105 0xf20
+ .long do_IRQ ! 106 0xf40
+ .long do_IRQ ! 107 0xf60
+ .long do_IRQ ! 108 0xf80
+#elif defined(CONFIG_CPU_SUBTYPE_ST40STB1)
+ .long exception_error ! 50 0x840
+ .long exception_error ! 51 0x860
+ .long exception_error ! 52 0x880
+ .long exception_error ! 53 0x8a0
+ .long exception_error ! 54 0x8c0
+ .long exception_error ! 55 0x8e0
+ .long exception_error ! 56 0x900
+ .long exception_error ! 57 0x920
+ .long exception_error ! 58 0x940
+ .long exception_error ! 59 0x960
+ .long exception_error ! 60 0x980
+ .long exception_error ! 61 0x9a0
+ .long exception_error ! 62 0x9c0
+ .long exception_error ! 63 0x9e0
+ .long do_IRQ ! 64 0xa00 PCI serr
+ .long do_IRQ ! 65 0xa20 err
+ .long do_IRQ ! 66 0xa40 ad
+ .long do_IRQ ! 67 0xa60 pwr_dwn
+ .long exception_error ! 68 0xa80
+ .long exception_error ! 69 0xaa0
+ .long exception_error ! 70 0xac0
+ .long exception_error ! 71 0xae0
+ .long do_IRQ ! 72 0xb00 DMA INT0
+ .long do_IRQ ! 73 0xb20 INT1
+ .long do_IRQ ! 74 0xb40 INT2
+ .long do_IRQ ! 75 0xb60 INT3
+ .long do_IRQ ! 76 0xb80 INT4
+ .long exception_error ! 77 0xba0
+ .long do_IRQ ! 78 0xbc0 DMA ERR
+ .long exception_error ! 79 0xbe0
+ .long do_IRQ ! 80 0xc00 PIO0
+ .long do_IRQ ! 81 0xc20 PIO1
+ .long do_IRQ ! 82 0xc40 PIO2
+ .long exception_error ! 83 0xc60
+ .long exception_error ! 84 0xc80
+ .long exception_error ! 85 0xca0
+ .long exception_error ! 86 0xcc0
+ .long exception_error ! 87 0xce0
+ .long exception_error ! 88 0xd00
+ .long exception_error ! 89 0xd20
+ .long exception_error ! 90 0xd40
+ .long exception_error ! 91 0xd60
+ .long exception_error ! 92 0xd80
+ .long exception_error ! 93 0xda0
+ .long exception_error ! 94 0xdc0
+ .long exception_error ! 95 0xde0
+ .long exception_error ! 96 0xe00
+ .long exception_error ! 97 0xe20
+ .long exception_error ! 98 0xe40
+ .long exception_error ! 99 0xe60
+ .long exception_error ! 100 0xe80
+ .long exception_error ! 101 0xea0
+ .long exception_error ! 102 0xec0
+ .long exception_error ! 103 0xee0
+ .long exception_error ! 104 0xf00
+ .long exception_error ! 105 0xf20
+ .long exception_error ! 106 0xf40
+ .long exception_error ! 107 0xf60
+ .long exception_error ! 108 0xf80
+ .long exception_error ! 109 0xfa0
+ .long exception_error ! 110 0xfc0
+ .long exception_error ! 111 0xfe0
+ .long do_IRQ ! 112 0x1000 Mailbox
+ .long exception_error ! 113 0x1020
+ .long exception_error ! 114 0x1040
+ .long exception_error ! 115 0x1060
+ .long exception_error ! 116 0x1080
+ .long exception_error ! 117 0x10a0
+ .long exception_error ! 118 0x10c0
+ .long exception_error ! 119 0x10e0
+ .long exception_error ! 120 0x1100
+ .long exception_error ! 121 0x1120
+ .long exception_error ! 122 0x1140
+ .long exception_error ! 123 0x1160
+ .long exception_error ! 124 0x1180
+ .long exception_error ! 125 0x11a0
+ .long exception_error ! 126 0x11c0
+ .long exception_error ! 127 0x11e0
+ .long exception_error ! 128 0x1200
+ .long exception_error ! 129 0x1220
+ .long exception_error ! 130 0x1240
+ .long exception_error ! 131 0x1260
+ .long exception_error ! 132 0x1280
+ .long exception_error ! 133 0x12a0
+ .long exception_error ! 134 0x12c0
+ .long exception_error ! 135 0x12e0
+ .long exception_error ! 136 0x1300
+ .long exception_error ! 137 0x1320
+ .long exception_error ! 138 0x1340
+ .long exception_error ! 139 0x1360
+ .long do_IRQ ! 140 0x1380 EMPI INV_ADDR
+ .long exception_error ! 141 0x13a0
+ .long exception_error ! 142 0x13c0
+ .long exception_error ! 143 0x13e0
+#endif
+
diff --git a/arch/sh/kernel/cpu/sh4/fpu.c b/arch/sh/kernel/cpu/sh4/fpu.c
new file mode 100644
index 000000000000..f486c07e10e2
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh4/fpu.c
@@ -0,0 +1,335 @@
+/* $Id: fpu.c,v 1.4 2004/01/13 05:52:11 kkojima Exp $
+ *
+ * linux/arch/sh/kernel/fpu.c
+ *
+ * Save/restore floating point context for signal handlers.
+ *
+ * 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) 1999, 2000 Kaz Kojima & Niibe Yutaka
+ *
+ * FIXME! These routines can be optimized in big endian case.
+ */
+
+#include <linux/sched.h>
+#include <linux/signal.h>
+#include <asm/processor.h>
+#include <asm/io.h>
+
+/* The PR (precision) bit in the FP Status Register must be clear when
+ * an frchg instruction is executed, otherwise the instruction is undefined.
+ * Executing frchg with PR set causes a trap on some SH4 implementations.
+ */
+
+#define FPSCR_RCHG 0x00000000
+
+
+/*
+ * Save FPU registers onto task structure.
+ * Assume called with FPU enabled (SR.FD=0).
+ */
+void
+save_fpu(struct task_struct *tsk, struct pt_regs *regs)
+{
+ unsigned long dummy;
+
+ clear_tsk_thread_flag(tsk, TIF_USEDFPU);
+ enable_fpu();
+ asm volatile("sts.l fpul, @-%0\n\t"
+ "sts.l fpscr, @-%0\n\t"
+ "lds %2, fpscr\n\t"
+ "frchg\n\t"
+ "fmov.s fr15, @-%0\n\t"
+ "fmov.s fr14, @-%0\n\t"
+ "fmov.s fr13, @-%0\n\t"
+ "fmov.s fr12, @-%0\n\t"
+ "fmov.s fr11, @-%0\n\t"
+ "fmov.s fr10, @-%0\n\t"
+ "fmov.s fr9, @-%0\n\t"
+ "fmov.s fr8, @-%0\n\t"
+ "fmov.s fr7, @-%0\n\t"
+ "fmov.s fr6, @-%0\n\t"
+ "fmov.s fr5, @-%0\n\t"
+ "fmov.s fr4, @-%0\n\t"
+ "fmov.s fr3, @-%0\n\t"
+ "fmov.s fr2, @-%0\n\t"
+ "fmov.s fr1, @-%0\n\t"
+ "fmov.s fr0, @-%0\n\t"
+ "frchg\n\t"
+ "fmov.s fr15, @-%0\n\t"
+ "fmov.s fr14, @-%0\n\t"
+ "fmov.s fr13, @-%0\n\t"
+ "fmov.s fr12, @-%0\n\t"
+ "fmov.s fr11, @-%0\n\t"
+ "fmov.s fr10, @-%0\n\t"
+ "fmov.s fr9, @-%0\n\t"
+ "fmov.s fr8, @-%0\n\t"
+ "fmov.s fr7, @-%0\n\t"
+ "fmov.s fr6, @-%0\n\t"
+ "fmov.s fr5, @-%0\n\t"
+ "fmov.s fr4, @-%0\n\t"
+ "fmov.s fr3, @-%0\n\t"
+ "fmov.s fr2, @-%0\n\t"
+ "fmov.s fr1, @-%0\n\t"
+ "fmov.s fr0, @-%0\n\t"
+ "lds %3, fpscr\n\t"
+ : "=r" (dummy)
+ : "0" ((char *)(&tsk->thread.fpu.hard.status)),
+ "r" (FPSCR_RCHG),
+ "r" (FPSCR_INIT)
+ : "memory");
+
+ disable_fpu();
+ release_fpu(regs);
+}
+
+static void
+restore_fpu(struct task_struct *tsk)
+{
+ unsigned long dummy;
+
+ enable_fpu();
+ asm volatile("lds %2, fpscr\n\t"
+ "fmov.s @%0+, fr0\n\t"
+ "fmov.s @%0+, fr1\n\t"
+ "fmov.s @%0+, fr2\n\t"
+ "fmov.s @%0+, fr3\n\t"
+ "fmov.s @%0+, fr4\n\t"
+ "fmov.s @%0+, fr5\n\t"
+ "fmov.s @%0+, fr6\n\t"
+ "fmov.s @%0+, fr7\n\t"
+ "fmov.s @%0+, fr8\n\t"
+ "fmov.s @%0+, fr9\n\t"
+ "fmov.s @%0+, fr10\n\t"
+ "fmov.s @%0+, fr11\n\t"
+ "fmov.s @%0+, fr12\n\t"
+ "fmov.s @%0+, fr13\n\t"
+ "fmov.s @%0+, fr14\n\t"
+ "fmov.s @%0+, fr15\n\t"
+ "frchg\n\t"
+ "fmov.s @%0+, fr0\n\t"
+ "fmov.s @%0+, fr1\n\t"
+ "fmov.s @%0+, fr2\n\t"
+ "fmov.s @%0+, fr3\n\t"
+ "fmov.s @%0+, fr4\n\t"
+ "fmov.s @%0+, fr5\n\t"
+ "fmov.s @%0+, fr6\n\t"
+ "fmov.s @%0+, fr7\n\t"
+ "fmov.s @%0+, fr8\n\t"
+ "fmov.s @%0+, fr9\n\t"
+ "fmov.s @%0+, fr10\n\t"
+ "fmov.s @%0+, fr11\n\t"
+ "fmov.s @%0+, fr12\n\t"
+ "fmov.s @%0+, fr13\n\t"
+ "fmov.s @%0+, fr14\n\t"
+ "fmov.s @%0+, fr15\n\t"
+ "frchg\n\t"
+ "lds.l @%0+, fpscr\n\t"
+ "lds.l @%0+, fpul\n\t"
+ : "=r" (dummy)
+ : "0" (&tsk->thread.fpu), "r" (FPSCR_RCHG)
+ : "memory");
+ disable_fpu();
+}
+
+/*
+ * Load the FPU with signalling NANS. This bit pattern we're using
+ * has the property that no matter wether considered as single or as
+ * double precission represents signaling NANS.
+ */
+
+static void
+fpu_init(void)
+{
+ enable_fpu();
+ asm volatile("lds %0, fpul\n\t"
+ "lds %1, fpscr\n\t"
+ "fsts fpul, fr0\n\t"
+ "fsts fpul, fr1\n\t"
+ "fsts fpul, fr2\n\t"
+ "fsts fpul, fr3\n\t"
+ "fsts fpul, fr4\n\t"
+ "fsts fpul, fr5\n\t"
+ "fsts fpul, fr6\n\t"
+ "fsts fpul, fr7\n\t"
+ "fsts fpul, fr8\n\t"
+ "fsts fpul, fr9\n\t"
+ "fsts fpul, fr10\n\t"
+ "fsts fpul, fr11\n\t"
+ "fsts fpul, fr12\n\t"
+ "fsts fpul, fr13\n\t"
+ "fsts fpul, fr14\n\t"
+ "fsts fpul, fr15\n\t"
+ "frchg\n\t"
+ "fsts fpul, fr0\n\t"
+ "fsts fpul, fr1\n\t"
+ "fsts fpul, fr2\n\t"
+ "fsts fpul, fr3\n\t"
+ "fsts fpul, fr4\n\t"
+ "fsts fpul, fr5\n\t"
+ "fsts fpul, fr6\n\t"
+ "fsts fpul, fr7\n\t"
+ "fsts fpul, fr8\n\t"
+ "fsts fpul, fr9\n\t"
+ "fsts fpul, fr10\n\t"
+ "fsts fpul, fr11\n\t"
+ "fsts fpul, fr12\n\t"
+ "fsts fpul, fr13\n\t"
+ "fsts fpul, fr14\n\t"
+ "fsts fpul, fr15\n\t"
+ "frchg\n\t"
+ "lds %2, fpscr\n\t"
+ : /* no output */
+ : "r" (0), "r" (FPSCR_RCHG), "r" (FPSCR_INIT));
+ disable_fpu();
+}
+
+/**
+ * denormal_to_double - Given denormalized float number,
+ * store double float
+ *
+ * @fpu: Pointer to sh_fpu_hard structure
+ * @n: Index to FP register
+ */
+static void
+denormal_to_double (struct sh_fpu_hard_struct *fpu, int n)
+{
+ unsigned long du, dl;
+ unsigned long x = fpu->fpul;
+ int exp = 1023 - 126;
+
+ if (x != 0 && (x & 0x7f800000) == 0) {
+ du = (x & 0x80000000);
+ while ((x & 0x00800000) == 0) {
+ x <<= 1;
+ exp--;
+ }
+ x &= 0x007fffff;
+ du |= (exp << 20) | (x >> 3);
+ dl = x << 29;
+
+ fpu->fp_regs[n] = du;
+ fpu->fp_regs[n+1] = dl;
+ }
+}
+
+/**
+ * ieee_fpe_handler - Handle denormalized number exception
+ *
+ * @regs: Pointer to register structure
+ *
+ * Returns 1 when it's handled (should not cause exception).
+ */
+static int
+ieee_fpe_handler (struct pt_regs *regs)
+{
+ unsigned short insn = *(unsigned short *) regs->pc;
+ unsigned short finsn;
+ unsigned long nextpc;
+ int nib[4] = {
+ (insn >> 12) & 0xf,
+ (insn >> 8) & 0xf,
+ (insn >> 4) & 0xf,
+ insn & 0xf};
+
+ if (nib[0] == 0xb ||
+ (nib[0] == 0x4 && nib[2] == 0x0 && nib[3] == 0xb)) /* bsr & jsr */
+ regs->pr = regs->pc + 4;
+
+ if (nib[0] == 0xa || nib[0] == 0xb) { /* bra & bsr */
+ nextpc = regs->pc + 4 + ((short) ((insn & 0xfff) << 4) >> 3);
+ finsn = *(unsigned short *) (regs->pc + 2);
+ } else if (nib[0] == 0x8 && nib[1] == 0xd) { /* bt/s */
+ if (regs->sr & 1)
+ nextpc = regs->pc + 4 + ((char) (insn & 0xff) << 1);
+ else
+ nextpc = regs->pc + 4;
+ finsn = *(unsigned short *) (regs->pc + 2);
+ } else if (nib[0] == 0x8 && nib[1] == 0xf) { /* bf/s */
+ if (regs->sr & 1)
+ nextpc = regs->pc + 4;
+ else
+ nextpc = regs->pc + 4 + ((char) (insn & 0xff) << 1);
+ finsn = *(unsigned short *) (regs->pc + 2);
+ } else if (nib[0] == 0x4 && nib[3] == 0xb &&
+ (nib[2] == 0x0 || nib[2] == 0x2)) { /* jmp & jsr */
+ nextpc = regs->regs[nib[1]];
+ finsn = *(unsigned short *) (regs->pc + 2);
+ } else if (nib[0] == 0x0 && nib[3] == 0x3 &&
+ (nib[2] == 0x0 || nib[2] == 0x2)) { /* braf & bsrf */
+ nextpc = regs->pc + 4 + regs->regs[nib[1]];
+ finsn = *(unsigned short *) (regs->pc + 2);
+ } else if (insn == 0x000b) { /* rts */
+ nextpc = regs->pr;
+ finsn = *(unsigned short *) (regs->pc + 2);
+ } else {
+ nextpc = regs->pc + 2;
+ finsn = insn;
+ }
+
+ if ((finsn & 0xf1ff) == 0xf0ad) { /* fcnvsd */
+ struct task_struct *tsk = current;
+
+ save_fpu(tsk, regs);
+ if ((tsk->thread.fpu.hard.fpscr & (1 << 17))) {
+ /* FPU error */
+ denormal_to_double (&tsk->thread.fpu.hard,
+ (finsn >> 8) & 0xf);
+ tsk->thread.fpu.hard.fpscr &=
+ ~(FPSCR_CAUSE_MASK | FPSCR_FLAG_MASK);
+ grab_fpu(regs);
+ restore_fpu(tsk);
+ set_tsk_thread_flag(tsk, TIF_USEDFPU);
+ } else {
+ tsk->thread.trap_no = 11;
+ tsk->thread.error_code = 0;
+ force_sig(SIGFPE, tsk);
+ }
+
+ regs->pc = nextpc;
+ return 1;
+ }
+
+ return 0;
+}
+
+asmlinkage void
+do_fpu_error(unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7,
+ struct pt_regs regs)
+{
+ struct task_struct *tsk = current;
+
+ if (ieee_fpe_handler (&regs))
+ return;
+
+ regs.pc += 2;
+ save_fpu(tsk, &regs);
+ tsk->thread.trap_no = 11;
+ tsk->thread.error_code = 0;
+ force_sig(SIGFPE, tsk);
+}
+
+asmlinkage void
+do_fpu_state_restore(unsigned long r4, unsigned long r5, unsigned long r6,
+ unsigned long r7, struct pt_regs regs)
+{
+ struct task_struct *tsk = current;
+
+ grab_fpu(&regs);
+ if (!user_mode(&regs)) {
+ printk(KERN_ERR "BUG: FPU is used in kernel mode.\n");
+ return;
+ }
+
+ if (used_math()) {
+ /* Using the FPU again. */
+ restore_fpu(tsk);
+ } else {
+ /* First time FPU user. */
+ fpu_init();
+ set_used_math();
+ }
+ set_tsk_thread_flag(tsk, TIF_USEDFPU);
+}
diff --git a/arch/sh/kernel/cpu/sh4/irq_intc2.c b/arch/sh/kernel/cpu/sh4/irq_intc2.c
new file mode 100644
index 000000000000..099ebbf89745
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh4/irq_intc2.c
@@ -0,0 +1,222 @@
+/*
+ * linux/arch/sh/kernel/irq_intc2.c
+ *
+ * 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.
+ *
+ * Interrupt handling for INTC2-based IRQ.
+ *
+ * These are the "new Hitachi style" interrupts, as present on the
+ * Hitachi 7751 and the STM ST40 STB1.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/machvec.h>
+
+
+struct intc2_data {
+ unsigned char msk_offset;
+ unsigned char msk_shift;
+#ifdef CONFIG_CPU_SUBTYPE_ST40
+ int (*clear_irq) (int);
+#endif
+};
+
+
+static struct intc2_data intc2_data[NR_INTC2_IRQS];
+
+static void enable_intc2_irq(unsigned int irq);
+static void disable_intc2_irq(unsigned int irq);
+
+/* shutdown is same as "disable" */
+#define shutdown_intc2_irq disable_intc2_irq
+
+static void mask_and_ack_intc2(unsigned int);
+static void end_intc2_irq(unsigned int irq);
+
+static unsigned int startup_intc2_irq(unsigned int irq)
+{
+ enable_intc2_irq(irq);
+ return 0; /* never anything pending */
+}
+
+static struct hw_interrupt_type intc2_irq_type = {
+ "INTC2-IRQ",
+ startup_intc2_irq,
+ shutdown_intc2_irq,
+ enable_intc2_irq,
+ disable_intc2_irq,
+ mask_and_ack_intc2,
+ end_intc2_irq
+};
+
+static void disable_intc2_irq(unsigned int irq)
+{
+ int irq_offset = irq - INTC2_FIRST_IRQ;
+ int msk_shift, msk_offset;
+
+ // Sanity check
+ if((irq_offset<0) || (irq_offset>=NR_INTC2_IRQS))
+ return;
+
+ msk_shift = intc2_data[irq_offset].msk_shift;
+ msk_offset = intc2_data[irq_offset].msk_offset;
+
+ ctrl_outl(1<<msk_shift,
+ INTC2_BASE+INTC2_INTMSK_OFFSET+msk_offset);
+}
+
+static void enable_intc2_irq(unsigned int irq)
+{
+ int irq_offset = irq - INTC2_FIRST_IRQ;
+ int msk_shift, msk_offset;
+
+ /* Sanity check */
+ if((irq_offset<0) || (irq_offset>=NR_INTC2_IRQS))
+ return;
+
+ msk_shift = intc2_data[irq_offset].msk_shift;
+ msk_offset = intc2_data[irq_offset].msk_offset;
+
+ ctrl_outl(1<<msk_shift,
+ INTC2_BASE+INTC2_INTMSKCLR_OFFSET+msk_offset);
+}
+
+static void mask_and_ack_intc2(unsigned int irq)
+{
+ disable_intc2_irq(irq);
+}
+
+static void end_intc2_irq(unsigned int irq)
+{
+ if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+ enable_intc2_irq(irq);
+
+#ifdef CONFIG_CPU_SUBTYPE_ST40
+ if (intc2_data[irq - INTC2_FIRST_IRQ].clear_irq)
+ intc2_data[irq - INTC2_FIRST_IRQ].clear_irq (irq);
+#endif
+}
+
+/*
+ * Setup an INTC2 style interrupt.
+ * NOTE: Unlike IPR interrupts, parameters are not shifted by this code,
+ * allowing the use of the numbers straight out of the datasheet.
+ * For example:
+ * PIO1 which is INTPRI00[19,16] and INTMSK00[13]
+ * would be: ^ ^ ^ ^
+ * | | | |
+ * make_intc2_irq(84, 0, 16, 0, 13);
+ */
+void make_intc2_irq(unsigned int irq,
+ unsigned int ipr_offset, unsigned int ipr_shift,
+ unsigned int msk_offset, unsigned int msk_shift,
+ unsigned int priority)
+{
+ int irq_offset = irq - INTC2_FIRST_IRQ;
+ unsigned int flags;
+ unsigned long ipr;
+
+ if((irq_offset<0) || (irq_offset>=NR_INTC2_IRQS))
+ return;
+
+ disable_irq_nosync(irq);
+
+ /* Fill the data we need */
+ intc2_data[irq_offset].msk_offset = msk_offset;
+ intc2_data[irq_offset].msk_shift = msk_shift;
+#ifdef CONFIG_CPU_SUBTYPE_ST40
+ intc2_data[irq_offset].clear_irq = NULL;
+#endif
+
+ /* Set the priority level */
+ local_irq_save(flags);
+
+ ipr=ctrl_inl(INTC2_BASE+INTC2_INTPRI_OFFSET+ipr_offset);
+ ipr&=~(0xf<<ipr_shift);
+ ipr|=(priority)<<ipr_shift;
+ ctrl_outl(ipr, INTC2_BASE+INTC2_INTPRI_OFFSET+ipr_offset);
+
+ local_irq_restore(flags);
+
+ irq_desc[irq].handler=&intc2_irq_type;
+
+ disable_intc2_irq(irq);
+}
+
+#ifdef CONFIG_CPU_SUBTYPE_ST40
+
+struct intc2_init {
+ unsigned short irq;
+ unsigned char ipr_offset, ipr_shift;
+ unsigned char msk_offset, msk_shift;
+};
+
+static struct intc2_init intc2_init_data[] __initdata = {
+ {64, 0, 0, 0, 0}, /* PCI serr */
+ {65, 0, 4, 0, 1}, /* PCI err */
+ {66, 0, 4, 0, 2}, /* PCI ad */
+ {67, 0, 4, 0, 3}, /* PCI pwd down */
+ {72, 0, 8, 0, 5}, /* DMAC INT0 */
+ {73, 0, 8, 0, 6}, /* DMAC INT1 */
+ {74, 0, 8, 0, 7}, /* DMAC INT2 */
+ {75, 0, 8, 0, 8}, /* DMAC INT3 */
+ {76, 0, 8, 0, 9}, /* DMAC INT4 */
+ {78, 0, 8, 0, 11}, /* DMAC ERR */
+ {80, 0, 12, 0, 12}, /* PIO0 */
+ {84, 0, 16, 0, 13}, /* PIO1 */
+ {88, 0, 20, 0, 14}, /* PIO2 */
+ {112, 4, 0, 4, 0}, /* Mailbox */
+#ifdef CONFIG_CPU_SUBTYPE_ST40GX1
+ {116, 4, 4, 4, 4}, /* SSC0 */
+ {120, 4, 8, 4, 8}, /* IR Blaster */
+ {124, 4, 12, 4, 12}, /* USB host */
+ {128, 4, 16, 4, 16}, /* Video processor BLITTER */
+ {132, 4, 20, 4, 20}, /* UART0 */
+ {134, 4, 20, 4, 22}, /* UART2 */
+ {136, 4, 24, 4, 24}, /* IO_PIO0 */
+ {140, 4, 28, 4, 28}, /* EMPI */
+ {144, 8, 0, 8, 0}, /* MAFE */
+ {148, 8, 4, 8, 4}, /* PWM */
+ {152, 8, 8, 8, 8}, /* SSC1 */
+ {156, 8, 12, 8, 12}, /* IO_PIO1 */
+ {160, 8, 16, 8, 16}, /* USB target */
+ {164, 8, 20, 8, 20}, /* UART1 */
+ {168, 8, 24, 8, 24}, /* Teletext */
+ {172, 8, 28, 8, 28}, /* VideoSync VTG */
+ {173, 8, 28, 8, 29}, /* VideoSync DVP0 */
+ {174, 8, 28, 8, 30}, /* VideoSync DVP1 */
+#endif
+};
+
+void __init init_IRQ_intc2(void)
+{
+ struct intc2_init *p;
+
+ printk(KERN_ALERT "init_IRQ_intc2\n");
+
+ for (p = intc2_init_data;
+ p<intc2_init_data+ARRAY_SIZE(intc2_init_data);
+ p++) {
+ make_intc2_irq(p->irq, p->ipr_offset, p->ipr_shift,
+ p-> msk_offset, p->msk_shift, 13);
+ }
+}
+
+/* Adds a termination callback to the interrupt */
+void intc2_add_clear_irq(int irq, int (*fn)(int))
+{
+ if (irq < INTC2_FIRST_IRQ)
+ return;
+
+ intc2_data[irq - INTC2_FIRST_IRQ].clear_irq = fn;
+}
+
+#endif /* CONFIG_CPU_SUBTYPE_ST40 */
diff --git a/arch/sh/kernel/cpu/sh4/probe.c b/arch/sh/kernel/cpu/sh4/probe.c
new file mode 100644
index 000000000000..42427b79697b
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh4/probe.c
@@ -0,0 +1,138 @@
+/*
+ * arch/sh/kernel/cpu/sh4/probe.c
+ *
+ * CPU Subtype Probing for SH-4.
+ *
+ * Copyright (C) 2001, 2002, 2003, 2004 Paul Mundt
+ * Copyright (C) 2003 Richard Curnow
+ *
+ * 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 <asm/processor.h>
+#include <asm/cache.h>
+#include <asm/io.h>
+
+int __init detect_cpu_and_cache_system(void)
+{
+ unsigned long pvr, prr, cvr;
+ unsigned long size;
+
+ static unsigned long sizes[16] = {
+ [1] = (1 << 12),
+ [2] = (1 << 13),
+ [4] = (1 << 14),
+ [8] = (1 << 15),
+ [9] = (1 << 16)
+ };
+
+ pvr = (ctrl_inl(CCN_PVR) >> 8) & 0xffff;
+ prr = (ctrl_inl(CCN_PRR) >> 4) & 0xff;
+ cvr = (ctrl_inl(CCN_CVR));
+
+ /*
+ * Setup some sane SH-4 defaults for the icache
+ */
+ cpu_data->icache.way_incr = (1 << 13);
+ cpu_data->icache.entry_shift = 5;
+ cpu_data->icache.entry_mask = 0x1fe0;
+ cpu_data->icache.sets = 256;
+ cpu_data->icache.ways = 1;
+ cpu_data->icache.linesz = L1_CACHE_BYTES;
+
+ /*
+ * And again for the dcache ..
+ */
+ cpu_data->dcache.way_incr = (1 << 14);
+ cpu_data->dcache.entry_shift = 5;
+ cpu_data->dcache.entry_mask = 0x3fe0;
+ cpu_data->dcache.sets = 512;
+ cpu_data->dcache.ways = 1;
+ cpu_data->dcache.linesz = L1_CACHE_BYTES;
+
+ /* Set the FPU flag, virtually all SH-4's have one */
+ cpu_data->flags |= CPU_HAS_FPU;
+
+ /*
+ * Probe the underlying processor version/revision and
+ * adjust cpu_data setup accordingly.
+ */
+ switch (pvr) {
+ case 0x205:
+ cpu_data->type = CPU_SH7750;
+ cpu_data->flags |= CPU_HAS_P2_FLUSH_BUG | CPU_HAS_PERF_COUNTER;
+ break;
+ case 0x206:
+ cpu_data->type = CPU_SH7750S;
+ cpu_data->flags |= CPU_HAS_P2_FLUSH_BUG | CPU_HAS_PERF_COUNTER;
+ break;
+ case 0x1100:
+ cpu_data->type = CPU_SH7751;
+ break;
+ case 0x2000:
+ cpu_data->type = CPU_SH73180;
+ cpu_data->icache.ways = 4;
+ cpu_data->dcache.ways = 4;
+ cpu_data->flags &= ~CPU_HAS_FPU;
+ break;
+ case 0x8000:
+ cpu_data->type = CPU_ST40RA;
+ break;
+ case 0x8100:
+ cpu_data->type = CPU_ST40GX1;
+ break;
+ case 0x700:
+ cpu_data->type = CPU_SH4_501;
+ cpu_data->icache.ways = 2;
+ cpu_data->dcache.ways = 2;
+
+ /* No FPU on the SH4-500 series.. */
+ cpu_data->flags &= ~CPU_HAS_FPU;
+ break;
+ case 0x600:
+ cpu_data->type = CPU_SH4_202;
+ cpu_data->icache.ways = 2;
+ cpu_data->dcache.ways = 2;
+ break;
+ case 0x500 ... 0x501:
+ switch (prr) {
+ case 0x10: cpu_data->type = CPU_SH7750R; break;
+ case 0x11: cpu_data->type = CPU_SH7751R; break;
+ case 0x50: cpu_data->type = CPU_SH7760; break;
+ }
+
+ cpu_data->icache.ways = 2;
+ cpu_data->dcache.ways = 2;
+
+ break;
+ default:
+ cpu_data->type = CPU_SH_NONE;
+ break;
+ }
+
+ /*
+ * On anything that's not a direct-mapped cache, look to the CVR
+ * for I/D-cache specifics.
+ */
+ if (cpu_data->icache.ways > 1) {
+ size = sizes[(cvr >> 20) & 0xf];
+ cpu_data->icache.way_incr = (size >> 1);
+ cpu_data->icache.sets = (size >> 6);
+ cpu_data->icache.entry_mask =
+ (cpu_data->icache.way_incr - (1 << 5));
+ }
+
+ if (cpu_data->dcache.ways > 1) {
+ size = sizes[(cvr >> 16) & 0xf];
+ cpu_data->dcache.way_incr = (size >> 1);
+ cpu_data->dcache.sets = (size >> 6);
+ cpu_data->dcache.entry_mask =
+ (cpu_data->dcache.way_incr - (1 << 5));
+ }
+
+ return 0;
+}
+
diff --git a/arch/sh/kernel/cpu/sh4/sq.c b/arch/sh/kernel/cpu/sh4/sq.c
new file mode 100644
index 000000000000..8437ea7430fe
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh4/sq.c
@@ -0,0 +1,453 @@
+/*
+ * arch/sh/kernel/cpu/sq.c
+ *
+ * General management API for SH-4 integrated Store Queues
+ *
+ * Copyright (C) 2001, 2002, 2003, 2004 Paul Mundt
+ * Copyright (C) 2001, 2002 M. R. Brown
+ *
+ * Some of this code has been adopted directly from the old arch/sh/mm/sq.c
+ * hack that was part of the LinuxDC project. For all intents and purposes,
+ * this is a completely new interface that really doesn't have much in common
+ * with the old zone-based approach at all. In fact, it's only listed here for
+ * general completeness.
+ *
+ * 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/kernel.h>
+#include <linux/module.h>
+#include <linux/config.h>
+#include <linux/slab.h>
+#include <linux/list.h>
+#include <linux/proc_fs.h>
+#include <linux/miscdevice.h>
+#include <linux/vmalloc.h>
+
+#include <asm/io.h>
+#include <asm/page.h>
+#include <asm/mmu_context.h>
+#include <asm/cpu/sq.h>
+
+static LIST_HEAD(sq_mapping_list);
+static DEFINE_SPINLOCK(sq_mapping_lock);
+
+/**
+ * sq_flush - Flush (prefetch) the store queue cache
+ * @addr: the store queue address to flush
+ *
+ * Executes a prefetch instruction on the specified store queue cache,
+ * so that the cached data is written to physical memory.
+ */
+inline void sq_flush(void *addr)
+{
+ __asm__ __volatile__ ("pref @%0" : : "r" (addr) : "memory");
+}
+
+/**
+ * sq_flush_range - Flush (prefetch) a specific SQ range
+ * @start: the store queue address to start flushing from
+ * @len: the length to flush
+ *
+ * Flushes the store queue cache from @start to @start + @len in a
+ * linear fashion.
+ */
+void sq_flush_range(unsigned long start, unsigned int len)
+{
+ volatile unsigned long *sq = (unsigned long *)start;
+ unsigned long dummy;
+
+ /* Flush the queues */
+ for (len >>= 5; len--; sq += 8)
+ sq_flush((void *)sq);
+
+ /* Wait for completion */
+ dummy = ctrl_inl(P4SEG_STORE_QUE);
+
+ ctrl_outl(0, P4SEG_STORE_QUE + 0);
+ ctrl_outl(0, P4SEG_STORE_QUE + 8);
+}
+
+static struct sq_mapping *__sq_alloc_mapping(unsigned long virt, unsigned long phys, unsigned long size, const char *name)
+{
+ struct sq_mapping *map;
+
+ if (virt + size > SQ_ADDRMAX)
+ return ERR_PTR(-ENOSPC);
+
+ map = kmalloc(sizeof(struct sq_mapping), GFP_KERNEL);
+ if (!map)
+ return ERR_PTR(-ENOMEM);
+
+ INIT_LIST_HEAD(&map->list);
+
+ map->sq_addr = virt;
+ map->addr = phys;
+ map->size = size + 1;
+ map->name = name;
+
+ list_add(&map->list, &sq_mapping_list);
+
+ return map;
+}
+
+static unsigned long __sq_get_next_addr(void)
+{
+ if (!list_empty(&sq_mapping_list)) {
+ struct list_head *pos, *tmp;
+
+ /*
+ * Read one off the list head, as it will have the highest
+ * mapped allocation. Set the next one up right above it.
+ *
+ * This is somewhat sub-optimal, as we don't look at
+ * gaps between allocations or anything lower then the
+ * highest-level allocation.
+ *
+ * However, in the interest of performance and the general
+ * lack of desire to do constant list rebalancing, we don't
+ * worry about it.
+ */
+ list_for_each_safe(pos, tmp, &sq_mapping_list) {
+ struct sq_mapping *entry;
+
+ entry = list_entry(pos, typeof(*entry), list);
+
+ return entry->sq_addr + entry->size;
+ }
+ }
+
+ return P4SEG_STORE_QUE;
+}
+
+/**
+ * __sq_remap - Perform a translation from the SQ to a phys addr
+ * @map: sq mapping containing phys and store queue addresses.
+ *
+ * Maps the store queue address specified in the mapping to the physical
+ * address specified in the mapping.
+ */
+static struct sq_mapping *__sq_remap(struct sq_mapping *map)
+{
+ unsigned long flags, pteh, ptel;
+ struct vm_struct *vma;
+ pgprot_t pgprot;
+
+ /*
+ * Without an MMU (or with it turned off), this is much more
+ * straightforward, as we can just load up each queue's QACR with
+ * the physical address appropriately masked.
+ */
+
+ ctrl_outl(((map->addr >> 26) << 2) & 0x1c, SQ_QACR0);
+ ctrl_outl(((map->addr >> 26) << 2) & 0x1c, SQ_QACR1);
+
+#ifdef CONFIG_MMU
+ /*
+ * With an MMU on the other hand, things are slightly more involved.
+ * Namely, we have to have a direct mapping between the SQ addr and
+ * the associated physical address in the UTLB by way of setting up
+ * a virt<->phys translation by hand. We do this by simply specifying
+ * the SQ addr in UTLB.VPN and the associated physical address in
+ * UTLB.PPN.
+ *
+ * Notably, even though this is a special case translation, and some
+ * of the configuration bits are meaningless, we're still required
+ * to have a valid ASID context in PTEH.
+ *
+ * We could also probably get by without explicitly setting PTEA, but
+ * we do it here just for good measure.
+ */
+ spin_lock_irqsave(&sq_mapping_lock, flags);
+
+ pteh = map->sq_addr;
+ ctrl_outl((pteh & MMU_VPN_MASK) | get_asid(), MMU_PTEH);
+
+ ptel = map->addr & PAGE_MASK;
+ ctrl_outl(((ptel >> 28) & 0xe) | (ptel & 0x1), MMU_PTEA);
+
+ pgprot = pgprot_noncached(PAGE_KERNEL);
+
+ ptel &= _PAGE_FLAGS_HARDWARE_MASK;
+ ptel |= pgprot_val(pgprot);
+ ctrl_outl(ptel, MMU_PTEL);
+
+ __asm__ __volatile__ ("ldtlb" : : : "memory");
+
+ spin_unlock_irqrestore(&sq_mapping_lock, flags);
+
+ /*
+ * Next, we need to map ourselves in the kernel page table, so that
+ * future accesses after a TLB flush will be handled when we take a
+ * page fault.
+ *
+ * Theoretically we could just do this directly and not worry about
+ * setting up the translation by hand ahead of time, but for the
+ * cases where we want a one-shot SQ mapping followed by a quick
+ * writeout before we hit the TLB flush, we do it anyways. This way
+ * we at least save ourselves the initial page fault overhead.
+ */
+ vma = __get_vm_area(map->size, VM_ALLOC, map->sq_addr, SQ_ADDRMAX);
+ if (!vma)
+ return ERR_PTR(-ENOMEM);
+
+ vma->phys_addr = map->addr;
+
+ if (remap_area_pages((unsigned long)vma->addr, vma->phys_addr,
+ map->size, pgprot_val(pgprot))) {
+ vunmap(vma->addr);
+ return NULL;
+ }
+#endif /* CONFIG_MMU */
+
+ return map;
+}
+
+/**
+ * sq_remap - Map a physical address through the Store Queues
+ * @phys: Physical address of mapping.
+ * @size: Length of mapping.
+ * @name: User invoking mapping.
+ *
+ * Remaps the physical address @phys through the next available store queue
+ * address of @size length. @name is logged at boot time as well as through
+ * the procfs interface.
+ *
+ * A pre-allocated and filled sq_mapping pointer is returned, and must be
+ * cleaned up with a call to sq_unmap() when the user is done with the
+ * mapping.
+ */
+struct sq_mapping *sq_remap(unsigned long phys, unsigned int size, const char *name)
+{
+ struct sq_mapping *map;
+ unsigned long virt, end;
+ unsigned int psz;
+
+ /* Don't allow wraparound or zero size */
+ end = phys + size - 1;
+ if (!size || end < phys)
+ return NULL;
+ /* Don't allow anyone to remap normal memory.. */
+ if (phys < virt_to_phys(high_memory))
+ return NULL;
+
+ phys &= PAGE_MASK;
+
+ size = PAGE_ALIGN(end + 1) - phys;
+ virt = __sq_get_next_addr();
+ psz = (size + (PAGE_SIZE - 1)) / PAGE_SIZE;
+ map = __sq_alloc_mapping(virt, phys, size, name);
+
+ printk("sqremap: %15s [%4d page%s] va 0x%08lx pa 0x%08lx\n",
+ map->name ? map->name : "???",
+ psz, psz == 1 ? " " : "s",
+ map->sq_addr, map->addr);
+
+ return __sq_remap(map);
+}
+
+/**
+ * sq_unmap - Unmap a Store Queue allocation
+ * @map: Pre-allocated Store Queue mapping.
+ *
+ * Unmaps the store queue allocation @map that was previously created by
+ * sq_remap(). Also frees up the pte that was previously inserted into
+ * the kernel page table and discards the UTLB translation.
+ */
+void sq_unmap(struct sq_mapping *map)
+{
+ if (map->sq_addr > (unsigned long)high_memory)
+ vfree((void *)(map->sq_addr & PAGE_MASK));
+
+ list_del(&map->list);
+ kfree(map);
+}
+
+/**
+ * sq_clear - Clear a store queue range
+ * @addr: Address to start clearing from.
+ * @len: Length to clear.
+ *
+ * A quick zero-fill implementation for clearing out memory that has been
+ * remapped through the store queues.
+ */
+void sq_clear(unsigned long addr, unsigned int len)
+{
+ int i;
+
+ /* Clear out both queues linearly */
+ for (i = 0; i < 8; i++) {
+ ctrl_outl(0, addr + i + 0);
+ ctrl_outl(0, addr + i + 8);
+ }
+
+ sq_flush_range(addr, len);
+}
+
+/**
+ * sq_vma_unmap - Unmap a VMA range
+ * @area: VMA containing range.
+ * @addr: Start of range.
+ * @len: Length of range.
+ *
+ * Searches the sq_mapping_list for a mapping matching the sq addr @addr,
+ * and subsequently frees up the entry. Further cleanup is done by generic
+ * code.
+ */
+static void sq_vma_unmap(struct vm_area_struct *area,
+ unsigned long addr, size_t len)
+{
+ struct list_head *pos, *tmp;
+
+ list_for_each_safe(pos, tmp, &sq_mapping_list) {
+ struct sq_mapping *entry;
+
+ entry = list_entry(pos, typeof(*entry), list);
+
+ if (entry->sq_addr == addr) {
+ /*
+ * We could probably get away without doing the tlb flush
+ * here, as generic code should take care of most of this
+ * when unmapping the rest of the VMA range for us. Leave
+ * it in for added sanity for the time being..
+ */
+ __flush_tlb_page(get_asid(), entry->sq_addr & PAGE_MASK);
+
+ list_del(&entry->list);
+ kfree(entry);
+
+ return;
+ }
+ }
+}
+
+/**
+ * sq_vma_sync - Sync a VMA range
+ * @area: VMA containing range.
+ * @start: Start of range.
+ * @len: Length of range.
+ * @flags: Additional flags.
+ *
+ * Synchronizes an sq mapped range by flushing the store queue cache for
+ * the duration of the mapping.
+ *
+ * Used internally for user mappings, which must use msync() to prefetch
+ * the store queue cache.
+ */
+static int sq_vma_sync(struct vm_area_struct *area,
+ unsigned long start, size_t len, unsigned int flags)
+{
+ sq_flush_range(start, len);
+
+ return 0;
+}
+
+static struct vm_operations_struct sq_vma_ops = {
+ .unmap = sq_vma_unmap,
+ .sync = sq_vma_sync,
+};
+
+/**
+ * sq_mmap - mmap() for /dev/cpu/sq
+ * @file: unused.
+ * @vma: VMA to remap.
+ *
+ * Remap the specified vma @vma through the store queues, and setup associated
+ * information for the new mapping. Also build up the page tables for the new
+ * area.
+ */
+static int sq_mmap(struct file *file, struct vm_area_struct *vma)
+{
+ unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
+ unsigned long size = vma->vm_end - vma->vm_start;
+ struct sq_mapping *map;
+
+ /*
+ * We're not interested in any arbitrary virtual address that has
+ * been stuck in the VMA, as we already know what addresses we
+ * want. Save off the size, and reposition the VMA to begin at
+ * the next available sq address.
+ */
+ vma->vm_start = __sq_get_next_addr();
+ vma->vm_end = vma->vm_start + size;
+
+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+
+ vma->vm_flags |= VM_IO | VM_RESERVED;
+
+ map = __sq_alloc_mapping(vma->vm_start, offset, size, "Userspace");
+
+ if (io_remap_pfn_range(vma, map->sq_addr, map->addr >> PAGE_SHIFT,
+ size, vma->vm_page_prot))
+ return -EAGAIN;
+
+ vma->vm_ops = &sq_vma_ops;
+
+ return 0;
+}
+
+#ifdef CONFIG_PROC_FS
+static int sq_mapping_read_proc(char *buf, char **start, off_t off,
+ int len, int *eof, void *data)
+{
+ struct list_head *pos;
+ char *p = buf;
+
+ list_for_each_prev(pos, &sq_mapping_list) {
+ struct sq_mapping *entry;
+
+ entry = list_entry(pos, typeof(*entry), list);
+
+ p += sprintf(p, "%08lx-%08lx [%08lx]: %s\n", entry->sq_addr,
+ entry->sq_addr + entry->size - 1, entry->addr,
+ entry->name);
+ }
+
+ return p - buf;
+}
+#endif
+
+static struct file_operations sq_fops = {
+ .owner = THIS_MODULE,
+ .mmap = sq_mmap,
+};
+
+static struct miscdevice sq_dev = {
+ .minor = STORE_QUEUE_MINOR,
+ .name = "sq",
+ .devfs_name = "cpu/sq",
+ .fops = &sq_fops,
+};
+
+static int __init sq_api_init(void)
+{
+ printk(KERN_NOTICE "sq: Registering store queue API.\n");
+
+#ifdef CONFIG_PROC_FS
+ create_proc_read_entry("sq_mapping", 0, 0, sq_mapping_read_proc, 0);
+#endif
+
+ return misc_register(&sq_dev);
+}
+
+static void __exit sq_api_exit(void)
+{
+ misc_deregister(&sq_dev);
+}
+
+module_init(sq_api_init);
+module_exit(sq_api_exit);
+
+MODULE_AUTHOR("Paul Mundt <lethal@linux-sh.org>, M. R. Brown <mrbrown@0xd6.org>");
+MODULE_DESCRIPTION("Simple API for SH-4 integrated Store Queues");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(STORE_QUEUE_MINOR);
+
+EXPORT_SYMBOL(sq_remap);
+EXPORT_SYMBOL(sq_unmap);
+EXPORT_SYMBOL(sq_clear);
+EXPORT_SYMBOL(sq_flush);
+EXPORT_SYMBOL(sq_flush_range);
+
diff --git a/arch/sh/kernel/cpu/ubc.S b/arch/sh/kernel/cpu/ubc.S
new file mode 100644
index 000000000000..0c569b20e1c1
--- /dev/null
+++ b/arch/sh/kernel/cpu/ubc.S
@@ -0,0 +1,59 @@
+/*
+ * arch/sh/kernel/ubc.S
+ *
+ * Set of management routines for the User Break Controller (UBC)
+ *
+ * Copyright (C) 2002 Paul Mundt
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+#include <linux/linkage.h>
+#include <asm/ubc.h>
+
+#define STBCR2 0xffc00010
+
+ENTRY(ubc_sleep)
+ mov #0, r0
+
+ mov.l 1f, r1 ! Zero out UBC_BBRA ..
+ mov.w r0, @r1
+
+ mov.l 2f, r1 ! .. same for BBRB ..
+ mov.w r0, @r1
+
+ mov.l 3f, r1 ! .. and again for BRCR.
+ mov.w r0, @r1
+
+ mov.w @r1, r0 ! Dummy read BRCR
+
+ mov.l 4f, r1 ! Set MSTP5 in STBCR2
+ mov.b @r1, r0
+ or #0x01, r0
+ mov.b r0, @r1
+
+ mov.b @r1, r0 ! Two dummy reads ..
+ mov.b @r1, r0
+
+ rts
+ nop
+
+ENTRY(ubc_wakeup)
+ mov.l 4f, r1 ! Clear MSTP5
+ mov.b @r1, r0
+ and #0xfe, r0
+ mov.b r0, @r1
+
+ mov.b @r1, r0 ! Two more dummy reads ..
+ mov.b @r1, r0
+
+ rts
+ nop
+
+1: .long UBC_BBRA
+2: .long UBC_BBRB
+3: .long UBC_BRCR
+4: .long STBCR2
+
diff --git a/arch/sh/kernel/cpufreq.c b/arch/sh/kernel/cpufreq.c
new file mode 100644
index 000000000000..e0b384bef55f
--- /dev/null
+++ b/arch/sh/kernel/cpufreq.c
@@ -0,0 +1,218 @@
+/*
+ * arch/sh/kernel/cpufreq.c
+ *
+ * cpufreq driver for the SuperH processors.
+ *
+ * Copyright (C) 2002, 2003, 2004, 2005 Paul Mundt
+ * Copyright (C) 2002 M. R. Brown
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+#include <linux/types.h>
+#include <linux/cpufreq.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/cpumask.h>
+#include <linux/smp.h>
+
+#include <asm/processor.h>
+#include <asm/watchdog.h>
+#include <asm/freq.h>
+#include <asm/io.h>
+
+/*
+ * For SuperH, each policy change requires that we change the IFC, BFC, and
+ * PFC at the same time. Here we define sane values that won't trash the
+ * system.
+ *
+ * Note the max set is computed at runtime, we use the divisors that we booted
+ * with to setup our maximum operating frequencies.
+ */
+struct clock_set {
+ unsigned int ifc;
+ unsigned int bfc;
+ unsigned int pfc;
+} clock_sets[] = {
+#if defined(CONFIG_CPU_SH3) || defined(CONFIG_CPU_SH2)
+ { 0, 0, 0 }, /* not implemented yet */
+#elif defined(CONFIG_CPU_SH4)
+ { 4, 8, 8 }, /* min - IFC: 1/4, BFC: 1/8, PFC: 1/8 */
+ { 1, 2, 2 }, /* max - IFC: 1, BFC: 1/2, PFC: 1/2 */
+#endif
+};
+
+#define MIN_CLOCK_SET 0
+#define MAX_CLOCK_SET (ARRAY_SIZE(clock_sets) - 1)
+
+/*
+ * For the time being, we only support two frequencies, which in turn are
+ * aimed at the POWERSAVE and PERFORMANCE policies, which in turn are derived
+ * directly from the respective min/max clock sets. Technically we could
+ * support a wider range of frequencies, but these vary far too much for each
+ * CPU subtype (and we'd have to construct a frequency table for each subtype).
+ *
+ * Maybe something to implement in the future..
+ */
+#define SH_FREQ_MAX 0
+#define SH_FREQ_MIN 1
+
+static struct cpufreq_frequency_table sh_freqs[] = {
+ { SH_FREQ_MAX, 0 },
+ { SH_FREQ_MIN, 0 },
+ { 0, CPUFREQ_TABLE_END },
+};
+
+static void sh_cpufreq_update_clocks(unsigned int set)
+{
+ current_cpu_data.cpu_clock = current_cpu_data.master_clock / clock_sets[set].ifc;
+ current_cpu_data.bus_clock = current_cpu_data.master_clock / clock_sets[set].bfc;
+ current_cpu_data.module_clock = current_cpu_data.master_clock / clock_sets[set].pfc;
+ current_cpu_data.loops_per_jiffy = loops_per_jiffy;
+}
+
+/* XXX: This needs to be split out per CPU and CPU subtype. */
+/*
+ * Here we notify other drivers of the proposed change and the final change.
+ */
+static int sh_cpufreq_setstate(unsigned int cpu, unsigned int set)
+{
+ unsigned short frqcr = ctrl_inw(FRQCR);
+ cpumask_t cpus_allowed;
+ struct cpufreq_freqs freqs;
+
+ if (!cpu_online(cpu))
+ return -ENODEV;
+
+ cpus_allowed = current->cpus_allowed;
+ set_cpus_allowed(current, cpumask_of_cpu(cpu));
+
+ BUG_ON(smp_processor_id() != cpu);
+
+ freqs.cpu = cpu;
+ freqs.old = current_cpu_data.cpu_clock / 1000;
+ freqs.new = (current_cpu_data.master_clock / clock_sets[set].ifc) / 1000;
+
+ cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+#if defined(CONFIG_CPU_SH3)
+ frqcr |= (newstate & 0x4000) << 14;
+ frqcr |= (newstate & 0x000c) << 2;
+#elif defined(CONFIG_CPU_SH4)
+ /*
+ * FRQCR.PLL2EN is 1, we need to allow the PLL to stabilize by
+ * initializing the WDT.
+ */
+ if (frqcr & (1 << 9)) {
+ __u8 csr;
+
+ /*
+ * Set the overflow period to the highest available,
+ * in this case a 1/4096 division ratio yields a 5.25ms
+ * overflow period. See asm-sh/watchdog.h for more
+ * information and a range of other divisors.
+ */
+ csr = sh_wdt_read_csr();
+ csr |= WTCSR_CKS_4096;
+ sh_wdt_write_csr(csr);
+
+ sh_wdt_write_cnt(0);
+ }
+ frqcr &= 0x0e00; /* Clear ifc, bfc, pfc */
+ frqcr |= get_ifc_value(clock_sets[set].ifc) << 6;
+ frqcr |= get_bfc_value(clock_sets[set].bfc) << 3;
+ frqcr |= get_pfc_value(clock_sets[set].pfc);
+#endif
+ ctrl_outw(frqcr, FRQCR);
+ sh_cpufreq_update_clocks(set);
+
+ set_cpus_allowed(current, cpus_allowed);
+ cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+
+ return 0;
+}
+
+static int sh_cpufreq_cpu_init(struct cpufreq_policy *policy)
+{
+ unsigned int min_freq, max_freq;
+ unsigned int ifc, bfc, pfc;
+
+ if (!cpu_online(policy->cpu))
+ return -ENODEV;
+
+ /* Update our maximum clock set */
+ get_current_frequency_divisors(&ifc, &bfc, &pfc);
+ clock_sets[MAX_CLOCK_SET].ifc = ifc;
+ clock_sets[MAX_CLOCK_SET].bfc = bfc;
+ clock_sets[MAX_CLOCK_SET].pfc = pfc;
+
+ /* Convert from Hz to kHz */
+ max_freq = current_cpu_data.cpu_clock / 1000;
+ min_freq = (current_cpu_data.master_clock / clock_sets[MIN_CLOCK_SET].ifc) / 1000;
+
+ sh_freqs[SH_FREQ_MAX].frequency = max_freq;
+ sh_freqs[SH_FREQ_MIN].frequency = min_freq;
+
+ /* cpuinfo and default policy values */
+ policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
+ policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
+ policy->cur = max_freq;
+
+ return cpufreq_frequency_table_cpuinfo(policy, &sh_freqs[0]);
+}
+
+static int sh_cpufreq_verify(struct cpufreq_policy *policy)
+{
+ return cpufreq_frequency_table_verify(policy, &sh_freqs[0]);
+}
+
+static int sh_cpufreq_target(struct cpufreq_policy *policy,
+ unsigned int target_freq,
+ unsigned int relation)
+{
+ unsigned int set, idx = 0;
+
+ if (cpufreq_frequency_table_target(policy, &sh_freqs[0], target_freq, relation, &idx))
+ return -EINVAL;
+
+ set = (idx == SH_FREQ_MIN) ? MIN_CLOCK_SET : MAX_CLOCK_SET;
+
+ sh_cpufreq_setstate(policy->cpu, set);
+
+ return 0;
+}
+
+static struct cpufreq_driver sh_cpufreq_driver = {
+ .owner = THIS_MODULE,
+ .name = "SH cpufreq",
+ .init = sh_cpufreq_cpu_init,
+ .verify = sh_cpufreq_verify,
+ .target = sh_cpufreq_target,
+};
+
+static int __init sh_cpufreq_init(void)
+{
+ if (!current_cpu_data.cpu_clock)
+ return -EINVAL;
+ if (cpufreq_register_driver(&sh_cpufreq_driver))
+ return -EINVAL;
+
+ return 0;
+}
+
+static void __exit sh_cpufreq_exit(void)
+{
+ cpufreq_unregister_driver(&sh_cpufreq_driver);
+}
+
+module_init(sh_cpufreq_init);
+module_exit(sh_cpufreq_exit);
+
+MODULE_AUTHOR("Paul Mundt <lethal@linux-sh.org>");
+MODULE_DESCRIPTION("cpufreq driver for SuperH");
+MODULE_LICENSE("GPL");
+
diff --git a/arch/sh/kernel/early_printk.c b/arch/sh/kernel/early_printk.c
new file mode 100644
index 000000000000..1378db375e17
--- /dev/null
+++ b/arch/sh/kernel/early_printk.c
@@ -0,0 +1,137 @@
+/*
+ * arch/sh/kernel/early_printk.c
+ *
+ * Copyright (C) 1999, 2000 Niibe Yutaka
+ * Copyright (C) 2002 M. R. Brown
+ * Copyright (C) 2004 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/console.h>
+#include <linux/tty.h>
+#include <linux/init.h>
+#include <asm/io.h>
+
+#ifdef CONFIG_SH_STANDARD_BIOS
+#include <asm/sh_bios.h>
+
+/*
+ * Print a string through the BIOS
+ */
+static void sh_console_write(struct console *co, const char *s,
+ unsigned count)
+{
+ sh_bios_console_write(s, count);
+}
+
+/*
+ * Setup initial baud/bits/parity. We do two things here:
+ * - construct a cflag setting for the first rs_open()
+ * - initialize the serial port
+ * Return non-zero if we didn't find a serial port.
+ */
+static int __init sh_console_setup(struct console *co, char *options)
+{
+ int cflag = CREAD | HUPCL | CLOCAL;
+
+ /*
+ * Now construct a cflag setting.
+ * TODO: this is a totally bogus cflag, as we have
+ * no idea what serial settings the BIOS is using, or
+ * even if its using the serial port at all.
+ */
+ cflag |= B115200 | CS8 | /*no parity*/0;
+
+ co->cflag = cflag;
+
+ return 0;
+}
+
+static struct console early_console = {
+ .name = "bios",
+ .write = sh_console_write,
+ .setup = sh_console_setup,
+ .flags = CON_PRINTBUFFER,
+ .index = -1,
+};
+#endif
+
+#ifdef CONFIG_EARLY_SCIF_CONSOLE
+#define SCIF_REG 0xffe80000
+
+static void scif_sercon_putc(int c)
+{
+ while (!(ctrl_inw(SCIF_REG + 0x10) & 0x20)) ;
+
+ ctrl_outb(c, SCIF_REG + 12);
+ ctrl_outw((ctrl_inw(SCIF_REG + 0x10) & 0x9f), SCIF_REG + 0x10);
+
+ if (c == '\n')
+ scif_sercon_putc('\r');
+}
+
+static void scif_sercon_flush(void)
+{
+ ctrl_outw((ctrl_inw(SCIF_REG + 0x10) & 0xbf), SCIF_REG + 0x10);
+
+ while (!(ctrl_inw(SCIF_REG + 0x10) & 0x40)) ;
+
+ ctrl_outw((ctrl_inw(SCIF_REG + 0x10) & 0xbf), SCIF_REG + 0x10);
+}
+
+static void scif_sercon_write(struct console *con, const char *s, unsigned count)
+{
+ while (count-- > 0)
+ scif_sercon_putc(*s++);
+
+ scif_sercon_flush();
+}
+
+static int __init scif_sercon_setup(struct console *con, char *options)
+{
+ con->cflag = CREAD | HUPCL | CLOCAL | B115200 | CS8;
+
+ return 0;
+}
+
+static struct console early_console = {
+ .name = "sercon",
+ .write = scif_sercon_write,
+ .setup = scif_sercon_setup,
+ .flags = CON_PRINTBUFFER,
+ .index = -1,
+};
+
+void scif_sercon_init(int baud)
+{
+ ctrl_outw(0, SCIF_REG + 8);
+ ctrl_outw(0, SCIF_REG);
+
+ /* Set baud rate */
+ ctrl_outb((CONFIG_SH_PCLK_FREQ + 16 * baud) /
+ (32 * baud) - 1, SCIF_REG + 4);
+
+ ctrl_outw(12, SCIF_REG + 24);
+ ctrl_outw(8, SCIF_REG + 24);
+ ctrl_outw(0, SCIF_REG + 32);
+ ctrl_outw(0x60, SCIF_REG + 16);
+ ctrl_outw(0, SCIF_REG + 36);
+ ctrl_outw(0x30, SCIF_REG + 8);
+}
+#endif
+
+void __init enable_early_printk(void)
+{
+#ifdef CONFIG_EARLY_SCIF_CONSOLE
+ scif_sercon_init(115200);
+#endif
+ register_console(&early_console);
+}
+
+void disable_early_printk(void)
+{
+ unregister_console(&early_console);
+}
+
diff --git a/arch/sh/kernel/entry.S b/arch/sh/kernel/entry.S
new file mode 100644
index 000000000000..6615e4838ee4
--- /dev/null
+++ b/arch/sh/kernel/entry.S
@@ -0,0 +1,1149 @@
+/* $Id: entry.S,v 1.37 2004/06/11 13:02:46 doyu Exp $
+ *
+ * linux/arch/sh/entry.S
+ *
+ * Copyright (C) 1999, 2000, 2002 Niibe Yutaka
+ * 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/sys.h>
+#include <linux/linkage.h>
+#include <linux/config.h>
+#include <asm/asm-offsets.h>
+#include <asm/thread_info.h>
+#include <asm/unistd.h>
+
+#if !defined(CONFIG_NFSD) && !defined(CONFIG_NFSD_MODULE)
+#define sys_nfsservctl sys_ni_syscall
+#endif
+
+#if !defined(CONFIG_MMU)
+#define sys_madvise sys_ni_syscall
+#define sys_readahead sys_ni_syscall
+#define sys_mprotect sys_ni_syscall
+#define sys_msync sys_ni_syscall
+#define sys_mlock sys_ni_syscall
+#define sys_munlock sys_ni_syscall
+#define sys_mlockall sys_ni_syscall
+#define sys_munlockall sys_ni_syscall
+#define sys_mremap sys_ni_syscall
+#define sys_mincore sys_ni_syscall
+#define sys_remap_file_pages sys_ni_syscall
+#endif
+
+! NOTE:
+! GNU as (as of 2.9.1) changes bf/s into bt/s and bra, when the address
+! to be jumped is too far, but it causes illegal slot exception.
+
+/*
+ * entry.S contains the system-call and fault low-level handling routines.
+ * This also contains the timer-interrupt handler, as well as all interrupts
+ * and faults that can result in a task-switch.
+ *
+ * NOTE: This code handles signal-recognition, which happens every time
+ * after a timer-interrupt and after each system call.
+ *
+ * NOTE: This code uses a convention that instructions in the delay slot
+ * of a transfer-control instruction are indented by an extra space, thus:
+ *
+ * jmp @k0 ! control-transfer instruction
+ * ldc k1, ssr ! delay slot
+ *
+ * Stack layout in 'ret_from_syscall':
+ * ptrace needs to have all regs on the stack.
+ * if the order here is changed, it needs to be
+ * updated in ptrace.c and ptrace.h
+ *
+ * r0
+ * ...
+ * r15 = stack pointer
+ * spc
+ * pr
+ * ssr
+ * gbr
+ * mach
+ * macl
+ * syscall #
+ *
+ */
+
+ENOSYS = 38
+EINVAL = 22
+
+#if defined(CONFIG_CPU_SH3)
+TRA = 0xffffffd0
+EXPEVT = 0xffffffd4
+#if defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7709) || \
+ defined(CONFIG_CPU_SUBTYPE_SH7300) || defined(CONFIG_CPU_SUBTYPE_SH7705)
+INTEVT = 0xa4000000 ! INTEVTE2(0xa4000000)
+#else
+INTEVT = 0xffffffd8
+#endif
+MMU_TEA = 0xfffffffc ! TLB Exception Address Register
+#elif defined(CONFIG_CPU_SH4)
+TRA = 0xff000020
+EXPEVT = 0xff000024
+INTEVT = 0xff000028
+MMU_TEA = 0xff00000c ! TLB Exception Address Register
+#endif
+
+#if defined(CONFIG_KGDB_NMI)
+NMI_VEC = 0x1c0 ! Must catch early for debounce
+#endif
+
+/* Offsets to the stack */
+OFF_R0 = 0 /* Return value. New ABI also arg4 */
+OFF_R1 = 4 /* New ABI: arg5 */
+OFF_R2 = 8 /* New ABI: arg6 */
+OFF_R3 = 12 /* New ABI: syscall_nr */
+OFF_R4 = 16 /* New ABI: arg0 */
+OFF_R5 = 20 /* New ABI: arg1 */
+OFF_R6 = 24 /* New ABI: arg2 */
+OFF_R7 = 28 /* New ABI: arg3 */
+OFF_SP = (15*4)
+OFF_PC = (16*4)
+OFF_SR = (16*4+8)
+OFF_TRA = (16*4+6*4)
+
+
+#define k0 r0
+#define k1 r1
+#define k2 r2
+#define k3 r3
+#define k4 r4
+
+#define k_ex_code r2_bank /* r2_bank1 */
+#define g_imask r6 /* r6_bank1 */
+#define k_g_imask r6_bank /* r6_bank1 */
+#define current r7 /* r7_bank1 */
+
+/*
+ * Kernel mode register usage:
+ * k0 scratch
+ * k1 scratch
+ * k2 scratch (Exception code)
+ * k3 scratch (Return address)
+ * k4 scratch
+ * k5 reserved
+ * k6 Global Interrupt Mask (0--15 << 4)
+ * k7 CURRENT_THREAD_INFO (pointer to current thread info)
+ */
+
+!
+! TLB Miss / Initial Page write exception handling
+! _and_
+! TLB hits, but the access violate the protection.
+! It can be valid access, such as stack grow and/or C-O-W.
+!
+!
+! Find the pmd/pte entry and loadtlb
+! If it's not found, cause address error (SEGV)
+!
+! Although this could be written in assembly language (and it'd be faster),
+! this first version depends *much* on C implementation.
+!
+
+#define CLI() \
+ stc sr, r0; \
+ or #0xf0, r0; \
+ ldc r0, sr
+
+#define STI() \
+ mov.l __INV_IMASK, r11; \
+ stc sr, r10; \
+ and r11, r10; \
+ stc k_g_imask, r11; \
+ or r11, r10; \
+ ldc r10, sr
+
+#if defined(CONFIG_PREEMPT)
+# define preempt_stop() CLI()
+#else
+# define preempt_stop()
+# define resume_kernel restore_all
+#endif
+
+#if defined(CONFIG_MMU)
+ .align 2
+ENTRY(tlb_miss_load)
+ bra call_dpf
+ mov #0, r5
+
+ .align 2
+ENTRY(tlb_miss_store)
+ bra call_dpf
+ mov #1, r5
+
+ .align 2
+ENTRY(initial_page_write)
+ bra call_dpf
+ mov #1, r5
+
+ .align 2
+ENTRY(tlb_protection_violation_load)
+ bra call_dpf
+ mov #0, r5
+
+ .align 2
+ENTRY(tlb_protection_violation_store)
+ bra call_dpf
+ mov #1, r5
+
+call_dpf:
+ mov.l 1f, r0
+ mov r5, r8
+ mov.l @r0, r6
+ mov r6, r9
+ mov.l 2f, r0
+ sts pr, r10
+ jsr @r0
+ mov r15, r4
+ !
+ tst r0, r0
+ bf/s 0f
+ lds r10, pr
+ rts
+ nop
+0: STI()
+ mov.l 3f, r0
+ mov r9, r6
+ mov r8, r5
+ jmp @r0
+ mov r15, r4
+
+ .align 2
+1: .long MMU_TEA
+2: .long __do_page_fault
+3: .long do_page_fault
+
+ .align 2
+ENTRY(address_error_load)
+ bra call_dae
+ mov #0,r5 ! writeaccess = 0
+
+ .align 2
+ENTRY(address_error_store)
+ bra call_dae
+ mov #1,r5 ! writeaccess = 1
+
+ .align 2
+call_dae:
+ mov.l 1f, r0
+ mov.l @r0, r6 ! address
+ mov.l 2f, r0
+ jmp @r0
+ mov r15, r4 ! regs
+
+ .align 2
+1: .long MMU_TEA
+2: .long do_address_error
+#endif /* CONFIG_MMU */
+
+#if defined(CONFIG_SH_STANDARD_BIOS) || defined(CONFIG_SH_KGDB)
+! Handle kernel debug if either kgdb (SW) or gdb-stub (FW) is present.
+! If both are configured, handle the debug traps (breakpoints) in SW,
+! but still allow BIOS traps to FW.
+
+ .align 2
+debug_kernel:
+#if defined(CONFIG_SH_STANDARD_BIOS) && defined(CONFIG_SH_KGDB)
+ /* Force BIOS call to FW (debug_trap put TRA in r8) */
+ mov r8,r0
+ shlr2 r0
+ cmp/eq #0x3f,r0
+ bt debug_kernel_fw
+#endif /* CONFIG_SH_STANDARD_BIOS && CONFIG_SH_KGDB */
+
+debug_enter:
+#if defined(CONFIG_SH_KGDB)
+ /* Jump to kgdb, pass stacked regs as arg */
+debug_kernel_sw:
+ mov.l 3f, r0
+ jmp @r0
+ mov r15, r4
+ .align 2
+3: .long kgdb_handle_exception
+#endif /* CONFIG_SH_KGDB */
+
+#if defined(CONFIG_SH_STANDARD_BIOS)
+ /* Unwind the stack and jmp to the debug entry */
+debug_kernel_fw:
+ mov.l @r15+, r0
+ mov.l @r15+, r1
+ mov.l @r15+, r2
+ mov.l @r15+, r3
+ mov.l @r15+, r4
+ mov.l @r15+, r5
+ mov.l @r15+, r6
+ mov.l @r15+, r7
+ stc sr, r8
+ mov.l 1f, r9 ! BL =1, RB=1, IMASK=0x0F
+ or r9, r8
+ ldc r8, sr ! here, change the register bank
+ mov.l @r15+, r8
+ mov.l @r15+, r9
+ mov.l @r15+, r10
+ mov.l @r15+, r11
+ mov.l @r15+, r12
+ mov.l @r15+, r13
+ mov.l @r15+, r14
+ mov.l @r15+, k0
+ ldc.l @r15+, spc
+ lds.l @r15+, pr
+ mov.l @r15+, k1
+ ldc.l @r15+, gbr
+ lds.l @r15+, mach
+ lds.l @r15+, macl
+ mov k0, r15
+ !
+ mov.l 2f, k0
+ mov.l @k0, k0
+ jmp @k0
+ ldc k1, ssr
+ .align 2
+1: .long 0x300000f0
+2: .long gdb_vbr_vector
+#endif /* CONFIG_SH_STANDARD_BIOS */
+
+#endif /* CONFIG_SH_STANDARD_BIOS || CONFIG_SH_KGDB */
+
+
+ .align 2
+debug_trap:
+#if defined(CONFIG_SH_STANDARD_BIOS) || defined(CONFIG_SH_KGDB)
+ mov #OFF_SR, r0
+ mov.l @(r0,r15), r0 ! get status register
+ shll r0
+ shll r0 ! kernel space?
+ bt/s debug_kernel
+#endif
+ mov.l @r15, r0 ! Restore R0 value
+ mov.l 1f, r8
+ jmp @r8
+ nop
+
+ .align 2
+ENTRY(exception_error)
+ !
+ STI()
+ mov.l 2f, r0
+ jmp @r0
+ nop
+
+!
+ .align 2
+1: .long break_point_trap_software
+2: .long do_exception_error
+
+ .align 2
+ret_from_exception:
+ preempt_stop()
+ret_from_irq:
+ !
+ mov #OFF_SR, r0
+ mov.l @(r0,r15), r0 ! get status register
+ shll r0
+ shll r0 ! kernel space?
+ bt/s resume_kernel ! Yes, it's from kernel, go back soon
+ GET_THREAD_INFO(r8)
+
+#ifdef CONFIG_PREEMPT
+ bra resume_userspace
+ nop
+ENTRY(resume_kernel)
+ mov.l @(TI_PRE_COUNT,r8), r0 ! current_thread_info->preempt_count
+ tst r0, r0
+ bf noresched
+need_resched:
+ mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags
+ tst #_TIF_NEED_RESCHED, r0 ! need_resched set?
+ bt noresched
+
+ mov #OFF_SR, r0
+ mov.l @(r0,r15), r0 ! get status register
+ and #0xf0, r0 ! interrupts off (exception path)?
+ cmp/eq #0xf0, r0
+ bt noresched
+
+ mov.l 1f, r0
+ mov.l r0, @(TI_PRE_COUNT,r8)
+
+ STI()
+ mov.l 2f, r0
+ jsr @r0
+ nop
+ mov #0, r0
+ mov.l r0, @(TI_PRE_COUNT,r8)
+ CLI()
+
+ bra need_resched
+ nop
+noresched:
+ bra restore_all
+ nop
+
+ .align 2
+1: .long PREEMPT_ACTIVE
+2: .long schedule
+#endif
+
+ENTRY(resume_userspace)
+ ! r8: current_thread_info
+ CLI()
+ mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags
+ tst #_TIF_WORK_MASK, r0
+ bt/s restore_all
+ tst #_TIF_NEED_RESCHED, r0
+
+ .align 2
+work_pending:
+ ! r0: current_thread_info->flags
+ ! r8: current_thread_info
+ ! t: result of "tst #_TIF_NEED_RESCHED, r0"
+ bf/s work_resched
+ tst #_TIF_SIGPENDING, r0
+work_notifysig:
+ bt/s restore_all
+ mov r15, r4
+ mov #0, r5
+ mov.l 2f, r1
+ mova restore_all, r0
+ jmp @r1
+ lds r0, pr
+work_resched:
+#ifndef CONFIG_PREEMPT
+ ! gUSA handling
+ mov.l @(OFF_SP,r15), r0 ! get user space stack pointer
+ mov r0, r1
+ shll r0
+ bf/s 1f
+ shll r0
+ bf/s 1f
+ mov #OFF_PC, r0
+ ! SP >= 0xc0000000 : gUSA mark
+ mov.l @(r0,r15), r2 ! get user space PC (program counter)
+ mov.l @(OFF_R0,r15), r3 ! end point
+ cmp/hs r3, r2 ! r2 >= r3?
+ bt 1f
+ add r3, r1 ! rewind point #2
+ mov.l r1, @(r0,r15) ! reset PC to rewind point #2
+ !
+1:
+#endif
+ mov.l 1f, r1
+ jsr @r1 ! schedule
+ nop
+ CLI()
+ !
+ mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags
+ tst #_TIF_WORK_MASK, r0
+ bt restore_all
+ bra work_pending
+ tst #_TIF_NEED_RESCHED, r0
+
+ .align 2
+1: .long schedule
+2: .long do_signal
+
+ .align 2
+syscall_exit_work:
+ ! r0: current_thread_info->flags
+ ! r8: current_thread_info
+ tst #_TIF_SYSCALL_TRACE, r0
+ bt/s work_pending
+ tst #_TIF_NEED_RESCHED, r0
+ STI()
+ ! XXX setup arguments...
+ mov.l 4f, r0 ! do_syscall_trace
+ jsr @r0
+ nop
+ bra resume_userspace
+ nop
+
+ .align 2
+syscall_trace_entry:
+ ! Yes it is traced.
+ ! XXX setup arguments...
+ mov.l 4f, r11 ! Call do_syscall_trace which notifies
+ jsr @r11 ! superior (will chomp R[0-7])
+ nop
+ ! Reload R0-R4 from kernel stack, where the
+ ! parent may have modified them using
+ ! ptrace(POKEUSR). (Note that R0-R2 are
+ ! used by the system call handler directly
+ ! from the kernel stack anyway, so don't need
+ ! to be reloaded here.) This allows the parent
+ ! to rewrite system calls and args on the fly.
+ mov.l @(OFF_R4,r15), r4 ! arg0
+ mov.l @(OFF_R5,r15), r5
+ mov.l @(OFF_R6,r15), r6
+ mov.l @(OFF_R7,r15), r7 ! arg3
+ mov.l @(OFF_R3,r15), r3 ! syscall_nr
+ ! Arrange for do_syscall_trace to be called
+ ! again as the system call returns.
+ mov.l 2f, r10 ! Number of syscalls
+ cmp/hs r10, r3
+ bf syscall_call
+ mov #-ENOSYS, r0
+ bra syscall_exit
+ mov.l r0, @(OFF_R0,r15) ! Return value
+
+/*
+ * Syscall interface:
+ *
+ * Syscall #: R3
+ * Arguments #0 to #3: R4--R7
+ * Arguments #4 to #6: R0, R1, R2
+ * TRA: (number of arguments + 0x10) x 4
+ *
+ * This code also handles delegating other traps to the BIOS/gdb stub
+ * according to:
+ *
+ * Trap number
+ * (TRA>>2) Purpose
+ * -------- -------
+ * 0x0-0xf old syscall ABI
+ * 0x10-0x1f new syscall ABI
+ * 0x20-0xff delegated through debug_trap to BIOS/gdb stub.
+ *
+ * Note: When we're first called, the TRA value must be shifted
+ * right 2 bits in order to get the value that was used as the "trapa"
+ * argument.
+ */
+
+ .align 2
+ .globl ret_from_fork
+ret_from_fork:
+ mov.l 1f, r8
+ jsr @r8
+ mov r0, r4
+ bra syscall_exit
+ nop
+ .align 2
+1: .long schedule_tail
+ !
+ENTRY(system_call)
+ mov.l 1f, r9
+ mov.l @r9, r8 ! Read from TRA (Trap Address) Register
+ !
+ ! Is the trap argument >= 0x20? (TRA will be >= 0x80)
+ mov #0x7f, r9
+ cmp/hi r9, r8
+ bt/s 0f
+ mov #OFF_TRA, r9
+ add r15, r9
+ !
+ mov.l r8, @r9 ! set TRA value to tra
+ STI()
+ ! Call the system call handler through the table.
+ ! First check for bad syscall number
+ mov r3, r9
+ mov.l 2f, r8 ! Number of syscalls
+ cmp/hs r8, r9
+ bf/s good_system_call
+ GET_THREAD_INFO(r8)
+syscall_badsys: ! Bad syscall number
+ mov #-ENOSYS, r0
+ bra resume_userspace
+ mov.l r0, @(OFF_R0,r15) ! Return value
+ !
+0:
+ bra debug_trap
+ nop
+ !
+good_system_call: ! Good syscall number
+ mov.l @(TI_FLAGS,r8), r8
+ mov #_TIF_SYSCALL_TRACE, r10
+ tst r10, r8
+ bf syscall_trace_entry
+ !
+syscall_call:
+ shll2 r9 ! x4
+ mov.l 3f, r8 ! Load the address of sys_call_table
+ add r8, r9
+ mov.l @r9, r8
+ jsr @r8 ! jump to specific syscall handler
+ nop
+ mov.l r0, @(OFF_R0,r15) ! save the return value
+ !
+syscall_exit:
+ CLI()
+ !
+ GET_THREAD_INFO(r8)
+ mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags
+ tst #_TIF_ALLWORK_MASK, r0
+ bf syscall_exit_work
+restore_all:
+ mov.l @r15+, r0
+ mov.l @r15+, r1
+ mov.l @r15+, r2
+ mov.l @r15+, r3
+ mov.l @r15+, r4
+ mov.l @r15+, r5
+ mov.l @r15+, r6
+ mov.l @r15+, r7
+ !
+ stc sr, r8
+ mov.l 7f, r9
+ or r9, r8 ! BL =1, RB=1
+ ldc r8, sr ! here, change the register bank
+ !
+ mov.l @r15+, r8
+ mov.l @r15+, r9
+ mov.l @r15+, r10
+ mov.l @r15+, r11
+ mov.l @r15+, r12
+ mov.l @r15+, r13
+ mov.l @r15+, r14
+ mov.l @r15+, k4 ! original stack pointer
+ ldc.l @r15+, spc
+ lds.l @r15+, pr
+ mov.l @r15+, k3 ! original SR
+ ldc.l @r15+, gbr
+ lds.l @r15+, mach
+ lds.l @r15+, macl
+ add #4, r15 ! Skip syscall number
+ !
+#ifdef CONFIG_SH_DSP
+ mov.l @r15+, k0 ! DSP mode marker
+ mov.l 5f, k1
+ cmp/eq k0, k1 ! Do we have a DSP stack frame?
+ bf skip_restore
+
+ stc sr, k0 ! Enable CPU DSP mode
+ or k1, k0 ! (within kernel it may be disabled)
+ ldc k0, sr
+ mov r2, k0 ! Backup r2
+
+ ! Restore DSP registers from stack
+ mov r15, r2
+ movs.l @r2+, a1
+ movs.l @r2+, a0g
+ movs.l @r2+, a1g
+ movs.l @r2+, m0
+ movs.l @r2+, m1
+ mov r2, r15
+
+ lds.l @r15+, a0
+ lds.l @r15+, x0
+ lds.l @r15+, x1
+ lds.l @r15+, y0
+ lds.l @r15+, y1
+ lds.l @r15+, dsr
+ ldc.l @r15+, rs
+ ldc.l @r15+, re
+ ldc.l @r15+, mod
+
+ mov k0, r2 ! Restore r2
+skip_restore:
+#endif
+ !
+ ! Calculate new SR value
+ mov k3, k2 ! original SR value
+ mov.l 9f, k1
+ and k1, k2 ! Mask orignal SR value
+ !
+ mov k3, k0 ! Calculate IMASK-bits
+ shlr2 k0
+ and #0x3c, k0
+ cmp/eq #0x3c, k0
+ bt/s 6f
+ shll2 k0
+ mov g_imask, k0
+ !
+6: or k0, k2 ! Set the IMASK-bits
+ ldc k2, ssr
+ !
+#if defined(CONFIG_KGDB_NMI)
+ ! Clear in_nmi
+ mov.l 4f, k0
+ mov #0, k1
+ mov.b k1, @k0
+#endif
+ mov.l @r15+, k2 ! restore EXPEVT
+ mov k4, r15
+ rte
+ nop
+
+ .align 2
+1: .long TRA
+2: .long NR_syscalls
+3: .long sys_call_table
+4: .long do_syscall_trace
+5: .long 0x00001000 ! DSP
+7: .long 0x30000000
+9:
+__INV_IMASK:
+ .long 0xffffff0f ! ~(IMASK)
+
+! Exception Vector Base
+!
+! Should be aligned page boundary.
+!
+ .balign 4096,0,4096
+ENTRY(vbr_base)
+ .long 0
+!
+ .balign 256,0,256
+general_exception:
+ mov.l 1f, k2
+ mov.l 2f, k3
+ bra handle_exception
+ mov.l @k2, k2
+ .align 2
+1: .long EXPEVT
+2: .long ret_from_exception
+!
+!
+ .balign 1024,0,1024
+tlb_miss:
+ mov.l 1f, k2
+ mov.l 4f, k3
+ bra handle_exception
+ mov.l @k2, k2
+!
+ .balign 512,0,512
+interrupt:
+ mov.l 2f, k2
+ mov.l 3f, k3
+#if defined(CONFIG_KGDB_NMI)
+ ! Debounce (filter nested NMI)
+ mov.l @k2, k0
+ mov.l 5f, k1
+ cmp/eq k1, k0
+ bf 0f
+ mov.l 6f, k1
+ tas.b @k1
+ bt 0f
+ rte
+ nop
+ .align 2
+5: .long NMI_VEC
+6: .long in_nmi
+0:
+#endif /* defined(CONFIG_KGDB_NMI) */
+ bra handle_exception
+ mov.l @k2, k2
+
+ .align 2
+1: .long EXPEVT
+2: .long INTEVT
+3: .long ret_from_irq
+4: .long ret_from_exception
+
+!
+!
+ .align 2
+handle_exception:
+ ! Using k0, k1 for scratch registers (r0_bank1, r1_bank),
+ ! save all registers onto stack.
+ !
+ stc ssr, k0 ! Is it from kernel space?
+ shll k0 ! Check MD bit (bit30) by shifting it into...
+ shll k0 ! ...the T bit
+ bt/s 1f ! It's a kernel to kernel transition.
+ mov r15, k0 ! save original stack to k0
+ /* User space to kernel */
+ mov #0x20, k1
+ shll8 k1 ! k1 := 8192 (== THREAD_SIZE)
+ add current, k1
+ mov k1, r15 ! change to kernel stack
+ !
+1: mov #-1, k4
+ mov.l 2f, k1
+ !
+#ifdef CONFIG_SH_DSP
+ mov.l r2, @-r15 ! Save r2, we need another reg
+ stc sr, k4
+ mov.l 1f, r2
+ tst r2, k4 ! Check if in DSP mode
+ mov.l @r15+, r2 ! Restore r2 now
+ bt/s skip_save
+ mov #0, k4 ! Set marker for no stack frame
+
+ mov r2, k4 ! Backup r2 (in k4) for later
+
+ ! Save DSP registers on stack
+ stc.l mod, @-r15
+ stc.l re, @-r15
+ stc.l rs, @-r15
+ sts.l dsr, @-r15
+ sts.l y1, @-r15
+ sts.l y0, @-r15
+ sts.l x1, @-r15
+ sts.l x0, @-r15
+ sts.l a0, @-r15
+
+ ! GAS is broken, does not generate correct "movs.l Ds,@-As" instr.
+
+ ! FIXME: Make sure that this is still the case with newer toolchains,
+ ! as we're not at all interested in supporting ancient toolchains at
+ ! this point. -- PFM.
+
+ mov r15, r2
+ .word 0xf653 ! movs.l a1, @-r2
+ .word 0xf6f3 ! movs.l a0g, @-r2
+ .word 0xf6d3 ! movs.l a1g, @-r2
+ .word 0xf6c3 ! movs.l m0, @-r2
+ .word 0xf6e3 ! movs.l m1, @-r2
+ mov r2, r15
+
+ mov k4, r2 ! Restore r2
+ mov.l 1f, k4 ! Force DSP stack frame
+skip_save:
+ mov.l k4, @-r15 ! Push DSP mode marker onto stack
+#endif
+ ! Save the user registers on the stack.
+ mov.l k2, @-r15 ! EXPEVT
+ mov.l k4, @-r15 ! set TRA (default: -1)
+ !
+ sts.l macl, @-r15
+ sts.l mach, @-r15
+ stc.l gbr, @-r15
+ stc.l ssr, @-r15
+ sts.l pr, @-r15
+ stc.l spc, @-r15
+ !
+ lds k3, pr ! Set the return address to pr
+ !
+ mov.l k0, @-r15 ! save orignal stack
+ mov.l r14, @-r15
+ mov.l r13, @-r15
+ mov.l r12, @-r15
+ mov.l r11, @-r15
+ mov.l r10, @-r15
+ mov.l r9, @-r15
+ mov.l r8, @-r15
+ !
+ stc sr, r8 ! Back to normal register bank, and
+ or k1, r8 ! Block all interrupts
+ mov.l 3f, k1
+ and k1, r8 ! ...
+ ldc r8, sr ! ...changed here.
+ !
+ mov.l r7, @-r15
+ mov.l r6, @-r15
+ mov.l r5, @-r15
+ mov.l r4, @-r15
+ mov.l r3, @-r15
+ mov.l r2, @-r15
+ mov.l r1, @-r15
+ mov.l r0, @-r15
+ ! Then, dispatch to the handler, according to the exception code.
+ stc k_ex_code, r8
+ shlr2 r8
+ shlr r8
+ mov.l 4f, r9
+ add r8, r9
+ mov.l @r9, r9
+ jmp @r9
+ nop
+
+ .align 2
+1: .long 0x00001000 ! DSP=1
+2: .long 0x000080f0 ! FD=1, IMASK=15
+3: .long 0xcfffffff ! RB=0, BL=0
+4: .long exception_handling_table
+
+ .align 2
+ENTRY(exception_none)
+ rts
+ nop
+
+ .data
+ENTRY(sys_call_table)
+ .long sys_ni_syscall /* 0 - old "setup()" system call*/
+ .long sys_exit
+ .long sys_fork
+ .long sys_read
+ .long sys_write
+ .long sys_open /* 5 */
+ .long sys_close
+ .long sys_waitpid
+ .long sys_creat
+ .long sys_link
+ .long sys_unlink /* 10 */
+ .long sys_execve
+ .long sys_chdir
+ .long sys_time
+ .long sys_mknod
+ .long sys_chmod /* 15 */
+ .long sys_lchown16
+ .long sys_ni_syscall /* old break syscall holder */
+ .long sys_stat
+ .long sys_lseek
+ .long sys_getpid /* 20 */
+ .long sys_mount
+ .long sys_oldumount
+ .long sys_setuid16
+ .long sys_getuid16
+ .long sys_stime /* 25 */
+ .long sys_ptrace
+ .long sys_alarm
+ .long sys_fstat
+ .long sys_pause
+ .long sys_utime /* 30 */
+ .long sys_ni_syscall /* old stty syscall holder */
+ .long sys_ni_syscall /* old gtty syscall holder */
+ .long sys_access
+ .long sys_nice
+ .long sys_ni_syscall /* 35 */ /* old ftime syscall holder */
+ .long sys_sync
+ .long sys_kill
+ .long sys_rename
+ .long sys_mkdir
+ .long sys_rmdir /* 40 */
+ .long sys_dup
+ .long sys_pipe
+ .long sys_times
+ .long sys_ni_syscall /* old prof syscall holder */
+ .long sys_brk /* 45 */
+ .long sys_setgid16
+ .long sys_getgid16
+ .long sys_signal
+ .long sys_geteuid16
+ .long sys_getegid16 /* 50 */
+ .long sys_acct
+ .long sys_umount /* recycled never used phys() */
+ .long sys_ni_syscall /* old lock syscall holder */
+ .long sys_ioctl
+ .long sys_fcntl /* 55 */
+ .long sys_ni_syscall /* old mpx syscall holder */
+ .long sys_setpgid
+ .long sys_ni_syscall /* old ulimit syscall holder */
+ .long sys_ni_syscall /* sys_olduname */
+ .long sys_umask /* 60 */
+ .long sys_chroot
+ .long sys_ustat
+ .long sys_dup2
+ .long sys_getppid
+ .long sys_getpgrp /* 65 */
+ .long sys_setsid
+ .long sys_sigaction
+ .long sys_sgetmask
+ .long sys_ssetmask
+ .long sys_setreuid16 /* 70 */
+ .long sys_setregid16
+ .long sys_sigsuspend
+ .long sys_sigpending
+ .long sys_sethostname
+ .long sys_setrlimit /* 75 */
+ .long sys_old_getrlimit
+ .long sys_getrusage
+ .long sys_gettimeofday
+ .long sys_settimeofday
+ .long sys_getgroups16 /* 80 */
+ .long sys_setgroups16
+ .long sys_ni_syscall /* sys_oldselect */
+ .long sys_symlink
+ .long sys_lstat
+ .long sys_readlink /* 85 */
+ .long sys_uselib
+ .long sys_swapon
+ .long sys_reboot
+ .long old_readdir
+ .long old_mmap /* 90 */
+ .long sys_munmap
+ .long sys_truncate
+ .long sys_ftruncate
+ .long sys_fchmod
+ .long sys_fchown16 /* 95 */
+ .long sys_getpriority
+ .long sys_setpriority
+ .long sys_ni_syscall /* old profil syscall holder */
+ .long sys_statfs
+ .long sys_fstatfs /* 100 */
+ .long sys_ni_syscall /* ioperm */
+ .long sys_socketcall
+ .long sys_syslog
+ .long sys_setitimer
+ .long sys_getitimer /* 105 */
+ .long sys_newstat
+ .long sys_newlstat
+ .long sys_newfstat
+ .long sys_uname
+ .long sys_ni_syscall /* 110 */ /* iopl */
+ .long sys_vhangup
+ .long sys_ni_syscall /* idle */
+ .long sys_ni_syscall /* vm86old */
+ .long sys_wait4
+ .long sys_swapoff /* 115 */
+ .long sys_sysinfo
+ .long sys_ipc
+ .long sys_fsync
+ .long sys_sigreturn
+ .long sys_clone /* 120 */
+ .long sys_setdomainname
+ .long sys_newuname
+ .long sys_ni_syscall /* sys_modify_ldt */
+ .long sys_adjtimex
+ .long sys_mprotect /* 125 */
+ .long sys_sigprocmask
+ .long sys_ni_syscall /* old "create_module" */
+ .long sys_init_module
+ .long sys_delete_module
+ .long sys_ni_syscall /* 130: old "get_kernel_syms" */
+ .long sys_quotactl
+ .long sys_getpgid
+ .long sys_fchdir
+ .long sys_bdflush
+ .long sys_sysfs /* 135 */
+ .long sys_personality
+ .long sys_ni_syscall /* for afs_syscall */
+ .long sys_setfsuid16
+ .long sys_setfsgid16
+ .long sys_llseek /* 140 */
+ .long sys_getdents
+ .long sys_select
+ .long sys_flock
+ .long sys_msync
+ .long sys_readv /* 145 */
+ .long sys_writev
+ .long sys_getsid
+ .long sys_fdatasync
+ .long sys_sysctl
+ .long sys_mlock /* 150 */
+ .long sys_munlock
+ .long sys_mlockall
+ .long sys_munlockall
+ .long sys_sched_setparam
+ .long sys_sched_getparam /* 155 */
+ .long sys_sched_setscheduler
+ .long sys_sched_getscheduler
+ .long sys_sched_yield
+ .long sys_sched_get_priority_max
+ .long sys_sched_get_priority_min /* 160 */
+ .long sys_sched_rr_get_interval
+ .long sys_nanosleep
+ .long sys_mremap
+ .long sys_setresuid16
+ .long sys_getresuid16 /* 165 */
+ .long sys_ni_syscall /* vm86 */
+ .long sys_ni_syscall /* old "query_module" */
+ .long sys_poll
+ .long sys_nfsservctl
+ .long sys_setresgid16 /* 170 */
+ .long sys_getresgid16
+ .long sys_prctl
+ .long sys_rt_sigreturn
+ .long sys_rt_sigaction
+ .long sys_rt_sigprocmask /* 175 */
+ .long sys_rt_sigpending
+ .long sys_rt_sigtimedwait
+ .long sys_rt_sigqueueinfo
+ .long sys_rt_sigsuspend
+ .long sys_pread_wrapper /* 180 */
+ .long sys_pwrite_wrapper
+ .long sys_chown16
+ .long sys_getcwd
+ .long sys_capget
+ .long sys_capset /* 185 */
+ .long sys_sigaltstack
+ .long sys_sendfile
+ .long sys_ni_syscall /* streams1 */
+ .long sys_ni_syscall /* streams2 */
+ .long sys_vfork /* 190 */
+ .long sys_getrlimit
+ .long sys_mmap2
+ .long sys_truncate64
+ .long sys_ftruncate64
+ .long sys_stat64 /* 195 */
+ .long sys_lstat64
+ .long sys_fstat64
+ .long sys_lchown
+ .long sys_getuid
+ .long sys_getgid /* 200 */
+ .long sys_geteuid
+ .long sys_getegid
+ .long sys_setreuid
+ .long sys_setregid
+ .long sys_getgroups /* 205 */
+ .long sys_setgroups
+ .long sys_fchown
+ .long sys_setresuid
+ .long sys_getresuid
+ .long sys_setresgid /* 210 */
+ .long sys_getresgid
+ .long sys_chown
+ .long sys_setuid
+ .long sys_setgid
+ .long sys_setfsuid /* 215 */
+ .long sys_setfsgid
+ .long sys_pivot_root
+ .long sys_mincore
+ .long sys_madvise
+ .long sys_getdents64 /* 220 */
+ .long sys_fcntl64
+ .long sys_ni_syscall /* reserved for TUX */
+ .long sys_ni_syscall /* Reserved for Security */
+ .long sys_gettid
+ .long sys_readahead /* 225 */
+ .long sys_setxattr
+ .long sys_lsetxattr
+ .long sys_fsetxattr
+ .long sys_getxattr
+ .long sys_lgetxattr /* 230 */
+ .long sys_fgetxattr
+ .long sys_listxattr
+ .long sys_llistxattr
+ .long sys_flistxattr
+ .long sys_removexattr /* 235 */
+ .long sys_lremovexattr
+ .long sys_fremovexattr
+ .long sys_tkill
+ .long sys_sendfile64
+ .long sys_futex /* 240 */
+ .long sys_sched_setaffinity
+ .long sys_sched_getaffinity
+ .long sys_ni_syscall
+ .long sys_ni_syscall
+ .long sys_io_setup /* 245 */
+ .long sys_io_destroy
+ .long sys_io_getevents
+ .long sys_io_submit
+ .long sys_io_cancel
+ .long sys_fadvise64 /* 250 */
+ .long sys_ni_syscall
+ .long sys_exit_group
+ .long sys_lookup_dcookie
+ .long sys_epoll_create
+ .long sys_epoll_ctl /* 255 */
+ .long sys_epoll_wait
+ .long sys_remap_file_pages
+ .long sys_set_tid_address
+ .long sys_timer_create
+ .long sys_timer_settime /* 260 */
+ .long sys_timer_gettime
+ .long sys_timer_getoverrun
+ .long sys_timer_delete
+ .long sys_clock_settime
+ .long sys_clock_gettime /* 265 */
+ .long sys_clock_getres
+ .long sys_clock_nanosleep
+ .long sys_statfs64
+ .long sys_fstatfs64
+ .long sys_tgkill /* 270 */
+ .long sys_utimes
+ .long sys_fadvise64_64_wrapper
+ .long sys_ni_syscall /* Reserved for vserver */
+ .long sys_ni_syscall /* Reserved for mbind */
+ .long sys_ni_syscall /* 275 - get_mempolicy */
+ .long sys_ni_syscall /* set_mempolicy */
+ .long sys_mq_open
+ .long sys_mq_unlink
+ .long sys_mq_timedsend
+ .long sys_mq_timedreceive /* 280 */
+ .long sys_mq_notify
+ .long sys_mq_getsetattr
+ .long sys_ni_syscall /* Reserved for kexec */
+ .long sys_waitid
+ .long sys_add_key /* 285 */
+ .long sys_request_key
+ .long sys_keyctl
+
+/* End of entry.S */
diff --git a/arch/sh/kernel/head.S b/arch/sh/kernel/head.S
new file mode 100644
index 000000000000..9b9e6ef626ce
--- /dev/null
+++ b/arch/sh/kernel/head.S
@@ -0,0 +1,76 @@
+/* $Id: head.S,v 1.7 2003/09/01 17:58:19 lethal Exp $
+ *
+ * arch/sh/kernel/head.S
+ *
+ * Copyright (C) 1999, 2000 Niibe Yutaka & Kaz Kojima
+ *
+ * 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.
+ *
+ * Head.S contains the SH exception handlers and startup code.
+ */
+#include <linux/linkage.h>
+
+ .section .empty_zero_page, "aw"
+ENTRY(empty_zero_page)
+ .long 1 /* MOUNT_ROOT_RDONLY */
+ .long 0 /* RAMDISK_FLAGS */
+ .long 0x0200 /* ORIG_ROOT_DEV */
+ .long 1 /* LOADER_TYPE */
+ .long 0x00360000 /* INITRD_START */
+ .long 0x000a0000 /* INITRD_SIZE */
+ .long 0
+ .balign 4096,0,4096
+
+ .text
+/*
+ * Condition at the entry of _stext:
+ *
+ * BSC has already been initialized.
+ * INTC may or may not be initialized.
+ * VBR may or may not be initialized.
+ * MMU may or may not be initialized.
+ * Cache may or may not be initialized.
+ * Hardware (including on-chip modules) may or may not be initialized.
+ *
+ */
+ENTRY(_stext)
+ ! Initialize Status Register
+ mov.l 1f, r0 ! MD=1, RB=0, BL=0, IMASK=0xF
+ ldc r0, sr
+ ! Initialize global interrupt mask
+ mov #0, r0
+ ldc r0, r6_bank
+ !
+ mov.l 2f, r0
+ mov r0, r15 ! Set initial r15 (stack pointer)
+ mov #0x20, r1 !
+ shll8 r1 ! r1 = 8192
+ sub r1, r0 !
+ ldc r0, r7_bank ! ... and initial thread_info
+ !
+ ! Additional CPU initialization
+ mov.l 6f, r0
+ jsr @r0
+ nop
+ ! Clear BSS area
+ mov.l 3f, r1
+ add #4, r1
+ mov.l 4f, r2
+ mov #0, r0
+9: cmp/hs r2, r1
+ bf/s 9b ! while (r1 < r2)
+ mov.l r0,@-r2
+ ! Start kernel
+ mov.l 5f, r0
+ jmp @r0
+ nop
+
+ .balign 4
+1: .long 0x400080F0 ! MD=1, RB=0, BL=0, FD=1, IMASK=0xF
+2: .long stack
+3: .long __bss_start
+4: .long _end
+5: .long start_kernel
+6: .long sh_cpu_init
diff --git a/arch/sh/kernel/init_task.c b/arch/sh/kernel/init_task.c
new file mode 100644
index 000000000000..44053ea92936
--- /dev/null
+++ b/arch/sh/kernel/init_task.c
@@ -0,0 +1,36 @@
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/init_task.h>
+#include <linux/mqueue.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);
+
+EXPORT_SYMBOL(init_mm);
+
+/*
+ * Initial thread structure.
+ *
+ * We need to make sure that this is 8192-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);
+
+EXPORT_SYMBOL(init_task);
diff --git a/arch/sh/kernel/io.c b/arch/sh/kernel/io.c
new file mode 100644
index 000000000000..d9932f25993b
--- /dev/null
+++ b/arch/sh/kernel/io.c
@@ -0,0 +1,59 @@
+/*
+ * linux/arch/sh/kernel/io.c
+ *
+ * Copyright (C) 2000 Stuart Menefy
+ *
+ * Provide real functions which expand to whatever the header file defined.
+ * Also definitions of machine independent IO functions.
+ */
+
+#include <asm/io.h>
+#include <linux/module.h>
+
+/*
+ * Copy data from IO memory space to "real" memory space.
+ * This needs to be optimized.
+ */
+void memcpy_fromio(void * to, unsigned long from, unsigned long count)
+{
+ char *p = to;
+ while (count) {
+ count--;
+ *p = readb(from);
+ p++;
+ from++;
+ }
+}
+
+/*
+ * Copy data from "real" memory space to IO memory space.
+ * This needs to be optimized.
+ */
+void memcpy_toio(unsigned long to, const void * from, unsigned long count)
+{
+ const char *p = from;
+ while (count) {
+ count--;
+ writeb(*p, to);
+ p++;
+ to++;
+ }
+}
+
+/*
+ * "memset" on IO memory space.
+ * This needs to be optimized.
+ */
+void memset_io(unsigned long dst, int c, unsigned long count)
+{
+ while (count) {
+ count--;
+ writeb(c, dst);
+ dst++;
+ }
+}
+
+EXPORT_SYMBOL(memcpy_fromio);
+EXPORT_SYMBOL(memcpy_toio);
+EXPORT_SYMBOL(memset_io);
+
diff --git a/arch/sh/kernel/io_generic.c b/arch/sh/kernel/io_generic.c
new file mode 100644
index 000000000000..a911b0149d1f
--- /dev/null
+++ b/arch/sh/kernel/io_generic.c
@@ -0,0 +1,243 @@
+/* $Id: io_generic.c,v 1.2 2003/05/04 19:29:53 lethal Exp $
+ *
+ * linux/arch/sh/kernel/io_generic.c
+ *
+ * Copyright (C) 2000 Niibe Yutaka
+ *
+ * Generic I/O routine. These can be used where a machine specific version
+ * is not required.
+ *
+ * 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 <asm/io.h>
+#include <asm/machvec.h>
+#include <linux/module.h>
+
+#if defined(CONFIG_CPU_SH3)
+/* I'm not sure SH7709 has this kind of bug */
+#define SH3_PCMCIA_BUG_WORKAROUND 1
+#define DUMMY_READ_AREA6 0xba000000
+#endif
+
+#define PORT2ADDR(x) (sh_mv.mv_isa_port2addr(x))
+
+unsigned long generic_io_base;
+
+static inline void delay(void)
+{
+ ctrl_inw(0xa0000000);
+}
+
+unsigned char generic_inb(unsigned long port)
+{
+ return *(volatile unsigned char*)PORT2ADDR(port);
+}
+
+unsigned short generic_inw(unsigned long port)
+{
+ return *(volatile unsigned short*)PORT2ADDR(port);
+}
+
+unsigned int generic_inl(unsigned long port)
+{
+ return *(volatile unsigned long*)PORT2ADDR(port);
+}
+
+unsigned char generic_inb_p(unsigned long port)
+{
+ unsigned long v = *(volatile unsigned char*)PORT2ADDR(port);
+
+ delay();
+ return v;
+}
+
+unsigned short generic_inw_p(unsigned long port)
+{
+ unsigned long v = *(volatile unsigned short*)PORT2ADDR(port);
+
+ delay();
+ return v;
+}
+
+unsigned int generic_inl_p(unsigned long port)
+{
+ unsigned long v = *(volatile unsigned long*)PORT2ADDR(port);
+
+ delay();
+ return v;
+}
+
+/*
+ * insb/w/l all read a series of bytes/words/longs from a fixed port
+ * address. However as the port address doesn't change we only need to
+ * convert the port address to real address once.
+ */
+
+void generic_insb(unsigned long port, void *buffer, unsigned long count)
+{
+ volatile unsigned char *port_addr;
+ unsigned char *buf=buffer;
+
+ port_addr = (volatile unsigned char *)PORT2ADDR(port);
+
+ while(count--)
+ *buf++ = *port_addr;
+}
+
+void generic_insw(unsigned long port, void *buffer, unsigned long count)
+{
+ volatile unsigned short *port_addr;
+ unsigned short *buf=buffer;
+
+ port_addr = (volatile unsigned short *)PORT2ADDR(port);
+
+ while(count--)
+ *buf++ = *port_addr;
+#ifdef SH3_PCMCIA_BUG_WORKAROUND
+ ctrl_inb (DUMMY_READ_AREA6);
+#endif
+}
+
+void generic_insl(unsigned long port, void *buffer, unsigned long count)
+{
+ volatile unsigned long *port_addr;
+ unsigned long *buf=buffer;
+
+ port_addr = (volatile unsigned long *)PORT2ADDR(port);
+
+ while(count--)
+ *buf++ = *port_addr;
+#ifdef SH3_PCMCIA_BUG_WORKAROUND
+ ctrl_inb (DUMMY_READ_AREA6);
+#endif
+}
+
+void generic_outb(unsigned char b, unsigned long port)
+{
+ *(volatile unsigned char*)PORT2ADDR(port) = b;
+}
+
+void generic_outw(unsigned short b, unsigned long port)
+{
+ *(volatile unsigned short*)PORT2ADDR(port) = b;
+}
+
+void generic_outl(unsigned int b, unsigned long port)
+{
+ *(volatile unsigned long*)PORT2ADDR(port) = b;
+}
+
+void generic_outb_p(unsigned char b, unsigned long port)
+{
+ *(volatile unsigned char*)PORT2ADDR(port) = b;
+ delay();
+}
+
+void generic_outw_p(unsigned short b, unsigned long port)
+{
+ *(volatile unsigned short*)PORT2ADDR(port) = b;
+ delay();
+}
+
+void generic_outl_p(unsigned int b, unsigned long port)
+{
+ *(volatile unsigned long*)PORT2ADDR(port) = b;
+ delay();
+}
+
+/*
+ * outsb/w/l all write a series of bytes/words/longs to a fixed port
+ * address. However as the port address doesn't change we only need to
+ * convert the port address to real address once.
+ */
+
+void generic_outsb(unsigned long port, const void *buffer, unsigned long count)
+{
+ volatile unsigned char *port_addr;
+ const unsigned char *buf=buffer;
+
+ port_addr = (volatile unsigned char *)PORT2ADDR(port);
+
+ while(count--)
+ *port_addr = *buf++;
+}
+
+void generic_outsw(unsigned long port, const void *buffer, unsigned long count)
+{
+ volatile unsigned short *port_addr;
+ const unsigned short *buf=buffer;
+
+ port_addr = (volatile unsigned short *)PORT2ADDR(port);
+
+ while(count--)
+ *port_addr = *buf++;
+
+#ifdef SH3_PCMCIA_BUG_WORKAROUND
+ ctrl_inb (DUMMY_READ_AREA6);
+#endif
+}
+
+void generic_outsl(unsigned long port, const void *buffer, unsigned long count)
+{
+ volatile unsigned long *port_addr;
+ const unsigned long *buf=buffer;
+
+ port_addr = (volatile unsigned long *)PORT2ADDR(port);
+
+ while(count--)
+ *port_addr = *buf++;
+
+#ifdef SH3_PCMCIA_BUG_WORKAROUND
+ ctrl_inb (DUMMY_READ_AREA6);
+#endif
+}
+
+unsigned char generic_readb(unsigned long addr)
+{
+ return *(volatile unsigned char*)addr;
+}
+
+unsigned short generic_readw(unsigned long addr)
+{
+ return *(volatile unsigned short*)addr;
+}
+
+unsigned int generic_readl(unsigned long addr)
+{
+ return *(volatile unsigned long*)addr;
+}
+
+void generic_writeb(unsigned char b, unsigned long addr)
+{
+ *(volatile unsigned char*)addr = b;
+}
+
+void generic_writew(unsigned short b, unsigned long addr)
+{
+ *(volatile unsigned short*)addr = b;
+}
+
+void generic_writel(unsigned int b, unsigned long addr)
+{
+ *(volatile unsigned long*)addr = b;
+}
+
+void * generic_ioremap(unsigned long offset, unsigned long size)
+{
+ return (void *) P2SEGADDR(offset);
+}
+EXPORT_SYMBOL(generic_ioremap);
+
+void generic_iounmap(void *addr)
+{
+}
+EXPORT_SYMBOL(generic_iounmap);
+
+unsigned long generic_isa_port2addr(unsigned long offset)
+{
+ return offset + generic_io_base;
+}
diff --git a/arch/sh/kernel/irq.c b/arch/sh/kernel/irq.c
new file mode 100644
index 000000000000..54c171225b78
--- /dev/null
+++ b/arch/sh/kernel/irq.c
@@ -0,0 +1,106 @@
+/* $Id: irq.c,v 1.20 2004/01/13 05:52:11 kkojima Exp $
+ *
+ * linux/arch/sh/kernel/irq.c
+ *
+ * Copyright (C) 1992, 1998 Linus Torvalds, Ingo Molnar
+ *
+ *
+ * SuperH version: Copyright (C) 1999 Niibe Yutaka
+ */
+
+/*
+ * IRQs are in fact implemented a bit like signal handlers for the kernel.
+ * Naturally it's not a 1:1 relation, but there are similarities.
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/ptrace.h>
+#include <linux/errno.h>
+#include <linux/kernel_stat.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/ioport.h>
+#include <linux/interrupt.h>
+#include <linux/timex.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/random.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/init.h>
+#include <linux/seq_file.h>
+#include <linux/kallsyms.h>
+#include <linux/bitops.h>
+
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/pgalloc.h>
+#include <asm/delay.h>
+#include <asm/irq.h>
+#include <linux/irq.h>
+
+
+/*
+ * 'what should we do if we get a hw irq event on an illegal vector'.
+ * each architecture has to answer this themselves, it doesn't deserve
+ * a generic callback i think.
+ */
+void ack_bad_irq(unsigned int irq)
+{
+ printk("unexpected IRQ trap at vector %02x\n", irq);
+}
+
+#if defined(CONFIG_PROC_FS)
+int show_interrupts(struct seq_file *p, void *v)
+{
+ int i = *(loff_t *) v, j;
+ struct irqaction * action;
+ unsigned long flags;
+
+ if (i == 0) {
+ seq_puts(p, " ");
+ for (j=0; j<NR_CPUS; j++)
+ if (cpu_online(j))
+ seq_printf(p, "CPU%d ",j);
+ seq_putc(p, '\n');
+ }
+
+ if (i < ACTUAL_NR_IRQS) {
+ spin_lock_irqsave(&irq_desc[i].lock, flags);
+ action = irq_desc[i].action;
+ if (!action)
+ goto unlock;
+ seq_printf(p, "%3d: ",i);
+ seq_printf(p, "%10u ", kstat_irqs(i));
+ seq_printf(p, " %14s", irq_desc[i].handler->typename);
+ seq_printf(p, " %s", action->name);
+
+ for (action=action->next; action; action = action->next)
+ seq_printf(p, ", %s", action->name);
+ seq_putc(p, '\n');
+unlock:
+ spin_unlock_irqrestore(&irq_desc[i].lock, flags);
+ }
+ return 0;
+}
+#endif
+
+asmlinkage int do_IRQ(unsigned long r4, unsigned long r5,
+ unsigned long r6, unsigned long r7,
+ struct pt_regs regs)
+{
+ int irq;
+
+ irq_enter();
+ asm volatile("stc r2_bank, %0\n\t"
+ "shlr2 %0\n\t"
+ "shlr2 %0\n\t"
+ "shlr %0\n\t"
+ "add #-16, %0\n\t"
+ :"=z" (irq));
+ irq = irq_demux(irq);
+ __do_IRQ(irq, &regs);
+ irq_exit();
+ return 1;
+}
diff --git a/arch/sh/kernel/kgdb_jmp.S b/arch/sh/kernel/kgdb_jmp.S
new file mode 100644
index 000000000000..339bb1d7ff0b
--- /dev/null
+++ b/arch/sh/kernel/kgdb_jmp.S
@@ -0,0 +1,33 @@
+#include <linux/linkage.h>
+
+ENTRY(setjmp)
+ add #(9*4), r4
+ sts.l pr, @-r4
+ mov.l r15, @-r4
+ mov.l r14, @-r4
+ mov.l r13, @-r4
+ mov.l r12, @-r4
+ mov.l r11, @-r4
+ mov.l r10, @-r4
+ mov.l r9, @-r4
+ mov.l r8, @-r4
+ rts
+ mov #0, r0
+
+ENTRY(longjmp)
+ mov.l @r4+, r8
+ mov.l @r4+, r9
+ mov.l @r4+, r10
+ mov.l @r4+, r11
+ mov.l @r4+, r12
+ mov.l @r4+, r13
+ mov.l @r4+, r14
+ mov.l @r4+, r15
+ lds.l @r4+, pr
+ mov r5, r0
+ tst r0, r0
+ bf 1f
+ mov #1, r0 ! in case val==0
+1: rts
+ nop
+
diff --git a/arch/sh/kernel/kgdb_stub.c b/arch/sh/kernel/kgdb_stub.c
new file mode 100644
index 000000000000..42638b92b51c
--- /dev/null
+++ b/arch/sh/kernel/kgdb_stub.c
@@ -0,0 +1,1491 @@
+/*
+ * May be copied or modified under the terms of the GNU General Public
+ * License. See linux/COPYING for more information.
+ *
+ * Containes extracts from code by Glenn Engel, Jim Kingdon,
+ * David Grothe <dave@gcom.com>, Tigran Aivazian <tigran@sco.com>,
+ * Amit S. Kale <akale@veritas.com>, William Gatliff <bgat@open-widgets.com>,
+ * Ben Lee, Steve Chamberlain and Benoit Miller <fulg@iname.com>.
+ *
+ * This version by Henry Bell <henry.bell@st.com>
+ * Minor modifications by Jeremy Siegel <jsiegel@mvista.com>
+ *
+ * Contains low-level support for remote debug using GDB.
+ *
+ * To enable debugger support, two things need to happen. A call to
+ * set_debug_traps() is necessary in order to allow any breakpoints
+ * or error conditions to be properly intercepted and reported to gdb.
+ * A breakpoint also needs to be generated to begin communication. This
+ * is most easily accomplished by a call to breakpoint() which does
+ * a trapa if the initialisation phase has been successfully completed.
+ *
+ * In this case, set_debug_traps() is not used to "take over" exceptions;
+ * other kernel code is modified instead to enter the kgdb functions here
+ * when appropriate (see entry.S for breakpoint traps and NMI interrupts,
+ * see traps.c for kernel error exceptions).
+ *
+ * The following gdb commands are supported:
+ *
+ * Command Function Return value
+ *
+ * g return the value of the CPU registers hex data or ENN
+ * G set the value of the CPU registers OK or ENN
+ *
+ * mAA..AA,LLLL Read LLLL bytes at address AA..AA hex data or ENN
+ * MAA..AA,LLLL: Write LLLL bytes at address AA.AA OK or ENN
+ * XAA..AA,LLLL: Same, but data is binary (not hex) OK or ENN
+ *
+ * c Resume at current address SNN ( signal NN)
+ * cAA..AA Continue at address AA..AA SNN
+ * CNN; Resume at current address with signal SNN
+ * CNN;AA..AA Resume at address AA..AA with signal SNN
+ *
+ * s Step one instruction SNN
+ * sAA..AA Step one instruction from AA..AA SNN
+ * SNN; Step one instruction with signal SNN
+ * SNNAA..AA Step one instruction from AA..AA w/NN SNN
+ *
+ * k kill (Detach GDB)
+ *
+ * d Toggle debug flag
+ * D Detach GDB
+ *
+ * Hct Set thread t for operations, OK or ENN
+ * c = 'c' (step, cont), c = 'g' (other
+ * operations)
+ *
+ * qC Query current thread ID QCpid
+ * qfThreadInfo Get list of current threads (first) m<id>
+ * qsThreadInfo " " " " " (subsequent)
+ * qOffsets Get section offsets Text=x;Data=y;Bss=z
+ *
+ * TXX Find if thread XX is alive OK or ENN
+ * ? What was the last sigval ? SNN (signal NN)
+ * O Output to GDB console
+ *
+ * Remote communication protocol.
+ *
+ * A debug packet whose contents are <data> is encapsulated for
+ * transmission in the form:
+ *
+ * $ <data> # CSUM1 CSUM2
+ *
+ * <data> must be ASCII alphanumeric and cannot include characters
+ * '$' or '#'. If <data> starts with two characters followed by
+ * ':', then the existing stubs interpret this as a sequence number.
+ *
+ * CSUM1 and CSUM2 are ascii hex representation of an 8-bit
+ * checksum of <data>, the most significant nibble is sent first.
+ * the hex digits 0-9,a-f are used.
+ *
+ * Receiver responds with:
+ *
+ * + - if CSUM is correct and ready for next packet
+ * - - if CSUM is incorrect
+ *
+ * Responses can be run-length encoded to save space. A '*' means that
+ * the next character is an ASCII encoding giving a repeat count which
+ * stands for that many repititions of the character preceding the '*'.
+ * The encoding is n+29, yielding a printable character where n >=3
+ * (which is where RLE starts to win). Don't use an n > 126.
+ *
+ * So "0* " means the same as "0000".
+ */
+
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/smp.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+#include <linux/linkage.h>
+#include <linux/init.h>
+
+#include <asm/system.h>
+#include <asm/current.h>
+#include <asm/signal.h>
+#include <asm/pgtable.h>
+#include <asm/ptrace.h>
+#include <asm/kgdb.h>
+
+#ifdef CONFIG_SH_KGDB_CONSOLE
+#include <linux/console.h>
+#endif
+
+/* Function pointers for linkage */
+kgdb_debug_hook_t *kgdb_debug_hook;
+kgdb_bus_error_hook_t *kgdb_bus_err_hook;
+
+int (*kgdb_getchar)(void);
+void (*kgdb_putchar)(int);
+
+static void put_debug_char(int c)
+{
+ if (!kgdb_putchar)
+ return;
+ (*kgdb_putchar)(c);
+}
+static int get_debug_char(void)
+{
+ if (!kgdb_getchar)
+ return -1;
+ return (*kgdb_getchar)();
+}
+
+/* Num chars in in/out bound buffers, register packets need NUMREGBYTES * 2 */
+#define BUFMAX 1024
+#define NUMREGBYTES (MAXREG*4)
+#define OUTBUFMAX (NUMREGBYTES*2+512)
+
+enum regs {
+ R0 = 0, R1, R2, R3, R4, R5, R6, R7,
+ R8, R9, R10, R11, R12, R13, R14, R15,
+ PC, PR, GBR, VBR, MACH, MACL, SR,
+ /* */
+ MAXREG
+};
+
+static unsigned int registers[MAXREG];
+struct kgdb_regs trap_registers;
+
+char kgdb_in_gdb_mode;
+char in_nmi; /* Set during NMI to prevent reentry */
+int kgdb_nofault; /* Boolean to ignore bus errs (i.e. in GDB) */
+int kgdb_enabled = 1; /* Default to enabled, cmdline can disable */
+int kgdb_halt;
+
+/* Exposed for user access */
+struct task_struct *kgdb_current;
+unsigned int kgdb_g_imask;
+int kgdb_trapa_val;
+int kgdb_excode;
+
+/* Default values for SCI (can override via kernel args in setup.c) */
+#ifndef CONFIG_KGDB_DEFPORT
+#define CONFIG_KGDB_DEFPORT 1
+#endif
+
+#ifndef CONFIG_KGDB_DEFBAUD
+#define CONFIG_KGDB_DEFBAUD 115200
+#endif
+
+#if defined(CONFIG_KGDB_DEFPARITY_E)
+#define CONFIG_KGDB_DEFPARITY 'E'
+#elif defined(CONFIG_KGDB_DEFPARITY_O)
+#define CONFIG_KGDB_DEFPARITY 'O'
+#else /* CONFIG_KGDB_DEFPARITY_N */
+#define CONFIG_KGDB_DEFPARITY 'N'
+#endif
+
+#ifdef CONFIG_KGDB_DEFBITS_7
+#define CONFIG_KGDB_DEFBITS '7'
+#else /* CONFIG_KGDB_DEFBITS_8 */
+#define CONFIG_KGDB_DEFBITS '8'
+#endif
+
+/* SCI/UART settings, used in kgdb_console_setup() */
+int kgdb_portnum = CONFIG_KGDB_DEFPORT;
+int kgdb_baud = CONFIG_KGDB_DEFBAUD;
+char kgdb_parity = CONFIG_KGDB_DEFPARITY;
+char kgdb_bits = CONFIG_KGDB_DEFBITS;
+
+/* Jump buffer for setjmp/longjmp */
+static jmp_buf rem_com_env;
+
+/* TRA differs sh3/4 */
+#if defined(CONFIG_CPU_SH3)
+#define TRA 0xffffffd0
+#elif defined(CONFIG_CPU_SH4)
+#define TRA 0xff000020
+#endif
+
+/* Macros for single step instruction identification */
+#define OPCODE_BT(op) (((op) & 0xff00) == 0x8900)
+#define OPCODE_BF(op) (((op) & 0xff00) == 0x8b00)
+#define OPCODE_BTF_DISP(op) (((op) & 0x80) ? (((op) | 0xffffff80) << 1) : \
+ (((op) & 0x7f ) << 1))
+#define OPCODE_BFS(op) (((op) & 0xff00) == 0x8f00)
+#define OPCODE_BTS(op) (((op) & 0xff00) == 0x8d00)
+#define OPCODE_BRA(op) (((op) & 0xf000) == 0xa000)
+#define OPCODE_BRA_DISP(op) (((op) & 0x800) ? (((op) | 0xfffff800) << 1) : \
+ (((op) & 0x7ff) << 1))
+#define OPCODE_BRAF(op) (((op) & 0xf0ff) == 0x0023)
+#define OPCODE_BRAF_REG(op) (((op) & 0x0f00) >> 8)
+#define OPCODE_BSR(op) (((op) & 0xf000) == 0xb000)
+#define OPCODE_BSR_DISP(op) (((op) & 0x800) ? (((op) | 0xfffff800) << 1) : \
+ (((op) & 0x7ff) << 1))
+#define OPCODE_BSRF(op) (((op) & 0xf0ff) == 0x0003)
+#define OPCODE_BSRF_REG(op) (((op) >> 8) & 0xf)
+#define OPCODE_JMP(op) (((op) & 0xf0ff) == 0x402b)
+#define OPCODE_JMP_REG(op) (((op) >> 8) & 0xf)
+#define OPCODE_JSR(op) (((op) & 0xf0ff) == 0x400b)
+#define OPCODE_JSR_REG(op) (((op) >> 8) & 0xf)
+#define OPCODE_RTS(op) ((op) == 0xb)
+#define OPCODE_RTE(op) ((op) == 0x2b)
+
+#define SR_T_BIT_MASK 0x1
+#define STEP_OPCODE 0xc320
+#define BIOS_CALL_TRAP 0x3f
+
+/* Exception codes as per SH-4 core manual */
+#define ADDRESS_ERROR_LOAD_VEC 7
+#define ADDRESS_ERROR_STORE_VEC 8
+#define TRAP_VEC 11
+#define INVALID_INSN_VEC 12
+#define INVALID_SLOT_VEC 13
+#define NMI_VEC 14
+#define USER_BREAK_VEC 15
+#define SERIAL_BREAK_VEC 58
+
+/* Misc static */
+static int stepped_address;
+static short stepped_opcode;
+static const char hexchars[] = "0123456789abcdef";
+static char in_buffer[BUFMAX];
+static char out_buffer[OUTBUFMAX];
+
+static void kgdb_to_gdb(const char *s);
+
+#ifdef CONFIG_KGDB_THREAD
+static struct task_struct *trapped_thread;
+static struct task_struct *current_thread;
+typedef unsigned char threadref[8];
+#define BUF_THREAD_ID_SIZE 16
+#endif
+
+/* Return addr as a real volatile address */
+static inline unsigned int ctrl_inl(const unsigned long addr)
+{
+ return *(volatile unsigned long *) addr;
+}
+
+/* Correctly set *addr using volatile */
+static inline void ctrl_outl(const unsigned int b, unsigned long addr)
+{
+ *(volatile unsigned long *) addr = b;
+}
+
+/* Get high hex bits */
+static char highhex(const int x)
+{
+ return hexchars[(x >> 4) & 0xf];
+}
+
+/* Get low hex bits */
+static char lowhex(const int x)
+{
+ return hexchars[x & 0xf];
+}
+
+/* Convert ch to hex */
+static int hex(const char ch)
+{
+ if ((ch >= 'a') && (ch <= 'f'))
+ return (ch - 'a' + 10);
+ if ((ch >= '0') && (ch <= '9'))
+ return (ch - '0');
+ if ((ch >= 'A') && (ch <= 'F'))
+ return (ch - 'A' + 10);
+ return (-1);
+}
+
+/* Convert the memory pointed to by mem into hex, placing result in buf.
+ Returns a pointer to the last char put in buf (null) */
+static char *mem_to_hex(const char *mem, char *buf, const int count)
+{
+ int i;
+ int ch;
+ unsigned short s_val;
+ unsigned long l_val;
+
+ /* Check for 16 or 32 */
+ if (count == 2 && ((long) mem & 1) == 0) {
+ s_val = *(unsigned short *) mem;
+ mem = (char *) &s_val;
+ } else if (count == 4 && ((long) mem & 3) == 0) {
+ l_val = *(unsigned long *) mem;
+ mem = (char *) &l_val;
+ }
+ for (i = 0; i < count; i++) {
+ ch = *mem++;
+ *buf++ = highhex(ch);
+ *buf++ = lowhex(ch);
+ }
+ *buf = 0;
+ return (buf);
+}
+
+/* Convert the hex array pointed to by buf into binary, to be placed in mem.
+ Return a pointer to the character after the last byte written */
+static char *hex_to_mem(const char *buf, char *mem, const int count)
+{
+ int i;
+ unsigned char ch;
+
+ for (i = 0; i < count; i++) {
+ ch = hex(*buf++) << 4;
+ ch = ch + hex(*buf++);
+ *mem++ = ch;
+ }
+ return (mem);
+}
+
+/* While finding valid hex chars, convert to an integer, then return it */
+static int hex_to_int(char **ptr, int *int_value)
+{
+ int num_chars = 0;
+ int hex_value;
+
+ *int_value = 0;
+
+ while (**ptr) {
+ hex_value = hex(**ptr);
+ if (hex_value >= 0) {
+ *int_value = (*int_value << 4) | hex_value;
+ num_chars++;
+ } else
+ break;
+ (*ptr)++;
+ }
+ return num_chars;
+}
+
+/* Copy the binary array pointed to by buf into mem. Fix $, #,
+ and 0x7d escaped with 0x7d. Return a pointer to the character
+ after the last byte written. */
+static char *ebin_to_mem(const char *buf, char *mem, int count)
+{
+ for (; count > 0; count--, buf++) {
+ if (*buf == 0x7d)
+ *mem++ = *(++buf) ^ 0x20;
+ else
+ *mem++ = *buf;
+ }
+ return mem;
+}
+
+/* Pack a hex byte */
+static char *pack_hex_byte(char *pkt, int byte)
+{
+ *pkt++ = hexchars[(byte >> 4) & 0xf];
+ *pkt++ = hexchars[(byte & 0xf)];
+ return pkt;
+}
+
+#ifdef CONFIG_KGDB_THREAD
+
+/* Pack a thread ID */
+static char *pack_threadid(char *pkt, threadref * id)
+{
+ char *limit;
+ unsigned char *altid;
+
+ altid = (unsigned char *) id;
+
+ limit = pkt + BUF_THREAD_ID_SIZE;
+ while (pkt < limit)
+ pkt = pack_hex_byte(pkt, *altid++);
+ return pkt;
+}
+
+/* Convert an integer into our threadref */
+static void int_to_threadref(threadref * id, const int value)
+{
+ unsigned char *scan = (unsigned char *) id;
+ int i = 4;
+
+ while (i--)
+ *scan++ = 0;
+
+ *scan++ = (value >> 24) & 0xff;
+ *scan++ = (value >> 16) & 0xff;
+ *scan++ = (value >> 8) & 0xff;
+ *scan++ = (value & 0xff);
+}
+
+/* Return a task structure ptr for a particular pid */
+static struct task_struct *get_thread(int pid)
+{
+ struct task_struct *thread;
+
+ /* Use PID_MAX w/gdb for pid 0 */
+ if (pid == PID_MAX) pid = 0;
+
+ /* First check via PID */
+ thread = find_task_by_pid(pid);
+
+ if (thread)
+ return thread;
+
+ /* Start at the start */
+ thread = init_tasks[0];
+
+ /* Walk along the linked list of tasks */
+ do {
+ if (thread->pid == pid)
+ return thread;
+ thread = thread->next_task;
+ } while (thread != init_tasks[0]);
+
+ return NULL;
+}
+
+#endif /* CONFIG_KGDB_THREAD */
+
+/* Scan for the start char '$', read the packet and check the checksum */
+static void get_packet(char *buffer, int buflen)
+{
+ unsigned char checksum;
+ unsigned char xmitcsum;
+ int i;
+ int count;
+ char ch;
+
+ do {
+ /* Ignore everything until the start character */
+ while ((ch = get_debug_char()) != '$');
+
+ checksum = 0;
+ xmitcsum = -1;
+ count = 0;
+
+ /* Now, read until a # or end of buffer is found */
+ while (count < (buflen - 1)) {
+ ch = get_debug_char();
+
+ if (ch == '#')
+ break;
+
+ checksum = checksum + ch;
+ buffer[count] = ch;
+ count = count + 1;
+ }
+
+ buffer[count] = 0;
+
+ /* Continue to read checksum following # */
+ if (ch == '#') {
+ xmitcsum = hex(get_debug_char()) << 4;
+ xmitcsum += hex(get_debug_char());
+
+ /* Checksum */
+ if (checksum != xmitcsum)
+ put_debug_char('-'); /* Failed checksum */
+ else {
+ /* Ack successful transfer */
+ put_debug_char('+');
+
+ /* If a sequence char is present, reply
+ the sequence ID */
+ if (buffer[2] == ':') {
+ put_debug_char(buffer[0]);
+ put_debug_char(buffer[1]);
+
+ /* Remove sequence chars from buffer */
+ count = strlen(buffer);
+ for (i = 3; i <= count; i++)
+ buffer[i - 3] = buffer[i];
+ }
+ }
+ }
+ }
+ while (checksum != xmitcsum); /* Keep trying while we fail */
+}
+
+/* Send the packet in the buffer with run-length encoding */
+static void put_packet(char *buffer)
+{
+ int checksum;
+ char *src;
+ int runlen;
+ int encode;
+
+ do {
+ src = buffer;
+ put_debug_char('$');
+ checksum = 0;
+
+ /* Continue while we still have chars left */
+ while (*src) {
+ /* Check for runs up to 99 chars long */
+ for (runlen = 1; runlen < 99; runlen++) {
+ if (src[0] != src[runlen])
+ break;
+ }
+
+ if (runlen > 3) {
+ /* Got a useful amount, send encoding */
+ encode = runlen + ' ' - 4;
+ put_debug_char(*src); checksum += *src;
+ put_debug_char('*'); checksum += '*';
+ put_debug_char(encode); checksum += encode;
+ src += runlen;
+ } else {
+ /* Otherwise just send the current char */
+ put_debug_char(*src); checksum += *src;
+ src += 1;
+ }
+ }
+
+ /* '#' Separator, put high and low components of checksum */
+ put_debug_char('#');
+ put_debug_char(highhex(checksum));
+ put_debug_char(lowhex(checksum));
+ }
+ while ((get_debug_char()) != '+'); /* While no ack */
+}
+
+/* A bus error has occurred - perform a longjmp to return execution and
+ allow handling of the error */
+static void kgdb_handle_bus_error(void)
+{
+ longjmp(rem_com_env, 1);
+}
+
+/* Translate SH-3/4 exception numbers to unix-like signal values */
+static int compute_signal(const int excep_code)
+{
+ int sigval;
+
+ switch (excep_code) {
+
+ case INVALID_INSN_VEC:
+ case INVALID_SLOT_VEC:
+ sigval = SIGILL;
+ break;
+ case ADDRESS_ERROR_LOAD_VEC:
+ case ADDRESS_ERROR_STORE_VEC:
+ sigval = SIGSEGV;
+ break;
+
+ case SERIAL_BREAK_VEC:
+ case NMI_VEC:
+ sigval = SIGINT;
+ break;
+
+ case USER_BREAK_VEC:
+ case TRAP_VEC:
+ sigval = SIGTRAP;
+ break;
+
+ default:
+ sigval = SIGBUS; /* "software generated" */
+ break;
+ }
+
+ return (sigval);
+}
+
+/* Make a local copy of the registers passed into the handler (bletch) */
+static void kgdb_regs_to_gdb_regs(const struct kgdb_regs *regs,
+ int *gdb_regs)
+{
+ gdb_regs[R0] = regs->regs[R0];
+ gdb_regs[R1] = regs->regs[R1];
+ gdb_regs[R2] = regs->regs[R2];
+ gdb_regs[R3] = regs->regs[R3];
+ gdb_regs[R4] = regs->regs[R4];
+ gdb_regs[R5] = regs->regs[R5];
+ gdb_regs[R6] = regs->regs[R6];
+ gdb_regs[R7] = regs->regs[R7];
+ gdb_regs[R8] = regs->regs[R8];
+ gdb_regs[R9] = regs->regs[R9];
+ gdb_regs[R10] = regs->regs[R10];
+ gdb_regs[R11] = regs->regs[R11];
+ gdb_regs[R12] = regs->regs[R12];
+ gdb_regs[R13] = regs->regs[R13];
+ gdb_regs[R14] = regs->regs[R14];
+ gdb_regs[R15] = regs->regs[R15];
+ gdb_regs[PC] = regs->pc;
+ gdb_regs[PR] = regs->pr;
+ gdb_regs[GBR] = regs->gbr;
+ gdb_regs[MACH] = regs->mach;
+ gdb_regs[MACL] = regs->macl;
+ gdb_regs[SR] = regs->sr;
+ gdb_regs[VBR] = regs->vbr;
+}
+
+/* Copy local gdb registers back to kgdb regs, for later copy to kernel */
+static void gdb_regs_to_kgdb_regs(const int *gdb_regs,
+ struct kgdb_regs *regs)
+{
+ regs->regs[R0] = gdb_regs[R0];
+ regs->regs[R1] = gdb_regs[R1];
+ regs->regs[R2] = gdb_regs[R2];
+ regs->regs[R3] = gdb_regs[R3];
+ regs->regs[R4] = gdb_regs[R4];
+ regs->regs[R5] = gdb_regs[R5];
+ regs->regs[R6] = gdb_regs[R6];
+ regs->regs[R7] = gdb_regs[R7];
+ regs->regs[R8] = gdb_regs[R8];
+ regs->regs[R9] = gdb_regs[R9];
+ regs->regs[R10] = gdb_regs[R10];
+ regs->regs[R11] = gdb_regs[R11];
+ regs->regs[R12] = gdb_regs[R12];
+ regs->regs[R13] = gdb_regs[R13];
+ regs->regs[R14] = gdb_regs[R14];
+ regs->regs[R15] = gdb_regs[R15];
+ regs->pc = gdb_regs[PC];
+ regs->pr = gdb_regs[PR];
+ regs->gbr = gdb_regs[GBR];
+ regs->mach = gdb_regs[MACH];
+ regs->macl = gdb_regs[MACL];
+ regs->sr = gdb_regs[SR];
+ regs->vbr = gdb_regs[VBR];
+}
+
+#ifdef CONFIG_KGDB_THREAD
+/* Make a local copy of registers from the specified thread */
+asmlinkage void ret_from_fork(void);
+static void thread_regs_to_gdb_regs(const struct task_struct *thread,
+ int *gdb_regs)
+{
+ int regno;
+ int *tregs;
+
+ /* Initialize to zero */
+ for (regno = 0; regno < MAXREG; regno++)
+ gdb_regs[regno] = 0;
+
+ /* Just making sure... */
+ if (thread == NULL)
+ return;
+
+ /* A new fork has pt_regs on the stack from a fork() call */
+ if (thread->thread.pc == (unsigned long)ret_from_fork) {
+
+ int vbr_val;
+ struct pt_regs *kregs;
+ kregs = (struct pt_regs*)thread->thread.sp;
+
+ gdb_regs[R0] = kregs->regs[R0];
+ gdb_regs[R1] = kregs->regs[R1];
+ gdb_regs[R2] = kregs->regs[R2];
+ gdb_regs[R3] = kregs->regs[R3];
+ gdb_regs[R4] = kregs->regs[R4];
+ gdb_regs[R5] = kregs->regs[R5];
+ gdb_regs[R6] = kregs->regs[R6];
+ gdb_regs[R7] = kregs->regs[R7];
+ gdb_regs[R8] = kregs->regs[R8];
+ gdb_regs[R9] = kregs->regs[R9];
+ gdb_regs[R10] = kregs->regs[R10];
+ gdb_regs[R11] = kregs->regs[R11];
+ gdb_regs[R12] = kregs->regs[R12];
+ gdb_regs[R13] = kregs->regs[R13];
+ gdb_regs[R14] = kregs->regs[R14];
+ gdb_regs[R15] = kregs->regs[R15];
+ gdb_regs[PC] = kregs->pc;
+ gdb_regs[PR] = kregs->pr;
+ gdb_regs[GBR] = kregs->gbr;
+ gdb_regs[MACH] = kregs->mach;
+ gdb_regs[MACL] = kregs->macl;
+ gdb_regs[SR] = kregs->sr;
+
+ asm("stc vbr, %0":"=r"(vbr_val));
+ gdb_regs[VBR] = vbr_val;
+ return;
+ }
+
+ /* Otherwise, we have only some registers from switch_to() */
+ tregs = (int *)thread->thread.sp;
+ gdb_regs[R15] = (int)tregs;
+ gdb_regs[R14] = *tregs++;
+ gdb_regs[R13] = *tregs++;
+ gdb_regs[R12] = *tregs++;
+ gdb_regs[R11] = *tregs++;
+ gdb_regs[R10] = *tregs++;
+ gdb_regs[R9] = *tregs++;
+ gdb_regs[R8] = *tregs++;
+ gdb_regs[PR] = *tregs++;
+ gdb_regs[GBR] = *tregs++;
+ gdb_regs[PC] = thread->thread.pc;
+}
+#endif /* CONFIG_KGDB_THREAD */
+
+/* Calculate the new address for after a step */
+static short *get_step_address(void)
+{
+ short op = *(short *) trap_registers.pc;
+ long addr;
+
+ /* BT */
+ if (OPCODE_BT(op)) {
+ if (trap_registers.sr & SR_T_BIT_MASK)
+ addr = trap_registers.pc + 4 + OPCODE_BTF_DISP(op);
+ else
+ addr = trap_registers.pc + 2;
+ }
+
+ /* BTS */
+ else if (OPCODE_BTS(op)) {
+ if (trap_registers.sr & SR_T_BIT_MASK)
+ addr = trap_registers.pc + 4 + OPCODE_BTF_DISP(op);
+ else
+ addr = trap_registers.pc + 4; /* Not in delay slot */
+ }
+
+ /* BF */
+ else if (OPCODE_BF(op)) {
+ if (!(trap_registers.sr & SR_T_BIT_MASK))
+ addr = trap_registers.pc + 4 + OPCODE_BTF_DISP(op);
+ else
+ addr = trap_registers.pc + 2;
+ }
+
+ /* BFS */
+ else if (OPCODE_BFS(op)) {
+ if (!(trap_registers.sr & SR_T_BIT_MASK))
+ addr = trap_registers.pc + 4 + OPCODE_BTF_DISP(op);
+ else
+ addr = trap_registers.pc + 4; /* Not in delay slot */
+ }
+
+ /* BRA */
+ else if (OPCODE_BRA(op))
+ addr = trap_registers.pc + 4 + OPCODE_BRA_DISP(op);
+
+ /* BRAF */
+ else if (OPCODE_BRAF(op))
+ addr = trap_registers.pc + 4
+ + trap_registers.regs[OPCODE_BRAF_REG(op)];
+
+ /* BSR */
+ else if (OPCODE_BSR(op))
+ addr = trap_registers.pc + 4 + OPCODE_BSR_DISP(op);
+
+ /* BSRF */
+ else if (OPCODE_BSRF(op))
+ addr = trap_registers.pc + 4
+ + trap_registers.regs[OPCODE_BSRF_REG(op)];
+
+ /* JMP */
+ else if (OPCODE_JMP(op))
+ addr = trap_registers.regs[OPCODE_JMP_REG(op)];
+
+ /* JSR */
+ else if (OPCODE_JSR(op))
+ addr = trap_registers.regs[OPCODE_JSR_REG(op)];
+
+ /* RTS */
+ else if (OPCODE_RTS(op))
+ addr = trap_registers.pr;
+
+ /* RTE */
+ else if (OPCODE_RTE(op))
+ addr = trap_registers.regs[15];
+
+ /* Other */
+ else
+ addr = trap_registers.pc + 2;
+
+ kgdb_flush_icache_range(addr, addr + 2);
+ return (short *) addr;
+}
+
+/* Set up a single-step. Replace the instruction immediately after the
+ current instruction (i.e. next in the expected flow of control) with a
+ trap instruction, so that returning will cause only a single instruction
+ to be executed. Note that this model is slightly broken for instructions
+ with delay slots (e.g. B[TF]S, BSR, BRA etc), where both the branch
+ and the instruction in the delay slot will be executed. */
+static void do_single_step(void)
+{
+ unsigned short *addr = 0;
+
+ /* Determine where the target instruction will send us to */
+ addr = get_step_address();
+ stepped_address = (int)addr;
+
+ /* Replace it */
+ stepped_opcode = *(short *)addr;
+ *addr = STEP_OPCODE;
+
+ /* Flush and return */
+ kgdb_flush_icache_range((long) addr, (long) addr + 2);
+ return;
+}
+
+/* Undo a single step */
+static void undo_single_step(void)
+{
+ /* If we have stepped, put back the old instruction */
+ /* Use stepped_address in case we stopped elsewhere */
+ if (stepped_opcode != 0) {
+ *(short*)stepped_address = stepped_opcode;
+ kgdb_flush_icache_range(stepped_address, stepped_address + 2);
+ }
+ stepped_opcode = 0;
+}
+
+/* Send a signal message */
+static void send_signal_msg(const int signum)
+{
+#ifndef CONFIG_KGDB_THREAD
+ out_buffer[0] = 'S';
+ out_buffer[1] = highhex(signum);
+ out_buffer[2] = lowhex(signum);
+ out_buffer[3] = 0;
+ put_packet(out_buffer);
+#else /* CONFIG_KGDB_THREAD */
+ int threadid;
+ threadref thref;
+ char *out = out_buffer;
+ const char *tstring = "thread";
+
+ *out++ = 'T';
+ *out++ = highhex(signum);
+ *out++ = lowhex(signum);
+
+ while (*tstring) {
+ *out++ = *tstring++;
+ }
+ *out++ = ':';
+
+ threadid = trapped_thread->pid;
+ if (threadid == 0) threadid = PID_MAX;
+ int_to_threadref(&thref, threadid);
+ pack_threadid(out, &thref);
+ out += BUF_THREAD_ID_SIZE;
+ *out++ = ';';
+
+ *out = 0;
+ put_packet(out_buffer);
+#endif /* CONFIG_KGDB_THREAD */
+}
+
+/* Reply that all was well */
+static void send_ok_msg(void)
+{
+ strcpy(out_buffer, "OK");
+ put_packet(out_buffer);
+}
+
+/* Reply that an error occurred */
+static void send_err_msg(void)
+{
+ strcpy(out_buffer, "E01");
+ put_packet(out_buffer);
+}
+
+/* Empty message indicates unrecognised command */
+static void send_empty_msg(void)
+{
+ put_packet("");
+}
+
+/* Read memory due to 'm' message */
+static void read_mem_msg(void)
+{
+ char *ptr;
+ int addr;
+ int length;
+
+ /* Jmp, disable bus error handler */
+ if (setjmp(rem_com_env) == 0) {
+
+ kgdb_nofault = 1;
+
+ /* Walk through, have m<addr>,<length> */
+ ptr = &in_buffer[1];
+ if (hex_to_int(&ptr, &addr) && (*ptr++ == ','))
+ if (hex_to_int(&ptr, &length)) {
+ ptr = 0;
+ if (length * 2 > OUTBUFMAX)
+ length = OUTBUFMAX / 2;
+ mem_to_hex((char *) addr, out_buffer, length);
+ }
+ if (ptr)
+ send_err_msg();
+ else
+ put_packet(out_buffer);
+ } else
+ send_err_msg();
+
+ /* Restore bus error handler */
+ kgdb_nofault = 0;
+}
+
+/* Write memory due to 'M' or 'X' message */
+static void write_mem_msg(int binary)
+{
+ char *ptr;
+ int addr;
+ int length;
+
+ if (setjmp(rem_com_env) == 0) {
+
+ kgdb_nofault = 1;
+
+ /* Walk through, have M<addr>,<length>:<data> */
+ ptr = &in_buffer[1];
+ if (hex_to_int(&ptr, &addr) && (*ptr++ == ','))
+ if (hex_to_int(&ptr, &length) && (*ptr++ == ':')) {
+ if (binary)
+ ebin_to_mem(ptr, (char*)addr, length);
+ else
+ hex_to_mem(ptr, (char*)addr, length);
+ kgdb_flush_icache_range(addr, addr + length);
+ ptr = 0;
+ send_ok_msg();
+ }
+ if (ptr)
+ send_err_msg();
+ } else
+ send_err_msg();
+
+ /* Restore bus error handler */
+ kgdb_nofault = 0;
+}
+
+/* Continue message */
+static void continue_msg(void)
+{
+ /* Try to read optional parameter, PC unchanged if none */
+ char *ptr = &in_buffer[1];
+ int addr;
+
+ if (hex_to_int(&ptr, &addr))
+ trap_registers.pc = addr;
+}
+
+/* Continue message with signal */
+static void continue_with_sig_msg(void)
+{
+ int signal;
+ char *ptr = &in_buffer[1];
+ int addr;
+
+ /* Report limitation */
+ kgdb_to_gdb("Cannot force signal in kgdb, continuing anyway.\n");
+
+ /* Signal */
+ hex_to_int(&ptr, &signal);
+ if (*ptr == ';')
+ ptr++;
+
+ /* Optional address */
+ if (hex_to_int(&ptr, &addr))
+ trap_registers.pc = addr;
+}
+
+/* Step message */
+static void step_msg(void)
+{
+ continue_msg();
+ do_single_step();
+}
+
+/* Step message with signal */
+static void step_with_sig_msg(void)
+{
+ continue_with_sig_msg();
+ do_single_step();
+}
+
+/* Send register contents */
+static void send_regs_msg(void)
+{
+#ifdef CONFIG_KGDB_THREAD
+ if (!current_thread)
+ kgdb_regs_to_gdb_regs(&trap_registers, registers);
+ else
+ thread_regs_to_gdb_regs(current_thread, registers);
+#else
+ kgdb_regs_to_gdb_regs(&trap_registers, registers);
+#endif
+
+ mem_to_hex((char *) registers, out_buffer, NUMREGBYTES);
+ put_packet(out_buffer);
+}
+
+/* Set register contents - currently can't set other thread's registers */
+static void set_regs_msg(void)
+{
+#ifdef CONFIG_KGDB_THREAD
+ if (!current_thread) {
+#endif
+ kgdb_regs_to_gdb_regs(&trap_registers, registers);
+ hex_to_mem(&in_buffer[1], (char *) registers, NUMREGBYTES);
+ gdb_regs_to_kgdb_regs(registers, &trap_registers);
+ send_ok_msg();
+#ifdef CONFIG_KGDB_THREAD
+ } else
+ send_err_msg();
+#endif
+}
+
+
+#ifdef CONFIG_KGDB_THREAD
+
+/* Set the status for a thread */
+void set_thread_msg(void)
+{
+ int threadid;
+ struct task_struct *thread = NULL;
+ char *ptr;
+
+ switch (in_buffer[1]) {
+
+ /* To select which thread for gG etc messages, i.e. supported */
+ case 'g':
+
+ ptr = &in_buffer[2];
+ hex_to_int(&ptr, &threadid);
+ thread = get_thread(threadid);
+
+ /* If we haven't found it */
+ if (!thread) {
+ send_err_msg();
+ break;
+ }
+
+ /* Set current_thread (or not) */
+ if (thread == trapped_thread)
+ current_thread = NULL;
+ else
+ current_thread = thread;
+ send_ok_msg();
+ break;
+
+ /* To select which thread for cCsS messages, i.e. unsupported */
+ case 'c':
+ send_ok_msg();
+ break;
+
+ default:
+ send_empty_msg();
+ break;
+ }
+}
+
+/* Is a thread alive? */
+static void thread_status_msg(void)
+{
+ char *ptr;
+ int threadid;
+ struct task_struct *thread = NULL;
+
+ ptr = &in_buffer[1];
+ hex_to_int(&ptr, &threadid);
+ thread = get_thread(threadid);
+ if (thread)
+ send_ok_msg();
+ else
+ send_err_msg();
+}
+/* Send the current thread ID */
+static void thread_id_msg(void)
+{
+ int threadid;
+ threadref thref;
+
+ out_buffer[0] = 'Q';
+ out_buffer[1] = 'C';
+
+ if (current_thread)
+ threadid = current_thread->pid;
+ else if (trapped_thread)
+ threadid = trapped_thread->pid;
+ else /* Impossible, but just in case! */
+ {
+ send_err_msg();
+ return;
+ }
+
+ /* Translate pid 0 to PID_MAX for gdb */
+ if (threadid == 0) threadid = PID_MAX;
+
+ int_to_threadref(&thref, threadid);
+ pack_threadid(out_buffer + 2, &thref);
+ out_buffer[2 + BUF_THREAD_ID_SIZE] = '\0';
+ put_packet(out_buffer);
+}
+
+/* Send thread info */
+static void thread_info_msg(void)
+{
+ struct task_struct *thread = NULL;
+ int threadid;
+ char *pos;
+ threadref thref;
+
+ /* Start with 'm' */
+ out_buffer[0] = 'm';
+ pos = &out_buffer[1];
+
+ /* For all possible thread IDs - this will overrun if > 44 threads! */
+ /* Start at 1 and include PID_MAX (since GDB won't use pid 0...) */
+ for (threadid = 1; threadid <= PID_MAX; threadid++) {
+
+ read_lock(&tasklist_lock);
+ thread = get_thread(threadid);
+ read_unlock(&tasklist_lock);
+
+ /* If it's a valid thread */
+ if (thread) {
+ int_to_threadref(&thref, threadid);
+ pack_threadid(pos, &thref);
+ pos += BUF_THREAD_ID_SIZE;
+ *pos++ = ',';
+ }
+ }
+ *--pos = 0; /* Lose final comma */
+ put_packet(out_buffer);
+
+}
+
+/* Return printable info for gdb's 'info threads' command */
+static void thread_extra_info_msg(void)
+{
+ int threadid;
+ struct task_struct *thread = NULL;
+ char buffer[20], *ptr;
+ int i;
+
+ /* Extract thread ID */
+ ptr = &in_buffer[17];
+ hex_to_int(&ptr, &threadid);
+ thread = get_thread(threadid);
+
+ /* If we don't recognise it, say so */
+ if (thread == NULL)
+ strcpy(buffer, "(unknown)");
+ else
+ strcpy(buffer, thread->comm);
+
+ /* Construct packet */
+ for (i = 0, ptr = out_buffer; buffer[i]; i++)
+ ptr = pack_hex_byte(ptr, buffer[i]);
+
+ if (thread->thread.pc == (unsigned long)ret_from_fork) {
+ strcpy(buffer, "<new fork>");
+ for (i = 0; buffer[i]; i++)
+ ptr = pack_hex_byte(ptr, buffer[i]);
+ }
+
+ *ptr = '\0';
+ put_packet(out_buffer);
+}
+
+/* Handle all qFooBarBaz messages - have to use an if statement as
+ opposed to a switch because q messages can have > 1 char id. */
+static void query_msg(void)
+{
+ const char *q_start = &in_buffer[1];
+
+ /* qC = return current thread ID */
+ if (strncmp(q_start, "C", 1) == 0)
+ thread_id_msg();
+
+ /* qfThreadInfo = query all threads (first) */
+ else if (strncmp(q_start, "fThreadInfo", 11) == 0)
+ thread_info_msg();
+
+ /* qsThreadInfo = query all threads (subsequent). We know we have sent
+ them all after the qfThreadInfo message, so there are no to send */
+ else if (strncmp(q_start, "sThreadInfo", 11) == 0)
+ put_packet("l"); /* el = last */
+
+ /* qThreadExtraInfo = supply printable information per thread */
+ else if (strncmp(q_start, "ThreadExtraInfo", 15) == 0)
+ thread_extra_info_msg();
+
+ /* Unsupported - empty message as per spec */
+ else
+ send_empty_msg();
+}
+#endif /* CONFIG_KGDB_THREAD */
+
+/*
+ * Bring up the ports..
+ */
+static int kgdb_serial_setup(void)
+{
+ extern int kgdb_console_setup(struct console *co, char *options);
+ struct console dummy;
+
+ kgdb_console_setup(&dummy, 0);
+
+ return 0;
+}
+
+/* The command loop, read and act on requests */
+static void kgdb_command_loop(const int excep_code, const int trapa_value)
+{
+ int sigval;
+
+ if (excep_code == NMI_VEC) {
+#ifndef CONFIG_KGDB_NMI
+ KGDB_PRINTK("Ignoring unexpected NMI?\n");
+ return;
+#else /* CONFIG_KGDB_NMI */
+ if (!kgdb_enabled) {
+ kgdb_enabled = 1;
+ kgdb_init();
+ }
+#endif /* CONFIG_KGDB_NMI */
+ }
+
+ /* Ignore if we're disabled */
+ if (!kgdb_enabled)
+ return;
+
+#ifdef CONFIG_KGDB_THREAD
+ /* Until GDB specifies a thread */
+ current_thread = NULL;
+ trapped_thread = current;
+#endif
+
+ /* Enter GDB mode (e.g. after detach) */
+ if (!kgdb_in_gdb_mode) {
+ /* Do serial setup, notify user, issue preemptive ack */
+ kgdb_serial_setup();
+ KGDB_PRINTK("Waiting for GDB (on %s%d at %d baud)\n",
+ (kgdb_porttype ? kgdb_porttype->name : ""),
+ kgdb_portnum, kgdb_baud);
+ kgdb_in_gdb_mode = 1;
+ put_debug_char('+');
+ }
+
+ /* Reply to host that an exception has occurred */
+ sigval = compute_signal(excep_code);
+ send_signal_msg(sigval);
+
+ /* TRAP_VEC exception indicates a software trap inserted in place of
+ code by GDB so back up PC by one instruction, as this instruction
+ will later be replaced by its original one. Do NOT do this for
+ trap 0xff, since that indicates a compiled-in breakpoint which
+ will not be replaced (and we would retake the trap forever) */
+ if ((excep_code == TRAP_VEC) && (trapa_value != (0xff << 2))) {
+ trap_registers.pc -= 2;
+ }
+
+ /* Undo any stepping we may have done */
+ undo_single_step();
+
+ while (1) {
+
+ out_buffer[0] = 0;
+ get_packet(in_buffer, BUFMAX);
+
+ /* Examine first char of buffer to see what we need to do */
+ switch (in_buffer[0]) {
+
+ case '?': /* Send which signal we've received */
+ send_signal_msg(sigval);
+ break;
+
+ case 'g': /* Return the values of the CPU registers */
+ send_regs_msg();
+ break;
+
+ case 'G': /* Set the value of the CPU registers */
+ set_regs_msg();
+ break;
+
+ case 'm': /* Read LLLL bytes address AA..AA */
+ read_mem_msg();
+ break;
+
+ case 'M': /* Write LLLL bytes address AA..AA, ret OK */
+ write_mem_msg(0); /* 0 = data in hex */
+ break;
+
+ case 'X': /* Write LLLL bytes esc bin address AA..AA */
+ if (kgdb_bits == '8')
+ write_mem_msg(1); /* 1 = data in binary */
+ else
+ send_empty_msg();
+ break;
+
+ case 'C': /* Continue, signum included, we ignore it */
+ continue_with_sig_msg();
+ return;
+
+ case 'c': /* Continue at address AA..AA (optional) */
+ continue_msg();
+ return;
+
+ case 'S': /* Step, signum included, we ignore it */
+ step_with_sig_msg();
+ return;
+
+ case 's': /* Step one instruction from AA..AA */
+ step_msg();
+ return;
+
+#ifdef CONFIG_KGDB_THREAD
+
+ case 'H': /* Task related */
+ set_thread_msg();
+ break;
+
+ case 'T': /* Query thread status */
+ thread_status_msg();
+ break;
+
+ case 'q': /* Handle query - currently thread-related */
+ query_msg();
+ break;
+#endif
+
+ case 'k': /* 'Kill the program' with a kernel ? */
+ break;
+
+ case 'D': /* Detach from program, send reply OK */
+ kgdb_in_gdb_mode = 0;
+ send_ok_msg();
+ get_debug_char();
+ return;
+
+ default:
+ send_empty_msg();
+ break;
+ }
+ }
+}
+
+/* There has been an exception, most likely a breakpoint. */
+void kgdb_handle_exception(struct pt_regs *regs)
+{
+ int excep_code, vbr_val;
+ int count;
+ int trapa_value = ctrl_inl(TRA);
+
+ /* Copy kernel regs (from stack) */
+ for (count = 0; count < 16; count++)
+ trap_registers.regs[count] = regs->regs[count];
+ trap_registers.pc = regs->pc;
+ trap_registers.pr = regs->pr;
+ trap_registers.sr = regs->sr;
+ trap_registers.gbr = regs->gbr;
+ trap_registers.mach = regs->mach;
+ trap_registers.macl = regs->macl;
+
+ asm("stc vbr, %0":"=r"(vbr_val));
+ trap_registers.vbr = vbr_val;
+
+ /* Get excode for command loop call, user access */
+ asm("stc r2_bank, %0":"=r"(excep_code));
+ kgdb_excode = excep_code;
+
+ /* Other interesting environment items for reference */
+ asm("stc r6_bank, %0":"=r"(kgdb_g_imask));
+ kgdb_current = current;
+ kgdb_trapa_val = trapa_value;
+
+ /* Act on the exception */
+ kgdb_command_loop(excep_code >> 5, trapa_value);
+
+ kgdb_current = NULL;
+
+ /* Copy back the (maybe modified) registers */
+ for (count = 0; count < 16; count++)
+ regs->regs[count] = trap_registers.regs[count];
+ regs->pc = trap_registers.pc;
+ regs->pr = trap_registers.pr;
+ regs->sr = trap_registers.sr;
+ regs->gbr = trap_registers.gbr;
+ regs->mach = trap_registers.mach;
+ regs->macl = trap_registers.macl;
+
+ vbr_val = trap_registers.vbr;
+ asm("ldc %0, vbr": :"r"(vbr_val));
+
+ return;
+}
+
+/* Trigger a breakpoint by function */
+void breakpoint(void)
+{
+ if (!kgdb_enabled) {
+ kgdb_enabled = 1;
+ kgdb_init();
+ }
+ BREAKPOINT();
+}
+
+/* Initialise the KGDB data structures and serial configuration */
+int kgdb_init(void)
+{
+ if (!kgdb_enabled)
+ return 1;
+
+ in_nmi = 0;
+ kgdb_nofault = 0;
+ stepped_opcode = 0;
+ kgdb_in_gdb_mode = 0;
+
+ if (kgdb_serial_setup() != 0) {
+ KGDB_PRINTK("serial setup error\n");
+ return -1;
+ }
+
+ /* Init ptr to exception handler */
+ kgdb_debug_hook = kgdb_handle_exception;
+ kgdb_bus_err_hook = kgdb_handle_bus_error;
+
+ /* Enter kgdb now if requested, or just report init done */
+ if (kgdb_halt) {
+ kgdb_in_gdb_mode = 1;
+ put_debug_char('+');
+ breakpoint();
+ }
+ else
+ {
+ KGDB_PRINTK("stub is initialized.\n");
+ }
+
+ return 0;
+}
+
+/* Make function available for "user messages"; console will use it too. */
+
+char gdbmsgbuf[BUFMAX];
+#define MAXOUT ((BUFMAX-2)/2)
+
+static void kgdb_msg_write(const char *s, unsigned count)
+{
+ int i;
+ int wcount;
+ char *bufptr;
+
+ /* 'O'utput */
+ gdbmsgbuf[0] = 'O';
+
+ /* Fill and send buffers... */
+ while (count > 0) {
+ bufptr = gdbmsgbuf + 1;
+
+ /* Calculate how many this time */
+ wcount = (count > MAXOUT) ? MAXOUT : count;
+
+ /* Pack in hex chars */
+ for (i = 0; i < wcount; i++)
+ bufptr = pack_hex_byte(bufptr, s[i]);
+ *bufptr = '\0';
+
+ /* Move up */
+ s += wcount;
+ count -= wcount;
+
+ /* Write packet */
+ put_packet(gdbmsgbuf);
+ }
+}
+
+static void kgdb_to_gdb(const char *s)
+{
+ kgdb_msg_write(s, strlen(s));
+}
+
+#ifdef CONFIG_SH_KGDB_CONSOLE
+void kgdb_console_write(struct console *co, const char *s, unsigned count)
+{
+ /* Bail if we're not talking to GDB */
+ if (!kgdb_in_gdb_mode)
+ return;
+
+ kgdb_msg_write(s, count);
+}
+#endif
diff --git a/arch/sh/kernel/module.c b/arch/sh/kernel/module.c
new file mode 100644
index 000000000000..142a4e5b7ebc
--- /dev/null
+++ b/arch/sh/kernel/module.c
@@ -0,0 +1,146 @@
+/* Kernel module help for SH.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+#include <linux/moduleloader.h>
+#include <linux/elf.h>
+#include <linux/vmalloc.h>
+#include <linux/fs.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+
+#if 0
+#define DEBUGP printk
+#else
+#define DEBUGP(fmt...)
+#endif
+
+void *module_alloc(unsigned long size)
+{
+ if (size == 0)
+ return NULL;
+ return vmalloc(size);
+}
+
+
+/* Free memory returned from module_alloc */
+void module_free(struct module *mod, void *module_region)
+{
+ vfree(module_region);
+ /* FIXME: If module_region == mod->init_region, trim exception
+ table entries. */
+}
+
+/* We don't need anything special. */
+int module_frob_arch_sections(Elf_Ehdr *hdr,
+ Elf_Shdr *sechdrs,
+ char *secstrings,
+ struct module *mod)
+{
+ return 0;
+}
+
+#define COPY_UNALIGNED_WORD(sw, tw, align) \
+{ \
+ void *__s = &(sw), *__t = &(tw); \
+ unsigned short *__s2 = __s, *__t2 = __t; \
+ unsigned char *__s1 = __s, *__t1 = __t; \
+ switch ((align)) \
+ { \
+ case 0: \
+ *(unsigned long *) __t = *(unsigned long *) __s; \
+ break; \
+ case 2: \
+ *__t2++ = *__s2++; \
+ *__t2 = *__s2; \
+ break; \
+ default: \
+ *__t1++ = *__s1++; \
+ *__t1++ = *__s1++; \
+ *__t1++ = *__s1++; \
+ *__t1 = *__s1; \
+ break; \
+ } \
+}
+
+int apply_relocate_add(Elf32_Shdr *sechdrs,
+ const char *strtab,
+ unsigned int symindex,
+ unsigned int relsec,
+ struct module *me)
+{
+ unsigned int i;
+ Elf32_Rela *rel = (void *)sechdrs[relsec].sh_addr;
+ Elf32_Sym *sym;
+ Elf32_Addr relocation;
+ uint32_t *location;
+ uint32_t value;
+ int align;
+
+ DEBUGP("Applying relocate section %u to %u\n", relsec,
+ sechdrs[relsec].sh_info);
+ for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
+ /* This is where to make the change */
+ location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
+ + rel[i].r_offset;
+ /* This is the symbol it is referring to. Note that all
+ undefined symbols have been resolved. */
+ sym = (Elf32_Sym *)sechdrs[symindex].sh_addr
+ + ELF32_R_SYM(rel[i].r_info);
+ relocation = sym->st_value + rel[i].r_addend;
+ align = (int)location & 3;
+
+ switch (ELF32_R_TYPE(rel[i].r_info)) {
+ case R_SH_DIR32:
+ COPY_UNALIGNED_WORD (*location, value, align);
+ value += relocation;
+ COPY_UNALIGNED_WORD (value, *location, align);
+ break;
+ case R_SH_REL32:
+ relocation = (relocation - (Elf32_Addr) location);
+ COPY_UNALIGNED_WORD (*location, value, align);
+ value += relocation;
+ COPY_UNALIGNED_WORD (value, *location, align);
+ break;
+ default:
+ printk(KERN_ERR "module %s: Unknown relocation: %u\n",
+ me->name, ELF32_R_TYPE(rel[i].r_info));
+ return -ENOEXEC;
+ }
+ }
+ return 0;
+}
+
+int apply_relocate(Elf32_Shdr *sechdrs,
+ const char *strtab,
+ unsigned int symindex,
+ unsigned int relsec,
+ struct module *me)
+{
+ printk(KERN_ERR "module %s: REL RELOCATION unsupported\n",
+ me->name);
+ return -ENOEXEC;
+}
+
+int module_finalize(const Elf_Ehdr *hdr,
+ const Elf_Shdr *sechdrs,
+ struct module *me)
+{
+ return 0;
+}
+
+void module_arch_cleanup(struct module *mod)
+{
+}
diff --git a/arch/sh/kernel/process.c b/arch/sh/kernel/process.c
new file mode 100644
index 000000000000..3d024590c24e
--- /dev/null
+++ b/arch/sh/kernel/process.c
@@ -0,0 +1,531 @@
+/* $Id: process.c,v 1.28 2004/05/05 16:54:23 lethal Exp $
+ *
+ * linux/arch/sh/kernel/process.c
+ *
+ * Copyright (C) 1995 Linus Torvalds
+ *
+ * SuperH version: Copyright (C) 1999, 2000 Niibe Yutaka & Kaz Kojima
+ */
+
+/*
+ * This file handles the architecture-dependent parts of process handling..
+ */
+
+#include <linux/module.h>
+#include <linux/unistd.h>
+#include <linux/mm.h>
+#include <linux/elfcore.h>
+#include <linux/slab.h>
+#include <linux/a.out.h>
+#include <linux/ptrace.h>
+#include <linux/platform.h>
+#include <linux/kallsyms.h>
+
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/mmu_context.h>
+#include <asm/elf.h>
+#if defined(CONFIG_SH_HS7751RVOIP)
+#include <asm/hs7751rvoip/hs7751rvoip.h>
+#elif defined(CONFIG_SH_RTS7751R2D)
+#include <asm/rts7751r2d/rts7751r2d.h>
+#endif
+
+static int hlt_counter=0;
+
+int ubc_usercnt = 0;
+
+#define HARD_IDLE_TIMEOUT (HZ / 3)
+
+void disable_hlt(void)
+{
+ hlt_counter++;
+}
+
+EXPORT_SYMBOL(disable_hlt);
+
+void enable_hlt(void)
+{
+ hlt_counter--;
+}
+
+EXPORT_SYMBOL(enable_hlt);
+
+void default_idle(void)
+{
+ /* endless idle loop with no priority at all */
+ while (1) {
+ if (hlt_counter) {
+ while (1)
+ if (need_resched())
+ break;
+ } else {
+ while (!need_resched())
+ cpu_sleep();
+ }
+
+ schedule();
+ }
+}
+
+void cpu_idle(void)
+{
+ default_idle();
+}
+
+void machine_restart(char * __unused)
+{
+ /* SR.BL=1 and invoke address error to let CPU reset (manual reset) */
+ asm volatile("ldc %0, sr\n\t"
+ "mov.l @%1, %0" : : "r" (0x10000000), "r" (0x80000001));
+}
+
+EXPORT_SYMBOL(machine_restart);
+
+void machine_halt(void)
+{
+#if defined(CONFIG_SH_HS7751RVOIP)
+ unsigned short value;
+
+ value = ctrl_inw(PA_OUTPORTR);
+ ctrl_outw((value & 0xffdf), PA_OUTPORTR);
+#elif defined(CONFIG_SH_RTS7751R2D)
+ ctrl_outw(0x0001, PA_POWOFF);
+#endif
+ while (1)
+ cpu_sleep();
+}
+
+EXPORT_SYMBOL(machine_halt);
+
+void machine_power_off(void)
+{
+#if defined(CONFIG_SH_HS7751RVOIP)
+ unsigned short value;
+
+ value = ctrl_inw(PA_OUTPORTR);
+ ctrl_outw((value & 0xffdf), PA_OUTPORTR);
+#elif defined(CONFIG_SH_RTS7751R2D)
+ ctrl_outw(0x0001, PA_POWOFF);
+#endif
+}
+
+EXPORT_SYMBOL(machine_power_off);
+
+void show_regs(struct pt_regs * regs)
+{
+ printk("\n");
+ printk("Pid : %d, Comm: %20s\n", current->pid, current->comm);
+ print_symbol("PC is at %s\n", regs->pc);
+ printk("PC : %08lx SP : %08lx SR : %08lx ",
+ regs->pc, regs->regs[15], regs->sr);
+#ifdef CONFIG_MMU
+ printk("TEA : %08x ", ctrl_inl(MMU_TEA));
+#else
+ printk(" ");
+#endif
+ printk("%s\n", print_tainted());
+
+ printk("R0 : %08lx R1 : %08lx R2 : %08lx R3 : %08lx\n",
+ regs->regs[0],regs->regs[1],
+ regs->regs[2],regs->regs[3]);
+ printk("R4 : %08lx R5 : %08lx R6 : %08lx R7 : %08lx\n",
+ regs->regs[4],regs->regs[5],
+ regs->regs[6],regs->regs[7]);
+ printk("R8 : %08lx R9 : %08lx R10 : %08lx R11 : %08lx\n",
+ regs->regs[8],regs->regs[9],
+ regs->regs[10],regs->regs[11]);
+ printk("R12 : %08lx R13 : %08lx R14 : %08lx\n",
+ regs->regs[12],regs->regs[13],
+ regs->regs[14]);
+ printk("MACH: %08lx MACL: %08lx GBR : %08lx PR : %08lx\n",
+ regs->mach, regs->macl, regs->gbr, regs->pr);
+
+ /*
+ * If we're in kernel mode, dump the stack too..
+ */
+ if (!user_mode(regs)) {
+ extern void show_task(unsigned long *sp);
+ unsigned long sp = regs->regs[15];
+
+ show_task((unsigned long *)sp);
+ }
+}
+
+/*
+ * Create a kernel thread
+ */
+
+/*
+ * This is the mechanism for creating a new kernel thread.
+ *
+ */
+extern void kernel_thread_helper(void);
+__asm__(".align 5\n"
+ "kernel_thread_helper:\n\t"
+ "jsr @r5\n\t"
+ " nop\n\t"
+ "mov.l 1f, r1\n\t"
+ "jsr @r1\n\t"
+ " mov r0, r4\n\t"
+ ".align 2\n\t"
+ "1:.long do_exit");
+
+int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
+{ /* Don't use this in BL=1(cli). Or else, CPU resets! */
+ struct pt_regs regs;
+
+ memset(&regs, 0, sizeof(regs));
+ regs.regs[4] = (unsigned long) arg;
+ regs.regs[5] = (unsigned long) fn;
+
+ regs.pc = (unsigned long) kernel_thread_helper;
+ regs.sr = (1 << 30);
+
+ /* Ok, create the new process.. */
+ return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, &regs, 0, NULL, NULL);
+}
+
+/*
+ * Free current thread data structures etc..
+ */
+void exit_thread(void)
+{
+ if (current->thread.ubc_pc) {
+ current->thread.ubc_pc = 0;
+ ubc_usercnt -= 1;
+ }
+}
+
+void flush_thread(void)
+{
+#if defined(CONFIG_SH_FPU)
+ struct task_struct *tsk = current;
+ struct pt_regs *regs = (struct pt_regs *)
+ ((unsigned long)tsk->thread_info
+ + THREAD_SIZE - sizeof(struct pt_regs)
+ - sizeof(unsigned long));
+
+ /* Forget lazy FPU state */
+ clear_fpu(tsk, regs);
+ clear_used_math();
+#endif
+}
+
+void release_thread(struct task_struct *dead_task)
+{
+ /* do nothing */
+}
+
+/* Fill in the fpu structure for a core dump.. */
+int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu)
+{
+ int fpvalid = 0;
+
+#if defined(CONFIG_SH_FPU)
+ struct task_struct *tsk = current;
+
+ fpvalid = !!tsk_used_math(tsk);
+ if (fpvalid) {
+ unlazy_fpu(tsk, regs);
+ memcpy(fpu, &tsk->thread.fpu.hard, sizeof(*fpu));
+ }
+#endif
+
+ return fpvalid;
+}
+
+/*
+ * Capture the user space registers if the task is not running (in user space)
+ */
+int dump_task_regs(struct task_struct *tsk, elf_gregset_t *regs)
+{
+ struct pt_regs ptregs;
+
+ ptregs = *(struct pt_regs *)
+ ((unsigned long)tsk->thread_info + THREAD_SIZE
+ - sizeof(struct pt_regs)
+#ifdef CONFIG_SH_DSP
+ - sizeof(struct pt_dspregs)
+#endif
+ - sizeof(unsigned long));
+ elf_core_copy_regs(regs, &ptregs);
+
+ return 1;
+}
+
+int
+dump_task_fpu (struct task_struct *tsk, elf_fpregset_t *fpu)
+{
+ int fpvalid = 0;
+
+#if defined(CONFIG_SH_FPU)
+ fpvalid = !!tsk_used_math(tsk);
+ if (fpvalid) {
+ struct pt_regs *regs = (struct pt_regs *)
+ ((unsigned long)tsk->thread_info
+ + THREAD_SIZE - sizeof(struct pt_regs)
+ - sizeof(unsigned long));
+ unlazy_fpu(tsk, regs);
+ memcpy(fpu, &tsk->thread.fpu.hard, sizeof(*fpu));
+ }
+#endif
+
+ return fpvalid;
+}
+
+asmlinkage void ret_from_fork(void);
+
+int copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
+ unsigned long unused,
+ struct task_struct *p, struct pt_regs *regs)
+{
+ struct pt_regs *childregs;
+#if defined(CONFIG_SH_FPU)
+ struct task_struct *tsk = current;
+
+ unlazy_fpu(tsk, regs);
+ p->thread.fpu = tsk->thread.fpu;
+ copy_to_stopped_child_used_math(p);
+#endif
+
+ childregs = ((struct pt_regs *)
+ (THREAD_SIZE + (unsigned long) p->thread_info)
+#ifdef CONFIG_SH_DSP
+ - sizeof(struct pt_dspregs)
+#endif
+ - sizeof(unsigned long)) - 1;
+ *childregs = *regs;
+
+ if (user_mode(regs)) {
+ childregs->regs[15] = usp;
+ } else {
+ childregs->regs[15] = (unsigned long)p->thread_info + THREAD_SIZE;
+ }
+ if (clone_flags & CLONE_SETTLS) {
+ childregs->gbr = childregs->regs[0];
+ }
+ childregs->regs[0] = 0; /* Set return value for child */
+
+ p->thread.sp = (unsigned long) childregs;
+ p->thread.pc = (unsigned long) ret_from_fork;
+
+ p->thread.ubc_pc = 0;
+
+ return 0;
+}
+
+/*
+ * fill in the user structure for a core dump..
+ */
+void dump_thread(struct pt_regs * regs, struct user * dump)
+{
+ dump->magic = CMAGIC;
+ dump->start_code = current->mm->start_code;
+ dump->start_data = current->mm->start_data;
+ dump->start_stack = regs->regs[15] & ~(PAGE_SIZE - 1);
+ dump->u_tsize = (current->mm->end_code - dump->start_code) >> PAGE_SHIFT;
+ dump->u_dsize = (current->mm->brk + (PAGE_SIZE-1) - dump->start_data) >> PAGE_SHIFT;
+ dump->u_ssize = (current->mm->start_stack - dump->start_stack +
+ PAGE_SIZE - 1) >> PAGE_SHIFT;
+ /* Debug registers will come here. */
+
+ dump->regs = *regs;
+
+ dump->u_fpvalid = dump_fpu(regs, &dump->fpu);
+}
+
+/* Tracing by user break controller. */
+static void
+ubc_set_tracing(int asid, unsigned long pc)
+{
+ ctrl_outl(pc, UBC_BARA);
+
+ /* We don't have any ASID settings for the SH-2! */
+ if (cpu_data->type != CPU_SH7604)
+ ctrl_outb(asid, UBC_BASRA);
+
+ ctrl_outl(0, UBC_BAMRA);
+
+ if (cpu_data->type == CPU_SH7729) {
+ ctrl_outw(BBR_INST | BBR_READ | BBR_CPU, UBC_BBRA);
+ ctrl_outl(BRCR_PCBA | BRCR_PCTE, UBC_BRCR);
+ } else {
+ ctrl_outw(BBR_INST | BBR_READ, UBC_BBRA);
+ ctrl_outw(BRCR_PCBA, UBC_BRCR);
+ }
+}
+
+/*
+ * switch_to(x,y) should switch tasks from x to y.
+ *
+ */
+struct task_struct *__switch_to(struct task_struct *prev, struct task_struct *next)
+{
+#if defined(CONFIG_SH_FPU)
+ struct pt_regs *regs = (struct pt_regs *)
+ ((unsigned long)prev->thread_info
+ + THREAD_SIZE - sizeof(struct pt_regs)
+ - sizeof(unsigned long));
+ unlazy_fpu(prev, regs);
+#endif
+
+#ifdef CONFIG_PREEMPT
+ {
+ unsigned long flags;
+ struct pt_regs *regs;
+
+ local_irq_save(flags);
+ regs = (struct pt_regs *)
+ ((unsigned long)prev->thread_info
+ + THREAD_SIZE - sizeof(struct pt_regs)
+#ifdef CONFIG_SH_DSP
+ - sizeof(struct pt_dspregs)
+#endif
+ - sizeof(unsigned long));
+ if (user_mode(regs) && regs->regs[15] >= 0xc0000000) {
+ int offset = (int)regs->regs[15];
+
+ /* Reset stack pointer: clear critical region mark */
+ regs->regs[15] = regs->regs[1];
+ if (regs->pc < regs->regs[0])
+ /* Go to rewind point */
+ regs->pc = regs->regs[0] + offset;
+ }
+ local_irq_restore(flags);
+ }
+#endif
+
+ /*
+ * Restore the kernel mode register
+ * k7 (r7_bank1)
+ */
+ asm volatile("ldc %0, r7_bank"
+ : /* no output */
+ : "r" (next->thread_info));
+
+#ifdef CONFIG_MMU
+ /* If no tasks are using the UBC, we're done */
+ if (ubc_usercnt == 0)
+ /* If no tasks are using the UBC, we're done */;
+ else if (next->thread.ubc_pc && next->mm) {
+ ubc_set_tracing(next->mm->context & MMU_CONTEXT_ASID_MASK,
+ next->thread.ubc_pc);
+ } else {
+ ctrl_outw(0, UBC_BBRA);
+ ctrl_outw(0, UBC_BBRB);
+ }
+#endif
+
+ return prev;
+}
+
+asmlinkage int sys_fork(unsigned long r4, unsigned long r5,
+ unsigned long r6, unsigned long r7,
+ struct pt_regs regs)
+{
+#ifdef CONFIG_MMU
+ return do_fork(SIGCHLD, regs.regs[15], &regs, 0, NULL, NULL);
+#else
+ /* fork almost works, enough to trick you into looking elsewhere :-( */
+ return -EINVAL;
+#endif
+}
+
+asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp,
+ unsigned long parent_tidptr,
+ unsigned long child_tidptr,
+ struct pt_regs regs)
+{
+ if (!newsp)
+ newsp = regs.regs[15];
+ return do_fork(clone_flags, newsp, &regs, 0,
+ (int __user *)parent_tidptr, (int __user *)child_tidptr);
+}
+
+/*
+ * This is trivial, and on the face of it looks like it
+ * could equally well be done in user mode.
+ *
+ * Not so, for quite unobvious reasons - register pressure.
+ * In user mode vfork() cannot have a stack frame, and if
+ * done by calling the "clone()" system call directly, you
+ * do not have enough call-clobbered registers to hold all
+ * the information you need.
+ */
+asmlinkage int sys_vfork(unsigned long r4, unsigned long r5,
+ unsigned long r6, unsigned long r7,
+ struct pt_regs regs)
+{
+ return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs.regs[15], &regs,
+ 0, NULL, NULL);
+}
+
+/*
+ * sys_execve() executes a new program.
+ */
+asmlinkage int sys_execve(char *ufilename, char **uargv,
+ char **uenvp, unsigned long r7,
+ struct pt_regs regs)
+{
+ int error;
+ char *filename;
+
+ filename = getname((char __user *)ufilename);
+ error = PTR_ERR(filename);
+ if (IS_ERR(filename))
+ goto out;
+
+ error = do_execve(filename,
+ (char __user * __user *)uargv,
+ (char __user * __user *)uenvp,
+ &regs);
+ if (error == 0) {
+ task_lock(current);
+ current->ptrace &= ~PT_DTRACE;
+ task_unlock(current);
+ }
+ putname(filename);
+out:
+ return error;
+}
+
+unsigned long get_wchan(struct task_struct *p)
+{
+ unsigned long schedule_frame;
+ unsigned long pc;
+
+ if (!p || p == current || p->state == TASK_RUNNING)
+ return 0;
+
+ /*
+ * The same comment as on the Alpha applies here, too ...
+ */
+ pc = thread_saved_pc(p);
+ if (in_sched_functions(pc)) {
+ schedule_frame = ((unsigned long *)(long)p->thread.sp)[1];
+ return (unsigned long)((unsigned long *)schedule_frame)[1];
+ }
+ return pc;
+}
+
+asmlinkage void break_point_trap(unsigned long r4, unsigned long r5,
+ unsigned long r6, unsigned long r7,
+ struct pt_regs regs)
+{
+ /* Clear tracing. */
+ ctrl_outw(0, UBC_BBRA);
+ ctrl_outw(0, UBC_BBRB);
+ current->thread.ubc_pc = 0;
+ ubc_usercnt -= 1;
+
+ force_sig(SIGTRAP, current);
+}
+
+asmlinkage void break_point_trap_software(unsigned long r4, unsigned long r5,
+ unsigned long r6, unsigned long r7,
+ struct pt_regs regs)
+{
+ regs.pc -= 2;
+ force_sig(SIGTRAP, current);
+}
diff --git a/arch/sh/kernel/ptrace.c b/arch/sh/kernel/ptrace.c
new file mode 100644
index 000000000000..1b0dfb4d8ea4
--- /dev/null
+++ b/arch/sh/kernel/ptrace.c
@@ -0,0 +1,320 @@
+/*
+ * linux/arch/sh/kernel/ptrace.c
+ *
+ * Original x86 implementation:
+ * By Ross Biro 1/23/92
+ * edited by Linus Torvalds
+ *
+ * SuperH version: Copyright (C) 1999, 2000 Kaz Kojima & Niibe Yutaka
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/errno.h>
+#include <linux/ptrace.h>
+#include <linux/user.h>
+#include <linux/slab.h>
+#include <linux/security.h>
+
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/pgtable.h>
+#include <asm/system.h>
+#include <asm/processor.h>
+#include <asm/mmu_context.h>
+
+/*
+ * does not yet catch signals sent when the child dies.
+ * in exit.c or in signal.c.
+ */
+
+/*
+ * This routine will get a word off of the process kernel stack.
+ */
+static inline int get_stack_long(struct task_struct *task, int offset)
+{
+ unsigned char *stack;
+
+ stack = (unsigned char *)
+ task->thread_info + THREAD_SIZE - sizeof(struct pt_regs)
+#ifdef CONFIG_SH_DSP
+ - sizeof(struct pt_dspregs)
+#endif
+ - sizeof(unsigned long);
+ stack += offset;
+ return (*((int *)stack));
+}
+
+/*
+ * This routine will put a word on the process kernel stack.
+ */
+static inline int put_stack_long(struct task_struct *task, int offset,
+ unsigned long data)
+{
+ unsigned char *stack;
+
+ stack = (unsigned char *)
+ task->thread_info + THREAD_SIZE - sizeof(struct pt_regs)
+#ifdef CONFIG_SH_DSP
+ - sizeof(struct pt_dspregs)
+#endif
+ - sizeof(unsigned long);
+ stack += offset;
+ *(unsigned long *) stack = data;
+ return 0;
+}
+
+/*
+ * Called by kernel/ptrace.c when detaching..
+ *
+ * Make sure single step bits etc are not set.
+ */
+void ptrace_disable(struct task_struct *child)
+{
+ /* nothing to do.. */
+}
+
+asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
+{
+ struct task_struct *child;
+ struct user * dummy = NULL;
+ int ret;
+
+ lock_kernel();
+ ret = -EPERM;
+ if (request == PTRACE_TRACEME) {
+ /* are we already being traced? */
+ if (current->ptrace & PT_PTRACED)
+ goto out;
+ ret = security_ptrace(current->parent, current);
+ if (ret)
+ goto out;
+ /* set the ptrace bit in the process flags. */
+ current->ptrace |= PT_PTRACED;
+ ret = 0;
+ goto out;
+ }
+ ret = -ESRCH;
+ read_lock(&tasklist_lock);
+ child = find_task_by_pid(pid);
+ if (child)
+ get_task_struct(child);
+ read_unlock(&tasklist_lock);
+ if (!child)
+ goto out;
+
+ ret = -EPERM;
+ if (pid == 1) /* you may not mess with init */
+ goto out_tsk;
+
+ if (request == PTRACE_ATTACH) {
+ ret = ptrace_attach(child);
+ goto out_tsk;
+ }
+
+ ret = ptrace_check_attach(child, request == PTRACE_KILL);
+ if (ret < 0)
+ goto out_tsk;
+
+ switch (request) {
+ /* when I and D space are separate, these will need to be fixed. */
+ case PTRACE_PEEKTEXT: /* read word at location addr. */
+ case PTRACE_PEEKDATA: {
+ unsigned long tmp;
+ int copied;
+
+ copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
+ ret = -EIO;
+ if (copied != sizeof(tmp))
+ break;
+ ret = put_user(tmp,(unsigned long *) data);
+ break;
+ }
+
+ /* read the word at location addr in the USER area. */
+ case PTRACE_PEEKUSR: {
+ unsigned long tmp;
+
+ ret = -EIO;
+ if ((addr & 3) || addr < 0 ||
+ addr > sizeof(struct user) - 3)
+ break;
+
+ if (addr < sizeof(struct pt_regs))
+ tmp = get_stack_long(child, addr);
+ else if (addr >= (long) &dummy->fpu &&
+ addr < (long) &dummy->u_fpvalid) {
+ if (!tsk_used_math(child)) {
+ if (addr == (long)&dummy->fpu.fpscr)
+ tmp = FPSCR_INIT;
+ else
+ tmp = 0;
+ } else
+ tmp = ((long *)&child->thread.fpu)
+ [(addr - (long)&dummy->fpu) >> 2];
+ } else if (addr == (long) &dummy->u_fpvalid)
+ tmp = !!tsk_used_math(child);
+ else
+ tmp = 0;
+ ret = put_user(tmp, (unsigned long *)data);
+ break;
+ }
+
+ /* when I and D space are separate, this will have to be fixed. */
+ case PTRACE_POKETEXT: /* write the word at location addr. */
+ case PTRACE_POKEDATA:
+ ret = 0;
+ if (access_process_vm(child, addr, &data, sizeof(data), 1) == sizeof(data))
+ break;
+ ret = -EIO;
+ break;
+
+ case PTRACE_POKEUSR: /* write the word at location addr in the USER area */
+ ret = -EIO;
+ if ((addr & 3) || addr < 0 ||
+ addr > sizeof(struct user) - 3)
+ break;
+
+ if (addr < sizeof(struct pt_regs))
+ ret = put_stack_long(child, addr, data);
+ else if (addr >= (long) &dummy->fpu &&
+ addr < (long) &dummy->u_fpvalid) {
+ set_stopped_child_used_math(child);
+ ((long *)&child->thread.fpu)
+ [(addr - (long)&dummy->fpu) >> 2] = data;
+ ret = 0;
+ } else if (addr == (long) &dummy->u_fpvalid) {
+ conditional_stopped_child_used_math(data, child);
+ ret = 0;
+ }
+ break;
+
+ case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
+ case PTRACE_CONT: { /* restart after signal. */
+ ret = -EIO;
+ if ((unsigned long) data > _NSIG)
+ break;
+ if (request == PTRACE_SYSCALL)
+ set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
+ else
+ clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
+ child->exit_code = data;
+ wake_up_process(child);
+ ret = 0;
+ break;
+ }
+
+/*
+ * make the child exit. Best I can do is send it a sigkill.
+ * perhaps it should be put in the status that it wants to
+ * exit.
+ */
+ case PTRACE_KILL: {
+ ret = 0;
+ if (child->exit_state == EXIT_ZOMBIE) /* already dead */
+ break;
+ child->exit_code = SIGKILL;
+ wake_up_process(child);
+ break;
+ }
+
+ case PTRACE_SINGLESTEP: { /* set the trap flag. */
+ long pc;
+ struct pt_regs *dummy = NULL;
+
+ ret = -EIO;
+ if ((unsigned long) data > _NSIG)
+ break;
+ clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
+ if ((child->ptrace & PT_DTRACE) == 0) {
+ /* Spurious delayed TF traps may occur */
+ child->ptrace |= PT_DTRACE;
+ }
+
+ pc = get_stack_long(child, (long)&dummy->pc);
+
+ /* Next scheduling will set up UBC */
+ if (child->thread.ubc_pc == 0)
+ ubc_usercnt += 1;
+ child->thread.ubc_pc = pc;
+
+ child->exit_code = data;
+ /* give it a chance to run. */
+ wake_up_process(child);
+ ret = 0;
+ break;
+ }
+
+ case PTRACE_DETACH: /* detach a process that was attached. */
+ ret = ptrace_detach(child, data);
+ break;
+
+#ifdef CONFIG_SH_DSP
+ case PTRACE_GETDSPREGS: {
+ unsigned long dp;
+
+ ret = -EIO;
+ dp = ((unsigned long) child) + THREAD_SIZE -
+ sizeof(struct pt_dspregs);
+ if (*((int *) (dp - 4)) == SR_FD) {
+ copy_to_user(addr, (void *) dp,
+ sizeof(struct pt_dspregs));
+ ret = 0;
+ }
+ break;
+ }
+
+ case PTRACE_SETDSPREGS: {
+ unsigned long dp;
+ int i;
+
+ ret = -EIO;
+ dp = ((unsigned long) child) + THREAD_SIZE -
+ sizeof(struct pt_dspregs);
+ if (*((int *) (dp - 4)) == SR_FD) {
+ copy_from_user((void *) dp, addr,
+ sizeof(struct pt_dspregs));
+ ret = 0;
+ }
+ break;
+ }
+#endif
+ default:
+ ret = ptrace_request(child, request, addr, data);
+ break;
+ }
+out_tsk:
+ put_task_struct(child);
+out:
+ unlock_kernel();
+ return ret;
+}
+
+asmlinkage void do_syscall_trace(void)
+{
+ struct task_struct *tsk = current;
+
+ if (!test_thread_flag(TIF_SYSCALL_TRACE))
+ return;
+ if (!(tsk->ptrace & PT_PTRACED))
+ return;
+ /* the 0x80 provides a way for the tracing parent to distinguish
+ between a syscall stop and SIGTRAP delivery */
+ ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
+ ? 0x80 : 0));
+
+ /*
+ * this isn't the same as continuing with a signal, but it will do
+ * for normal use. strace only continues with a signal if the
+ * stopping signal is not SIGTRAP. -brl
+ */
+ if (tsk->exit_code) {
+ send_sig(tsk->exit_code, tsk, 1);
+ tsk->exit_code = 0;
+ }
+}
diff --git a/arch/sh/kernel/semaphore.c b/arch/sh/kernel/semaphore.c
new file mode 100644
index 000000000000..a3c24dcbf01d
--- /dev/null
+++ b/arch/sh/kernel/semaphore.c
@@ -0,0 +1,139 @@
+/*
+ * 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/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);
+}
diff --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c
new file mode 100644
index 000000000000..25b9d9ebe858
--- /dev/null
+++ b/arch/sh/kernel/setup.c
@@ -0,0 +1,649 @@
+/* $Id: setup.c,v 1.30 2003/10/13 07:21:19 lethal Exp $
+ *
+ * linux/arch/sh/kernel/setup.c
+ *
+ * Copyright (C) 1999 Niibe Yutaka
+ * Copyright (C) 2002, 2003 Paul Mundt
+ */
+
+/*
+ * This file handles the architecture-dependent parts of initialization
+ */
+
+#include <linux/tty.h>
+#include <linux/ioport.h>
+#include <linux/init.h>
+#include <linux/initrd.h>
+#include <linux/bootmem.h>
+#include <linux/console.h>
+#include <linux/seq_file.h>
+#include <linux/root_dev.h>
+#include <linux/utsname.h>
+#include <linux/cpu.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#include <asm/io_generic.h>
+#include <asm/sections.h>
+#include <asm/irq.h>
+#include <asm/setup.h>
+
+#ifdef CONFIG_SH_KGDB
+#include <asm/kgdb.h>
+static int kgdb_parse_options(char *options);
+#endif
+extern void * __rd_start, * __rd_end;
+/*
+ * Machine setup..
+ */
+
+/*
+ * Initialize loops_per_jiffy as 10000000 (1000MIPS).
+ * This value will be used at the very early stage of serial setup.
+ * The bigger value means no problem.
+ */
+struct sh_cpuinfo boot_cpu_data = { CPU_SH_NONE, 0, 10000000, };
+struct screen_info screen_info;
+
+#if defined(CONFIG_SH_UNKNOWN)
+struct sh_machine_vector sh_mv;
+#endif
+
+/* We need this to satisfy some external references. */
+struct screen_info screen_info = {
+ 0, 25, /* orig-x, orig-y */
+ 0, /* unused */
+ 0, /* orig-video-page */
+ 0, /* orig-video-mode */
+ 80, /* orig-video-cols */
+ 0,0,0, /* ega_ax, ega_bx, ega_cx */
+ 25, /* orig-video-lines */
+ 0, /* orig-video-isVGA */
+ 16 /* orig-video-points */
+};
+
+extern void platform_setup(void);
+extern char *get_system_type(void);
+extern int root_mountflags;
+
+#define MV_NAME_SIZE 32
+
+static struct sh_machine_vector* __init get_mv_byname(const char* name);
+
+/*
+ * This is set up by the setup-routine at boot-time
+ */
+#define PARAM ((unsigned char *)empty_zero_page)
+
+#define MOUNT_ROOT_RDONLY (*(unsigned long *) (PARAM+0x000))
+#define RAMDISK_FLAGS (*(unsigned long *) (PARAM+0x004))
+#define ORIG_ROOT_DEV (*(unsigned long *) (PARAM+0x008))
+#define LOADER_TYPE (*(unsigned long *) (PARAM+0x00c))
+#define INITRD_START (*(unsigned long *) (PARAM+0x010))
+#define INITRD_SIZE (*(unsigned long *) (PARAM+0x014))
+/* ... */
+#define COMMAND_LINE ((char *) (PARAM+0x100))
+
+#define RAMDISK_IMAGE_START_MASK 0x07FF
+#define RAMDISK_PROMPT_FLAG 0x8000
+#define RAMDISK_LOAD_FLAG 0x4000
+
+static char command_line[COMMAND_LINE_SIZE] = { 0, };
+
+struct resource standard_io_resources[] = {
+ { "dma1", 0x00, 0x1f },
+ { "pic1", 0x20, 0x3f },
+ { "timer", 0x40, 0x5f },
+ { "keyboard", 0x60, 0x6f },
+ { "dma page reg", 0x80, 0x8f },
+ { "pic2", 0xa0, 0xbf },
+ { "dma2", 0xc0, 0xdf },
+ { "fpu", 0xf0, 0xff }
+};
+
+#define STANDARD_IO_RESOURCES (sizeof(standard_io_resources)/sizeof(struct resource))
+
+/* System RAM - interrupted by the 640kB-1M hole */
+#define code_resource (ram_resources[3])
+#define data_resource (ram_resources[4])
+static struct resource ram_resources[] = {
+ { "System RAM", 0x000000, 0x09ffff, IORESOURCE_BUSY },
+ { "System RAM", 0x100000, 0x100000, IORESOURCE_BUSY },
+ { "Video RAM area", 0x0a0000, 0x0bffff },
+ { "Kernel code", 0x100000, 0 },
+ { "Kernel data", 0, 0 }
+};
+
+unsigned long memory_start, memory_end;
+
+static inline void parse_cmdline (char ** cmdline_p, char mv_name[MV_NAME_SIZE],
+ struct sh_machine_vector** mvp,
+ unsigned long *mv_io_base,
+ int *mv_mmio_enable)
+{
+ char c = ' ', *to = command_line, *from = COMMAND_LINE;
+ int len = 0;
+
+ /* Save unparsed command line copy for /proc/cmdline */
+ memcpy(saved_command_line, COMMAND_LINE, COMMAND_LINE_SIZE);
+ saved_command_line[COMMAND_LINE_SIZE-1] = '\0';
+
+ memory_start = (unsigned long)PAGE_OFFSET+__MEMORY_START;
+ memory_end = memory_start + __MEMORY_SIZE;
+
+ for (;;) {
+ /*
+ * "mem=XXX[kKmM]" defines a size of memory.
+ */
+ if (c == ' ' && !memcmp(from, "mem=", 4)) {
+ if (to != command_line)
+ to--;
+ {
+ unsigned long mem_size;
+
+ mem_size = memparse(from+4, &from);
+ memory_end = memory_start + mem_size;
+ }
+ }
+ if (c == ' ' && !memcmp(from, "sh_mv=", 6)) {
+ char* mv_end;
+ char* mv_comma;
+ int mv_len;
+ if (to != command_line)
+ to--;
+ from += 6;
+ mv_end = strchr(from, ' ');
+ if (mv_end == NULL)
+ mv_end = from + strlen(from);
+
+ mv_comma = strchr(from, ',');
+ if ((mv_comma != NULL) && (mv_comma < mv_end)) {
+ int ints[3];
+ get_options(mv_comma+1, ARRAY_SIZE(ints), ints);
+ *mv_io_base = ints[1];
+ *mv_mmio_enable = ints[2];
+ mv_len = mv_comma - from;
+ } else {
+ mv_len = mv_end - from;
+ }
+ if (mv_len > (MV_NAME_SIZE-1))
+ mv_len = MV_NAME_SIZE-1;
+ memcpy(mv_name, from, mv_len);
+ mv_name[mv_len] = '\0';
+ from = mv_end;
+
+ *mvp = get_mv_byname(mv_name);
+ }
+ c = *(from++);
+ if (!c)
+ break;
+ if (COMMAND_LINE_SIZE <= ++len)
+ break;
+ *(to++) = c;
+ }
+ *to = '\0';
+ *cmdline_p = command_line;
+}
+
+static int __init sh_mv_setup(char **cmdline_p)
+{
+#if defined(CONFIG_SH_UNKNOWN)
+ extern struct sh_machine_vector mv_unknown;
+#endif
+ struct sh_machine_vector *mv = NULL;
+ char mv_name[MV_NAME_SIZE] = "";
+ unsigned long mv_io_base = 0;
+ int mv_mmio_enable = 0;
+
+ parse_cmdline(cmdline_p, mv_name, &mv, &mv_io_base, &mv_mmio_enable);
+
+#ifdef CONFIG_SH_GENERIC
+ if (mv == NULL) {
+ mv = &mv_unknown;
+ if (*mv_name != '\0') {
+ printk("Warning: Unsupported machine %s, using unknown\n",
+ mv_name);
+ }
+ }
+ sh_mv = *mv;
+#endif
+#ifdef CONFIG_SH_UNKNOWN
+ sh_mv = mv_unknown;
+#endif
+
+ /*
+ * Manually walk the vec, fill in anything that the board hasn't yet
+ * by hand, wrapping to the generic implementation.
+ */
+#define mv_set(elem) do { \
+ if (!sh_mv.mv_##elem) \
+ sh_mv.mv_##elem = generic_##elem; \
+} while (0)
+
+ mv_set(inb); mv_set(inw); mv_set(inl);
+ mv_set(outb); mv_set(outw); mv_set(outl);
+
+ mv_set(inb_p); mv_set(inw_p); mv_set(inl_p);
+ mv_set(outb_p); mv_set(outw_p); mv_set(outl_p);
+
+ mv_set(insb); mv_set(insw); mv_set(insl);
+ mv_set(outsb); mv_set(outsw); mv_set(outsl);
+
+ mv_set(readb); mv_set(readw); mv_set(readl);
+ mv_set(writeb); mv_set(writew); mv_set(writel);
+
+ mv_set(ioremap);
+ mv_set(iounmap);
+
+ mv_set(isa_port2addr);
+ mv_set(irq_demux);
+
+#ifdef CONFIG_SH_UNKNOWN
+ __set_io_port_base(mv_io_base);
+#endif
+
+ return 0;
+}
+
+void __init setup_arch(char **cmdline_p)
+{
+ unsigned long bootmap_size;
+ unsigned long start_pfn, max_pfn, max_low_pfn;
+
+#ifdef CONFIG_EARLY_PRINTK
+ extern void enable_early_printk(void);
+
+ enable_early_printk();
+#endif
+#ifdef CONFIG_CMDLINE_BOOL
+ strcpy(COMMAND_LINE, CONFIG_CMDLINE);
+#endif
+
+ ROOT_DEV = old_decode_dev(ORIG_ROOT_DEV);
+
+#ifdef CONFIG_BLK_DEV_RAM
+ rd_image_start = RAMDISK_FLAGS & RAMDISK_IMAGE_START_MASK;
+ rd_prompt = ((RAMDISK_FLAGS & RAMDISK_PROMPT_FLAG) != 0);
+ rd_doload = ((RAMDISK_FLAGS & RAMDISK_LOAD_FLAG) != 0);
+#endif
+
+ if (!MOUNT_ROOT_RDONLY)
+ root_mountflags &= ~MS_RDONLY;
+ init_mm.start_code = (unsigned long) _text;
+ init_mm.end_code = (unsigned long) _etext;
+ init_mm.end_data = (unsigned long) _edata;
+ init_mm.brk = (unsigned long) _end;
+
+ code_resource.start = virt_to_bus(_text);
+ code_resource.end = virt_to_bus(_etext)-1;
+ data_resource.start = virt_to_bus(_etext);
+ data_resource.end = virt_to_bus(_edata)-1;
+
+ sh_mv_setup(cmdline_p);
+
+#define PFN_UP(x) (((x) + PAGE_SIZE-1) >> PAGE_SHIFT)
+#define PFN_DOWN(x) ((x) >> PAGE_SHIFT)
+#define PFN_PHYS(x) ((x) << PAGE_SHIFT)
+
+#ifdef CONFIG_DISCONTIGMEM
+ NODE_DATA(0)->bdata = &discontig_node_bdata[0];
+ NODE_DATA(1)->bdata = &discontig_node_bdata[1];
+
+ bootmap_size = init_bootmem_node(NODE_DATA(1),
+ PFN_UP(__MEMORY_START_2ND),
+ PFN_UP(__MEMORY_START_2ND),
+ PFN_DOWN(__MEMORY_START_2ND+__MEMORY_SIZE_2ND));
+ free_bootmem_node(NODE_DATA(1), __MEMORY_START_2ND, __MEMORY_SIZE_2ND);
+ reserve_bootmem_node(NODE_DATA(1), __MEMORY_START_2ND, bootmap_size);
+#endif
+
+ /*
+ * Find the highest page frame number we have available
+ */
+ max_pfn = PFN_DOWN(__pa(memory_end));
+
+ /*
+ * Determine low and high memory ranges:
+ */
+ max_low_pfn = max_pfn;
+
+ /*
+ * Partially used pages are not usable - thus
+ * we are rounding upwards:
+ */
+ start_pfn = PFN_UP(__pa(_end));
+
+ /*
+ * Find a proper area for the bootmem bitmap. After this
+ * bootstrap step all allocations (until the page allocator
+ * is intact) must be done via bootmem_alloc().
+ */
+ bootmap_size = init_bootmem_node(NODE_DATA(0), start_pfn,
+ __MEMORY_START>>PAGE_SHIFT,
+ max_low_pfn);
+ /*
+ * Register fully available low RAM pages with the bootmem allocator.
+ */
+ {
+ unsigned long curr_pfn, last_pfn, pages;
+
+ /*
+ * We are rounding up the start address of usable memory:
+ */
+ curr_pfn = PFN_UP(__MEMORY_START);
+ /*
+ * ... and at the end of the usable range downwards:
+ */
+ last_pfn = PFN_DOWN(__pa(memory_end));
+
+ if (last_pfn > max_low_pfn)
+ last_pfn = max_low_pfn;
+
+ pages = last_pfn - curr_pfn;
+ free_bootmem_node(NODE_DATA(0), PFN_PHYS(curr_pfn),
+ PFN_PHYS(pages));
+ }
+
+ /*
+ * Reserve the kernel text and
+ * Reserve the bootmem bitmap. We do this in two steps (first step
+ * was init_bootmem()), because this catches the (definitely buggy)
+ * case of us accidentally initializing the bootmem allocator with
+ * an invalid RAM area.
+ */
+ reserve_bootmem_node(NODE_DATA(0), __MEMORY_START+PAGE_SIZE,
+ (PFN_PHYS(start_pfn)+bootmap_size+PAGE_SIZE-1)-__MEMORY_START);
+
+ /*
+ * reserve physical page 0 - it's a special BIOS page on many boxes,
+ * enabling clean reboots, SMP operation, laptop functions.
+ */
+ reserve_bootmem_node(NODE_DATA(0), __MEMORY_START, PAGE_SIZE);
+
+#ifdef CONFIG_BLK_DEV_INITRD
+ ROOT_DEV = MKDEV(RAMDISK_MAJOR, 0);
+ if (&__rd_start != &__rd_end) {
+ LOADER_TYPE = 1;
+ INITRD_START = PHYSADDR((unsigned long)&__rd_start) - __MEMORY_START;
+ INITRD_SIZE = (unsigned long)&__rd_end - (unsigned long)&__rd_start;
+ }
+
+ if (LOADER_TYPE && INITRD_START) {
+ if (INITRD_START + INITRD_SIZE <= (max_low_pfn << PAGE_SHIFT)) {
+ reserve_bootmem_node(NODE_DATA(0), INITRD_START+__MEMORY_START, INITRD_SIZE);
+ initrd_start =
+ INITRD_START ? INITRD_START + PAGE_OFFSET + __MEMORY_START : 0;
+ initrd_end = initrd_start + INITRD_SIZE;
+ } else {
+ printk("initrd extends beyond end of memory "
+ "(0x%08lx > 0x%08lx)\ndisabling initrd\n",
+ INITRD_START + INITRD_SIZE,
+ max_low_pfn << PAGE_SHIFT);
+ initrd_start = 0;
+ }
+ }
+#endif
+
+#ifdef CONFIG_DUMMY_CONSOLE
+ conswitchp = &dummy_con;
+#endif
+
+ /* Perform the machine specific initialisation */
+ platform_setup();
+
+ paging_init();
+}
+
+struct sh_machine_vector* __init get_mv_byname(const char* name)
+{
+ extern int strcasecmp(const char *, const char *);
+ extern long __machvec_start, __machvec_end;
+ struct sh_machine_vector *all_vecs =
+ (struct sh_machine_vector *)&__machvec_start;
+
+ int i, n = ((unsigned long)&__machvec_end
+ - (unsigned long)&__machvec_start)/
+ sizeof(struct sh_machine_vector);
+
+ for (i = 0; i < n; ++i) {
+ struct sh_machine_vector *mv = &all_vecs[i];
+ if (mv == NULL)
+ continue;
+ if (strcasecmp(name, get_system_type()) == 0) {
+ return mv;
+ }
+ }
+ return NULL;
+}
+
+static struct cpu cpu[NR_CPUS];
+
+static int __init topology_init(void)
+{
+ int cpu_id;
+
+ for (cpu_id = 0; cpu_id < NR_CPUS; cpu_id++)
+ if (cpu_possible(cpu_id))
+ register_cpu(&cpu[cpu_id], cpu_id, NULL);
+
+ return 0;
+}
+
+subsys_initcall(topology_init);
+
+static const char *cpu_name[] = {
+ [CPU_SH7604] = "SH7604",
+ [CPU_SH7705] = "SH7705",
+ [CPU_SH7708] = "SH7708",
+ [CPU_SH7729] = "SH7729",
+ [CPU_SH7300] = "SH7300",
+ [CPU_SH7750] = "SH7750",
+ [CPU_SH7750S] = "SH7750S",
+ [CPU_SH7750R] = "SH7750R",
+ [CPU_SH7751] = "SH7751",
+ [CPU_SH7751R] = "SH7751R",
+ [CPU_SH7760] = "SH7760",
+ [CPU_SH73180] = "SH73180",
+ [CPU_ST40RA] = "ST40RA",
+ [CPU_ST40GX1] = "ST40GX1",
+ [CPU_SH4_202] = "SH4-202",
+ [CPU_SH4_501] = "SH4-501",
+ [CPU_SH_NONE] = "Unknown"
+};
+
+const char *get_cpu_subtype(void)
+{
+ return cpu_name[boot_cpu_data.type];
+}
+
+#ifdef CONFIG_PROC_FS
+static const char *cpu_flags[] = {
+ "none", "fpu", "p2flush", "mmuassoc", "dsp", "perfctr",
+};
+
+static void show_cpuflags(struct seq_file *m)
+{
+ unsigned long i;
+
+ seq_printf(m, "cpu flags\t:");
+
+ if (!cpu_data->flags) {
+ seq_printf(m, " %s\n", cpu_flags[0]);
+ return;
+ }
+
+ for (i = 0; i < cpu_data->flags; i++)
+ if ((cpu_data->flags & (1 << i)))
+ seq_printf(m, " %s", cpu_flags[i+1]);
+
+ seq_printf(m, "\n");
+}
+
+static void show_cacheinfo(struct seq_file *m, const char *type, struct cache_info info)
+{
+ unsigned int cache_size;
+
+ cache_size = info.ways * info.sets * info.linesz;
+
+ seq_printf(m, "%s size\t: %dKiB\n", type, cache_size >> 10);
+}
+
+/*
+ * Get CPU information for use by the procfs.
+ */
+static int show_cpuinfo(struct seq_file *m, void *v)
+{
+ unsigned int cpu = smp_processor_id();
+
+ if (!cpu && cpu_online(cpu))
+ seq_printf(m, "machine\t\t: %s\n", get_system_type());
+
+ seq_printf(m, "processor\t: %d\n", cpu);
+ seq_printf(m, "cpu family\t: %s\n", system_utsname.machine);
+ seq_printf(m, "cpu type\t: %s\n", get_cpu_subtype());
+
+ show_cpuflags(m);
+
+ seq_printf(m, "cache type\t: ");
+
+ /*
+ * Check for what type of cache we have, we support both the
+ * unified cache on the SH-2 and SH-3, as well as the harvard
+ * style cache on the SH-4.
+ */
+ if (test_bit(SH_CACHE_COMBINED, &(boot_cpu_data.icache.flags))) {
+ seq_printf(m, "unified\n");
+ show_cacheinfo(m, "cache", boot_cpu_data.icache);
+ } else {
+ seq_printf(m, "split (harvard)\n");
+ show_cacheinfo(m, "icache", boot_cpu_data.icache);
+ show_cacheinfo(m, "dcache", boot_cpu_data.dcache);
+ }
+
+ seq_printf(m, "bogomips\t: %lu.%02lu\n",
+ boot_cpu_data.loops_per_jiffy/(500000/HZ),
+ (boot_cpu_data.loops_per_jiffy/(5000/HZ)) % 100);
+
+#define PRINT_CLOCK(name, value) \
+ seq_printf(m, name " clock\t: %d.%02dMHz\n", \
+ ((value) / 1000000), ((value) % 1000000)/10000)
+
+ PRINT_CLOCK("cpu", boot_cpu_data.cpu_clock);
+ PRINT_CLOCK("bus", boot_cpu_data.bus_clock);
+#ifdef CONFIG_CPU_SUBTYPE_ST40STB1
+ PRINT_CLOCK("memory", boot_cpu_data.memory_clock);
+#endif
+ PRINT_CLOCK("module", boot_cpu_data.module_clock);
+
+ return 0;
+}
+
+
+static void *c_start(struct seq_file *m, loff_t *pos)
+{
+ return *pos < NR_CPUS ? cpu_data + *pos : NULL;
+}
+static void *c_next(struct seq_file *m, void *v, loff_t *pos)
+{
+ ++*pos;
+ return c_start(m, pos);
+}
+static void c_stop(struct seq_file *m, void *v)
+{
+}
+struct seq_operations cpuinfo_op = {
+ .start = c_start,
+ .next = c_next,
+ .stop = c_stop,
+ .show = show_cpuinfo,
+};
+#endif /* CONFIG_PROC_FS */
+
+#ifdef CONFIG_SH_KGDB
+/*
+ * Parse command-line kgdb options. By default KGDB is enabled,
+ * entered on error (or other action) using default serial info.
+ * The command-line option can include a serial port specification
+ * and an action to override default or configured behavior.
+ */
+struct kgdb_sermap kgdb_sci_sermap =
+{ "ttySC", 5, kgdb_sci_setup, NULL };
+
+struct kgdb_sermap *kgdb_serlist = &kgdb_sci_sermap;
+struct kgdb_sermap *kgdb_porttype = &kgdb_sci_sermap;
+
+void kgdb_register_sermap(struct kgdb_sermap *map)
+{
+ struct kgdb_sermap *last;
+
+ for (last = kgdb_serlist; last->next; last = last->next)
+ ;
+ last->next = map;
+ if (!map->namelen) {
+ map->namelen = strlen(map->name);
+ }
+}
+
+static int __init kgdb_parse_options(char *options)
+{
+ char c;
+ int baud;
+
+ /* Check for port spec (or use default) */
+
+ /* Determine port type and instance */
+ if (!memcmp(options, "tty", 3)) {
+ struct kgdb_sermap *map = kgdb_serlist;
+
+ while (map && memcmp(options, map->name, map->namelen))
+ map = map->next;
+
+ if (!map) {
+ KGDB_PRINTK("unknown port spec in %s\n", options);
+ return -1;
+ }
+
+ kgdb_porttype = map;
+ kgdb_serial_setup = map->setup_fn;
+ kgdb_portnum = options[map->namelen] - '0';
+ options += map->namelen + 1;
+
+ options = (*options == ',') ? options+1 : options;
+
+ /* Read optional parameters (baud/parity/bits) */
+ baud = simple_strtoul(options, &options, 10);
+ if (baud != 0) {
+ kgdb_baud = baud;
+
+ c = toupper(*options);
+ if (c == 'E' || c == 'O' || c == 'N') {
+ kgdb_parity = c;
+ options++;
+ }
+
+ c = *options;
+ if (c == '7' || c == '8') {
+ kgdb_bits = c;
+ options++;
+ }
+ options = (*options == ',') ? options+1 : options;
+ }
+ }
+
+ /* Check for action specification */
+ if (!memcmp(options, "halt", 4)) {
+ kgdb_halt = 1;
+ options += 4;
+ } else if (!memcmp(options, "disabled", 8)) {
+ kgdb_enabled = 0;
+ options += 8;
+ }
+
+ if (*options) {
+ KGDB_PRINTK("ignored unknown options: %s\n", options);
+ return 0;
+ }
+ return 1;
+}
+__setup("kgdb=", kgdb_parse_options);
+#endif /* CONFIG_SH_KGDB */
+
diff --git a/arch/sh/kernel/sh_bios.c b/arch/sh/kernel/sh_bios.c
new file mode 100644
index 000000000000..5b53e10bb9cd
--- /dev/null
+++ b/arch/sh/kernel/sh_bios.c
@@ -0,0 +1,75 @@
+/*
+ * linux/arch/sh/kernel/sh_bios.c
+ * C interface for trapping into the standard LinuxSH BIOS.
+ *
+ * Copyright (C) 2000 Greg Banks, Mitch Davis
+ *
+ */
+
+#include <asm/sh_bios.h>
+
+#define BIOS_CALL_CONSOLE_WRITE 0
+#define BIOS_CALL_READ_BLOCK 1
+#define BIOS_CALL_ETH_NODE_ADDR 10
+#define BIOS_CALL_SHUTDOWN 11
+#define BIOS_CALL_CHAR_OUT 0x1f /* TODO: hack */
+#define BIOS_CALL_GDB_GET_MODE_PTR 0xfe
+#define BIOS_CALL_GDB_DETACH 0xff
+
+static __inline__ long sh_bios_call(long func, long arg0, long arg1, long arg2, long arg3)
+{
+ register long r0 __asm__("r0") = func;
+ register long r4 __asm__("r4") = arg0;
+ register long r5 __asm__("r5") = arg1;
+ register long r6 __asm__("r6") = arg2;
+ register long r7 __asm__("r7") = arg3;
+ __asm__ __volatile__("trapa #0x3f"
+ : "=z" (r0)
+ : "0" (r0), "r" (r4), "r" (r5), "r" (r6), "r" (r7)
+ : "memory");
+ return r0;
+}
+
+
+void sh_bios_console_write(const char *buf, unsigned int len)
+{
+ sh_bios_call(BIOS_CALL_CONSOLE_WRITE, (long)buf, (long)len, 0, 0);
+}
+
+
+void sh_bios_char_out(char ch)
+{
+ sh_bios_call(BIOS_CALL_CHAR_OUT, ch, 0, 0, 0);
+}
+
+
+int sh_bios_in_gdb_mode(void)
+{
+ static char queried = 0;
+ static char *gdb_mode_p = 0;
+
+ if (!queried)
+ {
+ /* Query the gdb stub for address of its gdb mode variable */
+ long r = sh_bios_call(BIOS_CALL_GDB_GET_MODE_PTR, 0, 0, 0, 0);
+ if (r != ~0) /* BIOS returns -1 for unknown function */
+ gdb_mode_p = (char *)r;
+ queried = 1;
+ }
+ return (gdb_mode_p != 0 ? *gdb_mode_p : 0);
+}
+
+void sh_bios_gdb_detach(void)
+{
+ sh_bios_call(BIOS_CALL_GDB_DETACH, 0, 0, 0, 0);
+}
+
+void sh_bios_get_node_addr (unsigned char *node_addr)
+{
+ sh_bios_call(BIOS_CALL_ETH_NODE_ADDR, 0, (long)node_addr, 0, 0);
+}
+
+void sh_bios_shutdown(unsigned int how)
+{
+ sh_bios_call(BIOS_CALL_SHUTDOWN, how, 0, 0, 0);
+}
diff --git a/arch/sh/kernel/sh_ksyms.c b/arch/sh/kernel/sh_ksyms.c
new file mode 100644
index 000000000000..6954fd62470a
--- /dev/null
+++ b/arch/sh/kernel/sh_ksyms.c
@@ -0,0 +1,126 @@
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/smp.h>
+#include <linux/user.h>
+#include <linux/elfcore.h>
+#include <linux/sched.h>
+#include <linux/in6.h>
+#include <linux/interrupt.h>
+#include <linux/smp_lock.h>
+#include <linux/vmalloc.h>
+#include <linux/pci.h>
+#include <linux/irq.h>
+
+#include <asm/semaphore.h>
+#include <asm/processor.h>
+#include <asm/uaccess.h>
+#include <asm/checksum.h>
+#include <asm/io.h>
+#include <asm/delay.h>
+#include <asm/tlbflush.h>
+#include <asm/cacheflush.h>
+#include <asm/checksum.h>
+
+extern void dump_thread(struct pt_regs *, struct user *);
+extern int dump_fpu(struct pt_regs *, elf_fpregset_t *);
+extern struct hw_interrupt_type no_irq_type;
+
+EXPORT_SYMBOL(sh_mv);
+
+/* platform dependent support */
+EXPORT_SYMBOL(dump_thread);
+EXPORT_SYMBOL(dump_fpu);
+EXPORT_SYMBOL(iounmap);
+EXPORT_SYMBOL(enable_irq);
+EXPORT_SYMBOL(disable_irq);
+EXPORT_SYMBOL(probe_irq_mask);
+EXPORT_SYMBOL(kernel_thread);
+EXPORT_SYMBOL(disable_irq_nosync);
+EXPORT_SYMBOL(irq_desc);
+EXPORT_SYMBOL(no_irq_type);
+
+EXPORT_SYMBOL(strpbrk);
+EXPORT_SYMBOL(strstr);
+EXPORT_SYMBOL(strlen);
+EXPORT_SYMBOL(strnlen);
+EXPORT_SYMBOL(strchr);
+EXPORT_SYMBOL(strcat);
+EXPORT_SYMBOL(strncat);
+
+/* PCI exports */
+#ifdef CONFIG_PCI
+EXPORT_SYMBOL(pci_alloc_consistent);
+EXPORT_SYMBOL(pci_free_consistent);
+#endif
+
+/* mem exports */
+EXPORT_SYMBOL(memchr);
+EXPORT_SYMBOL(memcpy);
+EXPORT_SYMBOL(memcpy_fromio);
+EXPORT_SYMBOL(memcpy_toio);
+EXPORT_SYMBOL(memset);
+EXPORT_SYMBOL(memset_io);
+EXPORT_SYMBOL(memmove);
+EXPORT_SYMBOL(memcmp);
+EXPORT_SYMBOL(memscan);
+EXPORT_SYMBOL(__copy_user);
+EXPORT_SYMBOL(boot_cpu_data);
+
+#ifdef CONFIG_MMU
+EXPORT_SYMBOL(get_vm_area);
+#endif
+
+/* semaphore exports */
+EXPORT_SYMBOL(__up);
+EXPORT_SYMBOL(__down);
+EXPORT_SYMBOL(__down_interruptible);
+
+EXPORT_SYMBOL(__udelay);
+EXPORT_SYMBOL(__ndelay);
+EXPORT_SYMBOL(__const_udelay);
+
+EXPORT_SYMBOL(__div64_32);
+
+#define DECLARE_EXPORT(name) extern void name(void);EXPORT_SYMBOL(name)
+
+/* These symbols are generated by the compiler itself */
+DECLARE_EXPORT(__udivsi3);
+DECLARE_EXPORT(__udivdi3);
+DECLARE_EXPORT(__sdivsi3);
+DECLARE_EXPORT(__ashrdi3);
+DECLARE_EXPORT(__ashldi3);
+DECLARE_EXPORT(__lshrdi3);
+DECLARE_EXPORT(__movstr);
+
+EXPORT_SYMBOL(strcpy);
+
+#ifdef CONFIG_CPU_SH4
+DECLARE_EXPORT(__movstr_i4_even);
+DECLARE_EXPORT(__movstr_i4_odd);
+DECLARE_EXPORT(__movstrSI12_i4);
+
+/* needed by some modules */
+EXPORT_SYMBOL(flush_cache_all);
+EXPORT_SYMBOL(flush_cache_range);
+EXPORT_SYMBOL(flush_dcache_page);
+EXPORT_SYMBOL(__flush_purge_region);
+#endif
+
+#if defined(CONFIG_SH7705_CACHE_32KB)
+EXPORT_SYMBOL(flush_cache_all);
+EXPORT_SYMBOL(flush_cache_range);
+EXPORT_SYMBOL(flush_dcache_page);
+EXPORT_SYMBOL(__flush_purge_region);
+#endif
+
+EXPORT_SYMBOL(flush_tlb_page);
+EXPORT_SYMBOL(__down_trylock);
+
+#ifdef CONFIG_SMP
+EXPORT_SYMBOL(synchronize_irq);
+#endif
+
+EXPORT_SYMBOL(csum_partial);
+EXPORT_SYMBOL(csum_ipv6_magic);
+EXPORT_SYMBOL(consistent_sync);
+EXPORT_SYMBOL(clear_page);
diff --git a/arch/sh/kernel/signal.c b/arch/sh/kernel/signal.c
new file mode 100644
index 000000000000..06f1b47eded9
--- /dev/null
+++ b/arch/sh/kernel/signal.c
@@ -0,0 +1,607 @@
+/*
+ * linux/arch/sh/kernel/signal.c
+ *
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ *
+ * 1997-11-28 Modified for POSIX.1b signals by Richard Henderson
+ *
+ * SuperH version: Copyright (C) 1999, 2000 Niibe Yutaka & Kaz Kojima
+ *
+ */
+
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/kernel.h>
+#include <linux/signal.h>
+#include <linux/errno.h>
+#include <linux/wait.h>
+#include <linux/ptrace.h>
+#include <linux/unistd.h>
+#include <linux/stddef.h>
+#include <linux/tty.h>
+#include <linux/personality.h>
+#include <linux/binfmts.h>
+
+#include <asm/ucontext.h>
+#include <asm/uaccess.h>
+#include <asm/pgtable.h>
+#include <asm/cacheflush.h>
+
+#define DEBUG_SIG 0
+
+#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
+
+asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset);
+
+/*
+ * Atomically swap in the new signal mask, and wait for a signal.
+ */
+asmlinkage int
+sys_sigsuspend(old_sigset_t mask,
+ unsigned long r5, unsigned long r6, unsigned long r7,
+ struct pt_regs regs)
+{
+ sigset_t saveset;
+
+ mask &= _BLOCKABLE;
+ spin_lock_irq(&current->sighand->siglock);
+ saveset = current->blocked;
+ siginitset(&current->blocked, mask);
+ recalc_sigpending();
+ spin_unlock_irq(&current->sighand->siglock);
+
+ regs.regs[0] = -EINTR;
+ while (1) {
+ current->state = TASK_INTERRUPTIBLE;
+ schedule();
+ if (do_signal(&regs, &saveset))
+ return -EINTR;
+ }
+}
+
+asmlinkage int
+sys_rt_sigsuspend(sigset_t *unewset, size_t sigsetsize,
+ unsigned long r6, unsigned long r7,
+ struct pt_regs regs)
+{
+ sigset_t saveset, newset;
+
+ /* XXX: Don't preclude handling different sized sigset_t's. */
+ if (sigsetsize != sizeof(sigset_t))
+ return -EINVAL;
+
+ if (copy_from_user(&newset, unewset, sizeof(newset)))
+ return -EFAULT;
+ sigdelsetmask(&newset, ~_BLOCKABLE);
+ spin_lock_irq(&current->sighand->siglock);
+ saveset = current->blocked;
+ current->blocked = newset;
+ recalc_sigpending();
+ spin_unlock_irq(&current->sighand->siglock);
+
+ regs.regs[0] = -EINTR;
+ while (1) {
+ current->state = TASK_INTERRUPTIBLE;
+ schedule();
+ if (do_signal(&regs, &saveset))
+ return -EINTR;
+ }
+}
+
+asmlinkage int
+sys_sigaction(int sig, const struct old_sigaction __user *act,
+ struct old_sigaction __user *oact)
+{
+ struct k_sigaction new_ka, old_ka;
+ int ret;
+
+ if (act) {
+ old_sigset_t mask;
+ if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
+ __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
+ __get_user(new_ka.sa.sa_restorer, &act->sa_restorer))
+ return -EFAULT;
+ __get_user(new_ka.sa.sa_flags, &act->sa_flags);
+ __get_user(mask, &act->sa_mask);
+ siginitset(&new_ka.sa.sa_mask, mask);
+ }
+
+ ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
+
+ if (!ret && oact) {
+ if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
+ __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
+ __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
+ return -EFAULT;
+ __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
+ __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
+ }
+
+ return ret;
+}
+
+asmlinkage int
+sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss,
+ unsigned long r6, unsigned long r7,
+ struct pt_regs regs)
+{
+ return do_sigaltstack(uss, uoss, regs.regs[15]);
+}
+
+
+/*
+ * Do a signal return; undo the signal stack.
+ */
+
+#define MOVW(n) (0x9300|((n)-2)) /* Move mem word at PC+n to R3 */
+#define TRAP16 0xc310 /* Syscall w/no args (NR in R3) */
+#define OR_R0_R0 0x200b /* or r0,r0 (insert to avoid hardware bug) */
+
+struct sigframe
+{
+ struct sigcontext sc;
+ unsigned long extramask[_NSIG_WORDS-1];
+ u16 retcode[8];
+};
+
+struct rt_sigframe
+{
+ struct siginfo info;
+ struct ucontext uc;
+ u16 retcode[8];
+};
+
+#ifdef CONFIG_SH_FPU
+static inline int restore_sigcontext_fpu(struct sigcontext __user *sc)
+{
+ struct task_struct *tsk = current;
+
+ if (!(cpu_data->flags & CPU_HAS_FPU))
+ return 0;
+
+ set_used_math();
+ return __copy_from_user(&tsk->thread.fpu.hard, &sc->sc_fpregs[0],
+ sizeof(long)*(16*2+2));
+}
+
+static inline int save_sigcontext_fpu(struct sigcontext __user *sc,
+ struct pt_regs *regs)
+{
+ struct task_struct *tsk = current;
+
+ if (!(cpu_data->flags & CPU_HAS_FPU))
+ return 0;
+
+ if (!used_math()) {
+ __put_user(0, &sc->sc_ownedfp);
+ return 0;
+ }
+
+ __put_user(1, &sc->sc_ownedfp);
+
+ /* This will cause a "finit" to be triggered by the next
+ attempted FPU operation by the 'current' process.
+ */
+ clear_used_math();
+
+ unlazy_fpu(tsk, regs);
+ return __copy_to_user(&sc->sc_fpregs[0], &tsk->thread.fpu.hard,
+ sizeof(long)*(16*2+2));
+}
+#endif /* CONFIG_SH_FPU */
+
+static int
+restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, int *r0_p)
+{
+ unsigned int err = 0;
+
+#define COPY(x) err |= __get_user(regs->x, &sc->sc_##x)
+ COPY(regs[1]);
+ COPY(regs[2]); COPY(regs[3]);
+ COPY(regs[4]); COPY(regs[5]);
+ COPY(regs[6]); COPY(regs[7]);
+ COPY(regs[8]); COPY(regs[9]);
+ COPY(regs[10]); COPY(regs[11]);
+ COPY(regs[12]); COPY(regs[13]);
+ COPY(regs[14]); COPY(regs[15]);
+ COPY(gbr); COPY(mach);
+ COPY(macl); COPY(pr);
+ COPY(sr); COPY(pc);
+#undef COPY
+
+#ifdef CONFIG_SH_FPU
+ if (cpu_data->flags & CPU_HAS_FPU) {
+ int owned_fp;
+ struct task_struct *tsk = current;
+
+ regs->sr |= SR_FD; /* Release FPU */
+ clear_fpu(tsk, regs);
+ clear_used_math();
+ __get_user (owned_fp, &sc->sc_ownedfp);
+ if (owned_fp)
+ err |= restore_sigcontext_fpu(sc);
+ }
+#endif
+
+ regs->tra = -1; /* disable syscall checks */
+ err |= __get_user(*r0_p, &sc->sc_regs[0]);
+ return err;
+}
+
+asmlinkage int sys_sigreturn(unsigned long r4, unsigned long r5,
+ unsigned long r6, unsigned long r7,
+ struct pt_regs regs)
+{
+ struct sigframe __user *frame = (struct sigframe __user *)regs.regs[15];
+ sigset_t set;
+ int r0;
+
+ if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
+ goto badframe;
+
+ if (__get_user(set.sig[0], &frame->sc.oldmask)
+ || (_NSIG_WORDS > 1
+ && __copy_from_user(&set.sig[1], &frame->extramask,
+ sizeof(frame->extramask))))
+ goto badframe;
+
+ sigdelsetmask(&set, ~_BLOCKABLE);
+
+ spin_lock_irq(&current->sighand->siglock);
+ current->blocked = set;
+ recalc_sigpending();
+ spin_unlock_irq(&current->sighand->siglock);
+
+ if (restore_sigcontext(&regs, &frame->sc, &r0))
+ goto badframe;
+ return r0;
+
+badframe:
+ force_sig(SIGSEGV, current);
+ return 0;
+}
+
+asmlinkage int sys_rt_sigreturn(unsigned long r4, unsigned long r5,
+ unsigned long r6, unsigned long r7,
+ struct pt_regs regs)
+{
+ struct rt_sigframe __user *frame = (struct rt_sigframe __user *)regs.regs[15];
+ sigset_t set;
+ stack_t st;
+ int r0;
+
+ if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
+ goto badframe;
+
+ if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
+ goto badframe;
+
+ sigdelsetmask(&set, ~_BLOCKABLE);
+ spin_lock_irq(&current->sighand->siglock);
+ current->blocked = set;
+ recalc_sigpending();
+ spin_unlock_irq(&current->sighand->siglock);
+
+ if (restore_sigcontext(&regs, &frame->uc.uc_mcontext, &r0))
+ goto badframe;
+
+ if (__copy_from_user(&st, &frame->uc.uc_stack, sizeof(st)))
+ goto badframe;
+ /* It is more difficult to avoid calling this function than to
+ call it and ignore errors. */
+ do_sigaltstack(&st, NULL, regs.regs[15]);
+
+ return r0;
+
+badframe:
+ force_sig(SIGSEGV, current);
+ return 0;
+}
+
+/*
+ * Set up a signal frame.
+ */
+
+static int
+setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs,
+ unsigned long mask)
+{
+ int err = 0;
+
+#define COPY(x) err |= __put_user(regs->x, &sc->sc_##x)
+ COPY(regs[0]); COPY(regs[1]);
+ COPY(regs[2]); COPY(regs[3]);
+ COPY(regs[4]); COPY(regs[5]);
+ COPY(regs[6]); COPY(regs[7]);
+ COPY(regs[8]); COPY(regs[9]);
+ COPY(regs[10]); COPY(regs[11]);
+ COPY(regs[12]); COPY(regs[13]);
+ COPY(regs[14]); COPY(regs[15]);
+ COPY(gbr); COPY(mach);
+ COPY(macl); COPY(pr);
+ COPY(sr); COPY(pc);
+#undef COPY
+
+#ifdef CONFIG_SH_FPU
+ err |= save_sigcontext_fpu(sc, regs);
+#endif
+
+ /* non-iBCS2 extensions.. */
+ err |= __put_user(mask, &sc->oldmask);
+
+ return err;
+}
+
+/*
+ * Determine which stack to use..
+ */
+static inline void __user *
+get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size)
+{
+ if (ka->sa.sa_flags & SA_ONSTACK) {
+ if (sas_ss_flags(sp) == 0)
+ sp = current->sas_ss_sp + current->sas_ss_size;
+ }
+
+ return (void __user *)((sp - frame_size) & -8ul);
+}
+
+static void setup_frame(int sig, struct k_sigaction *ka,
+ sigset_t *set, struct pt_regs *regs)
+{
+ struct sigframe __user *frame;
+ int err = 0;
+ int signal;
+
+ frame = get_sigframe(ka, regs->regs[15], sizeof(*frame));
+
+ if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
+ goto give_sigsegv;
+
+ signal = current_thread_info()->exec_domain
+ && current_thread_info()->exec_domain->signal_invmap
+ && sig < 32
+ ? current_thread_info()->exec_domain->signal_invmap[sig]
+ : sig;
+
+ err |= setup_sigcontext(&frame->sc, regs, set->sig[0]);
+
+ if (_NSIG_WORDS > 1) {
+ err |= __copy_to_user(frame->extramask, &set->sig[1],
+ sizeof(frame->extramask));
+ }
+
+ /* Set up to return from userspace. If provided, use a stub
+ already in userspace. */
+ if (ka->sa.sa_flags & SA_RESTORER) {
+ regs->pr = (unsigned long) ka->sa.sa_restorer;
+ } else {
+ /* Generate return code (system call to sigreturn) */
+ err |= __put_user(MOVW(7), &frame->retcode[0]);
+ err |= __put_user(TRAP16, &frame->retcode[1]);
+ err |= __put_user(OR_R0_R0, &frame->retcode[2]);
+ err |= __put_user(OR_R0_R0, &frame->retcode[3]);
+ err |= __put_user(OR_R0_R0, &frame->retcode[4]);
+ err |= __put_user(OR_R0_R0, &frame->retcode[5]);
+ err |= __put_user(OR_R0_R0, &frame->retcode[6]);
+ err |= __put_user((__NR_sigreturn), &frame->retcode[7]);
+ regs->pr = (unsigned long) frame->retcode;
+ }
+
+ if (err)
+ goto give_sigsegv;
+
+ /* Set up registers for signal handler */
+ regs->regs[15] = (unsigned long) frame;
+ regs->regs[4] = signal; /* Arg for signal handler */
+ regs->regs[5] = 0;
+ regs->regs[6] = (unsigned long) &frame->sc;
+ regs->pc = (unsigned long) ka->sa.sa_handler;
+
+ set_fs(USER_DS);
+
+#if DEBUG_SIG
+ printk("SIG deliver (%s:%d): sp=%p pc=%08lx pr=%08lx\n",
+ current->comm, current->pid, frame, regs->pc, regs->pr);
+#endif
+
+ flush_cache_sigtramp(regs->pr);
+ if ((-regs->pr & (L1_CACHE_BYTES-1)) < sizeof(frame->retcode))
+ flush_cache_sigtramp(regs->pr + L1_CACHE_BYTES);
+ return;
+
+give_sigsegv:
+ force_sigsegv(sig, current);
+}
+
+static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
+ sigset_t *set, struct pt_regs *regs)
+{
+ struct rt_sigframe __user *frame;
+ int err = 0;
+ int signal;
+
+ frame = get_sigframe(ka, regs->regs[15], sizeof(*frame));
+
+ if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
+ goto give_sigsegv;
+
+ signal = current_thread_info()->exec_domain
+ && current_thread_info()->exec_domain->signal_invmap
+ && sig < 32
+ ? current_thread_info()->exec_domain->signal_invmap[sig]
+ : sig;
+
+ err |= copy_siginfo_to_user(&frame->info, info);
+
+ /* Create the ucontext. */
+ err |= __put_user(0, &frame->uc.uc_flags);
+ err |= __put_user(0, &frame->uc.uc_link);
+ err |= __put_user((void *)current->sas_ss_sp,
+ &frame->uc.uc_stack.ss_sp);
+ err |= __put_user(sas_ss_flags(regs->regs[15]),
+ &frame->uc.uc_stack.ss_flags);
+ err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
+ err |= setup_sigcontext(&frame->uc.uc_mcontext,
+ regs, set->sig[0]);
+ err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
+
+ /* Set up to return from userspace. If provided, use a stub
+ already in userspace. */
+ if (ka->sa.sa_flags & SA_RESTORER) {
+ regs->pr = (unsigned long) ka->sa.sa_restorer;
+ } else {
+ /* Generate return code (system call to rt_sigreturn) */
+ err |= __put_user(MOVW(7), &frame->retcode[0]);
+ err |= __put_user(TRAP16, &frame->retcode[1]);
+ err |= __put_user(OR_R0_R0, &frame->retcode[2]);
+ err |= __put_user(OR_R0_R0, &frame->retcode[3]);
+ err |= __put_user(OR_R0_R0, &frame->retcode[4]);
+ err |= __put_user(OR_R0_R0, &frame->retcode[5]);
+ err |= __put_user(OR_R0_R0, &frame->retcode[6]);
+ err |= __put_user((__NR_rt_sigreturn), &frame->retcode[7]);
+ regs->pr = (unsigned long) frame->retcode;
+ }
+
+ if (err)
+ goto give_sigsegv;
+
+ /* Set up registers for signal handler */
+ regs->regs[15] = (unsigned long) frame;
+ regs->regs[4] = signal; /* Arg for signal handler */
+ regs->regs[5] = (unsigned long) &frame->info;
+ regs->regs[6] = (unsigned long) &frame->uc;
+ regs->pc = (unsigned long) ka->sa.sa_handler;
+
+ set_fs(USER_DS);
+
+#if DEBUG_SIG
+ printk("SIG deliver (%s:%d): sp=%p pc=%08lx pr=%08lx\n",
+ current->comm, current->pid, frame, regs->pc, regs->pr);
+#endif
+
+ flush_cache_sigtramp(regs->pr);
+ if ((-regs->pr & (L1_CACHE_BYTES-1)) < sizeof(frame->retcode))
+ flush_cache_sigtramp(regs->pr + L1_CACHE_BYTES);
+ return;
+
+give_sigsegv:
+ force_sigsegv(sig, current);
+}
+
+/*
+ * OK, we're invoking a handler
+ */
+
+static void
+handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
+ sigset_t *oldset, struct pt_regs *regs)
+{
+ /* Are we from a system call? */
+ if (regs->tra >= 0) {
+ /* If so, check system call restarting.. */
+ switch (regs->regs[0]) {
+ case -ERESTARTNOHAND:
+ regs->regs[0] = -EINTR;
+ break;
+
+ case -ERESTARTSYS:
+ if (!(ka->sa.sa_flags & SA_RESTART)) {
+ regs->regs[0] = -EINTR;
+ break;
+ }
+ /* fallthrough */
+ case -ERESTARTNOINTR:
+ regs->pc -= 2;
+ }
+ } else {
+ /* gUSA handling */
+#ifdef CONFIG_PREEMPT
+ unsigned long flags;
+
+ local_irq_save(flags);
+#endif
+ if (regs->regs[15] >= 0xc0000000) {
+ int offset = (int)regs->regs[15];
+
+ /* Reset stack pointer: clear critical region mark */
+ regs->regs[15] = regs->regs[1];
+ if (regs->pc < regs->regs[0])
+ /* Go to rewind point #1 */
+ regs->pc = regs->regs[0] + offset - 2;
+ }
+#ifdef CONFIG_PREEMPT
+ local_irq_restore(flags);
+#endif
+ }
+
+ /* Set up the stack frame */
+ if (ka->sa.sa_flags & SA_SIGINFO)
+ setup_rt_frame(sig, ka, info, oldset, regs);
+ else
+ setup_frame(sig, ka, oldset, regs);
+
+ if (ka->sa.sa_flags & SA_ONESHOT)
+ ka->sa.sa_handler = SIG_DFL;
+
+ if (!(ka->sa.sa_flags & SA_NODEFER)) {
+ spin_lock_irq(&current->sighand->siglock);
+ sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+ sigaddset(&current->blocked,sig);
+ recalc_sigpending();
+ spin_unlock_irq(&current->sighand->siglock);
+ }
+}
+
+/*
+ * Note that 'init' is a special process: it doesn't get signals it doesn't
+ * want to handle. Thus you cannot kill init even with a SIGKILL even by
+ * mistake.
+ *
+ * Note that we go through the signals twice: once to check the signals that
+ * the kernel can handle, and then we build all the user-level signal handling
+ * stack-frames in one go after that.
+ */
+int do_signal(struct pt_regs *regs, sigset_t *oldset)
+{
+ siginfo_t info;
+ int signr;
+ struct k_sigaction ka;
+
+ /*
+ * We want the common case to go fast, which
+ * is why we may in certain cases get here from
+ * kernel mode. Just return without doing anything
+ * if so.
+ */
+ if (!user_mode(regs))
+ return 1;
+
+ if (try_to_freeze(0))
+ goto no_signal;
+
+ if (!oldset)
+ oldset = &current->blocked;
+
+ signr = get_signal_to_deliver(&info, &ka, regs, NULL);
+ if (signr > 0) {
+ /* Whee! Actually deliver the signal. */
+ handle_signal(signr, &ka, &info, oldset, regs);
+ return 1;
+ }
+
+ no_signal:
+ /* Did we come from a system call? */
+ if (regs->tra >= 0) {
+ /* Restart the system call - no handlers present */
+ if (regs->regs[0] == -ERESTARTNOHAND ||
+ regs->regs[0] == -ERESTARTSYS ||
+ regs->regs[0] == -ERESTARTNOINTR ||
+ regs->regs[0] == -ERESTART_RESTARTBLOCK) {
+ regs->pc -= 2;
+ }
+ }
+ return 0;
+}
diff --git a/arch/sh/kernel/smp.c b/arch/sh/kernel/smp.c
new file mode 100644
index 000000000000..56a39d69e080
--- /dev/null
+++ b/arch/sh/kernel/smp.c
@@ -0,0 +1,199 @@
+/*
+ * arch/sh/kernel/smp.c
+ *
+ * SMP support for the SuperH processors.
+ *
+ * Copyright (C) 2002, 2003 Paul Mundt
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+#include <linux/config.h>
+#include <linux/cache.h>
+#include <linux/cpumask.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/threads.h>
+#include <linux/module.h>
+#include <linux/time.h>
+#include <linux/timex.h>
+#include <linux/sched.h>
+
+#include <asm/atomic.h>
+#include <asm/processor.h>
+#include <asm/system.h>
+#include <asm/mmu_context.h>
+#include <asm/smp.h>
+
+/*
+ * This was written with the Sega Saturn (SMP SH-2 7604) in mind,
+ * but is designed to be usable regardless if there's an MMU
+ * present or not.
+ */
+struct sh_cpuinfo cpu_data[NR_CPUS];
+
+extern void per_cpu_trap_init(void);
+
+cpumask_t cpu_possible_map;
+cpumask_t cpu_online_map;
+static atomic_t cpus_booted = ATOMIC_INIT(0);
+
+/* These are defined by the board-specific code. */
+
+/*
+ * Cause the function described by call_data to be executed on the passed
+ * cpu. When the function has finished, increment the finished field of
+ * call_data.
+ */
+void __smp_send_ipi(unsigned int cpu, unsigned int action);
+
+/*
+ * Find the number of available processors
+ */
+unsigned int __smp_probe_cpus(void);
+
+/*
+ * Start a particular processor
+ */
+void __smp_slave_init(unsigned int cpu);
+
+/*
+ * Run specified function on a particular processor.
+ */
+void __smp_call_function(unsigned int cpu);
+
+static inline void __init smp_store_cpu_info(unsigned int cpu)
+{
+ cpu_data[cpu].loops_per_jiffy = loops_per_jiffy;
+}
+
+void __init smp_prepare_cpus(unsigned int max_cpus)
+{
+ unsigned int cpu = smp_processor_id();
+ int i;
+
+ atomic_set(&cpus_booted, 1);
+ smp_store_cpu_info(cpu);
+
+ for (i = 0; i < __smp_probe_cpus(); i++)
+ cpu_set(i, cpu_possible_map);
+}
+
+void __devinit smp_prepare_boot_cpu(void)
+{
+ unsigned int cpu = smp_processor_id();
+
+ cpu_set(cpu, cpu_online_map);
+ cpu_set(cpu, cpu_possible_map);
+}
+
+int __cpu_up(unsigned int cpu)
+{
+ struct task_struct *tsk;
+
+ tsk = fork_idle(cpu);
+
+ if (IS_ERR(tsk))
+ panic("Failed forking idle task for cpu %d\n", cpu);
+
+ tsk->thread_info->cpu = cpu;
+
+ cpu_set(cpu, cpu_online_map);
+
+ return 0;
+}
+
+int start_secondary(void *unused)
+{
+ unsigned int cpu = smp_processor_id();
+
+ atomic_inc(&init_mm.mm_count);
+ current->active_mm = &init_mm;
+
+ smp_store_cpu_info(cpu);
+
+ __smp_slave_init(cpu);
+ per_cpu_trap_init();
+
+ atomic_inc(&cpus_booted);
+
+ cpu_idle();
+ return 0;
+}
+
+void __init smp_cpus_done(unsigned int max_cpus)
+{
+ smp_mb();
+}
+
+void smp_send_reschedule(int cpu)
+{
+ __smp_send_ipi(cpu, SMP_MSG_RESCHEDULE);
+}
+
+static void stop_this_cpu(void *unused)
+{
+ cpu_clear(smp_processor_id(), cpu_online_map);
+ local_irq_disable();
+
+ for (;;)
+ cpu_relax();
+}
+
+void smp_send_stop(void)
+{
+ smp_call_function(stop_this_cpu, 0, 1, 0);
+}
+
+
+struct smp_fn_call_struct smp_fn_call = {
+ .lock = SPIN_LOCK_UNLOCKED,
+ .finished = ATOMIC_INIT(0),
+};
+
+/*
+ * The caller of this wants the passed function to run on every cpu. If wait
+ * is set, wait until all cpus have finished the function before returning.
+ * The lock is here to protect the call structure.
+ * You must not call this function with disabled interrupts or from a
+ * hardware interrupt handler or from a bottom half handler.
+ */
+int smp_call_function(void (*func)(void *info), void *info, int retry, int wait)
+{
+ unsigned int nr_cpus = atomic_read(&cpus_booted);
+ int i;
+
+ if (nr_cpus < 2)
+ return 0;
+
+ /* Can deadlock when called with interrupts disabled */
+ WARN_ON(irqs_disabled());
+
+ spin_lock(&smp_fn_call.lock);
+
+ atomic_set(&smp_fn_call.finished, 0);
+ smp_fn_call.fn = func;
+ smp_fn_call.data = info;
+
+ for (i = 0; i < nr_cpus; i++)
+ if (i != smp_processor_id())
+ __smp_call_function(i);
+
+ if (wait)
+ while (atomic_read(&smp_fn_call.finished) != (nr_cpus - 1));
+
+ spin_unlock(&smp_fn_call.lock);
+
+ return 0;
+}
+
+/* Not really SMP stuff ... */
+int setup_profiling_timer(unsigned int multiplier)
+{
+ return 0;
+}
+
diff --git a/arch/sh/kernel/sys_sh.c b/arch/sh/kernel/sys_sh.c
new file mode 100644
index 000000000000..df5ac294c379
--- /dev/null
+++ b/arch/sh/kernel/sys_sh.c
@@ -0,0 +1,289 @@
+/*
+ * linux/arch/sh/kernel/sys_sh.c
+ *
+ * This file contains various random system calls that
+ * have a non-standard calling sequence on the Linux/SuperH
+ * platform.
+ *
+ * Taken from i386 version.
+ */
+
+#include <linux/errno.h>
+#include <linux/sched.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>
+#include <linux/stat.h>
+#include <linux/syscalls.h>
+#include <linux/mman.h>
+#include <linux/file.h>
+#include <linux/utsname.h>
+
+#include <asm/uaccess.h>
+#include <asm/ipc.h>
+
+/*
+ * sys_pipe() is the normal C calling standard for creating
+ * a pipe. It's not the way Unix traditionally does this, though.
+ */
+asmlinkage int sys_pipe(unsigned long r4, unsigned long r5,
+ unsigned long r6, unsigned long r7,
+ struct pt_regs regs)
+{
+ int fd[2];
+ int error;
+
+ error = do_pipe(fd);
+ if (!error) {
+ regs.regs[1] = fd[1];
+ return fd[0];
+ }
+ return error;
+}
+
+#if defined(HAVE_ARCH_UNMAPPED_AREA)
+/*
+ * To avoid cache alias, we map the shard page with same color.
+ */
+#define COLOUR_ALIGN(addr) (((addr)+SHMLBA-1)&~(SHMLBA-1))
+
+unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr,
+ unsigned long len, unsigned long pgoff, unsigned long flags)
+{
+ struct mm_struct *mm = current->mm;
+ struct vm_area_struct *vma;
+ unsigned long start_addr;
+
+ if (flags & MAP_FIXED) {
+ /* We do not accept a shared mapping if it would violate
+ * cache aliasing constraints.
+ */
+ if ((flags & MAP_SHARED) && (addr & (SHMLBA - 1)))
+ return -EINVAL;
+ return addr;
+ }
+
+ if (len > TASK_SIZE)
+ return -ENOMEM;
+
+ if (addr) {
+ if (flags & MAP_PRIVATE)
+ addr = PAGE_ALIGN(addr);
+ else
+ addr = COLOUR_ALIGN(addr);
+ vma = find_vma(mm, addr);
+ if (TASK_SIZE - len >= addr &&
+ (!vma || addr + len <= vma->vm_start))
+ return addr;
+ }
+ if (flags & MAP_PRIVATE)
+ addr = PAGE_ALIGN(mm->free_area_cache);
+ else
+ addr = COLOUR_ALIGN(mm->free_area_cache);
+ start_addr = addr;
+
+full_search:
+ for (vma = find_vma(mm, addr); ; vma = vma->vm_next) {
+ /* At this point: (!vma || addr < vma->vm_end). */
+ if (TASK_SIZE - len < addr) {
+ /*
+ * Start a new search - just in case we missed
+ * some holes.
+ */
+ if (start_addr != TASK_UNMAPPED_BASE) {
+ start_addr = addr = TASK_UNMAPPED_BASE;
+ goto full_search;
+ }
+ return -ENOMEM;
+ }
+ if (!vma || addr + len <= vma->vm_start) {
+ /*
+ * Remember the place where we stopped the search:
+ */
+ mm->free_area_cache = addr + len;
+ return addr;
+ }
+ addr = vma->vm_end;
+ if (!(flags & MAP_PRIVATE))
+ addr = COLOUR_ALIGN(addr);
+ }
+}
+#endif
+
+static inline long
+do_mmap2(unsigned long addr, unsigned long len, unsigned long prot,
+ unsigned long flags, int fd, unsigned long pgoff)
+{
+ int error = -EBADF;
+ struct file *file = NULL;
+
+ flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+ if (!(flags & MAP_ANONYMOUS)) {
+ file = fget(fd);
+ if (!file)
+ goto out;
+ }
+
+ down_write(&current->mm->mmap_sem);
+ error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
+ up_write(&current->mm->mmap_sem);
+
+ if (file)
+ fput(file);
+out:
+ return error;
+}
+
+asmlinkage int old_mmap(unsigned long addr, unsigned long len,
+ unsigned long prot, unsigned long flags,
+ int fd, unsigned long off)
+{
+ if (off & ~PAGE_MASK)
+ return -EINVAL;
+ return do_mmap2(addr, len, prot, flags, fd, off>>PAGE_SHIFT);
+}
+
+asmlinkage long sys_mmap2(unsigned long addr, unsigned long len,
+ unsigned long prot, unsigned long flags,
+ unsigned long fd, unsigned long pgoff)
+{
+ return do_mmap2(addr, len, prot, flags, fd, pgoff);
+}
+
+/*
+ * sys_ipc() is the de-multiplexer for the SysV IPC calls..
+ *
+ * This is really horribly ugly.
+ */
+asmlinkage int sys_ipc(uint call, int first, int second,
+ int third, void __user *ptr, long fifth)
+{
+ int version, ret;
+
+ version = call >> 16; /* hack for backward compatibility */
+ call &= 0xffff;
+
+ if (call <= SEMCTL)
+ switch (call) {
+ case SEMOP:
+ return sys_semtimedop(first, (struct sembuf __user *)ptr,
+ second, NULL);
+ case SEMTIMEDOP:
+ return sys_semtimedop(first, (struct sembuf __user *)ptr,
+ second,
+ (const struct timespec __user *)fifth);
+ case SEMGET:
+ return sys_semget (first, second, third);
+ case SEMCTL: {
+ union semun fourth;
+ if (!ptr)
+ return -EINVAL;
+ if (get_user(fourth.__pad, (void * __user *) ptr))
+ return -EFAULT;
+ return sys_semctl (first, second, third, fourth);
+ }
+ default:
+ return -EINVAL;
+ }
+
+ if (call <= MSGCTL)
+ switch (call) {
+ case MSGSND:
+ return sys_msgsnd (first, (struct msgbuf __user *) ptr,
+ second, third);
+ case MSGRCV:
+ switch (version) {
+ case 0: {
+ struct ipc_kludge tmp;
+ if (!ptr)
+ return -EINVAL;
+
+ if (copy_from_user(&tmp,
+ (struct ipc_kludge __user *) ptr,
+ sizeof (tmp)))
+ return -EFAULT;
+ return sys_msgrcv (first, tmp.msgp, second,
+ tmp.msgtyp, third);
+ }
+ default:
+ return sys_msgrcv (first,
+ (struct msgbuf __user *) ptr,
+ second, fifth, third);
+ }
+ case MSGGET:
+ return sys_msgget ((key_t) first, second);
+ case MSGCTL:
+ return sys_msgctl (first, second,
+ (struct msqid_ds __user *) ptr);
+ default:
+ return -EINVAL;
+ }
+ if (call <= SHMCTL)
+ switch (call) {
+ case SHMAT:
+ switch (version) {
+ default: {
+ ulong raddr;
+ ret = do_shmat (first, (char __user *) ptr,
+ second, &raddr);
+ if (ret)
+ return ret;
+ return put_user (raddr, (ulong __user *) third);
+ }
+ case 1: /* iBCS2 emulator entry point */
+ if (!segment_eq(get_fs(), get_ds()))
+ return -EINVAL;
+ return do_shmat (first, (char __user *) ptr,
+ second, (ulong *) third);
+ }
+ case SHMDT:
+ return sys_shmdt ((char __user *)ptr);
+ case SHMGET:
+ return sys_shmget (first, second, third);
+ case SHMCTL:
+ return sys_shmctl (first, second,
+ (struct shmid_ds __user *) ptr);
+ default:
+ return -EINVAL;
+ }
+
+ return -EINVAL;
+}
+
+asmlinkage int sys_uname(struct old_utsname * name)
+{
+ int err;
+ if (!name)
+ return -EFAULT;
+ down_read(&uts_sem);
+ err=copy_to_user(name, &system_utsname, sizeof (*name));
+ up_read(&uts_sem);
+ return err?-EFAULT:0;
+}
+
+asmlinkage ssize_t sys_pread_wrapper(unsigned int fd, char * buf,
+ size_t count, long dummy, loff_t pos)
+{
+ return sys_pread64(fd, buf, count, pos);
+}
+
+asmlinkage ssize_t sys_pwrite_wrapper(unsigned int fd, const char * buf,
+ size_t count, long dummy, loff_t pos)
+{
+ return sys_pwrite64(fd, buf, count, pos);
+}
+
+asmlinkage int sys_fadvise64_64_wrapper(int fd, u32 offset0, u32 offset1,
+ u32 len0, u32 len1, int advice)
+{
+#ifdef __LITTLE_ENDIAN__
+ return sys_fadvise64_64(fd, (u64)offset1 << 32 | offset0,
+ (u64)len1 << 32 | len0, advice);
+#else
+ return sys_fadvise64_64(fd, (u64)offset0 << 32 | offset1,
+ (u64)len0 << 32 | len1, advice);
+#endif
+}
diff --git a/arch/sh/kernel/time.c b/arch/sh/kernel/time.c
new file mode 100644
index 000000000000..df7a9b9d4cbf
--- /dev/null
+++ b/arch/sh/kernel/time.c
@@ -0,0 +1,657 @@
+/*
+ * arch/sh/kernel/time.c
+ *
+ * Copyright (C) 1999 Tetsuya Okada & Niibe Yutaka
+ * Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>
+ * Copyright (C) 2002, 2003, 2004 Paul Mundt
+ * Copyright (C) 2002 M. R. Brown <mrbrown@linux-sh.org>
+ *
+ * Some code taken from i386 version.
+ * Copyright (C) 1991, 1992, 1995 Linus Torvalds
+ */
+
+#include <linux/config.h>
+#include <linux/errno.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/param.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/time.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/smp.h>
+#include <linux/profile.h>
+
+#include <asm/processor.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/delay.h>
+#include <asm/machvec.h>
+#include <asm/rtc.h>
+#include <asm/freq.h>
+#include <asm/cpu/timer.h>
+#ifdef CONFIG_SH_KGDB
+#include <asm/kgdb.h>
+#endif
+
+#include <linux/timex.h>
+#include <linux/irq.h>
+
+#define TMU_TOCR_INIT 0x00
+#define TMU0_TCR_INIT 0x0020
+#define TMU_TSTR_INIT 1
+
+#define TMU0_TCR_CALIB 0x0000
+
+#ifdef CONFIG_CPU_SUBTYPE_ST40STB1
+#define CLOCKGEN_MEMCLKCR 0xbb040038
+#define MEMCLKCR_RATIO_MASK 0x7
+#endif /* CONFIG_CPU_SUBTYPE_ST40STB1 */
+
+extern unsigned long wall_jiffies;
+#define TICK_SIZE (tick_nsec / 1000)
+DEFINE_SPINLOCK(tmu0_lock);
+
+u64 jiffies_64 = INITIAL_JIFFIES;
+
+EXPORT_SYMBOL(jiffies_64);
+
+/* XXX: Can we initialize this in a routine somewhere? Dreamcast doesn't want
+ * these routines anywhere... */
+#ifdef CONFIG_SH_RTC
+void (*rtc_get_time)(struct timespec *) = sh_rtc_gettimeofday;
+int (*rtc_set_time)(const time_t) = sh_rtc_settimeofday;
+#else
+void (*rtc_get_time)(struct timespec *);
+int (*rtc_set_time)(const time_t);
+#endif
+
+#if defined(CONFIG_CPU_SUBTYPE_SH7300)
+static int md_table[] = { 1, 2, 3, 4, 6, 8, 12 };
+#endif
+#if defined(CONFIG_CPU_SH3)
+static int stc_multipliers[] = { 1, 2, 3, 4, 6, 1, 1, 1 };
+static int stc_values[] = { 0, 1, 4, 2, 5, 0, 0, 0 };
+#define bfc_divisors stc_multipliers
+#define bfc_values stc_values
+static int ifc_divisors[] = { 1, 2, 3, 4, 1, 1, 1, 1 };
+static int ifc_values[] = { 0, 1, 4, 2, 0, 0, 0, 0 };
+static int pfc_divisors[] = { 1, 2, 3, 4, 6, 1, 1, 1 };
+static int pfc_values[] = { 0, 1, 4, 2, 5, 0, 0, 0 };
+#elif defined(CONFIG_CPU_SH4)
+#if defined(CONFIG_CPU_SUBTYPE_SH73180)
+static int ifc_divisors[] = { 1, 2, 3, 4, 6, 8, 12, 16 };
+static int ifc_values[] = { 0, 1, 2, 3, 4, 5, 6, 7 };
+#define bfc_divisors ifc_divisors /* Same */
+#define bfc_values ifc_values
+#define pfc_divisors ifc_divisors /* Same */
+#define pfc_values ifc_values
+#else
+static int ifc_divisors[] = { 1, 2, 3, 4, 6, 8, 1, 1 };
+static int ifc_values[] = { 0, 1, 2, 3, 0, 4, 0, 5 };
+#define bfc_divisors ifc_divisors /* Same */
+#define bfc_values ifc_values
+static int pfc_divisors[] = { 2, 3, 4, 6, 8, 2, 2, 2 };
+static int pfc_values[] = { 0, 0, 1, 2, 0, 3, 0, 4 };
+#endif
+#else
+#error "Unknown ifc/bfc/pfc/stc values for this processor"
+#endif
+
+/*
+ * Scheduler clock - returns current time in nanosec units.
+ */
+unsigned long long sched_clock(void)
+{
+ return (unsigned long long)jiffies * (1000000000 / HZ);
+}
+
+static unsigned long do_gettimeoffset(void)
+{
+ int count;
+ unsigned long flags;
+
+ static int count_p = 0x7fffffff; /* for the first call after boot */
+ static unsigned long jiffies_p = 0;
+
+ /*
+ * cache volatile jiffies temporarily; we have IRQs turned off.
+ */
+ unsigned long jiffies_t;
+
+ spin_lock_irqsave(&tmu0_lock, flags);
+ /* timer count may underflow right here */
+ count = ctrl_inl(TMU0_TCNT); /* read the latched count */
+
+ jiffies_t = jiffies;
+
+ /*
+ * avoiding timer inconsistencies (they are rare, but they happen)...
+ * there is one kind of problem that must be avoided here:
+ * 1. the timer counter underflows
+ */
+
+ if( jiffies_t == jiffies_p ) {
+ if( count > count_p ) {
+ /* the nutcase */
+
+ if(ctrl_inw(TMU0_TCR) & 0x100) { /* Check UNF bit */
+ /*
+ * We cannot detect lost timer interrupts ...
+ * well, that's why we call them lost, don't we? :)
+ * [hmm, on the Pentium and Alpha we can ... sort of]
+ */
+ count -= LATCH;
+ } else {
+ printk("do_slow_gettimeoffset(): hardware timer problem?\n");
+ }
+ }
+ } else
+ jiffies_p = jiffies_t;
+
+ count_p = count;
+ spin_unlock_irqrestore(&tmu0_lock, flags);
+
+ count = ((LATCH-1) - count) * TICK_SIZE;
+ count = (count + LATCH/2) / LATCH;
+
+ return count;
+}
+
+void do_gettimeofday(struct timeval *tv)
+{
+ unsigned long seq;
+ unsigned long usec, sec;
+ unsigned long lost;
+
+ do {
+ seq = read_seqbegin(&xtime_lock);
+ usec = do_gettimeoffset();
+
+ lost = jiffies - wall_jiffies;
+ if (lost)
+ usec += lost * (1000000 / HZ);
+
+ sec = xtime.tv_sec;
+ usec += xtime.tv_nsec / 1000;
+ } while (read_seqretry(&xtime_lock, seq));
+
+ while (usec >= 1000000) {
+ usec -= 1000000;
+ sec++;
+ }
+
+ tv->tv_sec = sec;
+ tv->tv_usec = usec;
+}
+
+EXPORT_SYMBOL(do_gettimeofday);
+
+int do_settimeofday(struct timespec *tv)
+{
+ time_t wtm_sec, sec = tv->tv_sec;
+ long wtm_nsec, nsec = tv->tv_nsec;
+
+ if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
+ return -EINVAL;
+
+ write_seqlock_irq(&xtime_lock);
+ /*
+ * This is revolting. We need to set "xtime" correctly. However, the
+ * value in this location is the value at the most recent update of
+ * wall time. Discover what correction gettimeofday() would have
+ * made, and then undo it!
+ */
+ nsec -= 1000 * (do_gettimeoffset() +
+ (jiffies - wall_jiffies) * (1000000 / HZ));
+
+ wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
+ wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
+
+ set_normalized_timespec(&xtime, sec, nsec);
+ set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
+
+ time_adjust = 0; /* stop active adjtime() */
+ time_status |= STA_UNSYNC;
+ time_maxerror = NTP_PHASE_LIMIT;
+ time_esterror = NTP_PHASE_LIMIT;
+ write_sequnlock_irq(&xtime_lock);
+ clock_was_set();
+
+ return 0;
+}
+
+EXPORT_SYMBOL(do_settimeofday);
+
+/* last time the RTC clock got updated */
+static long last_rtc_update;
+
+/*
+ * timer_interrupt() needs to keep up the real-time clock,
+ * as well as call the "do_timer()" routine every clocktick
+ */
+static inline void do_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ do_timer(regs);
+#ifndef CONFIG_SMP
+ update_process_times(user_mode(regs));
+#endif
+ profile_tick(CPU_PROFILING, regs);
+
+#ifdef CONFIG_HEARTBEAT
+ if (sh_mv.mv_heartbeat != NULL)
+ sh_mv.mv_heartbeat();
+#endif
+
+ /*
+ * If we have an externally synchronized Linux clock, then update
+ * RTC clock accordingly every ~11 minutes. Set_rtc_mmss() has to be
+ * called as close as possible to 500 ms before the new second starts.
+ */
+ if ((time_status & STA_UNSYNC) == 0 &&
+ xtime.tv_sec > last_rtc_update + 660 &&
+ (xtime.tv_nsec / 1000) >= 500000 - ((unsigned) TICK_SIZE) / 2 &&
+ (xtime.tv_nsec / 1000) <= 500000 + ((unsigned) TICK_SIZE) / 2) {
+ if (rtc_set_time(xtime.tv_sec) == 0)
+ last_rtc_update = xtime.tv_sec;
+ else
+ last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */
+ }
+}
+
+/*
+ * This is the same as the above, except we _also_ save the current
+ * Time Stamp Counter value at the time of the timer interrupt, so that
+ * we later on can estimate the time of day more exactly.
+ */
+static irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ unsigned long timer_status;
+
+ /* Clear UNF bit */
+ timer_status = ctrl_inw(TMU0_TCR);
+ timer_status &= ~0x100;
+ ctrl_outw(timer_status, TMU0_TCR);
+
+ /*
+ * Here we are in the timer irq handler. We just have irqs locally
+ * disabled but we don't know if the timer_bh is running on the other
+ * CPU. We need to avoid to SMP race with it. NOTE: we don' t need
+ * the irq version of write_lock because as just said we have irq
+ * locally disabled. -arca
+ */
+ write_seqlock(&xtime_lock);
+ do_timer_interrupt(irq, NULL, regs);
+ write_sequnlock(&xtime_lock);
+
+ return IRQ_HANDLED;
+}
+
+/*
+ * Hah! We'll see if this works (switching from usecs to nsecs).
+ */
+static unsigned int __init get_timer_frequency(void)
+{
+ u32 freq;
+ struct timespec ts1, ts2;
+ unsigned long diff_nsec;
+ unsigned long factor;
+
+ /* Setup the timer: We don't want to generate interrupts, just
+ * have it count down at its natural rate.
+ */
+ ctrl_outb(0, TMU_TSTR);
+#if !defined(CONFIG_CPU_SUBTYPE_SH7300)
+ ctrl_outb(TMU_TOCR_INIT, TMU_TOCR);
+#endif
+ ctrl_outw(TMU0_TCR_CALIB, TMU0_TCR);
+ ctrl_outl(0xffffffff, TMU0_TCOR);
+ ctrl_outl(0xffffffff, TMU0_TCNT);
+
+ rtc_get_time(&ts2);
+
+ do {
+ rtc_get_time(&ts1);
+ } while (ts1.tv_nsec == ts2.tv_nsec && ts1.tv_sec == ts2.tv_sec);
+
+ /* actually start the timer */
+ ctrl_outb(TMU_TSTR_INIT, TMU_TSTR);
+
+ do {
+ rtc_get_time(&ts2);
+ } while (ts1.tv_nsec == ts2.tv_nsec && ts1.tv_sec == ts2.tv_sec);
+
+ freq = 0xffffffff - ctrl_inl(TMU0_TCNT);
+ if (ts2.tv_nsec < ts1.tv_nsec) {
+ ts2.tv_nsec += 1000000000;
+ ts2.tv_sec--;
+ }
+
+ diff_nsec = (ts2.tv_sec - ts1.tv_sec) * 1000000000 + (ts2.tv_nsec - ts1.tv_nsec);
+
+ /* this should work well if the RTC has a precision of n Hz, where
+ * n is an integer. I don't think we have to worry about the other
+ * cases. */
+ factor = (1000000000 + diff_nsec/2) / diff_nsec;
+
+ if (factor * diff_nsec > 1100000000 ||
+ factor * diff_nsec < 900000000)
+ panic("weird RTC (diff_nsec %ld)", diff_nsec);
+
+ return freq * factor;
+}
+
+void (*board_time_init)(void);
+void (*board_timer_setup)(struct irqaction *irq);
+
+static unsigned int sh_pclk_freq __initdata = CONFIG_SH_PCLK_FREQ;
+
+static int __init sh_pclk_setup(char *str)
+{
+ unsigned int freq;
+
+ if (get_option(&str, &freq))
+ sh_pclk_freq = freq;
+
+ return 1;
+}
+__setup("sh_pclk=", sh_pclk_setup);
+
+static struct irqaction irq0 = { timer_interrupt, SA_INTERRUPT, CPU_MASK_NONE, "timer", NULL, NULL};
+
+void get_current_frequency_divisors(unsigned int *ifc, unsigned int *bfc, unsigned int *pfc)
+{
+ unsigned int frqcr = ctrl_inw(FRQCR);
+
+#if defined(CONFIG_CPU_SH3)
+#if defined(CONFIG_CPU_SUBTYPE_SH7300)
+ *ifc = md_table[((frqcr & 0x0070) >> 4)];
+ *bfc = md_table[((frqcr & 0x0700) >> 8)];
+ *pfc = md_table[frqcr & 0x0007];
+#elif defined(CONFIG_CPU_SUBTYPE_SH7705)
+ *bfc = stc_multipliers[(frqcr & 0x0300) >> 8];
+ *ifc = ifc_divisors[(frqcr & 0x0030) >> 4];
+ *pfc = pfc_divisors[frqcr & 0x0003];
+#else
+ unsigned int tmp;
+
+ tmp = (frqcr & 0x8000) >> 13;
+ tmp |= (frqcr & 0x0030) >> 4;
+ *bfc = stc_multipliers[tmp];
+ tmp = (frqcr & 0x4000) >> 12;
+ tmp |= (frqcr & 0x000c) >> 2;
+ *ifc = ifc_divisors[tmp];
+ tmp = (frqcr & 0x2000) >> 11;
+ tmp |= frqcr & 0x0003;
+ *pfc = pfc_divisors[tmp];
+#endif
+#elif defined(CONFIG_CPU_SH4)
+#if defined(CONFIG_CPU_SUBTYPE_SH73180)
+ *ifc = ifc_divisors[(frqcr>> 20) & 0x0007];
+ *bfc = bfc_divisors[(frqcr>> 12) & 0x0007];
+ *pfc = pfc_divisors[frqcr & 0x0007];
+#else
+ *ifc = ifc_divisors[(frqcr >> 6) & 0x0007];
+ *bfc = bfc_divisors[(frqcr >> 3) & 0x0007];
+ *pfc = pfc_divisors[frqcr & 0x0007];
+#endif
+#endif
+}
+
+/*
+ * This bit of ugliness builds up accessor routines to get at both
+ * the divisors and the physical values.
+ */
+#define _FREQ_TABLE(x) \
+ unsigned int get_##x##_divisor(unsigned int value) \
+ { return x##_divisors[value]; } \
+ \
+ unsigned int get_##x##_value(unsigned int divisor) \
+ { return x##_values[(divisor - 1)]; }
+
+_FREQ_TABLE(ifc);
+_FREQ_TABLE(bfc);
+_FREQ_TABLE(pfc);
+
+#ifdef CONFIG_CPU_SUBTYPE_ST40STB1
+
+/*
+ * The ST40 divisors are totally different so we set the cpu data
+ * clocks using a different algorithm
+ *
+ * I've just plugged this from the 2.4 code
+ * - Alex Bennee <kernel-hacker@bennee.com>
+ */
+#define CCN_PVR_CHIP_SHIFT 24
+#define CCN_PVR_CHIP_MASK 0xff
+#define CCN_PVR_CHIP_ST40STB1 0x4
+
+
+struct frqcr_data {
+ unsigned short frqcr;
+
+ struct {
+ unsigned char multiplier;
+ unsigned char divisor;
+ } factor[3];
+};
+
+static struct frqcr_data st40_frqcr_table[] = {
+ { 0x000, {{1,1}, {1,1}, {1,2}}},
+ { 0x002, {{1,1}, {1,1}, {1,4}}},
+ { 0x004, {{1,1}, {1,1}, {1,8}}},
+ { 0x008, {{1,1}, {1,2}, {1,2}}},
+ { 0x00A, {{1,1}, {1,2}, {1,4}}},
+ { 0x00C, {{1,1}, {1,2}, {1,8}}},
+ { 0x011, {{1,1}, {2,3}, {1,6}}},
+ { 0x013, {{1,1}, {2,3}, {1,3}}},
+ { 0x01A, {{1,1}, {1,2}, {1,4}}},
+ { 0x01C, {{1,1}, {1,2}, {1,8}}},
+ { 0x023, {{1,1}, {2,3}, {1,3}}},
+ { 0x02C, {{1,1}, {1,2}, {1,8}}},
+ { 0x048, {{1,2}, {1,2}, {1,4}}},
+ { 0x04A, {{1,2}, {1,2}, {1,6}}},
+ { 0x04C, {{1,2}, {1,2}, {1,8}}},
+ { 0x05A, {{1,2}, {1,3}, {1,6}}},
+ { 0x05C, {{1,2}, {1,3}, {1,6}}},
+ { 0x063, {{1,2}, {1,4}, {1,4}}},
+ { 0x06C, {{1,2}, {1,4}, {1,8}}},
+ { 0x091, {{1,3}, {1,3}, {1,6}}},
+ { 0x093, {{1,3}, {1,3}, {1,6}}},
+ { 0x0A3, {{1,3}, {1,6}, {1,6}}},
+ { 0x0DA, {{1,4}, {1,4}, {1,8}}},
+ { 0x0DC, {{1,4}, {1,4}, {1,8}}},
+ { 0x0EC, {{1,4}, {1,8}, {1,8}}},
+ { 0x123, {{1,4}, {1,4}, {1,8}}},
+ { 0x16C, {{1,4}, {1,8}, {1,8}}},
+};
+
+struct memclk_data {
+ unsigned char multiplier;
+ unsigned char divisor;
+};
+
+static struct memclk_data st40_memclk_table[8] = {
+ {1,1}, // 000
+ {1,2}, // 001
+ {1,3}, // 010
+ {2,3}, // 011
+ {1,4}, // 100
+ {1,6}, // 101
+ {1,8}, // 110
+ {1,8} // 111
+};
+
+static void st40_specific_time_init(unsigned int module_clock, unsigned short frqcr)
+{
+ unsigned int cpu_clock, master_clock, bus_clock, memory_clock;
+ struct frqcr_data *d;
+ int a;
+ unsigned long memclkcr;
+ struct memclk_data *e;
+
+ for (a = 0; a < ARRAY_SIZE(st40_frqcr_table); a++) {
+ d = &st40_frqcr_table[a];
+
+ if (d->frqcr == (frqcr & 0x1ff))
+ break;
+ }
+
+ if (a == ARRAY_SIZE(st40_frqcr_table)) {
+ d = st40_frqcr_table;
+
+ printk("ERROR: Unrecognised FRQCR value (0x%x), "
+ "using default multipliers\n", frqcr);
+ }
+
+ memclkcr = ctrl_inl(CLOCKGEN_MEMCLKCR);
+ e = &st40_memclk_table[memclkcr & MEMCLKCR_RATIO_MASK];
+
+ printk(KERN_INFO "Clock multipliers: CPU: %d/%d Bus: %d/%d "
+ "Mem: %d/%d Periph: %d/%d\n",
+ d->factor[0].multiplier, d->factor[0].divisor,
+ d->factor[1].multiplier, d->factor[1].divisor,
+ e->multiplier, e->divisor,
+ d->factor[2].multiplier, d->factor[2].divisor);
+
+ master_clock = module_clock * d->factor[2].divisor
+ / d->factor[2].multiplier;
+ bus_clock = master_clock * d->factor[1].multiplier
+ / d->factor[1].divisor;
+ memory_clock = master_clock * e->multiplier
+ / e->divisor;
+ cpu_clock = master_clock * d->factor[0].multiplier
+ / d->factor[0].divisor;
+
+ current_cpu_data.cpu_clock = cpu_clock;
+ current_cpu_data.master_clock = master_clock;
+ current_cpu_data.bus_clock = bus_clock;
+ current_cpu_data.memory_clock = memory_clock;
+ current_cpu_data.module_clock = module_clock;
+}
+#endif
+
+void __init time_init(void)
+{
+ unsigned int timer_freq = 0;
+ unsigned int ifc, pfc, bfc;
+ unsigned long interval;
+#ifdef CONFIG_CPU_SUBTYPE_ST40STB1
+ unsigned long pvr;
+ unsigned short frqcr;
+#endif
+
+ if (board_time_init)
+ board_time_init();
+
+ /*
+ * If we don't have an RTC (such as with the SH7300), don't attempt to
+ * probe the timer frequency. Rely on an either hardcoded peripheral
+ * clock value, or on the sh_pclk command line option. Note that we
+ * still need to have CONFIG_SH_PCLK_FREQ set in order for things like
+ * CLOCK_TICK_RATE to be sane.
+ */
+ current_cpu_data.module_clock = sh_pclk_freq;
+
+#ifdef CONFIG_SH_PCLK_CALC
+ /* XXX: Switch this over to a more generic test. */
+ {
+ unsigned int freq;
+
+ /*
+ * If we've specified a peripheral clock frequency, and we have
+ * an RTC, compare it against the autodetected value. Complain
+ * if there's a mismatch.
+ */
+ timer_freq = get_timer_frequency();
+ freq = timer_freq * 4;
+
+ if (sh_pclk_freq && (sh_pclk_freq/100*99 > freq || sh_pclk_freq/100*101 < freq)) {
+ printk(KERN_NOTICE "Calculated peripheral clock value "
+ "%d differs from sh_pclk value %d, fixing..\n",
+ freq, sh_pclk_freq);
+ current_cpu_data.module_clock = freq;
+ }
+ }
+#endif
+
+#ifdef CONFIG_CPU_SUBTYPE_ST40STB1
+ /* XXX: Update ST40 code to use board_time_init() */
+ pvr = ctrl_inl(CCN_PVR);
+ frqcr = ctrl_inw(FRQCR);
+ printk("time.c ST40 Probe: PVR %08lx, FRQCR %04hx\n", pvr, frqcr);
+
+ if (((pvr >> CCN_PVR_CHIP_SHIFT) & CCN_PVR_CHIP_MASK) == CCN_PVR_CHIP_ST40STB1)
+ st40_specific_time_init(current_cpu_data.module_clock, frqcr);
+ else
+#endif
+ get_current_frequency_divisors(&ifc, &bfc, &pfc);
+
+ if (rtc_get_time) {
+ rtc_get_time(&xtime);
+ } else {
+ xtime.tv_sec = mktime(2000, 1, 1, 0, 0, 0);
+ xtime.tv_nsec = 0;
+ }
+
+ set_normalized_timespec(&wall_to_monotonic,
+ -xtime.tv_sec, -xtime.tv_nsec);
+
+ if (board_timer_setup) {
+ board_timer_setup(&irq0);
+ } else {
+ setup_irq(TIMER_IRQ, &irq0);
+ }
+
+ /*
+ * for ST40 chips the current_cpu_data should already be set
+ * so not having valid pfc/bfc/ifc shouldn't be a problem
+ */
+ if (!current_cpu_data.master_clock)
+ current_cpu_data.master_clock = current_cpu_data.module_clock * pfc;
+ if (!current_cpu_data.bus_clock)
+ current_cpu_data.bus_clock = current_cpu_data.master_clock / bfc;
+ if (!current_cpu_data.cpu_clock)
+ current_cpu_data.cpu_clock = current_cpu_data.master_clock / ifc;
+
+ printk("CPU clock: %d.%02dMHz\n",
+ (current_cpu_data.cpu_clock / 1000000),
+ (current_cpu_data.cpu_clock % 1000000)/10000);
+ printk("Bus clock: %d.%02dMHz\n",
+ (current_cpu_data.bus_clock / 1000000),
+ (current_cpu_data.bus_clock % 1000000)/10000);
+#ifdef CONFIG_CPU_SUBTYPE_ST40STB1
+ printk("Memory clock: %d.%02dMHz\n",
+ (current_cpu_data.memory_clock / 1000000),
+ (current_cpu_data.memory_clock % 1000000)/10000);
+#endif
+ printk("Module clock: %d.%02dMHz\n",
+ (current_cpu_data.module_clock / 1000000),
+ (current_cpu_data.module_clock % 1000000)/10000);
+
+ interval = (current_cpu_data.module_clock/4 + HZ/2) / HZ;
+
+ printk("Interval = %ld\n", interval);
+
+ /* Start TMU0 */
+ ctrl_outb(0, TMU_TSTR);
+#if !defined(CONFIG_CPU_SUBTYPE_SH7300)
+ ctrl_outb(TMU_TOCR_INIT, TMU_TOCR);
+#endif
+ ctrl_outw(TMU0_TCR_INIT, TMU0_TCR);
+ ctrl_outl(interval, TMU0_TCOR);
+ ctrl_outl(interval, TMU0_TCNT);
+ ctrl_outb(TMU_TSTR_INIT, TMU_TSTR);
+
+#if defined(CONFIG_SH_KGDB)
+ /*
+ * Set up kgdb as requested. We do it here because the serial
+ * init uses the timer vars we just set up for figuring baud.
+ */
+ kgdb_init();
+#endif
+}
diff --git a/arch/sh/kernel/traps.c b/arch/sh/kernel/traps.c
new file mode 100644
index 000000000000..7eb06719d844
--- /dev/null
+++ b/arch/sh/kernel/traps.c
@@ -0,0 +1,712 @@
+/* $Id: traps.c,v 1.17 2004/05/02 01:46:30 sugioka Exp $
+ *
+ * linux/arch/sh/traps.c
+ *
+ * SuperH version: Copyright (C) 1999 Niibe Yutaka
+ * Copyright (C) 2000 Philipp Rumpf
+ * Copyright (C) 2000 David Howells
+ * Copyright (C) 2002, 2003 Paul Mundt
+ */
+
+/*
+ * 'Traps.c' handles hardware traps and faults after we have saved some
+ * state in 'entry.S'.
+ */
+#include <linux/config.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/ptrace.h>
+#include <linux/timer.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/spinlock.h>
+#include <linux/module.h>
+#include <linux/kallsyms.h>
+
+#include <asm/system.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#include <asm/atomic.h>
+#include <asm/processor.h>
+#include <asm/sections.h>
+
+#ifdef CONFIG_SH_KGDB
+#include <asm/kgdb.h>
+#define CHK_REMOTE_DEBUG(regs) \
+{ \
+ if ((kgdb_debug_hook != (kgdb_debug_hook_t *) NULL) && (!user_mode(regs))) \
+ { \
+ (*kgdb_debug_hook)(regs); \
+ } \
+}
+#else
+#define CHK_REMOTE_DEBUG(regs)
+#endif
+
+#define DO_ERROR(trapnr, signr, str, name, tsk) \
+asmlinkage void do_##name(unsigned long r4, unsigned long r5, \
+ unsigned long r6, unsigned long r7, \
+ struct pt_regs regs) \
+{ \
+ unsigned long error_code; \
+ \
+ /* Check if it's a DSP instruction */ \
+ if (is_dsp_inst(&regs)) { \
+ /* Enable DSP mode, and restart instruction. */ \
+ regs.sr |= SR_DSP; \
+ return; \
+ } \
+ \
+ asm volatile("stc r2_bank, %0": "=r" (error_code)); \
+ local_irq_enable(); \
+ tsk->thread.error_code = error_code; \
+ tsk->thread.trap_no = trapnr; \
+ CHK_REMOTE_DEBUG(&regs); \
+ force_sig(signr, tsk); \
+ die_if_no_fixup(str,&regs,error_code); \
+}
+
+#ifdef CONFIG_CPU_SH2
+#define TRAP_RESERVED_INST 4
+#define TRAP_ILLEGAL_SLOT_INST 6
+#else
+#define TRAP_RESERVED_INST 12
+#define TRAP_ILLEGAL_SLOT_INST 13
+#endif
+
+/*
+ * These constants are for searching for possible module text
+ * segments. VMALLOC_OFFSET comes from mm/vmalloc.c; MODULE_RANGE is
+ * a guess of how much space is likely to be vmalloced.
+ */
+#define VMALLOC_OFFSET (8*1024*1024)
+#define MODULE_RANGE (8*1024*1024)
+
+spinlock_t die_lock;
+
+void die(const char * str, struct pt_regs * regs, long err)
+{
+ static int die_counter;
+
+ console_verbose();
+ spin_lock_irq(&die_lock);
+ printk("%s: %04lx [#%d]\n", str, err & 0xffff, ++die_counter);
+ CHK_REMOTE_DEBUG(regs);
+ show_regs(regs);
+ spin_unlock_irq(&die_lock);
+ do_exit(SIGSEGV);
+}
+
+static inline void die_if_kernel(const char * str, struct pt_regs * regs, long err)
+{
+ if (!user_mode(regs))
+ die(str, regs, err);
+}
+
+static int handle_unaligned_notify_count = 10;
+
+/*
+ * try and fix up kernelspace address errors
+ * - userspace errors just cause EFAULT to be returned, resulting in SEGV
+ * - kernel/userspace interfaces cause a jump to an appropriate handler
+ * - other kernel errors are bad
+ * - return 0 if fixed-up, -EFAULT if non-fatal (to the kernel) fault
+ */
+static int die_if_no_fixup(const char * str, struct pt_regs * regs, long err)
+{
+ if (!user_mode(regs))
+ {
+ const struct exception_table_entry *fixup;
+ fixup = search_exception_tables(regs->pc);
+ if (fixup) {
+ regs->pc = fixup->fixup;
+ return 0;
+ }
+ die(str, regs, err);
+ }
+ return -EFAULT;
+}
+
+/*
+ * handle an instruction that does an unaligned memory access by emulating the
+ * desired behaviour
+ * - note that PC _may not_ point to the faulting instruction
+ * (if that instruction is in a branch delay slot)
+ * - return 0 if emulation okay, -EFAULT on existential error
+ */
+static int handle_unaligned_ins(u16 instruction, struct pt_regs *regs)
+{
+ int ret, index, count;
+ unsigned long *rm, *rn;
+ unsigned char *src, *dst;
+
+ index = (instruction>>8)&15; /* 0x0F00 */
+ rn = &regs->regs[index];
+
+ index = (instruction>>4)&15; /* 0x00F0 */
+ rm = &regs->regs[index];
+
+ count = 1<<(instruction&3);
+
+ ret = -EFAULT;
+ switch (instruction>>12) {
+ case 0: /* mov.[bwl] to/from memory via r0+rn */
+ if (instruction & 8) {
+ /* from memory */
+ src = (unsigned char*) *rm;
+ src += regs->regs[0];
+ dst = (unsigned char*) rn;
+ *(unsigned long*)dst = 0;
+
+#ifdef __LITTLE_ENDIAN__
+ if (copy_from_user(dst, src, count))
+ goto fetch_fault;
+
+ if ((count == 2) && dst[1] & 0x80) {
+ dst[2] = 0xff;
+ dst[3] = 0xff;
+ }
+#else
+ dst += 4-count;
+
+ if (__copy_user(dst, src, count))
+ goto fetch_fault;
+
+ if ((count == 2) && dst[2] & 0x80) {
+ dst[0] = 0xff;
+ dst[1] = 0xff;
+ }
+#endif
+ } else {
+ /* to memory */
+ src = (unsigned char*) rm;
+#if !defined(__LITTLE_ENDIAN__)
+ src += 4-count;
+#endif
+ dst = (unsigned char*) *rn;
+ dst += regs->regs[0];
+
+ if (copy_to_user(dst, src, count))
+ goto fetch_fault;
+ }
+ ret = 0;
+ break;
+
+ case 1: /* mov.l Rm,@(disp,Rn) */
+ src = (unsigned char*) rm;
+ dst = (unsigned char*) *rn;
+ dst += (instruction&0x000F)<<2;
+
+ if (copy_to_user(dst,src,4))
+ goto fetch_fault;
+ ret = 0;
+ break;
+
+ case 2: /* mov.[bwl] to memory, possibly with pre-decrement */
+ if (instruction & 4)
+ *rn -= count;
+ src = (unsigned char*) rm;
+ dst = (unsigned char*) *rn;
+#if !defined(__LITTLE_ENDIAN__)
+ src += 4-count;
+#endif
+ if (copy_to_user(dst, src, count))
+ goto fetch_fault;
+ ret = 0;
+ break;
+
+ case 5: /* mov.l @(disp,Rm),Rn */
+ src = (unsigned char*) *rm;
+ src += (instruction&0x000F)<<2;
+ dst = (unsigned char*) rn;
+ *(unsigned long*)dst = 0;
+
+ if (copy_from_user(dst,src,4))
+ goto fetch_fault;
+ ret = 0;
+ break;
+
+ case 6: /* mov.[bwl] from memory, possibly with post-increment */
+ src = (unsigned char*) *rm;
+ if (instruction & 4)
+ *rm += count;
+ dst = (unsigned char*) rn;
+ *(unsigned long*)dst = 0;
+
+#ifdef __LITTLE_ENDIAN__
+ if (copy_from_user(dst, src, count))
+ goto fetch_fault;
+
+ if ((count == 2) && dst[1] & 0x80) {
+ dst[2] = 0xff;
+ dst[3] = 0xff;
+ }
+#else
+ dst += 4-count;
+
+ if (copy_from_user(dst, src, count))
+ goto fetch_fault;
+
+ if ((count == 2) && dst[2] & 0x80) {
+ dst[0] = 0xff;
+ dst[1] = 0xff;
+ }
+#endif
+ ret = 0;
+ break;
+
+ case 8:
+ switch ((instruction&0xFF00)>>8) {
+ case 0x81: /* mov.w R0,@(disp,Rn) */
+ src = (unsigned char*) &regs->regs[0];
+#if !defined(__LITTLE_ENDIAN__)
+ src += 2;
+#endif
+ dst = (unsigned char*) *rm; /* called Rn in the spec */
+ dst += (instruction&0x000F)<<1;
+
+ if (copy_to_user(dst, src, 2))
+ goto fetch_fault;
+ ret = 0;
+ break;
+
+ case 0x85: /* mov.w @(disp,Rm),R0 */
+ src = (unsigned char*) *rm;
+ src += (instruction&0x000F)<<1;
+ dst = (unsigned char*) &regs->regs[0];
+ *(unsigned long*)dst = 0;
+
+#if !defined(__LITTLE_ENDIAN__)
+ dst += 2;
+#endif
+
+ if (copy_from_user(dst, src, 2))
+ goto fetch_fault;
+
+#ifdef __LITTLE_ENDIAN__
+ if (dst[1] & 0x80) {
+ dst[2] = 0xff;
+ dst[3] = 0xff;
+ }
+#else
+ if (dst[2] & 0x80) {
+ dst[0] = 0xff;
+ dst[1] = 0xff;
+ }
+#endif
+ ret = 0;
+ break;
+ }
+ break;
+ }
+ return ret;
+
+ fetch_fault:
+ /* Argh. Address not only misaligned but also non-existent.
+ * Raise an EFAULT and see if it's trapped
+ */
+ return die_if_no_fixup("Fault in unaligned fixup", regs, 0);
+}
+
+/*
+ * emulate the instruction in the delay slot
+ * - fetches the instruction from PC+2
+ */
+static inline int handle_unaligned_delayslot(struct pt_regs *regs)
+{
+ u16 instruction;
+
+ if (copy_from_user(&instruction, (u16 *)(regs->pc+2), 2)) {
+ /* the instruction-fetch faulted */
+ if (user_mode(regs))
+ return -EFAULT;
+
+ /* kernel */
+ die("delay-slot-insn faulting in handle_unaligned_delayslot", regs, 0);
+ }
+
+ return handle_unaligned_ins(instruction,regs);
+}
+
+/*
+ * handle an instruction that does an unaligned memory access
+ * - have to be careful of branch delay-slot instructions that fault
+ * SH3:
+ * - if the branch would be taken PC points to the branch
+ * - if the branch would not be taken, PC points to delay-slot
+ * SH4:
+ * - PC always points to delayed branch
+ * - return 0 if handled, -EFAULT if failed (may not return if in kernel)
+ */
+
+/* Macros to determine offset from current PC for branch instructions */
+/* Explicit type coercion is used to force sign extension where needed */
+#define SH_PC_8BIT_OFFSET(instr) ((((signed char)(instr))*2) + 4)
+#define SH_PC_12BIT_OFFSET(instr) ((((signed short)(instr<<4))>>3) + 4)
+
+static int handle_unaligned_access(u16 instruction, struct pt_regs *regs)
+{
+ u_int rm;
+ int ret, index;
+
+ index = (instruction>>8)&15; /* 0x0F00 */
+ rm = regs->regs[index];
+
+ /* shout about the first ten userspace fixups */
+ if (user_mode(regs) && handle_unaligned_notify_count>0) {
+ handle_unaligned_notify_count--;
+
+ printk("Fixing up unaligned userspace access in \"%s\" pid=%d pc=0x%p ins=0x%04hx\n",
+ current->comm,current->pid,(u16*)regs->pc,instruction);
+ }
+
+ ret = -EFAULT;
+ switch (instruction&0xF000) {
+ case 0x0000:
+ if (instruction==0x000B) {
+ /* rts */
+ ret = handle_unaligned_delayslot(regs);
+ if (ret==0)
+ regs->pc = regs->pr;
+ }
+ else if ((instruction&0x00FF)==0x0023) {
+ /* braf @Rm */
+ ret = handle_unaligned_delayslot(regs);
+ if (ret==0)
+ regs->pc += rm + 4;
+ }
+ else if ((instruction&0x00FF)==0x0003) {
+ /* bsrf @Rm */
+ ret = handle_unaligned_delayslot(regs);
+ if (ret==0) {
+ regs->pr = regs->pc + 4;
+ regs->pc += rm + 4;
+ }
+ }
+ else {
+ /* mov.[bwl] to/from memory via r0+rn */
+ goto simple;
+ }
+ break;
+
+ case 0x1000: /* mov.l Rm,@(disp,Rn) */
+ goto simple;
+
+ case 0x2000: /* mov.[bwl] to memory, possibly with pre-decrement */
+ goto simple;
+
+ case 0x4000:
+ if ((instruction&0x00FF)==0x002B) {
+ /* jmp @Rm */
+ ret = handle_unaligned_delayslot(regs);
+ if (ret==0)
+ regs->pc = rm;
+ }
+ else if ((instruction&0x00FF)==0x000B) {
+ /* jsr @Rm */
+ ret = handle_unaligned_delayslot(regs);
+ if (ret==0) {
+ regs->pr = regs->pc + 4;
+ regs->pc = rm;
+ }
+ }
+ else {
+ /* mov.[bwl] to/from memory via r0+rn */
+ goto simple;
+ }
+ break;
+
+ case 0x5000: /* mov.l @(disp,Rm),Rn */
+ goto simple;
+
+ case 0x6000: /* mov.[bwl] from memory, possibly with post-increment */
+ goto simple;
+
+ case 0x8000: /* bf lab, bf/s lab, bt lab, bt/s lab */
+ switch (instruction&0x0F00) {
+ case 0x0100: /* mov.w R0,@(disp,Rm) */
+ goto simple;
+ case 0x0500: /* mov.w @(disp,Rm),R0 */
+ goto simple;
+ case 0x0B00: /* bf lab - no delayslot*/
+ break;
+ case 0x0F00: /* bf/s lab */
+ ret = handle_unaligned_delayslot(regs);
+ if (ret==0) {
+#if defined(CONFIG_CPU_SH4) || defined(CONFIG_SH7705_CACHE_32KB)
+ if ((regs->sr & 0x00000001) != 0)
+ regs->pc += 4; /* next after slot */
+ else
+#endif
+ regs->pc += SH_PC_8BIT_OFFSET(instruction);
+ }
+ break;
+ case 0x0900: /* bt lab - no delayslot */
+ break;
+ case 0x0D00: /* bt/s lab */
+ ret = handle_unaligned_delayslot(regs);
+ if (ret==0) {
+#if defined(CONFIG_CPU_SH4) || defined(CONFIG_SH7705_CACHE_32KB)
+ if ((regs->sr & 0x00000001) == 0)
+ regs->pc += 4; /* next after slot */
+ else
+#endif
+ regs->pc += SH_PC_8BIT_OFFSET(instruction);
+ }
+ break;
+ }
+ break;
+
+ case 0xA000: /* bra label */
+ ret = handle_unaligned_delayslot(regs);
+ if (ret==0)
+ regs->pc += SH_PC_12BIT_OFFSET(instruction);
+ break;
+
+ case 0xB000: /* bsr label */
+ ret = handle_unaligned_delayslot(regs);
+ if (ret==0) {
+ regs->pr = regs->pc + 4;
+ regs->pc += SH_PC_12BIT_OFFSET(instruction);
+ }
+ break;
+ }
+ return ret;
+
+ /* handle non-delay-slot instruction */
+ simple:
+ ret = handle_unaligned_ins(instruction,regs);
+ if (ret==0)
+ regs->pc += 2;
+ return ret;
+}
+
+/*
+ * Handle various address error exceptions
+ */
+asmlinkage void do_address_error(struct pt_regs *regs,
+ unsigned long writeaccess,
+ unsigned long address)
+{
+ unsigned long error_code;
+ mm_segment_t oldfs;
+ u16 instruction;
+ int tmp;
+
+ asm volatile("stc r2_bank,%0": "=r" (error_code));
+
+ oldfs = get_fs();
+
+ if (user_mode(regs)) {
+ local_irq_enable();
+ current->thread.error_code = error_code;
+ current->thread.trap_no = (writeaccess) ? 8 : 7;
+
+ /* bad PC is not something we can fix */
+ if (regs->pc & 1)
+ goto uspace_segv;
+
+ set_fs(USER_DS);
+ if (copy_from_user(&instruction, (u16 *)(regs->pc), 2)) {
+ /* Argh. Fault on the instruction itself.
+ This should never happen non-SMP
+ */
+ set_fs(oldfs);
+ goto uspace_segv;
+ }
+
+ tmp = handle_unaligned_access(instruction, regs);
+ set_fs(oldfs);
+
+ if (tmp==0)
+ return; /* sorted */
+
+ uspace_segv:
+ printk(KERN_NOTICE "Killing process \"%s\" due to unaligned access\n", current->comm);
+ force_sig(SIGSEGV, current);
+ } else {
+ if (regs->pc & 1)
+ die("unaligned program counter", regs, error_code);
+
+ set_fs(KERNEL_DS);
+ if (copy_from_user(&instruction, (u16 *)(regs->pc), 2)) {
+ /* Argh. Fault on the instruction itself.
+ This should never happen non-SMP
+ */
+ set_fs(oldfs);
+ die("insn faulting in do_address_error", regs, 0);
+ }
+
+ handle_unaligned_access(instruction, regs);
+ set_fs(oldfs);
+ }
+}
+
+#ifdef CONFIG_SH_DSP
+/*
+ * SH-DSP support gerg@snapgear.com.
+ */
+int is_dsp_inst(struct pt_regs *regs)
+{
+ unsigned short inst;
+
+ /*
+ * Safe guard if DSP mode is already enabled or we're lacking
+ * the DSP altogether.
+ */
+ if (!(cpu_data->flags & CPU_HAS_DSP) || (regs->sr & SR_DSP))
+ return 0;
+
+ get_user(inst, ((unsigned short *) regs->pc));
+
+ inst &= 0xf000;
+
+ /* Check for any type of DSP or support instruction */
+ if ((inst == 0xf000) || (inst == 0x4000))
+ return 1;
+
+ return 0;
+}
+#else
+#define is_dsp_inst(regs) (0)
+#endif /* CONFIG_SH_DSP */
+
+DO_ERROR(TRAP_RESERVED_INST, SIGILL, "reserved instruction", reserved_inst, current)
+DO_ERROR(TRAP_ILLEGAL_SLOT_INST, SIGILL, "illegal slot instruction", illegal_slot_inst, current)
+
+asmlinkage void do_exception_error(unsigned long r4, unsigned long r5,
+ unsigned long r6, unsigned long r7,
+ struct pt_regs regs)
+{
+ long ex;
+ asm volatile("stc r2_bank, %0" : "=r" (ex));
+ die_if_kernel("exception", &regs, ex);
+}
+
+#if defined(CONFIG_SH_STANDARD_BIOS)
+void *gdb_vbr_vector;
+
+static inline void __init gdb_vbr_init(void)
+{
+ register unsigned long vbr;
+
+ /*
+ * Read the old value of the VBR register to initialise
+ * the vector through which debug and BIOS traps are
+ * delegated by the Linux trap handler.
+ */
+ asm volatile("stc vbr, %0" : "=r" (vbr));
+
+ gdb_vbr_vector = (void *)(vbr + 0x100);
+ printk("Setting GDB trap vector to 0x%08lx\n",
+ (unsigned long)gdb_vbr_vector);
+}
+#endif
+
+void __init per_cpu_trap_init(void)
+{
+ extern void *vbr_base;
+
+#ifdef CONFIG_SH_STANDARD_BIOS
+ gdb_vbr_init();
+#endif
+
+ /* NOTE: The VBR value should be at P1
+ (or P2, virtural "fixed" address space).
+ It's definitely should not in physical address. */
+
+ asm volatile("ldc %0, vbr"
+ : /* no output */
+ : "r" (&vbr_base)
+ : "memory");
+}
+
+void __init trap_init(void)
+{
+ extern void *exception_handling_table[];
+
+ exception_handling_table[TRAP_RESERVED_INST]
+ = (void *)do_reserved_inst;
+ exception_handling_table[TRAP_ILLEGAL_SLOT_INST]
+ = (void *)do_illegal_slot_inst;
+
+#ifdef CONFIG_CPU_SH4
+ if (!(cpu_data->flags & CPU_HAS_FPU)) {
+ /* For SH-4 lacking an FPU, treat floating point instructions
+ as reserved. */
+ /* entry 64 corresponds to EXPEVT=0x800 */
+ exception_handling_table[64] = (void *)do_reserved_inst;
+ exception_handling_table[65] = (void *)do_illegal_slot_inst;
+ }
+#endif
+
+ /* Setup VBR for boot cpu */
+ per_cpu_trap_init();
+}
+
+void show_stack(struct task_struct *tsk, unsigned long *sp)
+{
+ unsigned long *stack, addr;
+ unsigned long module_start = VMALLOC_START;
+ unsigned long module_end = VMALLOC_END;
+ int i = 1;
+
+ if (tsk && !sp) {
+ sp = (unsigned long *)tsk->thread.sp;
+ }
+
+ if (!sp) {
+ __asm__ __volatile__ (
+ "mov r15, %0\n\t"
+ "stc r7_bank, %1\n\t"
+ : "=r" (module_start),
+ "=r" (module_end)
+ );
+
+ sp = (unsigned long *)module_start;
+ }
+
+ stack = sp;
+
+ printk("\nCall trace: ");
+#ifdef CONFIG_KALLSYMS
+ printk("\n");
+#endif
+
+ while (!kstack_end(stack)) {
+ addr = *stack++;
+ if (((addr >= (unsigned long)_text) &&
+ (addr <= (unsigned long)_etext)) ||
+ ((addr >= module_start) && (addr <= module_end))) {
+ /*
+ * For 80-columns display, 6 entry is maximum.
+ * NOTE: '[<8c00abcd>] ' consumes 13 columns .
+ */
+#ifndef CONFIG_KALLSYMS
+ if (i && ((i % 6) == 0))
+ printk("\n ");
+#endif
+ printk("[<%08lx>] ", addr);
+ print_symbol("%s\n", addr);
+ i++;
+ }
+ }
+
+ printk("\n");
+}
+
+void show_task(unsigned long *sp)
+{
+ show_stack(NULL, sp);
+}
+
+void dump_stack(void)
+{
+ show_stack(NULL, NULL);
+}
+EXPORT_SYMBOL(dump_stack);
diff --git a/arch/sh/kernel/vmlinux.lds.S b/arch/sh/kernel/vmlinux.lds.S
new file mode 100644
index 000000000000..51bdc1cf7838
--- /dev/null
+++ b/arch/sh/kernel/vmlinux.lds.S
@@ -0,0 +1,155 @@
+/* $Id: vmlinux.lds.S,v 1.8 2003/05/16 17:18:14 lethal Exp $
+ * ld script to make SuperH Linux kernel
+ * Written by Niibe Yutaka
+ */
+#include <linux/config.h>
+#include <asm-generic/vmlinux.lds.h>
+
+#ifdef CONFIG_CPU_LITTLE_ENDIAN
+OUTPUT_FORMAT("elf32-sh-linux", "elf32-sh-linux", "elf32-sh-linux")
+#else
+OUTPUT_FORMAT("elf32-shbig-linux", "elf32-shbig-linux", "elf32-shbig-linux")
+#endif
+OUTPUT_ARCH(sh)
+ENTRY(_start)
+SECTIONS
+{
+ . = 0x80000000 + CONFIG_MEMORY_START + CONFIG_ZERO_PAGE_OFFSET;
+ _text = .; /* Text and read-only data */
+ text = .; /* Text and read-only data */
+ .empty_zero_page : {
+ *(.empty_zero_page)
+ } = 0
+ .text : {
+ *(.text)
+ SCHED_TEXT
+ LOCK_TEXT
+ *(.fixup)
+ *(.gnu.warning)
+ } = 0x0009
+
+ . = ALIGN(16); /* Exception table */
+ __start___ex_table = .;
+ __ex_table : { *(__ex_table) }
+ __stop___ex_table = .;
+
+ RODATA
+
+ _etext = .; /* End of text section */
+
+ .data : { /* Data */
+ *(.data)
+
+ /* Align the initial ramdisk image (INITRD) on page boundaries. */
+ . = ALIGN(4096);
+ __rd_start = .;
+ *(.initrd)
+ . = ALIGN(4096);
+ __rd_end = .;
+
+ CONSTRUCTORS
+ }
+
+ . = ALIGN(4096);
+ .data.page_aligned : { *(.data.idt) }
+
+ . = ALIGN(32);
+ __per_cpu_start = .;
+ .data.percpu : { *(.data.percpu) }
+ __per_cpu_end = .;
+ .data.cacheline_aligned : { *(.data.cacheline_aligned) }
+
+ _edata = .; /* End of data section */
+
+ . = ALIGN(8192); /* init_task */
+ .data.init_task : { *(.data.init_task) }
+ /* stack */
+ .stack : { stack = .; _stack = .; }
+
+ . = ALIGN(4096); /* Init code and data */
+ __init_begin = .;
+ _sinittext = .;
+ .init.text : { *(.init.text) }
+ _einittext = .;
+ .init.data : { *(.init.data) }
+ . = ALIGN(16);
+ __setup_start = .;
+ .init.setup : { *(.init.setup) }
+ __setup_end = .;
+ __initcall_start = .;
+ .initcall.init : {
+ *(.initcall1.init)
+ *(.initcall2.init)
+ *(.initcall3.init)
+ *(.initcall4.init)
+ *(.initcall5.init)
+ *(.initcall6.init)
+ *(.initcall7.init)
+ }
+ __initcall_end = .;
+ __con_initcall_start = .;
+ .con_initcall.init : { *(.con_initcall.init) }
+ __con_initcall_end = .;
+ SECURITY_INIT
+ __initramfs_start = .;
+ .init.ramfs : { *(.init.ramfs) }
+ __initramfs_end = .;
+ __machvec_start = .;
+ .init.machvec : { *(.init.machvec) }
+ __machvec_end = .;
+ . = ALIGN(4096);
+ __init_end = .;
+
+ . = ALIGN(4);
+ __bss_start = .; /* BSS */
+ .bss : { *(.bss) }
+
+ . = ALIGN(4);
+ _end = . ;
+
+ /* When something in the kernel is NOT compiled as a module, the
+ * module cleanup code and data are put into these segments. Both
+ * can then be thrown away, as cleanup code is never called unless
+ * it's a module.
+ */
+ /DISCARD/ : {
+ *(.exit.text)
+ *(.exit.data)
+ *(.exitcall.exit)
+ }
+
+ /* Stabs debugging sections. */
+ .stab 0 : { *(.stab) }
+ .stabstr 0 : { *(.stabstr) }
+ .stab.excl 0 : { *(.stab.excl) }
+ .stab.exclstr 0 : { *(.stab.exclstr) }
+ .stab.index 0 : { *(.stab.index) }
+ .stab.indexstr 0 : { *(.stab.indexstr) }
+ .comment 0 : { *(.comment) }
+ /* DWARF debug sections.
+ Symbols in the DWARF debugging section are relative to the beginning
+ of the section so we begin .debug at 0. */
+ /* DWARF 1 */
+ .debug 0 : { *(.debug) }
+ .line 0 : { *(.line) }
+ /* GNU DWARF 1 extensions */
+ .debug_srcinfo 0 : { *(.debug_srcinfo) }
+ .debug_sfnames 0 : { *(.debug_sfnames) }
+ /* DWARF 1.1 and DWARF 2 */
+ .debug_aranges 0 : { *(.debug_aranges) }
+ .debug_pubnames 0 : { *(.debug_pubnames) }
+ /* DWARF 2 */
+ .debug_info 0 : { *(.debug_info) }
+ .debug_abbrev 0 : { *(.debug_abbrev) }
+ .debug_line 0 : { *(.debug_line) }
+ .debug_frame 0 : { *(.debug_frame) }
+ .debug_str 0 : { *(.debug_str) }
+ .debug_loc 0 : { *(.debug_loc) }
+ .debug_macinfo 0 : { *(.debug_macinfo) }
+ /* SGI/MIPS DWARF 2 extensions */
+ .debug_weaknames 0 : { *(.debug_weaknames) }
+ .debug_funcnames 0 : { *(.debug_funcnames) }
+ .debug_typenames 0 : { *(.debug_typenames) }
+ .debug_varnames 0 : { *(.debug_varnames) }
+ /* These must appear regardless of . */
+}
diff --git a/arch/sh/lib/Makefile b/arch/sh/lib/Makefile
new file mode 100644
index 000000000000..b5681e3f9684
--- /dev/null
+++ b/arch/sh/lib/Makefile
@@ -0,0 +1,13 @@
+#
+# Makefile for SuperH-specific library files..
+#
+
+lib-y = delay.o memset.o memmove.o memchr.o \
+ checksum.o strcasecmp.o strlen.o div64.o udivdi3.o \
+ div64-generic.o
+
+memcpy-y := memcpy.o
+memcpy-$(CONFIG_CPU_SH4) := memcpy-sh4.o
+
+lib-y += $(memcpy-y)
+
diff --git a/arch/sh/lib/checksum.S b/arch/sh/lib/checksum.S
new file mode 100644
index 000000000000..7c50dfe68c07
--- /dev/null
+++ b/arch/sh/lib/checksum.S
@@ -0,0 +1,385 @@
+/* $Id: checksum.S,v 1.10 2001/07/06 13:11:32 gniibe Exp $
+ *
+ * INET An implementation of the TCP/IP protocol suite for the LINUX
+ * operating system. INET is implemented using the BSD Socket
+ * interface as the means of communication with the user level.
+ *
+ * IP/TCP/UDP checksumming routines
+ *
+ * Authors: Jorge Cwik, <jorge@laser.satlink.net>
+ * Arnt Gulbrandsen, <agulbra@nvg.unit.no>
+ * Tom May, <ftom@netcom.com>
+ * Pentium Pro/II routines:
+ * Alexander Kjeldaas <astor@guardian.no>
+ * Finn Arne Gangstad <finnag@guardian.no>
+ * Lots of code moved from tcp.c and ip.c; see those files
+ * for more names.
+ *
+ * Changes: Ingo Molnar, converted csum_partial_copy() to 2.1 exception
+ * handling.
+ * Andi Kleen, add zeroing on error
+ * converted to pure assembler
+ *
+ * SuperH version: Copyright (C) 1999 Niibe Yutaka
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <asm/errno.h>
+#include <linux/linkage.h>
+
+/*
+ * computes a partial checksum, e.g. for TCP/UDP fragments
+ */
+
+/*
+ * unsigned int csum_partial(const unsigned char *buf, int len,
+ * unsigned int sum);
+ */
+
+.text
+ENTRY(csum_partial)
+ /*
+ * Experiments with Ethernet and SLIP connections show that buff
+ * is aligned on either a 2-byte or 4-byte boundary. We get at
+ * least a twofold speedup on 486 and Pentium if it is 4-byte aligned.
+ * Fortunately, it is easy to convert 2-byte alignment to 4-byte
+ * alignment for the unrolled loop.
+ */
+ mov r5, r1
+ mov r4, r0
+ tst #2, r0 ! Check alignment.
+ bt 2f ! Jump if alignment is ok.
+ !
+ add #-2, r5 ! Alignment uses up two bytes.
+ cmp/pz r5 !
+ bt/s 1f ! Jump if we had at least two bytes.
+ clrt
+ bra 6f
+ add #2, r5 ! r5 was < 2. Deal with it.
+1:
+ mov r5, r1 ! Save new len for later use.
+ mov.w @r4+, r0
+ extu.w r0, r0
+ addc r0, r6
+ bf 2f
+ add #1, r6
+2:
+ mov #-5, r0
+ shld r0, r5
+ tst r5, r5
+ bt/s 4f ! if it's =0, go to 4f
+ clrt
+ .align 2
+3:
+ mov.l @r4+, r0
+ mov.l @r4+, r2
+ mov.l @r4+, r3
+ addc r0, r6
+ mov.l @r4+, r0
+ addc r2, r6
+ mov.l @r4+, r2
+ addc r3, r6
+ mov.l @r4+, r3
+ addc r0, r6
+ mov.l @r4+, r0
+ addc r2, r6
+ mov.l @r4+, r2
+ addc r3, r6
+ addc r0, r6
+ addc r2, r6
+ movt r0
+ dt r5
+ bf/s 3b
+ cmp/eq #1, r0
+ ! here, we know r5==0
+ addc r5, r6 ! add carry to r6
+4:
+ mov r1, r0
+ and #0x1c, r0
+ tst r0, r0
+ bt/s 6f
+ mov r0, r5
+ shlr2 r5
+ mov #0, r2
+5:
+ addc r2, r6
+ mov.l @r4+, r2
+ movt r0
+ dt r5
+ bf/s 5b
+ cmp/eq #1, r0
+ addc r2, r6
+ addc r5, r6 ! r5==0 here, so it means add carry-bit
+6:
+ mov r1, r5
+ mov #3, r0
+ and r0, r5
+ tst r5, r5
+ bt 9f ! if it's =0 go to 9f
+ mov #2, r1
+ cmp/hs r1, r5
+ bf 7f
+ mov.w @r4+, r0
+ extu.w r0, r0
+ cmp/eq r1, r5
+ bt/s 8f
+ clrt
+ shll16 r0
+ addc r0, r6
+7:
+ mov.b @r4+, r0
+ extu.b r0, r0
+#ifndef __LITTLE_ENDIAN__
+ shll8 r0
+#endif
+8:
+ addc r0, r6
+ mov #0, r0
+ addc r0, r6
+9:
+ rts
+ mov r6, r0
+
+/*
+unsigned int csum_partial_copy_generic (const char *src, char *dst, int len,
+ int sum, int *src_err_ptr, int *dst_err_ptr)
+ */
+
+/*
+ * Copy from ds while checksumming, otherwise like csum_partial
+ *
+ * The macros SRC and DST specify the type of access for the instruction.
+ * thus we can call a custom exception handler for all access types.
+ *
+ * FIXME: could someone double-check whether I haven't mixed up some SRC and
+ * DST definitions? It's damn hard to trigger all cases. I hope I got
+ * them all but there's no guarantee.
+ */
+
+#define SRC(...) \
+ 9999: __VA_ARGS__ ; \
+ .section __ex_table, "a"; \
+ .long 9999b, 6001f ; \
+ .previous
+
+#define DST(...) \
+ 9999: __VA_ARGS__ ; \
+ .section __ex_table, "a"; \
+ .long 9999b, 6002f ; \
+ .previous
+
+!
+! r4: const char *SRC
+! r5: char *DST
+! r6: int LEN
+! r7: int SUM
+!
+! on stack:
+! int *SRC_ERR_PTR
+! int *DST_ERR_PTR
+!
+ENTRY(csum_partial_copy_generic)
+ mov.l r5,@-r15
+ mov.l r6,@-r15
+
+ mov #3,r0 ! Check src and dest are equally aligned
+ mov r4,r1
+ and r0,r1
+ and r5,r0
+ cmp/eq r1,r0
+ bf 3f ! Different alignments, use slow version
+ tst #1,r0 ! Check dest word aligned
+ bf 3f ! If not, do it the slow way
+
+ mov #2,r0
+ tst r0,r5 ! Check dest alignment.
+ bt 2f ! Jump if alignment is ok.
+ add #-2,r6 ! Alignment uses up two bytes.
+ cmp/pz r6 ! Jump if we had at least two bytes.
+ bt/s 1f
+ clrt
+ bra 4f
+ add #2,r6 ! r6 was < 2. Deal with it.
+
+3: ! Handle different src and dest alignments.
+ ! This is not common, so simple byte by byte copy will do.
+ mov r6,r2
+ shlr r6
+ tst r6,r6
+ bt 4f
+ clrt
+ .align 2
+5:
+SRC( mov.b @r4+,r1 )
+SRC( mov.b @r4+,r0 )
+ extu.b r1,r1
+DST( mov.b r1,@r5 )
+DST( mov.b r0,@(1,r5) )
+ extu.b r0,r0
+ add #2,r5
+
+#ifdef __LITTLE_ENDIAN__
+ shll8 r0
+#else
+ shll8 r1
+#endif
+ or r1,r0
+
+ addc r0,r7
+ movt r0
+ dt r6
+ bf/s 5b
+ cmp/eq #1,r0
+ mov #0,r0
+ addc r0, r7
+
+ mov r2, r0
+ tst #1, r0
+ bt 7f
+ bra 5f
+ clrt
+
+ ! src and dest equally aligned, but to a two byte boundary.
+ ! Handle first two bytes as a special case
+ .align 2
+1:
+SRC( mov.w @r4+,r0 )
+DST( mov.w r0,@r5 )
+ add #2,r5
+ extu.w r0,r0
+ addc r0,r7
+ mov #0,r0
+ addc r0,r7
+2:
+ mov r6,r2
+ mov #-5,r0
+ shld r0,r6
+ tst r6,r6
+ bt/s 2f
+ clrt
+ .align 2
+1:
+SRC( mov.l @r4+,r0 )
+SRC( mov.l @r4+,r1 )
+ addc r0,r7
+DST( mov.l r0,@r5 )
+DST( mov.l r1,@(4,r5) )
+ addc r1,r7
+
+SRC( mov.l @r4+,r0 )
+SRC( mov.l @r4+,r1 )
+ addc r0,r7
+DST( mov.l r0,@(8,r5) )
+DST( mov.l r1,@(12,r5) )
+ addc r1,r7
+
+SRC( mov.l @r4+,r0 )
+SRC( mov.l @r4+,r1 )
+ addc r0,r7
+DST( mov.l r0,@(16,r5) )
+DST( mov.l r1,@(20,r5) )
+ addc r1,r7
+
+SRC( mov.l @r4+,r0 )
+SRC( mov.l @r4+,r1 )
+ addc r0,r7
+DST( mov.l r0,@(24,r5) )
+DST( mov.l r1,@(28,r5) )
+ addc r1,r7
+ add #32,r5
+ movt r0
+ dt r6
+ bf/s 1b
+ cmp/eq #1,r0
+ mov #0,r0
+ addc r0,r7
+
+2: mov r2,r6
+ mov #0x1c,r0
+ and r0,r6
+ cmp/pl r6
+ bf/s 4f
+ clrt
+ shlr2 r6
+3:
+SRC( mov.l @r4+,r0 )
+ addc r0,r7
+DST( mov.l r0,@r5 )
+ add #4,r5
+ movt r0
+ dt r6
+ bf/s 3b
+ cmp/eq #1,r0
+ mov #0,r0
+ addc r0,r7
+4: mov r2,r6
+ mov #3,r0
+ and r0,r6
+ cmp/pl r6
+ bf 7f
+ mov #2,r1
+ cmp/hs r1,r6
+ bf 5f
+SRC( mov.w @r4+,r0 )
+DST( mov.w r0,@r5 )
+ extu.w r0,r0
+ add #2,r5
+ cmp/eq r1,r6
+ bt/s 6f
+ clrt
+ shll16 r0
+ addc r0,r7
+5:
+SRC( mov.b @r4+,r0 )
+DST( mov.b r0,@r5 )
+ extu.b r0,r0
+#ifndef __LITTLE_ENDIAN__
+ shll8 r0
+#endif
+6: addc r0,r7
+ mov #0,r0
+ addc r0,r7
+7:
+5000:
+
+# Exception handler:
+.section .fixup, "ax"
+
+6001:
+ mov.l @(8,r15),r0 ! src_err_ptr
+ mov #-EFAULT,r1
+ mov.l r1,@r0
+
+ ! zero the complete destination - computing the rest
+ ! is too much work
+ mov.l @(4,r15),r5 ! dst
+ mov.l @r15,r6 ! len
+ mov #0,r7
+1: mov.b r7,@r5
+ dt r6
+ bf/s 1b
+ add #1,r5
+ mov.l 8000f,r0
+ jmp @r0
+ nop
+ .align 2
+8000: .long 5000b
+
+6002:
+ mov.l @(12,r15),r0 ! dst_err_ptr
+ mov #-EFAULT,r1
+ mov.l r1,@r0
+ mov.l 8001f,r0
+ jmp @r0
+ nop
+ .align 2
+8001: .long 5000b
+
+.previous
+ add #8,r15
+ rts
+ mov r7,r0
diff --git a/arch/sh/lib/delay.c b/arch/sh/lib/delay.c
new file mode 100644
index 000000000000..50b36037d86b
--- /dev/null
+++ b/arch/sh/lib/delay.c
@@ -0,0 +1,41 @@
+/*
+ * Precise Delay Loops for SuperH
+ *
+ * Copyright (C) 1999 Niibe Yutaka & Kaz Kojima
+ */
+
+#include <linux/sched.h>
+#include <linux/delay.h>
+
+void __delay(unsigned long loops)
+{
+ __asm__ __volatile__(
+ "tst %0, %0\n\t"
+ "1:\t"
+ "bf/s 1b\n\t"
+ " dt %0"
+ : "=r" (loops)
+ : "0" (loops)
+ : "t");
+}
+
+inline void __const_udelay(unsigned long xloops)
+{
+ __asm__("dmulu.l %0, %2\n\t"
+ "sts mach, %0"
+ : "=r" (xloops)
+ : "0" (xloops), "r" (cpu_data[_smp_processor_id()].loops_per_jiffy)
+ : "macl", "mach");
+ __delay(xloops * HZ);
+}
+
+void __udelay(unsigned long usecs)
+{
+ __const_udelay(usecs * 0x000010c6); /* 2**32 / 1000000 */
+}
+
+void __ndelay(unsigned long nsecs)
+{
+ __const_udelay(nsecs * 0x00000005);
+}
+
diff --git a/arch/sh/lib/div64-generic.c b/arch/sh/lib/div64-generic.c
new file mode 100644
index 000000000000..c02473afd581
--- /dev/null
+++ b/arch/sh/lib/div64-generic.c
@@ -0,0 +1,19 @@
+/*
+ * Generic __div64_32 wrapper for __xdiv64_32.
+ */
+
+#include <linux/types.h>
+
+extern u64 __xdiv64_32(u64 n, u32 d);
+
+u64 __div64_32(u64 *xp, u32 y)
+{
+ u64 rem;
+ u64 q = __xdiv64_32(*xp, y);
+
+ rem = *xp - q * y;
+ *xp = q;
+
+ return rem;
+}
+
diff --git a/arch/sh/lib/div64.S b/arch/sh/lib/div64.S
new file mode 100644
index 000000000000..eefc275d64a7
--- /dev/null
+++ b/arch/sh/lib/div64.S
@@ -0,0 +1,46 @@
+/*
+ * unsigned long long __xdiv64_32(unsigned long long n, unsigned long d);
+ */
+
+#include <linux/linkage.h>
+
+.text
+ENTRY(__xdiv64_32)
+#ifdef __LITTLE_ENDIAN__
+ mov r4, r0
+ mov r5, r1
+#else
+ mov r4, r1
+ mov r5, r0
+#endif
+ cmp/hs r6, r1
+ bf.s 1f
+ mov #0, r2
+
+ mov r1, r2
+ mov #0, r3
+ div0u
+ .rept 32
+ rotcl r2
+ div1 r6, r3
+ .endr
+ rotcl r2
+ mul.l r6, r2
+ sts macl, r3
+ sub r3, r1
+1:
+ div0u
+ .rept 32
+ rotcl r0
+ div1 r6, r1
+ .endr
+#ifdef __LITTLE_ENDIAN__
+ mov r2, r1
+ rts
+ rotcl r0
+#else
+ rotcl r0
+ mov r0, r1
+ rts
+ mov r2, r0
+#endif
diff --git a/arch/sh/lib/memchr.S b/arch/sh/lib/memchr.S
new file mode 100644
index 000000000000..bc6036ad5706
--- /dev/null
+++ b/arch/sh/lib/memchr.S
@@ -0,0 +1,26 @@
+/* $Id: memchr.S,v 1.1 2000/04/14 16:49:01 mjd Exp $
+ *
+ * "memchr" implementation of SuperH
+ *
+ * Copyright (C) 1999 Niibe Yutaka
+ *
+ */
+
+/*
+ * void *memchr(const void *s, int c, size_t n);
+ */
+
+#include <linux/linkage.h>
+ENTRY(memchr)
+ tst r6,r6
+ bt/s 2f
+ exts.b r5,r5
+1: mov.b @r4,r1
+ cmp/eq r1,r5
+ bt/s 3f
+ dt r6
+ bf/s 1b
+ add #1,r4
+2: mov #0,r4
+3: rts
+ mov r4,r0
diff --git a/arch/sh/lib/memcpy-sh4.S b/arch/sh/lib/memcpy-sh4.S
new file mode 100644
index 000000000000..55f227441f9e
--- /dev/null
+++ b/arch/sh/lib/memcpy-sh4.S
@@ -0,0 +1,800 @@
+/*
+ * "memcpy" implementation of SuperH
+ *
+ * Copyright (C) 1999 Niibe Yutaka
+ * Copyright (c) 2002 STMicroelectronics Ltd
+ * Modified from memcpy.S and micro-optimised for SH4
+ * Stuart Menefy (stuart.menefy@st.com)
+ *
+ */
+#include <linux/linkage.h>
+#include <linux/config.h>
+
+/*
+ * void *memcpy(void *dst, const void *src, size_t n);
+ *
+ * It is assumed that there is no overlap between src and dst.
+ * If there is an overlap, then the results are undefined.
+ */
+
+ !
+ ! GHIJ KLMN OPQR --> ...G HIJK LMNO PQR.
+ !
+
+ ! Size is 16 or greater, and may have trailing bytes
+
+ .balign 32
+.Lcase1:
+ ! Read a long word and write a long word at once
+ ! At the start of each iteration, r7 contains last long load
+ add #-1,r5 ! 79 EX
+ mov r4,r2 ! 5 MT (0 cycles latency)
+
+ mov.l @(r0,r5),r7 ! 21 LS (2 cycles latency)
+ add #-4,r5 ! 50 EX
+
+ add #7,r2 ! 79 EX
+ !
+#ifdef CONFIG_CPU_LITTLE_ENDIAN
+ ! 6 cycles, 4 bytes per iteration
+3: mov.l @(r0,r5),r1 ! 21 LS (latency=2) ! NMLK
+ mov r7, r3 ! 5 MT (latency=0) ! RQPO
+
+ cmp/hi r2,r0 ! 57 MT
+ shll16 r3 ! 103 EX
+
+ mov r1,r6 ! 5 MT (latency=0)
+ shll8 r3 ! 102 EX ! Oxxx
+
+ shlr8 r6 ! 106 EX ! xNML
+ mov r1, r7 ! 5 MT (latency=0)
+
+ or r6,r3 ! 82 EX ! ONML
+ bt/s 3b ! 109 BR
+
+ mov.l r3,@-r0 ! 30 LS
+#else
+3: mov.l @(r0,r5),r1 ! 21 LS (latency=2) ! KLMN
+ mov r7,r3 ! 5 MT (latency=0) ! OPQR
+
+ cmp/hi r2,r0 ! 57 MT
+ shlr16 r3 ! 107 EX
+
+ shlr8 r3 ! 106 EX ! xxxO
+ mov r1,r6 ! 5 MT (latency=0)
+
+ shll8 r6 ! 102 EX ! LMNx
+ mov r1,r7 ! 5 MT (latency=0)
+
+ or r6,r3 ! 82 EX ! LMNO
+ bt/s 3b ! 109 BR
+
+ mov.l r3,@-r0 ! 30 LS
+#endif
+ ! Finally, copy a byte at once, if necessary
+
+ add #4,r5 ! 50 EX
+ cmp/eq r4,r0 ! 54 MT
+
+ add #-6,r2 ! 50 EX
+ bt 9f ! 109 BR
+
+8: cmp/hi r2,r0 ! 57 MT
+ mov.b @(r0,r5),r1 ! 20 LS (latency=2)
+
+ bt/s 8b ! 109 BR
+
+ mov.b r1,@-r0 ! 29 LS
+
+9: rts
+ nop
+
+
+ !
+ ! GHIJ KLMN OPQR --> .GHI JKLM NOPQ R...
+ !
+
+ ! Size is 16 or greater, and may have trailing bytes
+
+ .balign 32
+.Lcase3:
+ ! Read a long word and write a long word at once
+ ! At the start of each iteration, r7 contains last long load
+ add #-3,r5 ! 79 EX
+ mov r4,r2 ! 5 MT (0 cycles latency)
+
+ mov.l @(r0,r5),r7 ! 21 LS (2 cycles latency)
+ add #-4,r5 ! 50 EX
+
+ add #7,r2 ! 79 EX
+ !
+#ifdef CONFIG_CPU_LITTLE_ENDIAN
+ ! 6 cycles, 4 bytes per iteration
+3: mov.l @(r0,r5),r1 ! 21 LS (latency=2) ! NMLK
+ mov r7, r3 ! 5 MT (latency=0) ! RQPO
+
+ cmp/hi r2,r0 ! 57 MT
+ shll8 r3 ! 102 EX ! QPOx
+
+ mov r1,r6 ! 5 MT (latency=0)
+ shlr16 r6 ! 107 EX
+
+ shlr8 r6 ! 106 EX ! xxxN
+ mov r1, r7 ! 5 MT (latency=0)
+
+ or r6,r3 ! 82 EX ! QPON
+ bt/s 3b ! 109 BR
+
+ mov.l r3,@-r0 ! 30 LS
+#else
+3: mov r1,r3 ! OPQR
+ shlr8 r3 ! xOPQ
+ mov.l @(r0,r5),r1 ! KLMN
+ mov r1,r6
+ shll16 r6
+ shll8 r6 ! Nxxx
+ or r6,r3 ! NOPQ
+ cmp/hi r2,r0
+ bt/s 3b
+ mov.l r3,@-r0
+#endif
+
+ ! Finally, copy a byte at once, if necessary
+
+ add #6,r5 ! 50 EX
+ cmp/eq r4,r0 ! 54 MT
+
+ add #-6,r2 ! 50 EX
+ bt 9f ! 109 BR
+
+8: cmp/hi r2,r0 ! 57 MT
+ mov.b @(r0,r5),r1 ! 20 LS (latency=2)
+
+ bt/s 8b ! 109 BR
+
+ mov.b r1,@-r0 ! 29 LS
+
+9: rts
+ nop
+
+ENTRY(memcpy)
+
+ ! Calculate the invariants which will be used in the remainder
+ ! of the code:
+ !
+ ! r4 --> [ ... ] DST [ ... ] SRC
+ ! [ ... ] [ ... ]
+ ! : :
+ ! r0 --> [ ... ] r0+r5 --> [ ... ]
+ !
+ !
+
+ ! Short circuit the common case of src, dst and len being 32 bit aligned
+ ! and test for zero length move
+
+ mov r6, r0 ! 5 MT (0 cycle latency)
+ or r4, r0 ! 82 EX
+
+ or r5, r0 ! 82 EX
+ tst r6, r6 ! 86 MT
+
+ bt/s 99f ! 111 BR (zero len)
+ tst #3, r0 ! 87 MT
+
+ mov r4, r0 ! 5 MT (0 cycle latency)
+ add r6, r0 ! 49 EX
+
+ mov #16, r1 ! 6 EX
+ bt/s .Lcase00 ! 111 BR (aligned)
+
+ sub r4, r5 ! 75 EX
+
+ ! Arguments are not nicely long word aligned or zero len.
+ ! Check for small copies, and if so do a simple byte at a time copy.
+ !
+ ! Deciding on an exact value of 'small' is not easy, as the point at which
+ ! using the optimised routines become worthwhile varies (these are the
+ ! cycle counts for differnet sizes using byte-at-a-time vs. optimised):
+ ! size byte-at-time long word byte
+ ! 16 42 39-40 46-50 50-55
+ ! 24 58 43-44 54-58 62-67
+ ! 36 82 49-50 66-70 80-85
+ ! However the penalty for getting it 'wrong' is much higher for long word
+ ! aligned data (and this is more common), so use a value of 16.
+
+ cmp/gt r6,r1 ! 56 MT
+
+ add #-1,r5 ! 50 EX
+ bf/s 6f ! 108 BR (not small)
+
+ mov r5, r3 ! 5 MT (latency=0)
+ shlr r6 ! 104 EX
+
+ mov.b @(r0,r5),r1 ! 20 LS (latency=2)
+ bf/s 4f ! 111 BR
+
+ add #-1,r3 ! 50 EX
+ tst r6, r6 ! 86 MT
+
+ bt/s 98f ! 110 BR
+ mov.b r1,@-r0 ! 29 LS
+
+ ! 4 cycles, 2 bytes per iteration
+3: mov.b @(r0,r5),r1 ! 20 LS (latency=2)
+
+4: mov.b @(r0,r3),r2 ! 20 LS (latency=2)
+ dt r6 ! 67 EX
+
+ mov.b r1,@-r0 ! 29 LS
+ bf/s 3b ! 111 BR
+
+ mov.b r2,@-r0 ! 29 LS
+98:
+ rts
+ nop
+
+99: rts
+ mov r4, r0
+
+ ! Size is not small, so its worthwhile looking for optimisations.
+ ! First align destination to a long word boundary.
+ !
+ ! r5 = normal value -1
+
+6: tst #3, r0 ! 87 MT
+ mov #3, r3 ! 6 EX
+
+ bt/s 2f ! 111 BR
+ and r0,r3 ! 78 EX
+
+ ! 3 cycles, 1 byte per iteration
+1: dt r3 ! 67 EX
+ mov.b @(r0,r5),r1 ! 19 LS (latency=2)
+
+ add #-1, r6 ! 79 EX
+ bf/s 1b ! 109 BR
+
+ mov.b r1,@-r0 ! 28 LS
+
+2: add #1, r5 ! 79 EX
+
+ ! Now select the appropriate bulk transfer code based on relative
+ ! alignment of src and dst.
+
+ mov r0, r3 ! 5 MT (latency=0)
+
+ mov r5, r0 ! 5 MT (latency=0)
+ tst #1, r0 ! 87 MT
+
+ bf/s 1f ! 111 BR
+ mov #64, r7 ! 6 EX
+
+ ! bit 0 clear
+
+ cmp/ge r7, r6 ! 55 MT
+
+ bt/s 2f ! 111 BR
+ tst #2, r0 ! 87 MT
+
+ ! small
+ bt/s .Lcase0
+ mov r3, r0
+
+ bra .Lcase2
+ nop
+
+ ! big
+2: bt/s .Lcase0b
+ mov r3, r0
+
+ bra .Lcase2b
+ nop
+
+ ! bit 0 set
+1: tst #2, r0 ! 87 MT
+
+ bt/s .Lcase1
+ mov r3, r0
+
+ bra .Lcase3
+ nop
+
+
+ !
+ ! GHIJ KLMN OPQR --> GHIJ KLMN OPQR
+ !
+
+ ! src, dst and size are all long word aligned
+ ! size is non-zero
+
+ .balign 32
+.Lcase00:
+ mov #64, r1 ! 6 EX
+ mov r5, r3 ! 5 MT (latency=0)
+
+ cmp/gt r6, r1 ! 56 MT
+ add #-4, r5 ! 50 EX
+
+ bf .Lcase00b ! 108 BR (big loop)
+ shlr2 r6 ! 105 EX
+
+ shlr r6 ! 104 EX
+ mov.l @(r0, r5), r1 ! 21 LS (latency=2)
+
+ bf/s 4f ! 111 BR
+ add #-8, r3 ! 50 EX
+
+ tst r6, r6 ! 86 MT
+ bt/s 5f ! 110 BR
+
+ mov.l r1,@-r0 ! 30 LS
+
+ ! 4 cycles, 2 long words per iteration
+3: mov.l @(r0, r5), r1 ! 21 LS (latency=2)
+
+4: mov.l @(r0, r3), r2 ! 21 LS (latency=2)
+ dt r6 ! 67 EX
+
+ mov.l r1, @-r0 ! 30 LS
+ bf/s 3b ! 109 BR
+
+ mov.l r2, @-r0 ! 30 LS
+
+5: rts
+ nop
+
+
+ ! Size is 16 or greater and less than 64, but may have trailing bytes
+
+ .balign 32
+.Lcase0:
+ add #-4, r5 ! 50 EX
+ mov r4, r7 ! 5 MT (latency=0)
+
+ mov.l @(r0, r5), r1 ! 21 LS (latency=2)
+ mov #4, r2 ! 6 EX
+
+ add #11, r7 ! 50 EX
+ tst r2, r6 ! 86 MT
+
+ mov r5, r3 ! 5 MT (latency=0)
+ bt/s 4f ! 111 BR
+
+ add #-4, r3 ! 50 EX
+ mov.l r1,@-r0 ! 30 LS
+
+ ! 4 cycles, 2 long words per iteration
+3: mov.l @(r0, r5), r1 ! 21 LS (latency=2)
+
+4: mov.l @(r0, r3), r2 ! 21 LS (latency=2)
+ cmp/hi r7, r0
+
+ mov.l r1, @-r0 ! 30 LS
+ bt/s 3b ! 109 BR
+
+ mov.l r2, @-r0 ! 30 LS
+
+ ! Copy the final 0-3 bytes
+
+ add #3,r5 ! 50 EX
+
+ cmp/eq r0, r4 ! 54 MT
+ add #-10, r7 ! 50 EX
+
+ bt 9f ! 110 BR
+
+ ! 3 cycles, 1 byte per iteration
+1: mov.b @(r0,r5),r1 ! 19 LS
+ cmp/hi r7,r0 ! 57 MT
+
+ bt/s 1b ! 111 BR
+ mov.b r1,@-r0 ! 28 LS
+
+9: rts
+ nop
+
+ ! Size is at least 64 bytes, so will be going round the big loop at least once.
+ !
+ ! r2 = rounded up r4
+ ! r3 = rounded down r0
+
+ .balign 32
+.Lcase0b:
+ add #-4, r5 ! 50 EX
+
+.Lcase00b:
+ mov r0, r3 ! 5 MT (latency=0)
+ mov #(~0x1f), r1 ! 6 EX
+
+ and r1, r3 ! 78 EX
+ mov r4, r2 ! 5 MT (latency=0)
+
+ cmp/eq r3, r0 ! 54 MT
+ add #0x1f, r2 ! 50 EX
+
+ bt/s 1f ! 110 BR
+ and r1, r2 ! 78 EX
+
+ ! copy initial words until cache line aligned
+
+ mov.l @(r0, r5), r1 ! 21 LS (latency=2)
+ tst #4, r0 ! 87 MT
+
+ mov r5, r6 ! 5 MT (latency=0)
+ add #-4, r6 ! 50 EX
+
+ bt/s 4f ! 111 BR
+ add #8, r3 ! 50 EX
+
+ tst #0x18, r0 ! 87 MT
+
+ bt/s 1f ! 109 BR
+ mov.l r1,@-r0 ! 30 LS
+
+ ! 4 cycles, 2 long words per iteration
+3: mov.l @(r0, r5), r1 ! 21 LS (latency=2)
+
+4: mov.l @(r0, r6), r7 ! 21 LS (latency=2)
+ cmp/eq r3, r0 ! 54 MT
+
+ mov.l r1, @-r0 ! 30 LS
+ bf/s 3b ! 109 BR
+
+ mov.l r7, @-r0 ! 30 LS
+
+ ! Copy the cache line aligned blocks
+ !
+ ! In use: r0, r2, r4, r5
+ ! Scratch: r1, r3, r6, r7
+ !
+ ! We could do this with the four scratch registers, but if src
+ ! and dest hit the same cache line, this will thrash, so make
+ ! use of additional registers.
+ !
+ ! We also need r0 as a temporary (for movca), so 'undo' the invariant:
+ ! r5: src (was r0+r5)
+ ! r1: dest (was r0)
+ ! this can be reversed at the end, so we don't need to save any extra
+ ! state.
+ !
+1: mov.l r8, @-r15 ! 30 LS
+ add r0, r5 ! 49 EX
+
+ mov.l r9, @-r15 ! 30 LS
+ mov r0, r1 ! 5 MT (latency=0)
+
+ mov.l r10, @-r15 ! 30 LS
+ add #-0x1c, r5 ! 50 EX
+
+ mov.l r11, @-r15 ! 30 LS
+
+ ! 16 cycles, 32 bytes per iteration
+2: mov.l @(0x00,r5),r0 ! 18 LS (latency=2)
+ add #-0x20, r1 ! 50 EX
+ mov.l @(0x04,r5),r3 ! 18 LS (latency=2)
+ mov.l @(0x08,r5),r6 ! 18 LS (latency=2)
+ mov.l @(0x0c,r5),r7 ! 18 LS (latency=2)
+ mov.l @(0x10,r5),r8 ! 18 LS (latency=2)
+ mov.l @(0x14,r5),r9 ! 18 LS (latency=2)
+ mov.l @(0x18,r5),r10 ! 18 LS (latency=2)
+ mov.l @(0x1c,r5),r11 ! 18 LS (latency=2)
+ movca.l r0,@r1 ! 40 LS (latency=3-7)
+ mov.l r3,@(0x04,r1) ! 33 LS
+ mov.l r6,@(0x08,r1) ! 33 LS
+ mov.l r7,@(0x0c,r1) ! 33 LS
+
+ mov.l r8,@(0x10,r1) ! 33 LS
+ add #-0x20, r5 ! 50 EX
+
+ mov.l r9,@(0x14,r1) ! 33 LS
+ cmp/eq r2,r1 ! 54 MT
+
+ mov.l r10,@(0x18,r1) ! 33 LS
+ bf/s 2b ! 109 BR
+
+ mov.l r11,@(0x1c,r1) ! 33 LS
+
+ mov r1, r0 ! 5 MT (latency=0)
+
+ mov.l @r15+, r11 ! 15 LS
+ sub r1, r5 ! 75 EX
+
+ mov.l @r15+, r10 ! 15 LS
+ cmp/eq r4, r0 ! 54 MT
+
+ bf/s 1f ! 109 BR
+ mov.l @r15+, r9 ! 15 LS
+
+ rts
+1: mov.l @r15+, r8 ! 15 LS
+ sub r4, r1 ! 75 EX (len remaining)
+
+ ! number of trailing bytes is non-zero
+ !
+ ! invariants restored (r5 already decremented by 4)
+ ! also r1=num bytes remaining
+
+ mov #4, r2 ! 6 EX
+ mov r4, r7 ! 5 MT (latency=0)
+
+ add #0x1c, r5 ! 50 EX (back to -4)
+ cmp/hs r2, r1 ! 58 MT
+
+ bf/s 5f ! 108 BR
+ add #11, r7 ! 50 EX
+
+ mov.l @(r0, r5), r6 ! 21 LS (latency=2)
+ tst r2, r1 ! 86 MT
+
+ mov r5, r3 ! 5 MT (latency=0)
+ bt/s 4f ! 111 BR
+
+ add #-4, r3 ! 50 EX
+ cmp/hs r2, r1 ! 58 MT
+
+ bt/s 5f ! 111 BR
+ mov.l r6,@-r0 ! 30 LS
+
+ ! 4 cycles, 2 long words per iteration
+3: mov.l @(r0, r5), r6 ! 21 LS (latency=2)
+
+4: mov.l @(r0, r3), r2 ! 21 LS (latency=2)
+ cmp/hi r7, r0
+
+ mov.l r6, @-r0 ! 30 LS
+ bt/s 3b ! 109 BR
+
+ mov.l r2, @-r0 ! 30 LS
+
+ ! Copy the final 0-3 bytes
+
+5: cmp/eq r0, r4 ! 54 MT
+ add #-10, r7 ! 50 EX
+
+ bt 9f ! 110 BR
+ add #3,r5 ! 50 EX
+
+ ! 3 cycles, 1 byte per iteration
+1: mov.b @(r0,r5),r1 ! 19 LS
+ cmp/hi r7,r0 ! 57 MT
+
+ bt/s 1b ! 111 BR
+ mov.b r1,@-r0 ! 28 LS
+
+9: rts
+ nop
+
+ !
+ ! GHIJ KLMN OPQR --> ..GH IJKL MNOP QR..
+ !
+
+ .balign 32
+.Lcase2:
+ ! Size is 16 or greater and less then 64, but may have trailing bytes
+
+2: mov r5, r6 ! 5 MT (latency=0)
+ add #-2,r5 ! 50 EX
+
+ mov r4,r2 ! 5 MT (latency=0)
+ add #-4,r6 ! 50 EX
+
+ add #7,r2 ! 50 EX
+3: mov.w @(r0,r5),r1 ! 20 LS (latency=2)
+
+ mov.w @(r0,r6),r3 ! 20 LS (latency=2)
+ cmp/hi r2,r0 ! 57 MT
+
+ mov.w r1,@-r0 ! 29 LS
+ bt/s 3b ! 111 BR
+
+ mov.w r3,@-r0 ! 29 LS
+
+ bra 10f
+ nop
+
+
+ .balign 32
+.Lcase2b:
+ ! Size is at least 64 bytes, so will be going round the big loop at least once.
+ !
+ ! r2 = rounded up r4
+ ! r3 = rounded down r0
+
+ mov r0, r3 ! 5 MT (latency=0)
+ mov #(~0x1f), r1 ! 6 EX
+
+ and r1, r3 ! 78 EX
+ mov r4, r2 ! 5 MT (latency=0)
+
+ cmp/eq r3, r0 ! 54 MT
+ add #0x1f, r2 ! 50 EX
+
+ add #-2, r5 ! 50 EX
+ bt/s 1f ! 110 BR
+ and r1, r2 ! 78 EX
+
+ ! Copy a short word one at a time until we are cache line aligned
+ ! Normal values: r0, r2, r3, r4
+ ! Unused: r1, r6, r7
+ ! Mod: r5 (=r5-2)
+ !
+ add #2, r3 ! 50 EX
+
+2: mov.w @(r0,r5),r1 ! 20 LS (latency=2)
+ cmp/eq r3,r0 ! 54 MT
+
+ bf/s 2b ! 111 BR
+
+ mov.w r1,@-r0 ! 29 LS
+
+ ! Copy the cache line aligned blocks
+ !
+ ! In use: r0, r2, r4, r5 (=r5-2)
+ ! Scratch: r1, r3, r6, r7
+ !
+ ! We could do this with the four scratch registers, but if src
+ ! and dest hit the same cache line, this will thrash, so make
+ ! use of additional registers.
+ !
+ ! We also need r0 as a temporary (for movca), so 'undo' the invariant:
+ ! r5: src (was r0+r5)
+ ! r1: dest (was r0)
+ ! this can be reversed at the end, so we don't need to save any extra
+ ! state.
+ !
+1: mov.l r8, @-r15 ! 30 LS
+ add r0, r5 ! 49 EX
+
+ mov.l r9, @-r15 ! 30 LS
+ mov r0, r1 ! 5 MT (latency=0)
+
+ mov.l r10, @-r15 ! 30 LS
+ add #-0x1e, r5 ! 50 EX
+
+ mov.l r11, @-r15 ! 30 LS
+
+ mov.l r12, @-r15 ! 30 LS
+
+ ! 17 cycles, 32 bytes per iteration
+#ifdef CONFIG_CPU_LITTLE_ENDIAN
+2: mov.w @r5+, r0 ! 14 LS (latency=2) ..JI
+ add #-0x20, r1 ! 50 EX
+
+ mov.l @r5+, r3 ! 15 LS (latency=2) NMLK
+
+ mov.l @r5+, r6 ! 15 LS (latency=2) RQPO
+ shll16 r0 ! 103 EX JI..
+
+ mov.l @r5+, r7 ! 15 LS (latency=2)
+ xtrct r3, r0 ! 48 EX LKJI
+
+ mov.l @r5+, r8 ! 15 LS (latency=2)
+ xtrct r6, r3 ! 48 EX PONM
+
+ mov.l @r5+, r9 ! 15 LS (latency=2)
+ xtrct r7, r6 ! 48 EX
+
+ mov.l @r5+, r10 ! 15 LS (latency=2)
+ xtrct r8, r7 ! 48 EX
+
+ mov.l @r5+, r11 ! 15 LS (latency=2)
+ xtrct r9, r8 ! 48 EX
+
+ mov.w @r5+, r12 ! 15 LS (latency=2)
+ xtrct r10, r9 ! 48 EX
+
+ movca.l r0,@r1 ! 40 LS (latency=3-7)
+ xtrct r11, r10 ! 48 EX
+
+ mov.l r3, @(0x04,r1) ! 33 LS
+ xtrct r12, r11 ! 48 EX
+
+ mov.l r6, @(0x08,r1) ! 33 LS
+
+ mov.l r7, @(0x0c,r1) ! 33 LS
+
+ mov.l r8, @(0x10,r1) ! 33 LS
+ add #-0x40, r5 ! 50 EX
+
+ mov.l r9, @(0x14,r1) ! 33 LS
+ cmp/eq r2,r1 ! 54 MT
+
+ mov.l r10, @(0x18,r1) ! 33 LS
+ bf/s 2b ! 109 BR
+
+ mov.l r11, @(0x1c,r1) ! 33 LS
+#else
+2: mov.w @(0x1e,r5), r0 ! 17 LS (latency=2)
+ add #-2, r5 ! 50 EX
+
+ mov.l @(0x1c,r5), r3 ! 18 LS (latency=2)
+ add #-4, r1 ! 50 EX
+
+ mov.l @(0x18,r5), r6 ! 18 LS (latency=2)
+ shll16 r0 ! 103 EX
+
+ mov.l @(0x14,r5), r7 ! 18 LS (latency=2)
+ xtrct r3, r0 ! 48 EX
+
+ mov.l @(0x10,r5), r8 ! 18 LS (latency=2)
+ xtrct r6, r3 ! 48 EX
+
+ mov.l @(0x0c,r5), r9 ! 18 LS (latency=2)
+ xtrct r7, r6 ! 48 EX
+
+ mov.l @(0x08,r5), r10 ! 18 LS (latency=2)
+ xtrct r8, r7 ! 48 EX
+
+ mov.l @(0x04,r5), r11 ! 18 LS (latency=2)
+ xtrct r9, r8 ! 48 EX
+
+ mov.w @(0x02,r5), r12 ! 18 LS (latency=2)
+ xtrct r10, r9 ! 48 EX
+
+ movca.l r0,@r1 ! 40 LS (latency=3-7)
+ add #-0x1c, r1 ! 50 EX
+
+ mov.l r3, @(0x1c,r1) ! 33 LS
+ xtrct r11, r10 ! 48 EX
+
+ mov.l r6, @(0x18,r1) ! 33 LS
+ xtrct r12, r11 ! 48 EX
+
+ mov.l r7, @(0x14,r1) ! 33 LS
+
+ mov.l r8, @(0x10,r1) ! 33 LS
+ add #-0x3e, r5 ! 50 EX
+
+ mov.l r9, @(0x0c,r1) ! 33 LS
+ cmp/eq r2,r1 ! 54 MT
+
+ mov.l r10, @(0x08,r1) ! 33 LS
+ bf/s 2b ! 109 BR
+
+ mov.l r11, @(0x04,r1) ! 33 LS
+#endif
+
+ mov.l @r15+, r12
+ mov r1, r0 ! 5 MT (latency=0)
+
+ mov.l @r15+, r11 ! 15 LS
+ sub r1, r5 ! 75 EX
+
+ mov.l @r15+, r10 ! 15 LS
+ cmp/eq r4, r0 ! 54 MT
+
+ bf/s 1f ! 109 BR
+ mov.l @r15+, r9 ! 15 LS
+
+ rts
+1: mov.l @r15+, r8 ! 15 LS
+
+ add #0x1e, r5 ! 50 EX
+
+ ! Finish off a short word at a time
+ ! r5 must be invariant - 2
+10: mov r4,r2 ! 5 MT (latency=0)
+ add #1,r2 ! 50 EX
+
+ cmp/hi r2, r0 ! 57 MT
+ bf/s 1f ! 109 BR
+
+ add #2, r2 ! 50 EX
+
+3: mov.w @(r0,r5),r1 ! 20 LS
+ cmp/hi r2,r0 ! 57 MT
+
+ bt/s 3b ! 109 BR
+
+ mov.w r1,@-r0 ! 29 LS
+1:
+
+ !
+ ! Finally, copy the last byte if necessary
+ cmp/eq r4,r0 ! 54 MT
+ bt/s 9b
+ add #1,r5
+ mov.b @(r0,r5),r1
+ rts
+ mov.b r1,@-r0
+
diff --git a/arch/sh/lib/memcpy.S b/arch/sh/lib/memcpy.S
new file mode 100644
index 000000000000..232fab34c261
--- /dev/null
+++ b/arch/sh/lib/memcpy.S
@@ -0,0 +1,227 @@
+/* $Id: memcpy.S,v 1.3 2001/07/27 11:50:52 gniibe Exp $
+ *
+ * "memcpy" implementation of SuperH
+ *
+ * Copyright (C) 1999 Niibe Yutaka
+ *
+ */
+
+/*
+ * void *memcpy(void *dst, const void *src, size_t n);
+ * No overlap between the memory of DST and of SRC are assumed.
+ */
+
+#include <linux/linkage.h>
+ENTRY(memcpy)
+ tst r6,r6
+ bt/s 9f ! if n=0, do nothing
+ mov r4,r0
+ sub r4,r5 ! From here, r5 has the distance to r0
+ add r6,r0 ! From here, r0 points the end of copying point
+ mov #12,r1
+ cmp/gt r6,r1
+ bt/s 7f ! if it's too small, copy a byte at once
+ add #-1,r5
+ add #1,r5
+ ! From here, r6 is free
+ !
+ ! r4 --> [ ... ] DST [ ... ] SRC
+ ! [ ... ] [ ... ]
+ ! : :
+ ! r0 --> [ ... ] r0+r5 --> [ ... ]
+ !
+ !
+ mov r5,r1
+ mov #3,r2
+ and r2,r1
+ shll2 r1
+ mov r0,r3 ! Save the value on R0 to R3
+ mova jmptable,r0
+ add r1,r0
+ mov.l @r0,r1
+ jmp @r1
+ mov r3,r0 ! and back to R0
+ .balign 4
+jmptable:
+ .long case0
+ .long case1
+ .long case2
+ .long case3
+
+ ! copy a byte at once
+7: mov r4,r2
+ add #1,r2
+8:
+ cmp/hi r2,r0
+ mov.b @(r0,r5),r1
+ bt/s 8b ! while (r0>r2)
+ mov.b r1,@-r0
+9:
+ rts
+ nop
+
+case0:
+ !
+ ! GHIJ KLMN OPQR --> GHIJ KLMN OPQR
+ !
+ ! First, align to long word boundary
+ mov r0,r3
+ and r2,r3
+ tst r3,r3
+ bt/s 2f
+ add #-4,r5
+ add #3,r5
+1: dt r3
+ mov.b @(r0,r5),r1
+ bf/s 1b
+ mov.b r1,@-r0
+ !
+ add #-3,r5
+2: ! Second, copy a long word at once
+ mov r4,r2
+ add #7,r2
+3: mov.l @(r0,r5),r1
+ cmp/hi r2,r0
+ bt/s 3b
+ mov.l r1,@-r0
+ !
+ ! Third, copy a byte at once, if necessary
+ cmp/eq r4,r0
+ bt/s 9b
+ add #3,r5
+ bra 8b
+ add #-6,r2
+
+case1:
+ !
+ ! GHIJ KLMN OPQR --> ...G HIJK LMNO PQR.
+ !
+ ! First, align to long word boundary
+ mov r0,r3
+ and r2,r3
+ tst r3,r3
+ bt/s 2f
+ add #-1,r5
+1: dt r3
+ mov.b @(r0,r5),r1
+ bf/s 1b
+ mov.b r1,@-r0
+ !
+2: ! Second, read a long word and write a long word at once
+ mov.l @(r0,r5),r1
+ add #-4,r5
+ mov r4,r2
+ add #7,r2
+ !
+#ifdef __LITTLE_ENDIAN__
+3: mov r1,r3 ! RQPO
+ shll16 r3
+ shll8 r3 ! Oxxx
+ mov.l @(r0,r5),r1 ! NMLK
+ mov r1,r6
+ shlr8 r6 ! xNML
+ or r6,r3 ! ONML
+ cmp/hi r2,r0
+ bt/s 3b
+ mov.l r3,@-r0
+#else
+3: mov r1,r3 ! OPQR
+ shlr16 r3
+ shlr8 r3 ! xxxO
+ mov.l @(r0,r5),r1 ! KLMN
+ mov r1,r6
+ shll8 r6 ! LMNx
+ or r6,r3 ! LMNO
+ cmp/hi r2,r0
+ bt/s 3b
+ mov.l r3,@-r0
+#endif
+ !
+ ! Third, copy a byte at once, if necessary
+ cmp/eq r4,r0
+ bt/s 9b
+ add #4,r5
+ bra 8b
+ add #-6,r2
+
+case2:
+ !
+ ! GHIJ KLMN OPQR --> ..GH IJKL MNOP QR..
+ !
+ ! First, align to word boundary
+ tst #1,r0
+ bt/s 2f
+ add #-1,r5
+ mov.b @(r0,r5),r1
+ mov.b r1,@-r0
+ !
+2: ! Second, read a word and write a word at once
+ add #-1,r5
+ mov r4,r2
+ add #3,r2
+ !
+3: mov.w @(r0,r5),r1
+ cmp/hi r2,r0
+ bt/s 3b
+ mov.w r1,@-r0
+ !
+ ! Third, copy a byte at once, if necessary
+ cmp/eq r4,r0
+ bt/s 9b
+ add #1,r5
+ mov.b @(r0,r5),r1
+ rts
+ mov.b r1,@-r0
+
+case3:
+ !
+ ! GHIJ KLMN OPQR --> .GHI JKLM NOPQ R...
+ !
+ ! First, align to long word boundary
+ mov r0,r3
+ and r2,r3
+ tst r3,r3
+ bt/s 2f
+ add #-1,r5
+1: dt r3
+ mov.b @(r0,r5),r1
+ bf/s 1b
+ mov.b r1,@-r0
+ !
+2: ! Second, read a long word and write a long word at once
+ add #-2,r5
+ mov.l @(r0,r5),r1
+ add #-4,r5
+ mov r4,r2
+ add #7,r2
+ !
+#ifdef __LITTLE_ENDIAN__
+3: mov r1,r3 ! RQPO
+ shll8 r3 ! QPOx
+ mov.l @(r0,r5),r1 ! NMLK
+ mov r1,r6
+ shlr16 r6
+ shlr8 r6 ! xxxN
+ or r6,r3 ! QPON
+ cmp/hi r2,r0
+ bt/s 3b
+ mov.l r3,@-r0
+#else
+3: mov r1,r3 ! OPQR
+ shlr8 r3 ! xOPQ
+ mov.l @(r0,r5),r1 ! KLMN
+ mov r1,r6
+ shll16 r6
+ shll8 r6 ! Nxxx
+ or r6,r3 ! NOPQ
+ cmp/hi r2,r0
+ bt/s 3b
+ mov.l r3,@-r0
+#endif
+ !
+ ! Third, copy a byte at once, if necessary
+ cmp/eq r4,r0
+ bt/s 9b
+ add #6,r5
+ bra 8b
+ add #-6,r2
diff --git a/arch/sh/lib/memmove.S b/arch/sh/lib/memmove.S
new file mode 100644
index 000000000000..5a2211f09202
--- /dev/null
+++ b/arch/sh/lib/memmove.S
@@ -0,0 +1,254 @@
+/* $Id: memmove.S,v 1.2 2001/07/27 11:51:09 gniibe Exp $
+ *
+ * "memmove" implementation of SuperH
+ *
+ * Copyright (C) 1999 Niibe Yutaka
+ *
+ */
+
+/*
+ * void *memmove(void *dst, const void *src, size_t n);
+ * The memory areas may overlap.
+ */
+
+#include <linux/linkage.h>
+ENTRY(memmove)
+ ! if dest > src, call memcpy (it copies in decreasing order)
+ cmp/hi r5,r4
+ bf 1f
+ mov.l 2f,r0
+ jmp @r0
+ nop
+ .balign 4
+2: .long memcpy
+1:
+ sub r5,r4 ! From here, r4 has the distance to r0
+ tst r6,r6
+ bt/s 9f ! if n=0, do nothing
+ mov r5,r0
+ add r6,r5
+ mov #12,r1
+ cmp/gt r6,r1
+ bt/s 8f ! if it's too small, copy a byte at once
+ add #-1,r4
+ add #1,r4
+ !
+ ! [ ... ] DST [ ... ] SRC
+ ! [ ... ] [ ... ]
+ ! : :
+ ! r0+r4--> [ ... ] r0 --> [ ... ]
+ ! : :
+ ! [ ... ] [ ... ]
+ ! r5 -->
+ !
+ mov r4,r1
+ mov #3,r2
+ and r2,r1
+ shll2 r1
+ mov r0,r3 ! Save the value on R0 to R3
+ mova jmptable,r0
+ add r1,r0
+ mov.l @r0,r1
+ jmp @r1
+ mov r3,r0 ! and back to R0
+ .balign 4
+jmptable:
+ .long case0
+ .long case1
+ .long case2
+ .long case3
+
+ ! copy a byte at once
+8: mov.b @r0+,r1
+ cmp/hs r5,r0
+ bf/s 8b ! while (r0<r5)
+ mov.b r1,@(r0,r4)
+ add #1,r4
+9:
+ add r4,r0
+ rts
+ sub r6,r0
+
+case_none:
+ bra 8b
+ add #-1,r4
+
+case0:
+ !
+ ! GHIJ KLMN OPQR --> GHIJ KLMN OPQR
+ !
+ ! First, align to long word boundary
+ mov r0,r3
+ and r2,r3
+ tst r3,r3
+ bt/s 2f
+ add #-1,r4
+ mov #4,r2
+ sub r3,r2
+1: dt r2
+ mov.b @r0+,r1
+ bf/s 1b
+ mov.b r1,@(r0,r4)
+ !
+2: ! Second, copy a long word at once
+ add #-3,r4
+ add #-3,r5
+3: mov.l @r0+,r1
+ cmp/hs r5,r0
+ bf/s 3b
+ mov.l r1,@(r0,r4)
+ add #3,r5
+ !
+ ! Third, copy a byte at once, if necessary
+ cmp/eq r5,r0
+ bt/s 9b
+ add #4,r4
+ bra 8b
+ add #-1,r4
+
+case3:
+ !
+ ! GHIJ KLMN OPQR --> ...G HIJK LMNO PQR.
+ !
+ ! First, align to long word boundary
+ mov r0,r3
+ and r2,r3
+ tst r3,r3
+ bt/s 2f
+ add #-1,r4
+ mov #4,r2
+ sub r3,r2
+1: dt r2
+ mov.b @r0+,r1
+ bf/s 1b
+ mov.b r1,@(r0,r4)
+ !
+2: ! Second, read a long word and write a long word at once
+ add #-2,r4
+ mov.l @(r0,r4),r1
+ add #-7,r5
+ add #-4,r4
+ !
+#ifdef __LITTLE_ENDIAN__
+ shll8 r1
+3: mov r1,r3 ! JIHG
+ shlr8 r3 ! xJIH
+ mov.l @r0+,r1 ! NMLK
+ mov r1,r2
+ shll16 r2
+ shll8 r2 ! Kxxx
+ or r2,r3 ! KJIH
+ cmp/hs r5,r0
+ bf/s 3b
+ mov.l r3,@(r0,r4)
+#else
+ shlr8 r1
+3: mov r1,r3 ! GHIJ
+ shll8 r3 ! HIJx
+ mov.l @r0+,r1 ! KLMN
+ mov r1,r2
+ shlr16 r2
+ shlr8 r2 ! xxxK
+ or r2,r3 ! HIJK
+ cmp/hs r5,r0
+ bf/s 3b
+ mov.l r3,@(r0,r4)
+#endif
+ add #7,r5
+ !
+ ! Third, copy a byte at once, if necessary
+ cmp/eq r5,r0
+ bt/s 9b
+ add #7,r4
+ add #-3,r0
+ bra 8b
+ add #-1,r4
+
+case2:
+ !
+ ! GHIJ KLMN OPQR --> ..GH IJKL MNOP QR..
+ !
+ ! First, align to word boundary
+ tst #1,r0
+ bt/s 2f
+ add #-1,r4
+ mov.b @r0+,r1
+ mov.b r1,@(r0,r4)
+ !
+2: ! Second, read a word and write a word at once
+ add #-1,r4
+ add #-1,r5
+ !
+3: mov.w @r0+,r1
+ cmp/hs r5,r0
+ bf/s 3b
+ mov.w r1,@(r0,r4)
+ add #1,r5
+ !
+ ! Third, copy a byte at once, if necessary
+ cmp/eq r5,r0
+ bt/s 9b
+ add #2,r4
+ mov.b @r0,r1
+ mov.b r1,@(r0,r4)
+ bra 9b
+ add #1,r0
+
+case1:
+ !
+ ! GHIJ KLMN OPQR --> .GHI JKLM NOPQ R...
+ !
+ ! First, align to long word boundary
+ mov r0,r3
+ and r2,r3
+ tst r3,r3
+ bt/s 2f
+ add #-1,r4
+ mov #4,r2
+ sub r3,r2
+1: dt r2
+ mov.b @r0+,r1
+ bf/s 1b
+ mov.b r1,@(r0,r4)
+ !
+2: ! Second, read a long word and write a long word at once
+ mov.l @(r0,r4),r1
+ add #-7,r5
+ add #-4,r4
+ !
+#ifdef __LITTLE_ENDIAN__
+ shll16 r1
+ shll8 r1
+3: mov r1,r3 ! JIHG
+ shlr16 r3
+ shlr8 r3 ! xxxJ
+ mov.l @r0+,r1 ! NMLK
+ mov r1,r2
+ shll8 r2 ! MLKx
+ or r2,r3 ! MLKJ
+ cmp/hs r5,r0
+ bf/s 3b
+ mov.l r3,@(r0,r4)
+#else
+ shlr16 r1
+ shlr8 r1
+3: mov r1,r3 ! GHIJ
+ shll16 r3
+ shll8 r3 ! Jxxx
+ mov.l @r0+,r1 ! KLMN
+ mov r1,r2
+ shlr8 r2 ! xKLM
+ or r2,r3 ! JKLM
+ cmp/hs r5,r0
+ bf/s 3b ! while(r0<r5)
+ mov.l r3,@(r0,r4)
+#endif
+ add #7,r5
+ !
+ ! Third, copy a byte at once, if necessary
+ cmp/eq r5,r0
+ bt/s 9b
+ add #5,r4
+ add #-3,r0
+ bra 8b
+ add #-1,r4
diff --git a/arch/sh/lib/memset.S b/arch/sh/lib/memset.S
new file mode 100644
index 000000000000..95670090680e
--- /dev/null
+++ b/arch/sh/lib/memset.S
@@ -0,0 +1,57 @@
+/* $Id: memset.S,v 1.1 2000/04/14 16:49:01 mjd Exp $
+ *
+ * "memset" implementation of SuperH
+ *
+ * Copyright (C) 1999 Niibe Yutaka
+ *
+ */
+
+/*
+ * void *memset(void *s, int c, size_t n);
+ */
+
+#include <linux/linkage.h>
+
+ENTRY(memset)
+ tst r6,r6
+ bt/s 5f ! if n=0, do nothing
+ add r6,r4
+ mov #12,r0
+ cmp/gt r6,r0
+ bt/s 4f ! if it's too small, set a byte at once
+ mov r4,r0
+ and #3,r0
+ cmp/eq #0,r0
+ bt/s 2f ! It's aligned
+ sub r0,r6
+1:
+ dt r0
+ bf/s 1b
+ mov.b r5,@-r4
+2: ! make VVVV
+ swap.b r5,r0 ! V0
+ or r0,r5 ! VV
+ swap.w r5,r0 ! VV00
+ or r0,r5 ! VVVV
+ !
+ mov r6,r0
+ shlr2 r0
+ shlr r0 ! r0 = r6 >> 3
+3:
+ dt r0
+ mov.l r5,@-r4 ! set 8-byte at once
+ bf/s 3b
+ mov.l r5,@-r4
+ !
+ mov #7,r0
+ and r0,r6
+ tst r6,r6
+ bt 5f
+ ! fill bytes
+4:
+ dt r6
+ bf/s 4b
+ mov.b r5,@-r4
+5:
+ rts
+ mov r4,r0
diff --git a/arch/sh/lib/strcasecmp.c b/arch/sh/lib/strcasecmp.c
new file mode 100644
index 000000000000..4e57a216feaf
--- /dev/null
+++ b/arch/sh/lib/strcasecmp.c
@@ -0,0 +1,26 @@
+/*
+ * linux/arch/alpha/lib/strcasecmp.c
+ */
+
+#include <linux/string.h>
+
+
+/* We handle nothing here except the C locale. Since this is used in
+ only one place, on strings known to contain only 7 bit ASCII, this
+ is ok. */
+
+int strcasecmp(const char *a, const char *b)
+{
+ int ca, cb;
+
+ do {
+ ca = *a++ & 0xff;
+ cb = *b++ & 0xff;
+ if (ca >= 'A' && ca <= 'Z')
+ ca += 'a' - 'A';
+ if (cb >= 'A' && cb <= 'Z')
+ cb += 'a' - 'A';
+ } while (ca == cb && ca != '\0');
+
+ return ca - cb;
+}
diff --git a/arch/sh/lib/strlen.S b/arch/sh/lib/strlen.S
new file mode 100644
index 000000000000..f8ab296047b3
--- /dev/null
+++ b/arch/sh/lib/strlen.S
@@ -0,0 +1,70 @@
+/* $Id: strlen.S,v 1.2 2001/06/29 14:07:15 gniibe Exp $
+ *
+ * "strlen" implementation of SuperH
+ *
+ * Copyright (C) 1999 Kaz Kojima
+ *
+ */
+
+/* size_t strlen (const char *s) */
+
+#include <linux/linkage.h>
+ENTRY(strlen)
+ mov r4,r0
+ and #3,r0
+ tst r0,r0
+ bt/s 1f
+ mov #0,r2
+
+ add #-1,r0
+ shll2 r0
+ shll r0
+ braf r0
+ nop
+
+ mov.b @r4+,r1
+ tst r1,r1
+ bt 8f
+ add #1,r2
+
+ mov.b @r4+,r1
+ tst r1,r1
+ bt 8f
+ add #1,r2
+
+ mov.b @r4+,r1
+ tst r1,r1
+ bt 8f
+ add #1,r2
+
+1:
+ mov #0,r3
+2:
+ mov.l @r4+,r1
+ cmp/str r3,r1
+ bf/s 2b
+ add #4,r2
+
+ add #-4,r2
+#ifndef __LITTLE_ENDIAN__
+ swap.b r1,r1
+ swap.w r1,r1
+ swap.b r1,r1
+#endif
+ extu.b r1,r0
+ tst r0,r0
+ bt/s 8f
+ shlr8 r1
+ add #1,r2
+ extu.b r1,r0
+ tst r0,r0
+ bt/s 8f
+ shlr8 r1
+ add #1,r2
+ extu.b r1,r0
+ tst r0,r0
+ bt 8f
+ add #1,r2
+8:
+ rts
+ mov r2,r0
diff --git a/arch/sh/lib/udivdi3.c b/arch/sh/lib/udivdi3.c
new file mode 100644
index 000000000000..68f038bf3c50
--- /dev/null
+++ b/arch/sh/lib/udivdi3.c
@@ -0,0 +1,16 @@
+/*
+ * Simple __udivdi3 function which doesn't use FPU.
+ */
+
+#include <linux/types.h>
+
+extern u64 __xdiv64_32(u64 n, u32 d);
+extern void panic(const char * fmt, ...);
+
+u64 __udivdi3(u64 n, u64 d)
+{
+ if (d & ~0xffffffff)
+ panic("Need true 64-bit/64-bit division");
+ return __xdiv64_32(n, (u32)d);
+}
+
diff --git a/arch/sh/mm/Makefile b/arch/sh/mm/Makefile
new file mode 100644
index 000000000000..9489a1424644
--- /dev/null
+++ b/arch/sh/mm/Makefile
@@ -0,0 +1,25 @@
+#
+# Makefile for the Linux SuperH-specific parts of the memory manager.
+#
+
+obj-y := init.o extable.o consistent.o
+
+obj-$(CONFIG_CPU_SH2) += cache-sh2.o
+obj-$(CONFIG_CPU_SH3) += cache-sh3.o
+obj-$(CONFIG_CPU_SH4) += cache-sh4.o pg-sh4.o
+
+obj-$(CONFIG_DMA_PAGE_OPS) += pg-dma.o
+obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o
+
+mmu-y := fault-nommu.o tlb-nommu.o pg-nommu.o
+mmu-$(CONFIG_MMU) := fault.o clear_page.o copy_page.o
+
+obj-y += $(mmu-y)
+
+ifdef CONFIG_MMU
+obj-$(CONFIG_CPU_SH3) += tlb-sh3.o
+obj-$(CONFIG_CPU_SH4) += tlb-sh4.o ioremap.o
+obj-$(CONFIG_SH7705_CACHE_32KB) += pg-sh7705.o
+endif
+
+obj-$(CONFIG_SH7705_CACHE_32KB) += cache-sh7705.o
diff --git a/arch/sh/mm/cache-sh2.c b/arch/sh/mm/cache-sh2.c
new file mode 100644
index 000000000000..2689cb24ea2b
--- /dev/null
+++ b/arch/sh/mm/cache-sh2.c
@@ -0,0 +1,50 @@
+/*
+ * arch/sh/mm/cache-sh2.c
+ *
+ * Copyright (C) 2002 Paul Mundt
+ *
+ * Released under the terms of the GNU GPL v2.0.
+ */
+#include <linux/init.h>
+#include <linux/mm.h>
+
+#include <asm/cache.h>
+#include <asm/addrspace.h>
+#include <asm/processor.h>
+#include <asm/cacheflush.h>
+#include <asm/io.h>
+
+/*
+ * Calculate the OC address and set the way bit on the SH-2.
+ *
+ * We must have already jump_to_P2()'ed prior to calling this
+ * function, since we rely on CCR manipulation to do the
+ * Right Thing(tm).
+ */
+unsigned long __get_oc_addr(unsigned long set, unsigned long way)
+{
+ unsigned long ccr;
+
+ /*
+ * On SH-2 the way bit isn't tracked in the address field
+ * if we're doing address array access .. instead, we need
+ * to manually switch out the way in the CCR.
+ */
+ ccr = ctrl_inl(CCR);
+ ccr &= ~0x00c0;
+ ccr |= way << cpu_data->dcache.way_shift;
+
+ /*
+ * Despite the number of sets being halved, we end up losing
+ * the first 2 ways to OCRAM instead of the last 2 (if we're
+ * 4-way). As a result, forcibly setting the W1 bit handily
+ * bumps us up 2 ways.
+ */
+ if (ccr & CCR_CACHE_ORA)
+ ccr |= 1 << (cpu_data->dcache.way_shift + 1);
+
+ ctrl_outl(ccr, CCR);
+
+ return CACHE_OC_ADDRESS_ARRAY | (set << cpu_data->dcache.entry_shift);
+}
+
diff --git a/arch/sh/mm/cache-sh3.c b/arch/sh/mm/cache-sh3.c
new file mode 100644
index 000000000000..838731fc608d
--- /dev/null
+++ b/arch/sh/mm/cache-sh3.c
@@ -0,0 +1,100 @@
+/*
+ * arch/sh/mm/cache-sh3.c
+ *
+ * Copyright (C) 1999, 2000 Niibe Yutaka
+ * Copyright (C) 2002 Paul Mundt
+ *
+ * Released under the terms of the GNU GPL v2.0.
+ */
+
+#include <linux/init.h>
+#include <linux/mman.h>
+#include <linux/mm.h>
+#include <linux/threads.h>
+#include <asm/addrspace.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/processor.h>
+#include <asm/cache.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/pgalloc.h>
+#include <asm/mmu_context.h>
+#include <asm/cacheflush.h>
+
+/*
+ * Write back the dirty D-caches, but not invalidate them.
+ *
+ * Is this really worth it, or should we just alias this routine
+ * to __flush_purge_region too?
+ *
+ * START: Virtual Address (U0, P1, or P3)
+ * SIZE: Size of the region.
+ */
+
+void __flush_wback_region(void *start, int size)
+{
+ unsigned long v, j;
+ unsigned long begin, end;
+ unsigned long flags;
+
+ begin = (unsigned long)start & ~(L1_CACHE_BYTES-1);
+ end = ((unsigned long)start + size + L1_CACHE_BYTES-1)
+ & ~(L1_CACHE_BYTES-1);
+
+ for (v = begin; v < end; v+=L1_CACHE_BYTES) {
+ unsigned long addrstart = CACHE_OC_ADDRESS_ARRAY;
+ for (j = 0; j < cpu_data->dcache.ways; j++) {
+ unsigned long data, addr, p;
+
+ p = __pa(v);
+ addr = addrstart | (v & cpu_data->dcache.entry_mask);
+ local_irq_save(flags);
+ data = ctrl_inl(addr);
+
+ if ((data & CACHE_PHYSADDR_MASK) ==
+ (p & CACHE_PHYSADDR_MASK)) {
+ data &= ~SH_CACHE_UPDATED;
+ ctrl_outl(data, addr);
+ local_irq_restore(flags);
+ break;
+ }
+ local_irq_restore(flags);
+ addrstart += cpu_data->dcache.way_incr;
+ }
+ }
+}
+
+/*
+ * Write back the dirty D-caches and invalidate them.
+ *
+ * START: Virtual Address (U0, P1, or P3)
+ * SIZE: Size of the region.
+ */
+void __flush_purge_region(void *start, int size)
+{
+ unsigned long v;
+ unsigned long begin, end;
+
+ begin = (unsigned long)start & ~(L1_CACHE_BYTES-1);
+ end = ((unsigned long)start + size + L1_CACHE_BYTES-1)
+ & ~(L1_CACHE_BYTES-1);
+
+ for (v = begin; v < end; v+=L1_CACHE_BYTES) {
+ unsigned long data, addr;
+
+ data = (v & 0xfffffc00); /* _Virtual_ address, ~U, ~V */
+ addr = CACHE_OC_ADDRESS_ARRAY |
+ (v & cpu_data->dcache.entry_mask) | SH_CACHE_ASSOC;
+ ctrl_outl(data, addr);
+ }
+}
+
+/*
+ * No write back please
+ *
+ * Except I don't think there's any way to avoid the writeback. So we
+ * just alias it to __flush_purge_region(). dwmw2.
+ */
+void __flush_invalidate_region(void *start, int size)
+ __attribute__((alias("__flush_purge_region")));
diff --git a/arch/sh/mm/cache-sh4.c b/arch/sh/mm/cache-sh4.c
new file mode 100644
index 000000000000..ab833adf28c3
--- /dev/null
+++ b/arch/sh/mm/cache-sh4.c
@@ -0,0 +1,362 @@
+/*
+ * arch/sh/mm/cache-sh4.c
+ *
+ * Copyright (C) 1999, 2000, 2002 Niibe Yutaka
+ * Copyright (C) 2001, 2002, 2003, 2004 Paul Mundt
+ * Copyright (C) 2003 Richard Curnow
+ *
+ * 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/config.h>
+#include <linux/init.h>
+#include <linux/mman.h>
+#include <linux/mm.h>
+#include <linux/threads.h>
+#include <asm/addrspace.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/processor.h>
+#include <asm/cache.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/pgalloc.h>
+#include <asm/mmu_context.h>
+#include <asm/cacheflush.h>
+
+extern void __flush_cache_4096_all(unsigned long start);
+static void __flush_cache_4096_all_ex(unsigned long start);
+extern void __flush_dcache_all(void);
+static void __flush_dcache_all_ex(void);
+
+/*
+ * SH-4 has virtually indexed and physically tagged cache.
+ */
+
+struct semaphore p3map_sem[4];
+
+void __init p3_cache_init(void)
+{
+ if (remap_area_pages(P3SEG, 0, PAGE_SIZE*4, _PAGE_CACHABLE))
+ panic("%s failed.", __FUNCTION__);
+
+ sema_init (&p3map_sem[0], 1);
+ sema_init (&p3map_sem[1], 1);
+ sema_init (&p3map_sem[2], 1);
+ sema_init (&p3map_sem[3], 1);
+}
+
+/*
+ * Write back the dirty D-caches, but not invalidate them.
+ *
+ * START: Virtual Address (U0, P1, or P3)
+ * SIZE: Size of the region.
+ */
+void __flush_wback_region(void *start, int size)
+{
+ unsigned long v;
+ unsigned long begin, end;
+
+ begin = (unsigned long)start & ~(L1_CACHE_BYTES-1);
+ end = ((unsigned long)start + size + L1_CACHE_BYTES-1)
+ & ~(L1_CACHE_BYTES-1);
+ for (v = begin; v < end; v+=L1_CACHE_BYTES) {
+ asm volatile("ocbwb %0"
+ : /* no output */
+ : "m" (__m(v)));
+ }
+}
+
+/*
+ * Write back the dirty D-caches and invalidate them.
+ *
+ * START: Virtual Address (U0, P1, or P3)
+ * SIZE: Size of the region.
+ */
+void __flush_purge_region(void *start, int size)
+{
+ unsigned long v;
+ unsigned long begin, end;
+
+ begin = (unsigned long)start & ~(L1_CACHE_BYTES-1);
+ end = ((unsigned long)start + size + L1_CACHE_BYTES-1)
+ & ~(L1_CACHE_BYTES-1);
+ for (v = begin; v < end; v+=L1_CACHE_BYTES) {
+ asm volatile("ocbp %0"
+ : /* no output */
+ : "m" (__m(v)));
+ }
+}
+
+
+/*
+ * No write back please
+ */
+void __flush_invalidate_region(void *start, int size)
+{
+ unsigned long v;
+ unsigned long begin, end;
+
+ begin = (unsigned long)start & ~(L1_CACHE_BYTES-1);
+ end = ((unsigned long)start + size + L1_CACHE_BYTES-1)
+ & ~(L1_CACHE_BYTES-1);
+ for (v = begin; v < end; v+=L1_CACHE_BYTES) {
+ asm volatile("ocbi %0"
+ : /* no output */
+ : "m" (__m(v)));
+ }
+}
+
+static void __flush_dcache_all_ex(void)
+{
+ unsigned long addr, end_addr, entry_offset;
+
+ end_addr = CACHE_OC_ADDRESS_ARRAY + (cpu_data->dcache.sets << cpu_data->dcache.entry_shift) * cpu_data->dcache.ways;
+ entry_offset = 1 << cpu_data->dcache.entry_shift;
+ for (addr = CACHE_OC_ADDRESS_ARRAY; addr < end_addr; addr += entry_offset) {
+ ctrl_outl(0, addr);
+ }
+}
+
+static void __flush_cache_4096_all_ex(unsigned long start)
+{
+ unsigned long addr, entry_offset;
+ int i;
+
+ entry_offset = 1 << cpu_data->dcache.entry_shift;
+ for (i = 0; i < cpu_data->dcache.ways; i++, start += cpu_data->dcache.way_incr) {
+ for (addr = CACHE_OC_ADDRESS_ARRAY + start;
+ addr < CACHE_OC_ADDRESS_ARRAY + 4096 + start;
+ addr += entry_offset) {
+ ctrl_outl(0, addr);
+ }
+ }
+}
+
+void flush_cache_4096_all(unsigned long start)
+{
+ if (cpu_data->dcache.ways == 1)
+ __flush_cache_4096_all(start);
+ else
+ __flush_cache_4096_all_ex(start);
+}
+
+/*
+ * Write back the range of D-cache, and purge the I-cache.
+ *
+ * Called from kernel/module.c:sys_init_module and routine for a.out format.
+ */
+void flush_icache_range(unsigned long start, unsigned long end)
+{
+ flush_cache_all();
+}
+
+/*
+ * Write back the D-cache and purge the I-cache for signal trampoline.
+ * .. which happens to be the same behavior as flush_icache_range().
+ * So, we simply flush out a line.
+ */
+void flush_cache_sigtramp(unsigned long addr)
+{
+ unsigned long v, index;
+ unsigned long flags;
+ int i;
+
+ v = addr & ~(L1_CACHE_BYTES-1);
+ asm volatile("ocbwb %0"
+ : /* no output */
+ : "m" (__m(v)));
+
+ index = CACHE_IC_ADDRESS_ARRAY | (v & cpu_data->icache.entry_mask);
+
+ local_irq_save(flags);
+ jump_to_P2();
+ for(i = 0; i < cpu_data->icache.ways; i++, index += cpu_data->icache.way_incr)
+ ctrl_outl(0, index); /* Clear out Valid-bit */
+ back_to_P1();
+ local_irq_restore(flags);
+}
+
+static inline void flush_cache_4096(unsigned long start,
+ unsigned long phys)
+{
+ unsigned long flags;
+ extern void __flush_cache_4096(unsigned long addr, unsigned long phys, unsigned long exec_offset);
+
+ /*
+ * SH7751, SH7751R, and ST40 have no restriction to handle cache.
+ * (While SH7750 must do that at P2 area.)
+ */
+ if ((cpu_data->flags & CPU_HAS_P2_FLUSH_BUG)
+ || start < CACHE_OC_ADDRESS_ARRAY) {
+ local_irq_save(flags);
+ __flush_cache_4096(start | SH_CACHE_ASSOC, P1SEGADDR(phys), 0x20000000);
+ local_irq_restore(flags);
+ } else {
+ __flush_cache_4096(start | SH_CACHE_ASSOC, P1SEGADDR(phys), 0);
+ }
+}
+
+/*
+ * Write back & invalidate the D-cache of the page.
+ * (To avoid "alias" issues)
+ */
+void flush_dcache_page(struct page *page)
+{
+ if (test_bit(PG_mapped, &page->flags)) {
+ unsigned long phys = PHYSADDR(page_address(page));
+
+ /* Loop all the D-cache */
+ flush_cache_4096(CACHE_OC_ADDRESS_ARRAY, phys);
+ flush_cache_4096(CACHE_OC_ADDRESS_ARRAY | 0x1000, phys);
+ flush_cache_4096(CACHE_OC_ADDRESS_ARRAY | 0x2000, phys);
+ flush_cache_4096(CACHE_OC_ADDRESS_ARRAY | 0x3000, phys);
+ }
+}
+
+static inline void flush_icache_all(void)
+{
+ unsigned long flags, ccr;
+
+ local_irq_save(flags);
+ jump_to_P2();
+
+ /* Flush I-cache */
+ ccr = ctrl_inl(CCR);
+ ccr |= CCR_CACHE_ICI;
+ ctrl_outl(ccr, CCR);
+
+ back_to_P1();
+ local_irq_restore(flags);
+}
+
+void flush_cache_all(void)
+{
+ if (cpu_data->dcache.ways == 1)
+ __flush_dcache_all();
+ else
+ __flush_dcache_all_ex();
+ flush_icache_all();
+}
+
+void flush_cache_mm(struct mm_struct *mm)
+{
+ /* Is there any good way? */
+ /* XXX: possibly call flush_cache_range for each vm area */
+ /*
+ * FIXME: Really, the optimal solution here would be able to flush out
+ * individual lines created by the specified context, but this isn't
+ * feasible for a number of architectures (such as MIPS, and some
+ * SPARC) .. is this possible for SuperH?
+ *
+ * In the meantime, we'll just flush all of the caches.. this
+ * seems to be the simplest way to avoid at least a few wasted
+ * cache flushes. -Lethal
+ */
+ flush_cache_all();
+}
+
+/*
+ * Write back and invalidate I/D-caches for the page.
+ *
+ * ADDR: Virtual Address (U0 address)
+ * PFN: Physical page number
+ */
+void flush_cache_page(struct vm_area_struct *vma, unsigned long address, unsigned long pfn)
+{
+ unsigned long phys = pfn << PAGE_SHIFT;
+
+ /* We only need to flush D-cache when we have alias */
+ if ((address^phys) & CACHE_ALIAS) {
+ /* Loop 4K of the D-cache */
+ flush_cache_4096(
+ CACHE_OC_ADDRESS_ARRAY | (address & CACHE_ALIAS),
+ phys);
+ /* Loop another 4K of the D-cache */
+ flush_cache_4096(
+ CACHE_OC_ADDRESS_ARRAY | (phys & CACHE_ALIAS),
+ phys);
+ }
+
+ if (vma->vm_flags & VM_EXEC)
+ /* Loop 4K (half) of the I-cache */
+ flush_cache_4096(
+ CACHE_IC_ADDRESS_ARRAY | (address & 0x1000),
+ phys);
+}
+
+/*
+ * Write back and invalidate D-caches.
+ *
+ * START, END: Virtual Address (U0 address)
+ *
+ * NOTE: We need to flush the _physical_ page entry.
+ * Flushing the cache lines for U0 only isn't enough.
+ * We need to flush for P1 too, which may contain aliases.
+ */
+void flush_cache_range(struct vm_area_struct *vma, unsigned long start,
+ unsigned long end)
+{
+ unsigned long p = start & PAGE_MASK;
+ pgd_t *dir;
+ pmd_t *pmd;
+ pte_t *pte;
+ pte_t entry;
+ unsigned long phys;
+ unsigned long d = 0;
+
+ dir = pgd_offset(vma->vm_mm, p);
+ pmd = pmd_offset(dir, p);
+
+ do {
+ if (pmd_none(*pmd) || pmd_bad(*pmd)) {
+ p &= ~((1 << PMD_SHIFT) -1);
+ p += (1 << PMD_SHIFT);
+ pmd++;
+ continue;
+ }
+ pte = pte_offset_kernel(pmd, p);
+ do {
+ entry = *pte;
+ if ((pte_val(entry) & _PAGE_PRESENT)) {
+ phys = pte_val(entry)&PTE_PHYS_MASK;
+ if ((p^phys) & CACHE_ALIAS) {
+ d |= 1 << ((p & CACHE_ALIAS)>>12);
+ d |= 1 << ((phys & CACHE_ALIAS)>>12);
+ if (d == 0x0f)
+ goto loop_exit;
+ }
+ }
+ pte++;
+ p += PAGE_SIZE;
+ } while (p < end && ((unsigned long)pte & ~PAGE_MASK));
+ pmd++;
+ } while (p < end);
+ loop_exit:
+ if (d & 1)
+ flush_cache_4096_all(0);
+ if (d & 2)
+ flush_cache_4096_all(0x1000);
+ if (d & 4)
+ flush_cache_4096_all(0x2000);
+ if (d & 8)
+ flush_cache_4096_all(0x3000);
+ if (vma->vm_flags & VM_EXEC)
+ flush_icache_all();
+}
+
+/*
+ * flush_icache_user_range
+ * @vma: VMA of the process
+ * @page: page
+ * @addr: U0 address
+ * @len: length of the range (< page size)
+ */
+void flush_icache_user_range(struct vm_area_struct *vma,
+ struct page *page, unsigned long addr, int len)
+{
+ flush_cache_page(vma, addr, page_to_pfn(page));
+}
+
diff --git a/arch/sh/mm/cache-sh7705.c b/arch/sh/mm/cache-sh7705.c
new file mode 100644
index 000000000000..ad8ed7d41e16
--- /dev/null
+++ b/arch/sh/mm/cache-sh7705.c
@@ -0,0 +1,206 @@
+/*
+ * arch/sh/mm/cache-sh7705.c
+ *
+ * Copyright (C) 1999, 2000 Niibe Yutaka
+ * Copyright (C) 2004 Alex Song
+ *
+ * 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/mman.h>
+#include <linux/mm.h>
+#include <linux/threads.h>
+#include <asm/addrspace.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/processor.h>
+#include <asm/cache.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/pgalloc.h>
+#include <asm/mmu_context.h>
+#include <asm/cacheflush.h>
+
+/* The 32KB cache on the SH7705 suffers from the same synonym problem
+ * as SH4 CPUs */
+
+#define __pte_offset(address) \
+ ((address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
+#define pte_offset(dir, address) ((pte_t *) pmd_page_kernel(*(dir)) + \
+ __pte_offset(address))
+
+static inline void cache_wback_all(void)
+{
+ unsigned long ways, waysize, addrstart;
+
+ ways = cpu_data->dcache.ways;
+ waysize = cpu_data->dcache.sets;
+ waysize <<= cpu_data->dcache.entry_shift;
+
+ addrstart = CACHE_OC_ADDRESS_ARRAY;
+
+ do {
+ unsigned long addr;
+
+ for (addr = addrstart;
+ addr < addrstart + waysize;
+ addr += cpu_data->dcache.linesz) {
+ unsigned long data;
+ int v = SH_CACHE_UPDATED | SH_CACHE_VALID;
+
+ data = ctrl_inl(addr);
+
+ if ((data & v) == v)
+ ctrl_outl(data & ~v, addr);
+
+ }
+
+ addrstart += cpu_data->dcache.way_incr;
+ } while (--ways);
+}
+
+/*
+ * Write back the range of D-cache, and purge the I-cache.
+ *
+ * Called from kernel/module.c:sys_init_module and routine for a.out format.
+ */
+void flush_icache_range(unsigned long start, unsigned long end)
+{
+ __flush_wback_region((void *)start, end - start);
+}
+
+
+/*
+ * Writeback&Invalidate the D-cache of the page
+ */
+static void __flush_dcache_page(unsigned long phys)
+{
+ unsigned long ways, waysize, addrstart;
+ unsigned long flags;
+
+ phys |= SH_CACHE_VALID;
+
+ /*
+ * Here, phys is the physical address of the page. We check all the
+ * tags in the cache for those with the same page number as this page
+ * (by masking off the lowest 2 bits of the 19-bit tag; these bits are
+ * derived from the offset within in the 4k page). Matching valid
+ * entries are invalidated.
+ *
+ * Since 2 bits of the cache index are derived from the virtual page
+ * number, knowing this would reduce the number of cache entries to be
+ * searched by a factor of 4. However this function exists to deal with
+ * potential cache aliasing, therefore the optimisation is probably not
+ * possible.
+ */
+ local_irq_save(flags);
+ jump_to_P2();
+
+ ways = cpu_data->dcache.ways;
+ waysize = cpu_data->dcache.sets;
+ waysize <<= cpu_data->dcache.entry_shift;
+
+ addrstart = CACHE_OC_ADDRESS_ARRAY;
+
+ do {
+ unsigned long addr;
+
+ for (addr = addrstart;
+ addr < addrstart + waysize;
+ addr += cpu_data->dcache.linesz) {
+ unsigned long data;
+
+ data = ctrl_inl(addr) & (0x1ffffC00 | SH_CACHE_VALID);
+ if (data == phys) {
+ data &= ~(SH_CACHE_VALID | SH_CACHE_UPDATED);
+ ctrl_outl(data, addr);
+ }
+ }
+
+ addrstart += cpu_data->dcache.way_incr;
+ } while (--ways);
+
+ back_to_P1();
+ local_irq_restore(flags);
+}
+
+
+/*
+ * Write back & invalidate the D-cache of the page.
+ * (To avoid "alias" issues)
+ */
+void flush_dcache_page(struct page *page)
+{
+ if (test_bit(PG_mapped, &page->flags))
+ __flush_dcache_page(PHYSADDR(page_address(page)));
+}
+
+void flush_cache_all(void)
+{
+ unsigned long flags;
+
+ local_irq_save(flags);
+ jump_to_P2();
+
+ cache_wback_all();
+ back_to_P1();
+ local_irq_restore(flags);
+}
+
+void flush_cache_mm(struct mm_struct *mm)
+{
+ /* Is there any good way? */
+ /* XXX: possibly call flush_cache_range for each vm area */
+ flush_cache_all();
+}
+
+/*
+ * Write back and invalidate D-caches.
+ *
+ * START, END: Virtual Address (U0 address)
+ *
+ * NOTE: We need to flush the _physical_ page entry.
+ * Flushing the cache lines for U0 only isn't enough.
+ * We need to flush for P1 too, which may contain aliases.
+ */
+void flush_cache_range(struct vm_area_struct *vma, unsigned long start,
+ unsigned long end)
+{
+
+ /*
+ * We could call flush_cache_page for the pages of these range,
+ * but it's not efficient (scan the caches all the time...).
+ *
+ * We can't use A-bit magic, as there's the case we don't have
+ * valid entry on TLB.
+ */
+ flush_cache_all();
+}
+
+/*
+ * Write back and invalidate I/D-caches for the page.
+ *
+ * ADDRESS: Virtual Address (U0 address)
+ */
+void flush_cache_page(struct vm_area_struct *vma, unsigned long address, unsigned long pfn)
+{
+ __flush_dcache_page(pfn << PAGE_SHIFT);
+}
+
+/*
+ * This is called when a page-cache page is about to be mapped into a
+ * user process' address space. It offers an opportunity for a
+ * port to ensure d-cache/i-cache coherency if necessary.
+ *
+ * Not entirely sure why this is necessary on SH3 with 32K cache but
+ * without it we get occasional "Memory fault" when loading a program.
+ */
+void flush_icache_page(struct vm_area_struct *vma, struct page *page)
+{
+ __flush_purge_region(page_address(page), PAGE_SIZE);
+}
+
diff --git a/arch/sh/mm/clear_page.S b/arch/sh/mm/clear_page.S
new file mode 100644
index 000000000000..ae58a61f0e66
--- /dev/null
+++ b/arch/sh/mm/clear_page.S
@@ -0,0 +1,295 @@
+/* $Id: clear_page.S,v 1.13 2003/08/25 17:03:10 lethal Exp $
+ *
+ * __clear_user_page, __clear_user, clear_page implementation of SuperH
+ *
+ * Copyright (C) 2001 Kaz Kojima
+ * Copyright (C) 2001, 2002 Niibe Yutaka
+ *
+ */
+#include <linux/config.h>
+#include <linux/linkage.h>
+
+/*
+ * clear_page_slow
+ * @to: P1 address
+ *
+ * void clear_page_slow(void *to)
+ */
+
+/*
+ * r0 --- scratch
+ * r4 --- to
+ * r5 --- to + 4096
+ */
+ENTRY(clear_page_slow)
+ mov r4,r5
+ mov.w .Llimit,r0
+ add r0,r5
+ mov #0,r0
+ !
+1:
+#if defined(CONFIG_CPU_SH3)
+ mov.l r0,@r4
+#elif defined(CONFIG_CPU_SH4)
+ movca.l r0,@r4
+ mov r4,r1
+#endif
+ add #32,r4
+ mov.l r0,@-r4
+ mov.l r0,@-r4
+ mov.l r0,@-r4
+ mov.l r0,@-r4
+ mov.l r0,@-r4
+ mov.l r0,@-r4
+ mov.l r0,@-r4
+#if defined(CONFIG_CPU_SH4)
+ ocbwb @r1
+#endif
+ cmp/eq r5,r4
+ bf/s 1b
+ add #28,r4
+ !
+ rts
+ nop
+.Llimit: .word (4096-28)
+
+ENTRY(__clear_user)
+ !
+ mov #0, r0
+ mov #0xe0, r1 ! 0xffffffe0
+ !
+ ! r4..(r4+31)&~32 -------- not aligned [ Area 0 ]
+ ! (r4+31)&~32..(r4+r5)&~32 -------- aligned [ Area 1 ]
+ ! (r4+r5)&~32..r4+r5 -------- not aligned [ Area 2 ]
+ !
+ ! Clear area 0
+ mov r4, r2
+ !
+ tst r1, r5 ! length < 32
+ bt .Larea2 ! skip to remainder
+ !
+ add #31, r2
+ and r1, r2
+ cmp/eq r4, r2
+ bt .Larea1
+ mov r2, r3
+ sub r4, r3
+ mov r3, r7
+ mov r4, r2
+ !
+.L0: dt r3
+0: mov.b r0, @r2
+ bf/s .L0
+ add #1, r2
+ !
+ sub r7, r5
+ mov r2, r4
+.Larea1:
+ mov r4, r3
+ add r5, r3
+ and r1, r3
+ cmp/hi r2, r3
+ bf .Larea2
+ !
+ ! Clear area 1
+#if defined(CONFIG_CPU_SH4)
+1: movca.l r0, @r2
+#else
+1: mov.l r0, @r2
+#endif
+ add #4, r2
+2: mov.l r0, @r2
+ add #4, r2
+3: mov.l r0, @r2
+ add #4, r2
+4: mov.l r0, @r2
+ add #4, r2
+5: mov.l r0, @r2
+ add #4, r2
+6: mov.l r0, @r2
+ add #4, r2
+7: mov.l r0, @r2
+ add #4, r2
+8: mov.l r0, @r2
+ add #4, r2
+ cmp/hi r2, r3
+ bt/s 1b
+ nop
+ !
+ ! Clear area 2
+.Larea2:
+ mov r4, r3
+ add r5, r3
+ cmp/hs r3, r2
+ bt/s .Ldone
+ sub r2, r3
+.L2: dt r3
+9: mov.b r0, @r2
+ bf/s .L2
+ add #1, r2
+ !
+.Ldone: rts
+ mov #0, r0 ! return 0 as normal return
+
+ ! return the number of bytes remained
+.Lbad_clear_user:
+ mov r4, r0
+ add r5, r0
+ rts
+ sub r2, r0
+
+.section __ex_table,"a"
+ .align 2
+ .long 0b, .Lbad_clear_user
+ .long 1b, .Lbad_clear_user
+ .long 2b, .Lbad_clear_user
+ .long 3b, .Lbad_clear_user
+ .long 4b, .Lbad_clear_user
+ .long 5b, .Lbad_clear_user
+ .long 6b, .Lbad_clear_user
+ .long 7b, .Lbad_clear_user
+ .long 8b, .Lbad_clear_user
+ .long 9b, .Lbad_clear_user
+.previous
+
+#if defined(CONFIG_CPU_SH4)
+/*
+ * __clear_user_page
+ * @to: P3 address (with same color)
+ * @orig_to: P1 address
+ *
+ * void __clear_user_page(void *to, void *orig_to)
+ */
+
+/*
+ * r0 --- scratch
+ * r4 --- to
+ * r5 --- orig_to
+ * r6 --- to + 4096
+ */
+ENTRY(__clear_user_page)
+ mov.w .L4096,r0
+ mov r4,r6
+ add r0,r6
+ mov #0,r0
+ !
+1: ocbi @r5
+ add #32,r5
+ movca.l r0,@r4
+ mov r4,r1
+ add #32,r4
+ mov.l r0,@-r4
+ mov.l r0,@-r4
+ mov.l r0,@-r4
+ mov.l r0,@-r4
+ mov.l r0,@-r4
+ mov.l r0,@-r4
+ mov.l r0,@-r4
+ add #28,r4
+ cmp/eq r6,r4
+ bf/s 1b
+ ocbwb @r1
+ !
+ rts
+ nop
+.L4096: .word 4096
+
+ENTRY(__flush_cache_4096)
+ mov.l 1f,r3
+ add r6,r3
+ mov r4,r0
+ mov #64,r2
+ shll r2
+ mov #64,r6
+ jmp @r3
+ mov #96,r7
+ .align 2
+1: .long 2f
+2:
+ .rept 32
+ mov.l r5,@r0
+ mov.l r5,@(32,r0)
+ mov.l r5,@(r0,r6)
+ mov.l r5,@(r0,r7)
+ add r2,r5
+ add r2,r0
+ .endr
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ rts
+ nop
+
+ENTRY(__flush_dcache_all)
+ mov.l 2f,r0
+ mov.l 3f,r4
+ and r0,r4 ! r4 = (unsigned long)&empty_zero_page[0] & ~0xffffc000
+ stc sr,r1 ! save SR
+ mov.l 4f,r2
+ or r1,r2
+ mov #32,r3
+ shll2 r3
+1:
+ ldc r2,sr ! set BL bit
+ movca.l r0,@r4
+ ocbi @r4
+ add #32,r4
+ movca.l r0,@r4
+ ocbi @r4
+ add #32,r4
+ movca.l r0,@r4
+ ocbi @r4
+ add #32,r4
+ movca.l r0,@r4
+ ocbi @r4
+ ldc r1,sr ! restore SR
+ dt r3
+ bf/s 1b
+ add #32,r4
+
+ rts
+ nop
+ .align 2
+2: .long 0xffffc000
+3: .long empty_zero_page
+4: .long 0x10000000 ! BL bit
+
+/* __flush_cache_4096_all(unsigned long addr) */
+ENTRY(__flush_cache_4096_all)
+ mov.l 2f,r0
+ mov.l 3f,r2
+ and r0,r2
+ or r2,r4 ! r4 = addr | (unsigned long)&empty_zero_page[0] & ~0x3fff
+ stc sr,r1 ! save SR
+ mov.l 4f,r2
+ or r1,r2
+ mov #32,r3
+1:
+ ldc r2,sr ! set BL bit
+ movca.l r0,@r4
+ ocbi @r4
+ add #32,r4
+ movca.l r0,@r4
+ ocbi @r4
+ add #32,r4
+ movca.l r0,@r4
+ ocbi @r4
+ add #32,r4
+ movca.l r0,@r4
+ ocbi @r4
+ ldc r1,sr ! restore SR
+ dt r3
+ bf/s 1b
+ add #32,r4
+
+ rts
+ nop
+ .align 2
+2: .long 0xffffc000
+3: .long empty_zero_page
+4: .long 0x10000000 ! BL bit
+#endif
diff --git a/arch/sh/mm/consistent.c b/arch/sh/mm/consistent.c
new file mode 100644
index 000000000000..1f7af0c73cf4
--- /dev/null
+++ b/arch/sh/mm/consistent.c
@@ -0,0 +1,85 @@
+/*
+ * arch/sh/mm/consistent.c
+ *
+ * Copyright (C) 2004 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/mm.h>
+#include <linux/dma-mapping.h>
+#include <asm/io.h>
+
+void *consistent_alloc(int gfp, size_t size, dma_addr_t *handle)
+{
+ struct page *page, *end, *free;
+ void *ret;
+ int order;
+
+ size = PAGE_ALIGN(size);
+ order = get_order(size);
+
+ page = alloc_pages(gfp, order);
+ if (!page)
+ return NULL;
+
+ ret = page_address(page);
+ *handle = virt_to_phys(ret);
+
+ /*
+ * We must flush the cache before we pass it on to the device
+ */
+ dma_cache_wback_inv(ret, size);
+
+ page = virt_to_page(ret);
+ free = page + (size >> PAGE_SHIFT);
+ end = page + (1 << order);
+
+ while (++page < end) {
+ set_page_count(page, 1);
+
+ /* Free any unused pages */
+ if (page >= free) {
+ __free_page(page);
+ }
+ }
+
+ return P2SEGADDR(ret);
+}
+
+void consistent_free(void *vaddr, size_t size)
+{
+ unsigned long addr = P1SEGADDR((unsigned long)vaddr);
+ struct page *page=virt_to_page(addr);
+ int num_pages=(size+PAGE_SIZE-1) >> PAGE_SHIFT;
+ int i;
+
+ for(i=0;i<num_pages;i++) {
+ __free_page((page+i));
+ }
+}
+
+void consistent_sync(void *vaddr, size_t size, int direction)
+{
+ void * p1addr = (void*) P1SEGADDR((unsigned long)vaddr);
+
+ switch (direction) {
+ case DMA_FROM_DEVICE: /* invalidate only */
+ dma_cache_inv(p1addr, size);
+ break;
+ case DMA_TO_DEVICE: /* writeback only */
+ dma_cache_wback(p1addr, size);
+ break;
+ case DMA_BIDIRECTIONAL: /* writeback and invalidate */
+ dma_cache_wback_inv(p1addr, size);
+ break;
+ default:
+ BUG();
+ }
+}
+
+EXPORT_SYMBOL(consistent_alloc);
+EXPORT_SYMBOL(consistent_free);
+EXPORT_SYMBOL(consistent_sync);
+
diff --git a/arch/sh/mm/copy_page.S b/arch/sh/mm/copy_page.S
new file mode 100644
index 000000000000..1addffe117c3
--- /dev/null
+++ b/arch/sh/mm/copy_page.S
@@ -0,0 +1,397 @@
+/* $Id: copy_page.S,v 1.8 2003/08/25 17:03:10 lethal Exp $
+ *
+ * copy_page, __copy_user_page, __copy_user implementation of SuperH
+ *
+ * Copyright (C) 2001 Niibe Yutaka & Kaz Kojima
+ * Copyright (C) 2002 Toshinobu Sugioka
+ *
+ */
+#include <linux/linkage.h>
+
+/*
+ * copy_page_slow
+ * @to: P1 address
+ * @from: P1 address
+ *
+ * void copy_page_slow(void *to, void *from)
+ */
+
+/*
+ * r0, r1, r2, r3, r4, r5, r6, r7 --- scratch
+ * r8 --- from + 4096
+ * r9 --- not used
+ * r10 --- to
+ * r11 --- from
+ */
+ENTRY(copy_page_slow)
+ mov.l r8,@-r15
+ mov.l r10,@-r15
+ mov.l r11,@-r15
+ mov r4,r10
+ mov r5,r11
+ mov r5,r8
+ mov.w .L4096,r0
+ add r0,r8
+ !
+1: mov.l @r11+,r0
+ mov.l @r11+,r1
+ mov.l @r11+,r2
+ mov.l @r11+,r3
+ mov.l @r11+,r4
+ mov.l @r11+,r5
+ mov.l @r11+,r6
+ mov.l @r11+,r7
+#if defined(CONFIG_CPU_SH3)
+ mov.l r0,@r10
+#elif defined(CONFIG_CPU_SH4)
+ movca.l r0,@r10
+ mov r10,r0
+#endif
+ add #32,r10
+ mov.l r7,@-r10
+ mov.l r6,@-r10
+ mov.l r5,@-r10
+ mov.l r4,@-r10
+ mov.l r3,@-r10
+ mov.l r2,@-r10
+ mov.l r1,@-r10
+#if defined(CONFIG_CPU_SH4)
+ ocbwb @r0
+#endif
+ cmp/eq r11,r8
+ bf/s 1b
+ add #28,r10
+ !
+ mov.l @r15+,r11
+ mov.l @r15+,r10
+ mov.l @r15+,r8
+ rts
+ nop
+
+#if defined(CONFIG_CPU_SH4)
+/*
+ * __copy_user_page
+ * @to: P1 address (with same color)
+ * @from: P1 address
+ * @orig_to: P1 address
+ *
+ * void __copy_user_page(void *to, void *from, void *orig_to)
+ */
+
+/*
+ * r0, r1, r2, r3, r4, r5, r6, r7 --- scratch
+ * r8 --- from + 4096
+ * r9 --- orig_to
+ * r10 --- to
+ * r11 --- from
+ */
+ENTRY(__copy_user_page)
+ mov.l r8,@-r15
+ mov.l r9,@-r15
+ mov.l r10,@-r15
+ mov.l r11,@-r15
+ mov r4,r10
+ mov r5,r11
+ mov r6,r9
+ mov r5,r8
+ mov.w .L4096,r0
+ add r0,r8
+ !
+1: ocbi @r9
+ add #32,r9
+ mov.l @r11+,r0
+ mov.l @r11+,r1
+ mov.l @r11+,r2
+ mov.l @r11+,r3
+ mov.l @r11+,r4
+ mov.l @r11+,r5
+ mov.l @r11+,r6
+ mov.l @r11+,r7
+ movca.l r0,@r10
+ mov r10,r0
+ add #32,r10
+ mov.l r7,@-r10
+ mov.l r6,@-r10
+ mov.l r5,@-r10
+ mov.l r4,@-r10
+ mov.l r3,@-r10
+ mov.l r2,@-r10
+ mov.l r1,@-r10
+ ocbwb @r0
+ cmp/eq r11,r8
+ bf/s 1b
+ add #28,r10
+ !
+ mov.l @r15+,r11
+ mov.l @r15+,r10
+ mov.l @r15+,r9
+ mov.l @r15+,r8
+ rts
+ nop
+#endif
+.L4096: .word 4096
+/*
+ * __kernel_size_t __copy_user(void *to, const void *from, __kernel_size_t n);
+ * Return the number of bytes NOT copied
+ */
+#define EX(...) \
+ 9999: __VA_ARGS__ ; \
+ .section __ex_table, "a"; \
+ .long 9999b, 6000f ; \
+ .previous
+ENTRY(__copy_user)
+ tst r6,r6 ! Check explicitly for zero
+ bf 1f
+ rts
+ mov #0,r0 ! normal return
+1:
+ mov.l r10,@-r15
+ mov.l r9,@-r15
+ mov.l r8,@-r15
+ mov r4,r3
+ add r6,r3 ! last destination address
+ mov #12,r0 ! Check if small number of bytes
+ cmp/gt r0,r6
+ bt 2f
+ bra .L_cleanup_loop
+ nop
+2:
+ neg r5,r0 ! Calculate bytes needed to align source
+ add #4,r0
+ and #3,r0
+ tst r0,r0
+ bt .L_jump
+ mov r0,r1
+
+.L_loop1:
+ ! Copy bytes to align source
+EX( mov.b @r5+,r0 )
+ dt r1
+EX( mov.b r0,@r4 )
+ add #-1,r6
+ bf/s .L_loop1
+ add #1,r4
+
+.L_jump:
+ mov r6,r2 ! Calculate number of longwords to copy
+ shlr2 r2
+ tst r2,r2
+ bt .L_cleanup
+
+ mov r4,r0 ! Jump to appropriate routine
+ and #3,r0
+ mov r0,r1
+ shll2 r1
+ mova .L_jump_tbl,r0
+ mov.l @(r0,r1),r1
+ jmp @r1
+ nop
+
+ .align 2
+.L_jump_tbl:
+ .long .L_dest00
+ .long .L_dest01
+ .long .L_dest10
+ .long .L_dest11
+
+! Destination = 00
+
+.L_dest00:
+ mov r2,r7
+ shlr2 r7
+ shlr r7
+ tst r7,r7
+ mov #7,r0
+ bt/s 1f
+ and r0,r2
+ .align 2
+2:
+EX( mov.l @r5+,r0 )
+EX( mov.l @r5+,r8 )
+EX( mov.l @r5+,r9 )
+EX( mov.l @r5+,r10 )
+EX( mov.l r0,@r4 )
+EX( mov.l r8,@(4,r4) )
+EX( mov.l r9,@(8,r4) )
+EX( mov.l r10,@(12,r4) )
+EX( mov.l @r5+,r0 )
+EX( mov.l @r5+,r8 )
+EX( mov.l @r5+,r9 )
+EX( mov.l @r5+,r10 )
+ dt r7
+EX( mov.l r0,@(16,r4) )
+EX( mov.l r8,@(20,r4) )
+EX( mov.l r9,@(24,r4) )
+EX( mov.l r10,@(28,r4) )
+ bf/s 2b
+ add #32,r4
+ tst r2,r2
+ bt .L_cleanup
+1:
+EX( mov.l @r5+,r0 )
+ dt r2
+EX( mov.l r0,@r4 )
+ bf/s 1b
+ add #4,r4
+
+ bra .L_cleanup
+ nop
+
+! Destination = 10
+
+.L_dest10:
+ mov r2,r7
+ shlr2 r7
+ shlr r7
+ tst r7,r7
+ mov #7,r0
+ bt/s 1f
+ and r0,r2
+2:
+ dt r7
+#ifdef __LITTLE_ENDIAN__
+EX( mov.l @r5+,r0 )
+EX( mov.l @r5+,r1 )
+EX( mov.l @r5+,r8 )
+EX( mov.l @r5+,r9 )
+EX( mov.l @r5+,r10 )
+EX( mov.w r0,@r4 )
+ add #2,r4
+ xtrct r1,r0
+ xtrct r8,r1
+ xtrct r9,r8
+ xtrct r10,r9
+
+EX( mov.l r0,@r4 )
+EX( mov.l r1,@(4,r4) )
+EX( mov.l r8,@(8,r4) )
+EX( mov.l r9,@(12,r4) )
+
+EX( mov.l @r5+,r1 )
+EX( mov.l @r5+,r8 )
+EX( mov.l @r5+,r0 )
+ xtrct r1,r10
+ xtrct r8,r1
+ xtrct r0,r8
+ shlr16 r0
+EX( mov.l r10,@(16,r4) )
+EX( mov.l r1,@(20,r4) )
+EX( mov.l r8,@(24,r4) )
+EX( mov.w r0,@(28,r4) )
+ bf/s 2b
+ add #30,r4
+#else
+EX( mov.l @(28,r5),r0 )
+EX( mov.l @(24,r5),r8 )
+EX( mov.l @(20,r5),r9 )
+EX( mov.l @(16,r5),r10 )
+EX( mov.w r0,@(30,r4) )
+ add #-2,r4
+ xtrct r8,r0
+ xtrct r9,r8
+ xtrct r10,r9
+EX( mov.l r0,@(28,r4) )
+EX( mov.l r8,@(24,r4) )
+EX( mov.l r9,@(20,r4) )
+
+EX( mov.l @(12,r5),r0 )
+EX( mov.l @(8,r5),r8 )
+ xtrct r0,r10
+EX( mov.l @(4,r5),r9 )
+ mov.l r10,@(16,r4)
+EX( mov.l @r5,r10 )
+ xtrct r8,r0
+ xtrct r9,r8
+ xtrct r10,r9
+EX( mov.l r0,@(12,r4) )
+EX( mov.l r8,@(8,r4) )
+ swap.w r10,r0
+EX( mov.l r9,@(4,r4) )
+EX( mov.w r0,@(2,r4) )
+
+ add #32,r5
+ bf/s 2b
+ add #34,r4
+#endif
+ tst r2,r2
+ bt .L_cleanup
+
+1: ! Read longword, write two words per iteration
+EX( mov.l @r5+,r0 )
+ dt r2
+#ifdef __LITTLE_ENDIAN__
+EX( mov.w r0,@r4 )
+ shlr16 r0
+EX( mov.w r0,@(2,r4) )
+#else
+EX( mov.w r0,@(2,r4) )
+ shlr16 r0
+EX( mov.w r0,@r4 )
+#endif
+ bf/s 1b
+ add #4,r4
+
+ bra .L_cleanup
+ nop
+
+! Destination = 01 or 11
+
+.L_dest01:
+.L_dest11:
+ ! Read longword, write byte, word, byte per iteration
+EX( mov.l @r5+,r0 )
+ dt r2
+#ifdef __LITTLE_ENDIAN__
+EX( mov.b r0,@r4 )
+ shlr8 r0
+ add #1,r4
+EX( mov.w r0,@r4 )
+ shlr16 r0
+EX( mov.b r0,@(2,r4) )
+ bf/s .L_dest01
+ add #3,r4
+#else
+EX( mov.b r0,@(3,r4) )
+ shlr8 r0
+ swap.w r0,r7
+EX( mov.b r7,@r4 )
+ add #1,r4
+EX( mov.w r0,@r4 )
+ bf/s .L_dest01
+ add #3,r4
+#endif
+
+! Cleanup last few bytes
+.L_cleanup:
+ mov r6,r0
+ and #3,r0
+ tst r0,r0
+ bt .L_exit
+ mov r0,r6
+
+.L_cleanup_loop:
+EX( mov.b @r5+,r0 )
+ dt r6
+EX( mov.b r0,@r4 )
+ bf/s .L_cleanup_loop
+ add #1,r4
+
+.L_exit:
+ mov #0,r0 ! normal return
+5000:
+
+# Exception handler:
+.section .fixup, "ax"
+6000:
+ mov.l 8000f,r1
+ mov r3,r0
+ jmp @r1
+ sub r4,r0
+ .align 2
+8000: .long 5000b
+
+.previous
+ mov.l @r15+,r8
+ mov.l @r15+,r9
+ rts
+ mov.l @r15+,r10
diff --git a/arch/sh/mm/extable.c b/arch/sh/mm/extable.c
new file mode 100644
index 000000000000..505ede7c21bf
--- /dev/null
+++ b/arch/sh/mm/extable.c
@@ -0,0 +1,22 @@
+/*
+ * linux/arch/sh/mm/extable.c
+ * Taken from:
+ * linux/arch/i386/mm/extable.c
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <asm/uaccess.h>
+
+int fixup_exception(struct pt_regs *regs)
+{
+ const struct exception_table_entry *fixup;
+
+ fixup = search_exception_tables(regs->pc);
+ if (fixup) {
+ regs->pc = fixup->fixup;
+ return 1;
+ }
+
+ return 0;
+}
diff --git a/arch/sh/mm/fault-nommu.c b/arch/sh/mm/fault-nommu.c
new file mode 100644
index 000000000000..34d4e0c68fbb
--- /dev/null
+++ b/arch/sh/mm/fault-nommu.c
@@ -0,0 +1,82 @@
+/*
+ * arch/sh/mm/fault-nommu.c
+ *
+ * Copyright (C) 2002 Paul Mundt
+ *
+ * Based on linux/arch/sh/mm/fault.c:
+ * Copyright (C) 1999 Niibe Yutaka
+ *
+ * Released under the terms of the GNU GPL v2.0.
+ */
+
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/ptrace.h>
+#include <linux/mman.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/interrupt.h>
+
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/pgalloc.h>
+#include <asm/mmu_context.h>
+#include <asm/cacheflush.h>
+
+#if defined(CONFIG_SH_KGDB)
+#include <asm/kgdb.h>
+#endif
+
+extern void die(const char *,struct pt_regs *,long);
+
+/*
+ * This routine handles page faults. It determines the address,
+ * and the problem, and then passes it off to one of the appropriate
+ * routines.
+ */
+asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long writeaccess,
+ unsigned long address)
+{
+#if defined(CONFIG_SH_KGDB)
+ if (kgdb_nofault && kgdb_bus_err_hook)
+ kgdb_bus_err_hook();
+#endif
+
+ /*
+ * Oops. The kernel tried to access some bad page. We'll have to
+ * terminate things with extreme prejudice.
+ *
+ */
+ if (address < PAGE_SIZE) {
+ printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference");
+ } else {
+ printk(KERN_ALERT "Unable to handle kernel paging request");
+ }
+
+ printk(" at virtual address %08lx\n", address);
+ printk(KERN_ALERT "pc = %08lx\n", regs->pc);
+
+ die("Oops", regs, writeaccess);
+ do_exit(SIGKILL);
+}
+
+asmlinkage int __do_page_fault(struct pt_regs *regs, unsigned long writeaccess,
+ unsigned long address)
+{
+#if defined(CONFIG_SH_KGDB)
+ if (kgdb_nofault && kgdb_bus_err_hook)
+ kgdb_bus_err_hook();
+#endif
+
+ if (address >= TASK_SIZE)
+ return 1;
+
+ return 0;
+}
+
diff --git a/arch/sh/mm/fault.c b/arch/sh/mm/fault.c
new file mode 100644
index 000000000000..7abba2161da6
--- /dev/null
+++ b/arch/sh/mm/fault.c
@@ -0,0 +1,374 @@
+/* $Id: fault.c,v 1.14 2004/01/13 05:52:11 kkojima Exp $
+ *
+ * linux/arch/sh/mm/fault.c
+ * Copyright (C) 1999 Niibe Yutaka
+ * Copyright (C) 2003 Paul Mundt
+ *
+ * Based on linux/arch/i386/mm/fault.c:
+ * Copyright (C) 1995 Linus Torvalds
+ */
+
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/ptrace.h>
+#include <linux/mman.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/pgalloc.h>
+#include <asm/mmu_context.h>
+#include <asm/cacheflush.h>
+#include <asm/kgdb.h>
+
+extern void die(const char *,struct pt_regs *,long);
+
+/*
+ * This routine handles page faults. It determines the address,
+ * and the problem, and then passes it off to one of the appropriate
+ * routines.
+ */
+asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long writeaccess,
+ unsigned long address)
+{
+ struct task_struct *tsk;
+ struct mm_struct *mm;
+ struct vm_area_struct * vma;
+ unsigned long page;
+
+#ifdef CONFIG_SH_KGDB
+ if (kgdb_nofault && kgdb_bus_err_hook)
+ kgdb_bus_err_hook();
+#endif
+
+ tsk = current;
+ mm = tsk->mm;
+
+ /*
+ * If we're in an interrupt or have no user
+ * context, we must not take the fault..
+ */
+ if (in_atomic() || !mm)
+ goto no_context;
+
+ down_read(&mm->mmap_sem);
+
+ vma = find_vma(mm, address);
+ if (!vma)
+ goto bad_area;
+ if (vma->vm_start <= address)
+ goto good_area;
+ if (!(vma->vm_flags & VM_GROWSDOWN))
+ goto bad_area;
+ if (expand_stack(vma, address))
+ goto bad_area;
+/*
+ * Ok, we have a good vm_area for this memory access, so
+ * we can handle it..
+ */
+good_area:
+ if (writeaccess) {
+ if (!(vma->vm_flags & VM_WRITE))
+ goto bad_area;
+ } else {
+ if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
+ goto bad_area;
+ }
+
+ /*
+ * If for any reason at all we couldn't handle the fault,
+ * make sure we exit gracefully rather than endlessly redo
+ * the fault.
+ */
+survive:
+ switch (handle_mm_fault(mm, vma, address, writeaccess)) {
+ case VM_FAULT_MINOR:
+ tsk->min_flt++;
+ break;
+ case VM_FAULT_MAJOR:
+ tsk->maj_flt++;
+ break;
+ case VM_FAULT_SIGBUS:
+ goto do_sigbus;
+ case VM_FAULT_OOM:
+ goto out_of_memory;
+ default:
+ BUG();
+ }
+
+ up_read(&mm->mmap_sem);
+ return;
+
+/*
+ * Something tried to access memory that isn't in our memory map..
+ * Fix it, but check if it's kernel or user first..
+ */
+bad_area:
+ up_read(&mm->mmap_sem);
+
+ if (user_mode(regs)) {
+ tsk->thread.address = address;
+ tsk->thread.error_code = writeaccess;
+ force_sig(SIGSEGV, tsk);
+ return;
+ }
+
+no_context:
+ /* Are we prepared to handle this kernel fault? */
+ if (fixup_exception(regs))
+ return;
+
+/*
+ * Oops. The kernel tried to access some bad page. We'll have to
+ * terminate things with extreme prejudice.
+ *
+ */
+ if (address < PAGE_SIZE)
+ printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference");
+ else
+ printk(KERN_ALERT "Unable to handle kernel paging request");
+ printk(" at virtual address %08lx\n", address);
+ printk(KERN_ALERT "pc = %08lx\n", regs->pc);
+ asm volatile("mov.l %1, %0"
+ : "=r" (page)
+ : "m" (__m(MMU_TTB)));
+ if (page) {
+ page = ((unsigned long *) page)[address >> 22];
+ printk(KERN_ALERT "*pde = %08lx\n", page);
+ if (page & _PAGE_PRESENT) {
+ page &= PAGE_MASK;
+ address &= 0x003ff000;
+ page = ((unsigned long *) __va(page))[address >> PAGE_SHIFT];
+ printk(KERN_ALERT "*pte = %08lx\n", page);
+ }
+ }
+ die("Oops", regs, writeaccess);
+ do_exit(SIGKILL);
+
+/*
+ * We ran out of memory, or some other thing happened to us that made
+ * us unable to handle the page fault gracefully.
+ */
+out_of_memory:
+ up_read(&mm->mmap_sem);
+ if (current->pid == 1) {
+ yield();
+ down_read(&mm->mmap_sem);
+ goto survive;
+ }
+ printk("VM: killing process %s\n", tsk->comm);
+ if (user_mode(regs))
+ do_exit(SIGKILL);
+ goto no_context;
+
+do_sigbus:
+ up_read(&mm->mmap_sem);
+
+ /*
+ * Send a sigbus, regardless of whether we were in kernel
+ * or user mode.
+ */
+ tsk->thread.address = address;
+ tsk->thread.error_code = writeaccess;
+ tsk->thread.trap_no = 14;
+ force_sig(SIGBUS, tsk);
+
+ /* Kernel mode? Handle exceptions or die */
+ if (!user_mode(regs))
+ goto no_context;
+}
+
+/*
+ * Called with interrupt disabled.
+ */
+asmlinkage int __do_page_fault(struct pt_regs *regs, unsigned long writeaccess,
+ unsigned long address)
+{
+ unsigned long addrmax = P4SEG;
+ pgd_t *dir;
+ pmd_t *pmd;
+ pte_t *pte;
+ pte_t entry;
+
+#ifdef CONFIG_SH_KGDB
+ if (kgdb_nofault && kgdb_bus_err_hook)
+ kgdb_bus_err_hook();
+#endif
+
+#ifdef CONFIG_SH_STORE_QUEUES
+ addrmax = P4SEG_STORE_QUE + 0x04000000;
+#endif
+
+ if (address >= P3SEG && address < addrmax)
+ dir = pgd_offset_k(address);
+ else if (address >= TASK_SIZE)
+ return 1;
+ else if (!current->mm)
+ return 1;
+ else
+ dir = pgd_offset(current->mm, address);
+
+ pmd = pmd_offset(dir, address);
+ if (pmd_none(*pmd))
+ return 1;
+ if (pmd_bad(*pmd)) {
+ pmd_ERROR(*pmd);
+ pmd_clear(pmd);
+ return 1;
+ }
+ pte = pte_offset_kernel(pmd, address);
+ entry = *pte;
+ if (pte_none(entry) || pte_not_present(entry)
+ || (writeaccess && !pte_write(entry)))
+ return 1;
+
+ if (writeaccess)
+ entry = pte_mkdirty(entry);
+ entry = pte_mkyoung(entry);
+
+#ifdef CONFIG_CPU_SH4
+ /*
+ * ITLB is not affected by "ldtlb" instruction.
+ * So, we need to flush the entry by ourselves.
+ */
+
+ {
+ unsigned long flags;
+ local_irq_save(flags);
+ __flush_tlb_page(get_asid(), address&PAGE_MASK);
+ local_irq_restore(flags);
+ }
+#endif
+
+ set_pte(pte, entry);
+ update_mmu_cache(NULL, address, entry);
+
+ return 0;
+}
+
+void flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
+{
+ if (vma->vm_mm && vma->vm_mm->context != NO_CONTEXT) {
+ unsigned long flags;
+ unsigned long asid;
+ unsigned long saved_asid = MMU_NO_ASID;
+
+ asid = vma->vm_mm->context & MMU_CONTEXT_ASID_MASK;
+ page &= PAGE_MASK;
+
+ local_irq_save(flags);
+ if (vma->vm_mm != current->mm) {
+ saved_asid = get_asid();
+ set_asid(asid);
+ }
+ __flush_tlb_page(asid, page);
+ if (saved_asid != MMU_NO_ASID)
+ set_asid(saved_asid);
+ local_irq_restore(flags);
+ }
+}
+
+void flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
+ unsigned long end)
+{
+ struct mm_struct *mm = vma->vm_mm;
+
+ if (mm->context != NO_CONTEXT) {
+ unsigned long flags;
+ int size;
+
+ local_irq_save(flags);
+ size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
+ if (size > (MMU_NTLB_ENTRIES/4)) { /* Too many TLB to flush */
+ mm->context = NO_CONTEXT;
+ if (mm == current->mm)
+ activate_context(mm);
+ } else {
+ unsigned long asid = mm->context&MMU_CONTEXT_ASID_MASK;
+ unsigned long saved_asid = MMU_NO_ASID;
+
+ start &= PAGE_MASK;
+ end += (PAGE_SIZE - 1);
+ end &= PAGE_MASK;
+ if (mm != current->mm) {
+ saved_asid = get_asid();
+ set_asid(asid);
+ }
+ while (start < end) {
+ __flush_tlb_page(asid, start);
+ start += PAGE_SIZE;
+ }
+ if (saved_asid != MMU_NO_ASID)
+ set_asid(saved_asid);
+ }
+ local_irq_restore(flags);
+ }
+}
+
+void flush_tlb_kernel_range(unsigned long start, unsigned long end)
+{
+ unsigned long flags;
+ int size;
+
+ local_irq_save(flags);
+ size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
+ if (size > (MMU_NTLB_ENTRIES/4)) { /* Too many TLB to flush */
+ flush_tlb_all();
+ } else {
+ unsigned long asid = init_mm.context&MMU_CONTEXT_ASID_MASK;
+ unsigned long saved_asid = get_asid();
+
+ start &= PAGE_MASK;
+ end += (PAGE_SIZE - 1);
+ end &= PAGE_MASK;
+ set_asid(asid);
+ while (start < end) {
+ __flush_tlb_page(asid, start);
+ start += PAGE_SIZE;
+ }
+ set_asid(saved_asid);
+ }
+ local_irq_restore(flags);
+}
+
+void flush_tlb_mm(struct mm_struct *mm)
+{
+ /* Invalidate all TLB of this process. */
+ /* Instead of invalidating each TLB, we get new MMU context. */
+ if (mm->context != NO_CONTEXT) {
+ unsigned long flags;
+
+ local_irq_save(flags);
+ mm->context = NO_CONTEXT;
+ if (mm == current->mm)
+ activate_context(mm);
+ local_irq_restore(flags);
+ }
+}
+
+void flush_tlb_all(void)
+{
+ unsigned long flags, status;
+
+ /*
+ * Flush all the TLB.
+ *
+ * Write to the MMU control register's bit:
+ * TF-bit for SH-3, TI-bit for SH-4.
+ * It's same position, bit #2.
+ */
+ local_irq_save(flags);
+ status = ctrl_inl(MMUCR);
+ status |= 0x04;
+ ctrl_outl(status, MMUCR);
+ local_irq_restore(flags);
+}
diff --git a/arch/sh/mm/hugetlbpage.c b/arch/sh/mm/hugetlbpage.c
new file mode 100644
index 000000000000..1f897bab2318
--- /dev/null
+++ b/arch/sh/mm/hugetlbpage.c
@@ -0,0 +1,264 @@
+/*
+ * arch/sh/mm/hugetlbpage.c
+ *
+ * SuperH HugeTLB page support.
+ *
+ * Cloned from sparc64 by Paul Mundt.
+ *
+ * Copyright (C) 2002, 2003 David S. Miller (davem@redhat.com)
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/hugetlb.h>
+#include <linux/pagemap.h>
+#include <linux/smp_lock.h>
+#include <linux/slab.h>
+#include <linux/sysctl.h>
+
+#include <asm/mman.h>
+#include <asm/pgalloc.h>
+#include <asm/tlb.h>
+#include <asm/tlbflush.h>
+#include <asm/cacheflush.h>
+
+static pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr)
+{
+ pgd_t *pgd;
+ pmd_t *pmd;
+ pte_t *pte = NULL;
+
+ pgd = pgd_offset(mm, addr);
+ if (pgd) {
+ pmd = pmd_alloc(mm, pgd, addr);
+ if (pmd)
+ pte = pte_alloc_map(mm, pmd, addr);
+ }
+ return pte;
+}
+
+static pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr)
+{
+ pgd_t *pgd;
+ pmd_t *pmd;
+ pte_t *pte = NULL;
+
+ pgd = pgd_offset(mm, addr);
+ if (pgd) {
+ pmd = pmd_offset(pgd, addr);
+ if (pmd)
+ pte = pte_offset_map(pmd, addr);
+ }
+ return pte;
+}
+
+#define mk_pte_huge(entry) do { pte_val(entry) |= _PAGE_SZHUGE; } while (0)
+
+static void set_huge_pte(struct mm_struct *mm, struct vm_area_struct *vma,
+ struct page *page, pte_t * page_table, int write_access)
+{
+ unsigned long i;
+ pte_t entry;
+
+ add_mm_counter(mm, rss, HPAGE_SIZE / PAGE_SIZE);
+
+ if (write_access)
+ entry = pte_mkwrite(pte_mkdirty(mk_pte(page,
+ vma->vm_page_prot)));
+ else
+ entry = pte_wrprotect(mk_pte(page, vma->vm_page_prot));
+ entry = pte_mkyoung(entry);
+ mk_pte_huge(entry);
+
+ for (i = 0; i < (1 << HUGETLB_PAGE_ORDER); i++) {
+ set_pte(page_table, entry);
+ page_table++;
+
+ pte_val(entry) += PAGE_SIZE;
+ }
+}
+
+/*
+ * This function checks for proper alignment of input addr and len parameters.
+ */
+int is_aligned_hugepage_range(unsigned long addr, unsigned long len)
+{
+ if (len & ~HPAGE_MASK)
+ return -EINVAL;
+ if (addr & ~HPAGE_MASK)
+ return -EINVAL;
+ return 0;
+}
+
+int copy_hugetlb_page_range(struct mm_struct *dst, struct mm_struct *src,
+ struct vm_area_struct *vma)
+{
+ pte_t *src_pte, *dst_pte, entry;
+ struct page *ptepage;
+ unsigned long addr = vma->vm_start;
+ unsigned long end = vma->vm_end;
+ int i;
+
+ while (addr < end) {
+ dst_pte = huge_pte_alloc(dst, addr);
+ if (!dst_pte)
+ goto nomem;
+ src_pte = huge_pte_offset(src, addr);
+ BUG_ON(!src_pte || pte_none(*src_pte));
+ entry = *src_pte;
+ ptepage = pte_page(entry);
+ get_page(ptepage);
+ for (i = 0; i < (1 << HUGETLB_PAGE_ORDER); i++) {
+ set_pte(dst_pte, entry);
+ pte_val(entry) += PAGE_SIZE;
+ dst_pte++;
+ }
+ add_mm_counter(dst, rss, HPAGE_SIZE / PAGE_SIZE);
+ addr += HPAGE_SIZE;
+ }
+ return 0;
+
+nomem:
+ return -ENOMEM;
+}
+
+int follow_hugetlb_page(struct mm_struct *mm, struct vm_area_struct *vma,
+ struct page **pages, struct vm_area_struct **vmas,
+ unsigned long *position, int *length, int i)
+{
+ unsigned long vaddr = *position;
+ int remainder = *length;
+
+ WARN_ON(!is_vm_hugetlb_page(vma));
+
+ while (vaddr < vma->vm_end && remainder) {
+ if (pages) {
+ pte_t *pte;
+ struct page *page;
+
+ pte = huge_pte_offset(mm, vaddr);
+
+ /* hugetlb should be locked, and hence, prefaulted */
+ BUG_ON(!pte || pte_none(*pte));
+
+ page = pte_page(*pte);
+
+ WARN_ON(!PageCompound(page));
+
+ get_page(page);
+ pages[i] = page;
+ }
+
+ if (vmas)
+ vmas[i] = vma;
+
+ vaddr += PAGE_SIZE;
+ --remainder;
+ ++i;
+ }
+
+ *length = remainder;
+ *position = vaddr;
+
+ return i;
+}
+
+struct page *follow_huge_addr(struct mm_struct *mm,
+ unsigned long address, int write)
+{
+ return ERR_PTR(-EINVAL);
+}
+
+int pmd_huge(pmd_t pmd)
+{
+ return 0;
+}
+
+struct page *follow_huge_pmd(struct mm_struct *mm, unsigned long address,
+ pmd_t *pmd, int write)
+{
+ return NULL;
+}
+
+void unmap_hugepage_range(struct vm_area_struct *vma,
+ unsigned long start, unsigned long end)
+{
+ struct mm_struct *mm = vma->vm_mm;
+ unsigned long address;
+ pte_t *pte;
+ struct page *page;
+ int i;
+
+ BUG_ON(start & (HPAGE_SIZE - 1));
+ BUG_ON(end & (HPAGE_SIZE - 1));
+
+ for (address = start; address < end; address += HPAGE_SIZE) {
+ pte = huge_pte_offset(mm, address);
+ BUG_ON(!pte);
+ if (pte_none(*pte))
+ continue;
+ page = pte_page(*pte);
+ put_page(page);
+ for (i = 0; i < (1 << HUGETLB_PAGE_ORDER); i++) {
+ pte_clear(mm, address+(i*PAGE_SIZE), pte);
+ pte++;
+ }
+ }
+ add_mm_counter(mm, rss, -((end - start) >> PAGE_SHIFT));
+ flush_tlb_range(vma, start, end);
+}
+
+int hugetlb_prefault(struct address_space *mapping, struct vm_area_struct *vma)
+{
+ struct mm_struct *mm = current->mm;
+ unsigned long addr;
+ int ret = 0;
+
+ BUG_ON(vma->vm_start & ~HPAGE_MASK);
+ BUG_ON(vma->vm_end & ~HPAGE_MASK);
+
+ spin_lock(&mm->page_table_lock);
+ for (addr = vma->vm_start; addr < vma->vm_end; addr += HPAGE_SIZE) {
+ unsigned long idx;
+ pte_t *pte = huge_pte_alloc(mm, addr);
+ struct page *page;
+
+ if (!pte) {
+ ret = -ENOMEM;
+ goto out;
+ }
+ if (!pte_none(*pte))
+ continue;
+
+ idx = ((addr - vma->vm_start) >> HPAGE_SHIFT)
+ + (vma->vm_pgoff >> (HPAGE_SHIFT - PAGE_SHIFT));
+ page = find_get_page(mapping, idx);
+ if (!page) {
+ /* charge the fs quota first */
+ if (hugetlb_get_quota(mapping)) {
+ ret = -ENOMEM;
+ goto out;
+ }
+ page = alloc_huge_page();
+ if (!page) {
+ hugetlb_put_quota(mapping);
+ ret = -ENOMEM;
+ goto out;
+ }
+ ret = add_to_page_cache(page, mapping, idx, GFP_ATOMIC);
+ if (! ret) {
+ unlock_page(page);
+ } else {
+ hugetlb_put_quota(mapping);
+ free_huge_page(page);
+ goto out;
+ }
+ }
+ set_huge_pte(mm, vma, page, pte, vma->vm_flags & VM_WRITE);
+ }
+out:
+ spin_unlock(&mm->page_table_lock);
+ return ret;
+}
diff --git a/arch/sh/mm/init.c b/arch/sh/mm/init.c
new file mode 100644
index 000000000000..4e9c854845a4
--- /dev/null
+++ b/arch/sh/mm/init.c
@@ -0,0 +1,313 @@
+/* $Id: init.c,v 1.19 2004/02/21 04:42:16 kkojima Exp $
+ *
+ * linux/arch/sh/mm/init.c
+ *
+ * Copyright (C) 1999 Niibe Yutaka
+ * Copyright (C) 2002, 2004 Paul Mundt
+ *
+ * Based on linux/arch/i386/mm/init.c:
+ * Copyright (C) 1995 Linus Torvalds
+ */
+
+#include <linux/config.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/ptrace.h>
+#include <linux/mman.h>
+#include <linux/mm.h>
+#include <linux/swap.h>
+#include <linux/smp.h>
+#include <linux/init.h>
+#include <linux/highmem.h>
+#include <linux/bootmem.h>
+#include <linux/pagemap.h>
+
+#include <asm/processor.h>
+#include <asm/system.h>
+#include <asm/uaccess.h>
+#include <asm/pgtable.h>
+#include <asm/pgalloc.h>
+#include <asm/mmu_context.h>
+#include <asm/io.h>
+#include <asm/tlb.h>
+#include <asm/cacheflush.h>
+#include <asm/cache.h>
+
+DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
+pgd_t swapper_pg_dir[PTRS_PER_PGD];
+
+/*
+ * Cache of MMU context last used.
+ */
+unsigned long mmu_context_cache = NO_CONTEXT;
+
+#ifdef CONFIG_MMU
+/* It'd be good if these lines were in the standard header file. */
+#define START_PFN (NODE_DATA(0)->bdata->node_boot_start >> PAGE_SHIFT)
+#define MAX_LOW_PFN (NODE_DATA(0)->bdata->node_low_pfn)
+#endif
+
+#ifdef CONFIG_DISCONTIGMEM
+pg_data_t discontig_page_data[MAX_NUMNODES];
+bootmem_data_t discontig_node_bdata[MAX_NUMNODES];
+#endif
+
+void (*copy_page)(void *from, void *to);
+void (*clear_page)(void *to);
+
+void show_mem(void)
+{
+ int i, total = 0, reserved = 0;
+ int shared = 0, cached = 0;
+
+ printk("Mem-info:\n");
+ show_free_areas();
+ printk("Free swap: %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10));
+ i = max_mapnr;
+ while (i-- > 0) {
+ total++;
+ if (PageReserved(mem_map+i))
+ reserved++;
+ else if (PageSwapCache(mem_map+i))
+ cached++;
+ else if (page_count(mem_map+i))
+ shared += page_count(mem_map+i) - 1;
+ }
+ printk("%d pages of RAM\n",total);
+ printk("%d reserved pages\n",reserved);
+ printk("%d pages shared\n",shared);
+ printk("%d pages swap cached\n",cached);
+}
+
+static void set_pte_phys(unsigned long addr, unsigned long phys, pgprot_t prot)
+{
+ pgd_t *pgd;
+ pmd_t *pmd;
+ pte_t *pte;
+
+ pgd = swapper_pg_dir + pgd_index(addr);
+ if (pgd_none(*pgd)) {
+ pgd_ERROR(*pgd);
+ return;
+ }
+
+ pmd = pmd_offset(pgd, addr);
+ if (pmd_none(*pmd)) {
+ pte = (pte_t *)get_zeroed_page(GFP_ATOMIC);
+ set_pmd(pmd, __pmd(__pa(pte) | _KERNPG_TABLE | _PAGE_USER));
+ if (pte != pte_offset_kernel(pmd, 0)) {
+ pmd_ERROR(*pmd);
+ return;
+ }
+ }
+
+ pte = pte_offset_kernel(pmd, addr);
+ if (!pte_none(*pte)) {
+ pte_ERROR(*pte);
+ return;
+ }
+
+ set_pte(pte, pfn_pte(phys >> PAGE_SHIFT, prot));
+
+ __flush_tlb_page(get_asid(), addr);
+}
+
+/*
+ * As a performance optimization, other platforms preserve the fixmap mapping
+ * across a context switch, we don't presently do this, but this could be done
+ * in a similar fashion as to the wired TLB interface that sh64 uses (by way
+ * of the memorry mapped UTLB configuration) -- this unfortunately forces us to
+ * give up a TLB entry for each mapping we want to preserve. While this may be
+ * viable for a small number of fixmaps, it's not particularly useful for
+ * everything and needs to be carefully evaluated. (ie, we may want this for
+ * the vsyscall page).
+ *
+ * XXX: Perhaps add a _PAGE_WIRED flag or something similar that we can pass
+ * in at __set_fixmap() time to determine the appropriate behavior to follow.
+ *
+ * -- PFM.
+ */
+void __set_fixmap(enum fixed_addresses idx, unsigned long phys, pgprot_t prot)
+{
+ unsigned long address = __fix_to_virt(idx);
+
+ if (idx >= __end_of_fixed_addresses) {
+ BUG();
+ return;
+ }
+
+ set_pte_phys(address, phys, prot);
+}
+
+/* References to section boundaries */
+
+extern char _text, _etext, _edata, __bss_start, _end;
+extern char __init_begin, __init_end;
+
+/*
+ * paging_init() sets up the page tables
+ *
+ * This routines also unmaps the page at virtual kernel address 0, so
+ * that we can trap those pesky NULL-reference errors in the kernel.
+ */
+void __init paging_init(void)
+{
+ unsigned long zones_size[MAX_NR_ZONES] = { 0, };
+
+ /*
+ * Setup some defaults for the zone sizes.. these should be safe
+ * regardless of distcontiguous memory or MMU settings.
+ */
+ zones_size[ZONE_DMA] = 0 >> PAGE_SHIFT;
+ zones_size[ZONE_NORMAL] = __MEMORY_SIZE >> PAGE_SHIFT;
+#ifdef CONFIG_HIGHMEM
+ zones_size[ZONE_HIGHMEM] = 0 >> PAGE_SHIFT;
+#endif
+
+#ifdef CONFIG_MMU
+ /*
+ * If we have an MMU, and want to be using it .. we need to adjust
+ * the zone sizes accordingly, in addition to turning it on.
+ */
+ {
+ unsigned long max_dma, low, start_pfn;
+ pgd_t *pg_dir;
+ int i;
+
+ /* We don't need kernel mapping as hardware support that. */
+ pg_dir = swapper_pg_dir;
+
+ for (i = 0; i < PTRS_PER_PGD; i++)
+ pgd_val(pg_dir[i]) = 0;
+
+ /* Turn on the MMU */
+ enable_mmu();
+
+ /* Fixup the zone sizes */
+ start_pfn = START_PFN;
+ max_dma = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT;
+ low = MAX_LOW_PFN;
+
+ if (low < max_dma) {
+ zones_size[ZONE_DMA] = low - start_pfn;
+ zones_size[ZONE_NORMAL] = 0;
+ } else {
+ zones_size[ZONE_DMA] = max_dma - start_pfn;
+ zones_size[ZONE_NORMAL] = low - max_dma;
+ }
+ }
+
+#elif defined(CONFIG_CPU_SH3) || defined(CONFIG_CPU_SH4)
+ /*
+ * If we don't have CONFIG_MMU set and the processor in question
+ * still has an MMU, care needs to be taken to make sure it doesn't
+ * stay on.. Since the boot loader could have potentially already
+ * turned it on, and we clearly don't want it, we simply turn it off.
+ *
+ * We don't need to do anything special for the zone sizes, since the
+ * default values that were already configured up above should be
+ * satisfactory.
+ */
+ disable_mmu();
+#endif
+ NODE_DATA(0)->node_mem_map = NULL;
+ free_area_init_node(0, NODE_DATA(0), zones_size, __MEMORY_START >> PAGE_SHIFT, 0);
+
+#ifdef CONFIG_DISCONTIGMEM
+ /*
+ * And for discontig, do some more fixups on the zone sizes..
+ */
+ zones_size[ZONE_DMA] = __MEMORY_SIZE_2ND >> PAGE_SHIFT;
+ zones_size[ZONE_NORMAL] = 0;
+ free_area_init_node(1, NODE_DATA(1), zones_size, __MEMORY_START_2ND >> PAGE_SHIFT, 0);
+#endif
+}
+
+void __init mem_init(void)
+{
+ extern unsigned long empty_zero_page[1024];
+ int codesize, reservedpages, datasize, initsize;
+ int tmp;
+ extern unsigned long memory_start;
+
+#ifdef CONFIG_MMU
+ high_memory = (void *)__va(MAX_LOW_PFN * PAGE_SIZE);
+#else
+ extern unsigned long memory_end;
+
+ high_memory = (void *)(memory_end & PAGE_MASK);
+#endif
+
+ max_mapnr = num_physpages = MAP_NR(high_memory) - MAP_NR(memory_start);
+
+ /* clear the zero-page */
+ memset(empty_zero_page, 0, PAGE_SIZE);
+ __flush_wback_region(empty_zero_page, PAGE_SIZE);
+
+ /*
+ * Setup wrappers for copy/clear_page(), these will get overridden
+ * later in the boot process if a better method is available.
+ */
+ copy_page = copy_page_slow;
+ clear_page = clear_page_slow;
+
+ /* this will put all low memory onto the freelists */
+ totalram_pages += free_all_bootmem_node(NODE_DATA(0));
+#ifdef CONFIG_DISCONTIGMEM
+ totalram_pages += free_all_bootmem_node(NODE_DATA(1));
+#endif
+ reservedpages = 0;
+ for (tmp = 0; tmp < num_physpages; tmp++)
+ /*
+ * Only count reserved RAM pages
+ */
+ if (PageReserved(mem_map+tmp))
+ reservedpages++;
+
+ codesize = (unsigned long) &_etext - (unsigned long) &_text;
+ datasize = (unsigned long) &_edata - (unsigned long) &_etext;
+ initsize = (unsigned long) &__init_end - (unsigned long) &__init_begin;
+
+ printk("Memory: %luk/%luk available (%dk kernel code, %dk reserved, %dk data, %dk init)\n",
+ (unsigned long) nr_free_pages() << (PAGE_SHIFT-10),
+ max_mapnr << (PAGE_SHIFT-10),
+ codesize >> 10,
+ reservedpages << (PAGE_SHIFT-10),
+ datasize >> 10,
+ initsize >> 10);
+
+ p3_cache_init();
+}
+
+void free_initmem(void)
+{
+ unsigned long addr;
+
+ addr = (unsigned long)(&__init_begin);
+ for (; addr < (unsigned long)(&__init_end); addr += PAGE_SIZE) {
+ ClearPageReserved(virt_to_page(addr));
+ set_page_count(virt_to_page(addr), 1);
+ free_page(addr);
+ totalram_pages++;
+ }
+ printk ("Freeing unused kernel memory: %dk freed\n", (&__init_end - &__init_begin) >> 10);
+}
+
+#ifdef CONFIG_BLK_DEV_INITRD
+void free_initrd_mem(unsigned long start, unsigned long end)
+{
+ unsigned long p;
+ for (p = start; p < end; p += PAGE_SIZE) {
+ ClearPageReserved(virt_to_page(p));
+ set_page_count(virt_to_page(p), 1);
+ free_page(p);
+ totalram_pages++;
+ }
+ printk ("Freeing initrd memory: %ldk freed\n", (end - start) >> 10);
+}
+#endif
+
diff --git a/arch/sh/mm/ioremap.c b/arch/sh/mm/ioremap.c
new file mode 100644
index 000000000000..9f490c2742f0
--- /dev/null
+++ b/arch/sh/mm/ioremap.c
@@ -0,0 +1,163 @@
+/*
+ * arch/sh/mm/ioremap.c
+ *
+ * Re-map IO memory to kernel address space so that we can access it.
+ * This is needed for high PCI addresses that aren't mapped in the
+ * 640k-1MB IO memory area on PC's
+ *
+ * (C) Copyright 1995 1996 Linus Torvalds
+ */
+
+#include <linux/vmalloc.h>
+#include <linux/mm.h>
+#include <asm/io.h>
+#include <asm/page.h>
+#include <asm/pgalloc.h>
+#include <asm/cacheflush.h>
+#include <asm/tlbflush.h>
+
+static inline void remap_area_pte(pte_t * pte, unsigned long address,
+ unsigned long size, unsigned long phys_addr, unsigned long flags)
+{
+ unsigned long end;
+ unsigned long pfn;
+ pgprot_t pgprot = __pgprot(_PAGE_PRESENT | _PAGE_RW |
+ _PAGE_DIRTY | _PAGE_ACCESSED |
+ _PAGE_HW_SHARED | _PAGE_FLAGS_HARD | flags);
+
+ address &= ~PMD_MASK;
+ end = address + size;
+ if (end > PMD_SIZE)
+ end = PMD_SIZE;
+ if (address >= end)
+ BUG();
+ pfn = phys_addr >> PAGE_SHIFT;
+ do {
+ if (!pte_none(*pte)) {
+ printk("remap_area_pte: page already exists\n");
+ BUG();
+ }
+ set_pte(pte, pfn_pte(pfn, pgprot));
+ address += PAGE_SIZE;
+ pfn++;
+ pte++;
+ } while (address && (address < end));
+}
+
+static inline int remap_area_pmd(pmd_t * pmd, unsigned long address,
+ unsigned long size, unsigned long phys_addr, unsigned long flags)
+{
+ unsigned long end;
+
+ address &= ~PGDIR_MASK;
+ end = address + size;
+ if (end > PGDIR_SIZE)
+ end = PGDIR_SIZE;
+ phys_addr -= address;
+ if (address >= end)
+ BUG();
+ do {
+ pte_t * pte = pte_alloc_kernel(&init_mm, pmd, address);
+ if (!pte)
+ return -ENOMEM;
+ remap_area_pte(pte, address, end - address, address + phys_addr, flags);
+ address = (address + PMD_SIZE) & PMD_MASK;
+ pmd++;
+ } while (address && (address < end));
+ return 0;
+}
+
+int remap_area_pages(unsigned long address, unsigned long phys_addr,
+ unsigned long size, unsigned long flags)
+{
+ int error;
+ pgd_t * dir;
+ unsigned long end = address + size;
+
+ phys_addr -= address;
+ dir = pgd_offset_k(address);
+ flush_cache_all();
+ if (address >= end)
+ BUG();
+ spin_lock(&init_mm.page_table_lock);
+ do {
+ pmd_t *pmd;
+ pmd = pmd_alloc(&init_mm, dir, address);
+ error = -ENOMEM;
+ if (!pmd)
+ break;
+ if (remap_area_pmd(pmd, address, end - address,
+ phys_addr + address, flags))
+ break;
+ error = 0;
+ address = (address + PGDIR_SIZE) & PGDIR_MASK;
+ dir++;
+ } while (address && (address < end));
+ spin_unlock(&init_mm.page_table_lock);
+ flush_tlb_all();
+ return error;
+}
+
+/*
+ * Generic mapping function (not visible outside):
+ */
+
+/*
+ * Remap an arbitrary physical address space into the kernel virtual
+ * address space. Needed when the kernel wants to access high addresses
+ * directly.
+ *
+ * NOTE! We need to allow non-page-aligned mappings too: we will obviously
+ * have to convert them into an offset in a page-aligned mapping, but the
+ * caller shouldn't need to know that small detail.
+ */
+void * p3_ioremap(unsigned long phys_addr, unsigned long size, unsigned long flags)
+{
+ void * addr;
+ struct vm_struct * area;
+ unsigned long offset, last_addr;
+
+ /* Don't allow wraparound or zero size */
+ last_addr = phys_addr + size - 1;
+ if (!size || last_addr < phys_addr)
+ return NULL;
+
+ /*
+ * Don't remap the low PCI/ISA area, it's always mapped..
+ */
+ if (phys_addr >= 0xA0000 && last_addr < 0x100000)
+ return phys_to_virt(phys_addr);
+
+ /*
+ * Don't allow anybody to remap normal RAM that we're using..
+ */
+ if (phys_addr < virt_to_phys(high_memory))
+ return NULL;
+
+ /*
+ * Mappings have to be page-aligned
+ */
+ offset = phys_addr & ~PAGE_MASK;
+ phys_addr &= PAGE_MASK;
+ size = PAGE_ALIGN(last_addr+1) - phys_addr;
+
+ /*
+ * Ok, go for it..
+ */
+ area = get_vm_area(size, VM_IOREMAP);
+ if (!area)
+ return NULL;
+ area->phys_addr = phys_addr;
+ addr = area->addr;
+ if (remap_area_pages((unsigned long) addr, phys_addr, size, flags)) {
+ vunmap(addr);
+ return NULL;
+ }
+ return (void *) (offset + (char *)addr);
+}
+
+void p3_iounmap(void *addr)
+{
+ if (addr > high_memory)
+ vfree((void *)(PAGE_MASK & (unsigned long)addr));
+}
diff --git a/arch/sh/mm/pg-dma.c b/arch/sh/mm/pg-dma.c
new file mode 100644
index 000000000000..1406d2e348ca
--- /dev/null
+++ b/arch/sh/mm/pg-dma.c
@@ -0,0 +1,97 @@
+/*
+ * arch/sh/mm/pg-dma.c
+ *
+ * Fast clear_page()/copy_page() implementation using the SH 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/kernel.h>
+#include <linux/module.h>
+#include <asm/semaphore.h>
+#include <asm/mmu_context.h>
+#include <asm/addrspace.h>
+#include <asm/atomic.h>
+#include <asm/page.h>
+#include <asm/dma.h>
+#include <asm/io.h>
+
+/* Channel to use for page ops, must be dual-address mode capable. */
+static int dma_channel = CONFIG_DMA_PAGE_OPS_CHANNEL;
+
+static void copy_page_dma(void *to, void *from)
+{
+ /*
+ * This doesn't seem to get triggered until further along in the
+ * boot process, at which point the DMAC is already initialized.
+ * Fix this in the same fashion as clear_page_dma() in the event
+ * that this crashes due to the DMAC not being initialized.
+ */
+
+ flush_icache_range((unsigned long)from, PAGE_SIZE);
+ dma_write_page(dma_channel, (unsigned long)from, (unsigned long)to);
+ dma_wait_for_completion(dma_channel);
+}
+
+static void clear_page_dma(void *to)
+{
+ extern unsigned long empty_zero_page[1024];
+
+ /*
+ * We get invoked quite early on, if the DMAC hasn't been initialized
+ * yet, fall back on the slow manual implementation.
+ */
+ if (dma_info[dma_channel].chan != dma_channel) {
+ clear_page_slow(to);
+ return;
+ }
+
+ dma_write_page(dma_channel, (unsigned long)empty_zero_page,
+ (unsigned long)to);
+
+ /*
+ * FIXME: Something is a bit racy here, if we poll the counter right
+ * away, we seem to lock. flushing the page from the dcache doesn't
+ * seem to make a difference one way or the other, though either a full
+ * icache or dcache flush does.
+ *
+ * The location of this is important as well, and must happen prior to
+ * the completion loop but after the transfer was initiated.
+ *
+ * Oddly enough, this doesn't appear to be an issue for copy_page()..
+ */
+ flush_icache_range((unsigned long)to, PAGE_SIZE);
+
+ dma_wait_for_completion(dma_channel);
+}
+
+static int __init pg_dma_init(void)
+{
+ int ret;
+
+ ret = request_dma(dma_channel, "page ops");
+ if (ret != 0)
+ return ret;
+
+ copy_page = copy_page_dma;
+ clear_page = clear_page_dma;
+
+ return ret;
+}
+
+static void __exit pg_dma_exit(void)
+{
+ free_dma(dma_channel);
+}
+
+module_init(pg_dma_init);
+module_exit(pg_dma_exit);
+
+MODULE_AUTHOR("Paul Mundt <lethal@linux-sh.org>");
+MODULE_DESCRIPTION("Optimized page copy/clear routines using a dual-address mode capable DMAC channel");
+MODULE_LICENSE("GPL");
+
diff --git a/arch/sh/mm/pg-nommu.c b/arch/sh/mm/pg-nommu.c
new file mode 100644
index 000000000000..8f9165a4e333
--- /dev/null
+++ b/arch/sh/mm/pg-nommu.c
@@ -0,0 +1,36 @@
+/*
+ * arch/sh/mm/pg-nommu.c
+ *
+ * clear_page()/copy_page() implementation for MMUless SH.
+ *
+ * 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/kernel.h>
+#include <linux/string.h>
+#include <asm/page.h>
+
+static void copy_page_nommu(void *to, void *from)
+{
+ memcpy(to, from, PAGE_SIZE);
+}
+
+static void clear_page_nommu(void *to)
+{
+ memset(to, 0, PAGE_SIZE);
+}
+
+static int __init pg_nommu_init(void)
+{
+ copy_page = copy_page_nommu;
+ clear_page = clear_page_nommu;
+
+ return 0;
+}
+
+subsys_initcall(pg_nommu_init);
+
diff --git a/arch/sh/mm/pg-sh4.c b/arch/sh/mm/pg-sh4.c
new file mode 100644
index 000000000000..e5907c7330e5
--- /dev/null
+++ b/arch/sh/mm/pg-sh4.c
@@ -0,0 +1,122 @@
+/*
+ * arch/sh/mm/pg-sh4.c
+ *
+ * Copyright (C) 1999, 2000, 2002 Niibe Yutaka
+ * Copyright (C) 2002 Paul Mundt
+ *
+ * Released under the terms of the GNU GPL v2.0.
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/mman.h>
+#include <linux/mm.h>
+#include <linux/threads.h>
+#include <asm/addrspace.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/processor.h>
+#include <asm/cache.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/pgalloc.h>
+#include <asm/mmu_context.h>
+#include <asm/cacheflush.h>
+
+extern struct semaphore p3map_sem[];
+
+/*
+ * clear_user_page
+ * @to: P1 address
+ * @address: U0 address to be mapped
+ * @page: page (virt_to_page(to))
+ */
+void clear_user_page(void *to, unsigned long address, struct page *page)
+{
+ __set_bit(PG_mapped, &page->flags);
+ if (((address ^ (unsigned long)to) & CACHE_ALIAS) == 0)
+ clear_page(to);
+ else {
+ pgprot_t pgprot = __pgprot(_PAGE_PRESENT |
+ _PAGE_RW | _PAGE_CACHABLE |
+ _PAGE_DIRTY | _PAGE_ACCESSED |
+ _PAGE_HW_SHARED | _PAGE_FLAGS_HARD);
+ unsigned long phys_addr = PHYSADDR(to);
+ unsigned long p3_addr = P3SEG + (address & CACHE_ALIAS);
+ pgd_t *dir = pgd_offset_k(p3_addr);
+ pmd_t *pmd = pmd_offset(dir, p3_addr);
+ pte_t *pte = pte_offset_kernel(pmd, p3_addr);
+ pte_t entry;
+ unsigned long flags;
+
+ entry = pfn_pte(phys_addr >> PAGE_SHIFT, pgprot);
+ down(&p3map_sem[(address & CACHE_ALIAS)>>12]);
+ set_pte(pte, entry);
+ local_irq_save(flags);
+ __flush_tlb_page(get_asid(), p3_addr);
+ local_irq_restore(flags);
+ update_mmu_cache(NULL, p3_addr, entry);
+ __clear_user_page((void *)p3_addr, to);
+ pte_clear(&init_mm, p3_addr, pte);
+ up(&p3map_sem[(address & CACHE_ALIAS)>>12]);
+ }
+}
+
+/*
+ * copy_user_page
+ * @to: P1 address
+ * @from: P1 address
+ * @address: U0 address to be mapped
+ * @page: page (virt_to_page(to))
+ */
+void copy_user_page(void *to, void *from, unsigned long address,
+ struct page *page)
+{
+ __set_bit(PG_mapped, &page->flags);
+ if (((address ^ (unsigned long)to) & CACHE_ALIAS) == 0)
+ copy_page(to, from);
+ else {
+ pgprot_t pgprot = __pgprot(_PAGE_PRESENT |
+ _PAGE_RW | _PAGE_CACHABLE |
+ _PAGE_DIRTY | _PAGE_ACCESSED |
+ _PAGE_HW_SHARED | _PAGE_FLAGS_HARD);
+ unsigned long phys_addr = PHYSADDR(to);
+ unsigned long p3_addr = P3SEG + (address & CACHE_ALIAS);
+ pgd_t *dir = pgd_offset_k(p3_addr);
+ pmd_t *pmd = pmd_offset(dir, p3_addr);
+ pte_t *pte = pte_offset_kernel(pmd, p3_addr);
+ pte_t entry;
+ unsigned long flags;
+
+ entry = pfn_pte(phys_addr >> PAGE_SHIFT, pgprot);
+ down(&p3map_sem[(address & CACHE_ALIAS)>>12]);
+ set_pte(pte, entry);
+ local_irq_save(flags);
+ __flush_tlb_page(get_asid(), p3_addr);
+ local_irq_restore(flags);
+ update_mmu_cache(NULL, p3_addr, entry);
+ __copy_user_page((void *)p3_addr, from, to);
+ pte_clear(&init_mm, p3_addr, pte);
+ up(&p3map_sem[(address & CACHE_ALIAS)>>12]);
+ }
+}
+
+/*
+ * For SH-4, we have our own implementation for ptep_get_and_clear
+ */
+inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
+{
+ pte_t pte = *ptep;
+
+ pte_clear(mm, addr, ptep);
+ if (!pte_not_present(pte)) {
+ unsigned long pfn = pte_pfn(pte);
+ if (pfn_valid(pfn)) {
+ struct page *page = pfn_to_page(pfn);
+ struct address_space *mapping = page_mapping(page);
+ if (!mapping || !mapping_writably_mapped(mapping))
+ __clear_bit(PG_mapped, &page->flags);
+ }
+ }
+ return pte;
+}
+
diff --git a/arch/sh/mm/pg-sh7705.c b/arch/sh/mm/pg-sh7705.c
new file mode 100644
index 000000000000..ff9ece986cbc
--- /dev/null
+++ b/arch/sh/mm/pg-sh7705.c
@@ -0,0 +1,137 @@
+/*
+ * arch/sh/mm/pg-sh7705.c
+ *
+ * Copyright (C) 1999, 2000 Niibe Yutaka
+ * Copyright (C) 2004 Alex Song
+ *
+ * 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/mman.h>
+#include <linux/mm.h>
+#include <linux/threads.h>
+#include <asm/addrspace.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/processor.h>
+#include <asm/cache.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/pgalloc.h>
+#include <asm/mmu_context.h>
+#include <asm/cacheflush.h>
+
+static inline void __flush_purge_virtual_region(void *p1, void *virt, int size)
+{
+ unsigned long v;
+ unsigned long begin, end;
+ unsigned long p1_begin;
+
+
+ begin = L1_CACHE_ALIGN((unsigned long)virt);
+ end = L1_CACHE_ALIGN((unsigned long)virt + size);
+
+ p1_begin = (unsigned long)p1 & ~(L1_CACHE_BYTES - 1);
+
+ /* do this the slow way as we may not have TLB entries
+ * for virt yet. */
+ for (v = begin; v < end; v += L1_CACHE_BYTES) {
+ unsigned long p;
+ unsigned long ways, addr;
+
+ p = __pa(p1_begin);
+
+ ways = cpu_data->dcache.ways;
+ addr = CACHE_OC_ADDRESS_ARRAY;
+
+ do {
+ unsigned long data;
+
+ addr |= (v & cpu_data->dcache.entry_mask);
+
+ data = ctrl_inl(addr);
+ if ((data & CACHE_PHYSADDR_MASK) ==
+ (p & CACHE_PHYSADDR_MASK)) {
+ data &= ~(SH_CACHE_UPDATED|SH_CACHE_VALID);
+ ctrl_outl(data, addr);
+ }
+
+ addr += cpu_data->dcache.way_incr;
+ } while (--ways);
+
+ p1_begin += L1_CACHE_BYTES;
+ }
+}
+
+/*
+ * clear_user_page
+ * @to: P1 address
+ * @address: U0 address to be mapped
+ */
+void clear_user_page(void *to, unsigned long address, struct page *pg)
+{
+ struct page *page = virt_to_page(to);
+
+ __set_bit(PG_mapped, &page->flags);
+ if (((address ^ (unsigned long)to) & CACHE_ALIAS) == 0) {
+ clear_page(to);
+ __flush_wback_region(to, PAGE_SIZE);
+ } else {
+ __flush_purge_virtual_region(to,
+ (void *)(address & 0xfffff000),
+ PAGE_SIZE);
+ clear_page(to);
+ __flush_wback_region(to, PAGE_SIZE);
+ }
+}
+
+/*
+ * copy_user_page
+ * @to: P1 address
+ * @from: P1 address
+ * @address: U0 address to be mapped
+ */
+void copy_user_page(void *to, void *from, unsigned long address, struct page *pg)
+{
+ struct page *page = virt_to_page(to);
+
+
+ __set_bit(PG_mapped, &page->flags);
+ if (((address ^ (unsigned long)to) & CACHE_ALIAS) == 0) {
+ copy_page(to, from);
+ __flush_wback_region(to, PAGE_SIZE);
+ } else {
+ __flush_purge_virtual_region(to,
+ (void *)(address & 0xfffff000),
+ PAGE_SIZE);
+ copy_page(to, from);
+ __flush_wback_region(to, PAGE_SIZE);
+ }
+}
+
+/*
+ * For SH7705, we have our own implementation for ptep_get_and_clear
+ * Copied from pg-sh4.c
+ */
+inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
+{
+ pte_t pte = *ptep;
+
+ pte_clear(mm, addr, ptep);
+ if (!pte_not_present(pte)) {
+ unsigned long pfn = pte_pfn(pte);
+ if (pfn_valid(pfn)) {
+ struct page *page = pfn_to_page(pfn);
+ struct address_space *mapping = page_mapping(page);
+ if (!mapping || !mapping_writably_mapped(mapping))
+ __clear_bit(PG_mapped, &page->flags);
+ }
+ }
+
+ return pte;
+}
+
diff --git a/arch/sh/mm/tlb-nommu.c b/arch/sh/mm/tlb-nommu.c
new file mode 100644
index 000000000000..e55cfea01092
--- /dev/null
+++ b/arch/sh/mm/tlb-nommu.c
@@ -0,0 +1,58 @@
+/*
+ * arch/sh/mm/tlb-nommu.c
+ *
+ * TLB Operations for MMUless SH.
+ *
+ * Copyright (C) 2002 Paul Mundt
+ *
+ * Released under the terms of the GNU GPL v2.0.
+ */
+#include <linux/kernel.h>
+#include <linux/mm.h>
+
+/*
+ * Nothing too terribly exciting here ..
+ */
+
+void flush_tlb(void)
+{
+ BUG();
+}
+
+void flush_tlb_all(void)
+{
+ BUG();
+}
+
+void flush_tlb_mm(struct mm_struct *mm)
+{
+ BUG();
+}
+
+void flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
+ unsigned long end)
+{
+ BUG();
+}
+
+void flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
+{
+ BUG();
+}
+
+void __flush_tlb_page(unsigned long asid, unsigned long page)
+{
+ BUG();
+}
+
+void flush_tlb_kernel_range(unsigned long start, unsigned long end)
+{
+ BUG();
+}
+
+void update_mmu_cache(struct vm_area_struct * vma,
+ unsigned long address, pte_t pte)
+{
+ BUG();
+}
+
diff --git a/arch/sh/mm/tlb-sh3.c b/arch/sh/mm/tlb-sh3.c
new file mode 100644
index 000000000000..7a0d5c10bf20
--- /dev/null
+++ b/arch/sh/mm/tlb-sh3.c
@@ -0,0 +1,92 @@
+/*
+ * arch/sh/mm/tlb-sh3.c
+ *
+ * SH-3 specific TLB operations
+ *
+ * Copyright (C) 1999 Niibe Yutaka
+ * Copyright (C) 2002 Paul Mundt
+ *
+ * Released under the terms of the GNU GPL v2.0.
+ */
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/ptrace.h>
+#include <linux/mman.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/interrupt.h>
+
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/pgalloc.h>
+#include <asm/mmu_context.h>
+#include <asm/cacheflush.h>
+
+void update_mmu_cache(struct vm_area_struct * vma,
+ unsigned long address, pte_t pte)
+{
+ unsigned long flags;
+ unsigned long pteval;
+ unsigned long vpn;
+
+ /* Ptrace may call this routine. */
+ if (vma && current->active_mm != vma->vm_mm)
+ return;
+
+#if defined(CONFIG_SH7705_CACHE_32KB)
+ struct page *page;
+ page = pte_page(pte);
+ if (VALID_PAGE(page) && !test_bit(PG_mapped, &page->flags)) {
+ unsigned long phys = pte_val(pte) & PTE_PHYS_MASK;
+ __flush_wback_region((void *)P1SEGADDR(phys), PAGE_SIZE);
+ __set_bit(PG_mapped, &page->flags);
+ }
+#endif
+
+ local_irq_save(flags);
+
+ /* Set PTEH register */
+ vpn = (address & MMU_VPN_MASK) | get_asid();
+ ctrl_outl(vpn, MMU_PTEH);
+
+ pteval = pte_val(pte);
+
+ /* Set PTEL register */
+ pteval &= _PAGE_FLAGS_HARDWARE_MASK; /* drop software flags */
+ /* conveniently, we want all the software flags to be 0 anyway */
+ ctrl_outl(pteval, MMU_PTEL);
+
+ /* Load the TLB */
+ asm volatile("ldtlb": /* no output */ : /* no input */ : "memory");
+ local_irq_restore(flags);
+}
+
+void __flush_tlb_page(unsigned long asid, unsigned long page)
+{
+ unsigned long addr, data;
+ int i, ways = MMU_NTLB_WAYS;
+
+ /*
+ * NOTE: PTEH.ASID should be set to this MM
+ * _AND_ we need to write ASID to the array.
+ *
+ * It would be simple if we didn't need to set PTEH.ASID...
+ */
+ addr = MMU_TLB_ADDRESS_ARRAY | (page & 0x1F000);
+ data = (page & 0xfffe0000) | asid; /* VALID bit is off */
+
+ if ((cpu_data->flags & CPU_HAS_MMU_PAGE_ASSOC)) {
+ addr |= MMU_PAGE_ASSOC_BIT;
+ ways = 1; /* we already know the way .. */
+ }
+
+ for (i = 0; i < ways; i++)
+ ctrl_outl(data, addr + (i << 8));
+}
+
diff --git a/arch/sh/mm/tlb-sh4.c b/arch/sh/mm/tlb-sh4.c
new file mode 100644
index 000000000000..115b1b6be40b
--- /dev/null
+++ b/arch/sh/mm/tlb-sh4.c
@@ -0,0 +1,96 @@
+/*
+ * arch/sh/mm/tlb-sh4.c
+ *
+ * SH-4 specific TLB operations
+ *
+ * Copyright (C) 1999 Niibe Yutaka
+ * Copyright (C) 2002 Paul Mundt
+ *
+ * Released under the terms of the GNU GPL v2.0.
+ */
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/ptrace.h>
+#include <linux/mman.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/interrupt.h>
+
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/pgalloc.h>
+#include <asm/mmu_context.h>
+#include <asm/cacheflush.h>
+
+void update_mmu_cache(struct vm_area_struct * vma,
+ unsigned long address, pte_t pte)
+{
+ unsigned long flags;
+ unsigned long pteval;
+ unsigned long vpn;
+ struct page *page;
+ unsigned long pfn;
+ unsigned long ptea;
+
+ /* Ptrace may call this routine. */
+ if (vma && current->active_mm != vma->vm_mm)
+ return;
+
+ pfn = pte_pfn(pte);
+ if (pfn_valid(pfn)) {
+ page = pfn_to_page(pfn);
+ if (!test_bit(PG_mapped, &page->flags)) {
+ unsigned long phys = pte_val(pte) & PTE_PHYS_MASK;
+ __flush_wback_region((void *)P1SEGADDR(phys), PAGE_SIZE);
+ __set_bit(PG_mapped, &page->flags);
+ }
+ }
+
+ local_irq_save(flags);
+
+ /* Set PTEH register */
+ vpn = (address & MMU_VPN_MASK) | get_asid();
+ ctrl_outl(vpn, MMU_PTEH);
+
+ pteval = pte_val(pte);
+ /* Set PTEA register */
+ /* TODO: make this look less hacky */
+ ptea = ((pteval >> 28) & 0xe) | (pteval & 0x1);
+ ctrl_outl(ptea, MMU_PTEA);
+
+ /* Set PTEL register */
+ pteval &= _PAGE_FLAGS_HARDWARE_MASK; /* drop software flags */
+#ifdef CONFIG_SH_WRITETHROUGH
+ pteval |= _PAGE_WT;
+#endif
+ /* conveniently, we want all the software flags to be 0 anyway */
+ ctrl_outl(pteval, MMU_PTEL);
+
+ /* Load the TLB */
+ asm volatile("ldtlb": /* no output */ : /* no input */ : "memory");
+ local_irq_restore(flags);
+}
+
+void __flush_tlb_page(unsigned long asid, unsigned long page)
+{
+ unsigned long addr, data;
+
+ /*
+ * NOTE: PTEH.ASID should be set to this MM
+ * _AND_ we need to write ASID to the array.
+ *
+ * It would be simple if we didn't need to set PTEH.ASID...
+ */
+ addr = MMU_UTLB_ADDRESS_ARRAY | MMU_PAGE_ASSOC_BIT;
+ data = page | asid; /* VALID bit is off */
+ jump_to_P2();
+ ctrl_outl(data, addr);
+ back_to_P1();
+}
+
diff --git a/arch/sh/oprofile/Kconfig b/arch/sh/oprofile/Kconfig
new file mode 100644
index 000000000000..5ade19801b97
--- /dev/null
+++ b/arch/sh/oprofile/Kconfig
@@ -0,0 +1,23 @@
+
+menu "Profiling support"
+ depends on EXPERIMENTAL
+
+config PROFILING
+ bool "Profiling support (EXPERIMENTAL)"
+ help
+ Say Y here to enable the extended profiling support mechanisms used
+ by profilers such as OProfile.
+
+
+config OPROFILE
+ tristate "OProfile system profiling (EXPERIMENTAL)"
+ depends on PROFILING
+ help
+ OProfile is a profiling system capable of profiling the
+ whole system, include the kernel, kernel modules, libraries,
+ and applications.
+
+ If unsure, say N.
+
+endmenu
+
diff --git a/arch/sh/oprofile/Makefile b/arch/sh/oprofile/Makefile
new file mode 100644
index 000000000000..686738d4aa3c
--- /dev/null
+++ b/arch/sh/oprofile/Makefile
@@ -0,0 +1,13 @@
+obj-$(CONFIG_OPROFILE) += oprofile.o
+
+DRIVER_OBJS = $(addprefix ../../../drivers/oprofile/, \
+ oprof.o cpu_buffer.o buffer_sync.o \
+ event_buffer.o oprofile_files.o \
+ oprofilefs.o oprofile_stats.o \
+ timer_int.o )
+
+profdrvr-y := op_model_null.o
+profdrvr-$(CONFIG_CPU_SUBTYPE_SH7750) := op_model_sh7750.o
+
+oprofile-y := $(DRIVER_OBJS) $(profdrvr-y)
+
diff --git a/arch/sh/oprofile/op_model_null.c b/arch/sh/oprofile/op_model_null.c
new file mode 100644
index 000000000000..a845b088edb4
--- /dev/null
+++ b/arch/sh/oprofile/op_model_null.c
@@ -0,0 +1,23 @@
+/*
+ * arch/sh/oprofile/op_model_null.c
+ *
+ * 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/kernel.h>
+#include <linux/oprofile.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+
+int __init oprofile_arch_init(struct oprofile_operations *ops)
+{
+ return -ENODEV;
+}
+
+void oprofile_arch_exit(void)
+{
+}
+
diff --git a/arch/sh/oprofile/op_model_sh7750.c b/arch/sh/oprofile/op_model_sh7750.c
new file mode 100644
index 000000000000..5ec9ddcc4b0b
--- /dev/null
+++ b/arch/sh/oprofile/op_model_sh7750.c
@@ -0,0 +1,281 @@
+/*
+ * arch/sh/oprofile/op_model_sh7750.c
+ *
+ * OProfile support for SH7750/SH7750S Performance Counters
+ *
+ * Copyright (C) 2003, 2004 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/kernel.h>
+#include <linux/oprofile.h>
+#include <linux/profile.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/fs.h>
+#include <linux/notifier.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+
+#define PM_CR_BASE 0xff000084 /* 16-bit */
+#define PM_CTR_BASE 0xff100004 /* 32-bit */
+
+#define PMCR1 (PM_CR_BASE + 0x00)
+#define PMCR2 (PM_CR_BASE + 0x04)
+#define PMCTR1H (PM_CTR_BASE + 0x00)
+#define PMCTR1L (PM_CTR_BASE + 0x04)
+#define PMCTR2H (PM_CTR_BASE + 0x08)
+#define PMCTR2L (PM_CTR_BASE + 0x0c)
+
+#define PMCR_PMM_MASK 0x0000003f
+
+#define PMCR_CLKF 0x00000100
+#define PMCR_PMCLR 0x00002000
+#define PMCR_PMST 0x00004000
+#define PMCR_PMEN 0x00008000
+
+#define PMCR_ENABLE (PMCR_PMST | PMCR_PMEN)
+
+/*
+ * SH7750/SH7750S have 2 perf counters
+ */
+#define NR_CNTRS 2
+
+extern const char *get_cpu_subtype(void);
+
+struct op_counter_config {
+ unsigned long enabled;
+ unsigned long event;
+ unsigned long count;
+
+ /* Dummy values for userspace tool compliance */
+ unsigned long kernel;
+ unsigned long user;
+ unsigned long unit_mask;
+};
+
+static struct op_counter_config ctr[NR_CNTRS];
+
+/*
+ * There are a number of events supported by each counter (33 in total).
+ * Since we have 2 counters, each counter will take the event code as it
+ * corresponds to the PMCR PMM setting. Each counter can be configured
+ * independently.
+ *
+ * Event Code Description
+ * ---------- -----------
+ *
+ * 0x01 Operand read access
+ * 0x02 Operand write access
+ * 0x03 UTLB miss
+ * 0x04 Operand cache read miss
+ * 0x05 Operand cache write miss
+ * 0x06 Instruction fetch (w/ cache)
+ * 0x07 Instruction TLB miss
+ * 0x08 Instruction cache miss
+ * 0x09 All operand accesses
+ * 0x0a All instruction accesses
+ * 0x0b OC RAM operand access
+ * 0x0d On-chip I/O space access
+ * 0x0e Operand access (r/w)
+ * 0x0f Operand cache miss (r/w)
+ * 0x10 Branch instruction
+ * 0x11 Branch taken
+ * 0x12 BSR/BSRF/JSR
+ * 0x13 Instruction execution
+ * 0x14 Instruction execution in parallel
+ * 0x15 FPU Instruction execution
+ * 0x16 Interrupt
+ * 0x17 NMI
+ * 0x18 trapa instruction execution
+ * 0x19 UBCA match
+ * 0x1a UBCB match
+ * 0x21 Instruction cache fill
+ * 0x22 Operand cache fill
+ * 0x23 Elapsed time
+ * 0x24 Pipeline freeze by I-cache miss
+ * 0x25 Pipeline freeze by D-cache miss
+ * 0x27 Pipeline freeze by branch instruction
+ * 0x28 Pipeline freeze by CPU register
+ * 0x29 Pipeline freeze by FPU
+ *
+ * Unfortunately we don't have a native exception or interrupt for counter
+ * overflow (although since these counters can run for 16.3 days without
+ * overflowing, it's not really necessary).
+ *
+ * OProfile on the other hand likes to have samples taken periodically, so
+ * for now we just piggyback the timer interrupt to get the expected
+ * behavior.
+ */
+
+static int sh7750_timer_notify(struct notifier_block *self,
+ unsigned long val, void *regs)
+{
+ oprofile_add_sample((struct pt_regs *)regs, 0);
+ return 0;
+}
+
+static struct notifier_block sh7750_timer_notifier = {
+ .notifier_call = sh7750_timer_notify,
+};
+
+static u64 sh7750_read_counter(int counter)
+{
+ u32 hi, lo;
+
+ hi = (counter == 0) ? ctrl_inl(PMCTR1H) : ctrl_inl(PMCTR2H);
+ lo = (counter == 0) ? ctrl_inl(PMCTR1L) : ctrl_inl(PMCTR2L);
+
+ return (u64)((u64)(hi & 0xffff) << 32) | lo;
+}
+
+/*
+ * Files will be in a path like:
+ *
+ * /<oprofilefs mount point>/<counter number>/<file>
+ *
+ * So when dealing with <file>, we look to the parent dentry for the counter
+ * number.
+ */
+static inline int to_counter(struct file *file)
+{
+ const unsigned char *name = file->f_dentry->d_parent->d_name.name;
+
+ return (int)simple_strtol(name, NULL, 10);
+}
+
+/*
+ * XXX: We have 48-bit counters, so we're probably going to want something
+ * more along the lines of oprofilefs_ullong_to_user().. Truncating to
+ * unsigned long works fine for now though, as long as we don't attempt to
+ * profile for too horribly long.
+ */
+static ssize_t sh7750_read_count(struct file *file, char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ int counter = to_counter(file);
+ u64 val = sh7750_read_counter(counter);
+
+ return oprofilefs_ulong_to_user((unsigned long)val, buf, count, ppos);
+}
+
+static ssize_t sh7750_write_count(struct file *file, const char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ int counter = to_counter(file);
+ unsigned long val;
+
+ if (oprofilefs_ulong_from_user(&val, buf, count))
+ return -EFAULT;
+
+ /*
+ * Any write will clear the counter, although only 0 should be
+ * written for this purpose, as we do not support setting the
+ * counter to an arbitrary value.
+ */
+ WARN_ON(val != 0);
+
+ if (counter == 0) {
+ ctrl_outw(ctrl_inw(PMCR1) | PMCR_PMCLR, PMCR1);
+ } else {
+ ctrl_outw(ctrl_inw(PMCR2) | PMCR_PMCLR, PMCR2);
+ }
+
+ return count;
+}
+
+static struct file_operations count_fops = {
+ .read = sh7750_read_count,
+ .write = sh7750_write_count,
+};
+
+static int sh7750_perf_counter_create_files(struct super_block *sb, struct dentry *root)
+{
+ int i;
+
+ for (i = 0; i < NR_CNTRS; i++) {
+ struct dentry *dir;
+ char buf[3];
+
+ snprintf(buf, sizeof(buf), "%d", i);
+ dir = oprofilefs_mkdir(sb, root, buf);
+
+ oprofilefs_create_ulong(sb, dir, "enabled", &ctr[i].enabled);
+ oprofilefs_create_ulong(sb, dir, "event", &ctr[i].event);
+ oprofilefs_create_file(sb, dir, "count", &count_fops);
+
+ /* Dummy entries */
+ oprofilefs_create_ulong(sb, dir, "kernel", &ctr[i].kernel);
+ oprofilefs_create_ulong(sb, dir, "user", &ctr[i].user);
+ oprofilefs_create_ulong(sb, dir, "unit_mask", &ctr[i].unit_mask);
+ }
+
+ return 0;
+}
+
+static int sh7750_perf_counter_start(void)
+{
+ u16 pmcr;
+
+ /* Enable counter 1 */
+ if (ctr[0].enabled) {
+ pmcr = ctrl_inw(PMCR1);
+ WARN_ON(pmcr & PMCR_PMEN);
+
+ pmcr &= ~PMCR_PMM_MASK;
+ pmcr |= ctr[0].event;
+ ctrl_outw(pmcr | PMCR_ENABLE, PMCR1);
+ }
+
+ /* Enable counter 2 */
+ if (ctr[1].enabled) {
+ pmcr = ctrl_inw(PMCR2);
+ WARN_ON(pmcr & PMCR_PMEN);
+
+ pmcr &= ~PMCR_PMM_MASK;
+ pmcr |= ctr[1].event;
+ ctrl_outw(pmcr | PMCR_ENABLE, PMCR2);
+ }
+
+ return register_profile_notifier(&sh7750_timer_notifier);
+}
+
+static void sh7750_perf_counter_stop(void)
+{
+ ctrl_outw(ctrl_inw(PMCR1) & ~PMCR_PMEN, PMCR1);
+ ctrl_outw(ctrl_inw(PMCR2) & ~PMCR_PMEN, PMCR2);
+
+ unregister_profile_notifier(&sh7750_timer_notifier);
+}
+
+static struct oprofile_operations sh7750_perf_counter_ops = {
+ .create_files = sh7750_perf_counter_create_files,
+ .start = sh7750_perf_counter_start,
+ .stop = sh7750_perf_counter_stop,
+};
+
+int __init oprofile_arch_init(struct oprofile_operations **ops)
+{
+ if (!(cpu_data->flags & CPU_HAS_PERF_COUNTER))
+ return -ENODEV;
+
+ sh7750_perf_counter_ops.cpu_type = (char *)get_cpu_subtype();
+ *ops = &sh7750_perf_counter_ops;
+
+ printk(KERN_INFO "oprofile: using SH-4 (%s) performance monitoring.\n",
+ sh7750_perf_counter_ops.cpu_type);
+
+ /* Clear the counters */
+ ctrl_outw(ctrl_inw(PMCR1) | PMCR_PMCLR, PMCR1);
+ ctrl_outw(ctrl_inw(PMCR2) | PMCR_PMCLR, PMCR2);
+
+ return 0;
+}
+
+void oprofile_arch_exit(void)
+{
+}
+
diff --git a/arch/sh/ramdisk/Makefile b/arch/sh/ramdisk/Makefile
new file mode 100644
index 000000000000..99e1c68673cf
--- /dev/null
+++ b/arch/sh/ramdisk/Makefile
@@ -0,0 +1,20 @@
+#
+# Makefile for a ramdisk image
+#
+
+obj-y += ramdisk.o
+
+
+O_FORMAT = $(shell $(OBJDUMP) -i | head -n 2 | grep elf32)
+img := $(subst ",,$(CONFIG_EMBEDDED_RAMDISK_IMAGE))
+# add $(src) when $(img) is relative
+img := $(subst $(src)//,/,$(src)/$(img))
+
+quiet_cmd_ramdisk = LD $@
+define cmd_ramdisk
+ $(LD) -T $(srctree)/$(src)/ld.script -b binary --oformat $(O_FORMAT) \
+ -o $@ $(img)
+endef
+
+$(obj)/ramdisk.o: $(img) $(srctree)/$(src)/ld.script
+ $(call cmd,ramdisk)
diff --git a/arch/sh/ramdisk/ld.script b/arch/sh/ramdisk/ld.script
new file mode 100644
index 000000000000..94beee248c04
--- /dev/null
+++ b/arch/sh/ramdisk/ld.script
@@ -0,0 +1,9 @@
+OUTPUT_ARCH(sh)
+SECTIONS
+{
+ .initrd :
+ {
+ *(.data)
+ }
+}
+
diff --git a/arch/sh/tools/Makefile b/arch/sh/tools/Makefile
new file mode 100644
index 000000000000..3c370a113291
--- /dev/null
+++ b/arch/sh/tools/Makefile
@@ -0,0 +1,15 @@
+#
+# arch/sh/tools/Makefile
+#
+# 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.
+#
+# Shamelessly cloned from ARM.
+#
+
+include/asm-sh/machtypes.h: $(src)/gen-mach-types $(src)/mach-types
+ @echo ' Generating $@'
+ $(Q)$(AWK) -f $^ > $@ || { rm -f $@; /bin/false; }
diff --git a/arch/sh/tools/gen-mach-types b/arch/sh/tools/gen-mach-types
new file mode 100644
index 000000000000..bb2b82234e83
--- /dev/null
+++ b/arch/sh/tools/gen-mach-types
@@ -0,0 +1,49 @@
+#!/bin/awk
+#
+# Awk script to generate include/asm-sh/machtypes.h
+# Heavily based on arch/arm/tools/gen-mach-types
+#
+BEGIN { nr = 0 }
+/^#/ { next }
+/^[ ]*$/ { next }
+
+NF == 2 {
+ mach[nr] = $1;
+ config[nr] = "CONFIG_"$2;
+ nr++;
+ }
+
+END {
+ printf("/*\n");
+ printf(" * Automagically generated, don't touch.\n");
+ printf(" */\n");
+ printf("#ifndef __ASM_SH_MACHTYPES_H\n");
+ printf("#define __ASM_SH_MACHTYPES_H\n");
+ printf("\n");
+ printf("#include <linux/config.h>\n");
+ printf("\n");
+ printf("/*\n");
+ printf(" * We'll use the following MACH_xxx defs for placeholders for the time\n");
+ printf(" * being .. these will all go away once sh_machtype is assigned per-board.\n");
+ printf(" *\n");
+ printf(" * For now we leave things the way they are for backwards compatibility.\n");
+ printf(" */\n");
+ printf("\n");
+ printf("/* Mach types */\n");
+
+ for (i = 0; i < nr; i++) {
+ printf("#ifdef %s\n", config[i]);
+ printf(" #define MACH_%s\t\t1\n", mach[i]);
+ printf("#else\n");
+ printf(" #define MACH_%s\t\t0\n", mach[i]);
+ printf("#endif\n");
+ }
+
+ printf("\n");
+ printf("/* Machtype checks */\n");
+ for (i = 0; i < nr; i++)
+ printf("#define mach_is_%s()\t\t\t(MACH_%s)\n",
+ tolower(mach[i]), mach[i]);
+ printf("\n");
+ printf("#endif /* __ASM_SH_MACHTYPES_H */\n");
+ }
diff --git a/arch/sh/tools/mach-types b/arch/sh/tools/mach-types
new file mode 100644
index 000000000000..0693fbd1f956
--- /dev/null
+++ b/arch/sh/tools/mach-types
@@ -0,0 +1,31 @@
+#
+# List of boards.
+#
+
+#
+# MACH_<xxx> CONFIG_<xxx>
+#
+SE SH_SOLUTION_ENGINE
+7751SE SH_7751_SOLUTION_ENGINE
+7300SE SH_7300_SOLUTION_ENGINE
+73180SE SH_73180_SOLUTION_ENGINE
+7751SYSTEMH SH_7751_SYSTEMH
+HP600 SH_HP600
+HP620 SH_HP620
+HP680 SH_HP680
+HP690 SH_HP690
+HD64461 HD64461
+HD64465 HD64465
+SH2000 SH_SH2000
+SATURN SH_SATURN
+DREAMCAST SH_DREAMCAST
+BIGSUR SH_BIGSUR
+ADX SH_ADX
+MPC1211 SH_MPC1211
+SNAPGEAR SH_SECUREEDGE5410
+HS7751RVOIP SH_HS7751RVOIP
+RTS7751R2D SH_RTS7751R2D
+EDOSK7705 SH_EDOSK7705
+SH4202_MICRODEV SH_SH4202_MICRODEV
+SH03 SH_SH03
+