Linux-2.6.12-rc2
Initial git repository build. I'm not bothering with the full history, even though we have it. We can create a separate "historical" git archive of that later if we want to, and in the meantime it's about 3.2GB when imported into git - space that would just make the early git days unnecessarily complicated, when we don't have a lot of good infrastructure for it. Let it rip!
This commit is contained in:
793
arch/sh/Kconfig
Normal file
793
arch/sh/Kconfig
Normal file
@@ -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"
|
124
arch/sh/Kconfig.debug
Normal file
124
arch/sh/Kconfig.debug
Normal file
@@ -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
|
183
arch/sh/Makefile
Normal file
183
arch/sh/Makefile
Normal file
@@ -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
|
||||
|
6
arch/sh/boards/adx/Makefile
Normal file
6
arch/sh/boards/adx/Makefile
Normal file
@@ -0,0 +1,6 @@
|
||||
#
|
||||
# Makefile for ADX boards
|
||||
#
|
||||
|
||||
obj-y := setup.o irq.o irq_maskreq.o
|
||||
|
31
arch/sh/boards/adx/irq.c
Normal file
31
arch/sh/boards/adx/irq.c
Normal file
@@ -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);
|
||||
}
|
||||
}
|
107
arch/sh/boards/adx/irq_maskreg.c
Normal file
107
arch/sh/boards/adx/irq_maskreg.c
Normal file
@@ -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);
|
||||
}
|
56
arch/sh/boards/adx/setup.c
Normal file
56
arch/sh/boards/adx/setup.c
Normal file
@@ -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;
|
||||
}
|
||||
|
6
arch/sh/boards/bigsur/Makefile
Normal file
6
arch/sh/boards/bigsur/Makefile
Normal file
@@ -0,0 +1,6 @@
|
||||
#
|
||||
# Makefile for the BigSur specific parts of the kernel
|
||||
#
|
||||
|
||||
obj-y := setup.o io.o irq.o led.o
|
||||
|
125
arch/sh/boards/bigsur/io.c
Normal file
125
arch/sh/boards/bigsur/io.c
Normal file
@@ -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;
|
||||
}
|
||||
|
348
arch/sh/boards/bigsur/irq.c
Normal file
348
arch/sh/boards/bigsur/irq.c
Normal file
@@ -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);
|
||||
|
||||
}
|
55
arch/sh/boards/bigsur/led.c
Normal file
55
arch/sh/boards/bigsur/led.c
Normal file
@@ -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 */
|
||||
|
96
arch/sh/boards/bigsur/setup.c
Normal file
96
arch/sh/boards/bigsur/setup.c
Normal file
@@ -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;
|
||||
}
|
||||
|
6
arch/sh/boards/cat68701/Makefile
Normal file
6
arch/sh/boards/cat68701/Makefile
Normal file
@@ -0,0 +1,6 @@
|
||||
#
|
||||
# Makefile for the CAT-68701 specific parts of the kernel
|
||||
#
|
||||
|
||||
obj-y := setup.o irq.o
|
||||
|
28
arch/sh/boards/cat68701/irq.c
Normal file
28
arch/sh/boards/cat68701/irq.c
Normal file
@@ -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);
|
||||
}
|
86
arch/sh/boards/cat68701/setup.c
Normal file
86
arch/sh/boards/cat68701/setup.c
Normal file
@@ -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) */
|
||||
}
|
||||
|
6
arch/sh/boards/cqreek/Makefile
Normal file
6
arch/sh/boards/cqreek/Makefile
Normal file
@@ -0,0 +1,6 @@
|
||||
#
|
||||
# Makefile for the CqREEK specific parts of the kernel
|
||||
#
|
||||
|
||||
obj-y := setup.o irq.o
|
||||
|
128
arch/sh/boards/cqreek/irq.c
Normal file
128
arch/sh/boards/cqreek/irq.c
Normal file
@@ -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);
|
||||
}
|
||||
}
|
||||
|
101
arch/sh/boards/cqreek/setup.c
Normal file
101
arch/sh/boards/cqreek/setup.c
Normal file
@@ -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);
|
||||
}
|
||||
|
7
arch/sh/boards/dmida/Makefile
Normal file
7
arch/sh/boards/dmida/Makefile
Normal file
@@ -0,0 +1,7 @@
|
||||
#
|
||||
# Makefile for the DataMyte Industrial Digital Assistant(tm) specific parts
|
||||
# of the kernel
|
||||
#
|
||||
|
||||
obj-y := mach.o
|
||||
|
59
arch/sh/boards/dmida/mach.c
Normal file
59
arch/sh/boards/dmida/mach.c
Normal file
@@ -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)
|
||||
|
6
arch/sh/boards/dreamcast/Makefile
Normal file
6
arch/sh/boards/dreamcast/Makefile
Normal file
@@ -0,0 +1,6 @@
|
||||
#
|
||||
# Makefile for the Sega Dreamcast specific parts of the kernel
|
||||
#
|
||||
|
||||
obj-y := setup.o irq.o rtc.o
|
||||
|
160
arch/sh/boards/dreamcast/irq.c
Normal file
160
arch/sh/boards/dreamcast/irq.c
Normal file
@@ -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;
|
||||
}
|
81
arch/sh/boards/dreamcast/rtc.c
Normal file
81
arch/sh/boards/dreamcast/rtc.c
Normal file
@@ -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;
|
||||
}
|
||||
|
83
arch/sh/boards/dreamcast/setup.c
Normal file
83
arch/sh/boards/dreamcast/setup.c
Normal file
@@ -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;
|
||||
}
|
6
arch/sh/boards/ec3104/Makefile
Normal file
6
arch/sh/boards/ec3104/Makefile
Normal file
@@ -0,0 +1,6 @@
|
||||
#
|
||||
# Makefile for the EC3104 specific parts of the kernel
|
||||
#
|
||||
|
||||
obj-y := setup.o io.o irq.o
|
||||
|
81
arch/sh/boards/ec3104/io.c
Normal file
81
arch/sh/boards/ec3104/io.c
Normal file
@@ -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();
|
||||
}
|
196
arch/sh/boards/ec3104/irq.c
Normal file
196
arch/sh/boards/ec3104/irq.c
Normal file
@@ -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;
|
||||
}
|
78
arch/sh/boards/ec3104/setup.c
Normal file
78
arch/sh/boards/ec3104/setup.c
Normal file
@@ -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;
|
||||
}
|
||||
|
8
arch/sh/boards/harp/Makefile
Normal file
8
arch/sh/boards/harp/Makefile
Normal file
@@ -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
|
||||
|
148
arch/sh/boards/harp/irq.c
Normal file
148
arch/sh/boards/harp/irq.c
Normal file
@@ -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);
|
||||
}
|
||||
}
|
52
arch/sh/boards/harp/led.c
Normal file
52
arch/sh/boards/harp/led.c
Normal file
@@ -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
|
62
arch/sh/boards/harp/mach.c
Normal file
62
arch/sh/boards/harp/mach.c
Normal file
@@ -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)
|
42
arch/sh/boards/harp/pcidma.c
Normal file
42
arch/sh/boards/harp/pcidma.c
Normal file
@@ -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));
|
||||
}
|
91
arch/sh/boards/harp/setup.c
Normal file
91
arch/sh/boards/harp/setup.c
Normal file
@@ -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;
|
||||
}
|
||||
}
|
||||
|
6
arch/sh/boards/hp6xx/hp620/Makefile
Normal file
6
arch/sh/boards/hp6xx/hp620/Makefile
Normal file
@@ -0,0 +1,6 @@
|
||||
#
|
||||
# Makefile for the HP620 specific parts of the kernel
|
||||
#
|
||||
|
||||
obj-y := mach.o setup.o
|
||||
|
52
arch/sh/boards/hp6xx/hp620/mach.c
Normal file
52
arch/sh/boards/hp6xx/hp620/mach.c
Normal file
@@ -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)
|
45
arch/sh/boards/hp6xx/hp620/setup.c
Normal file
45
arch/sh/boards/hp6xx/hp620/setup.c
Normal file
@@ -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;
|
||||
}
|
||||
|
6
arch/sh/boards/hp6xx/hp680/Makefile
Normal file
6
arch/sh/boards/hp6xx/hp680/Makefile
Normal file
@@ -0,0 +1,6 @@
|
||||
#
|
||||
# Makefile for the HP680 specific parts of the kernel
|
||||
#
|
||||
|
||||
obj-y := mach.o setup.o
|
||||
|
53
arch/sh/boards/hp6xx/hp680/mach.c
Normal file
53
arch/sh/boards/hp6xx/hp680/mach.c
Normal file
@@ -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)
|
41
arch/sh/boards/hp6xx/hp680/setup.c
Normal file
41
arch/sh/boards/hp6xx/hp680/setup.c
Normal file
@@ -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;
|
||||
}
|
6
arch/sh/boards/hp6xx/hp690/Makefile
Normal file
6
arch/sh/boards/hp6xx/hp690/Makefile
Normal file
@@ -0,0 +1,6 @@
|
||||
#
|
||||
# Makefile for the HP690 specific parts of the kernel
|
||||
#
|
||||
|
||||
obj-y := mach.o
|
||||
|
48
arch/sh/boards/hp6xx/hp690/mach.c
Normal file
48
arch/sh/boards/hp6xx/hp690/mach.c
Normal file
@@ -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)
|
8
arch/sh/boards/mpc1211/Makefile
Normal file
8
arch/sh/boards/mpc1211/Makefile
Normal file
@@ -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
|
||||
|
64
arch/sh/boards/mpc1211/led.c
Normal file
64
arch/sh/boards/mpc1211/led.c
Normal file
@@ -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 */
|
296
arch/sh/boards/mpc1211/pci.c
Normal file
296
arch/sh/boards/mpc1211/pci.c
Normal file
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
152
arch/sh/boards/mpc1211/rtc.c
Normal file
152
arch/sh/boards/mpc1211/rtc.c
Normal file
@@ -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;
|
||||
}
|
||||
|
360
arch/sh/boards/mpc1211/setup.c
Normal file
360
arch/sh/boards/mpc1211/setup.c
Normal file
@@ -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;
|
||||
}
|
||||
|
8
arch/sh/boards/overdrive/Makefile
Normal file
8
arch/sh/boards/overdrive/Makefile
Normal file
@@ -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
|
||||
|
134
arch/sh/boards/overdrive/fpga.c
Normal file
134
arch/sh/boards/overdrive/fpga.c
Normal file
@@ -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;
|
||||
}
|
588
arch/sh/boards/overdrive/galileo.c
Normal file
588
arch/sh/boards/overdrive/galileo.c
Normal file
@@ -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 & 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);
|
||||
}
|
173
arch/sh/boards/overdrive/io.c
Normal file
173
arch/sh/boards/overdrive/io.c
Normal file
@@ -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;
|
||||
|
||||
}
|
||||
}
|
192
arch/sh/boards/overdrive/irq.c
Normal file
192
arch/sh/boards/overdrive/irq.c
Normal file
@@ -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);
|
||||
}
|
59
arch/sh/boards/overdrive/led.c
Normal file
59
arch/sh/boards/overdrive/led.c
Normal file
@@ -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 */
|
62
arch/sh/boards/overdrive/mach.c
Normal file
62
arch/sh/boards/overdrive/mach.c
Normal file
@@ -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)
|
46
arch/sh/boards/overdrive/pcidma.c
Normal file
46
arch/sh/boards/overdrive/pcidma.c
Normal file
@@ -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));
|
||||
}
|
41
arch/sh/boards/overdrive/setup.c
Normal file
41
arch/sh/boards/overdrive/setup.c
Normal file
@@ -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);
|
||||
}
|
119
arch/sh/boards/overdrive/time.c
Normal file
119
arch/sh/boards/overdrive/time.c
Normal file
@@ -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;
|
||||
}
|
||||
|
10
arch/sh/boards/renesas/edosk7705/Makefile
Normal file
10
arch/sh/boards/renesas/edosk7705/Makefile
Normal file
@@ -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
|
||||
|
94
arch/sh/boards/renesas/edosk7705/io.c
Normal file
94
arch/sh/boards/renesas/edosk7705/io.c
Normal file
@@ -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);
|
||||
}
|
||||
|
60
arch/sh/boards/renesas/edosk7705/setup.c
Normal file
60
arch/sh/boards/renesas/edosk7705/setup.c
Normal file
@@ -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 .. */
|
||||
}
|
||||
|
12
arch/sh/boards/renesas/hs7751rvoip/Makefile
Normal file
12
arch/sh/boards/renesas/hs7751rvoip/Makefile
Normal file
@@ -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
|
||||
|
310
arch/sh/boards/renesas/hs7751rvoip/io.c
Normal file
310
arch/sh/boards/renesas/hs7751rvoip/io.c
Normal file
@@ -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);
|
||||
}
|
122
arch/sh/boards/renesas/hs7751rvoip/irq.c
Normal file
122
arch/sh/boards/renesas/hs7751rvoip/irq.c
Normal file
@@ -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);
|
||||
}
|
27
arch/sh/boards/renesas/hs7751rvoip/led.c
Normal file
27
arch/sh/boards/renesas/hs7751rvoip/led.c
Normal file
@@ -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;
|
||||
}
|
55
arch/sh/boards/renesas/hs7751rvoip/mach.c
Normal file
55
arch/sh/boards/renesas/hs7751rvoip/mach.c
Normal file
@@ -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)
|
150
arch/sh/boards/renesas/hs7751rvoip/pci.c
Normal file
150
arch/sh/boards/renesas/hs7751rvoip/pci.c
Normal file
@@ -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);
|
89
arch/sh/boards/renesas/hs7751rvoip/setup.c
Normal file
89
arch/sh/boards/renesas/hs7751rvoip/setup.c
Normal file
@@ -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);
|
10
arch/sh/boards/renesas/rts7751r2d/Makefile
Normal file
10
arch/sh/boards/renesas/rts7751r2d/Makefile
Normal file
@@ -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
|
||||
|
319
arch/sh/boards/renesas/rts7751r2d/io.c
Normal file
319
arch/sh/boards/renesas/rts7751r2d/io.c
Normal file
@@ -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);
|
||||
}
|
135
arch/sh/boards/renesas/rts7751r2d/irq.c
Normal file
135
arch/sh/boards/renesas/rts7751r2d/irq.c
Normal file
@@ -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();
|
||||
}
|
67
arch/sh/boards/renesas/rts7751r2d/led.c
Normal file
67
arch/sh/boards/renesas/rts7751r2d/led.c
Normal file
@@ -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;
|
||||
}
|
70
arch/sh/boards/renesas/rts7751r2d/mach.c
Normal file
70
arch/sh/boards/renesas/rts7751r2d/mach.c
Normal file
@@ -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)
|
31
arch/sh/boards/renesas/rts7751r2d/setup.c
Normal file
31
arch/sh/boards/renesas/rts7751r2d/setup.c
Normal file
@@ -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;
|
||||
}
|
13
arch/sh/boards/renesas/systemh/Makefile
Normal file
13
arch/sh/boards/renesas/systemh/Makefile
Normal file
@@ -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
|
||||
|
283
arch/sh/boards/renesas/systemh/io.c
Normal file
283
arch/sh/boards/renesas/systemh/io.c
Normal file
@@ -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;
|
||||
}
|
111
arch/sh/boards/renesas/systemh/irq.c
Normal file
111
arch/sh/boards/renesas/systemh/irq.c
Normal file
@@ -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);
|
||||
}
|
||||
|
80
arch/sh/boards/renesas/systemh/setup.c
Normal file
80
arch/sh/boards/renesas/systemh/setup.c
Normal file
@@ -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;
|
||||
}
|
||||
|
8
arch/sh/boards/saturn/Makefile
Normal file
8
arch/sh/boards/saturn/Makefile
Normal file
@@ -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
|
||||
|
26
arch/sh/boards/saturn/io.c
Normal file
26
arch/sh/boards/saturn/io.c
Normal file
@@ -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)
|
||||
{
|
||||
}
|
||||
|
118
arch/sh/boards/saturn/irq.c
Normal file
118
arch/sh/boards/saturn/irq.c
Normal file
@@ -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;
|
||||
}
|
||||
|
43
arch/sh/boards/saturn/setup.c
Normal file
43
arch/sh/boards/saturn/setup.c
Normal file
@@ -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;
|
||||
}
|
||||
|
68
arch/sh/boards/saturn/smp.c
Normal file
68
arch/sh/boards/saturn/smp.c
Normal file
@@ -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);
|
||||
}
|
||||
|
7
arch/sh/boards/se/7300/Makefile
Normal file
7
arch/sh/boards/se/7300/Makefile
Normal file
@@ -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
|
265
arch/sh/boards/se/7300/io.c
Normal file
265
arch/sh/boards/se/7300/io.c
Normal file
@@ -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);
|
||||
}
|
37
arch/sh/boards/se/7300/irq.c
Normal file
37
arch/sh/boards/se/7300/irq.c
Normal file
@@ -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 */
|
||||
}
|
69
arch/sh/boards/se/7300/led.c
Normal file
69
arch/sh/boards/se/7300/led.c
Normal file
@@ -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);
|
||||
|
||||
}
|
||||
|
66
arch/sh/boards/se/7300/setup.c
Normal file
66
arch/sh/boards/se/7300/setup.c
Normal file
@@ -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)
|
||||
{
|
||||
|
||||
}
|
7
arch/sh/boards/se/73180/Makefile
Normal file
7
arch/sh/boards/se/73180/Makefile
Normal file
@@ -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
|
265
arch/sh/boards/se/73180/io.c
Normal file
265
arch/sh/boards/se/73180/io.c
Normal file
@@ -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);
|
||||
}
|
137
arch/sh/boards/se/73180/irq.c
Normal file
137
arch/sh/boards/se/73180/irq.c
Normal file
@@ -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 */
|
||||
}
|
67
arch/sh/boards/se/73180/led.c
Normal file
67
arch/sh/boards/se/73180/led.c
Normal file
@@ -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);
|
||||
|
||||
}
|
68
arch/sh/boards/se/73180/setup.c
Normal file
68
arch/sh/boards/se/73180/setup.c
Normal file
@@ -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)
|
||||
{
|
||||
|
||||
}
|
6
arch/sh/boards/se/770x/Makefile
Normal file
6
arch/sh/boards/se/770x/Makefile
Normal file
@@ -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
|
||||
|
226
arch/sh/boards/se/770x/io.c
Normal file
226
arch/sh/boards/se/770x/io.c
Normal file
@@ -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;
|
||||
}
|
80
arch/sh/boards/se/770x/irq.c
Normal file
80
arch/sh/boards/se/770x/irq.c
Normal file
@@ -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
|
||||
}
|
68
arch/sh/boards/se/770x/led.c
Normal file
68
arch/sh/boards/se/770x/led.c
Normal file
@@ -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 */
|
68
arch/sh/boards/se/770x/mach.c
Normal file
68
arch/sh/boards/se/770x/mach.c
Normal file
@@ -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)
|
85
arch/sh/boards/se/770x/setup.c
Normal file
85
arch/sh/boards/se/770x/setup.c
Normal file
@@ -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 */
|
||||
}
|
8
arch/sh/boards/se/7751/Makefile
Normal file
8
arch/sh/boards/se/7751/Makefile
Normal file
@@ -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
|
||||
|
244
arch/sh/boards/se/7751/io.c
Normal file
244
arch/sh/boards/se/7751/io.c
Normal file
@@ -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;
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user