Commit 01a17cfd authored by Anton Altaparmakov's avatar Anton Altaparmakov

Merge cantab.net:/home/src/bklinux-2.6

into cantab.net:/home/src/ntfs-2.6
parents 800687bd 14729dbe
Simtec Electronics EB2410ITX (BAST)
===================================
http://www.simtec.co.uk/products/EB2410ITX/
Introduction
------------
The EB2410ITX is a S3C2410 based development board with a variety of
peripherals and expansion connectors. This board is also known by
the shortened name of Bast.
Configuration
-------------
To set the default configuration, use `make bast_defconfig` which
supports the commonly used features of this board
Support
-------
Official support information can be found on the Simtec Electronics
website, at the product page http://www.simtec.co.uk/products/EB2410ITX/
and http://www.simtec.co.uk/products/EB2410ITX/resources.html
(c) 2004 Ben Dooks, Simtec Electronics
S3C24XX ARM Linux Overview
==========================
Introduction
------------
The Samsung S3C24XX range of ARM9 System-on-Chip CPUs are supported
by the 's3c2410' architecture of ARM Linux. Currently the S3C2410 is
the only supported CPU in this range.
Configuration
-------------
A generic S3C2410 configuration is provided, and can be used as the
default by `make s3c2410_defconfig`. This configuration has support
for all the machines, and the commonly used features on them.
Machines
--------
The currently supported machines are as follows:
Simtec Electronics EB2410ITX (BAST)
A general purpose development board, see EB2410ITX.txt for further
details
Samsung SMDK2410
Samsung's own development board, geared for PDA work.
Thorcom VR1000
Custom embedded board
HP IPAQ 1940
Handheld (IPAQ), available in several varieties
Contributors
------------
Ben Dooks
Vincent Sanders
Herbert Potzl
Arnaud Patard
...@@ -120,12 +120,18 @@ The following sysctls are available for the XFS filesystem: ...@@ -120,12 +120,18 @@ The following sysctls are available for the XFS filesystem:
fs.xfs.stats_clear (Min: 0 Default: 0 Max: 1) fs.xfs.stats_clear (Min: 0 Default: 0 Max: 1)
Setting this to "1" clears accumulated XFS statistics Setting this to "1" clears accumulated XFS statistics
in /proc/fs/xfs/stat. It then immediately reset to "0". in /proc/fs/xfs/stat. It then immediately resets to "0".
fs.xfs.sync_interval (Min: HZ Default: 30*HZ Max: 60*HZ) fs.xfs.xfssyncd_centisecs (Min: 100 Default: 3000 Max: 720000)
The interval at which the xfssyncd thread for xfs filesystems The interval at which the xfssyncd thread flushes metadata
flushes metadata out to disk. This thread will flush log out to disk. This thread will flush log activity out, and
activity out, and do some processing on unlinked inodes do some processing on unlinked inodes.
fs.xfs.xfsbufd_centisecs (Min: 50 Default: 100 Max: 3000)
The interval at which xfsbufd scans the dirty metadata buffers list.
fs.xfs.age_buffer_centisecs (Min: 100 Default: 1500 Max: 720000)
The age at which xfsbufd flushes dirty metadata buffers to disk.
fs.xfs.error_level (Min: 0 Default: 3 Max: 11) fs.xfs.error_level (Min: 0 Default: 3 Max: 11)
A volume knob for error reporting when internal errors occur. A volume knob for error reporting when internal errors occur.
...@@ -180,14 +186,3 @@ The following sysctls are available for the XFS filesystem: ...@@ -180,14 +186,3 @@ The following sysctls are available for the XFS filesystem:
Setting this to "1" will cause the "noatime" flag set Setting this to "1" will cause the "noatime" flag set
by the chattr(1) command on a directory to be by the chattr(1) command on a directory to be
inherited by files in that directory. inherited by files in that directory.
vm.pagebuf.stats_clear (Min: 0 Default: 0 Max: 1)
Setting this to "1" clears accumulated pagebuf statistics
in /proc/fs/pagebuf/stat. It then immediately reset to "0".
vm.pagebuf.flush_age (Min: 1*HZ Default: 15*HZ Max: 300*HZ)
The age at which dirty metadata buffers are flushed to disk
vm.pagebuf.flush_int (Min: HZ/2 Default: HZ Max: 30*HZ)
The interval at which the list of dirty metadata buffers is
scanned.
...@@ -35,7 +35,8 @@ ...@@ -35,7 +35,8 @@
#include <unistd.h> #include <unistd.h>
#include <fcntl.h> #include <fcntl.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <linux/pcwd.h> #include <linux/types.h>
#include <linux/watchdog.h>
int fd; int fd;
......
...@@ -1586,6 +1586,8 @@ L: oprofile-list@lists.sf.net ...@@ -1586,6 +1586,8 @@ L: oprofile-list@lists.sf.net
S: Maintained S: Maintained
ORINOCO DRIVER ORINOCO DRIVER
P: Pavel Roskin
M: proski@gnu.org
P: David Gibson P: David Gibson
M: hermes@gibson.dropbear.id.au M: hermes@gibson.dropbear.id.au
W: http://www.ozlabs.org/people/dgibson/dldwd W: http://www.ozlabs.org/people/dgibson/dldwd
......
...@@ -158,6 +158,9 @@ config ARCH_VERSATILE_PB ...@@ -158,6 +158,9 @@ config ARCH_VERSATILE_PB
help help
This enables support for ARM Ltd Versatile PB board. This enables support for ARM Ltd Versatile PB board.
config ARCH_IMX
bool "IMX"
endchoice endchoice
source "arch/arm/mach-clps711x/Kconfig" source "arch/arm/mach-clps711x/Kconfig"
...@@ -182,6 +185,8 @@ source "arch/arm/mach-s3c2410/Kconfig" ...@@ -182,6 +185,8 @@ source "arch/arm/mach-s3c2410/Kconfig"
source "arch/arm/mach-lh7a40x/Kconfig" source "arch/arm/mach-lh7a40x/Kconfig"
source "arch/arm/mach-imx/Kconfig"
# Definitions to make life easier # Definitions to make life easier
config ARCH_ACORN config ARCH_ACORN
bool bool
...@@ -294,7 +299,7 @@ config ARM_AMBA ...@@ -294,7 +299,7 @@ config ARM_AMBA
config ISA config ISA
bool bool
depends on FOOTBRIDGE_HOST || ARCH_SHARK || ARCH_CLPS7500 || ARCH_EBSA110 || ARCH_CDB89712 || ARCH_EDB7211 || ARCH_SA1100 depends on FOOTBRIDGE_HOST || ARCH_SHARK || ARCH_CLPS7500 || ARCH_EBSA110 || ARCH_CDB89712 || ARCH_EDB7211 || ARCH_SA1100 || ARCH_MX1ADS
default y default y
help help
Find out whether you have ISA slots on your motherboard. ISA is the Find out whether you have ISA slots on your motherboard. ISA is the
...@@ -552,7 +557,7 @@ config CMDLINE ...@@ -552,7 +557,7 @@ config CMDLINE
config LEDS config LEDS
bool "Timer and CPU usage LEDs" bool "Timer and CPU usage LEDs"
depends on ARCH_NETWINDER || ARCH_EBSA110 || ARCH_EBSA285 || ARCH_SHARK || ARCH_CO285 || ARCH_SA1100 || ARCH_LUBBOCK || MACH_MAINSTONE || ARCH_PXA_IDP || ARCH_INTEGRATOR || ARCH_CDB89712 || ARCH_P720T || ARCH_OMAP || ARCH_VERSATILE_PB depends on ARCH_NETWINDER || ARCH_EBSA110 || ARCH_EBSA285 || ARCH_SHARK || ARCH_CO285 || ARCH_SA1100 || ARCH_LUBBOCK || MACH_MAINSTONE || ARCH_PXA_IDP || ARCH_INTEGRATOR || ARCH_CDB89712 || ARCH_P720T || ARCH_OMAP || ARCH_VERSATILE_PB || ARCH_IMX
help help
If you say Y here, the LEDs on your machine will be used If you say Y here, the LEDs on your machine will be used
to provide useful information about your current system status. to provide useful information about your current system status.
...@@ -565,8 +570,8 @@ config LEDS ...@@ -565,8 +570,8 @@ config LEDS
system, but the driver will do nothing. system, but the driver will do nothing.
config LEDS_TIMER config LEDS_TIMER
bool "Timer LED" if LEDS && (ARCH_NETWINDER || ARCH_EBSA285 || ARCH_SHARK || MACH_MAINSTONE || ARCH_CO285 || ARCH_SA1100 || ARCH_LUBBOCK || ARCH_PXA_IDP || ARCH_INTEGRATOR || ARCH_P720T || ARCH_VERSATILE_PB) bool "Timer LED" if LEDS && (ARCH_NETWINDER || ARCH_EBSA285 || ARCH_SHARK || MACH_MAINSTONE || ARCH_CO285 || ARCH_SA1100 || ARCH_LUBBOCK || ARCH_PXA_IDP || ARCH_INTEGRATOR || ARCH_P720T || ARCH_VERSATILE_PB || ARCH_IMX)
depends on ARCH_NETWINDER || ARCH_EBSA110 || ARCH_EBSA285 || ARCH_SHARK || ARCH_CO285 || ARCH_SA1100 || ARCH_LUBBOCK || MACH_MAINSTONE || ARCH_PXA_IDP || ARCH_INTEGRATOR || ARCH_CDB89712 || ARCH_P720T || ARCH_OMAP || ARCH_VERSATILE_PB depends on ARCH_NETWINDER || ARCH_EBSA110 || ARCH_EBSA285 || ARCH_SHARK || ARCH_CO285 || ARCH_SA1100 || ARCH_LUBBOCK || MACH_MAINSTONE || ARCH_PXA_IDP || ARCH_INTEGRATOR || ARCH_CDB89712 || ARCH_P720T || ARCH_OMAP || ARCH_VERSATILE_PB || ARCH_IMX
default y if ARCH_EBSA110 default y if ARCH_EBSA110
help help
If you say Y here, one of the system LEDs (the green one on the If you say Y here, one of the system LEDs (the green one on the
...@@ -581,7 +586,7 @@ config LEDS_TIMER ...@@ -581,7 +586,7 @@ config LEDS_TIMER
config LEDS_CPU config LEDS_CPU
bool "CPU usage LED" bool "CPU usage LED"
depends on LEDS && (ARCH_NETWINDER || ARCH_EBSA285 || ARCH_SHARK || ARCH_CO285 || ARCH_SA1100 || ARCH_LUBBOCK || MACH_MAINSTONE || ARCH_PXA_IDP || ARCH_INTEGRATOR || ARCH_P720T || ARCH_VERSATILE_PB) depends on LEDS && (ARCH_NETWINDER || ARCH_EBSA285 || ARCH_SHARK || ARCH_CO285 || ARCH_SA1100 || ARCH_LUBBOCK || MACH_MAINSTONE || ARCH_PXA_IDP || ARCH_INTEGRATOR || ARCH_P720T || ARCH_VERSATILE_PB || ARCH_IMX)
help help
If you say Y here, the red LED will be used to give a good real If you say Y here, the red LED will be used to give a good real
time indication of CPU usage, by lighting whenever the idle task time indication of CPU usage, by lighting whenever the idle task
......
...@@ -94,6 +94,7 @@ textaddr-$(CONFIG_ARCH_FORTUNET) := 0xc0008000 ...@@ -94,6 +94,7 @@ textaddr-$(CONFIG_ARCH_FORTUNET) := 0xc0008000
machine-$(CONFIG_ARCH_S3C2410) := s3c2410 machine-$(CONFIG_ARCH_S3C2410) := s3c2410
machine-$(CONFIG_ARCH_LH7A40X) := lh7a40x machine-$(CONFIG_ARCH_LH7A40X) := lh7a40x
machine-$(CONFIG_ARCH_VERSATILE_PB) := versatile machine-$(CONFIG_ARCH_VERSATILE_PB) := versatile
machine-$(CONFIG_ARCH_IMX) := imx
ifeq ($(CONFIG_ARCH_EBSA110),y) ifeq ($(CONFIG_ARCH_EBSA110),y)
# This is what happens if you forget the IOCS16 line. # This is what happens if you forget the IOCS16 line.
......
...@@ -47,6 +47,7 @@ endif ...@@ -47,6 +47,7 @@ endif
params_phys-$(CONFIG_ARCH_SA1100) := 0xc0000100 params_phys-$(CONFIG_ARCH_SA1100) := 0xc0000100
initrd_phys-$(CONFIG_ARCH_SA1100) := 0xc0800000 initrd_phys-$(CONFIG_ARCH_SA1100) := 0xc0800000
zreladdr-$(CONFIG_ARCH_PXA) := 0xa0008000 zreladdr-$(CONFIG_ARCH_PXA) := 0xa0008000
zreladdr-$(CONFIG_ARCH_MX1ADS) := 0x08008000
zreladdr-$(CONFIG_ARCH_IOP3XX) := 0xa0008000 zreladdr-$(CONFIG_ARCH_IOP3XX) := 0xa0008000
params_phys-$(CONFIG_ARCH_IOP3XX) := 0xa0000100 params_phys-$(CONFIG_ARCH_IOP3XX) := 0xa0000100
zreladdr-$(CONFIG_ARCH_IXP4XX) := 0x00008000 zreladdr-$(CONFIG_ARCH_IXP4XX) := 0x00008000
......
...@@ -47,23 +47,3 @@ __XScale_start: ...@@ -47,23 +47,3 @@ __XScale_start:
#ifdef CONFIG_ARCH_COTULLA_IDP #ifdef CONFIG_ARCH_COTULLA_IDP
mov r7, #MACH_TYPE_COTULLA_IDP mov r7, #MACH_TYPE_COTULLA_IDP
#endif #endif
#ifdef CONFIG_ARCH_IQ80310
/*
* Crank the CPU up to 733MHz
*/
mov r1, #9
mcr p14, 0, r1, c6, c0, 0
/*
* Disable ECC error notification
* At some point, we should add an ECC handler to Linux
*/
mov r1, #0x1500
mov r0, #0x4
str r0, [r1, #0x34]
mov r7, #MACH_TYPE_IQ80310
#endif
This diff is collapsed.
...@@ -77,6 +77,12 @@ CONFIG_ARCH_H1940=y ...@@ -77,6 +77,12 @@ CONFIG_ARCH_H1940=y
CONFIG_ARCH_SMDK2410=y CONFIG_ARCH_SMDK2410=y
CONFIG_MACH_VR1000=y CONFIG_MACH_VR1000=y
#
# S3C2410 Setup
#
CONFIG_S3C2410_DMA=y
# CONFIG_S3C2410_DMA_DEBUG is not set
# #
# Processor Type # Processor Type
# #
...@@ -601,6 +607,8 @@ CONFIG_ROMFS_FS=y ...@@ -601,6 +607,8 @@ CONFIG_ROMFS_FS=y
CONFIG_FAT_FS=y CONFIG_FAT_FS=y
CONFIG_MSDOS_FS=y CONFIG_MSDOS_FS=y
CONFIG_VFAT_FS=y CONFIG_VFAT_FS=y
CONFIG_FAT_DEFAULT_CODEPAGE=437
CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
# CONFIG_NTFS_FS is not set # CONFIG_NTFS_FS is not set
# #
......
...@@ -19,6 +19,9 @@ obj-$(CONFIG_ARTHUR) += arthur.o ...@@ -19,6 +19,9 @@ obj-$(CONFIG_ARTHUR) += arthur.o
obj-$(CONFIG_ISA_DMA) += dma-isa.o obj-$(CONFIG_ISA_DMA) += dma-isa.o
obj-$(CONFIG_PCI) += bios32.o obj-$(CONFIG_PCI) += bios32.o
obj-$(CONFIG_IWMMXT) += iwmmxt.o
AFLAGS_iwmmxt.o := -Wa,-mcpu=iwmmxt
ifneq ($(CONFIG_ARCH_EBSA110),y) ifneq ($(CONFIG_ARCH_EBSA110),y)
obj-y += io.o obj-y += io.o
endif endif
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <asm/mach/arch.h> #include <asm/mach/arch.h>
#include <asm/thread_info.h>
/* /*
* Make sure that the compiler and target are compatible. * Make sure that the compiler and target are compatible.
...@@ -48,10 +49,23 @@ int main(void) ...@@ -48,10 +49,23 @@ int main(void)
{ {
DEFINE(TSK_ACTIVE_MM, offsetof(struct task_struct, active_mm)); DEFINE(TSK_ACTIVE_MM, offsetof(struct task_struct, active_mm));
BLANK(); BLANK();
DEFINE(TI_FLAGS, offsetof(struct thread_info, flags));
DEFINE(TI_PREEMPT, offsetof(struct thread_info, preempt_count));
DEFINE(TI_ADDR_LIMIT, offsetof(struct thread_info, addr_limit));
DEFINE(TI_TASK, offsetof(struct thread_info, task));
DEFINE(TI_EXEC_DOMAIN, offsetof(struct thread_info, exec_domain));
DEFINE(TI_CPU, offsetof(struct thread_info, cpu));
DEFINE(TI_CPU_DOMAIN, offsetof(struct thread_info, cpu_domain));
DEFINE(TI_CPU_SAVE, offsetof(struct thread_info, cpu_context));
DEFINE(TI_USED_CP, offsetof(struct thread_info, used_cp));
DEFINE(TI_FPSTATE, offsetof(struct thread_info, fpstate));
DEFINE(TI_VFPSTATE, offsetof(struct thread_info, vfpstate));
DEFINE(TI_IWMMXT_STATE, (offsetof(struct thread_info, fpstate)+4)&~7);
BLANK();
#if __LINUX_ARM_ARCH__ >= 6 #if __LINUX_ARM_ARCH__ >= 6
DEFINE(MM_CONTEXT_ID, offsetof(struct mm_struct, context.id)); DEFINE(MM_CONTEXT_ID, offsetof(struct mm_struct, context.id));
#endif
BLANK(); BLANK();
#endif
DEFINE(VMA_VM_MM, offsetof(struct vm_area_struct, vm_mm)); DEFINE(VMA_VM_MM, offsetof(struct vm_area_struct, vm_mm));
DEFINE(VMA_VM_FLAGS, offsetof(struct vm_area_struct, vm_flags)); DEFINE(VMA_VM_FLAGS, offsetof(struct vm_area_struct, vm_flags));
BLANK(); BLANK();
......
...@@ -411,9 +411,7 @@ ...@@ -411,9 +411,7 @@
.macro addruart,rx .macro addruart,rx
mov \rx, #0xfe000000 @ physical mov \rx, #0xfe000000 @ physical
#ifdef CONFIG_ARCH_IQ80310 #if defined(CONFIG_ARCH_IQ80321)
orr \rx, \rx, #0x00810000 @ location of the UART
#elif defined(CONFIG_ARCH_IQ80321)
orr \rx, \rx, #0x00800000 @ location of the UART orr \rx, \rx, #0x00800000 @ location of the UART
#else #else
#error Unknown IOP3XX implementation #error Unknown IOP3XX implementation
...@@ -615,6 +613,30 @@ ...@@ -615,6 +613,30 @@
tst \rd, #1 << 3 @ UARTFLGUBUSY - 1 when busy tst \rd, #1 << 3 @ UARTFLGUBUSY - 1 when busy
bne 1001b bne 1001b
.endm .endm
#elif defined(CONFIG_ARCH_IMX)
.macro addruart,rx
mrc p15, 0, \rx, c1, c0
tst \rx, #1 @ MMU enabled?
moveq \rx, #0x00000000 @ physical
movne \rx, #0xe0000000 @ virtual
orr \rx, \rx, #0x00200000
orr \rx, \rx, #0x00006000 @ UART1 offset
.endm
.macro senduart,rd,rx
str \rd, [\rx, #0x40] @ TXDATA
.endm
.macro waituart,rd,rx
.endm
.macro busyuart,rd,rx
1002: ldr \rd, [\rx, #0x98] @ SR2
tst \rd, #1 << 3 @ TXDC
beq 1002b @ wait until transmit done
.endm
#else #else
#error Unknown architecture #error Unknown architecture
#endif #endif
......
...@@ -562,40 +562,6 @@ ENTRY(soft_irq_mask) ...@@ -562,40 +562,6 @@ ENTRY(soft_irq_mask)
.macro irq_prio_table .macro irq_prio_table
.endm .endm
#elif defined(CONFIG_ARCH_IOP310)
.macro disable_fiq
.endm
.macro get_irqnr_and_base, irqnr, irqstat, base, tmp
mrc p13, 0, \irqstat, c4, c0, 0 @ get INTSRC
mrc p13, 0, \base, c0, c0, 0 @ get INTCTL
tst \irqstat, #(1<<29) @ if INTSRC_BI
tstne \base, #(1<<3) @ and INTCTL_BM
movne \irqnr, #IRQ_XS80200_BCU
bne 1001f
tst \irqstat, #(1<<28) @ if INTSRC_PI
tstne \base, #(1<<2) @ and INTCTL_PM
movne \irqnr, #IRQ_XS80200_PMU
bne 1001f
tst \irqstat, #(1<<31) @ if INTSRC_FI
tstne \base, #(1<<0) @ and INTCTL_FM
movne \irqnr, #IRQ_XS80200_EXTFIQ
bne 1001f
tst \irqstat, #(1<<30) @ if INTSRC_II
tstne \base, #(1<<1) @ and INTCTL_IM
movne \irqnr, #IRQ_XS80200_EXTIRQ
1001:
.endm
.macro irq_prio_table
.endm
#elif defined(CONFIG_ARCH_IOP321) #elif defined(CONFIG_ARCH_IOP321)
.macro disable_fiq .macro disable_fiq
.endm .endm
...@@ -884,6 +850,31 @@ ENTRY(soft_irq_mask) ...@@ -884,6 +850,31 @@ ENTRY(soft_irq_mask)
.macro irq_prio_table .macro irq_prio_table
.endm .endm
#elif defined(CONFIG_ARCH_IMX)
.macro disable_fiq
.endm
#define AITC_NIVECSR 0x40
.macro get_irqnr_and_base, irqnr, irqstat, base, tmp
ldr \irqstat, =IO_ADDRESS(IMX_AITC_BASE)
@ Load offset & priority of the highest priority
@ interrupt pending.
ldr \irqnr, [\irqstat, #AITC_NIVECSR]
@ Shift off the priority leaving the offset or
@ "interrupt number"
mov \irqnr, \irqnr, lsr #16
ldr \irqstat, =1 @ dummy compare
ldr \base, =0xFFFF // invalid interrupt
cmp \irqnr, \base
bne 1001f
ldr \irqstat, =0
1001:
tst \irqstat, #1 @ to make the condition code = TRUE
.endm
.macro irq_prio_table
.endm
#else #else
#error Unknown architecture #error Unknown architecture
#endif #endif
...@@ -1174,7 +1165,7 @@ __und_usr: sub sp, sp, #S_FRAME_SIZE @ Allocate frame size in one go ...@@ -1174,7 +1165,7 @@ __und_usr: sub sp, sp, #S_FRAME_SIZE @ Allocate frame size in one go
* r0 - instruction opcode. * r0 - instruction opcode.
* r10 - this threads thread_info structure. * r10 - this threads thread_info structure.
*/ */
call_fpe: enable_irq r10 @ Enable interrupts call_fpe:
tst r0, #0x08000000 @ only CDP/CPRT/LDC/STC have bit 27 tst r0, #0x08000000 @ only CDP/CPRT/LDC/STC have bit 27
#if defined(CONFIG_CPU_ARM610) || defined(CONFIG_CPU_ARM710) #if defined(CONFIG_CPU_ARM610) || defined(CONFIG_CPU_ARM710)
and r8, r0, #0x0f000000 @ mask out op-code bits and r8, r0, #0x0f000000 @ mask out op-code bits
...@@ -1186,6 +1177,14 @@ call_fpe: enable_irq r10 @ Enable interrupts ...@@ -1186,6 +1177,14 @@ call_fpe: enable_irq r10 @ Enable interrupts
mov r7, #1 mov r7, #1
add r6, r10, #TI_USED_CP add r6, r10, #TI_USED_CP
strb r7, [r6, r8, lsr #8] @ set appropriate used_cp[] strb r7, [r6, r8, lsr #8] @ set appropriate used_cp[]
#ifdef CONFIG_IWMMXT
@ Test if we need to give access to iWMMXt coprocessors
ldr r5, [r10, #TI_FLAGS]
rsbs r7, r8, #(1 << 8) @ CP 0 or 1 only
movcss r7, r5, lsr #(TIF_USING_IWMMXT + 1)
bcs iwmmxt_task_enable
#endif
enable_irq r7
add pc, pc, r8, lsr #6 add pc, pc, r8, lsr #6
mov r0, r0 mov r0, r0
...@@ -1264,7 +1263,11 @@ ENTRY(ret_from_exception) ...@@ -1264,7 +1263,11 @@ ENTRY(ret_from_exception)
ENTRY(__switch_to) ENTRY(__switch_to)
add ip, r1, #TI_CPU_SAVE add ip, r1, #TI_CPU_SAVE
ldr r3, [r2, #TI_CPU_DOMAIN]! ldr r3, [r2, #TI_CPU_DOMAIN]!
stmia ip, {r4 - sl, fp, sp, lr} @ Store most regs on stack stmia ip!, {r4 - sl, fp, sp, lr} @ Store most regs on stack
#if defined(CONFIG_CPU_XSCALE) && !defined(CONFIG_IWMMXT)
mra r4, r5, acc0
stmia ip, {r4, r5}
#endif
mcr p15, 0, r3, c3, c0, 0 @ Set domain register mcr p15, 0, r3, c3, c0, 0 @ Set domain register
#ifdef CONFIG_VFP #ifdef CONFIG_VFP
@ Always disable VFP so we can lazily save/restore the old @ Always disable VFP so we can lazily save/restore the old
...@@ -1272,6 +1275,13 @@ ENTRY(__switch_to) ...@@ -1272,6 +1275,13 @@ ENTRY(__switch_to)
VFPFMRX r4, FPEXC VFPFMRX r4, FPEXC
bic r4, r4, #FPEXC_ENABLE bic r4, r4, #FPEXC_ENABLE
VFPFMXR FPEXC, r4 VFPFMXR FPEXC, r4
#endif
#if defined(CONFIG_IWMMXT)
bl iwmmxt_task_switch
#elif defined(CONFIG_CPU_XSCALE)
add r4, r2, #40 @ cpu_context_save->extra
ldmib r4, {r4, r5}
mar acc0, r4, r5
#endif #endif
ldmib r2, {r4 - sl, fp, sp, pc} @ Load all regs saved previously ldmib r2, {r4 - sl, fp, sp, pc} @ Load all regs saved previously
......
/*
* linux/arch/arm/kernel/iwmmxt.S
*
* XScale iWMMXt (Concan) context switching and handling
*
* Initial code:
* Copyright (c) 2003, Intel Corporation
*
* Full lazy switching support, optimizations and more, by Nicolas Pitre
* Copyright (c) 2003-2004, MontaVista Software, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/linkage.h>
#include <asm/ptrace.h>
#include <asm/thread_info.h>
#include <asm/constants.h>
#define MMX_WR0 (0x00)
#define MMX_WR1 (0x08)
#define MMX_WR2 (0x10)
#define MMX_WR3 (0x18)
#define MMX_WR4 (0x20)
#define MMX_WR5 (0x28)
#define MMX_WR6 (0x30)
#define MMX_WR7 (0x38)
#define MMX_WR8 (0x40)
#define MMX_WR9 (0x48)
#define MMX_WR10 (0x50)
#define MMX_WR11 (0x58)
#define MMX_WR12 (0x60)
#define MMX_WR13 (0x68)
#define MMX_WR14 (0x70)
#define MMX_WR15 (0x78)
#define MMX_WCSSF (0x80)
#define MMX_WCASF (0x84)
#define MMX_WCGR0 (0x88)
#define MMX_WCGR1 (0x8C)
#define MMX_WCGR2 (0x90)
#define MMX_WCGR3 (0x94)
#define MMX_SIZE (0x98)
.text
/*
* Lazy switching of Concan coprocessor context
*
* r10 = struct thread_info pointer
* r9 = ret_from_exception
* lr = undefined instr exit
*
* called from prefetch exception handler with interrupts disabled
*/
ENTRY(iwmmxt_task_enable)
mrc p15, 0, r2, c15, c1, 0
tst r2, #0x3 @ CP0 and CP1 accessible?
movne pc, lr @ if so no business here
orr r2, r2, #0x3 @ enable access to CP0 and CP1
mcr p15, 0, r2, c15, c1, 0
ldr r3, =concan_owner
add r0, r10, #TI_IWMMXT_STATE @ get task Concan save area
ldr r2, [sp, #60] @ current task pc value
ldr r1, [r3] @ get current Concan owner
str r0, [r3] @ this task now owns Concan regs
sub r2, r2, #4 @ adjust pc back
str r2, [sp, #60]
mrc p15, 0, r2, c2, c0, 0
mov r2, r2 @ cpwait
teq r1, #0 @ test for last ownership
mov lr, r9 @ normal exit from exception
beq concan_load @ no owner, skip save
concan_save:
tmrc r2, wCon
@ CUP? wCx
tst r2, #0x1
beq 1f
concan_dump:
wstrw wCSSF, [r1, #MMX_WCSSF]
wstrw wCASF, [r1, #MMX_WCASF]
wstrw wCGR0, [r1, #MMX_WCGR0]
wstrw wCGR1, [r1, #MMX_WCGR1]
wstrw wCGR2, [r1, #MMX_WCGR2]
wstrw wCGR3, [r1, #MMX_WCGR3]
1: @ MUP? wRn
tst r2, #0x2
beq 2f
wstrd wR0, [r1, #MMX_WR0]
wstrd wR1, [r1, #MMX_WR1]
wstrd wR2, [r1, #MMX_WR2]
wstrd wR3, [r1, #MMX_WR3]
wstrd wR4, [r1, #MMX_WR4]
wstrd wR5, [r1, #MMX_WR5]
wstrd wR6, [r1, #MMX_WR6]
wstrd wR7, [r1, #MMX_WR7]
wstrd wR8, [r1, #MMX_WR8]
wstrd wR9, [r1, #MMX_WR9]
wstrd wR10, [r1, #MMX_WR10]
wstrd wR11, [r1, #MMX_WR11]
wstrd wR12, [r1, #MMX_WR12]
wstrd wR13, [r1, #MMX_WR13]
wstrd wR14, [r1, #MMX_WR14]
wstrd wR15, [r1, #MMX_WR15]
2: teq r0, #0 @ anything to load?
moveq pc, lr
concan_load:
@ Load wRn
wldrd wR0, [r0, #MMX_WR0]
wldrd wR1, [r0, #MMX_WR1]
wldrd wR2, [r0, #MMX_WR2]
wldrd wR3, [r0, #MMX_WR3]
wldrd wR4, [r0, #MMX_WR4]
wldrd wR5, [r0, #MMX_WR5]
wldrd wR6, [r0, #MMX_WR6]
wldrd wR7, [r0, #MMX_WR7]
wldrd wR8, [r0, #MMX_WR8]
wldrd wR9, [r0, #MMX_WR9]
wldrd wR10, [r0, #MMX_WR10]
wldrd wR11, [r0, #MMX_WR11]
wldrd wR12, [r0, #MMX_WR12]
wldrd wR13, [r0, #MMX_WR13]
wldrd wR14, [r0, #MMX_WR14]
wldrd wR15, [r0, #MMX_WR15]
@ Load wCx
wldrw wCSSF, [r0, #MMX_WCSSF]
wldrw wCASF, [r0, #MMX_WCASF]
wldrw wCGR0, [r0, #MMX_WCGR0]
wldrw wCGR1, [r0, #MMX_WCGR1]
wldrw wCGR2, [r0, #MMX_WCGR2]
wldrw wCGR3, [r0, #MMX_WCGR3]
@ clear CUP/MUP (only if r1 != 0)
teq r1, #0
mov r2, #0
moveq pc, lr
tmcr wCon, r2
mov pc, lr
/*
* Back up Concan regs to save area and disable access to them
* (mainly for gdb or sleep mode usage)
*
* r0 = struct thread_info pointer of target task or NULL for any
*/
ENTRY(iwmmxt_task_disable)
stmfd sp!, {r4, lr}
mrs ip, cpsr
orr r2, ip, #PSR_I_BIT @ disable interrupts
msr cpsr_c, r2
ldr r3, =concan_owner
add r2, r0, #TI_IWMMXT_STATE @ get task Concan save area
ldr r1, [r3] @ get current Concan owner
teq r1, #0 @ any current owner?
beq 1f @ no: quit
teq r0, #0 @ any owner?
teqne r1, r2 @ or specified one?
bne 1f @ no: quit
mrc p15, 0, r4, c15, c1, 0
orr r4, r4, #0x3 @ enable access to CP0 and CP1
mcr p15, 0, r4, c15, c1, 0
mov r0, #0 @ nothing to load
str r0, [r3] @ no more current owner
mrc p15, 0, r2, c2, c0, 0
mov r2, r2 @ cpwait
bl concan_save
bic r4, r4, #0x3 @ disable access to CP0 and CP1
mcr p15, 0, r4, c15, c1, 0
mrc p15, 0, r2, c2, c0, 0
mov r2, r2 @ cpwait
1: msr cpsr_c, ip @ restore interrupt mode
ldmfd sp!, {r4, pc}
/*
* Copy Concan state to given memory address
*
* r0 = struct thread_info pointer of target task
* r1 = memory address where to store Concan state
*
* this is called mainly in the creation of signal stack frames
*/
ENTRY(iwmmxt_task_copy)
mrs ip, cpsr
orr r2, ip, #PSR_I_BIT @ disable interrupts
msr cpsr_c, r2
ldr r3, =concan_owner
add r2, r0, #TI_IWMMXT_STATE @ get task Concan save area
ldr r3, [r3] @ get current Concan owner
teq r2, r3 @ does this task own it...
beq 1f
@ current Concan values are in the task save area
msr cpsr_c, ip @ restore interrupt mode
mov r0, r1
mov r1, r2
mov r2, #MMX_SIZE
b memcpy
1: @ this task owns Concan regs -- grab a copy from there
mov r0, #0 @ nothing to load
mov r2, #3 @ save all regs
mov r3, lr @ preserve return address
bl concan_dump
msr cpsr_c, ip @ restore interrupt mode
mov pc, r3
/*
* Restore Concan state from given memory address
*
* r0 = struct thread_info pointer of target task
* r1 = memory address where to get Concan state from
*
* this is used to restore Concan state when unwinding a signal stack frame
*/
ENTRY(iwmmxt_task_restore)
mrs ip, cpsr
orr r2, ip, #PSR_I_BIT @ disable interrupts
msr cpsr_c, r2
ldr r3, =concan_owner
add r2, r0, #TI_IWMMXT_STATE @ get task Concan save area
ldr r3, [r3] @ get current Concan owner
bic r2, r2, #0x7 @ 64-bit alignment
teq r2, r3 @ does this task own it...
beq 1f
@ this task doesn't own Concan regs -- use its save area
msr cpsr_c, ip @ restore interrupt mode
mov r0, r2
mov r2, #MMX_SIZE
b memcpy
1: @ this task owns Concan regs -- load them directly
mov r0, r1
mov r1, #0 @ don't clear CUP/MUP
mov r3, lr @ preserve return address
bl concan_load
msr cpsr_c, ip @ restore interrupt mode
mov pc, r3
/*
* Concan handling on task switch
*
* r0 = previous task_struct pointer (must be preserved)
* r1 = previous thread_info pointer
* r2 = next thread_info.cpu_domain pointer (must be preserved)
*
* Called only from __switch_to with task preemption disabled.
* No need to care about preserving r4 and above.
*/
ENTRY(iwmmxt_task_switch)
mrc p15, 0, r4, c15, c1, 0
tst r4, #0x3 @ CP0 and CP1 accessible?
bne 1f @ yes: block them for next task
ldr r5, =concan_owner
add r6, r2, #(TI_IWMMXT_STATE - TI_CPU_DOMAIN) @ get next task Concan save area
ldr r5, [r5] @ get current Concan owner
teq r5, r6 @ next task owns it?
movne pc, lr @ no: leave Concan disabled
1: eor r4, r4, #3 @ flip Concan access
mcr p15, 0, r4, c15, c1, 0
mrc p15, 0, r4, c2, c0, 0
sub pc, lr, r4, lsr #32 @ cpwait and return
/*
* Remove Concan ownership of given task
*
* r0 = struct thread_info pointer
*/
ENTRY(iwmmxt_task_release)
mrs r2, cpsr
orr ip, r2, #PSR_I_BIT @ disable interrupts
msr cpsr_c, ip
ldr r3, =concan_owner
add r0, r0, #TI_IWMMXT_STATE @ get task Concan save area
ldr r1, [r3] @ get current Concan owner
eors r0, r0, r1 @ if equal...
streq r0, [r3] @ then clear ownership
msr cpsr_c, r2 @ restore interrupts
mov pc, lr
.data
concan_owner:
.word 0
...@@ -313,6 +313,9 @@ void flush_thread(void) ...@@ -313,6 +313,9 @@ void flush_thread(void)
memset(thread->used_cp, 0, sizeof(thread->used_cp)); memset(thread->used_cp, 0, sizeof(thread->used_cp));
memset(&tsk->thread.debug, 0, sizeof(struct debug_info)); memset(&tsk->thread.debug, 0, sizeof(struct debug_info));
#if defined(CONFIG_IWMMXT)
iwmmxt_task_release(thread);
#endif
fp_init(&thread->fpstate); fp_init(&thread->fpstate);
#if defined(CONFIG_VFP) #if defined(CONFIG_VFP)
vfp_flush_thread(&thread->vfpstate); vfp_flush_thread(&thread->vfpstate);
...@@ -324,6 +327,9 @@ void release_thread(struct task_struct *dead_task) ...@@ -324,6 +327,9 @@ void release_thread(struct task_struct *dead_task)
#if defined(CONFIG_VFP) #if defined(CONFIG_VFP)
vfp_release_thread(&dead_task->thread_info->vfpstate); vfp_release_thread(&dead_task->thread_info->vfpstate);
#endif #endif
#if defined(CONFIG_IWMMXT)
iwmmxt_task_release(dead_task->thread_info);
#endif
} }
asmlinkage void ret_from_fork(void) __asm__("ret_from_fork"); asmlinkage void ret_from_fork(void) __asm__("ret_from_fork");
......
...@@ -57,7 +57,6 @@ extern unsigned int mem_fclk_21285; ...@@ -57,7 +57,6 @@ extern unsigned int mem_fclk_21285;
extern void paging_init(struct meminfo *, struct machine_desc *desc); extern void paging_init(struct meminfo *, struct machine_desc *desc);
extern void convert_to_tag_list(struct tag *tags); extern void convert_to_tag_list(struct tag *tags);
extern void squash_mem_tags(struct tag *tag); extern void squash_mem_tags(struct tag *tag);
extern void bootmem_init(struct meminfo *);
extern void reboot_setup(char *str); extern void reboot_setup(char *str);
extern int root_mountflags; extern int root_mountflags;
extern int _stext, _text, _etext, _edata, _end; extern int _stext, _text, _etext, _edata, _end;
...@@ -720,7 +719,6 @@ void __init setup_arch(char **cmdline_p) ...@@ -720,7 +719,6 @@ void __init setup_arch(char **cmdline_p)
memcpy(saved_command_line, from, COMMAND_LINE_SIZE); memcpy(saved_command_line, from, COMMAND_LINE_SIZE);
saved_command_line[COMMAND_LINE_SIZE-1] = '\0'; saved_command_line[COMMAND_LINE_SIZE-1] = '\0';
parse_cmdline(cmdline_p, from); parse_cmdline(cmdline_p, from);
bootmem_init(&meminfo);
paging_init(&meminfo, mdesc); paging_init(&meminfo, mdesc);
request_standard_resources(&meminfo, mdesc); request_standard_resources(&meminfo, mdesc);
......
...@@ -145,6 +145,100 @@ struct rt_sigframe ...@@ -145,6 +145,100 @@ struct rt_sigframe
unsigned long retcode; unsigned long retcode;
}; };
#ifdef CONFIG_IWMMXT
/* iwmmxt_area is 0x98 bytes long, preceeded by 8 bytes of signature */
#define IWMMXT_STORAGE_SIZE (0x98 + 8)
#define IWMMXT_MAGIC0 0x12ef842a
#define IWMMXT_MAGIC1 0x1c07ca71
static int page_present(struct mm_struct *mm, unsigned long addr, int wr)
{
pgd_t *pgd = pgd_offset(mm, addr);
if (pgd_present(*pgd)) {
pmd_t *pmd = pmd_offset(pgd, addr);
if (pmd_present(*pmd)) {
pte_t *pte = pte_offset_map(pmd, addr);
return (pte_present(*pte) && (!wr || pte_write(*pte)));
}
}
return 0;
}
static int
preserve_iwmmxt_context(void *iwmmxt_save_area)
{
int err = 0;
/* the iWMMXt context must be 64 bit aligned */
long *iwmmxt_storage = (long *)(((long)iwmmxt_save_area + 4) & ~7);
again:
__put_user_error(IWMMXT_MAGIC0, iwmmxt_storage+0, err);
__put_user_error(IWMMXT_MAGIC1, iwmmxt_storage+1, err);
/*
* iwmmxt_task_copy() doesn't check user permissions.
* Let's do a dummy write on the upper boundary to ensure
* access to user mem is OK all way up.
*/
__put_user_error(0, iwmmxt_storage+IWMMXT_STORAGE_SIZE/4-1, err);
if (!err) {
/* Let's make sure the user mapping won't disappear under us */
struct mm_struct *mm = current->mm;
unsigned long addr = (unsigned long)iwmmxt_storage;
spin_lock(&mm->page_table_lock);
if ( !page_present(mm, addr, 1) ||
!page_present(mm, addr+IWMMXT_STORAGE_SIZE-1, 1) ) {
/* our user area has gone before grabbing the lock */
spin_unlock(&mm->page_table_lock);
goto again;
}
iwmmxt_task_copy(current_thread_info(), iwmmxt_storage+2);
spin_unlock(&mm->page_table_lock);
return 0;
}
return err;
}
static int
restore_iwmmxt_context(void *iwmmxt_save_area)
{
int err = 0;
long *iwmmxt_storage, magic0, magic1, dummy;
/* the iWMMXt context is 64 bit aligned */
iwmmxt_storage = (long *)(((long)iwmmxt_save_area + 4) & ~7);
/*
* Validate iWMMXt context signature.
* Also, iwmmxt_task_restore() doesn't check user permissions.
* Let's do a dummy write on the upper boundary to ensure
* access to user mem is OK all way up.
*/
again:
__get_user_error(magic0, iwmmxt_storage+0, err);
__get_user_error(magic1, iwmmxt_storage+1, err);
if (!err && magic0 == IWMMXT_MAGIC0 && magic1 == IWMMXT_MAGIC1 &&
!__get_user(dummy, iwmmxt_storage+IWMMXT_STORAGE_SIZE/4-1)) {
/* Let's make sure the user mapping won't disappear under us */
struct mm_struct *mm = current->mm;
unsigned long addr = (unsigned long)iwmmxt_storage;
spin_lock(&mm->page_table_lock);
if ( !page_present(mm, addr, 0) ||
!page_present(mm, addr+IWMMXT_STORAGE_SIZE-1, 0) ) {
/* our user area has gone before grabbing the lock */
spin_unlock(&mm->page_table_lock);
goto again;
}
iwmmxt_task_restore(current_thread_info(), iwmmxt_storage+2);
spin_unlock(&mm->page_table_lock);
return 0;
}
return -1;
}
#endif
static int static int
restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc) restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc)
{ {
...@@ -208,6 +302,11 @@ asmlinkage int sys_sigreturn(struct pt_regs *regs) ...@@ -208,6 +302,11 @@ asmlinkage int sys_sigreturn(struct pt_regs *regs)
if (restore_sigcontext(regs, &frame->sc)) if (restore_sigcontext(regs, &frame->sc))
goto badframe; goto badframe;
#ifdef CONFIG_IWMMXT
if (test_thread_flag(TIF_USING_IWMMXT) && restore_iwmmxt_context(frame+1))
goto badframe;
#endif
/* Send SIGTRAP if we're single-stepping */ /* Send SIGTRAP if we're single-stepping */
if (current->ptrace & PT_SINGLESTEP) { if (current->ptrace & PT_SINGLESTEP) {
ptrace_cancel_bpt(current); ptrace_cancel_bpt(current);
...@@ -256,6 +355,11 @@ asmlinkage int sys_rt_sigreturn(struct pt_regs *regs) ...@@ -256,6 +355,11 @@ asmlinkage int sys_rt_sigreturn(struct pt_regs *regs)
if (do_sigaltstack(&frame->uc.uc_stack, NULL, regs->ARM_sp) == -EFAULT) if (do_sigaltstack(&frame->uc.uc_stack, NULL, regs->ARM_sp) == -EFAULT)
goto badframe; goto badframe;
#ifdef CONFIG_IWMMXT
if (test_thread_flag(TIF_USING_IWMMXT) && restore_iwmmxt_context(frame+1))
goto badframe;
#endif
/* Send SIGTRAP if we're single-stepping */ /* Send SIGTRAP if we're single-stepping */
if (current->ptrace & PT_SINGLESTEP) { if (current->ptrace & PT_SINGLESTEP) {
ptrace_cancel_bpt(current); ptrace_cancel_bpt(current);
...@@ -306,6 +410,11 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, int framesize) ...@@ -306,6 +410,11 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, int framesize)
{ {
unsigned long sp = regs->ARM_sp; unsigned long sp = regs->ARM_sp;
#ifdef CONFIG_IWMMXT
if (test_thread_flag(TIF_USING_IWMMXT))
framesize = (framesize + 4 + IWMMXT_STORAGE_SIZE) & ~7;
#endif
/* /*
* This is the X/Open sanctioned signal stack switching. * This is the X/Open sanctioned signal stack switching.
*/ */
...@@ -394,6 +503,11 @@ setup_frame(int usig, struct k_sigaction *ka, sigset_t *set, struct pt_regs *reg ...@@ -394,6 +503,11 @@ setup_frame(int usig, struct k_sigaction *ka, sigset_t *set, struct pt_regs *reg
sizeof(frame->extramask)); sizeof(frame->extramask));
} }
#ifdef CONFIG_IWMMXT
if (test_thread_flag(TIF_USING_IWMMXT))
err |= preserve_iwmmxt_context(frame+1);
#endif
if (err == 0) if (err == 0)
err = setup_return(regs, ka, &frame->retcode, frame, usig); err = setup_return(regs, ka, &frame->retcode, frame, usig);
...@@ -428,6 +542,11 @@ setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info, ...@@ -428,6 +542,11 @@ setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info,
regs, set->sig[0]); regs, set->sig[0]);
err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
#ifdef CONFIG_IWMMXT
if (test_thread_flag(TIF_USING_IWMMXT))
err |= preserve_iwmmxt_context(frame+1);
#endif
if (err == 0) if (err == 0)
err = setup_return(regs, ka, &frame->retcode, frame, usig); err = setup_return(regs, ka, &frame->retcode, frame, usig);
......
...@@ -32,59 +32,34 @@ ...@@ -32,59 +32,34 @@
.global __get_user_1 .global __get_user_1
__get_user_1: __get_user_1:
bic r1, sp, #0x1f00 1: ldrbt r1, [r0]
bic r1, r1, #0x00ff mov r0, #0
ldr r1, [r1, #TI_ADDR_LIMIT] mov pc, lr
sub r1, r1, #1
cmp r0, r1
1: ldrlsbt r1, [r0]
movls r0, #0
movls pc, lr
b __get_user_bad
.global __get_user_2 .global __get_user_2
__get_user_2: __get_user_2:
bic r2, sp, #0x1f00 2: ldrbt r1, [r0], #1
bic r2, r2, #0x00ff 3: ldrbt r2, [r0]
ldr r2, [r2, #TI_ADDR_LIMIT]
sub r2, r2, #2
cmp r0, r2
2: ldrlsbt r1, [r0], #1
3: ldrlsbt r2, [r0]
#ifndef __ARMEB__ #ifndef __ARMEB__
orrls r1, r1, r2, lsl #8 orr r1, r1, r2, lsl #8
#else #else
orrls r1, r2, r1, lsl #8 orr r1, r2, r1, lsl #8
#endif #endif
movls r0, #0 mov r0, #0
movls pc, lr mov pc, lr
b __get_user_bad
.global __get_user_4 .global __get_user_4
__get_user_4: __get_user_4:
bic r1, sp, #0x1f00 4: ldrt r1, [r0]
bic r1, r1, #0x00ff mov r0, #0
ldr r1, [r1, #TI_ADDR_LIMIT] mov pc, lr
sub r1, r1, #4
cmp r0, r1
4: ldrlst r1, [r0]
movls r0, #0
movls pc, lr
b __get_user_bad
.global __get_user_8 .global __get_user_8
__get_user_8: __get_user_8:
bic r2, sp, #0x1f00 5: ldrt r1, [r0], #4
bic r2, r2, #0x00ff 6: ldrt r2, [r0]
ldr r2, [r2, #TI_ADDR_LIMIT] mov r0, #0
sub r2, r2, #8 mov pc, lr
cmp r0, r2
5: ldrlst r1, [r0], #4
6: ldrlst r2, [r0]
movls r0, #0
movls pc, lr
/* fall through */
__get_user_bad_8: __get_user_bad_8:
mov r2, #0 mov r2, #0
......
...@@ -32,60 +32,35 @@ ...@@ -32,60 +32,35 @@
.global __put_user_1 .global __put_user_1
__put_user_1: __put_user_1:
bic ip, sp, #0x1f00 1: strbt r1, [r0]
bic ip, ip, #0x00ff mov r0, #0
ldr ip, [ip, #TI_ADDR_LIMIT] mov pc, lr
sub ip, ip, #1
cmp r0, ip
1: strlsbt r1, [r0]
movls r0, #0
movls pc, lr
b __put_user_bad
.global __put_user_2 .global __put_user_2
__put_user_2: __put_user_2:
bic ip, sp, #0x1f00 mov ip, r1, lsr #8
bic ip, ip, #0x00ff
ldr ip, [ip, #TI_ADDR_LIMIT]
sub ip, ip, #2
cmp r0, ip
movls ip, r1, lsr #8
#ifndef __ARMEB__ #ifndef __ARMEB__
2: strlsbt r1, [r0], #1 2: strbt r1, [r0], #1
3: strlsbt ip, [r0] 3: strbt ip, [r0]
#else #else
2: strlsbt ip, [r0], #1 2: strbt ip, [r0], #1
3: strlsbt r1, [r0] 3: strbt r1, [r0]
#endif #endif
movls r0, #0 mov r0, #0
movls pc, lr mov pc, lr
b __put_user_bad
.global __put_user_4 .global __put_user_4
__put_user_4: __put_user_4:
bic ip, sp, #0x1f00 4: strt r1, [r0]
bic ip, ip, #0x00ff mov r0, #0
ldr ip, [ip, #TI_ADDR_LIMIT] mov pc, lr
sub ip, ip, #4
cmp r0, ip
4: strlst r1, [r0]
movls r0, #0
movls pc, lr
b __put_user_bad
.global __put_user_8 .global __put_user_8
__put_user_8: __put_user_8:
bic ip, sp, #0x1f00 5: strt r1, [r0], #4
bic ip, ip, #0x00ff 6: strt r2, [r0]
ldr ip, [ip, #TI_ADDR_LIMIT] mov r0, #0
sub ip, ip, #8 mov pc, lr
cmp r0, ip
5: strlst r1, [r0], #4
6: strlst r2, [r0]
movls r0, #0
movls pc, lr
/* fall through */
__put_user_bad: __put_user_bad:
mov r0, #-EFAULT mov r0, #-EFAULT
......
menu "IMX Implementations"
depends on ARCH_IMX
config ARCH_MX1ADS
bool "mx1ads"
depends on ARCH_IMX
help
Say Y here if you are using the Motorola MX1ADS board
endmenu
#
# Makefile for the linux 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).
# Object file lists.
obj-y += irq.o time.o dma.o generic.o
# Specific board support
obj-$(CONFIG_ARCH_MX1ADS) += mx1ads.o
# Support for blinky lights
led-y := leds.o
obj-$(CONFIG_LEDS) += $(led-y)
led-$(CONFIG_ARCH_MX1ADS) += leds-mx1ads.o
/*
* linux/arch/arm/mach-imx/dma.c
*
* imx DMA registration and IRQ dispatching
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* 03/03/2004 Sascha Hauer <sascha@saschahauer.de>
* initial version heavily inspired by
* linux/arch/arm/mach-pxa/dma.c
*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/interrupt.h>
#include <linux/errno.h>
#include <asm/system.h>
#include <asm/irq.h>
#include <asm/hardware.h>
#include <asm/dma.h>
static struct dma_channel {
char *name;
void (*irq_handler) (int, void *, struct pt_regs *);
void (*err_handler) (int, void *, struct pt_regs *);
void *data;
} dma_channels[11];
/* set err_handler to NULL to have the standard info-only error handler */
int
imx_request_dma(char *name, imx_dma_prio prio,
void (*irq_handler) (int, void *, struct pt_regs *),
void (*err_handler) (int, void *, struct pt_regs *), void *data)
{
unsigned long flags;
int i, found = 0;
/* basic sanity checks */
if (!name || !irq_handler)
return -EINVAL;
local_irq_save(flags);
/* try grabbing a DMA channel with the requested priority */
for (i = prio; i < prio + (prio == DMA_PRIO_LOW) ? 8 : 4; i++) {
if (!dma_channels[i].name) {
found = 1;
break;
}
}
if (!found) {
/* requested prio group is full, try hier priorities */
for (i = prio - 1; i >= 0; i--) {
if (!dma_channels[i].name) {
found = 1;
break;
}
}
}
if (found) {
DIMR &= ~(1 << i);
dma_channels[i].name = name;
dma_channels[i].irq_handler = irq_handler;
dma_channels[i].err_handler = err_handler;
dma_channels[i].data = data;
} else {
printk(KERN_WARNING "No more available DMA channels for %s\n",
name);
i = -ENODEV;
}
local_irq_restore(flags);
return i;
}
void
imx_free_dma(int dma_ch)
{
unsigned long flags;
if (!dma_channels[dma_ch].name) {
printk(KERN_CRIT
"%s: trying to free channel %d which is already freed\n",
__FUNCTION__, dma_ch);
return;
}
local_irq_save(flags);
DIMR &= ~(1 << dma_ch);
dma_channels[dma_ch].name = NULL;
local_irq_restore(flags);
}
static irqreturn_t
dma_err_handler(int irq, void *dev_id, struct pt_regs *regs)
{
int i;
struct dma_channel *channel;
unsigned int err_mask = DBTOSR | DRTOSR | DSESR | DBOSR;
for (i = 0; i < 11; i++) {
channel = &dma_channels[i];
if ( (err_mask & 1<<i) && channel->name && channel->err_handler) {
channel->err_handler(i, channel->data, regs);
continue;
}
if (DBTOSR & (1 << i)) {
printk(KERN_WARNING
"Burst timeout on channel %d (%s)\n",
i, channel->name);
DBTOSR |= (1 << i);
}
if (DRTOSR & (1 << i)) {
printk(KERN_WARNING
"Request timeout on channel %d (%s)\n",
i, channel->name);
DRTOSR |= (1 << i);
}
if (DSESR & (1 << i)) {
printk(KERN_WARNING
"Transfer timeout on channel %d (%s)\n",
i, channel->name);
DSESR |= (1 << i);
}
if (DBOSR & (1 << i)) {
printk(KERN_WARNING
"Buffer overflow timeout on channel %d (%s)\n",
i, channel->name);
DBOSR |= (1 << i);
}
DISR |= (1 << i);
}
return IRQ_HANDLED;
}
static irqreturn_t
dma_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
{
int i, disr = DISR;
for (i = 0; i < 11; i++) {
if (disr & (1 << i)) {
struct dma_channel *channel = &dma_channels[i];
if (channel->name && channel->irq_handler) {
channel->irq_handler(i, channel->data, regs);
} else {
/*
* IRQ for an unregistered DMA channel:
* let's clear the interrupts and disable it.
*/
printk(KERN_WARNING
"spurious IRQ for DMA channel %d\n", i);
DISR |= (1 << i);
}
}
}
return IRQ_HANDLED;
}
static int __init
imx_dma_init(void)
{
int ret;
/* reset DMA module */
DCR = DCR_DRST;
ret = request_irq(DMA_INT, dma_irq_handler, 0, "DMA", NULL);
if (ret) {
printk(KERN_CRIT "Wow! Can't register IRQ for DMA\n");
return ret;
}
ret = request_irq(DMA_ERR, dma_err_handler, 0, "DMA", NULL);
if (ret) {
printk(KERN_CRIT "Wow! Can't register ERRIRQ for DMA\n");
free_irq(DMA_INT, NULL);
}
/* enable DMA module */
DCR = DCR_DEN;
/* clear all interrupts */
DISR = 0x3ff;
/* enable interrupts */
DIMR = 0;
return ret;
}
arch_initcall(imx_dma_init);
EXPORT_SYMBOL(imx_request_dma);
EXPORT_SYMBOL(imx_free_dma);
/*
* arch/arm/mach-imx/generic.c
*
* author: Sascha Hauer
* Created: april 20th, 2004
* Copyright: Synertronixx GmbH
*
* Common code for i.MX machines
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include <linux/device.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <asm/hardware.h>
#include <asm/mach/map.h>
void imx_gpio_mode(int gpio_mode)
{
unsigned int pin = gpio_mode & GPIO_PIN_MASK;
unsigned int port = (gpio_mode & GPIO_PORT_MASK) >> 5;
unsigned int ocr = (gpio_mode & GPIO_OCR_MASK) >> 10;
unsigned int tmp;
/* Pullup enable */
if(gpio_mode & GPIO_PUEN)
PUEN(port) |= (1<<pin);
else
PUEN(port) &= ~(1<<pin);
/* Data direction */
if(gpio_mode & GPIO_OUT)
DDIR(port) |= 1<<pin;
else
DDIR(port) &= ~(1<<pin);
/* Primary / alternate function */
if(gpio_mode & GPIO_AF)
GPR(port) |= (1<<pin);
else
GPR(port) &= ~(1<<pin);
/* use as gpio? */
if( ocr == 3 )
GIUS(port) |= (1<<pin);
else
GIUS(port) &= ~(1<<pin);
/* Output / input configuration */
/* FIXME: I'm not very sure about OCR and ICONF, someone
* should have a look over it
*/
if(pin<16) {
tmp = OCR1(port);
tmp &= ~( 3<<(pin*2));
tmp |= (ocr << (pin*2));
OCR1(port) = tmp;
if( gpio_mode & GPIO_AOUT )
ICONFA1(port) &= ~( 3<<(pin*2));
if( gpio_mode & GPIO_BOUT )
ICONFB1(port) &= ~( 3<<(pin*2));
} else {
tmp = OCR2(port);
tmp &= ~( 3<<((pin-16)*2));
tmp |= (ocr << ((pin-16)*2));
OCR2(port) = tmp;
if( gpio_mode & GPIO_AOUT )
ICONFA2(port) &= ~( 3<<((pin-16)*2));
if( gpio_mode & GPIO_BOUT )
ICONFB2(port) &= ~( 3<<((pin-16)*2));
}
}
EXPORT_SYMBOL(imx_gpio_mode);
/*
* get the system pll clock in Hz
*
* mfi + mfn / (mfd +1)
* f = 2 * f_ref * --------------------
* pd + 1
*/
static unsigned int imx_decode_pll(unsigned int pll)
{
u32 mfi = (pll >> 10) & 0xf;
u32 mfn = pll & 0x3f;
u32 mfd = (pll >> 16) & 0x3f;
u32 pd = (pll >> 26) & 0xf;
u32 f_ref = (CSCR & CSCR_SYSTEM_SEL) ? 16000000 : (CLK32 * 512);
mfi = mfi <= 5 ? 5 : mfi;
return (2 * (f_ref>>10) * ( (mfi<<10) + (mfn<<10) / (mfd+1) )) / (pd+1);
}
unsigned int imx_get_system_clk(void)
{
return imx_decode_pll(SPCTL0);
}
EXPORT_SYMBOL(imx_get_system_clk);
unsigned int imx_get_mcu_clk(void)
{
return imx_decode_pll(MPCTL0);
}
EXPORT_SYMBOL(imx_get_mcu_clk);
/*
* get peripheral clock 1 ( UART[12], Timer[12], PWM )
*/
unsigned int imx_get_perclk1(void)
{
return imx_get_system_clk() / (((PCDR) & 0xf)+1);
}
EXPORT_SYMBOL(imx_get_perclk1);
/*
* get peripheral clock 2 ( LCD, SD, SPI[12] )
*/
unsigned int imx_get_perclk2(void)
{
return imx_get_system_clk() / (((PCDR>>4) & 0xf)+1);
}
EXPORT_SYMBOL(imx_get_perclk2);
/*
* get peripheral clock 3 ( SSI )
*/
unsigned int imx_get_perclk3(void)
{
return imx_get_system_clk() / (((PCDR>>16) & 0x7f)+1);
}
EXPORT_SYMBOL(imx_get_perclk3);
/*
* get hclk ( SDRAM, CSI, Memory Stick, I2C, DMA )
*/
unsigned int imx_get_hclk(void)
{
return imx_get_system_clk() / (((CSCR>>10) & 0xf)+1);
}
EXPORT_SYMBOL(imx_get_hclk);
static struct resource imx_mmc_resources[] = {
[0] = {
.start = 0x00214000,
.end = 0x002140FF,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = (SDHC_INT),
.end = (SDHC_INT),
.flags = IORESOURCE_IRQ,
},
};
static struct platform_device imx_mmc_device = {
.name = "imx-mmc",
.id = 0,
.num_resources = ARRAY_SIZE(imx_mmc_resources),
.resource = imx_mmc_resources,
};
static struct resource imx_uart1_resources[] = {
[0] = {
.start = 0x00206000,
.end = 0x002060FF,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = (UART1_MINT_RX),
.end = (UART1_MINT_RX),
.flags = IORESOURCE_IRQ,
},
[2] = {
.start = (UART1_MINT_TX),
.end = (UART1_MINT_TX),
.flags = IORESOURCE_IRQ,
},
};
static struct platform_device imx_uart1_device = {
.name = "imx-uart",
.id = 0,
.num_resources = ARRAY_SIZE(imx_uart1_resources),
.resource = imx_uart1_resources,
};
static struct resource imx_uart2_resources[] = {
[0] = {
.start = 0x00207000,
.end = 0x002070FF,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = (UART2_MINT_RX),
.end = (UART2_MINT_RX),
.flags = IORESOURCE_IRQ,
},
[2] = {
.start = (UART2_MINT_TX),
.end = (UART2_MINT_TX),
.flags = IORESOURCE_IRQ,
},
};
static struct platform_device imx_uart2_device = {
.name = "imx-uart",
.id = 1,
.num_resources = ARRAY_SIZE(imx_uart2_resources),
.resource = imx_uart2_resources,
};
static struct resource imxfb_resources[] = {
[0] = {
.start = 0x00205000,
.end = 0x002050FF,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = LCDC_INT,
.end = LCDC_INT,
.flags = IORESOURCE_IRQ,
},
};
static struct platform_device imxfb_device = {
.name = "imx-fb",
.id = 0,
.num_resources = ARRAY_SIZE(imxfb_resources),
.resource = imxfb_resources,
};
static struct platform_device *devices[] __initdata = {
&imx_mmc_device,
&imxfb_device,
&imx_uart1_device,
&imx_uart2_device,
};
static struct map_desc imx_io_desc[] __initdata = {
/* virtual physical length type */
{IMX_IO_BASE, IMX_IO_PHYS, IMX_IO_SIZE, MT_DEVICE},
};
void __init
imx_map_io(void)
{
iotable_init(imx_io_desc, ARRAY_SIZE(imx_io_desc));
}
static int __init imx_init(void)
{
return platform_add_devices(devices, ARRAY_SIZE(devices));
}
subsys_initcall(imx_init);
/*
* linux/arch/arm/mach-imx/generic.h
*
* Author: Sascha Hauer <sascha@saschahauer.de>
* Copyright: Synertronixx GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
extern void __init imx_map_io(void);
extern void __init imx_init_irq(void);
extern void __init imx_init_time(void);
/*
* linux/arch/arm/mach-imx/irq.c
*
* Copyright (C) 1999 ARM Limited
* Copyright (C) 2002 Shane Nay (shane@minirl.com)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* 03/03/2004 Sascha Hauer <sascha@saschahauer.de>
* Copied from the motorola bsp package and added gpio demux
* interrupt handler
*/
#include <linux/init.h>
#include <linux/list.h>
#include <linux/timer.h>
#include <asm/hardware.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <asm/mach/irq.h>
/*
*
* We simply use the ENABLE DISABLE registers inside of the IMX
* to turn on/off specific interrupts. FIXME- We should
* also add support for the accelerated interrupt controller
* by putting offets to irq jump code in the appropriate
* places.
*
*/
#define INTENNUM_OFF 0x8
#define INTDISNUM_OFF 0xC
#define VA_AITC_BASE IO_ADDRESS(IMX_AITC_BASE)
#define IMX_AITC_INTDISNUM (VA_AITC_BASE + INTDISNUM_OFF)
#define IMX_AITC_INTENNUM (VA_AITC_BASE + INTENNUM_OFF)
#if 0
#define DEBUG_IRQ(fmt...) printk(fmt)
#else
#define DEBUG_IRQ(fmt...) do { } while (0)
#endif
static void
imx_mask_irq(unsigned int irq)
{
__raw_writel(irq, IMX_AITC_INTDISNUM);
}
static void
imx_unmask_irq(unsigned int irq)
{
__raw_writel(irq, IMX_AITC_INTENNUM);
}
static int
imx_gpio_irq_type(unsigned int _irq, unsigned int type)
{
unsigned int irq_type = 0, irq, reg, bit;
irq = _irq - IRQ_GPIOA(0);
reg = irq >> 5;
bit = 1 << (irq % 32);
if (type == IRQT_PROBE) {
/* Don't mess with enabled GPIOs using preconfigured edges or
GPIOs set to alternate function during probe */
/* TODO: support probe */
// if ((GPIO_IRQ_rising_edge[idx] | GPIO_IRQ_falling_edge[idx]) &
// GPIO_bit(gpio))
// return 0;
// if (GAFR(gpio) & (0x3 << (((gpio) & 0xf)*2)))
// return 0;
// type = __IRQT_RISEDGE | __IRQT_FALEDGE;
}
GIUS(reg) |= bit;
DDIR(reg) &= ~(bit);
DEBUG_IRQ("setting type of irq %d to ", _irq);
if (type & __IRQT_RISEDGE) {
DEBUG_IRQ("rising edges\n");
irq_type = 0x0;
}
if (type & __IRQT_FALEDGE) {
DEBUG_IRQ("falling edges\n");
irq_type = 0x1;
}
if (type & __IRQT_LOWLVL) {
DEBUG_IRQ("low level\n");
irq_type = 0x3;
}
if (type & __IRQT_HIGHLVL) {
DEBUG_IRQ("high level\n");
irq_type = 0x2;
}
if (irq % 32 < 16) {
ICR1(reg) = (ICR1(reg) & ~(0x3 << ((irq % 16) * 2))) |
(irq_type << ((irq % 16) * 2));
} else {
ICR2(reg) = (ICR2(reg) & ~(0x3 << ((irq % 16) * 2))) |
(irq_type << ((irq % 16) * 2));
}
return 0;
}
static void
imx_gpio_ack_irq(unsigned int irq)
{
DEBUG_IRQ("%s: irq %d\n", __FUNCTION__, irq);
ISR(IRQ_TO_REG(irq)) |= 1 << ((irq - IRQ_GPIOA(0)) % 32);
}
static void
imx_gpio_mask_irq(unsigned int irq)
{
DEBUG_IRQ("%s: irq %d\n", __FUNCTION__, irq);
IMR(IRQ_TO_REG(irq)) &= ~( 1 << ((irq - IRQ_GPIOA(0)) % 32));
}
static void
imx_gpio_unmask_irq(unsigned int irq)
{
DEBUG_IRQ("%s: irq %d\n", __FUNCTION__, irq);
IMR(IRQ_TO_REG(irq)) |= 1 << ((irq - IRQ_GPIOA(0)) % 32);
}
static void
imx_gpio_handler(unsigned int mask, unsigned int irq,
struct irqdesc *desc, struct pt_regs *regs)
{
desc = irq_desc + irq;
while (mask) {
if (mask & 1) {
DEBUG_IRQ("handling irq %d\n", irq);
desc->handle(irq, desc, regs);
}
irq++;
desc++;
mask >>= 1;
}
}
static void
imx_gpioa_demux_handler(unsigned int irq_unused, struct irqdesc *desc,
struct pt_regs *regs)
{
unsigned int mask, irq;
mask = ISR(0);
irq = IRQ_GPIOA(0);
imx_gpio_handler(mask, irq, desc, regs);
}
static void
imx_gpiob_demux_handler(unsigned int irq_unused, struct irqdesc *desc,
struct pt_regs *regs)
{
unsigned int mask, irq;
mask = ISR(1);
irq = IRQ_GPIOB(0);
imx_gpio_handler(mask, irq, desc, regs);
}
static void
imx_gpioc_demux_handler(unsigned int irq_unused, struct irqdesc *desc,
struct pt_regs *regs)
{
unsigned int mask, irq;
mask = ISR(2);
irq = IRQ_GPIOC(0);
imx_gpio_handler(mask, irq, desc, regs);
}
static void
imx_gpiod_demux_handler(unsigned int irq_unused, struct irqdesc *desc,
struct pt_regs *regs)
{
unsigned int mask, irq;
mask = ISR(3);
irq = IRQ_GPIOD(0);
imx_gpio_handler(mask, irq, desc, regs);
}
static struct irqchip imx_internal_chip = {
.ack = imx_mask_irq,
.mask = imx_mask_irq,
.unmask = imx_unmask_irq,
};
static struct irqchip imx_gpio_chip = {
.ack = imx_gpio_ack_irq,
.mask = imx_gpio_mask_irq,
.unmask = imx_gpio_unmask_irq,
.type = imx_gpio_irq_type,
};
void __init
imx_init_irq(void)
{
unsigned int irq;
DEBUG_IRQ("Initializing imx interrupts\n");
/* Mask all interrupts initially */
IMR(0) = 0;
IMR(1) = 0;
IMR(2) = 0;
IMR(3) = 0;
for (irq = 0; irq < IMX_IRQS; irq++) {
set_irq_chip(irq, &imx_internal_chip);
set_irq_handler(irq, do_level_IRQ);
set_irq_flags(irq, IRQF_VALID);
}
for (irq = IRQ_GPIOA(0); irq < IRQ_GPIOD(32); irq++) {
set_irq_chip(irq, &imx_gpio_chip);
set_irq_handler(irq, do_edge_IRQ);
set_irq_flags(irq, IRQF_VALID);
}
set_irq_chained_handler(GPIO_INT_PORTA, imx_gpioa_demux_handler);
set_irq_chained_handler(GPIO_INT_PORTB, imx_gpiob_demux_handler);
set_irq_chained_handler(GPIO_INT_PORTC, imx_gpioc_demux_handler);
set_irq_chained_handler(GPIO_INT_PORTD, imx_gpiod_demux_handler);
/* Disable all interrupts initially. */
/* In IMX this is done in the bootloader. */
}
/*
* linux/arch/arm/mach-imx/leds-mx1ads.c
*
* Copyright (c) 2004 Sascha Hauer <sascha@saschahauer.de>
*
* Original (leds-footbridge.c) by Russell King
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
*/
#include <linux/kernel.h>
#include <linux/init.h>
#include <asm/hardware.h>
#include <asm/system.h>
#include <asm/io.h>
#include <asm/leds.h>
#include <asm/mach-types.h>
#include "leds.h"
/*
* The MX1ADS Board has only one usable LED,
* so select only the timer led or the
* cpu usage led
*/
void
mx1ads_leds_event(led_event_t ledevt)
{
unsigned long flags;
local_irq_save(flags);
switch (ledevt) {
#ifdef CONFIG_LEDS_CPU
case led_idle_start:
DR(0) &= ~(1<<2);
break;
case led_idle_end:
DR(0) |= 1<<2;
break;
#endif
#ifdef CONFIG_LEDS_TIMER
case led_timer:
DR(0) ^= 1<<2;
#endif
default:
break;
}
local_irq_restore(flags);
}
/*
* linux/arch/arm/mach-imx/leds.h
*
* Copyright (C) 2004 Sascha Hauer <sascha@saschahauer.de>
*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
*/
#include <linux/kernel.h>
#include <linux/init.h>
#include <asm/leds.h>
#include <asm/mach-types.h>
#include "leds.h"
static int __init
leds_init(void)
{
if (machine_is_mx1ads()) {
leds_event = mx1ads_leds_event;
}
return 0;
}
__initcall(leds_init);
/*
* include/asm-arm/arch-imx/leds.h
*
* Copyright (c) 2004 Sascha Hauer <sascha@saschahauer.de>
*
* blinky lights for IMX-based systems
*
*/
extern void mx1ads_leds_event(led_event_t evt);
/*
* arch/arm/mach-imx/mx1ads.c
*
* Initially based on:
* linux-2.6.7-imx/arch/arm/mach-imx/scb9328.c
* Copyright (c) 2004 Sascha Hauer <sascha@saschahauer.de>
*
* 2004 (c) MontaVista Software, Inc.
*
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied.
*/
#include <linux/device.h>
#include <linux/init.h>
#include <asm/system.h>
#include <asm/hardware.h>
#include <asm/irq.h>
#include <asm/pgtable.h>
#include <asm/page.h>
#include <asm/mach/map.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
#include <linux/interrupt.h>
#include "generic.h"
#include <asm/serial.h>
static struct resource mx1ads_resources[] = {
[0] = {
.start = IMX_CS4_VIRT,
.end = IMX_CS4_VIRT + 16,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = 13,
.end = 13,
.flags = IORESOURCE_IRQ,
},
};
static struct platform_device mx1ads_device = {
.name = "mx1ads",
.num_resources = ARRAY_SIZE(mx1ads_resources),
.resource = mx1ads_resources,
};
static struct platform_device *devices[] __initdata = {
&mx1ads_device,
};
static void __init
mx1ads_init(void)
{
#ifdef CONFIG_LEDS
imx_gpio_mode(GPIO_PORTA | GPIO_OUT | GPIO_GPIO | 2);
#endif
platform_add_devices(devices, ARRAY_SIZE(devices));
}
static struct map_desc mx1ads_io_desc[] __initdata = {
/* virtual physical length type */
{IMX_CS0_VIRT, IMX_CS0_PHYS, IMX_CS0_SIZE, MT_DEVICE},
{IMX_CS1_VIRT, IMX_CS1_PHYS, IMX_CS1_SIZE, MT_DEVICE},
{IMX_CS2_VIRT, IMX_CS2_PHYS, IMX_CS2_SIZE, MT_DEVICE},
{IMX_CS3_VIRT, IMX_CS3_PHYS, IMX_CS3_SIZE, MT_DEVICE},
{IMX_CS4_VIRT, IMX_CS4_PHYS, IMX_CS4_SIZE, MT_DEVICE},
{IMX_CS5_VIRT, IMX_CS5_PHYS, IMX_CS5_SIZE, MT_DEVICE},
};
static void __init
mx1ads_map_io(void)
{
imx_map_io();
iotable_init(mx1ads_io_desc, ARRAY_SIZE(mx1ads_io_desc));
}
MACHINE_START(MX1ADS, "Motorola MX1ADS")
MAINTAINER("Sascha Hauer, Pengutronix")
BOOT_MEM(0x08000000, 0x00200000, 0xe0200000)
BOOT_PARAMS(0x08000100)
MAPIO(mx1ads_map_io)
INITIRQ(imx_init_irq)
INITTIME(imx_init_time)
INIT_MACHINE(mx1ads_init)
MACHINE_END
/*
* linux/arch/arm/mach-imx/time.c
*
* Copyright (C) 2000-2001 Deep Blue Solutions
* Copyright (C) 2002 Shane Nay (shane@minirl.com)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/time.h>
#include <asm/hardware.h>
#include <asm/io.h>
#include <asm/leds.h>
#include <asm/irq.h>
#include <asm/mach/time.h>
/* Use timer 1 as system timer */
#define TIMER_BASE IMX_TIM1_BASE
/*
* Returns number of ms since last clock interrupt. Note that interrupts
* will have been disabled by do_gettimeoffset()
*/
static unsigned long
imx_gettimeoffset(void)
{
unsigned long ticks;
/*
* Get the current number of ticks. Note that there is a race
* condition between us reading the timer and checking for
* an interrupt. We get around this by ensuring that the
* counter has not reloaded between our two reads.
*/
ticks = IMX_TCR(TIMER_BASE);
/*
* Interrupt pending? If so, we've reloaded once already.
*/
if (IMX_TSTAT(TIMER_BASE) & TSTAT_COMP)
ticks += LATCH;
/*
* Convert the ticks to usecs
*/
return (1000000 / CLK32) * ticks;
}
/*
* IRQ handler for the timer
*/
static irqreturn_t
imx_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
/* clear the interrupt */
if (IMX_TSTAT(TIMER_BASE))
IMX_TSTAT(TIMER_BASE) = 0;
timer_tick(regs);
return IRQ_HANDLED;
}
static struct irqaction imx_timer_irq = {
.name = "i.MX Timer Tick",
.flags = SA_INTERRUPT,
.handler = imx_timer_interrupt
};
/*
* Set up timer interrupt, and return the current time in seconds.
*/
void __init
imx_init_time(void)
{
/*
* Initialise to a known state (all timers off, and timing reset)
*/
IMX_TCTL(TIMER_BASE) = 0;
IMX_TPRER(TIMER_BASE) = 0;
IMX_TCMP(TIMER_BASE) = LATCH;
IMX_TCTL(TIMER_BASE) = TCTL_CLK_32 | TCTL_IRQEN | TCTL_TEN;
/*
* Make irqs happen for the system timer
*/
setup_irq(TIM1_INT, &imx_timer_irq);
gettimeoffset = imx_gettimeoffset;
}
...@@ -79,7 +79,7 @@ static int integrator_set_target(struct cpufreq_policy *policy, ...@@ -79,7 +79,7 @@ static int integrator_set_target(struct cpufreq_policy *policy,
unsigned int target_freq, unsigned int target_freq,
unsigned int relation) unsigned int relation)
{ {
unsigned long cpus_allowed; cpumask_t cpus_allowed;
int cpu = policy->cpu; int cpu = policy->cpu;
struct icst525_vco vco; struct icst525_vco vco;
struct cpufreq_freqs freqs; struct cpufreq_freqs freqs;
...@@ -94,7 +94,7 @@ static int integrator_set_target(struct cpufreq_policy *policy, ...@@ -94,7 +94,7 @@ static int integrator_set_target(struct cpufreq_policy *policy,
* Bind to the specified CPU. When this call returns, * Bind to the specified CPU. When this call returns,
* we should be running on the right CPU. * we should be running on the right CPU.
*/ */
set_cpus_allowed(current, 1 << cpu); set_cpus_allowed(current, cpumask_of_cpu(cpu));
BUG_ON(cpu != smp_processor_id()); BUG_ON(cpu != smp_processor_id());
/* get current setting */ /* get current setting */
...@@ -154,14 +154,14 @@ static int integrator_set_target(struct cpufreq_policy *policy, ...@@ -154,14 +154,14 @@ static int integrator_set_target(struct cpufreq_policy *policy,
static unsigned int integrator_get(unsigned int cpu) static unsigned int integrator_get(unsigned int cpu)
{ {
unsigned long cpus_allowed; cpumask_t cpus_allowed;
unsigned int current_freq; unsigned int current_freq;
u_int cm_osc; u_int cm_osc;
struct icst525_vco vco; struct icst525_vco vco;
cpus_allowed = current->cpus_allowed; cpus_allowed = current->cpus_allowed;
set_cpus_allowed(current, 1 << cpu); set_cpus_allowed(current, cpumask_of_cpu(cpu));
BUG_ON(cpu != smp_processor_id()); BUG_ON(cpu != smp_processor_id());
/* detect memory etc. */ /* detect memory etc. */
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include <asm/io.h> #include <asm/io.h>
#include <asm/hardware/icst525.h> #include <asm/hardware/icst525.h>
#include <asm/hardware/amba.h> #include <asm/hardware/amba.h>
#include <asm/hardware/amba_clcd.h>
#include <asm/arch/lm.h> #include <asm/arch/lm.h>
#include <asm/arch/impd1.h> #include <asm/arch/impd1.h>
#include <asm/sizes.h> #include <asm/sizes.h>
...@@ -87,10 +88,198 @@ void impd1_tweak_control(struct device *dev, u32 mask, u32 val) ...@@ -87,10 +88,198 @@ void impd1_tweak_control(struct device *dev, u32 mask, u32 val)
EXPORT_SYMBOL(impd1_tweak_control); EXPORT_SYMBOL(impd1_tweak_control);
/*
* CLCD support
*/
#define PANEL PROSPECTOR
#define LTM10C209 1
#define PROSPECTOR 2
#define SVGA 3
#define VGA 4
#if PANEL == VGA
#define PANELTYPE vga
static struct clcd_panel vga = {
.mode = {
.name = "VGA",
.refresh = 60,
.xres = 640,
.yres = 480,
.pixclock = 39721,
.left_margin = 40,
.right_margin = 24,
.upper_margin = 32,
.lower_margin = 11,
.hsync_len = 96,
.vsync_len = 2,
.sync = 0,
.vmode = FB_VMODE_NONINTERLACED,
},
.width = -1,
.height = -1,
.tim2 = TIM2_BCD | TIM2_IPC,
.cntl = CNTL_LCDTFT | CNTL_LCDVCOMP(1),
.connector = IMPD1_CTRL_DISP_VGA,
.bpp = 16,
.grayscale = 0,
};
#elif PANEL == SVGA
#define PANELTYPE svga
static struct clcd_panel svga = {
.mode = {
.name = "SVGA",
.refresh = 0,
.xres = 800,
.yres = 600,
.pixclock = 27778,
.left_margin = 20,
.right_margin = 20,
.upper_margin = 5,
.lower_margin = 5,
.hsync_len = 164,
.vsync_len = 62,
.sync = 0,
.vmode = FB_VMODE_NONINTERLACED,
},
.width = -1,
.height = -1,
.tim2 = TIM2_BCD,
.cntl = CNTL_LCDTFT | CNTL_LCDVCOMP(1),
.connector = IMPD1_CTRL_DISP_VGA,
.bpp = 16,
.grayscale = 0,
};
#elif PANEL == PROSPECTOR
#define PANELTYPE prospector
static struct clcd_panel prospector = {
.mode = {
.name = "PROSPECTOR",
.refresh = 0,
.xres = 640,
.yres = 480,
.pixclock = 40000,
.left_margin = 33,
.right_margin = 64,
.upper_margin = 36,
.lower_margin = 7,
.hsync_len = 64,
.vsync_len = 25,
.sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
.vmode = FB_VMODE_NONINTERLACED,
},
.width = -1,
.height = -1,
.tim2 = TIM2_BCD,
.cntl = CNTL_LCDTFT | CNTL_LCDVCOMP(1),
.fixedtimings = 1,
.connector = IMPD1_CTRL_DISP_LCD,
.bpp = 16,
.grayscale = 0,
};
#elif PANEL == LTM10C209
#define PANELTYPE ltm10c209
/*
* Untested.
*/
static struct clcd_panel ltm10c209 = {
.mode = {
.name = "LTM10C209",
.refresh = 0,
.xres = 640,
.yres = 480,
.pixclock = 40000,
.left_margin = 20,
.right_margin = 20,
.upper_margin = 19,
.lower_margin = 19,
.hsync_len = 20,
.vsync_len = 10,
.sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
.vmode = FB_VMODE_NONINTERLACED,
},
.width = -1,
.height = -1,
.tim2 = TIM2_BCD,
.cntl = CNTL_LCDTFT | CNTL_LCDVCOMP(1),
.fixedtimings = 1,
.connector = IMPD1_CTRL_DISP_LCD,
.bpp = 16,
.grayscale = 0,
};
#endif
/*
* Disable all display connectors on the interface module.
*/
static void impd1fb_clcd_disable(struct clcd_fb *fb)
{
impd1_tweak_control(fb->dev->dev.parent, IMPD1_CTRL_DISP_MASK, 0);
}
/*
* Enable the relevant connector on the interface module.
*/
static void impd1fb_clcd_enable(struct clcd_fb *fb)
{
impd1_tweak_control(fb->dev->dev.parent, IMPD1_CTRL_DISP_MASK,
fb->panel->connector | IMPD1_CTRL_DISP_ENABLE);
}
static int impd1fb_clcd_setup(struct clcd_fb *fb)
{
unsigned long framebase = fb->dev->res.start + 0x01000000;
unsigned long framesize = SZ_1M;
int ret = 0;
fb->panel = &PANELTYPE;
if (!request_mem_region(framebase, framesize, "clcd framebuffer")) {
printk(KERN_ERR "IM-PD1: unable to reserve framebuffer\n");
return -EBUSY;
}
fb->fb.screen_base = ioremap(framebase, framesize);
if (!fb->fb.screen_base) {
printk(KERN_ERR "IM-PD1: unable to map framebuffer\n");
ret = -ENOMEM;
goto free_buffer;
}
fb->fb.fix.smem_start = framebase;
fb->fb.fix.smem_len = framesize;
return 0;
free_buffer:
release_mem_region(framebase, framesize);
return ret;
}
static void impd1fb_clcd_remove(struct clcd_fb *fb)
{
iounmap(fb->fb.screen_base);
release_mem_region(fb->fb.fix.smem_start, fb->fb.fix.smem_len);
}
static struct clcd_board impd1_clcd_data = {
.name = "IM-PD/1",
.check = clcdfb_check,
.decode = clcdfb_decode,
.disable = impd1fb_clcd_disable,
.enable = impd1fb_clcd_enable,
.setup = impd1fb_clcd_setup,
.remove = impd1fb_clcd_remove,
};
struct impd1_device { struct impd1_device {
unsigned long offset; unsigned long offset;
unsigned int irq[2]; unsigned int irq[2];
unsigned int id; unsigned int id;
void *platform_data;
}; };
static struct impd1_device impd1_devs[] = { static struct impd1_device impd1_devs[] = {
...@@ -133,6 +322,7 @@ static struct impd1_device impd1_devs[] = { ...@@ -133,6 +322,7 @@ static struct impd1_device impd1_devs[] = {
.offset = 0x01000000, .offset = 0x01000000,
.irq = { 11 }, .irq = { 11 },
.id = 0x00041110, .id = 0x00041110,
.platform_data = &impd1_clcd_data,
} }
}; };
...@@ -202,6 +392,7 @@ static int impd1_probe(struct lm_device *dev) ...@@ -202,6 +392,7 @@ static int impd1_probe(struct lm_device *dev)
d->irq[0] = dev->irq; d->irq[0] = dev->irq;
d->irq[1] = dev->irq; d->irq[1] = dev->irq;
d->periphid = idev->id; d->periphid = idev->id;
d->dev.platform_data = idev->platform_data;
ret = amba_device_register(d, &dev->resource); ret = amba_device_register(d, &dev->resource);
if (ret) { if (ret) {
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/list.h> #include <linux/list.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/dma-mapping.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/sysdev.h> #include <linux/sysdev.h>
...@@ -23,8 +24,10 @@ ...@@ -23,8 +24,10 @@
#include <asm/mach-types.h> #include <asm/mach-types.h>
#include <asm/hardware/amba.h> #include <asm/hardware/amba.h>
#include <asm/hardware/amba_kmi.h> #include <asm/hardware/amba_kmi.h>
#include <asm/hardware/amba_clcd.h>
#include <asm/hardware/icst525.h> #include <asm/hardware/icst525.h>
#include <asm/arch/cm.h>
#include <asm/arch/lm.h> #include <asm/arch/lm.h>
#include <asm/mach/arch.h> #include <asm/mach/arch.h>
...@@ -382,10 +385,83 @@ static struct amba_device aaci_device = { ...@@ -382,10 +385,83 @@ static struct amba_device aaci_device = {
.periphid = 0, .periphid = 0,
}; };
/*
* CLCD support
*/
static struct clcd_panel vga = {
.mode = {
.name = "VGA",
.refresh = 60,
.xres = 640,
.yres = 480,
.pixclock = 39721,
.left_margin = 40,
.right_margin = 24,
.upper_margin = 32,
.lower_margin = 11,
.hsync_len = 96,
.vsync_len = 2,
.sync = 0,
.vmode = FB_VMODE_NONINTERLACED,
},
.width = -1,
.height = -1,
.tim2 = TIM2_BCD | TIM2_IPC,
.cntl = CNTL_LCDTFT | CNTL_LCDVCOMP(1),
.bpp = 16,
.grayscale = 0,
};
/*
* Ensure VGA is selected.
*/
static void cp_clcd_enable(struct clcd_fb *fb)
{
cm_control(CM_CTRL_LCDMUXSEL_MASK, CM_CTRL_LCDMUXSEL_VGA);
}
static unsigned long framesize = SZ_1M;
static int cp_clcd_setup(struct clcd_fb *fb)
{
dma_addr_t dma;
fb->panel = &vga;
fb->fb.screen_base = dma_alloc_writecombine(&fb->dev->dev, framesize,
&dma, GFP_KERNEL);
if (!fb->fb.screen_base) {
printk(KERN_ERR "CLCD: unable to map framebuffer\n");
return -ENOMEM;
}
fb->fb.fix.smem_start = dma;
fb->fb.fix.smem_len = framesize;
return 0;
}
static void cp_clcd_remove(struct clcd_fb *fb)
{
dma_free_writecombine(&fb->dev->dev, fb->fb.fix.smem_len,
fb->fb.screen_base, fb->fb.fix.smem_start);
}
static struct clcd_board clcd_data = {
.name = "Integrator/CP",
.check = clcdfb_check,
.decode = clcdfb_decode,
.enable = cp_clcd_enable,
.setup = cp_clcd_setup,
.remove = cp_clcd_remove,
};
static struct amba_device clcd_device = { static struct amba_device clcd_device = {
.dev = { .dev = {
.bus_id = "mb:c0", .bus_id = "mb:c0",
.coherent_dma_mask = ~0, .coherent_dma_mask = ~0,
.platform_data = &clcd_data,
}, },
.res = { .res = {
.start = INTCP_PA_CLCD_BASE, .start = INTCP_PA_CLCD_BASE,
......
...@@ -4,13 +4,7 @@ menu "IOP3xx Implementation Options" ...@@ -4,13 +4,7 @@ menu "IOP3xx Implementation Options"
choice choice
prompt "IOP3xx System Type" prompt "IOP3xx System Type"
default ARCH_IQ80310 default ARCH_IQ80321
config ARCH_IQ80310
bool "IQ80310"
help
Say Y here if you want to run your kernel on the Intel IQ80310
evaluation kit for the IOP310 chipset.
config ARCH_IQ80321 config ARCH_IQ80321
bool "IQ80321" bool "IQ80321"
...@@ -20,12 +14,6 @@ config ARCH_IQ80321 ...@@ -20,12 +14,6 @@ config ARCH_IQ80321
endchoice endchoice
# Which IOP variant are we running? # Which IOP variant are we running?
config ARCH_IOP310
bool
default ARCH_IQ80310
help
The IQ80310 uses the IOP310 variant.
config ARCH_IOP321 config ARCH_IOP321
bool bool
default ARCH_IQ80321 default ARCH_IQ80321
...@@ -42,14 +30,6 @@ config IOP3XX_DMA ...@@ -42,14 +30,6 @@ config IOP3XX_DMA
bool "Support Intel IOP3xx DMA (EXPERIMENTAL)" bool "Support Intel IOP3xx DMA (EXPERIMENTAL)"
depends on EXPERIMENTAL depends on EXPERIMENTAL
config IOP3XX_MU
bool "Support Intel IOP3xx Messaging Unit (EXPERIMENTAL)"
depends on EXPERIMENTAL
config IOP3XX_PMON
bool "Support Intel IOP3xx Performance Monitor (EXPERIMENTAL)"
depends on EXPERIMENTAL
endmenu endmenu
endif endif
...@@ -10,21 +10,9 @@ obj-m := ...@@ -10,21 +10,9 @@ obj-m :=
obj-n := obj-n :=
obj- := obj- :=
obj-$(CONFIG_ARCH_IOP310) += xs80200-irq.o iop310-irq.o iop310-pci.o mm.o
obj-$(CONFIG_ARCH_IQ80310) += iq80310-pci.o iq80310-irq.o
obj-$(CONFIG_ARCH_IOP321) += iop321-irq.o iop321-pci.o mm-321.o iop321-time.o obj-$(CONFIG_ARCH_IOP321) += iop321-irq.o iop321-pci.o mm-321.o iop321-time.o
obj-$(CONFIG_ARCH_IQ80321) += iq80321-pci.o obj-$(CONFIG_ARCH_IQ80321) += iq80321-pci.o
ifeq ($(CONFIG_ARCH_IQ80310),y)
ifneq ($(CONFIG_XSCALE_PMU_TIMER),y)
obj-y += iq80310-time.o
endif
endif
obj-$(CONFIG_IOP3XX_AAU) += aau.o obj-$(CONFIG_IOP3XX_AAU) += aau.o
obj-$(CONFIG_IOP3XX_DMA) += dma.o obj-$(CONFIG_IOP3XX_DMA) += dma.o
obj-$(CONFIG_IOP3XX_MU) += message.o
obj-$(CONFIG_IOP3XX_PMON) += pmon.o
...@@ -21,49 +21,23 @@ ...@@ -21,49 +21,23 @@
#include <asm/mach-types.h> #include <asm/mach-types.h>
#include <asm/mach/arch.h> #include <asm/mach/arch.h>
#ifdef CONFIG_ARCH_IQ80310
extern void iq80310_map_io(void);
extern void iq80310_init_irq(void);
#endif
#ifdef CONFIG_ARCH_IQ80321 #ifdef CONFIG_ARCH_IQ80321
extern void iq80321_map_io(void); extern void iq80321_map_io(void);
extern void iop321_init_irq(void); extern void iop321_init_irq(void);
extern void iop321_init_time(void); extern void iop321_init_time(void);
#endif #endif
#ifdef CONFIG_ARCH_IQ80310
static void __init
fixup_iq80310(struct machine_desc *desc, struct tag *tags,
char **cmdline, struct meminfo *mi)
{
system_rev = (*(volatile unsigned int*)0xfe830000) & 0x0f;
if (system_rev)
system_rev = 0xF;
}
#endif
#ifdef CONFIG_ARCH_IQ80321 #ifdef CONFIG_ARCH_IQ80321
static void __init static void __init
fixup_iop321(struct machine_desc *desc, struct param_struct *params, fixup_iop321(struct machine_desc *desc, struct tag *tags,
char **cmdline, struct meminfo *mi) char **cmdline, struct meminfo *mi)
{ {
} }
#endif #endif
#ifdef CONFIG_ARCH_IQ80310 #if defined(CONFIG_ARCH_IQ80321)
MACHINE_START(IQ80310, "Cyclone IQ80310")
MAINTAINER("MontaVista Software Inc.")
BOOT_MEM(0xa0000000, 0xfe000000, 0xfe000000)
FIXUP(fixup_iq80310)
MAPIO(iq80310_map_io)
INITIRQ(iq80310_init_irq)
MACHINE_END
#elif defined(CONFIG_ARCH_IQ80321)
MACHINE_START(IQ80321, "Intel IQ80321") MACHINE_START(IQ80321, "Intel IQ80321")
MAINTAINER("MontaVista Software, Inc.") MAINTAINER("Intel Corporation")
BOOT_MEM(PHYS_OFFSET, IQ80321_UART1, 0xfe800000) BOOT_MEM(PHYS_OFFSET, IQ80321_UART1, 0xfe800000)
FIXUP(fixup_iop321) FIXUP(fixup_iop321)
MAPIO(iq80321_map_io) MAPIO(iq80321_map_io)
...@@ -72,5 +46,5 @@ MACHINE_START(IQ80321, "Intel IQ80321") ...@@ -72,5 +46,5 @@ MACHINE_START(IQ80321, "Intel IQ80321")
MACHINE_END MACHINE_END
#else #else
#error No machine descriptor defined for this IOP310 implementation #error No machine descriptor defined for this IOP3xx implementation
#endif #endif
/*
* linux/arch/arm/mach-iop3xx/iop310-irq.c
*
* Generic IOP310 IRQ handling functionality
*
* Author: Nicolas Pitre
* Copyright: (C) 2001 MontaVista Software Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Added IOP310 chipset and IQ80310 board demuxing, masking code. - DS
*
*/
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/list.h>
#include <asm/mach/irq.h>
#include <asm/irq.h>
#include <asm/hardware.h>
extern void xs80200_irq_mask(unsigned int);
extern void xs80200_irq_unmask(unsigned int);
extern void xs80200_init_irq(void);
extern void do_IRQ(int, struct pt_regs *);
static u32 iop310_mask /* = 0 */;
static void iop310_irq_mask (unsigned int irq)
{
iop310_mask ++;
/*
* No mask bits on the 80312, so we have to
* mask everything from the outside!
*/
if (iop310_mask == 1) {
disable_irq(IRQ_XS80200_EXTIRQ);
irq_desc[IRQ_XS80200_EXTIRQ].chip->mask(IRQ_XS80200_EXTIRQ);
}
}
static void iop310_irq_unmask (unsigned int irq)
{
if (iop310_mask)
iop310_mask --;
/*
* Check if all 80312 sources are unmasked now
*/
if (iop310_mask == 0)
enable_irq(IRQ_XS80200_EXTIRQ);
}
struct irqchip ext_chip = {
.ack = iop310_irq_mask,
.mask = iop310_irq_mask,
.unmask = iop310_irq_unmask,
};
void
iop310_irq_demux(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs)
{
u32 fiq1isr = *((volatile u32*)IOP310_FIQ1ISR);
u32 fiq2isr = *((volatile u32*)IOP310_FIQ2ISR);
struct irqdesc *d;
unsigned int irqno = 0;
if(fiq1isr)
{
if(fiq1isr & 0x1)
irqno = IRQ_IOP310_DMA0;
if(fiq1isr & 0x2)
irqno = IRQ_IOP310_DMA1;
if(fiq1isr & 0x4)
irqno = IRQ_IOP310_DMA2;
if(fiq1isr & 0x10)
irqno = IRQ_IOP310_PMON;
if(fiq1isr & 0x20)
irqno = IRQ_IOP310_AAU;
}
else
{
if(fiq2isr & 0x2)
irqno = IRQ_IOP310_I2C;
if(fiq2isr & 0x4)
irqno = IRQ_IOP310_MU;
}
if (irqno) {
d = irq_desc + irqno;
d->handle(irqno, d, regs);
}
}
void __init iop310_init_irq(void)
{
unsigned int i;
for(i = IOP310_IRQ_OFS; i < NR_IOP310_IRQS; i++)
{
set_irq_chip(i, &ext_chip);
set_irq_handler(i, do_level_IRQ);
set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
}
xs80200_init_irq();
}
This diff is collapsed.
...@@ -158,6 +158,7 @@ iop321_write_config(struct pci_bus *bus, unsigned int devfn, int where, ...@@ -158,6 +158,7 @@ iop321_write_config(struct pci_bus *bus, unsigned int devfn, int where,
: "r" (value), "r" (addr), : "r" (value), "r" (addr),
"r" (IOP321_OCCAR), "r" (IOP321_OCCDR)); "r" (IOP321_OCCAR), "r" (IOP321_OCCDR));
} }
return PCIBIOS_SUCCESSFUL;
} }
static struct pci_ops iop321_ops = { static struct pci_ops iop321_ops = {
......
...@@ -79,7 +79,7 @@ extern int setup_arm_irq(int, struct irqaction*); ...@@ -79,7 +79,7 @@ extern int setup_arm_irq(int, struct irqaction*);
void __init iop321_init_time(void) void __init iop321_init_time(void)
{ {
u32 timer_ctl; u32 timer_ctl;
u32 latch = LATCH; /* u32 latch = LATCH; */
gettimeoffset = iop321_gettimeoffset; gettimeoffset = iop321_gettimeoffset;
setup_irq(IRQ_IOP321_TIMER0, &iop321_timer_irq); setup_irq(IRQ_IOP321_TIMER0, &iop321_timer_irq);
......
/*
* linux/arch/arm/mach-iop3xx/iq80310-irq.c
*
* IRQ hadling/demuxing for IQ80310 board
*
* Author: Nicolas Pitre
* Copyright: (C) 2001 MontaVista Software Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* 2.4.7-rmk1-iop310.1
* Moved demux from asm to C - DS
* Fixes for various revision boards - DS
*/
#include <linux/init.h>
#include <linux/list.h>
#include <asm/irq.h>
#include <asm/mach/irq.h>
#include <asm/hardware.h>
#include <asm/system.h>
extern void iop310_init_irq(void);
extern void iop310_irq_demux(unsigned int, struct irqdesc *, struct pt_regs *);
static void iq80310_irq_mask(unsigned int irq)
{
*(volatile char *)IQ80310_INT_MASK |= (1 << (irq - IQ80310_IRQ_OFS));
}
static void iq80310_irq_unmask(unsigned int irq)
{
*(volatile char *)IQ80310_INT_MASK &= ~(1 << (irq - IQ80310_IRQ_OFS));
}
static struct irqchip iq80310_irq_chip = {
.ack = iq80310_irq_mask,
.mask = iq80310_irq_mask,
.unmask = iq80310_irq_unmask,
};
extern struct irqchip ext_chip;
static void
iq80310_cpld_irq_handler(unsigned int irq, struct irqdesc *desc,
struct pt_regs *regs)
{
unsigned int irq_stat = *(volatile u8*)IQ80310_INT_STAT;
unsigned int irq_mask = *(volatile u8*)IQ80310_INT_MASK;
unsigned int i, handled = 0;
struct irqdesc *d;
desc->chip->ack(irq);
/*
* Mask out the interrupts which aren't enabled.
*/
irq_stat &= 0x1f & ~irq_mask;
/*
* Test each IQ80310 CPLD interrupt
*/
for (i = IRQ_IQ80310_TIMER, d = irq_desc + IRQ_IQ80310_TIMER;
irq_stat; i++, d++, irq_stat >>= 1)
if (irq_stat & 1) {
d->handle(i, d, regs);
handled++;
}
/*
* If running on a board later than REV D.1, we can
* decode the PCI interrupt status.
*/
if (system_rev) {
irq_stat = *((volatile u8*)IQ80310_PCI_INT_STAT) & 7;
for (i = IRQ_IQ80310_INTA, d = irq_desc + IRQ_IQ80310_INTA;
irq_stat; i++, d++, irq_stat >>= 1)
if (irq_stat & 0x1) {
d->handle(i, d, regs);
handled++;
}
}
/*
* If on a REV D.1 or lower board, we just assumed INTA
* since PCI is not routed, and it may actually be an
* on-chip interrupt.
*
* Note that we're giving on-chip interrupts slightly
* higher priority than PCI by handling them first.
*
* On boards later than REV D.1, if we didn't read a
* CPLD interrupt, we assume it's from a device on the
* chipset itself.
*/
if (system_rev == 0 || handled == 0)
iop310_irq_demux(irq, desc, regs);
desc->chip->unmask(irq);
}
void __init iq80310_init_irq(void)
{
volatile char *mask = (volatile char *)IQ80310_INT_MASK;
unsigned int i;
iop310_init_irq();
/*
* Setup PIRSR to route PCI interrupts into xs80200
*/
*IOP310_PIRSR = 0xff;
/*
* Setup the IRQs in the FE820000/FE860000 registers
*/
for (i = IQ80310_IRQ_OFS; i <= IRQ_IQ80310_INTD; i++) {
set_irq_chip(i, &iq80310_irq_chip);
set_irq_handler(i, do_level_IRQ);
set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
}
/*
* Setup the PCI IRQs
*/
for (i = IRQ_IQ80310_INTA; i < IRQ_IQ80310_INTC; i++) {
set_irq_chip(i, &ext_chip);
set_irq_handler(i, do_level_IRQ);
set_irq_flags(i, IRQF_VALID);
}
*mask = 0xff; /* mask all sources */
set_irq_chained_handler(IRQ_XS80200_EXTIRQ,
&iq80310_cpld_irq_handler);
}
/*
* arch/arm/mach-iop3xx/iq80310-pci.c
*
* PCI support for the Intel IQ80310 reference board
*
* Matt Porter <mporter@mvista.com>
*
* Copyright (C) 2001 MontaVista Software, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/kernel.h>
#include <linux/pci.h>
#include <linux/init.h>
#include <asm/hardware.h>
#include <asm/irq.h>
#include <asm/mach/pci.h>
#include <asm/mach-types.h>
/*
* The following macro is used to lookup irqs in a standard table
* format for those systems that do not already have PCI
* interrupts properly routed. We assume 1 <= pin <= 4
*/
#define PCI_IRQ_TABLE_LOOKUP(minid,maxid) \
({ int _ctl_ = -1; \
unsigned int _idsel = idsel - minid; \
if (_idsel <= maxid) \
_ctl_ = pci_irq_table[_idsel][pin-1]; \
_ctl_; })
#define INTA IRQ_IQ80310_INTA
#define INTB IRQ_IQ80310_INTB
#define INTC IRQ_IQ80310_INTC
#define INTD IRQ_IQ80310_INTD
#define INTE IRQ_IQ80310_I82559
typedef u8 irq_table[4];
/*
* IRQ tables for primary bus.
*
* On a Rev D.1 and older board, INT A-C are not routed, so we
* just fake it as INTA and than we take care of handling it
* correctly in the IRQ demux routine.
*/
static irq_table pci_pri_d_irq_table[] = {
/* Pin: A B C D */
{ INTA, INTD, INTA, INTA }, /* PCI Slot J3 */
{ INTD, INTA, INTA, INTA }, /* PCI Slot J4 */
};
static irq_table pci_pri_f_irq_table[] = {
/* Pin: A B C D */
{ INTC, INTD, INTA, INTB }, /* PCI Slot J3 */
{ INTD, INTA, INTB, INTC }, /* PCI Slot J4 */
};
static int __init
iq80310_pri_map_irq(struct pci_dev *dev, u8 idsel, u8 pin)
{
irq_table *pci_irq_table;
BUG_ON(pin < 1 || pin > 4);
if (!system_rev) {
pci_irq_table = pci_pri_d_irq_table;
} else {
pci_irq_table = pci_pri_f_irq_table;
}
return PCI_IRQ_TABLE_LOOKUP(2, 3);
}
/*
* IRQ tables for secondary bus.
*
* On a Rev D.1 and older board, INT A-C are not routed, so we
* just fake it as INTA and than we take care of handling it
* correctly in the IRQ demux routine.
*/
static irq_table pci_sec_d_irq_table[] = {
/* Pin: A B C D */
{ INTA, INTA, INTA, INTD }, /* PCI Slot J1 */
{ INTA, INTA, INTD, INTA }, /* PCI Slot J5 */
{ INTE, INTE, INTE, INTE }, /* P2P Bridge */
};
static irq_table pci_sec_f_irq_table[] = {
/* Pin: A B C D */
{ INTA, INTB, INTC, INTD }, /* PCI Slot J1 */
{ INTB, INTC, INTD, INTA }, /* PCI Slot J5 */
{ INTE, INTE, INTE, INTE }, /* P2P Bridge */
};
static int __init
iq80310_sec_map_irq(struct pci_dev *dev, u8 idsel, u8 pin)
{
irq_table *pci_irq_table;
BUG_ON(pin < 1 || pin > 4);
if (!system_rev) {
pci_irq_table = pci_sec_d_irq_table;
} else {
pci_irq_table = pci_sec_f_irq_table;
}
return PCI_IRQ_TABLE_LOOKUP(0, 2);
}
static int iq80310_pri_host;
static int iq80310_setup(int nr, struct pci_sys_data *sys)
{
switch (nr) {
case 0:
if (!iq80310_pri_host)
return 0;
sys->map_irq = iq80310_pri_map_irq;
break;
case 1:
sys->map_irq = iq80310_sec_map_irq;
break;
default:
return 0;
}
return iop310_setup(nr, sys);
}
static void iq80310_preinit(void)
{
iq80310_pri_host = *(volatile u32 *)IQ80310_BACKPLANE & 1;
printk(KERN_INFO "PCI: IQ80310 is a%s\n",
iq80310_pri_host ? " system controller" : "n agent");
iop310_init();
}
static struct hw_pci iq80310_pci __initdata = {
.swizzle = pci_std_swizzle,
.nr_controllers = 2,
.setup = iq80310_setup,
.scan = iop310_scan_bus,
.preinit = iq80310_preinit,
};
static int __init iq80310_pci_init(void)
{
if (machine_is_iq80310())
pci_common_init(&iq80310_pci);
return 0;
}
subsys_initcall(iq80310_pci_init);
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -207,7 +207,7 @@ void __init ixp4xx_init_irq(void) ...@@ -207,7 +207,7 @@ void __init ixp4xx_init_irq(void)
static unsigned volatile last_jiffy_time; static unsigned volatile last_jiffy_time;
#define CLOCK_TICKS_PER_USEC (CLOCK_TICK_RATE / USEC_PER_SEC) #define CLOCK_TICKS_PER_USEC ((CLOCK_TICK_RATE + USEC_PER_SEC/2) / USEC_PER_SEC)
/* IRQs are disabled before entering here from do_gettimeofday() */ /* IRQs are disabled before entering here from do_gettimeofday() */
static unsigned long ixp4xx_gettimeoffset(void) static unsigned long ixp4xx_gettimeoffset(void)
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment