Before I get into the review of this patch, I would like to
make a comment on the overall size of changes. This patch
would have been easier to review if it was smaller, such
as core changes, then other core items (such as dma) and
then any driver changes.
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 5c79519..7fb09d5 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -322,6 +322,12 @@ config ARCH_S3C2410
BAST (), the IPAQ 1940 or
the Samsung SMDK2410 development board (and derivatives).
+config MACH_S3C24A0
+ bool "Samsung S3C24A0"
+ help
+ select ISA
+ Samsung S3C24A0 based systems.
+ Samsung SMDK24A0 development board & derivatives.
config ARCH_SHARK
bool "Shark"
select ISA
This should be ARCH_S3C24A0, the MACH_ are for machine implementations
@@ -378,6 +384,8 @@ source "arch/arm/mach-omap2/Kconfig"
source "arch/arm/mach-s3c2410/Kconfig"
+source "arch/arm/mach-s3c24a0/Kconfig"
+
source "arch/arm/mach-lh7a40x/Kconfig"
source "arch/arm/mach-imx/Kconfig"
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index 000f110..daa44b3 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -118,6 +118,7 @@ endif
machine-$(CONFIG_ARCH_OMAP2) := omap2
incdir-$(CONFIG_ARCH_OMAP) := omap
machine-$(CONFIG_ARCH_S3C2410) := s3c2410
+ machine-$(CONFIG_MACH_S3C24A0) := s3c24a0
machine-$(CONFIG_ARCH_LH7A40X) := lh7a40x
machine-$(CONFIG_ARCH_VERSATILE) := versatile
machine-$(CONFIG_ARCH_IMX) := imx
diff --git a/arch/arm/configs/s3c24a0initrd_defconfig b/arch/arm/configs/s3c24a0initrd_defconfig
new file mode 100644
index 0000000..bba1233
--- /dev/null
+++ b/arch/arm/configs/s3c24a0initrd_defconfig
@@ -0,0 +1,650 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.20
+# Fri Mar 2 19:16:20 2007
+#
+CONFIG_ARM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+# CONFIG_GENERIC_TIME is not set
+CONFIG_MMU=y
+# CONFIG_NO_IOPORT is not set
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_ZONE_DMA=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_UTS_NS is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_SYSFS_DEPRECATED=y
+# CONFIG_RELAY is not set
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_SLAB=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# Block layer
+#
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+
+#
+# System Type
+#
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_AT91 is not set
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CO285 is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_PNX4008 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+CONFIG_MACH_S3C24A0=y
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_OMAP is not set
+
+#
+# S3C24A0 Implementations
+#
+CONFIG_MACH_SMDK24A0=y
+CONFIG_CPU_S3C24A0=y
+
+#
+# S3C24A0 Setup
+#
+# CONFIG_S3C24A0_DMA is not set
+CONFIG_MACH_EVT3_SMDK24A0=y
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_ARM926T=y
+CONFIG_CPU_32v5=y
+CONFIG_CPU_ABRT_EV5TJ=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_COPY_V4WB=y
+CONFIG_CPU_TLB_V4WBI=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+
+#
+# Processor Features
+#
+# CONFIG_ARM_THUMB is not set
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
+# CONFIG_CPU_CACHE_ROUND_ROBIN is not set
+
+#
+# Bus support
+#
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+# CONFIG_PREEMPT is not set
+# CONFIG_NO_IDLE_HZ is not set
+CONFIG_HZ=100
+# CONFIG_AEABI is not set
+# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4096
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="root=/dev/hda1 ro init=/bin/bash console=ttySAC0"
+# CONFIG_XIP_KERNEL is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+CONFIG_FPE_NWFPE_XP=y
+CONFIG_FPE_FASTFPE=y
+CONFIG_VFP=y
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_AOUT=y
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_ARTHUR is not set
+
+#
+# Power management options
+#
+# CONFIG_PM is not set
+
+#
+# Networking
+#
+# CONFIG_NET is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+CONFIG_PARPORT=y
+# CONFIG_PARPORT_PC is not set
+# CONFIG_PARPORT_GSC is not set
+# CONFIG_PARPORT_AX88796 is not set
+CONFIG_PARPORT_1284=y
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=25600
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+# CONFIG_SCSI_NETLINK is not set
+
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+# CONFIG_ATA is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# ISDN subsystem
+#
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_SERIAL_NONSTANDARD=y
+# CONFIG_ROCKETPORT is not set
+# CONFIG_CYCLADES is not set
+# CONFIG_DIGIEPCA is not set
+# CONFIG_MOXA_INTELLIO is not set
+# CONFIG_MOXA_SMARTIO is not set
+# CONFIG_SYNCLINKMP is not set
+# CONFIG_N_HDLC is not set
+# CONFIG_RISCOM8 is not set
+# CONFIG_SPECIALIX is not set
+# CONFIG_RIO is not set
+# CONFIG_STALDRV is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_S3C24A0=y
+CONFIG_SERIAL_S3C24A0_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_PRINTER is not set
+# CONFIG_PPDEV is not set
+# CONFIG_TIPAR is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_NVRAM is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+# CONFIG_HWMON is not set
+# CONFIG_HWMON_VID is not set
+
+#
+# Misc devices
+#
+
+#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+
+#
+# Graphics support
+#
+# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# HID Devices
+#
+# CONFIG_HID is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB_ARCH_HAS_EHCI is not set
+# CONFIG_USB is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# Real Time Clock
+#
+CONFIG_RTC_LIB=y
+# CONFIG_RTC_CLASS is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_EXT4DEV_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_INOTIFY is not set
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_CRAMFS=y
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_LOG_BUF_SHIFT=16
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+CONFIG_DEBUG_MUTEXES=y
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_LIST is not set
+CONFIG_FRAME_POINTER=y
+CONFIG_FORCED_INLINING=y
+# CONFIG_RCU_TORTURE_TEST is not set
+CONFIG_DEBUG_USER=y
+# CONFIG_DEBUG_ERRORS is not set
+CONFIG_DEBUG_LL=y
+# CONFIG_DEBUG_ICEDCC is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
diff --git a/arch/arm/mach-s3c24a0/Kconfig b/arch/arm/mach-s3c24a0/Kconfig
new file mode 100644
index 0000000..b0b11b3
--- /dev/null
+++ b/arch/arm/mach-s3c24a0/Kconfig
@@ -0,0 +1,37 @@
+if MACH_S3C24A0
+menu "S3C24A0 Implementations"
+
+config MACH_SMDK24A0
+ bool "SMDK24A0"
+ select CPU_S3C24A0
+ help
+ Say Y here if you are using the SMDK24A0 board
+
+endmenu
+
+config CPU_S3C24A0
+ bool
+ depends on MACH_S3C24A0
+ help
+ Support for S3C24A0 and S3C24A0A family from the S3C24XX line
+ of Samsung Mobile CPUs.
+
+comment "S3C24A0 Setup"
+
+config S3C24A0_DMA
+ bool "S3C24A0 DMA support"
+ depends on MACH_S3C24A0
+ help
+ S3C24A0 DMA support. This is needed for drivers like sound which
+ use the S3C24A0's DMA system to move data to and from the
+ peripheral blocks.
+
+config MACH_EVT3_SMDK24A0
+ bool "SMDK24A0A(Meritech Board) above 1.0"
+ depends on MACH_SMDK24A0
+ help
+ Say Y here if you are using the new EVT3 SMDK board
+ above version 1.0
+
+
+endif
diff --git a/arch/arm/mach-s3c24a0/Makefile b/arch/arm/mach-s3c24a0/Makefile
new file mode 100644
index 0000000..9f85308
--- /dev/null
+++ b/arch/arm/mach-s3c24a0/Makefile
@@ -0,0 +1,24 @@
+
+#
+# Makefile for the linux kernel.
+#
+
+# Object file lists.
+
+obj-y := cpu.o irq.o time.o clock.o devs.o gpio.o leds-smdk.o
+obj-m :=
+obj-n :=
+obj- :=
+
+# S3C24A0 support files
+
+obj-$(CONFIG_CPU_S3C24A0) += s3c24a0.o
+obj-$(CONFIG_S3C24A0_DMA) += dma.o
+
+# Power Management support
+
+obj-$(CONFIG_PM) += pm.o sleep.o
+
+# machine specific support
+
+obj-$(CONFIG_MACH_SMDK24A0) += mach-smdk24a0.o
diff --git a/arch/arm/mach-s3c24a0/Makefile.boot b/arch/arm/mach-s3c24a0/Makefile.boot
new file mode 100644
index 0000000..61a3495
--- /dev/null
+++ b/arch/arm/mach-s3c24a0/Makefile.boot
@@ -0,0 +1,3 @@
+ zreladdr-y := 0x10008000
+params_phys-y := 0x10000100
+
diff --git a/arch/arm/mach-s3c24a0/clock.c b/arch/arm/mach-s3c24a0/clock.c
new file mode 100644
index 0000000..78467fe
--- /dev/null
+++ b/arch/arm/mach-s3c24a0/clock.c
@@ -0,0 +1,522 @@
+/* linux/arch/arm/mach-s3c24a0/clock.c
+ *
+ * S3C24a0 Clock control support
+ *
+ * $Id: clock.c,v 1.1.1.1 2006/02/13 05:22:49 ihlee215 Exp $
+ *
+ * Copyright (C) 2005, Sean Choi
+ * All rights reserved.
+ *
Firstly, there is what looks like an RCS/CVS ID in this, which
should not be leaking out.
Secondly, this code looks an awful lot like the original s3c2410.c
that I would like my copyright kept in this file (you can add your
own copyright, but leave mine intact please).
Thirdly, if this is to be submitted, then the multiple authours of
this patch is a good reason to split the submissions.
+ * 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.
+ *
+ * derived from linux/arch/arm/mach-s3c2410/clock.c, written by
+ * Ben Dooks
+ *
+ * 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
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+
+#include
+#include
+#include
+#include
+
+//#include
+#include
+
+#include "clock.h"
+
+/* clock information */
+
+unsigned long s3c24xx_xtal = 12*1000*1000; /* default 12MHz */
+unsigned long s3c24xx_fclk;
+unsigned long s3c24xx_hclk;
+unsigned long s3c24xx_pclk;
+
+static LIST_HEAD(clocks);
+static DECLARE_MUTEX(clocks_sem);
+
+
+/* old functions */
+
+void inline s3c24a0_clk_enable(unsigned int clocks, unsigned int enable)
+{
+ unsigned long clkcon;
+ unsigned long flags;
+
+ local_irq_save(flags);
+
+ clkcon = __raw_readl(S3C24A0_CLKCON);
+ clkcon &= ~clocks;
+
+ if (enable)
+ clkcon |= clocks;
+
+ /* ensure none of the special function bits set */
+ clkcon &= ~(S3C24A0_CLKCON_STOP|S3C24A0_CLKCON_IDLE|S3C24A0_CLKCON_MON);
+
+ __raw_writel(clkcon, S3C24A0_CLKCON);
+
+ local_irq_restore(flags);
+}
+
+/* enable and disable calls for use with the clk struct */
+
+static int clk_null_enable(struct clk *clk, int enable)
+{
+ return 0;
+}
+
+int s3c24a0_clkcon_enable(struct clk *clk, int enable)
+{
+ s3c24a0_clk_enable(clk->ctrlbit, enable);
+ return 0;
+}
+
+/* Clock API calls */
+
+struct clk *clk_get(struct device *dev, const char *id)
+{
+ struct clk *p;
+ struct clk *clk = ERR_PTR(-ENOENT);
+ int idno;
+
+ idno = (dev == NULL) ? -1 : to_platform_device(dev)->id;
+
+ down(&clocks_sem);
+
+ list_for_each_entry(p, &clocks, list) {
+ if (p->id == idno &&
+ strcmp(id, p->name) == 0 &&
+ try_module_get(p->owner)) {
+ clk = p;
+ break;
+ }
+ }
+
+ /* check for the case where a device was supplied, but the
+ * clock that was being searched for is not device specific */
+
+ if (IS_ERR(clk)) {
+ list_for_each_entry(p, &clocks, list) {
+ if (p->id == -1 && strcmp(id, p->name) == 0 &&
+ try_module_get(p->owner)) {
+ clk = p;
+ break;
+ }
+ }
+ }
+
+ up(&clocks_sem);
+ return clk;
+}
+
+void clk_put(struct clk *clk)
+{
+ module_put(clk->owner);
+}
+
+int clk_enable(struct clk *clk)
+{
+ if (IS_ERR(clk))
+ return -EINVAL;
+
+ return (clk->enable)(clk, 1);
+}
+
+void clk_disable(struct clk *clk)
+{
+ if (!IS_ERR(clk))
+ (clk->enable)(clk, 0);
+}
+
+
+int clk_use(struct clk *clk)
+{
+ atomic_inc(&clk->used);
+ return 0;
+}
+
+
+void clk_unuse(struct clk *clk)
+{
+ atomic_dec(&clk->used);
+}
+
+unsigned long clk_get_rate(struct clk *clk)
+{
+ if (IS_ERR(clk))
+ return 0;
+
+ if (clk->rate != 0)
+ return clk->rate;
+
+ while (clk->parent != NULL && clk->rate == 0)
+ clk = clk->parent;
+
+ return clk->rate;
+}
+
+long clk_round_rate(struct clk *clk, unsigned long rate)
+{
+ return rate;
+}
+
+int clk_set_rate(struct clk *clk, unsigned long rate)
+{
+ return -EINVAL;
+}
+
+struct clk *clk_get_parent(struct clk *clk)
+{
+ return clk->parent;
+}
+
+EXPORT_SYMBOL(clk_get);
+EXPORT_SYMBOL(clk_put);
+EXPORT_SYMBOL(clk_enable);
+EXPORT_SYMBOL(clk_disable);
+EXPORT_SYMBOL(clk_use);
+EXPORT_SYMBOL(clk_unuse);
+EXPORT_SYMBOL(clk_get_rate);
+EXPORT_SYMBOL(clk_round_rate);
+EXPORT_SYMBOL(clk_set_rate);
+EXPORT_SYMBOL(clk_get_parent);
+
+/* base clocks */
+
+static struct clk clk_f = {
+ .name = "fclk",
+ .id = -1,
+ .rate = 0,
+ .parent = NULL,
+ .ctrlbit = 0,
+};
+
+static struct clk clk_h = {
+ .name = "hclk",
+ .id = -1,
+ .rate = 0,
+ .parent = NULL,
+ .ctrlbit = 0,
+};
+
+static struct clk clk_p = {
+ .name = "pclk",
+ .id = -1,
+ .rate = 0,
+ .parent = NULL,
+ .ctrlbit = 0,
+};
+
+static struct clk clk_u = {
+ .name = "uclk",
+ .id = -1,
+ .rate = 0,
+ .parent = NULL,
+ .ctrlbit = 0,
+};
+
+static struct clk clk_m = {
+ .name = "mpegclk",
+ .id = -1,
+ .rate = 0,
+ .parent = NULL,
+ .ctrlbit = 0,
+};
+
+/* clocks that could be registered by external code */
+
+struct clk s3c24xx_dclk0 = {
+ .name = "dclk0",
+ .id = -1,
+};
+
+struct clk s3c24xx_dclk1 = {
+ .name = "dclk1",
+ .id = -1,
+};
+
+struct clk s3c24xx_clkout0 = {
+ .name = "clkout0",
+ .id = -1,
+};
+
+struct clk s3c24xx_clkout1 = {
+ .name = "clkout1",
+ .id = -1,
+};
+
+struct clk s3c24xx_uclk = {
+ .name = "uclk",
+ .id = -1,
+};
+
+
+/* clock definitions */
+
+static struct clk init_clocks[] = {
+ { .name = "irda",
+ .id = -1,
+ .parent = &clk_u,
+ .enable = s3c24a0_clkcon_enable,
+ .ctrlbit = S3C24A0_CLKCON_IrDA
+ },
+ { .name = "ac97",
+ .id = -1,
+ .parent = &clk_u,
+ .enable = s3c24a0_clkcon_enable,
+ .ctrlbit = S3C24A0_CLKCON_AC97
+ },
+ { .name = "usb-host",
+ .id = -1,
+ .parent = &clk_h,
+ .enable = s3c24a0_clkcon_enable,
+ .ctrlbit = S3C24A0_CLKCON_USBH
+ },
+ { .name = "timers",
+ .parent = &clk_p,
+ .enable = s3c24a0_clkcon_enable,
+ .ctrlbit = S3C24A0_CLKCON_PWM
+ },
+ { .name = "uart",
+ .id = 0,
+ .parent = &clk_p,
+ .enable = s3c24a0_clkcon_enable,
+ .ctrlbit = S3C24A0_CLKCON_UART0
+ },
+ { .name = "irda",
+ .id = 1,
+ .parent = &clk_p,
+ .enable = s3c24a0_clkcon_enable,
+ .ctrlbit = S3C24A0_CLKCON_UART1
+ },
+ { .name = "spi",
+ .id = -1,
+ .parent = &clk_p,
+ .enable = s3c24a0_clkcon_enable,
+ .ctrlbit = S3C24A0_CLKCON_SPI
+ },
+ { .name = "i2c",
+ .id = -1,
+ .parent = &clk_p,
+ .enable = s3c24a0_clkcon_enable,
+ .ctrlbit = S3C24A0_CLKCON_IIC
+ },
+ { .name = "iis",
+ .id = -1,
+ .parent = &clk_p,
+ .enable = s3c24a0_clkcon_enable,
+ .ctrlbit = S3C24A0_CLKCON_IIS
+ },
+ { .name = "gpio",
+ .id = -1,
+ .parent = &clk_p,
+ .enable = s3c24a0_clkcon_enable,
+ .ctrlbit = S3C24A0_CLKCON_GPIO
+ },
+ { .name = "usb-device",
+ .id = -1,
+ .parent = &clk_p,
+ .enable = s3c24a0_clkcon_enable,
+ .ctrlbit = S3C24A0_CLKCON_USBD
+ },
+ { .name = "ms-stick",
+ .id = -1,
+ .parent = &clk_p,
+ .enable = s3c24a0_clkcon_enable,
+ .ctrlbit = S3C24A0_CLKCON_MS
+ },
+ { .name = "sdi",
+ .id = -1,
+ .parent = &clk_p,
+ .enable = s3c24a0_clkcon_enable,
+ .ctrlbit = S3C24A0_CLKCON_SDI
+ },
+ { .name = "adc",
+ .id = -1,
+ .parent = &clk_p,
+ .enable = s3c24a0_clkcon_enable,
+ .ctrlbit = S3C24A0_CLKCON_ADC
+ },
+ { .name = "keypad",
+ .id = -1,
+ .parent = &clk_p,
+ .enable = s3c24a0_clkcon_enable,
+ .ctrlbit = S3C24A0_CLKCON_KEYPAD
+ },
+ { .name = "mpeg4",
+ .id = -1,
+ .parent = &clk_m,
+ .enable = s3c24a0_clkcon_enable,
+ .ctrlbit = S3C24A0_CLKCON_MPEG4
+ },
+ { .name = "camif",
+ .id = -1,
+ .parent = &clk_h,
+ .enable = s3c24a0_clkcon_enable,
+ .ctrlbit = S3C24A0_CLKCON_CAM_HCLK
+ },
+ { .name = "lcd",
+ .id = -1,
+ .parent = &clk_h,
+ .enable = s3c24a0_clkcon_enable,
+ .ctrlbit = S3C24A0_CLKCON_LCD
+ },
+ { .name = "cam",
+ .id = -1,
+ .parent = &clk_u,
+ .enable = s3c24a0_clkcon_enable,
+ .ctrlbit = S3C24A0_CLKCON_CAM_UPLL
+ },
+ { .name = "mpeg4if",
+ .id = -1,
+ .parent = &clk_h,
+ .enable = s3c24a0_clkcon_enable,
+ .ctrlbit = S3C24A0_CLKCON_MPEG4IF
+ },
+ { .name = "vpostif",
+ .id = -1,
+ .parent = &clk_h,
+ .enable = s3c24a0_clkcon_enable,
+ .ctrlbit = S3C24A0_CLKCON_VPOSTIF
+ },
+ { .name = "s3c24a0-wdt",
+ .id = -1,
+ .parent = &clk_p,
+ .enable = s3c24a0_clkcon_enable,
+ .ctrlbit = S3C24A0_CLKCON_WDT
+ }
+#if 0 //,
+ { .name = "mpegdctq",
+ .id = -1,
+ .parent = &clk_m,
+ .enable = s3c24a0_clkcon_enable,
+ .ctrlbit = CLKCON_MPEGDCTQ
+ },
+ { .name = "vpost",
+ .id = -1,
+ .parent = &clk_m,
+ .enable = s3c24a0_clkcon_enable,
+ .ctrlbit = CLKCON_VPOST
+ },
+ { .name = "vlx",
+ .id = -1,
+ .parent = &clk_h,
+ .enable = s3c24a0_clkcon_enable,
+ .ctrlbit = CLKCON_VLX
+ }
+#endif
+};
+
+/* initialise the clock system */
+
+int s3c24a0_register_clock(struct clk *clk)
+{
+ clk->owner = THIS_MODULE;
+ atomic_set(&clk->used, 0);
+
+ if (clk->enable == NULL)
+ clk->enable = clk_null_enable;
+
+ /* add to the list of available clocks */
+
+ down(&clocks_sem);
+ list_add(&clk->list, &clocks);
+ up(&clocks_sem);
+
+ return 0;
+}
+
+/* initalise all the clocks */
+
+int __init s3c24a0_init_clocks(void)
+{
+ struct clk *clkp = init_clocks;
+ int ptr;
+ int ret;
+
+ printk(KERN_INFO "S3C24A0 Clock control, (c) 2005 Samsung Electronics\n");
+
+ /* initialise the main system clocks */
+
+ clk_h.rate = s3c24xx_hclk;
+ clk_p.rate = s3c24xx_pclk;
+ clk_f.rate = s3c24xx_fclk;
+
+ /* it looks like just setting the register here is not good
+ * enough, and causes the odd hang at initial boot time, so
+ * do all of them indivdually.
+ *
+ * I think disabling the LCD clock if the LCD is active is
+ * very dangerous, and therefore the bootloader should be
+ * careful to not enable the LCD clock if it is not needed.
+ *
+ * and of course, this looks neater
+ */
+
+ __raw_writel(((56 << 12) | ( 2 << 4) | 1), S3C24A0_UPLLCON);
+
+ s3c24a0_clk_enable(S3C24A0_CLKCON_PWM, 1);
+ s3c24a0_clk_enable(S3C24A0_CLKCON_USBH, 1);
+ s3c24a0_clk_enable(S3C24A0_CLKCON_USBD, 1);
+ s3c24a0_clk_enable(S3C24A0_CLKCON_ADC, 1);
+ s3c24a0_clk_enable(S3C24A0_CLKCON_IIC, 1);
+ s3c24a0_clk_enable(S3C24A0_CLKCON_SPI, 1);
+ s3c24a0_clk_enable(S3C24A0_CLKCON_AC97, 1);
+ s3c24a0_clk_enable(S3C24A0_CLKCON_LCD, 1);
+ s3c24a0_clk_enable(S3C24A0_CLKCON_SDI, 1);
+ s3c24a0_clk_enable(S3C24A0_CLKCON_UART1, 1);
+ s3c24a0_clk_enable(S3C24A0_CLKCON_IrDA, 1);
+
+ /* assume uart clocks are correctly setup */
+
+ /* register our clocks */
+
+ if (s3c24a0_register_clock(&clk_f) < 0)
+ printk(KERN_ERR "failed to register cpu fclk\n");
+
+ if (s3c24a0_register_clock(&clk_h) < 0)
+ printk(KERN_ERR "failed to register cpu hclk\n");
+
+ if (s3c24a0_register_clock(&clk_p) < 0)
+ printk(KERN_ERR "failed to register cpu pclk\n");
+
+ if (s3c24a0_register_clock(&clk_u) < 0)
+ printk(KERN_ERR "failed to register cpu uclk\n");
+
+ if (s3c24a0_register_clock(&clk_m) < 0)
+ printk(KERN_ERR "failed to register cpu mpegclk\n");
+
+ for (ptr = 0; ptr < ARRAY_SIZE(init_clocks); ptr++, clkp++) {
+ ret = s3c24a0_register_clock(clkp);
+ if (ret < 0) {
+ printk(KERN_ERR "Failed to register clock %s (%d)\n",
+ clkp->name, ret);
+ }
+ }
+
+ return 0;
+}
+
+
diff --git a/arch/arm/mach-s3c24a0/clock.h b/arch/arm/mach-s3c24a0/clock.h
new file mode 100644
index 0000000..c212d74
--- /dev/null
+++ b/arch/arm/mach-s3c24a0/clock.h
@@ -0,0 +1,52 @@
+/*
+ * linux/arch/arm/mach-s3c24a0/clock.h
+ *
+ * $Id: clock.h,v 1.1.1.1 2006/02/13 05:22:49 ihlee215 Exp $
+ *
+ * Copyright (C) 2005, Sean Choi
+ * All rights reserved.
+ *
+ * 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.
+ *
+ * derived from linux/arch/arm/mach-s3c2410/clock.h, written by
+ * Ben Dooks
+ */
Again the same comment, the changes for plat-s3c24xx means these
items should be sharable.
+struct clk {
+ struct list_head list;
+ struct module *owner;
+ struct clk *parent;
+ const char *name;
+ int id;
+ atomic_t used;
+ unsigned long rate;
+ unsigned long ctrlbit;
+ int (*enable)(struct clk *, int enable);
+};
+
+/* other clocks which may be registered by board support */
+
+extern struct clk s3c24xx_dclk0;
+extern struct clk s3c24xx_dclk1;
+extern struct clk s3c24xx_clkout0;
+extern struct clk s3c24xx_clkout1;
+extern struct clk s3c24xx_uclk;
+
+/* processor clock settings, in Hz */
+
+extern unsigned long s3c24xx_xtal;
+extern unsigned long s3c24xx_pclk;
+extern unsigned long s3c24xx_hclk;
+extern unsigned long s3c24xx_fclk;
+
+/* exports for arch/arm/mach-s3c2410
+ *
+ * Please DO NOT use these outside of arch/arm/mach-s3c2410
+*/
+
+extern int s3c24a0_clkcon_enable(struct clk *clk, int enable);
+extern int s3c24a0_register_clock(struct clk *clk);
+extern int s3c24a0_init_clocks(void);
+
diff --git a/arch/arm/mach-s3c24a0/cpu.c b/arch/arm/mach-s3c24a0/cpu.c
new file mode 100644
index 0000000..fe81063
--- /dev/null
+++ b/arch/arm/mach-s3c24a0/cpu.c
@@ -0,0 +1,165 @@
+/* linux/arch/arm/mach-s3c24a0/cpu.c
+ *
+ * $Id: cpu.c,v 1.1.1.1 2006/02/13 05:22:49 ihlee215 Exp $
+ *
+ * Copyright (C) 2005, Sean Choi
+ * All rights reserved.
Is this your patch or something that samsung have put out?
+ * S3C24A0 CPU Support
+ *
+ * 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
+ *
+ * derived from linux/arch/arm/mach-s3c2410/cpu.c, written by
+ * Ben Dooks
+ *
+*/
+
+
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+
+#include
+#include
+
+#include
+
+#include "cpu.h"
+#include "clock.h"
+#include "s3c24a0.h"
+
+struct cpu_table {
+ unsigned long idcode;
+ unsigned long idmask;
+ void (*map_io)(struct map_desc *mach_desc, int size);
+ int (*init)(void);
+ const char *name;
+};
+
+/* table of supported CPUs */
+
+static const char name_s3c24a0[] = "S3C24A0";
+
+static struct cpu_table cpu_ids[] __initdata = {
+ {
+ .idcode = 0x324a0000,
+ .idmask = 0xffffffff,
+ .map_io = s3c24a0_map_io,
+ .init = s3c24a0_init,
+ .name = name_s3c24a0
+ }
+};
+
+static struct cpu_table *
+s3c_lookup_cpu(unsigned long idcode)
+{
+ struct cpu_table *tab;
+ int count;
+
+ tab = cpu_ids;
+ for (count = 0; count < ARRAY_SIZE(cpu_ids); count++, tab++) {
+ if ((idcode & tab->idmask) == tab->idcode)
+ return tab;
+ }
+
+ return NULL;
+}
+
+/* board information */
+
+static struct s3c24xx_board *board;
+
+void s3c24xx_set_board(struct s3c24xx_board *b)
+{
+ int i;
+
+ board = b;
+
+ if (b->clocks_count != 0) {
+ struct clk **ptr = b->clocks;;
+
+ for (i = b->clocks_count; i > 0; i--, ptr++)
+ s3c24a0_register_clock(*ptr);
+ }
+}
+
+/* cpu information */
+
+static struct cpu_table *cpu;
+
+void __init s3c24xx_init_io(struct map_desc *mach_desc, int size)
+{
+ unsigned long idcode;
+
+#if 1 // swlab choish there is no chip id of S3C24A0
+ idcode = 0x324a0000;
+ cpu = s3c_lookup_cpu(idcode);
+
+ if (cpu == NULL) {
+ printk(KERN_ERR "Unknown CPU type 0x%08lx\n", idcode);
+ panic("Unknown S3C24XX CPU");
+ }
+#endif
+ if (cpu->map_io == NULL || cpu->init == NULL) {
+ printk(KERN_ERR "CPU %s support not enabled\n", cpu->name);
+ panic("Unsupported S3C24XX CPU");
+ }
+
+ printk("CPU %s (id 0x%08lx)\n", cpu->name, idcode);
+
+ (cpu->map_io)(mach_desc, size);
+}
+
+static int __init s3c_arch_init(void)
+{
+ int ret;
+
+ // do the correct init for cpu
+
+ if (cpu == NULL)
+ panic("s3c_arch_init: NULL cpu\n");
+
+ ret = (cpu->init)();
+ if (ret != 0)
+ return ret;
+
+ if (board != NULL) {
+ struct platform_device **ptr = board->devices;
+ int i;
+
+ for (i = 0; i < board->devices_count; i++, ptr++) {
+ ret = platform_device_register(*ptr);
+
+ if (ret) {
+ printk(KERN_ERR "s3c24xx: failed to add board device %s (%d) @%p--%d\n", (*ptr)->name, ret, *ptr,i);
+ }
+ }
+
+ /* mask any error, we may not need all these board
+ * devices */
+ ret = 0;
+ }
+
+ return ret;
+}
+
+arch_initcall(s3c_arch_init);
Again, see comments on code sharing...
diff --git a/arch/arm/mach-s3c24a0/cpu.h b/arch/arm/mach-s3c24a0/cpu.h
new file mode 100644
index 0000000..61e8b56
--- /dev/null
+++ b/arch/arm/mach-s3c24a0/cpu.h
@@ -0,0 +1,52 @@
+/* arch/arm/mach-s3c24a0/cpu.h
+ *
+ * Copyright (c) 2004 Simtec Electronics
+ * Ben Dooks
+ *
+ * Header file for S3C24XX CPU support
+ *
+ * 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.
+ *
+ * Modifications:
+ * 24-Aug-2004 BJD Start of generic S3C24XX support
+ * 18-Oct-2004 BJD Moved board struct into this file
+*/
+
+#define IODESC_ENT(x) { S3C24A0_VA_##x, S3C24A0_PA_##x, S3C24A0_SZ_##x, MT_DEVICE }
+
+#ifndef MHZ
+#define MHZ (1000*1000)
+#endif
+
+#define print_mhz(m) ((m) / MHZ), ((m / 1000) % 1000)
+
+#ifdef CONFIG_CPU_S3C24A0
+extern int s3c24a0_init(void);
+extern void s3c24a0_map_io(struct map_desc *mach_desc, int size);
+#else
+#define s3c24a0_map_io NULL
+#define s3c24a0_init NULL
+#endif
+
+
+extern void s3c24xx_init_io(struct map_desc *mach_desc, int size);
+
+/* the board structure is used at first initialsation time
+ * to get info such as the devices to register for this
+ * board. This is done because platfrom_add_devices() cannot
+ * be called from the map_io entry.
+*/
+
+struct s3c24xx_board {
+ struct platform_device **devices;
+ unsigned int devices_count;
+
+ struct clk **clocks;
+ unsigned int clocks_count;
+};
+
+extern void s3c24xx_set_board(struct s3c24xx_board *board);
+
+
As noticed before, the board struct is going away.
diff --git a/arch/arm/mach-s3c24a0/devs.c b/arch/arm/mach-s3c24a0/devs.c
new file mode 100644
index 0000000..fe5e244
--- /dev/null
+++ b/arch/arm/mach-s3c24a0/devs.c
@@ -0,0 +1,529 @@
+/* linux/arch/arm/mach-s3c24a0/devs.c
+ *
+ * $Id: devs.c,v 1.1.1.1 2006/02/13 05:22:49 ihlee215 Exp $
+ *
+ * Copyright (C) 2005, Sean Choi
+ * All rights reserved.
a repeat of the comments above can go here.
+ * Base S3C24A0 platform device definitions
+ *
+ * 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.
+ *
+ * derived from linux/arch/arm/mach-s3c2410/devs.c, written by
+ * Ben Dooks
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+
+#include
+
+#include "devs.h"
+
+/* Serial port registrations */
+
+struct platform_device *s3c24xx_uart_devs[2]; /* UART0, UART1 total 2 channel port */
+
+/* USB Host Controller */
+
+static struct resource s3c_usb_resource[] = {
+ [0] = {
+ .start = S3C24A0_PA_USBHOST,
+ .end = S3C24A0_PA_USBHOST + S3C24A0_SZ_USBHOST,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_USBH,
+ .end = IRQ_USBH,
+ .flags = IORESOURCE_IRQ,
+ }
+};
+
+static u64 s3c_device_usb_dmamask = 0xffffffffUL;
+
+struct platform_device s3c_device_usb = {
+ .name = "s3c24a0-ohci",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(s3c_usb_resource),
+ .resource = s3c_usb_resource,
+ .dev = {
+ .dma_mask = &s3c_device_usb_dmamask,
+ .coherent_dma_mask = 0xffffffffUL
+ }
+};
+
+EXPORT_SYMBOL(s3c_device_usb);
+
+/* LCD Controller */
+static struct s3c24a0fb_mach_info s3c24a0fb_info;
+
+void __init set_s3c24a0fb_info(struct s3c24a0fb_mach_info *hard_s3c24a0fb_info)
+{
+ memcpy(&s3c24a0fb_info,hard_s3c24a0fb_info,sizeof(struct s3c24a0fb_mach_info));
+}
+EXPORT_SYMBOL(set_s3c24a0fb_info);
Exporting an __init marked symbol is dangerous, this will have been
deleted before anything that can use it will be able to be loaded.
I intend on changing these initialisations in the next kernel change.
+
+static struct resource s3c_lcd_resource[] = {
+ [0] = {
+ .start = S3C24A0_PA_LCD,
+ .end = S3C24A0_PA_LCD + S3C24A0_SZ_LCD,
+ .flags = IORESOURCE_IO,
+// .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_LCD_POST,
+ .end = IRQ_LCD_POST,
+ .flags = IORESOURCE_IRQ,
+ }
+
+};
+
+static u64 s3c_device_lcd_dmamask = 0xffffffffUL;
+
+struct platform_device s3c_device_lcd = {
+ .name = "s3c24a0-lcd",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(s3c_lcd_resource),
+ .resource = s3c_lcd_resource,
+ .dev = {
+ .platform_data = &s3c24a0fb_info,
+ .dma_mask = &s3c_device_lcd_dmamask,
+ .coherent_dma_mask = 0xffffffffUL
+ }
+};
+
+EXPORT_SYMBOL(s3c_device_lcd);
+
+/* NAND Controller */
+
+static struct resource s3c_nand_resource[] = {
+ [0] = {
+ .start = S3C24A0_PA_NAND,
+ .end = S3C24A0_PA_NAND + S3C24A0_SZ_NAND,
+ .flags = IORESOURCE_MEM,
+ }
+};
+
+struct platform_device s3c_device_nand = {
+ .name = "s3c24a0-nand",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(s3c_nand_resource),
+ .resource = s3c_nand_resource,
+};
+
+void s3c_set_flash_data(struct s3c24a0_platform_nand *flash)
+{
+ s3c_device_nand.dev.platform_data = flash;
+};
+
+EXPORT_SYMBOL(s3c_device_nand);
+EXPORT_SYMBOL(s3c_set_flash_data);
+
+/* USB Device (Gadget)*/
+
+static struct resource s3c_usbgadget_resource[] = {
+ [0] = {
+ .start = S3C24A0_PA_USBDEV,
+ .end = S3C24A0_PA_USBDEV + S3C24A0_SZ_USBDEV,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_USBD,
+ .end = IRQ_USBD,
+ .flags = IORESOURCE_IRQ,
+ }
+
+};
+
+struct platform_device s3c_device_udc = {
+ .name = "s3c24a0_udc",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(s3c_usbgadget_resource),
+ .resource = s3c_usbgadget_resource,
+};
+
+EXPORT_SYMBOL(s3c_device_udc);
+
+/* Watchdog */
+
+static struct resource s3c_wdt_resource[] = {
+ [0] = {
+ .start = S3C24A0_PA_WATCHDOG,
+ .end = S3C24A0_PA_WATCHDOG + S3C24A0_SZ_WATCHDOG,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_WDT,
+ .end = IRQ_WDT,
+ .flags = IORESOURCE_IRQ,
+ }
+
+};
+
+struct platform_device s3c_device_wdt = {
+ .name = "s3c24a0-wdt",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(s3c_wdt_resource),
+ .resource = s3c_wdt_resource,
+};
+
+EXPORT_SYMBOL(s3c_device_wdt);
+
+/* I2C */
+
+static struct resource s3c_i2c_resource[] = {
+ [0] = {
+ .start = S3C24A0_PA_IIC,
+ .end = S3C24A0_PA_IIC + 0x1000,//overlap with IIS space
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_IIC,
+ .end = IRQ_IIC,
+ .flags = IORESOURCE_IRQ,
+ }
+
+};
+
+
+struct platform_device s3c_device_i2c = {
+ .name = "s3c24a0-i2c",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(s3c_i2c_resource),
+ .resource = s3c_i2c_resource,
+};
+
+EXPORT_SYMBOL(s3c_device_i2c);
+
+/* IIS */
+
+static struct resource s3c_iis_resource[] = {
+ [0] = {
+ .start = S3C24A0_PA_IIS,
+ .end = S3C24A0_PA_IIS + S3C24A0_SZ_IIS,
+ .flags = IORESOURCE_MEM,
+ }
+};
+
+static u64 s3c_device_iis_dmamask = 0xffffffffUL;
+
+struct platform_device s3c_device_iis = {
+ .name = "elfin-iis",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(s3c_iis_resource),
+ .resource = s3c_iis_resource,
+ .dev = {
+ .dma_mask = &s3c_device_iis_dmamask,
+ .coherent_dma_mask = 0xffffffffUL
+ }
+};
+
+EXPORT_SYMBOL(s3c_device_iis);
+
+/* RTC */
+
+static struct resource s3c_rtc_resource[] = {
+ [0] = {
+ .start = S3C24A0_PA_RTC+0x4,
+ .end = S3C24A0_PA_RTC + 0xff,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_RTC,
+ .end = IRQ_RTC,
+ .flags = IORESOURCE_IRQ,
+ },
+
+ [2] = {
+ .start = IRQ_TICK,
+ .end = IRQ_TICK,
+ .flags = IORESOURCE_IRQ
+ }
+
+};
+
+struct platform_device s3c_device_rtc = {
+ .name = "s3c24a0-rtc",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(s3c_rtc_resource),
+ .resource = s3c_rtc_resource,
+};
+
+EXPORT_SYMBOL(s3c_device_rtc);
+
+/* ADC */
+static struct resource s3c_adc_resource[] = {
+ [0] = {
+ .start = S3C24A0_PA_ADC,
+ .end = S3C24A0_PA_ADC + S3C24A0_SZ_ADC,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_ADC,
+ .end = IRQ_ADC,
+ .flags = IORESOURCE_IRQ,
+ }
+
+};
+
+struct platform_device s3c_device_adc = {
+ .name = "s3c24a0-adc",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(s3c_adc_resource),
+ .resource = s3c_adc_resource,
+};
+
+
+/* SDI */
+
+static struct resource s3c_sdi_resource[] = {
+ [0] = {
+ .start = S3C24A0_PA_SDI,
+ .end = S3C24A0_PA_SDI + S3C24A0_SZ_SDI,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_SDI,
+ .end = IRQ_SDI,
+ .flags = IORESOURCE_IRQ,
+ }
+
+};
+
+struct platform_device s3c_device_sdi = {
+ .name = "s3c24a0-sdi",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(s3c_sdi_resource),
+ .resource = s3c_sdi_resource,
+};
+
+EXPORT_SYMBOL(s3c_device_sdi);
+
+/* SPI (0) */
+
+static struct resource s3c_spi0_resource[] = {
+ [0] = {
+ .start = S3C24A0_PA_SPI,
+ .end = S3C24A0_PA_SPI + 0x1f,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_SPI0,
+ .end = IRQ_SPI0,
+ .flags = IORESOURCE_IRQ,
+ }
+
+};
+
+struct platform_device s3c_device_spi0 = {
+ .name = "s3c24a0-spi",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(s3c_spi0_resource),
+ .resource = s3c_spi0_resource,
+};
+
+EXPORT_SYMBOL(s3c_device_spi0);
+
+/* SPI (1) */
+
+static struct resource s3c_spi1_resource[] = {
+ [0] = {
+ .start = S3C24A0_PA_SPI + 0x20,
+ .end = S3C24A0_PA_SPI + 0x20 + 0x1f,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_SPI1,
+ .end = IRQ_SPI1,
+ .flags = IORESOURCE_IRQ,
+ }
+
+};
+
+struct platform_device s3c_device_spi1 = {
+ .name = "s3c24a0-spi",
+ .id = 1,
+ .num_resources = ARRAY_SIZE(s3c_spi1_resource),
+ .resource = s3c_spi1_resource,
+};
+
+EXPORT_SYMBOL(s3c_device_spi1);
+
+/* pwm timer blocks */
+
+static struct resource s3c_timer0_resource[] = {
+ [0] = {
+ .start = S3C24A0_PA_TIMER + 0x0C,
+ .end = S3C24A0_PA_TIMER + 0x0C + 0xB,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_TIMER0,
+ .end = IRQ_TIMER0,
+ .flags = IORESOURCE_IRQ,
+ }
+
+};
+
+struct platform_device s3c_device_timer0 = {
+ .name = "s3c24a0-timer",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(s3c_timer0_resource),
+ .resource = s3c_timer0_resource,
+};
+
+EXPORT_SYMBOL(s3c_device_timer0);
+
+/* timer 1 */
+
+static struct resource s3c_timer1_resource[] = {
+ [0] = {
+ .start = S3C24A0_PA_TIMER + 0x18,
+ .end = S3C24A0_PA_TIMER + 0x23,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_TIMER1,
+ .end = IRQ_TIMER1,
+ .flags = IORESOURCE_IRQ,
+ }
+
+};
+
+struct platform_device s3c_device_timer1 = {
+ .name = "s3c24a0-timer",
+ .id = 1,
+ .num_resources = ARRAY_SIZE(s3c_timer1_resource),
+ .resource = s3c_timer1_resource,
+};
+
+EXPORT_SYMBOL(s3c_device_timer1);
+
+/* timer 2 */
+
+static struct resource s3c_timer2_resource[] = {
+ [0] = {
+ .start = S3C24A0_PA_TIMER + 0x24,
+ .end = S3C24A0_PA_TIMER + 0x2F,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_TIMER2,
+ .end = IRQ_TIMER2,
+ .flags = IORESOURCE_IRQ,
+ }
+
+};
+
+struct platform_device s3c_device_timer2 = {
+ .name = "s3c24a0-timer",
+ .id = 2,
+ .num_resources = ARRAY_SIZE(s3c_timer2_resource),
+ .resource = s3c_timer2_resource,
+};
+
+EXPORT_SYMBOL(s3c_device_timer2);
+
+/* timer 3 */
+
+static struct resource s3c_timer3_resource[] = {
+ [0] = {
+ .start = S3C24A0_PA_TIMER + 0x30,
+ .end = S3C24A0_PA_TIMER + 0x3B,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_TIMER3_4,
+ .end = IRQ_TIMER3_4,
+ .flags = IORESOURCE_IRQ,
+ }
+
+};
+
+struct platform_device s3c_device_timer3 = {
+ .name = "s3c24a0-timer",
+ .id = 3,
+ .num_resources = ARRAY_SIZE(s3c_timer3_resource),
+ .resource = s3c_timer3_resource,
+};
+
+
+// Irda
+
+
+static struct resource s3c_irda_resource[] = {
+ [0] = {
+ .start = S3C24A0_PA_IRDA,
+ .end = S3C24A0_PA_IRDA + 0x40,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = S3C24A0_PA_UART + 0x4000,
+ .end = S3C24A0_PA_UART + 0x4040,
+ .flags = IORESOURCE_MEM,
+ },
+ [2] = {
+ .start = IRQ_IRDA,
+ .end = IRQ_IRDA,
+ .flags = IORESOURCE_IRQ,
+ },
+ [3] = {
+ .start = IRQ_RXD1,
+ .end = IRQ_ERR1,
+ .flags = IORESOURCE_IRQ,
+ }
+
+};
+
+struct platform_device s3c_device_irda = {
+ .name = "s3c24a0-irda",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(s3c_irda_resource),
+ .resource = s3c_irda_resource,
+};
+
+EXPORT_SYMBOL(s3c_device_irda);
+
+/* KEYPAD */
+static struct resource s3c_keypad_resource[] = {
+ [0] = {
+ .start = S3C24A0_PA_KEYIF,
+ .end = S3C24A0_PA_KEYIF + 0xff,
+ .flags = IORESOURCE_MEM,
+ },
+
+ [1] = {
+ .start = IRQ_KEYPAD,
+ .end = IRQ_KEYPAD,
+ .flags = IORESOURCE_IRQ
+ }
+};
+
+struct platform_device s3c_device_keypad = {
+ .name = "s3c24a0-keypad",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(s3c_keypad_resource),
+ .resource = s3c_keypad_resource,
+};
+
+EXPORT_SYMBOL(s3c_device_keypad);
+
+
diff --git a/arch/arm/mach-s3c24a0/devs.h b/arch/arm/mach-s3c24a0/devs.h
new file mode 100644
index 0000000..479386b
--- /dev/null
+++ b/arch/arm/mach-s3c24a0/devs.h
@@ -0,0 +1,41 @@
+/* arch/arm/mach-s3c24a0/devs.h
+ *
+ * $Id: devs.h,v 1.1.1.1 2006/02/13 05:22:49 ihlee215 Exp $
+ *
+ * Copyright (C) 2005, Sean Choi
+ * All rights reserved.
+ *
+ * Header file for s3c24a0 standard platform devices
+ *
+ * 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.
+ *
+ * derived from linux/arch/arm/mach-s3c2410/devs.h, written by
+ * Ben Dooks
+ *
+*/
+
+extern struct platform_device s3c_device_usb;
+extern struct platform_device s3c_device_lcd;
+extern struct platform_device s3c_device_wdt;
+extern struct platform_device s3c_device_i2c;
+extern struct platform_device s3c_device_iis;
+extern struct platform_device s3c_device_rtc;
+extern struct platform_device s3c_device_adc;
+extern struct platform_device s3c_device_sdi;
+
+extern struct platform_device s3c_device_spi0;
+extern struct platform_device s3c_device_spi1;
+
+extern struct platform_device s3c_device_nand;
+
+extern struct platform_device s3c_device_timer0;
+extern struct platform_device s3c_device_timer1;
+extern struct platform_device s3c_device_timer2;
+extern struct platform_device s3c_device_timer3;
+
+extern struct platform_device s3c_device_udc;
+
+extern struct platform_device s3c_device_irda;
+extern struct platform_device s3c_device_keypad;
diff --git a/arch/arm/mach-s3c24a0/dma.c b/arch/arm/mach-s3c24a0/dma.c
new file mode 100644
index 0000000..401cc21
--- /dev/null
+++ b/arch/arm/mach-s3c24a0/dma.c
@@ -0,0 +1,1204 @@
+/* linux/arch/arm/mach-s3c24a0/dma.c
+ *
+ * $Id: dma.c,v 1.1.1.1 2006/02/13 05:22:49 ihlee215 Exp $
+ *
+ * Copyright (C) 2005, Sean Choi
+ * All rights reserved.
Again, see above comments on author and copyright.
+ * S3C24A0 DMA core
+ *
+ * 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.
+ *
+ * This file is based on the Sangwook Lee/Samsung patches, re-written due
+ * to various ommisions from the code (such as flexible dma configuration)
+ * for use with the BAST system board.
+ *
+ * The re-write is pretty much complete, and should be good enough for any
+ * possible DMA function
+ *
+ * derived from linux/arch/arm/mach-s3c24a0/devs.c, written by
+ * Ben Dooks
+ */
+
+#define CONFIG_S3C24A0_DMA_DEUG
+
+#ifdef CONFIG_S3C24A0_DMA_DEBUG
+#define DEBUG
+#endif
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+
+//#define pr_debug printk
+//#define KERN_DEBUG
+
+
+/* dma channel state information */
+s3c24a0_dma_chan_t s3c24a0_chans[S3C24A0_DMA_CHANNELS];
+
+/* debugging functions */
+
+#define BUF_MAGIC (0xcafebabe)
+
+#define dmawarn(fmt...) printk(KERN_DEBUG fmt)
+
+#define dma_regaddr(chan, reg) ((chan)->regs + (reg))
+
+#if 1
+#define dma_wrreg(chan, reg, val) writel((val), (chan)->regs + (reg))
+#else
+static inline void
+dma_wrreg(s3c24a0_dma_chan_t *chan, int reg, unsigned long val)
+{
+ pr_debug("writing %08x to register %08x\n",(unsigned int)val,reg);
+ writel(val, dma_regaddr(chan, reg));
+}
+
+#endif
+
+#define dma_rdreg(chan, reg) readl((chan)->regs + (reg))
+
+/* captured register state for debug */
+
+struct s3c24a0_dma_regstate {
+ unsigned long dcsrc;
+ unsigned long disrc;
+ unsigned long disrcc;
+ unsigned long dcdst;
+ unsigned long didst;
+ unsigned long didstc;
+ unsigned long dstat;
+ unsigned long dcon;
+ unsigned long dmsktrig;
+};
+
+
+#ifdef CONFIG_S3C24A0_DMA_DEBUG
+
+/* dmadbg_showregs
+ *
+ * simple debug routine to print the current state of the dma registers
+*/
+
+static void
+dmadbg_capture(s3c24a0_dma_chan_t *chan, struct s3c24a0_dma_regstate *regs)
+{
+ regs->dcsrc = dma_rdreg(chan, S3C24A0_DMA_DCSRC);
+ regs->disrc = dma_rdreg(chan, S3C24A0_DMA_DISRC);
+ regs->disrcc = dma_rdreg(chan, S3C24A0_DMA_DISRCC);
+ regs->dcdst = dma_rdreg(chan, S3C24A0_DMA_DCDST);
+ regs->didst = dma_rdreg(chan, S3C24A0_DMA_DIDST);
+ regs->didstc = dma_rdreg(chan, S3C24A0_DMA_DIDSTC);
+ regs->dstat = dma_rdreg(chan, S3C24A0_DMA_DSTAT);
+ regs->dcon = dma_rdreg(chan, S3C24A0_DMA_DCON);
+ regs->dmsktrig = dma_rdreg(chan, S3C24A0_DMA_DMASKTRIG);
+}
+
+static void
+dmadbg_showregs(const char *fname, int line, s3c24a0_dma_chan_t *chan,
+ struct s3c24a0_dma_regstate *regs)
+{
+ printk(KERN_DEBUG "dma%d: %s:%d: DCSRC=%08lx, DISRC=%08lx,DISRCC=%08lx,\
+ DCDST=%08lx, DIDST=%08lx,DIDSTC=%08lx,\
+ DSTAT=%08lx DMT=%02lx, DCON=%08lx\n",
+ chan->number, fname, line,
+ regs->dcsrc, regs->disrc,regs->disrcc,
+ regs->dcdst, regs->didst,regs->didstc,
+ regs->dstat, regs->dmsktrig,
+ regs->dcon);
+}
+
+static void
+dmadbg_showchan(const char *fname, int line, s3c24a0_dma_chan_t *chan)
+{
+ struct s3c24a0_dma_regstate state;
+
+ dmadbg_capture(chan, &state);
+
+ printk(KERN_DEBUG "dma%d: %s:%d: ls=%d, cur=%p, %p %p\n",
+ chan->number, fname, line, chan->load_state,
+ chan->curr, chan->next, chan->end);
+
+ dmadbg_showregs(fname, line, chan, &state);
+}
+
+#define dbg_showregs(chan) dmadbg_showregs(__FUNCTION__, __LINE__, (chan))
+#define dbg_showchan(chan) dmadbg_showchan(__FUNCTION__, __LINE__, (chan))
+#else
+#define dbg_showregs(chan) do { } while(0)
+#define dbg_showchan(chan) do { } while(0)
+#endif /* CONFIG_S3C24A0_DMA_DEBUG */
+
+#define check_channel(chan) \
+ do { if ((chan) >= S3C24A0_DMA_CHANNELS) { \
+ printk(KERN_ERR "%s: invalid channel %d\n", __FUNCTION__, (chan)); \
+ return -EINVAL; \
+ } } while(0)
+
+
+/* s3c24a0_dma_stats_timeout
+ *
+ * Update DMA stats from timeout info
+*/
+
+static void
+s3c24a0_dma_stats_timeout(s3c24a0_dma_stats_t *stats, int val)
+{
+ if (stats == NULL)
+ return;
+
+ if (val > stats->timeout_longest)
+ stats->timeout_longest = val;
+ if (val < stats->timeout_shortest)
+ stats->timeout_shortest = val;
+
+ stats->timeout_avg += val;
+}
+
+/* s3c24a0_dma_waitforload
+ *
+ * wait for the DMA engine to load a buffer, and update the state accordingly
+*/
+
+static int
+s3c24a0_dma_waitforload(s3c24a0_dma_chan_t *chan, int line)
+{
+ int timeout = chan->load_timeout;
+ int took;
+
+ if (chan->load_state != S3C24A0_DMALOAD_1LOADED) {
+ printk(KERN_ERR "dma%d: s3c24a0_dma_waitforload() called in loadstate %d from line %d\n", chan->number, chan->load_state, line);
+ return 0;
+ }
+
+ if (chan->stats != NULL)
+ chan->stats->loads++;
+
+ while (--timeout > 0) {
+ if ((dma_rdreg(chan, S3C24A0_DMA_DSTAT) << (32-20)) != 0) {
+ took = chan->load_timeout - timeout;
+
+ s3c24a0_dma_stats_timeout(chan->stats, took);
+
+ switch (chan->load_state) {
+ case S3C24A0_DMALOAD_1LOADED:
+ chan->load_state = S3C24A0_DMALOAD_1RUNNING;
+ break;
+
+ default:
+ printk(KERN_ERR "dma%d: unknown load_state in s3c24a0_dma_waitforload() %d\n", chan->number, chan->load_state);
+ }
+
+ return 1;
+ }
+ }
+
+ if (chan->stats != NULL) {
+ chan->stats->timeout_failed++;
+ }
+
+ return 0;
+}
+
+
+
+/* s3c24a0_dma_loadbuffer
+ *
+ * load a buffer, and update the channel state
+*/
+
+static inline int
+s3c24a0_dma_loadbuffer(s3c24a0_dma_chan_t *chan,
+ s3c24a0_dma_buf_t *buf)
+{
+ unsigned long reload;
+
+ pr_debug("s3c24a0_chan_loadbuffer: loading buff %p (0x%08lx,0x%06x)\n",
+ buf, (unsigned long)buf->data, buf->size);
+
+ if (buf == NULL) {
+ dmawarn("buffer is NULL\n");
+ return -EINVAL;
+ }
+
+ /* check the state of the channel before we do anything */
+
+ if (chan->load_state == S3C24A0_DMALOAD_1LOADED) {
+ dmawarn("load_state is S3C24A0_DMALOAD_1LOADED\n");
+ }
+
+ if (chan->load_state == S3C24A0_DMALOAD_1LOADED_1RUNNING) {
+ dmawarn("state is S3C24A0_DMALOAD_1LOADED_1RUNNING\n");
+ }
+
+ /* it would seem sensible if we are the last buffer to not bother
+ * with the auto-reload bit, so that the DMA engine will not try
+ * and load another transfer after this one has finished...
+ */
+ if (chan->load_state == S3C24A0_DMALOAD_NONE) {
+ pr_debug("load_state is none, checking for noreload (next=%p)\n",
+ buf->next);
+ reload = (buf->next == NULL) ? S3C24A0_DCON_NORELOAD : 0;
+ } else {
+ pr_debug("load_state is %d => autoreload\n", chan->load_state);
+ reload = S3C24A0_DCON_AUTORELOAD;
+ }
+
+ writel(buf->data, chan->addr_reg);
+
+ dma_wrreg(chan, S3C24A0_DMA_DCON,
+ chan->dcon | reload | (buf->size/chan->xfer_unit));
+
+ chan->next = buf->next;
+
+ /* update the state of the channel */
+
+ switch (chan->load_state) {
+ case S3C24A0_DMALOAD_NONE:
+ chan->load_state = S3C24A0_DMALOAD_1LOADED;
+ break;
+
+ case S3C24A0_DMALOAD_1RUNNING:
+ chan->load_state = S3C24A0_DMALOAD_1LOADED_1RUNNING;
+ break;
+
+ default:
+ dmawarn("dmaload: unknown state %d in loadbuffer\n",
+ chan->load_state);
+ break;
+ }
+
+ return 0;
+}
+
+/* s3c24a0_dma_call_op
+ *
+ * small routine to call the op routine with the given op if it has been
+ * registered
+*/
+
+static void
+s3c24a0_dma_call_op(s3c24a0_dma_chan_t *chan, s3c24a0_chan_op_t op)
+{
+ if (chan->op_fn != NULL) {
+ (chan->op_fn)(chan, op);
+ }
+}
+
+/* s3c24a0_dma_buffdone
+ *
+ * small wrapper to check if callback routine needs to be called, and
+ * if so, call it
+*/
+
+static inline void
+s3c24a0_dma_buffdone(s3c24a0_dma_chan_t *chan, s3c24a0_dma_buf_t *buf,
+ s3c24a0_dma_buffresult_t result)
+{
+ pr_debug("callback_fn=%p, buf=%p, id=%p, size=%d, result=%d\n",
+ chan->callback_fn, buf, buf->id, buf->size, result);
+
+ if (chan->callback_fn != NULL) {
+ (chan->callback_fn)(chan, buf->id, buf->size, result);
+ }
+}
+
+/* s3c24a0_dma_start
+ *
+ * start a dma channel going
+*/
+
+static int s3c24a0_dma_start(s3c24a0_dma_chan_t *chan)
+{
+ unsigned long tmp,dcon;
+ unsigned long flags;
+
+ pr_debug("s3c24a0_start_dma: channel=%d\n", chan->number);
+
+ local_irq_save(flags);
+
+ if (chan->state == S3C24A0_DMA_RUNNING) {
+ pr_debug("s3c24a0_start_dma: already running (%d)\n", chan->state);
+ local_irq_restore(flags);
+ return 0;
+ }
+
+ chan->state = S3C24A0_DMA_RUNNING;
+
+ /* check wether there is anything to load, and if not, see
+ * if we can find anything to load
+ */
+
+ if (chan->load_state == S3C24A0_DMALOAD_NONE) {
+ if (chan->next == NULL) {
+ printk(KERN_ERR "dma%d: channel has nothing loaded\n",
+ chan->number);
+ chan->state = S3C24A0_DMA_IDLE;
+ local_irq_restore(flags);
+ return -EINVAL;
+ }
+
+ s3c24a0_dma_loadbuffer(chan, chan->next);
+ }
+
+ dbg_showchan(chan);
+
+ /* enable the channel */
+
+ if (!chan->irq_enabled) {
+ enable_irq(chan->irq);
+ chan->irq_enabled = 1;
+ }
+
+ /* start the channel going */
+
+ tmp = dma_rdreg(chan, S3C24A0_DMA_DMASKTRIG);
+ dcon = dma_rdreg(chan, S3C24A0_DMA_DCON);
+ tmp &= ~S3C24A0_DMASKTRIG_STOP;
+ tmp |= S3C24A0_DMASKTRIG_ON;
+ dma_wrreg(chan, S3C24A0_DMA_DMASKTRIG, tmp);
+
+ pr_debug("wrote %08lx to DMASKTRIG, dcon %lx\n", tmp,dcon);
+
+#if 0
+ /* the dma buffer loads should take care of clearing the AUTO
+ * reloading feature */
+ tmp = dma_rdreg(chan, S3C24A0_DMA_DCON);
+ tmp &= ~S3C24A0_DCON_NORELOAD;
+ dma_wrreg(chan, S3C24A0_DMA_DCON, tmp);
+#endif
+
+ s3c24a0_dma_call_op(chan, S3C24A0_DMAOP_START);
+
+ dbg_showchan(chan);
+
+ local_irq_restore(flags);
+ return 0;
+}
+
+/* s3c24a0_dma_canload
+ *
+ * work out if we can queue another buffer into the DMA engine
+*/
+
+static int
+s3c24a0_dma_canload(s3c24a0_dma_chan_t *chan)
+{
+ if (chan->load_state == S3C24A0_DMALOAD_NONE ||
+ chan->load_state == S3C24A0_DMALOAD_1RUNNING)
+ return 1;
+
+ return 0;
+}
+
+
+/* s3c24a0_dma_enqueue
+ *
+ * queue an given buffer for dma transfer.
+ *
+ * id the device driver's id information for this buffer
+ * data the physical address of the buffer data
+ * size the size of the buffer in bytes
+ *
+ * If the channel is not running, then the flag S3C24A0_DMAF_AUTOSTART
+ * is checked, and if set, the channel is started. If this flag isn't set,
+ * then an error will be returned.
+ *
+ * It is possible to queue more than one DMA buffer onto a channel at
+ * once, and the code will deal with the re-loading of the next buffer
+ * when necessary.
+*/
+
+int s3c24a0_dma_enqueue(unsigned int channel, void *id,
+ dma_addr_t data, int size)
+{
+ s3c24a0_dma_chan_t *chan = &s3c24a0_chans[channel];
+ s3c24a0_dma_buf_t *buf;
+ unsigned long flags;
+
+ check_channel(channel);
+
+ pr_debug("%s: id=%p, data=%08x, size=%d\n",
+ __FUNCTION__, id, (unsigned int)data, size);
+
+ buf = (s3c24a0_dma_buf_t *)kmalloc(sizeof(*buf), GFP_ATOMIC);
+ if (buf == NULL) {
+ pr_debug("%s: out of memory (%d alloc)\n",
+ __FUNCTION__, sizeof(*buf));
+ return -ENOMEM;
+ }
+
+ pr_debug("%s: new buffer %p\n", __FUNCTION__, buf);
+
+ //dbg_showchan(chan);
+
+ buf->next = NULL;
+ buf->data = buf->ptr = data;
+ buf->size = size;
+ buf->id = id;
+ buf->magic = BUF_MAGIC;
+
+ local_irq_save(flags);
+
+ if (chan->curr == NULL) {
+ /* we've got nothing loaded... */
+ pr_debug("%s: buffer %p queued onto empty channel\n",
+ __FUNCTION__, buf);
+
+ chan->curr = buf;
+ chan->end = buf;
+ chan->next = NULL;
+ } else {
+ pr_debug("dma%d: %s: buffer %p queued onto non-empty channel\n",
+ chan->number, __FUNCTION__, buf);
+
+ if (chan->end == NULL)
+ pr_debug("dma%d: %s: %p not empty, and chan->end==NULL?\n",
+ chan->number, __FUNCTION__, chan);
+
+ chan->end->next = buf;
+ chan->end = buf;
+ }
+
+ /* if necessary, update the next buffer field */
+ if (chan->next == NULL)
+ chan->next = buf;
+
+ /* check to see if we can load a buffer */
+ if (chan->state == S3C24A0_DMA_RUNNING) {
+ if (chan->load_state == S3C24A0_DMALOAD_1LOADED && 1) {
+ if (s3c24a0_dma_waitforload(chan, __LINE__) == 0) {
+ printk(KERN_ERR "dma%d: loadbuffer:"
+ "timeout loading buffer\n",
+ chan->number);
+ dbg_showchan(chan);
+ local_irq_restore(flags);
+ return -EINVAL;
+ }
+ }
+
+ while (s3c24a0_dma_canload(chan) && chan->next != NULL) {
+ s3c24a0_dma_loadbuffer(chan, chan->next);
+ }
+ } else if (chan->state == S3C24A0_DMA_IDLE) {
+ if (chan->flags & S3C24A0_DMAF_AUTOSTART) {
+ s3c24a0_dma_ctrl(chan->number, S3C24A0_DMAOP_START);
+ }
+ }
+
+ local_irq_restore(flags);
+ return 0;
+}
+
+EXPORT_SYMBOL(s3c24a0_dma_enqueue);
+
+static inline void
+s3c24a0_dma_freebuf(s3c24a0_dma_buf_t *buf)
+{
+ int magicok = (buf->magic == BUF_MAGIC);
+
+ buf->magic = -1;
+
+ if (magicok) {
+ kfree(buf);
+ } else {
+ printk("s3c24a0_dma_freebuf: buff %p with bad magic\n", buf);
+ }
+}
+
+/* s3c24a0_dma_lastxfer
+ *
+ * called when the system is out of buffers, to ensure that the channel
+ * is prepared for shutdown.
+*/
+
+static inline void
+s3c24a0_dma_lastxfer(s3c24a0_dma_chan_t *chan)
+{
+ pr_debug("dma%d: s3c24a0_dma_lastxfer: load_state %d\n",
+ chan->number, chan->load_state);
+
+ switch (chan->load_state) {
+ case S3C24A0_DMALOAD_NONE:
+ break;
+
+ case S3C24A0_DMALOAD_1LOADED:
+ if (s3c24a0_dma_waitforload(chan, __LINE__) == 0) {
+ /* flag error? */
+ printk(KERN_ERR "dma%d: timeout waiting for load\n",
+ chan->number);
+ return;
+ }
+ break;
+
+ default:
+ pr_debug("dma%d: lastxfer: unhandled load_state %d with no next",
+ chan->number, chan->load_state);
+ return;
+
+ }
+
+ /* hopefully this'll shut the damned thing up after the transfer... */
+ dma_wrreg(chan, S3C24A0_DMA_DCON, chan->dcon | S3C24A0_DCON_NORELOAD);
+}
+
+
+#define dmadbg2(x...)
+
+static irqreturn_t
+s3c24a0_dma_irq(int irq, void *devpw)
+{
+ s3c24a0_dma_chan_t *chan = (s3c24a0_dma_chan_t *)devpw;
+ s3c24a0_dma_buf_t *buf;
+
+
+ buf = chan->curr;
+
+ dbg_showchan(chan);
+
+ /* modify the channel state */
+
+ switch (chan->load_state) {
+ case S3C24A0_DMALOAD_1RUNNING:
+ /* TODO - if we are running only one buffer, we probably
+ * want to reload here, and then worry about the buffer
+ * callback */
+
+ chan->load_state = S3C24A0_DMALOAD_NONE;
+ break;
+
+ case S3C24A0_DMALOAD_1LOADED:
+ /* iirc, we should go back to NONE loaded here, we
+ * had a buffer, and it was never verified as being
+ * loaded.
+ */
+
+ chan->load_state = S3C24A0_DMALOAD_NONE;
+ break;
+
+ case S3C24A0_DMALOAD_1LOADED_1RUNNING:
+ /* we'll worry about checking to see if another buffer is
+ * ready after we've called back the owner. This should
+ * ensure we do not wait around too long for the DMA
+ * engine to start the next transfer
+ */
+
+ chan->load_state = S3C24A0_DMALOAD_1LOADED;
+ break;
+
+ case S3C24A0_DMALOAD_NONE:
+ printk(KERN_ERR "dma%d: IRQ with no loaded buffer?\n",
+ chan->number);
+ break;
+
+ default:
+ printk(KERN_ERR "dma%d: IRQ in invalid load_state %d\n",
+ chan->number, chan->load_state);
+ break;
+ }
+
+ if (buf != NULL) {
+ /* update the chain to make sure that if we load any more
+ * buffers when we call the callback function, things should
+ * work properly */
+
+ chan->curr = buf->next;
+ buf->next = NULL;
+
+ if (buf->magic != BUF_MAGIC) {
+ printk(KERN_ERR "dma%d: %s: buf %p incorrect magic\n",
+ chan->number, __FUNCTION__, buf);
+ return IRQ_HANDLED;
+ }
+
+ s3c24a0_dma_buffdone(chan, buf, S3C24A0_RES_OK);
+
+ /* free resouces */
+ s3c24a0_dma_freebuf(buf);
+ } else {
+ }
+
+ if (chan->next != NULL) {
+ unsigned long flags;
+
+ switch (chan->load_state) {
+ case S3C24A0_DMALOAD_1RUNNING:
+ /* don't need to do anything for this state */
+ break;
+
+ case S3C24A0_DMALOAD_NONE:
+ /* can load buffer immediately */
+ break;
+
+ case S3C24A0_DMALOAD_1LOADED:
+ if (s3c24a0_dma_waitforload(chan, __LINE__) == 0) {
+ /* flag error? */
+ printk(KERN_ERR "dma%d: timeout waiting for load\n",
+ chan->number);
+ return IRQ_HANDLED;
+ }
+
+ break;
+
+ case S3C24A0_DMALOAD_1LOADED_1RUNNING:
+ goto no_load;
+
+ default:
+ printk(KERN_ERR "dma%d: unknown load_state in irq, %d\n",
+ chan->number, chan->load_state);
+ return IRQ_HANDLED;
+ }
+
+ local_irq_save(flags);
+ s3c24a0_dma_loadbuffer(chan, chan->next);
+ local_irq_restore(flags);
+ } else {
+ s3c24a0_dma_lastxfer(chan);
+
+ /* see if we can stop this channel.. */
+ if (chan->load_state == S3C24A0_DMALOAD_NONE) {
+ pr_debug("dma%d: end of transfer, stopping channel (%ld)\n",
+ chan->number, jiffies);
+ s3c24a0_dma_ctrl(chan->number, S3C24A0_DMAOP_STOP);
+ }
+ }
+
+ no_load:
+ return IRQ_HANDLED;
+}
+
+
+
+/* s3c24a0_request_dma
+ *
+ * get control of an dma channel
+*/
+
+int s3c24a0_dma_request(unsigned int channel, s3c24a0_dma_client_t *client,
+ void *dev)
+{
+ s3c24a0_dma_chan_t *chan = &s3c24a0_chans[channel];
+ unsigned long flags;
+ int err;
+
+ pr_debug("dma%d: s3c24a0_request_dma: client=%s, dev=%p\n",
+ channel, client->name, dev);
+
+ check_channel(channel);
+
+ local_irq_save(flags);
+
+ dbg_showchan(chan);
+
+ if (chan->in_use) {
+ if (client != chan->client) {
+ printk(KERN_ERR "dma%d: already in use\n", channel);
+ local_irq_restore(flags);
+ return -EBUSY;
+ } else {
+ printk(KERN_ERR "dma%d: client already has channel\n", channel);
+ }
+ }
+
+ chan->client = client;
+ chan->in_use = 1;
+
+ if (!chan->irq_claimed) {
+ pr_debug("dma%d: %s : requesting irq %d\n",
+ channel, __FUNCTION__, chan->irq);
+
+ err = request_irq(chan->irq, s3c24a0_dma_irq, SA_INTERRUPT,
+ client->name, (void *)chan);
+
+ if (err) {
+ chan->in_use = 0;
+ local_irq_restore(flags);
+
+ printk(KERN_ERR "%s: cannot get IRQ %d for DMA %d\n",
+ client->name, chan->irq, chan->number);
+ return err;
+ }
+
+ chan->irq_claimed = 1;
+ chan->irq_enabled = 1;
+ }
+
+ local_irq_restore(flags);
+
+ /* need to setup */
+
+ pr_debug("%s: channel initialised, %p\n", __FUNCTION__, chan);
+
+ return 0;
+}
+
+EXPORT_SYMBOL(s3c24a0_dma_request);
+
+/* s3c24a0_dma_free
+ *
+ * release the given channel back to the system, will stop and flush
+ * any outstanding transfers, and ensure the channel is ready for the
+ * next claimant.
+ *
+ * Note, although a warning is currently printed if the freeing client
+ * info is not the same as the registrant's client info, the free is still
+ * allowed to go through.
+*/
+
+int s3c24a0_dma_free(dmach_t channel, s3c24a0_dma_client_t *client)
+{
+ s3c24a0_dma_chan_t *chan = &s3c24a0_chans[channel];
+ unsigned long flags;
+
+ check_channel(channel);
+
+ local_irq_save(flags);
+
+
+ if (chan->client != client) {
+ printk(KERN_WARNING "dma%d: possible free from different client (channel %p, passed %p)\n",
+ channel, chan->client, client);
+ }
+
+ /* sort out stopping and freeing the channel */
+
+ if (chan->state != S3C24A0_DMA_IDLE) {
+ pr_debug("%s: need to stop dma channel %p\n",
+ __FUNCTION__, chan);
+
+ /* possibly flush the channel */
+ s3c24a0_dma_ctrl(channel, S3C24A0_DMAOP_STOP);
+ }
+
+ chan->client = NULL;
+ chan->in_use = 0;
+
+ local_irq_restore(flags);
+
+ return 0;
+}
+
+EXPORT_SYMBOL(s3c24a0_dma_free);
+
+static int s3c24a0_dma_dostop(s3c24a0_dma_chan_t *chan)
+{
+ unsigned long tmp;
+ unsigned long flags;
+
+ pr_debug("%s:\n", __FUNCTION__);
+
+ dbg_showchan(chan);
+
+ local_irq_save(flags);
+
+ s3c24a0_dma_call_op(chan, S3C24A0_DMAOP_STOP);
+
+ tmp = dma_rdreg(chan, S3C24A0_DMA_DMASKTRIG);
+ tmp |= S3C24A0_DMASKTRIG_STOP;
+ dma_wrreg(chan, S3C24A0_DMA_DMASKTRIG, tmp);
+
+#if 0
+ /* should also clear interrupts, according to WinCE BSP */
+ tmp = dma_rdreg(chan, S3C24A0_DMA_DCON);
+ tmp |= S3C24A0_DCON_NORELOAD;
+ dma_wrreg(chan, S3C24A0_DMA_DCON, tmp);
+#endif
+
+ chan->state = S3C24A0_DMA_IDLE;
+ chan->load_state = S3C24A0_DMALOAD_NONE;
+
+ local_irq_restore(flags);
+
+ return 0;
+}
+
+/* s3c24a0_dma_flush
+ *
+ * stop the channel, and remove all current and pending transfers
+*/
+
+static int s3c24a0_dma_flush(s3c24a0_dma_chan_t *chan)
+{
+ s3c24a0_dma_buf_t *buf, *next;
+ unsigned long flags;
+
+ pr_debug("%s:\n", __FUNCTION__);
+
+ local_irq_save(flags);
+
+ if (chan->state != S3C24A0_DMA_IDLE) {
+ pr_debug("%s: stopping channel...\n", __FUNCTION__ );
+ s3c24a0_dma_ctrl(chan->number, S3C24A0_DMAOP_STOP);
+ }
+
+ buf = chan->curr;
+ if (buf == NULL)
+ buf = chan->next;
+
+ chan->curr = chan->next = chan->end = NULL;
+
+ if (buf != NULL) {
+ for ( ; buf != NULL; buf = next) {
+ next = buf->next;
+
+ pr_debug("%s: free buffer %p, next %p\n",
+ __FUNCTION__, buf, buf->next);
+
+ s3c24a0_dma_buffdone(chan, buf, S3C24A0_RES_ABORT);
+ s3c24a0_dma_freebuf(buf);
+ }
+ }
+
+ local_irq_restore(flags);
+
+ return 0;
+}
+
+
+int
+s3c24a0_dma_ctrl(dmach_t channel, s3c24a0_chan_op_t op)
+{
+ s3c24a0_dma_chan_t *chan = &s3c24a0_chans[channel];
+
+ check_channel(channel);
+
+ switch (op) {
+ case S3C24A0_DMAOP_START:
+ return s3c24a0_dma_start(chan);
+
+ case S3C24A0_DMAOP_STOP:
+ return s3c24a0_dma_dostop(chan);
+
+ case S3C24A0_DMAOP_PAUSE:
+ return -ENOENT;
+
+ case S3C24A0_DMAOP_RESUME:
+ return -ENOENT;
+
+ case S3C24A0_DMAOP_FLUSH:
+ return s3c24a0_dma_flush(chan);
+
+ case S3C24A0_DMAOP_TIMEOUT:
+ return 0;
+
+ }
+
+ return -ENOENT; /* unknown, don't bother */
+}
+
+EXPORT_SYMBOL(s3c24a0_dma_ctrl);
+
+/* DMA configuration for each channel
+ *
+ * DISRCC -> source of the DMA (AHB,APB)
+ * DISRC -> source address of the DMA
+ * DIDSTC -> destination of the DMA (AHB,APD)
+ * DIDST -> destination address of the DMA
+*/
+
+/* s3c24a0_dma_config
+ *
+ * xfersize: size of unit in bytes (1,2,4)
+ * dcon: base value of the DCONx register
+*/
+
+int s3c24a0_dma_config(dmach_t channel,
+ int xferunit,
+ int dcon)
+{
+ s3c24a0_dma_chan_t *chan = &s3c24a0_chans[channel];
+
+ pr_debug("%s: chan=%d, xfer_unit=%d, dcon=%08x\n",
+ __FUNCTION__, channel, xferunit, dcon);
+
+ check_channel(channel);
+
+ switch (xferunit) {
+ case 1:
+ dcon |= S3C24A0_DCON_BYTE;
+ break;
+
+ case 2:
+ dcon |= S3C24A0_DCON_HALFWORD;
+ break;
+
+ case 4:
+ dcon |= S3C24A0_DCON_WORD;
+ break;
+
+ default:
+ pr_debug("%s: bad transfer size %d\n", __FUNCTION__, xferunit);
+ return -EINVAL;
+ }
+
+ dcon |= S3C24A0_DCON_HWTRIG;
+ dcon |= S3C24A0_DCON_INTREQ;
+
+ pr_debug("%s: dcon now %08x\n", __FUNCTION__, dcon);
+
+ chan->dcon = dcon;
+ chan->xfer_unit = xferunit;
+
+ return 0;
+}
+
+EXPORT_SYMBOL(s3c24a0_dma_config);
+
+int s3c24a0_dma_setflags(dmach_t channel, unsigned int flags)
+{
+ s3c24a0_dma_chan_t *chan = &s3c24a0_chans[channel];
+
+ check_channel(channel);
+
+ pr_debug("%s: chan=%d, flags=%08x\n", __FUNCTION__, channel, flags);
+
+ chan->flags = flags;
+
+ return 0;
+}
+
+EXPORT_SYMBOL(s3c24a0_dma_setflags);
+
+
+/* do we need to protect the settings of the fields from
+ * irq?
+*/
+
+int s3c24a0_dma_set_opfn(dmach_t channel, s3c24a0_dma_opfn_t rtn)
+{
+ s3c24a0_dma_chan_t *chan = &s3c24a0_chans[channel];
+
+ check_channel(channel);
+
+ pr_debug("%s: chan=%d, op rtn=%p\n", __FUNCTION__, channel, rtn);
+
+ chan->op_fn = rtn;
+
+ return 0;
+}
+
+EXPORT_SYMBOL(s3c24a0_dma_set_opfn);
+
+int s3c24a0_dma_set_buffdone_fn(dmach_t channel, s3c24a0_dma_cbfn_t rtn)
+{
+ s3c24a0_dma_chan_t *chan = &s3c24a0_chans[channel];
+
+ check_channel(channel);
+
+ pr_debug("%s: chan=%d, callback rtn=%p\n", __FUNCTION__, channel, rtn);
+
+ chan->callback_fn = rtn;
+
+ return 0;
+}
+
+EXPORT_SYMBOL(s3c24a0_dma_set_buffdone_fn);
+
+/* s3c24a0_dma_devconfig
+ *
+ * configure the dma source/destination hardware type and address
+ *
+ * source: S3C24A0_DMASRC_HW: source is hardware
+ * S3C24A0_DMASRC_MEM: source is memory
+ *
+ * hwcfg: the value for xxxSTCn register,
+ * bit 0: 0=increment pointer, 1=leave pointer
+ * bit 1: 0=soucre is AHB, 1=soucre is APB
+ *
+ * devaddr: physical address of the source
+*/
+
+int s3c24a0_dma_devconfig(int channel,
+ s3c24a0_dmasrc_t source,
+ int hwcfg,
+ unsigned long devaddr)
+{
+ s3c24a0_dma_chan_t *chan = &s3c24a0_chans[channel];
+
+ check_channel(channel);
+
+ pr_debug("%s: source=%d, hwcfg=%08x, devaddr=%08lx\n",
+ __FUNCTION__, (int)source, hwcfg, devaddr);
+
+ chan->source = source;
+ chan->dev_addr = devaddr;
+
+ switch (source) {
+ case S3C24A0_DMASRC_HW:
+ /* source is hardware */
+ pr_debug("%s: hw source, devaddr=%08lx, hwcfg=%d\n",
+ __FUNCTION__, devaddr, hwcfg);
+ dma_wrreg(chan, S3C24A0_DMA_DISRCC, hwcfg & 3);
+ dma_wrreg(chan, S3C24A0_DMA_DISRC, devaddr);
+ dma_wrreg(chan, S3C24A0_DMA_DIDSTC, (0<<1) | (0<<0));
+
+ chan->addr_reg = dma_regaddr(chan, S3C24A0_DMA_DIDST);
+ return 0;
+
+ case S3C24A0_DMASRC_MEM:
+ /* source is memory */
+ pr_debug( "%s: mem source, devaddr=%08lx, hwcfg=%d\n",
+ __FUNCTION__, devaddr, hwcfg);
+ dma_wrreg(chan, S3C24A0_DMA_DISRCC, (0<<1) | (0<<0));
+ dma_wrreg(chan, S3C24A0_DMA_DIDST, devaddr);
+ dma_wrreg(chan, S3C24A0_DMA_DIDSTC, hwcfg & 3);
+
+ chan->addr_reg = dma_regaddr(chan, S3C24A0_DMA_DISRC);
+ return 0;
+ }
+
+ printk(KERN_ERR "dma%d: invalid source type (%d)\n", channel, source);
+ return -EINVAL;
+}
+
+EXPORT_SYMBOL(s3c24a0_dma_devconfig);
+
+/* system device class */
+
+int s3c24a0_dma_getposition(dmach_t channel, dma_addr_t *src, dma_addr_t *dst)
+{
+ s3c24a0_dma_chan_t *chan = &s3c24a0_chans[channel];
+
+ check_channel(channel);
+
+ if (src != NULL)
+ *src = dma_rdreg(chan, S3C24A0_DMA_DCSRC);
+
+ if (dst != NULL)
+ *dst = dma_rdreg(chan, S3C24A0_DMA_DCDST);
+
+ return 0;
+}
+
+EXPORT_SYMBOL(s3c24a0_dma_getposition);
+
+
+
+
+
+
+
+
+#ifdef CONFIG_PM
+
+static int s3c24a0_dma_suspend(struct sys_device *dev, u32 state)
+{
+ s3c24a0_dma_chan_t *cp = container_of(dev, s3c24a0_dma_chan_t, dev);
+
+ printk(KERN_DEBUG "suspending dma channel %d\n", cp->number);
+
+ if (dma_rdreg(cp, S3C24A0_DMA_DMASKTRIG) & S3C24A0_DMASKTRIG_ON) {
+ /* the dma channel is still working, which is probably
+ * a bad thing to do over suspend/resume. We stop the
+ * channel and assume that the client is either going to
+ * retry after resume, or that it is broken.
+ */
+
+ printk(KERN_INFO "dma: stopping channel %d due to suspend\n",
+ cp->number);
+
+ s3c24a0_dma_dostop(cp);
+ }
+
+ return 0;
+}
+
+static int s3c24a0_dma_resume(struct sys_device *dev)
+{
+ return 0;
+}
+
+#else
+#define s3c24a0_dma_suspend NULL
+#define s3c24a0_dma_resume NULL
+#endif /* CONFIG_PM */
+
+static struct sysdev_class dma_sysclass = {
+ set_kset_name("s3c24xx-dma"),
+ .suspend = s3c24a0_dma_suspend,
+ .resume = s3c24a0_dma_resume,
+};
+
+/* initialisation code */
+
+static int __init s3c24a0_init_dma(void)
+{
+ s3c24a0_dma_chan_t *cp;
+ int channel;
+ int ret;
+
+ printk("S3C24A0 DMA Driver, (c) 2003-2004 Simtec Electronics\n");
+
+ ret = sysdev_class_register(&dma_sysclass);
+ if (ret != 0) {
+ printk(KERN_ERR "dma sysclass registration failed\n");
+ return -ENODEV;
+ }
+
+ for (channel = 0; channel < S3C24A0_DMA_CHANNELS; channel++) {
+ cp = &s3c24a0_chans[channel];
+
+ memset(cp, 0, sizeof(s3c24a0_dma_chan_t));
+
+ cp->regs = ioremap((S3C24A0_PA_DMA + ( channel * 0x100000)), 0x40);
+ if (cp->regs == NULL) {
+ printk(KERN_ERR "dma failed to remap register block\n");
+ goto err;
+ }
+
+ /* dma channel irqs are in order.. */
+ cp->number = channel;
+ cp->irq = channel + IRQ_DMA0;
+
+ /* point current stats somewhere */
+ cp->stats = &cp->stats_store;
+ cp->stats_store.timeout_shortest = LONG_MAX;
+
+ /* basic channel configuration */
+
+ cp->load_timeout = 1<<18;
+
+ /* register system device */
+
+ cp->dev.cls = &dma_sysclass;
+ cp->dev.id = channel;
+ ret = sysdev_register(&cp->dev);
+
+ printk("DMA channel %d at %p, irq %d\n",
+ cp->number, cp->regs, cp->irq);
+ }
+
+ return 0;
+
+err:
+ sysdev_class_unregister(&dma_sysclass);
+ for (channel = 0; channel < S3C24A0_DMA_CHANNELS; channel++) {
+ cp = &s3c24a0_chans[channel];
+ if(cp->regs) {
+ iounmap(cp->regs);
+ sysdev_unregister(&cp->dev);
+ }
+ }
+
+ return ret;
+}
+
+__initcall(s3c24a0_init_dma);
Why copy this file? It dosen't look much different from the s3c2410
dma code, so I would like to know why this code has been forked from
the original?
diff --git a/arch/arm/mach-s3c24a0/dma.h b/arch/arm/mach-s3c24a0/dma.h
new file mode 100644
index 0000000..c1e678b
--- /dev/null
+++ b/arch/arm/mach-s3c24a0/dma.h
@@ -0,0 +1,430 @@
+/*
+ * linux/arch/arm/mach-s3c24a0/dma.h
+ *
+ * Generic S3C24A0 DMA handling.
+ *
+ * $Id: dma.h,v 1.1.1.1 2006/02/13 05:22:49 ihlee215 Exp $
+ *
+ * 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
+
+/* DMA buffer struct */
+typedef struct dma_buf_s {
+ int size; /* buffer size */
+ dma_addr_t dma_start; /* starting DMA address */
+ int ref; /* number of DMA references */
+ void *id; /* to identify buffer from outside */
+ int write; /* 1: buf to write , 0: but to read */
+ struct dma_buf_s *next; /* next buf to process */
+} dma_buf_t;
+
+/* DMA control register structure */
+typedef struct {
+ volatile u_long DISRC;
+ volatile u_long DISRCC;
+ volatile u_long DIDST;
+ volatile u_long DIDSTC;
+ volatile u_long DCON;
+ volatile u_long DSTAT;
+ volatile u_long DCSRC;
+ volatile u_long DCDST;
+ volatile u_long DMASKTRIG;
+} dma_regs_t;
Argh! NO. volatile should not be used for accessing registers
and secondly, do not use structures for describing register
sets.
+/* DMA device structre */
+typedef struct {
+ dma_callback_t callback;
+ u_long dst;
+ u_long src;
+ u_long ctl;
+ u_long dst_ctl;
+ u_long src_ctl;
+} dma_device_t;
What is this u_long ?
+/* DMA channel structure */
+typedef struct {
+ dmach_t channel;
+ unsigned int in_use; /* Device is allocated */
+ const char *device_id; /* Device name */
+ dma_buf_t *head; /* where to insert buffers */
+ dma_buf_t *tail; /* where to remove buffers */
+ dma_buf_t *curr; /* buffer currently DMA'ed */
+ unsigned long queue_count; /* number of buffers in the queue */
+ int active; /* 1 if DMA is actually processing data */
+ dma_regs_t *regs; /* points to appropriate DMA registers */
+ int irq; /* IRQ used by the channel */
+ dma_device_t write; /* to write */
+ dma_device_t read; /* to read */
+} s3c24a0_dma_t;
+
+s3c24a0_dma_t dma_chan[MAX_S3C24A0_DMA_CHANNELS];
+
+typedef struct {
+ const char *name;
+ u_long write_src;
+ u_long write_dst;
+ u_long write_ctl;
+ u_long write_src_ctl;
+ u_long write_dst_ctl;
+ u_long read_src;
+ u_long read_dst;
+ u_long read_ctl;
+ u_long read_src_ctl;
+ u_long read_dst_ctl;
+} dma_type_t;
+
+#define DMA_UNDEF 0xffffffff /* not available */
+#define BUF_ON_MEM (ON_AHB | ADDR_INC)
+#define BUF_ON_APB (ON_APB | ADDR_FIX)
+
+#define UART0_MEM 0x0
+#define UART0_CTL (HS_MODE | SYNC_PCLK | INT_MODE | TSZ_UNIT | \
+ SINGLE_SERVICE | HWSRC(CH0_UART0) | DMA_SRC_HW | \
+ CLR_ATRELOAD | DSZ(DSZ_BYTE) | TX_CNT(0))
+#define UART0_WR_SRC UART0_MEM
+#define UART0_WR_DST 0x50000020 /* UTXH0 */
+#define UART0_WR_CTL UART0_CTL
+#define UART0_RD_SRC 0x50000024 /* URXH0 */
+#define UART0_RD_DST UART0_MEM
+#define UART0_RD_CTL UART0_CTL
+#define UART0_WR_SRC_CTL BUF_ON_MEM
+#define UART0_WR_DST_CTL BUF_ON_APB
+#define UART0_RD_SRC_CTL BUF_ON_APB
+#define UART0_RD_DST_CTL BUF_ON_MEM
+
+#define UART1_WR_SRC DMA_UNDEF
+#define UART1_WR_DST DMA_UNDEF
+#define UART1_WR_CTL DMA_UNDEF
+#define UART1_RD_SRC DMA_UNDEF
+#define UART1_RD_DST DMA_UNDEF
+#define UART1_RD_CTL DMA_UNDEF
+#define UART1_WR_SRC_CTL DMA_UNDEF
+#define UART1_WR_DST_CTL DMA_UNDEF
+#define UART1_RD_SRC_CTL DMA_UNDEF
+#define UART1_RD_DST_CTL DMA_UNDEF
+
+#define I2SSDO_CTL (HS_MODE | SYNC_PCLK | INT_MODE | TSZ_UNIT | \
+ SINGLE_SERVICE | HWSRC(CH2_I2SSDO) | DMA_SRC_HW | \
+ CLR_ATRELOAD | DSZ(DSZ_HALFWORD) | TX_CNT(0))
+
+#define I2SSDO_WR_SRC 0x0
+#define I2SSDO_WR_DST 0x44700010
+#define I2SSDO_WR_CTL I2SSDO_CTL
+#define I2SSDO_RD_SRC DMA_UNDEF
+#define I2SSDO_RD_DST DMA_UNDEF
+#define I2SSDO_RD_CTL DMA_UNDEF
+#define I2SSDO_WR_SRC_CTL BUF_ON_MEM
+#define I2SSDO_WR_DST_CTL BUF_ON_APB
+#define I2SSDO_RD_SRC_CTL DMA_UNDEF
+#define I2SSDO_RD_DST_CTL DMA_UNDEF
+
+#define I2SSDI_CTL (HS_MODE | SYNC_PCLK | INT_MODE | TSZ_UNIT | \
+ SINGLE_SERVICE | HWSRC(CH0_I2SSDI) | DMA_SRC_HW | \
+ CLR_ATRELOAD | DSZ(DSZ_HALFWORD) | TX_CNT(0))
+
+
+#define I2SSDI_WR_SRC DMA_UNDEF
+#define I2SSDI_WR_DST DMA_UNDEF
+#define I2SSDI_WR_CTL DMA_UNDEF
+#define I2SSDI_RD_SRC 0x44700010
+#define I2SSDI_RD_DST 0x0
+#define I2SSDI_RD_CTL I2SSDI_CTL
+#define I2SSDI_WR_SRC_CTL DMA_UNDEF
+#define I2SSDI_WR_DST_CTL DMA_UNDEF
+#define I2SSDI_RD_SRC_CTL BUF_ON_APB
+#define I2SSDI_RD_DST_CTL BUF_ON_MEM
+
+
+/* This is write-only (system memory -> device) */
+/*
+ * Note: It's temporarily definition. If you want to change DMA channel,
+ * you should be change HWSRC(...).
+ */
+#define AC97PCMOUT_CTL (HS_MODE | SYNC_PCLK | INT_MODE | TSZ_UNIT | \
+ SINGLE_SERVICE | HWSRC(CH0_AC97_PCMOUT) | \
+ DMA_SRC_HW | CLR_ATRELOAD | DSZ(DSZ_WORD) | \
+ TX_CNT(0))
+#define AC97PCMOUT_WR_SRC 0x0 /* on the SDRAM */
+#define AC97PCMOUT_WR_DST 0x45000018 /* Data FIFO */
+#define AC97PCMOUT_WR_CTL AC97PCMOUT_CTL
+#define AC97PCMOUT_RD_SRC DMA_UNDEF
+#define AC97PCMOUT_RD_DST DMA_UNDEF
+#define AC97PCMOUT_RD_CTL DMA_UNDEF
+#define AC97PCMOUT_WR_SRC_CTL BUF_ON_MEM
+#define AC97PCMOUT_WR_DST_CTL BUF_ON_APB
+#define AC97PCMOUT_RD_SRC_CTL DMA_UNDEF
+#define AC97PCMOUT_RD_DST_CTL DMA_UNDEF
+
+/* This is read-only (device -> system memory) */
+#define AC97PCMIN_CTL (HS_MODE | SYNC_PCLK | INT_MODE | TSZ_UNIT | \
+ SINGLE_SERVICE | HWSRC(CH1_AC97_PCMIN) | \
+ DMA_SRC_HW | CLR_ATRELOAD | DSZ(DSZ_WORD) | \
+ TX_CNT(0))
+#define AC97PCMIN_WR_SRC DMA_UNDEF
+#define AC97PCMIN_WR_DST DMA_UNDEF
+#define AC97PCMIN_WR_CTL DMA_UNDEF
+#define AC97PCMIN_RD_SRC 0x45000018 /* Data FIFO */
+#define AC97PCMIN_RD_DST 0x0 /* on the SDRAM */
+#define AC97PCMIN_RD_CTL AC97PCMIN_CTL
+#define AC97PCMIN_WR_SRC_CTL DMA_UNDEF
+#define AC97PCMIN_WR_DST_CTL DMA_UNDEF
+#define AC97PCMIN_RD_SRC_CTL BUF_ON_APB
+#define AC97PCMIN_RD_DST_CTL BUF_ON_MEM
+
+#define AC97MICIN_CTL (HS_MODE | SYNC_PCLK | INT_MODE | TSZ_UNIT | \
+ SINGLE_SERVICE | HWSRC(CH2_AC97_MICIN) | \
+ DMA_SRC_HW | CLR_ATRELOAD | DSZ(DSZ_WORD) | \
+ TX_CNT(0))
+#define AC97MICIN_WR_SRC DMA_UNDEF
+#define AC97MICIN_WR_DST DMA_UNDEF
+#define AC97MICIN_WR_CTL DMA_UNDEF
+#define AC97MICIN_RD_SRC 0x4500001C /* Data FIFO */
+#define AC97MICIN_RD_DST 0x0 /* on the SDRAM */
+#define AC97MICIN_RD_CTL AC97MICIN_CTL
+#define AC97MICIN_WR_SRC_CTL DMA_UNDEF
+#define AC97MICIN_WR_DST_CTL DMA_UNDEF
+#define AC97MICIN_RD_SRC_CTL BUF_ON_APB
+#define AC97MICIN_RD_DST_CTL BUF_ON_MEM
+
+#define USB_WR_SRC DMA_UNDEF
+#define USB_WR_DST DMA_UNDEF
+#define USB_WR_CTL DMA_UNDEF
+#define USB_RD_SRC DMA_UNDEF
+#define USB_RD_DST DMA_UNDEF
+#define USB_RD_CTL DMA_UNDEF
+#define USB_WR_SRC_CTL DMA_UNDEF
+#define USB_WR_DST_CTL DMA_UNDEF
+#define USB_RD_SRC_CTL DMA_UNDEF
+#define USB_RD_DST_CTL DMA_UNDEF
+
+#define MMC_WR_SRC DMA_UNDEF
+#define MMC_WR_DST DMA_UNDEF
+#define MMC_WR_CTL DMA_UNDEF
+#define MMC_RD_SRC DMA_UNDEF
+#define MMC_RD_DST DMA_UNDEF
+#define MMC_RD_CTL DMA_UNDEF
+#define MMC_WR_SRC_CTL DMA_UNDEF
+#define MMC_WR_DST_CTL DMA_UNDEF
+#define MMC_RD_SRC_CTL DMA_UNDEF
+#define MMC_RD_DST_CTL DMA_UNDEF
+
+#define SPI_WR_SRC DMA_UNDEF
+#define SPI_WR_DST DMA_UNDEF
+#define SPI_WR_CTL DMA_UNDEF
+#define SPI_RD_SRC DMA_UNDEF
+#define SPI_RD_DST DMA_UNDEF
+#define SPI_RD_CTL DMA_UNDEF
+#define SPI_WR_SRC_CTL DMA_UNDEF
+#define SPI_WR_DST_CTL DMA_UNDEF
+#define SPI_RD_SRC_CTL DMA_UNDEF
+#define SPI_RD_DST_CTL DMA_UNDEF
+
+#define TIMER_WR_SRC DMA_UNDEF
+#define TIMER_WR_DST DMA_UNDEF
+#define TIMER_WR_CTL DMA_UNDEF
+#define TIMER_RD_SRC DMA_UNDEF
+#define TIMER_RD_DST DMA_UNDEF
+#define TIMER_RD_CTL DMA_UNDEF
+#define TIMER_WR_SRC_CTL DMA_UNDEF
+#define TIMER_WR_DST_CTL DMA_UNDEF
+#define TIMER_RD_SRC_CTL DMA_UNDEF
+#define TIMER_RD_DST_CTL DMA_UNDEF
+
+#define XDREQ0_WR_SRC DMA_UNDEF
+#define XDREQ0_WR_DST DMA_UNDEF
+#define XDREQ0_WR_CTL DMA_UNDEF
+#define XDREQ0_RD_SRC DMA_UNDEF
+#define XDREQ0_RD_DST DMA_UNDEF
+#define XDREQ0_RD_CTL DMA_UNDEF
+#define XDREQ0_WR_SRC_CTL DMA_UNDEF
+#define XDREQ0_WR_DST_CTL DMA_UNDEF
+#define XDREQ0_RD_SRC_CTL DMA_UNDEF
+#define XDREQ0_RD_DST_CTL DMA_UNDEF
+
+#define XDREQ1_WR_SRC DMA_UNDEF
+#define XDREQ1_WR_DST DMA_UNDEF
+#define XDREQ1_WR_CTL DMA_UNDEF
+#define XDREQ1_RD_SRC DMA_UNDEF
+#define XDREQ1_RD_DST DMA_UNDEF
+#define XDREQ1_RD_CTL DMA_UNDEF
+#define XDREQ1_WR_SRC_CTL DMA_UNDEF
+#define XDREQ1_WR_DST_CTL DMA_UNDEF
+#define XDREQ1_RD_SRC_CTL DMA_UNDEF
+#define XDREQ1_RD_DST_CTL DMA_UNDEF
+
+#define MSTICK_WR_SRC DMA_UNDEF
+#define MSTICK_WR_DST DMA_UNDEF
+#define MSTICK_WR_CTL DMA_UNDEF
+#define MSTICK_RD_SRC DMA_UNDEF
+#define MSTICK_RD_DST DMA_UNDEF
+#define MSTICK_RD_CTL DMA_UNDEF
+#define MSTICK_WR_SRC_CTL DMA_UNDEF
+#define MSTICK_WR_DST_CTL DMA_UNDEF
+#define MSTICK_RD_SRC_CTL DMA_UNDEF
+#define MSTICK_RD_DST_CTL DMA_UNDEF
+
+#define AC97_WR_SRC DMA_UNDEF
+#define AC97_WR_DST DMA_UNDEF
+#define AC97_WR_CTL DMA_UNDEF
+#define AC97_RD_SRC DMA_UNDEF
+#define AC97_RD_DST DMA_UNDEF
+#define AC97_RD_CTL DMA_UNDEF
+#define AC97_WR_SRC_CTL DMA_UNDEF
+#define AC97_WR_DST_CTL DMA_UNDEF
+#define AC97_RD_SRC_CTL DMA_UNDEF
+#define AC97_RD_DST_CTL DMA_UNDEF
+
+#define IRDA_WR_SRC DMA_UNDEF
+#define IRDA_WR_DST DMA_UNDEF
+#define IRDA_WR_CTL DMA_UNDEF
+#define IRDA_RD_SRC DMA_UNDEF
+#define IRDA_RD_DST DMA_UNDEF
+#define IRDA_RD_CTL DMA_UNDEF
+#define IRDA_WR_SRC_CTL DMA_UNDEF
+#define IRDA_WR_DST_CTL DMA_UNDEF
+#define IRDA_RD_SRC_CTL DMA_UNDEF
+#define IRDA_RD_DST_CTL DMA_UNDEF
+
+static dma_type_t dma_types[4][8] = {
+{
+ { "XDREQ0", XDREQ0_WR_SRC, XDREQ0_WR_DST, XDREQ0_WR_CTL, \
+ XDREQ0_WR_SRC_CTL, XDREQ0_WR_DST_CTL, \
+ XDREQ0_RD_SRC, XDREQ0_RD_DST, XDREQ0_RD_CTL, \
+ XDREQ0_RD_SRC_CTL, XDREQ0_RD_DST_CTL },
+ { "UART0", UART0_WR_SRC, UART0_WR_DST, UART0_WR_CTL, \
+ UART0_WR_SRC_CTL, UART0_WR_DST_CTL, \
+ UART0_RD_SRC, UART0_RD_DST, UART0_RD_CTL, \
+ UART0_RD_SRC_CTL, UART0_RD_DST_CTL },
+ { "I2SSDI", I2SSDI_WR_SRC, I2SSDI_WR_DST, I2SSDI_WR_CTL, \
+ I2SSDI_WR_SRC_CTL, I2SSDI_WR_DST_CTL, \
+ I2SSDI_RD_SRC, I2SSDI_RD_DST, I2SSDI_RD_CTL, \
+ I2SSDI_RD_SRC_CTL, I2SSDI_RD_DST_CTL },
+ { "TIMER", TIMER_WR_SRC, TIMER_WR_DST, TIMER_WR_CTL, \
+ TIMER_WR_SRC_CTL, TIMER_WR_DST_CTL, \
+ TIMER_RD_SRC, TIMER_RD_DST, TIMER_RD_CTL, \
+ TIMER_RD_SRC_CTL, TIMER_RD_DST_CTL },
+ { "USB", USB_WR_SRC, USB_WR_DST, USB_WR_CTL, \
+ USB_WR_SRC_CTL, USB_WR_DST_CTL, \
+ USB_RD_SRC, USB_RD_DST, USB_RD_CTL, \
+ USB_RD_SRC_CTL, USB_RD_DST_CTL },
+ { "AC97PCMOUT", AC97PCMOUT_WR_SRC, AC97PCMOUT_WR_DST, AC97PCMOUT_WR_CTL, \
+ AC97PCMOUT_WR_SRC_CTL, AC97PCMOUT_WR_DST_CTL, \
+ AC97PCMOUT_RD_SRC, AC97PCMOUT_RD_DST, AC97PCMOUT_RD_CTL, \
+ AC97PCMOUT_RD_SRC_CTL, AC97PCMOUT_RD_DST_CTL },
+ { "MSTICK", MSTICK_WR_SRC, MSTICK_WR_DST, MSTICK_WR_CTL, \
+ MSTICK_WR_SRC_CTL, MSTICK_WR_DST_CTL, \
+ MSTICK_RD_SRC, MSTICK_RD_DST, MSTICK_RD_CTL, \
+ MSTICK_RD_SRC_CTL, MSTICK_RD_DST_CTL },
+ { "IRDA", IRDA_WR_SRC, IRDA_WR_DST, IRDA_WR_CTL, \
+ IRDA_WR_SRC_CTL, IRDA_WR_DST_CTL, \
+ IRDA_RD_SRC, IRDA_RD_DST, IRDA_RD_CTL, \
+ IRDA_RD_SRC_CTL, IRDA_RD_DST_CTL }
+},
+{
+ { "XDREQ1", XDREQ1_WR_SRC, XDREQ1_WR_DST, XDREQ1_WR_CTL, \
+ XDREQ1_WR_SRC_CTL, XDREQ1_WR_DST_CTL, \
+ XDREQ1_RD_SRC, XDREQ1_RD_DST, XDREQ1_RD_CTL, \
+ XDREQ1_RD_SRC_CTL, XDREQ1_RD_DST_CTL },
+ { "UART1", UART1_WR_SRC, UART1_WR_DST, UART1_WR_CTL, \
+ UART1_WR_SRC_CTL, UART1_WR_DST_CTL, \
+ UART1_RD_SRC, UART1_RD_DST, UART1_RD_CTL, \
+ UART1_RD_SRC_CTL, UART1_RD_DST_CTL },
+ { "I2SSDO", I2SSDO_WR_SRC, I2SSDO_WR_DST, I2SSDO_WR_CTL, \
+ I2SSDO_WR_SRC_CTL, I2SSDO_WR_DST_CTL, \
+ I2SSDO_RD_SRC, I2SSDO_RD_DST, I2SSDO_RD_CTL, \
+ I2SSDO_RD_SRC_CTL, I2SSDO_RD_DST_CTL },
+ { "SPI", SPI_WR_SRC, SPI_WR_DST, SPI_WR_CTL, \
+ SPI_WR_SRC_CTL, SPI_WR_DST_CTL, \
+ SPI_RD_SRC, SPI_RD_DST, SPI_WR_CTL, \
+ SPI_RD_SRC_CTL, SPI_RD_DST_CTL },
+ { "USB", USB_WR_SRC, USB_WR_DST, USB_WR_CTL, \
+ USB_WR_SRC_CTL, USB_WR_DST_CTL, \
+ USB_RD_SRC, USB_RD_DST, USB_RD_CTL, \
+ USB_RD_SRC_CTL, USB_RD_DST_CTL },
+ { "AC97PCMIN", AC97PCMIN_WR_SRC, AC97PCMIN_WR_DST, AC97PCMIN_WR_CTL, \
+ AC97PCMIN_WR_SRC_CTL, AC97PCMIN_WR_DST_CTL, \
+ AC97PCMIN_RD_SRC, AC97PCMIN_RD_DST, AC97PCMIN_RD_CTL, \
+ AC97PCMIN_RD_SRC_CTL, AC97PCMIN_RD_DST_CTL },
+ { "AC97", AC97_WR_SRC, AC97_WR_DST, AC97_WR_CTL, \
+ AC97_WR_SRC_CTL, AC97_WR_DST_CTL, \
+ AC97_RD_SRC, AC97_RD_DST, AC97_RD_CTL, \
+ AC97_RD_SRC_CTL, AC97_RD_DST_CTL },
+ { "IRDA", IRDA_WR_SRC, IRDA_WR_DST, IRDA_WR_CTL, \
+ IRDA_WR_SRC_CTL, IRDA_WR_DST_CTL, \
+ IRDA_RD_SRC, IRDA_RD_DST, IRDA_RD_CTL, \
+ IRDA_RD_SRC_CTL, IRDA_RD_DST_CTL }
+},
+{
+ { "UART0", UART0_WR_SRC, UART0_WR_DST, UART0_WR_CTL, \
+ UART0_WR_SRC_CTL, UART0_WR_DST_CTL, \
+ UART0_RD_SRC, UART0_RD_DST, UART0_RD_CTL, \
+ UART0_RD_SRC_CTL, UART0_RD_DST_CTL },
+ { "I2SSDO", I2SSDO_WR_SRC, I2SSDO_WR_DST, I2SSDO_WR_CTL, \
+ I2SSDO_WR_SRC_CTL, I2SSDO_WR_DST_CTL, \
+ I2SSDO_RD_SRC, I2SSDO_RD_DST, I2SSDO_RD_CTL, \
+ I2SSDO_RD_SRC_CTL, I2SSDO_RD_DST_CTL },
+ { "MMC", MMC_WR_SRC, MMC_WR_DST, MMC_WR_CTL, \
+ MMC_WR_SRC_CTL, MMC_WR_DST_CTL, \
+ MMC_RD_SRC, MMC_RD_SRC, MMC_RD_CTL, \
+ MMC_RD_SRC_CTL, MMC_RD_DST_CTL },
+ { "TIMER", TIMER_WR_SRC, TIMER_WR_DST, TIMER_WR_CTL, \
+ TIMER_WR_SRC_CTL, TIMER_WR_DST_CTL, \
+ TIMER_RD_SRC, TIMER_RD_DST, TIMER_RD_CTL, \
+ TIMER_RD_SRC_CTL, TIMER_RD_DST_CTL },
+ { "USB", USB_WR_SRC, USB_WR_DST, USB_WR_CTL, \
+ USB_WR_SRC_CTL, USB_WR_DST_CTL, \
+ USB_RD_SRC, USB_RD_DST, USB_RD_CTL, \
+ USB_RD_SRC_CTL, USB_RD_DST_CTL },
+ { "AC97MICIN", AC97MICIN_WR_SRC, AC97MICIN_WR_DST, AC97MICIN_WR_CTL, \
+ AC97MICIN_WR_SRC_CTL, AC97MICIN_WR_DST_CTL, \
+ AC97MICIN_RD_SRC, AC97MICIN_RD_DST, AC97MICIN_RD_CTL, \
+ AC97MICIN_RD_SRC_CTL, AC97MICIN_RD_DST_CTL },
+ { "AC97", AC97_WR_SRC, AC97_WR_DST, AC97_WR_CTL, \
+ AC97_WR_SRC_CTL, AC97_WR_DST_CTL, \
+ AC97_RD_SRC, AC97_RD_DST, AC97_RD_CTL, \
+ AC97_RD_SRC_CTL, AC97_RD_DST_CTL },
+ { "AC97", AC97_WR_SRC, AC97_WR_DST, AC97_WR_CTL, \
+ AC97_WR_SRC_CTL, AC97_WR_DST_CTL, \
+ AC97_RD_SRC, AC97_RD_DST, AC97_RD_CTL, \
+ AC97_RD_SRC_CTL, AC97_RD_DST_CTL }
+},
+{
+ { "UART1", UART1_WR_SRC, UART1_WR_DST, UART1_WR_CTL, \
+ UART1_WR_SRC_CTL, UART1_WR_DST_CTL, \
+ UART1_RD_SRC, UART1_RD_DST, UART1_RD_CTL, \
+ UART1_RD_SRC_CTL, UART1_RD_DST_CTL },
+ { "MMC", MMC_WR_SRC, MMC_WR_DST, MMC_WR_CTL, \
+ MMC_WR_SRC_CTL, MMC_WR_DST_CTL, \
+ MMC_RD_SRC, MMC_RD_SRC, MMC_RD_CTL, \
+ MMC_RD_SRC_CTL, MMC_RD_DST_CTL },
+ { "SPI", SPI_WR_SRC, SPI_WR_DST, SPI_WR_CTL, \
+ SPI_WR_SRC_CTL, SPI_WR_DST_CTL, \
+ SPI_RD_SRC, SPI_RD_DST, SPI_WR_CTL, \
+ SPI_RD_SRC_CTL, SPI_RD_DST_CTL },
+ { "TIMER", TIMER_WR_SRC, TIMER_WR_DST, TIMER_WR_CTL, \
+ TIMER_WR_SRC_CTL, TIMER_WR_DST_CTL, \
+ TIMER_RD_SRC, TIMER_RD_DST, TIMER_RD_CTL, \
+ TIMER_RD_SRC_CTL, TIMER_RD_DST_CTL },
+ { "USB", USB_WR_SRC, USB_WR_DST, USB_WR_CTL, \
+ USB_WR_SRC_CTL, USB_WR_DST_CTL, \
+ USB_RD_SRC, USB_RD_DST, USB_RD_CTL, \
+ USB_RD_SRC_CTL, USB_RD_DST_CTL },
+ { "MSTICK", MSTICK_WR_SRC, MSTICK_WR_DST, MSTICK_WR_CTL, \
+ MSTICK_WR_SRC_CTL, MSTICK_WR_DST_CTL, \
+ MSTICK_RD_SRC, MSTICK_RD_DST, MSTICK_RD_CTL, \
+ MSTICK_RD_SRC_CTL, MSTICK_RD_DST_CTL },
+ { "AC97", AC97_WR_SRC, AC97_WR_DST, AC97_WR_CTL, \
+ AC97_WR_SRC_CTL, AC97_WR_DST_CTL, \
+ AC97_RD_SRC, AC97_RD_DST, AC97_RD_CTL, \
+ AC97_RD_SRC_CTL, AC97_RD_DST_CTL },
+ { "AC97", AC97_WR_SRC, AC97_WR_DST, AC97_WR_CTL, \
+ AC97_WR_SRC_CTL, AC97_WR_DST_CTL, \
+ AC97_RD_SRC, AC97_RD_DST, AC97_RD_CTL, \
+ AC97_RD_SRC_CTL, AC97_RD_DST_CTL }
+}
+};
Structures should not be defined in header files
diff --git a/arch/arm/mach-s3c24a0/gpio.c b/arch/arm/mach-s3c24a0/gpio.c
new file mode 100644
index 0000000..e042864
--- /dev/null
+++ b/arch/arm/mach-s3c24a0/gpio.c
@@ -0,0 +1,196 @@
+/* linux/arch/arm/mach-s3c24A0/gpio.c
+ *
+ * Copyright (c) 2004 Simtec Electronics
+ * Ben Dooks
+ *
+ * S3C24A0 GPIO support
+ *
+ * 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
+ *
+ * Changelog
+ * 13-Sep-2004 BJD Implemented change of MISCCR
+ * 14-Sep-2004 BJD Added getpin call
+ * 14-Sep-2004 BJD Fixed bug in setpin() call
+ * 30-Sep-2004 BJD Fixed cfgpin() mask bug
+ * 01-Oct-2004 BJD Added getcfg() to get pin configuration
+ * 01-Oct-2004 BJD Fixed mask bug in pullup() call
+ * 01-Oct-2004 BJD Added getirq() to turn pin into irqno
+ * 04-Oct-2004 BJD Added irq filter controls for GPIO
+ * 05-Nov-2004 BJD EXPORT_SYMBOL() added for all code
+ */
thought i'd gotten rid of all these changelogs... they are redundant
as the version control system keeps the changes as well.
+
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+
+void s3c24a0_gpio_cfgpin(unsigned int pin, unsigned int function)
+{
+ unsigned long base = S3C24A0_GPIO_BASE(pin);
+ unsigned long mask;
+ unsigned long con;
+ unsigned long flags;
+ mask = 3 << (S3C24A0_GPIO_OFFSET(pin) * 2 );
+ local_irq_save(flags);
+ con = __raw_readl(base + 0x00);
+ con &= ~mask;
+ con |= function ;
+ __raw_writel(con, base + 0x00);
+ local_irq_restore(flags);
+}
+
+EXPORT_SYMBOL(s3c24a0_gpio_cfgpin);
+
+unsigned int s3c24A0_gpio_getcfg(unsigned int pin)
+{
+ unsigned long base = S3C24A0_GPIO_BASE(pin);
+ unsigned long mask;
+
+ mask = 3 << (S3C24A0_GPIO_OFFSET(pin)*2);
+
+ return __raw_readl(base) & mask;
+}
+
+EXPORT_SYMBOL(s3c24A0_gpio_getcfg);
+
+void s3c24a0_gpio_pullup(unsigned int pin, unsigned int to)
+{
+ unsigned long offs = S3C24A0_GPIO_PINNO(pin);
+ unsigned long flags;
+ unsigned long up;
+
+
+ local_irq_save(flags);
+
+ up = __raw_readl(S3C24A0_GPPU);
+ up &= ~(1L << offs);
+ up |= to << offs;
+ __raw_writel(up, S3C24A0_GPPU);
+
+ local_irq_restore(flags);
+}
+
+EXPORT_SYMBOL(s3c24a0_gpio_pullup);
+
+void s3c24A0_gpio_setpin(unsigned int pin, unsigned int to)
+{
+ unsigned long base = S3C24A0_GPDAT;
+ unsigned long offs = S3C24A0_GPIO_PINNO(pin);
+ unsigned long flags;
+ unsigned long dat;
+
+ local_irq_save(flags);
+ dat = __raw_readl(base );
+ dat &= ~(1 << offs);
+ dat |= to << offs;
+ __raw_writel(dat, base );
+
+ local_irq_restore(flags);
+}
+
+EXPORT_SYMBOL(s3c24A0_gpio_setpin);
+
+unsigned int s3c24A0_gpio_getpin(unsigned int pin)
+{
+ unsigned long base = S3C24A0_GPDAT;
+ unsigned long offs = S3C24A0_GPIO_PINNO(pin);
+
+ return __raw_readl(base) & (1<< offs);
+}
+
+EXPORT_SYMBOL(s3c24A0_gpio_getpin);
+
+#if 0
+unsigned int s3c24a0_modify_misccr(unsigned int clear, unsigned int change)
+{
+ unsigned long flags;
+ unsigned long misccr;
+
+ local_irq_save(flags);
+ misccr = __raw_readl(S3C24A0_MISCCR);
+ misccr &= ~clear;
+ misccr ^= change;
+ __raw_writel(misccr, S3C24A0_MISCCR);
+ local_irq_restore(flags);
+
+ return misccr;
+}
+
+EXPORT_SYMBOL(s3c24a0_modify_misccr);
+
+int s3c24a0_gpio_getirq(unsigned int pin)
+{
+ if (pin < S3C24A0_GPF0 || pin > S3C24A0_GPG15_EINT23)
+ return -1; /* not valid interrupts */
+
+ if (pin < S3C24A0_GPG0 && pin > S3C24A0_GPF7)
+ return -1; /* not valid pin */
+
+ if (pin < S3C24A0_GPF4)
+ return (pin - S3C24A0_GPF0) + IRQ_EINT0;
+
+ if (pin < S3C24A0_GPG0)
+ return (pin - S3C24A0_GPF4) + IRQ_EINT4;
+
+ return (pin - S3C24A0_GPG0) + IRQ_EINT8;
+}
+
+EXPORT_SYMBOL(s3c24a0_gpio_getirq);
+
+int s3c24a0_gpio_irqfilter(unsigned int pin, unsigned int on,
+ unsigned int config)
+{
+ unsigned long reg = S3C24A0_EINFLT0;
+ unsigned long flags;
+ unsigned long val;
+
+ if (pin < S3C24A0_GPG8 || pin > S3C24A0_GPG15)
+ return -1;
+
+ config &= 0xff;
+
+ pin -= S3C24A0_GPG8_EINT16;
+ reg += pin & ~3;
+
+ local_irq_save(flags);
+
+ /* update filter width and clock source */
+
+ val = __raw_readl(reg);
+ val &= ~(0xff << ((pin & 3) * 8));
+ val |= config << ((pin & 3) * 8);
+ __raw_writel(val, reg);
+
+ /* update filter enable */
+
+ val = __raw_readl(S3C24A0_EXTINT2);
+ val &= ~(1 << ((pin * 4) + 3));
+ val |= on << ((pin * 4) + 3);
+ __raw_writel(val, S3C24A0_EXTINT2);
+
+ local_irq_restore(flags);
+
+ return 0;
+}
+
+EXPORT_SYMBOL(s3c24a0_gpio_irqfilter);
+#endif
+
diff --git a/arch/arm/mach-s3c24a0/irq.c b/arch/arm/mach-s3c24a0/irq.c
new file mode 100644
index 0000000..23b4f55
--- /dev/null
+++ b/arch/arm/mach-s3c24a0/irq.c
@@ -0,0 +1,1134 @@
+/* linux/arch/arm/mach-s3c24a0/irq.c
+ * s3c24a0_pm_timer_update();
+ *
+ * $Id: irq.c,v 1.1.1.1 2006/02/13 05:22:49 ihlee215 Exp $
+ *
+ * Copyright (C) 2005, Sean Choi
+ * All rights reserved.
+ *
+ * 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
+ *
+ * derived from linux/include/asm-arm/arch-s3c2410/map.h, written by
+ * Ben Dooks
+ *
+*/
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+#include
+
+#include
+#include
+
+#include "pm.h"
+
+#define irqdbf(x...)
+#define irqdbf2(x...)
+
+static void
+s3c_irq_mask(unsigned int irqno)
+{
+ unsigned long mask;
+
+ irqno -= IRQ_EINT0_2;
+
+ mask = __raw_readl(S3C24A0_INTMSK);
+ mask |= 1UL << irqno;
+ __raw_writel(mask, S3C24A0_INTMSK);
+}
+
+static inline void
+s3c_irq_ack(unsigned int irqno)
+{
+ unsigned long bitval = 1UL << (irqno - IRQ_EINT0_2);
+
+ __raw_writel(bitval, S3C24A0_SRCPND);
+ __raw_writel(bitval, S3C24A0_INTPND);
+}
+
+static inline void
+s3c_irq_maskack(unsigned int irqno)
+{
+ unsigned long bitval = 1UL << (irqno - IRQ_EINT0_2);
+ unsigned long mask;
+
+ mask = __raw_readl(S3C24A0_INTMSK);
+ __raw_writel(mask|bitval, S3C24A0_INTMSK);
+
+ __raw_writel(bitval, S3C24A0_SRCPND);
+ __raw_writel(bitval, S3C24A0_INTPND);
+}
+
+
+static void
+s3c_irq_unmask(unsigned int irqno)
+{
+ unsigned long mask;
+
+ irqno -= IRQ_EINT0_2;
+
+ mask = __raw_readl(S3C24A0_INTMSK);
+ mask &= ~(1UL << irqno);
+ __raw_writel(mask, S3C24A0_INTMSK);
+}
+
+static struct irq_chip s3c_irq_level_chip = {
+ .ack = s3c_irq_maskack,
+ .mask = s3c_irq_mask,
+ .unmask = s3c_irq_unmask,
+};
+
+static struct irq_chip s3c_irq_chip = {
+ .ack = s3c_irq_ack,
+ .mask = s3c_irq_mask,
+ .unmask = s3c_irq_unmask,
+};
+
+/* EINTMASK
+ * EINTPEND
+ */
+
+static void
+s3c_irqext_mask(unsigned int irqno)
+{
+ unsigned long mask;
+
+ irqno -= IRQ_EINT0;
+
+ mask = __raw_readl(S3C24A0_EINTMASK);
+ mask |= ( 1UL << irqno);
+ __raw_writel(mask, S3C24A0_EINTMASK);
+
+ if (irqno <= (IRQ_EINT2 - IRQ_EINT0)) {
+ /* check to see if all need masking */
+ if ((mask & 0x7) == 0x7) {
+ /* all masked, mask the parent */
+ s3c_irq_mask(IRQ_EINT0_2);
+ }
+ }
+ else if ((irqno <= (IRQ_EINT6 - IRQ_EINT0))&&(irqno > (IRQ_EINT2 - IRQ_EINT0))) {
+ /* check to see if all need masking */
+ if ((mask & (0xf << 3)) == (0xf << 3)) {
+ /* all masked, mask the parent */
+ s3c_irq_mask(IRQ_EINT3_6);
+ }
+ }
+ else if ((irqno <= (IRQ_EINT10 - IRQ_EINT0))&&(irqno > (IRQ_EINT6 - IRQ_EINT0))) {
+ /* check to see if all need masking */
+ if ((mask & (0xf << 7)) == (0xf << 7)) {
+ /* all masked, mask the parent */
+ s3c_irq_mask(IRQ_EINT7_10);
+ }
+ }
+ else if ((irqno <= (IRQ_EINT14 - IRQ_EINT0))&&(irqno > (IRQ_EINT10 - IRQ_EINT0))) {
+ /* check to see if all need masking */
+ if ((mask & (0xf << 11)) == (0xf << 11)) {
+ /* all masked, mask the parent */
+ s3c_irq_mask(IRQ_EINT11_14);
+ }
+ }
+ else {
+ /* check to see if all need masking */
+ if ((mask & (0xf << 15)) == (0xf << 15)) {
+ /* all masked, mask the parent */
+ s3c_irq_mask(IRQ_EINT15_18);
+ }
+ }
+}
+
+static void
+s3c_irqext_ack(unsigned int irqno)
+{
+ unsigned long bit;
+
+ bit = 1UL << (irqno - IRQ_EINT0);
+
+ __raw_writel(bit, S3C24A0_EINTPEND);
+
+ /* not sure if we should be acking the parent irq... */
+
+ if (irqno <= IRQ_EINT2 )
+ s3c_irq_ack(IRQ_EINT0_2);
+ else if (irqno <= IRQ_EINT6 && irqno > IRQ_EINT2 )
+ s3c_irq_ack(IRQ_EINT3_6);
+ else if (irqno <= IRQ_EINT10 && irqno > IRQ_EINT6 )
+ s3c_irq_ack(IRQ_EINT7_10);
+ else if (irqno <= IRQ_EINT14 && irqno > IRQ_EINT10 )
+ s3c_irq_ack(IRQ_EINT11_14);
+ else
+ s3c_irq_ack(IRQ_EINT15_18);
+}
+
+static void
+s3c_irqext_unmask(unsigned int irqno)
+{
+ unsigned long mask;
+
+ irqno -= IRQ_EINT0;
+
+ mask = __raw_readl(S3C24A0_EINTMASK);
+ mask &= ~( 1UL << irqno);
+ __raw_writel(mask, S3C24A0_EINTMASK);
+
+ if (irqno <= (IRQ_EINT2 - IRQ_EINT0))
+ s3c_irq_unmask(IRQ_EINT0_2);
+ else if ((irqno <= (IRQ_EINT6 - IRQ_EINT0))&&(irqno > (IRQ_EINT2 - IRQ_EINT0)))
+ s3c_irq_unmask(IRQ_EINT3_6);
+ else if ((irqno <= (IRQ_EINT10 - IRQ_EINT0))&&(irqno > (IRQ_EINT6 - IRQ_EINT0)))
+ s3c_irq_unmask(IRQ_EINT7_10);
+ else if ((irqno <= (IRQ_EINT14 - IRQ_EINT0))&&(irqno > (IRQ_EINT10 - IRQ_EINT0)))
+ s3c_irq_unmask(IRQ_EINT11_14);
+ else
+ s3c_irq_unmask(IRQ_EINT15_18);
+}
+
+
+static int
+s3c_irqext_type(unsigned int irq, unsigned int type)
+{
+ unsigned long extint_reg;
+ unsigned long gpcon_reg;
+ unsigned long gpcon_offset, extint_offset;
+ unsigned long newvalue = 0, value;
+ unsigned int irq_r;
+
+ irq_r = irq - IRQ_EINT0;
+ if ((irq_r >= 0) && (irq_r <= 2))
+ {
+ gpcon_reg = S3C24A0_GPCONL;
+ extint_reg = S3C24A0_EINTCR0;
+ gpcon_offset = (irq_r) * 2;
+ extint_offset = (irq_r) * 4;
+ }
+ else if ((irq_r >= 3) && (irq_r <= 10))
+ {
+ gpcon_reg = S3C24A0_GPCONL;
+ extint_reg = S3C24A0_EINTCR1;
+ gpcon_offset = (irq_r) * 2;
+ extint_offset = (irq_r-3) * 4;
+ }
+ else if ((irq_r >= 11) && (irq_r <= 18))
+ {
+ gpcon_reg = S3C24A0_GPCONM;
+ extint_reg = S3C24A0_EINTCR2;
+ gpcon_offset = (irq_r-11) * 2;
+ extint_offset = (irq_r-11) * 4;
+ }
+ else
+ return -1;
These would have been better off for readability if left as EINT_xxx
then using the irq_r as an intermediate.
+ /* Set the GPIO to external interrupt mode */
+ value = __raw_readl(gpcon_reg);
+ value = (value & ~(3 << gpcon_offset)) | (0x2 << gpcon_offset);
+ __raw_writel(value, gpcon_reg);
+
+ /* Set the external interrupt to pointed trigger type */
+ switch (type)
+ {
bad code style, use
switch (type) {
+ case IRQT_NOEDGE:
+ printk(KERN_WARNING "No edge setting!\n");
+ break;
+
+ case IRQT_RISING:
+ newvalue = S3C24A0_EXTINT_RISEEDGE;
+ break;
+
+ case IRQT_FALLING:
+ newvalue = S3C24A0_EXTINT_FALLEDGE;
+ break;
+
+ case IRQT_BOTHEDGE:
+ newvalue = S3C24A0_EXTINT_BOTHEDGE;
+ break;
+
+ case IRQT_LOW:
+ newvalue = S3C24A0_EXTINT_LOWLEV;
+ break;
+
+ case IRQT_HIGH:
+ newvalue = S3C24A0_EXTINT_HILEV;
+ break;
+
+ default:
+ printk(KERN_ERR "s3c_irqext_type:No such irq type %d", type);
+ return -1;
+ }
+
+ /* Set the external interrupt type */
+ value = __raw_readl(extint_reg);
+ value = (value & ~(7 << extint_offset)) | (newvalue << extint_offset);
+ __raw_writel(value, extint_reg);
+ return 0;
+}
+
+static int s3c_irqext_wake(unsigned int irq, unsigned int type)
+{
+ /* Check if the irqno passed is one of the wake-up sources */
+ if (irq < IRQ_EINT0 && irq > IRQ_EINT9) {
+ printk("Invalid External interrupt number!\n");
+ return -EINVAL;
+ }
+
+ if((s3c_irqext_type(irq, type)) == -1)
+ return -1;
+
+ s3c_irqext_ack(irq);
+ s3c_irqext_unmask(irq);
+ return 0;
+}
+
+static struct irq_chip s3c_irqext_chip = {
+ .mask = s3c_irqext_mask,
+ .unmask = s3c_irqext_unmask,
+ .ack = s3c_irqext_ack,
+ .set_type = s3c_irqext_type,
+ .set_wake = s3c_irqext_wake,
+};
+
+/* mask values for the parent registers for each of the interrupt types */
+
+#define INTMSK_UART0 (1UL << 17)
+#define INTMSK_UART1 (1UL << 23)
+#define INTMSK_ADCPARENT (1UL << 31)
+#define INTMSK_LCD (1UL << 14)
+#define INTMSK_RTC (1UL << 30)
+#define INTMSK_TIMER3_4 (1UL << 13)
+#define INTMSK_WDT_BATFLT (1UL << 16)
+#define INTMSK_AC97_NF (1UL << 24)
+#define INTMSK_DMA (1UL << 20)
+#define INTMSK_IRDA_MS (1UL << 28)
+
+static inline void
+s3c_irqsub_mask(unsigned int irqno, unsigned int parentbit,
+ int subcheck)
+{
+ unsigned long mask;
+ unsigned long submask;
+
+ submask = __raw_readl(S3C24A0_INTSUBMSK);
+ mask = __raw_readl(S3C24A0_INTMSK);
+
+ submask |= (1UL << (irqno - IRQ_RXD0));
+
+ /* check to see if we need to mask the parent IRQ */
+ if ((submask & subcheck) == subcheck) {
+ __raw_writel(mask | parentbit, S3C24A0_INTMSK);
+ }
+
+ /* write back masks */
+ __raw_writel(submask, S3C24A0_INTSUBMSK);
+
+}
+
+static inline void
+s3c_irqsub_unmask(unsigned int irqno, unsigned int parentbit)
+{
+ unsigned long mask;
+ unsigned long submask;
+
+ submask = __raw_readl(S3C24A0_INTSUBMSK);
+ mask = __raw_readl(S3C24A0_INTMSK);
+ submask &= ~(1UL << (irqno - IRQ_RXD0));
+ mask &= ~parentbit;
+
+ /* write back masks */
+ __raw_writel(submask, S3C24A0_INTSUBMSK);
+ __raw_writel(mask, S3C24A0_INTMSK);
+}
+
+
+static inline void
+s3c_irqsub_maskack(unsigned int irqno, unsigned int parentmask, unsigned int group)
+{
+ unsigned int bit = 1UL << (irqno - IRQ_RXD0);
+
+ s3c_irqsub_mask(irqno, parentmask, group);
+
+ __raw_writel(bit, S3C24A0_SUBSRCPND);
+
+ /* only ack parent if we've got all the irqs (seems we must
+ * ack, all and hope that the irq system retriggers ok when
+ * the interrupt goes off again)
+ */
+ __raw_writel(parentmask, S3C24A0_SRCPND);
+ __raw_writel(parentmask, S3C24A0_INTPND);
+}
+
+
+/* UART0 */
+
+static void
+s3c_irq_uart0_mask(unsigned int irqno)
+{
+ s3c_irqsub_mask(irqno, INTMSK_UART0, 7);
+}
+
+static void
+s3c_irq_uart0_unmask(unsigned int irqno)
+{
+ s3c_irqsub_unmask(irqno, INTMSK_UART0);
+}
+
+static void
+s3c_irq_uart0_ack(unsigned int irqno)
+{
+ s3c_irqsub_maskack(irqno, INTMSK_UART0, 7);
+}
+
+static struct irq_chip s3c_irq_uart0 = {
+ .mask = s3c_irq_uart0_mask,
+ .unmask = s3c_irq_uart0_unmask,
+ .ack = s3c_irq_uart0_ack,
+};
+
+/* UART1 */
+
+static void
+s3c_irq_uart1_mask(unsigned int irqno)
+{
+ s3c_irqsub_mask(irqno, INTMSK_UART1, 7 << 3);
+}
+
+static void
+s3c_irq_uart1_unmask(unsigned int irqno)
+{
+ s3c_irqsub_unmask(irqno, INTMSK_UART1);
+}
+
+static void
+s3c_irq_uart1_ack(unsigned int irqno)
+{
+ s3c_irqsub_maskack(irqno, INTMSK_UART1, 7 << 3);
+}
+
+static struct irq_chip s3c_irq_uart1 = {
+ .mask = s3c_irq_uart1_mask,
+ .unmask = s3c_irq_uart1_unmask,
+ .ack = s3c_irq_uart1_ack,
+};
+
+/* TIMER3_4 */
+
+static void
+s3c_irq_timer3_4_mask(unsigned int irqno)
+{
+ s3c_irqsub_mask(irqno, INTMSK_TIMER3_4, 3 << 11);
+}
+
+static void
+s3c_irq_timer3_4_unmask(unsigned int irqno)
+{
+ s3c_irqsub_unmask(irqno, INTMSK_TIMER3_4);
+}
+
+static void
+s3c_irq_timer3_4_ack(unsigned int irqno)
+{
+ s3c_irqsub_maskack(irqno, INTMSK_TIMER3_4, 3 << 11);
+}
+
+static struct irq_chip s3c_irq_timer3_4 = {
+ .ack = s3c_irq_timer3_4_ack,
+ .mask = s3c_irq_timer3_4_mask,
+ .unmask = s3c_irq_timer3_4_unmask,
+};
+
+/* AC97 & NAND Flash */
+
+static void
+s3c_irq_ac97_nflash_mask(unsigned int irqno)
+{
+ s3c_irqsub_mask(irqno, INTMSK_AC97_NF, 3 << 21);
+}
+
+static void
+s3c_irq_ac97_nflash_unmask(unsigned int irqno)
+{
+ s3c_irqsub_unmask(irqno, INTMSK_AC97_NF);
+}
+
+static void
+s3c_irq_ac97_nflash_ack(unsigned int irqno)
+{
+ s3c_irqsub_maskack(irqno, INTMSK_AC97_NF, 3 << 21);
+}
+
+static struct irq_chip s3c_irq_ac97_nflash = {
+ .ack = s3c_irq_ac97_nflash_ack,
+ .mask = s3c_irq_ac97_nflash_mask,
+ .unmask = s3c_irq_ac97_nflash_unmask,
+};
+
+
+/* Watchdog & BATFLT */
+
+static void
+s3c_irq_wdt_batflt_mask(unsigned int irqno)
+{
+ s3c_irqsub_mask(irqno, INTMSK_WDT_BATFLT, 3 << 13);
+}
+
+static void
+s3c_irq_wdt_batflt_unmask(unsigned int irqno)
+{
+ s3c_irqsub_unmask(irqno, INTMSK_WDT_BATFLT);
+}
+
+static void
+s3c_irq_wdt_batflt_ack(unsigned int irqno)
+{
+ s3c_irqsub_maskack(irqno, INTMSK_WDT_BATFLT, 3 << 13);
+}
+
+static struct irq_chip s3c_irq_wdt_batflt = {
+ .ack = s3c_irq_wdt_batflt_ack,
+ .mask = s3c_irq_wdt_batflt_mask,
+ .unmask = s3c_irq_wdt_batflt_unmask,
+};
+
+
+/* RTC */
+static struct irq_chip s3c_irq_rtc = {
+ .ack = s3c_irq_ack,
+ .mask = s3c_irq_mask,
+ .unmask = s3c_irq_unmask,
+};
+
+
+
+/* DMA */
+
+static void
+s3c_irq_dma0_3_mask(unsigned int irqno)
+{
+ s3c_irqsub_mask(irqno, INTMSK_DMA, 0xf << 25);
+}
+
+static void
+s3c_irq_dma0_3_unmask(unsigned int irqno)
+{
+ s3c_irqsub_unmask(irqno, INTMSK_DMA);
+}
+
+static void
+s3c_irq_dma0_3_ack(unsigned int irqno)
+{
+ s3c_irqsub_maskack(irqno, INTMSK_DMA, 0xf << 25);
+}
+
+static struct irq_chip s3c_irq_dma0_3 = {
+ .ack = s3c_irq_dma0_3_ack,
+ .mask = s3c_irq_dma0_3_mask,
+ .unmask = s3c_irq_dma0_3_unmask,
+};
+
+
+
+/* ADC and Touchscreen */
+
+static void
+s3c_irq_adc_mask(unsigned int irqno)
+{
+ s3c_irqsub_mask(irqno, INTMSK_ADCPARENT, 7 << 17);
+}
+
+static void
+s3c_irq_adc_unmask(unsigned int irqno)
+{
+ s3c_irqsub_unmask(irqno, INTMSK_ADCPARENT);
+}
+
+static void
+s3c_irq_adc_ack(unsigned int irqno)
+{
+ s3c_irqsub_maskack(irqno, INTMSK_ADCPARENT, 7 << 17);
+}
+
+static struct irq_chip s3c_irq_adc = {
+ .mask = s3c_irq_adc_mask,
+ .unmask = s3c_irq_adc_unmask,
+ .ack = s3c_irq_adc_ack,
+};
+
+/* IrDA & Memory Stick */
+
+static void
+s3c_irq_irda_ms_mask(unsigned int irqno)
+{
+ s3c_irqsub_mask(irqno, INTMSK_IRDA_MS, 3 << 6);
+}
+
+static void
+s3c_irq_irda_ms_unmask(unsigned int irqno)
+{
+ s3c_irqsub_unmask(irqno, INTMSK_IRDA_MS);
+}
+
+static void
+s3c_irq_irda_ms_ack(unsigned int irqno)
+{
+ s3c_irqsub_maskack(irqno, INTMSK_IRDA_MS, 3 << 6);
+}
+
+static struct irq_chip s3c_irq_irda_ms = {
+ .ack = s3c_irq_irda_ms_ack,
+ .mask = s3c_irq_irda_ms_mask,
+ .unmask = s3c_irq_irda_ms_unmask,
+};
+
+
+/* irq demux for adc */
+static void s3c_irq_demux_adc(unsigned int irq,
+ struct irq_desc *desc)
+{
+ unsigned int subsrc, submsk;
+ unsigned int offset = 17;
+ struct irq_desc *mydesc;
+
+ /* read the current pending interrupts, and the mask
+ * for what it is available */
+
+ subsrc = __raw_readl(S3C24A0_SUBSRCPND);
+ submsk = __raw_readl(S3C24A0_INTSUBMSK);
+
+ subsrc &= ~submsk;
+ subsrc >>= offset;
+ subsrc &= 7;
+
+ if (subsrc != 0) {
+ // mydesc = irq_desc+ IRQ_PENUP;
+ if (subsrc & 1) {
+ mydesc = irq_desc+ IRQ_PENUP;
+ // mydesc++; //TODO: swlab choish
+ mydesc->handle_irq( IRQ_PENUP, mydesc);
+ }
+ if (subsrc & 2) {
+ mydesc = irq_desc+ IRQ_PENDN;
+ // mydesc++;
+ mydesc->handle_irq(IRQ_PENDN, mydesc);
+ }
+ if (subsrc & 4) {
+ mydesc = irq_desc+ IRQ_ADC;
+ // mydesc++;
+ mydesc->handle_irq(IRQ_ADC, mydesc);
+ }
+ }
+}
+
+static void s3c_irq_demux_uart(unsigned int start)
+{
+ unsigned int subsrc, submsk;
+ unsigned int offset = start - IRQ_RXD0;
+ struct irq_desc *desc;
+
+ /* read the current pending interrupts, and the mask
+ * for what it is available */
+
+ subsrc = __raw_readl(S3C24A0_SUBSRCPND);
+ submsk = __raw_readl(S3C24A0_INTSUBMSK);
+
+#if 0
+ if( start == IRQ_RXD1) {
+ //irqdbf2("s3c_irq_demux_uart: start=%d (%d), subsrc=0x%08x,0x%08x\n",
+ printk("s3c_irq_demux_uart: start=%d (%d), subsrc=0x%08x,0x%08x\n",
+ start, offset, subsrc, submsk);
+ }
+#endif
+ subsrc &= ~submsk;
+ subsrc >>= offset;
+ subsrc &= 7;
+
+ if (subsrc != 0) {
+ desc = irq_desc + start;
+
+ if (subsrc & 1)
+ desc->handle_irq(start, desc);
+
+ desc++;
+
+ if (subsrc & 2)
+ desc->handle_irq(start+1, desc);
+
+ desc++;
+
+ if (subsrc & 4)
+ desc->handle_irq(start+2, desc);
+ }
+}
+
+static void s3c_irq_demux_timer(unsigned int start)
+{
+ unsigned int subsrc, submsk;
+ unsigned int offset = start - IRQ_RXD0;
+ struct irq_desc *desc;
+
+ /* read the current pending interrupts, and the mask
+ * for what it is available */
+
+ subsrc = __raw_readl(S3C24A0_SUBSRCPND);
+ submsk = __raw_readl(S3C24A0_INTSUBMSK);
+
+ irqdbf2("s3c_irq_demux_timer: start=%d (%d), subsrc=0x%08x,0x%08x\n",
+ start, offset, subsrc, submsk);
+
+ subsrc &= ~submsk;
+ subsrc >>= offset;
+ subsrc &= 3;
+
+
+ if (subsrc != 0) {
+ desc = irq_desc + start;
+
+ if (subsrc & 1)
+ desc->handle_irq(start, desc);
+
+ desc++;
+
+ if (subsrc & 2)
+ desc->handle_irq(start+1, desc);
+ }
+}
+
+static void s3c_irq_demux_ac97_nf(unsigned int start)
+{
+ unsigned int subsrc, submsk;
+ unsigned int offset = start - IRQ_RXD0;
+ struct irq_desc *desc;
+
+ /* read the current pending interrupts, and the mask
+ * for what it is available */
+
+
+ subsrc = __raw_readl(S3C24A0_SUBSRCPND);
+ submsk = __raw_readl(S3C24A0_INTSUBMSK);
+
+ irqdbf2("s3c_irq_demux_ac97_nflash: start=%d (%d), subsrc=0x%08x,0x%08x\n",
+ start, offset, subsrc, submsk);
+
+ subsrc &= ~submsk;
+ subsrc >>= offset;
+ subsrc &= 3;
+
+
+ if (subsrc != 0) {
+ desc = irq_desc + start;
+
+ if (subsrc & 1)
+ desc->handle_irq(start, desc);
+
+ desc++;
+
+ if (subsrc & 2)
+ desc->handle_irq(start+1, desc);
+ }
+}
+
+
+static void s3c_irq_demux_wdt_batflt(unsigned int start)
+{
+ unsigned int subsrc, submsk;
+ unsigned int offset = start - IRQ_RXD0;
+ struct irq_desc *desc;
+
+ /* read the current pending interrupts, and the mask
+ * for what it is available */
+
+
+ subsrc = __raw_readl(S3C24A0_SUBSRCPND);
+ submsk = __raw_readl(S3C24A0_INTSUBMSK);
+
+ irqdbf2("s3c_irq_demux_wdt_batflt: start=%d (%d), subsrc=0x%08x,0x%08x\n",
+ start, offset, subsrc, submsk);
+
+ subsrc &= ~submsk;
+ subsrc >>= offset;
+ subsrc &= 3;
+
+
+ if (subsrc != 0) {
+ desc = irq_desc + start;
+
+ if (subsrc & 1)
+ desc->handle_irq(start, desc);
+
+ desc++;
+
+ if (subsrc & 2)
+ desc->handle_irq(start+1, desc);
+ }
+}
+
+
+
+
+static void s3c_irq_demux_dma(unsigned int start)
+{
+ unsigned int subsrc, submsk;
+ unsigned int offset = start - IRQ_RXD0;
+ struct irq_desc *desc;
+
+ /* read the current pending interrupts, and the mask
+ * for what it is available */
+
+ subsrc = __raw_readl(S3C24A0_SUBSRCPND);
+ submsk = __raw_readl(S3C24A0_INTSUBMSK);
+
+
+ irqdbf2("s3c_irq_demux_dma: start=%d (%d), subsrc=0x%08x,0x%08x\n",
+ start, offset, subsrc, submsk);
+
+
+ subsrc &= ~submsk;
+ subsrc >>= offset;
+ subsrc &= 0xf;
+
+
+ if (subsrc != 0) {
+ desc = irq_desc + start;
+
+ if (subsrc & 1)
+ desc->handle_irq(start, desc);
+
+ desc++;
+
+ if (subsrc & 2)
+ desc->handle_irq(start+1, desc);
+ desc++;
+
+ if (subsrc & 4)
+ desc->handle_irq(start+2, desc);
+ desc++;
+
+ if (subsrc & 8)
+ desc->handle_irq(start+3, desc);
+
+ }
+}
+
+static void s3c_irq_demux_irda_ms(unsigned int start)
+{
+ unsigned int subsrc, submsk;
+ unsigned int offset = start - IRQ_RXD0;
+ struct irq_desc *desc;
+
+ /* read the current pending interrupts, and the mask
+ * for what it is available */
+
+
+ subsrc = __raw_readl(S3C24A0_SUBSRCPND);
+ submsk = __raw_readl(S3C24A0_INTSUBMSK);
+
+// printk("s3c_irq_demux_irda_ms: start=%d (%d), subsrc=0x%08x,0x%08x\n",
+// start, offset, subsrc, submsk);
+
+ subsrc &= ~submsk;
+ subsrc >>= offset;
+ subsrc &= 3;
+
+
+ if (subsrc != 0) {
+ desc = irq_desc + start;
+
+ if (subsrc & 1)
+ desc->handle_irq(start, desc);
+
+ desc++;
+
+ if (subsrc & 2)
+ desc->handle_irq(start+1, desc);
+ }
+}
+
+
+/* uart demux entry points */
+
+static void
+s3c_irq_demux_uart0(unsigned int irq,
+ struct irq_desc *desc)
+{
+ irq = irq;
+ s3c_irq_demux_uart(IRQ_RXD0);
+}
+
+static void
+s3c_irq_demux_uart1(unsigned int irq,
+ struct irq_desc *desc)
+{
+ irq = irq;
+ s3c_irq_demux_uart(IRQ_RXD1);
+}
+
+/* timer demux entry points */
+static void
+s3c_irq_demux_timer3_4(unsigned int irq,
+ struct irq_desc *desc)
+{
+ irq = irq;
+ s3c_irq_demux_timer(IRQ_TIMER3);
+}
+
+/* ac97 Nand flash demux entry points */
+static void
+s3c_irq_demux_ac97_nflash(unsigned int irq,
+ struct irq_desc *desc)
+{
+ irq = irq;
+ s3c_irq_demux_ac97_nf(IRQ_NFLASH);
+}
+
+/* ac97 Nand flash demux entry points */
+static void
+s3c_irq_demux_watchdog_batteryfault(unsigned int irq,
+ struct irq_desc *desc)
+{
+ irq = irq;
+ s3c_irq_demux_wdt_batflt(IRQ_WDT);
+}
+
+
+/* dma demux entry points */
+static void
+s3c_irq_demux_dma0_3(unsigned int irq,
+ struct irq_desc *desc)
+{
+ irq = irq;
+ s3c_irq_demux_dma(IRQ_DMA0);
+}
+
+/* Irda and MS demux entry points */
+static void
+__s3c_irq_demux_irda_ms(unsigned int irq,
+ struct irq_desc *desc)
+{
+ irq = irq;
+ s3c_irq_demux_irda_ms(IRQ_IRDA);
+}
+/* s3c24a0_init_irq
+ *
+ * Initialise S3C24A0 IRQ system
+*/
+
+void __init s3c24a0_init_irq(void)
+{
+ unsigned long pend;
+ unsigned long last;
+ int irqno;
+ int i;
+ unsigned long value_e;
+
+ irqdbf("s3c24a0_init_irq: clearing interrupt status flags\n");
+
+ /* first, clear all interrupts pending... */
+
+ last = 0;
+ for (i = 0; i < 4; i++) {
+ pend = __raw_readl(S3C24A0_EINTPEND);
+
+ if (pend == 0 || pend == last)
+ break;
+
+ __raw_writel(pend, S3C24A0_EINTPEND);
+ printk("irq: clearing pending ext status %08x\n", (int)pend);
+ last = pend;
+ }
+
+ last = 0;
+ for (i = 0; i < 4; i++) {
+ pend = __raw_readl(S3C24A0_INTPND);
+
+ if (pend == 0 || pend == last)
+ break;
+
+ __raw_writel(pend, S3C24A0_SRCPND);
+ __raw_writel(pend, S3C24A0_INTPND);
+ printk("irq: clearing pending status %08x\n", (int)pend);
+ last = pend;
+ }
+
+ last = 0;
+ for (i = 0; i < 4; i++) {
+ pend = __raw_readl(S3C24A0_SUBSRCPND);
+
+ if (pend == 0 || pend == last)
+ break;
+
+ printk("irq: clearing subpending status %08x\n", (int)pend);
+ __raw_writel(pend, S3C24A0_SUBSRCPND);
+ last = pend;
+ }
+
+ /* register the main interrupts */
+
+ irqdbf("s3c24a0_init_irq: registering s3c24a0 interrupt handlers\n");
+
+ for (irqno = IRQ_TICK; irqno <= IRQ_ADC_PENUPDN; irqno++) {
+ /* set all the s3c24a0 internal irqs */
+
+ switch (irqno) {
+ /* deal with the special IRQs (cascaded) */
+
+ case IRQ_UART0:
+ case IRQ_DMA:
+ case IRQ_UART1:
+ case IRQ_LCD_POST:
+ case IRQ_ADC_PENUPDN:
+ case IRQ_IRDA_MSTICK:
+ set_irq_chip(irqno, &s3c_irq_level_chip);
+ set_irq_handler(irqno, handle_level_irq);
+ break;
+
+ case IRQ_RTC :
+ set_irq_chip(irqno, &s3c_irq_rtc);
+ set_irq_handler(irqno, handle_level_irq);
+ set_irq_flags(irqno, IRQF_VALID);
+ break;
+
+ case IRQ_TICK :
+ set_irq_chip(irqno, &s3c_irq_rtc);
+ set_irq_handler(irqno, handle_level_irq);
+ set_irq_flags(irqno, IRQF_VALID);
+ break;
+
+ case IRQ_WDT_BATFLT :
+ set_irq_chip(irqno, &s3c_irq_level_chip);
+ set_irq_handler(irqno, s3c_irq_demux_watchdog_batteryfault);
+ break;
+
+ case IRQ_CAM_C :
+ set_irq_chip(irqno, &s3c_irq_chip);
+ set_irq_handler(irqno, handle_level_irq);
+ set_irq_flags(irqno, IRQF_VALID);
+ break;
+
+ case IRQ_CAM_P :
+ set_irq_chip(irqno, &s3c_irq_chip);
+ set_irq_handler(irqno, handle_level_irq);
+ set_irq_flags(irqno, IRQF_VALID);
+ break;
these case statements could be commonsied.
+ default:
+ //irqdbf("registering irq %d (s3c irq)\n", irqno);
+ set_irq_chip(irqno, &s3c_irq_chip);
+ set_irq_handler(irqno, handle_edge_irq);
+ // set_irq_handler(irqno, handle_level_irq);
+ set_irq_flags(irqno, IRQF_VALID);
+ }
+ }
+
+ /* setup the cascade irq handlers */
+
+ set_irq_chained_handler(IRQ_UART0, s3c_irq_demux_uart0);
+ set_irq_chained_handler(IRQ_UART1, s3c_irq_demux_uart1);
+ set_irq_chained_handler(IRQ_ADC_PENUPDN, s3c_irq_demux_adc);
+ set_irq_chained_handler(IRQ_TIMER3_4, s3c_irq_demux_timer3_4);
+ set_irq_chained_handler(IRQ_AC97_NFLASH, s3c_irq_demux_ac97_nflash);
+ set_irq_chained_handler(IRQ_DMA, s3c_irq_demux_dma0_3);
+ set_irq_chained_handler(IRQ_IRDA_MSTICK, __s3c_irq_demux_irda_ms);
+
+
+ /* external interrupts */
+ for (irqno = IRQ_EINT0; irqno <= IRQ_EINT18; irqno++) {
+ irqdbf("registering irq %d (extended s3c irq)\n", irqno);
+ set_irq_chip(irqno, &s3c_irqext_chip);
+ //set_irq_handler(irqno, handle_level_irq);
+ set_irq_handler(irqno, handle_edge_irq);
+ set_irq_flags(irqno, IRQF_VALID);
+ }
+
+ /* register the uart interrupts */
+
+ irqdbf("s3c24a0: registering external interrupts\n");
+
+
+ for (irqno = IRQ_RXD0; irqno <= IRQ_ERR0; irqno++) {
+ irqdbf("registering irq %d (s3c uart0 irq)\n", irqno);
+ set_irq_chip(irqno, &s3c_irq_uart0);
+ set_irq_handler(irqno, handle_level_irq);
+ set_irq_flags(irqno, IRQF_VALID);
+ }
+
+ for (irqno = IRQ_RXD1; irqno <= IRQ_ERR1; irqno++) {
+ irqdbf("registering irq %d (s3c uart1 irq)\n", irqno);
+ set_irq_chip(irqno, &s3c_irq_uart1);
+ set_irq_handler(irqno, handle_level_irq);
+ set_irq_flags(irqno, IRQF_VALID);
+ }
+ /* register the timer interrupts (timer3, timer 4) */
+ for (irqno = IRQ_TIMER3; irqno <= IRQ_TIMER4; irqno++) {
+ irqdbf("registering irq %d (s3c timer irq)\n", irqno);
+ set_irq_chip(irqno, &s3c_irq_timer3_4);
+ set_irq_handler(irqno, handle_level_irq);
+ set_irq_flags(irqno, IRQF_VALID);
+ }
+ /* register the AC97 & Nand Flash interrupt */
+ for (irqno = IRQ_NFLASH; irqno <= IRQ_AC97; irqno++) {
+ irqdbf("registering irq %d (s3c ac97 & Nand flash irq)\n", irqno);
+ set_irq_chip(irqno, &s3c_irq_ac97_nflash);
+ set_irq_handler(irqno, handle_level_irq);
+ set_irq_flags(irqno, IRQF_VALID);
+ }
+ /* register the IrDA & Memory Stick interrupt */
+ for (irqno = IRQ_IRDA; irqno <= IRQ_MSTICK; irqno++) {
+ irqdbf("registering irq %d (s3c irda & Memory Stick irq)\n", irqno);
+ set_irq_chip(irqno, &s3c_irq_irda_ms);
+ set_irq_handler(irqno, handle_level_irq);
+ set_irq_flags(irqno, IRQF_VALID);
+ }
+
+ /* register the Watchdog & Batter fault interrupts */
+ for (irqno = IRQ_WDT; irqno <= IRQ_BATFLT; irqno++) {
+ irqdbf("registering irq %d (s3c wdt_batflt irq)\n", irqno);
+ set_irq_chip(irqno, &s3c_irq_wdt_batflt);
+ set_irq_handler(irqno, handle_level_irq);
+ set_irq_flags(irqno, IRQF_VALID);
+ }
+
+ /* register the DMA interrupts */
+ for (irqno = IRQ_DMA0; irqno <= IRQ_DMA3; irqno++) {
+ irqdbf("registering irq %d (s3c dma irq)\n", irqno);
+ set_irq_chip(irqno, &s3c_irq_dma0_3);
+ set_irq_handler(irqno, handle_level_irq);
+ set_irq_flags(irqno, IRQF_VALID);
+ }
+ /* register the ADC interrupts */
+ for (irqno = IRQ_PENUP; irqno <= IRQ_ADC; irqno++) {
+ irqdbf("registering irq %d (s3c adc irq)\n", irqno);
+ set_irq_chip(irqno, &s3c_irq_adc);
+ set_irq_handler(irqno, handle_level_irq);
+ set_irq_flags(irqno, IRQF_VALID);
+ }
+
+
+ irqdbf("s3c24a0: registered interrupt handlers\n");
+
+#ifdef CONFIG_MACH_SMDK24A0
+ /* External interrupt 13 enable for CS8900 */
+ value_e = __raw_readl(S3C24A0_EINTMASK);
+ value_e &= ~(1<<13);
+ __raw_writel(value_e, S3C24A0_EINTMASK);
+ value_e = __raw_readl(S3C24A0_INTMSK);
+ value_e &= ~(1<<3);
+ __raw_writel(value_e,S3C24A0_INTMSK);
+#endif
this looks like a nasty hack to me, please find a better place for it.
+}
diff --git a/arch/arm/mach-s3c24a0/leds-smdk.c b/arch/arm/mach-s3c24a0/leds-smdk.c
new file mode 100644
index 0000000..d378571
--- /dev/null
+++ b/arch/arm/mach-s3c24a0/leds-smdk.c
@@ -0,0 +1,148 @@
+/*
+ * arch/arm/mach-s3c24a0/leds-smdk.c
+ *
+ * $Id: leds-smdk.c,v 1.1.1.1 2006/02/13 05:22:49 ihlee215 Exp $
+ *
+ * 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
+
+#include
+#include
+#include
+#include
+//#include
+
+#include
+#include "leds.h"
+
+#define LED_STATE_ENABLED 1
+#define LED_STATE_CLAIMED 2
+
+#define SMDK_LED7 GPIO_7 /* O : LED3, Low-Active */
+#define SMDK_LED6 GPIO_6 /* O : LED2, LOw-Active */
+#define SMDK_LED5 GPIO_5 /* O : LED1, LOw-Active */
+#define SMDK_LED4 GPIO_4 /* O : LED0, Low-Active */
+
+
+#define LED0 (1 << 0)
+#define LED1 (1 << 1)
+#define LED2 (1 << 2)
+#define LED3 (1 << 3)
+
+
+#if 0
+static inline void led_update(unsigned int state)
+{
+ write_gpio_bit(SMDK_LED4, (state & LED0));
+ write_gpio_bit(SMDK_LED5, ((state & LED1) >> 1));
+ write_gpio_bit(SMDK_LED6, ((state & LED2) >> 2));
+ write_gpio_bit(SMDK_LED7, ((state & LED3) >> 3));
+}
+
+void smdk_leds_event(led_event_t evt)
+{
+ unsigned long flags;
+
+ local_irq_save(flags);
+
+ switch (evt) {
+ case led_start:
+ hw_led_state = (LED1 | LED2 | LED3);
+ led_state = LED_STATE_ENABLED;
+ break;
+
+ case led_stop:
+ led_state &= ~LED_STATE_ENABLED;
+ hw_led_state = (LED0 | LED1 | LED2 | LED3);
+ led_update(hw_led_state);
+ break;
+
+ case led_claim:
+ led_state |= LED_STATE_CLAIMED;
+ hw_led_state = (LED0 | LED1 | LED2 | LED3);
+ break;
+
+ case led_release:
+ led_state &= ~LED_STATE_CLAIMED;
+ hw_led_state = (LED1 | LED2 | LED3);
+ break;
+
+#ifdef CONFIG_LEDS_TIMER
+ case led_timer:
+ if (!(led_state & LED_STATE_CLAIMED))
+ hw_led_state ^= LED3;
+ break;
+#endif
+
+#ifdef CONFIG_LEDS_CPU
+ case led_idle_start:
+ if (!(led_state & LED_STATE_CLAIMED))
+ hw_led_state |= LED2;
+ break;
+
+ case led_idle_end:
+ if (!(led_state & LED_STATE_CLAIMED))
+ hw_led_state &= ~LED2;
+ break;
+#endif
+
+ case led_halted:
+ break;
+
+ case led_green_on:
+ if (led_state & LED_STATE_CLAIMED)
+ hw_led_state &= ~LED2;
+ break;
+
+ case led_green_off:
+ if (led_state & LED_STATE_CLAIMED)
+ hw_led_state |= LED2;
+ break;
+
+ case led_amber_on:
+ break;
+
+ case led_amber_off:
+ break;
+
+ case led_red_on:
+ break;
+
+ case led_red_off:
+ break;
+
+ default:
+ break;
+ }
+
+ if (led_state & LED_STATE_ENABLED)
+ led_update(hw_led_state);
+
+ local_irq_restore(flags);
+}
+
+#endif
+
+int led_testinit(void)
+{
+ set_gpio_ctrl(GPIO_7 | GPIO_PULLUP_DIS | GPIO_MODE_OUT);
+ set_gpio_ctrl(GPIO_6 | GPIO_PULLUP_DIS | GPIO_MODE_OUT);
+ set_gpio_ctrl(GPIO_5 | GPIO_PULLUP_DIS | GPIO_MODE_OUT);
+ set_gpio_ctrl(GPIO_4 | GPIO_PULLUP_DIS | GPIO_MODE_OUT);
+}
+int led_teston(u32 pattern)
+{
+#if 0
+ set_gpio_ctrl(GPIO_7 | GPIO_PULLUP_DIS | GPIO_MODE_OUT);
+ set_gpio_ctrl(GPIO_6 | GPIO_PULLUP_DIS | GPIO_MODE_OUT);
+ set_gpio_ctrl(GPIO_5 | GPIO_PULLUP_DIS | GPIO_MODE_OUT);
+ set_gpio_ctrl(GPIO_4 | GPIO_PULLUP_DIS | GPIO_MODE_OUT);
+#endif
+// __raw_writel(__raw_readl(S3C24A0_GPDAT) | (0xf<< 4), S3C24A0_GPDAT);
+ __raw_writel((__raw_readl(S3C24A0_GPDAT) & ~(0xf<<4)) | ((~pattern&0xf) << 4), S3C24A0_GPDAT);
+ return 0;
+}
There is an s3c24xx gpio led driver using the LED class framework
available. It should not be difficult to adapt to using this.
diff --git a/arch/arm/mach-s3c24a0/leds.h b/arch/arm/mach-s3c24a0/leds.h
new file mode 100644
index 0000000..1938222
--- /dev/null
+++ b/arch/arm/mach-s3c24a0/leds.h
@@ -0,0 +1,7 @@
+/*
+ * arch/arm/mach-s3c24a0/leds.h
+ *
+ * $Id: leds.h,v 1.1.1.1 2006/02/13 05:22:49 ihlee215 Exp $
+ *
+ */
+extern void smdk_leds_event(led_event_t evt);
diff --git a/arch/arm/mach-s3c24a0/mach-smdk24a0.c b/arch/arm/mach-s3c24a0/mach-smdk24a0.c
new file mode 100644
index 0000000..32de668
--- /dev/null
+++ b/arch/arm/mach-s3c24a0/mach-smdk24a0.c
@@ -0,0 +1,224 @@
+/***********************************************************************
+ *
+ * linux/arch/arm/mach-s3c24a0/mach-smdk24a0.c
+ *
+ * $Id: mach-smdk24a0.c,v 1.1.1.1 2006/02/13 05:22:49 ihlee215 Exp $
+ *
+ * Copyright (C) 2005, Sean Choi
+ * All rights reserved
+ *
+ * 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
+ *
+ * derived from linux/arch/arm/mach-s3c2410/devs.c, written by
+ * Ben Dooks
+ *
+ ***********************************************************************/
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+
+#include "s3c24a0.h"
+#include "devs.h"
+#include "cpu.h"
+
+static struct map_desc smdk24a0_iodesc[] __initdata = {
+#ifdef CONFIG_MACH_SMDK24A0
+ /* virtual physical length type */
+ {SMDK_CS8900_VIO, __phys_to_pfn(SMDK_CS8900_PIO) , 0x00100000 , MT_DEVICE}
+#endif
Named initialisers are better used here, ie:
{
.virtial = SMDK_CS8900_VIO
+};
+
+#define DEF_UCON S3C24A0_UCON_DEFAULT
+#define DEF_ULCON S3C24A0_LCON_CS8 | S3C24A0_LCON_PNONE | S3C24A0_LCON_STOPB
+#define DEF_UFCON S3C24A0_UFCON_RXTRIG8 | S3C24A0_UFCON_FIFOMODE
+
+static struct s3c24a0_uartcfg smdk24a0_uartcfgs[] = {
+ [0] = {
+ .hwport = 0,
+ .flags = 0,
+ .ucon = DEF_UCON,
+ .ulcon = DEF_ULCON,
+ .ufcon = DEF_UFCON,
+ },
+ [1] = {
+ .hwport = 1,
+ .flags = 0,
+ .ucon = DEF_UCON,
+ .ulcon = DEF_ULCON,
+ .ufcon = DEF_UFCON,
+ }
+};
+
+#include
+
+static struct s3c24a0fb_mach_info s3c24a0_lcdcfg = {
+
+ .lcdcon1= BDBCON_BUF1 | DIVEN | CLKDIR_DIVIDE | PNRMODE_PRGB | BPPMODEF_565 | MPPMODEB_565,
+ .lcdcon2= PALFRM_565 | IHSYNC_INVERT | IVSYNC_INVERT | HAWSWP_EN,
+
+ .lcdtcon1= VBPD(V_BP) | VFPD(V_FP) | VSPW(V_SW),
+ .lcdtcon2= HBPD(H_BP) | HFPD(H_FP) | HSPW(H_SW),
+ .lcdtcon3= LINEVAL(V_RESOLUTION - 1) | HOZVAL(H_RESOLUTION - 1),
+
+
+
+ .width= 240,
+ .height= 320,
+ .xres= H_RESOLUTION,
+ .yres= V_RESOLUTION,
+ .bpp= PIXEL_BPP,
+
+ .pixclock= PIXEL_CLOCK,
+
+ .hsync_len= H_SW,
+ .vsync_len= V_SW,
+
+ .left_margin= H_FP,
+ .upper_margin= V_FP,
+ .right_margin= H_BP,
+ .lower_margin= V_BP,
+
+ .sync= 0,
+ .cmap_static= 1,
+
+
+};
+
+static struct platform_device *smdk24a0_devices[] __initdata = {
+ &s3c_device_usb,
+ &s3c_device_udc,
+ &s3c_device_lcd,
+ &s3c_device_wdt,
+ &s3c_device_i2c,
+ &s3c_device_nand,
+ &s3c_device_sdi,
+ &s3c_device_irda,
+ &s3c_device_iis,
+ &s3c_device_rtc,
+ &s3c_device_keypad,
+ /* add device */
+};
+
+static struct s3c24xx_board smdk24a0_board __initdata = {
+ .devices = smdk24a0_devices,
+ .devices_count = ARRAY_SIZE(smdk24a0_devices)
+};
+
+void __init smdk24a0_map_io(void)
+{
+ s3c24xx_init_io(smdk24a0_iodesc, ARRAY_SIZE(smdk24a0_iodesc));
+
+ //s3c24a0_init_uarts(smdk24a0_uartcfgs, ARRAY_SIZE(smdk24a0_uartcfgs));
+ s3c24a0_init_uarts(smdk24a0_uartcfgs, 1);
+ s3c24xx_set_board(&smdk24a0_board);
+}
+
+void smdk24a0_cs89x0_set(void)
+{
+ unsigned long srom_value;
+
+ srom_value = __raw_readl(SROM_BW);
+ srom_value &= ~0x38;
+ srom_value |= 0x38;
+ __raw_writel(srom_value,SROM_BW);/* CS1 : nBE, nWAIT, 16bit */
+ srom_value = 0x25a8;
+ __raw_writel(srom_value,SROM_BC1);
+
+ set_irq_type(IRQ_EINT13,IRQT_RISING);
+}
You should not be using set_irq_type, it the proper way is to
use the IRQF_TRIGGER flags when requesting the IRQ.
+void __init smdk24a0_init_irq(void)
+{
+ s3c24a0_init_irq();
+ smdk24a0_cs89x0_set();
+}
+static struct mtd_partition smdk_partitions[] = {
+ {
+ .name = "NAND partition 0 : Bootloader",
+ .size = (192*SZ_1K),
+ .offset = 0,
+ .mask_flags = MTD_WRITEABLE,
+ },
+ {
+ .name = "NAND partition 1 : Kernel",
+ .size = (2*SZ_1M) - (192*SZ_1K),
+ .offset = (192*SZ_1K), /* Block number is 0xC */
+ .mask_flags = MTD_WRITEABLE,
+ }, {
+ .name = "NAND partition 2 : NAND Root",
+ .size = MTDPART_SIZ_FULL,
+ .offset = MTDPART_OFS_APPEND,
+ }
+};
+
+static struct s3c24a0_nand_set smdk_nand_set = {
+ .nr_chips = 1,
+ .nr_partitions = 3,
+ .partitions = smdk_partitions,
+};
+
+static struct s3c24a0_platform_nand smdk_flash_data = {
+ .tacls = 10, //10nsec
+ .twrph0 = 70, //70nsec
+ .twrph1 =70, //70nsec
+ .nr_sets = 1,
+ .sets = &smdk_nand_set,
+};
Hmm, is this properly idented?
+static void __init smdk_init(void)
+{
+ s3c_set_flash_data(&smdk_flash_data);
+ set_s3c24a0fb_info(&s3c24a0_lcdcfg);
+
+ //s3c_device_lcd.dev.platform_data = &s3c24a0_lcdcfg;
+}
+
+MACHINE_START(S3C24A0, "S3C24A0") /* @TODO: request a new identifier and switch
+ * to SMDK24A0 */
+ //MAINTAINER("Jonas Dietsche")
+ //BOOT_MEM(S3C24A0_SDRAM_PA, S3C24A0_PA_UART, S3C24A0_VA_UART)
+ //BOOT_MEM(S3C24A0_SDRAM_PA, S3C24A0_PA_RTC, S3C24A0_VA_RTC)
+ .phys_io = S3C24A0_PA_IO_BASE,
+ .io_pg_offst = (((u32)S3C24A0_VA_IO_BASE>>18) & 0xfffc),
+ .boot_params = S3C24A0_SDRAM_PA + 0x100,
+ .map_io = smdk24a0_map_io,
+ .init_irq = smdk24a0_init_irq,
+ .timer = &s3c24a0_timer,
+ .init_machine = smdk_init,
+MACHINE_END
+
+
Remove the //s
diff --git a/arch/arm/mach-s3c24a0/pm.c b/arch/arm/mach-s3c24a0/pm.c
new file mode 100644
index 0000000..32ddfbe
--- /dev/null
+++ b/arch/arm/mach-s3c24a0/pm.c
@@ -0,0 +1,493 @@
+/* linux/arch/arm/mach-s3c24a0/pm.c
+ *
+ * $Id: pm.c,v 1.1.1.1 2006/02/13 05:22:49 ihlee215 Exp $
+ *
+ * Copyright (c) 2005, Sean Choi
+ *
+ * S3C24A0 Power Manager (Suspend-To-RAM) support
+ *
+ * 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.
+ *
+ * derived from linux/include/asm-arm/arch-s3c2410/map.h, written by
+ * Ben Dooks
+ *
+ *
+*/
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+
+#include "pm.h"
+#include "clock.h"
+
+#ifdef CONFIG_MACH_SMDK24A0
+#define SLEEP_BUTTON IRQ_EINT9
+#endif
+
+/* cache functions from arch/arm/mm/proc-arm926.S */
+extern void arm926_flush_kern_cache_all(void);
+
+#define PFX "s3c24xx-pm: "
+
+static struct sleep_save core_save[] = {
+ SAVE_ITEM(S3C24A0_LOCKTIME),
+ SAVE_ITEM(S3C24A0_CLKCON),
+ SAVE_ITEM(S3C24A0_CLKDIVN),
+ SAVE_ITEM(S3C24A0_MPLLCON),
+ SAVE_ITEM(S3C24A0_UPLLCON),
+#ifdef CONFIG_MACH_SMDK24A0
+ /* ROM BANK --> CS8900 */
+ SAVE_ITEM(SROM_BW),
+ SAVE_ITEM(SROM_BC1),
+#endif
+};
+
+/* this lot should be really saved by the IRQ code */
+static struct sleep_save irq_save[] = {
+ /* Interrupt */
+ SAVE_ITEM(S3C24A0_INTMOD),
+ SAVE_ITEM(S3C24A0_INTMSK),
+ SAVE_ITEM(S3C24A0_INTSUBMSK),
+ SAVE_ITEM(S3C24A0_EINTMASK),
+};
+
+static struct sleep_save gpio_save[] = {
+ SAVE_ITEM(S3C24A0_GPCONU),
+ SAVE_ITEM(S3C24A0_GPCONM),
+ SAVE_ITEM(S3C24A0_GPCONL),
+ SAVE_ITEM(S3C24A0_GPDAT),
+ SAVE_ITEM(S3C24A0_GPUP),
+ SAVE_ITEM(S3C24A0_EINTCR0),
+ SAVE_ITEM(S3C24A0_EINTCR1),
+ SAVE_ITEM(S3C24A0_EINTCR2),
+ SAVE_ITEM(S3C24A0_EINTFLT0),
+ SAVE_ITEM(S3C24A0_EINTFLT1),
+};
+
+static struct sleep_save nand_save[] = {
+ SAVE_ITEM(PM_NFCONF),
+ SAVE_ITEM(PM_NFCONT),
+};
+
+#define DBG(fmt...) printk(fmt)
+
+#if defined(CONFIG_S3C24A0_PM_CHECK) && CONFIG_S3C24A0_PM_CHECK_CHUNKSIZE != 0
+
+/* suspend checking code...
+ *
+ * this next area does a set of crc checks over all the installed
+ * memory, so the system can verify if the resume was ok.
+ *
+ * CONFIG_S3C24A0_PM_CHECK_CHUNKSIZE defines the block-size for the CRC,
+ * increasing it will mean that the area corrupted will be less easy to spot,
+ * and reducing the size will cause the CRC save area to grow
+*/
+
+#define CHECK_CHUNKSIZE (CONFIG_S3C24A0_PM_CHECK_CHUNKSIZE * 1024)
+
+static u32 crc_size; /* size needed for the crc block */
+static u32 *crcs; /* allocated over suspend/resume */
+
+typedef u32 *(run_fn_t)(struct resource *ptr, u32 *arg);
+
+/* s3c24a0_pm_run_res
+ *
+ * go thorugh the given resource list, and look for system ram
+*/
+
+static void s3c24a0_pm_run_res(struct resource *ptr, run_fn_t fn, u32 *arg)
+{
+ while (ptr != NULL) {
+ if (ptr->child != NULL)
+ s3c24a0_pm_run_res(ptr->child, fn, arg);
+
+ if ((ptr->flags & IORESOURCE_MEM) &&
+ strcmp(ptr->name, "System RAM") == 0) {
+ DBG("Found system RAM at %08lx..%08lx\n",
+ ptr->start, ptr->end);
+ arg = (fn)(ptr, arg);
+ }
+
+ ptr = ptr->sibling;
+ }
+}
+
+static void s3c24a0_pm_run_sysram(run_fn_t fn, u32 *arg)
+{
+ s3c24a0_pm_run_res(&iomem_resource, fn, arg);
+}
+
+static u32 *s3c24a0_pm_countram(struct resource *res, u32 *val)
+{
+ u32 size = (u32)(res->end - res->start)+1;
+
+ size += CHECK_CHUNKSIZE-1;
+ size /= CHECK_CHUNKSIZE;
+
+ DBG("Area %08lx..%08lx, %d blocks\n", res->start, res->end, size);
+
+ *val += size * sizeof(u32);
+ return val;
+}
+
+/* s3c24a0_pm_prepare_check
+ *
+ * prepare the necessary information for creating the CRCs. This
+ * must be done before the final save, as it will require memory
+ * allocating, and thus touching bits of the kernel we do not
+ * know about.
+*/
+
+static void s3c24a0_pm_check_prepare(void)
+{
+ crc_size = 0;
+
+ s3c24a0_pm_run_sysram(s3c24a0_pm_countram, &crc_size);
+
+ DBG("s3c24a0_pm_prepare_check: %u checks needed\n", crc_size);
+
+ crcs = kmalloc(crc_size+4, GFP_KERNEL);
+ if (crcs == NULL)
+ printk(KERN_ERR "Cannot allocated CRC save area\n");
+}
+
+static u32 *s3c24a0_pm_makecheck(struct resource *res, u32 *val)
+{
+ unsigned long addr, left;
+
+ for (addr = res->start; addr < res->end;
+ addr += CHECK_CHUNKSIZE) {
+ left = res->end - addr;
+
+ if (left > CHECK_CHUNKSIZE)
+ left = CHECK_CHUNKSIZE;
+
+ *val = crc32_le(~0, phys_to_virt(addr), left);
+ val++;
+ }
+
+ return val;
+}
+
+/* s3c24a0_pm_check_store
+ *
+ * compute the CRC values for the memory blocks before the final
+ * sleep.
+*/
+
+static void s3c24a0_pm_check_store(void)
+{
+ if (crcs != NULL)
+ s3c24a0_pm_run_sysram(s3c24a0_pm_makecheck, crcs);
+}
+
+/* in_region
+ *
+ * return TRUE if the area defined by ptr..ptr+size contatins the
+ * what..what+whatsz
+*/
+
+static inline int in_region(void *ptr, int size, void *what, size_t whatsz)
+{
+ if ((what+whatsz) < ptr)
+ return 0;
+
+ if (what > (ptr+size))
+ return 0;
+
+ return 1;
+}
+
+static u32 *s3c24a0_pm_runcheck(struct resource *res, u32 *val)
+{
+ void *save_at = phys_to_virt(sleep_save_sp);
+ unsigned long addr;
+ unsigned long left;
+ void *ptr;
+ u32 calc;
+
+ for (addr = res->start; addr < res->end;
+ addr += CHECK_CHUNKSIZE) {
+ left = res->end - addr;
+
+ if (left > CHECK_CHUNKSIZE)
+ left = CHECK_CHUNKSIZE;
+
+ ptr = phys_to_virt(addr);
+
+ if (in_region(ptr, left, crcs, crc_size)) {
+ DBG("skipping %08lx, has crc block in\n", addr);
+ goto skip_check;
+ }
+
+ if (in_region(ptr, left, save_at, 32*4 )) {
+ DBG("skipping %08lx, has save block in\n", addr);
+ goto skip_check;
+ }
+
+ /* calculate and check the checksum */
+
+ calc = crc32_le(~0, ptr, left);
+ if (calc != *val) {
+ printk(KERN_ERR PFX "Restore CRC error at "
+ "%08lx (%08x vs %08x)\n", addr, calc, *val);
+
+ DBG("Restore CRC error at %08lx (%08x vs %08x)\n",
+ addr, calc, *val);
+ }
+
+ skip_check:
+ val++;
+ }
+
+ return val;
+}
+
+/* s3c24a0_pm_check_restore
+ *
+ * check the CRCs after the restore event and free the memory used
+ * to hold them
+*/
+
+static void s3c24a0_pm_check_restore(void)
+{
+ if (crcs != NULL) {
+ s3c24a0_pm_run_sysram(s3c24a0_pm_runcheck, crcs);
+ kfree(crcs);
+ crcs = NULL;
+ }
+}
+
+#else
+
+#define s3c24a0_pm_check_prepare() do { } while(0)
+#define s3c24a0_pm_check_restore() do { } while(0)
+#define s3c24a0_pm_check_store() do { } while(0)
+#endif
+
+/* helper functions to save and restore register state */
+
+void s3c24a0_pm_do_save(struct sleep_save *ptr, int count)
+{
+ for (; count > 0; count--, ptr++) {
+ ptr->val = __raw_readl(ptr->reg);
+ DBG("saved %08lx value %08lx\n", ptr->reg, ptr->val);
+ }
+}
+
+/* s3c24a0_pm_do_restore
+ *
+ * restore the system from the given list of saved registers
+ *
+ * Note, we do not use DBG() in here, as the system may not have
+ * restore the UARTs state yet
+*/
+
+void s3c24a0_pm_do_restore(struct sleep_save *ptr, int count)
+{
+ for (; count > 0; count--, ptr++) {
+ printk(KERN_DEBUG "restore %08lx (restore %08lx, was %08x)\n",
+ ptr->reg, ptr->val, __raw_readl(ptr->reg));
+
+ __raw_writel(ptr->val, ptr->reg);
+ }
+}
+
+/* s3c24a0_pm_do_restore_core
+ *
+ * similar to s3c24a0_pm_do_restore_core
+ *
+ * WARNING: Do not put any debug in here that may effect memory or use
+ * peripherals, as things may be changing!
+*/
+
+static void s3c24a0_pm_do_restore_core(struct sleep_save *ptr, int count)
+{
+ for (; count > 0; count--, ptr++) {
+ __raw_writel(ptr->val, ptr->reg);
+ }
+}
+
+/* sleep_phys_sp */
+unsigned long sleep_phys_sp(void *sp)
+{
+ return virt_to_phys(sp);
+}
+
+/* setup wakeup interrupt source */
+static void setup_wakeup_src(unsigned int irq, unsigned int type)
+{
+ struct irq_desc *desc;
+
+ desc = irq_desc + irq;
+
+ /* Set Wakeup-enable on the irq */
+ desc->chip->set_wake(irq, type);
+}
+
+/* s3c24a0_pm_enter
+ *
+ * central control for sleep/resume process
+ */
+static int s3c24a0_pm_enter(suspend_state_t state)
+{
+ unsigned long alivecon;
+
+ /* ensure the debug is initialised (if enabled) */
+
+ DBG("s3c24a0_pm_enter(%d)\n", state);
+
+ if (state != PM_SUSPEND_MEM) {
+ printk(KERN_ERR PFX "error: only PM_SUSPEND_MEM supported\n");
+ return -EINVAL;
+ }
+
+ /* prepare check area if configured */
+ s3c24a0_pm_check_prepare();
+
+ alivecon = __raw_readl(ALIVECON)|(1 << 1);
+ __raw_writel(alivecon,ALIVECON);
+
+ /* set power settle down time */
+ __raw_writel(0x10, RSTCNT); /* aboue 1 second */
+
+ /* ensure at least GESTATUS3 has the resume address */
+
+ __raw_writel(virt_to_phys(s3c24a0_cpu_resume), GPRAM0);
+
+ /* save all necessary core registers not covered by the drivers */
+
+ s3c24a0_pm_do_save(core_save, ARRAY_SIZE(core_save));
+ s3c24a0_pm_do_save(irq_save, ARRAY_SIZE(irq_save));
+ s3c24a0_pm_do_save(gpio_save, ARRAY_SIZE(gpio_save));
+ s3c24a0_pm_do_save(nand_save, ARRAY_SIZE(nand_save));
+
+#ifdef CONFIG_MACH_SMDK24A0
+ __raw_writel(0x000700d0, GPDATINSLEEP); /* set GPIO data in sleep mode */
+ __raw_writel(0xfff8ff2b, ENGPINSLEEP); /* set GPIO mode in sleep mode 0: outpuu 1: Hi-z state */
+ __raw_writel(0xffcfdff7, GPUPINSLEEP);
+ __raw_writel(0x80912222, DATRINSLEEP0); /* set output value in sleep state */
+ __raw_writel(0x00040010, DATRINSLEEP1); /* enable the ouput in sleep state */
+ __raw_writel(0x050f0600, ENPUINSLEEP); /* configure pullup in sleep state */
+
+ /* peripheral port output control for sleep mode */
+ __raw_writel(0x003f3287, OENINSLEEP0);
+#endif
+
+ /* set the irq configuration for wake */
+#ifdef CONFIG_MACH_SMDK24A0
+ setup_wakeup_src(IRQ_EINT9, IRQT_RISING); /* GPIO9 --> S3 button */
+#endif
+
+ /* ack any outstanding external interrupts before we go to sleep */
+ __raw_writel(__raw_readl(S3C24A0_EINTPEND), S3C24A0_EINTPEND);
+
+ /* flush cache back to ram */
+
+ arm926_flush_kern_cache_all();
+
+ s3c24a0_pm_check_store();
+
+ s3c24a0_cpu_suspend();
+
+ cpu_init();
+
+ /* restore the system state */
+ s3c24a0_pm_do_restore_core(core_save, ARRAY_SIZE(core_save));
+ s3c24a0_pm_do_restore(irq_save, ARRAY_SIZE(irq_save));
+ s3c24a0_pm_do_restore(gpio_save, ARRAY_SIZE(gpio_save));
+ s3c24a0_pm_do_restore(nand_save, ARRAY_SIZE(nand_save));
+
+ alivecon = __raw_readl(ALIVECON) & ~(1 << 1);
+ __raw_writel(alivecon, ALIVECON);
+
+ /* clear status registers */
+ __raw_writel(0xffffffff, S3C24A0_EINTPEND);
+ __raw_writel(0xffffffff, S3C24A0_SUBSRCPND);
+ __raw_writel(0xffffffff, S3C24A0_SRCPND);
+ __raw_writel(0xffffffff, S3C24A0_INTPND);
+
+ /* check what irq (if any) restored the system */
+ DBG("post sleep: IRQs 0x%08x, 0x%08x\n",
+ __raw_readl(S3C24A0_SRCPND),
+ __raw_readl(S3C24A0_EINTPEND));
+
+ DBG("post sleep, preparing to return\n");
+
+ s3c24a0_pm_check_restore();
+
+ DBG("S3C24A0 PM Resume (post-restore)\n");
+ return 0;
+}
+
+/*
+ * Called after processes are frozen, but before we shut down devices.
+ */
+static int s3c24a0_pm_prepare(suspend_state_t state)
+{
+ return 0;
+}
+
+/*
+ * Called after devices are re-setup, but before processes are thawed.
+ */
+static int s3c24a0_pm_finish(suspend_state_t state)
+{
+ return 0;
+}
+
+/*
+ * Set to PM_DISK_FIRMWARE so we can quickly veto suspend-to-disk.
+ */
+static struct pm_ops s3c24a0_pm_ops = {
+ .pm_disk_mode = PM_DISK_FIRMWARE,
+ .prepare = s3c24a0_pm_prepare,
+ .enter = s3c24a0_pm_enter,
+ .finish = s3c24a0_pm_finish,
+};
+
+/* s3c24a0_pm_init
+ *
+ * Attach the power management functions. This should be called
+ * from the board specific initialisation if the board supports
+ * it.
+*/
+
+static int __init s3c24a0_pm_init(void)
+{
+ printk("S3C24A0 Power Management, (c) 2005 Samsung Electronics\n");
+ pm_set_ops(&s3c24a0_pm_ops);
+ return 0;
+}
+
+module_init(s3c24a0_pm_init);
diff --git a/arch/arm/mach-s3c24a0/pm.h b/arch/arm/mach-s3c24a0/pm.h
new file mode 100644
index 0000000..761c143
--- /dev/null
+++ b/arch/arm/mach-s3c24a0/pm.h
@@ -0,0 +1,33 @@
+/* linux/arch/arm/mach-s3c24a0/pm.h
+ *
+ * $Id: pm.h,v 1.1.1.1 2006/02/13 05:22:49 ihlee215 Exp $
+ *
+ * Copyright (c) 2005, Sean Choi
+ * All right reserved.
+ *
+ * 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.
+ *
+ * derived from linux/include/asm-arm/arch-s3c24a0/map.h, written by
+ * Ben Dooks
+ *
+*/
+
+/* from sleep.S */
+
+extern void s3c24a0_cpu_suspend(void);
+extern void s3c24a0_cpu_resume(void);
+
+/* sleep save info */
+
+struct sleep_save {
+ unsigned long reg;
+ unsigned long val;
+};
+
+#define SAVE_ITEM(x) \
+ { .reg = (x) }
+
+extern void s3c24a0_pm_do_save(struct sleep_save *ptr, int count);
+extern void s3c24a0_pm_do_restore(struct sleep_save *ptr, int count);
These two look so much like the s3c24xx variants, that it would be better
to use the common platform code.
diff --git a/arch/arm/mach-s3c24a0/s3c24a0.c b/arch/arm/mach-s3c24a0/s3c24a0.c
new file mode 100644
index 0000000..4826aa1
--- /dev/null
+++ b/arch/arm/mach-s3c24a0/s3c24a0.c
@@ -0,0 +1,170 @@
+/* linux/arch/arm/mach-s3c24a0/s3c24a0.c
+ *
+ * $Id: s3c24a0.c,v 1.1.1.1 2006/02/13 05:22:49 ihlee215 Exp $
+ *
+ * Copyright (C) 2005, Sean Choi
+ * All rights reserved.
+ *
+ * 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.
+ *
+ * derived from linux/arch/arm/mach-s3c2410/s3c24a0.c, written by
+ * Ben Dooks
+*/
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+#include
+#include
+
+#include "s3c24a0.h"
+#include "cpu.h"
+#include "clock.h"
+
+int s3c24a0_clock_tick_rate = 12*1000*1000; /* current timers at 12MHz */
+
+/* Initial IO mappings */
+
+static struct map_desc s3c24a0_iodesc[] __initdata = {
+ { S3C24A0_VA_IO_BASE,
+ __phys_to_pfn(S3C24A0_PA_IO_BASE),
+ S3C24A0_SZ_IO,
+ MT_DEVICE }
+};
+
+static struct resource s3c_uart0_resource[] = {
+ [0] = {
+ .start = S3C24A0_PA_UART,
+ .end = S3C24A0_PA_UART + 0x3fff,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_RXD0,
+ .end = IRQ_ERR0,
+ .flags = IORESOURCE_IRQ,
+ }
+
+};
+
+static struct resource s3c_uart1_resource[] = {
+ [0] = {
+ .start = S3C24A0_PA_UART + 0x4000,
+ .end = S3C24A0_PA_UART + 0x4000 + 0x3fff,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_RXD1,
+ .end = IRQ_ERR1,
+ .flags = IORESOURCE_IRQ,
+ }
+};
+
+/* our uart devices */
+
+static struct platform_device s3c_uart0 = {
+ .name = "s3c24a0-uart",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(s3c_uart0_resource),
+ .resource = s3c_uart0_resource,
+};
+
+
+static struct platform_device s3c_uart1 = {
+ .name = "s3c24a0-uart",
+ .id = 1,
+ .num_resources = ARRAY_SIZE(s3c_uart1_resource),
+ .resource = s3c_uart1_resource,
+};
+
+static struct platform_device *uart_devices[] __initdata = {
+ &s3c_uart0,
+ &s3c_uart1,
+};
+
+/* store our uart devices for the serial driver console */
+struct platform_device *s3c24a0_uart_devices[2];
+
+static int s3c24a0_uart_count = 0;
+
+/* uart registration process */
+
+void __init s3c24a0_init_uarts(struct s3c24a0_uartcfg *cfg, int no)
+{
+ struct platform_device *platdev;
+ int uart;
+
+ for (uart = 0; uart < no; uart++, cfg++) {
+ platdev = uart_devices[cfg->hwport];
+
+ s3c24xx_uart_devs[uart] = platdev;
+ platdev->dev.platform_data = cfg;
+ }
+
+ s3c24a0_uart_count = uart;
+}
+
+/* s3c24a0_map_io
+ *
+ * register the standard cpu IO areas, and any passed in from the
+ * machine specific initialisation.
+ *
+ * this function also sets the initial clock frequencies from the
+ * settings passed in
+*/
+
+void __init s3c24a0_map_io(struct map_desc *mach_desc, int mach_size)
+{
+ unsigned long tmp;
+
+ /* register our io-tables */
+
+ iotable_init(s3c24a0_iodesc, ARRAY_SIZE(s3c24a0_iodesc));
+ iotable_init(mach_desc, mach_size);
+
+ /* now we've got our machine bits initialised, work out what
+ * clocks we've got */
+
+ s3c24xx_fclk = s3c24a0_get_pll(__raw_readl(S3C24A0_MPLLCON),
+ s3c24xx_xtal);
+
+ tmp = __raw_readl(S3C24A0_CLKDIVN);
+
+ /* work out clock scalings */
+ s3c24xx_hclk = s3c24xx_fclk / ((tmp & S3C24A0_CLKDIV_HCLK) ? 2 : 1);
+ //swlab choish you must modified more detail for 3:1, 4:1 for armclk
+ s3c24xx_pclk = s3c24xx_hclk / ((tmp & S3C24A0_CLKDIV_PCLK) ? 2 : 1);
comment does not make sense?
+ /* print brieft summary of clocks, etc */
+
+ printk("S3C24A0: core %ld.%03ld MHz, memory %ld.%03ld MHz, peripheral %ld.%03ld MHz\n",
+ print_mhz(s3c24xx_fclk), print_mhz(s3c24xx_hclk),
+ print_mhz(s3c24xx_pclk));
+
+ /* initialise the clocks here, to allow other things like the
+ * console to use them
+ */
+
+ s3c24a0_init_clocks();
+}
+
+int __init s3c24a0_init(void)
+{
+ printk("S3C24A0: Initialising architecture\n");
+
+ return platform_add_devices(s3c24xx_uart_devs, s3c24a0_uart_count);
+}
diff --git a/arch/arm/mach-s3c24a0/s3c24a0.h b/arch/arm/mach-s3c24a0/s3c24a0.h
new file mode 100644
index 0000000..001a15b
--- /dev/null
+++ b/arch/arm/mach-s3c24a0/s3c24a0.h
@@ -0,0 +1,30 @@
+/* arch/arm/mach-s3c24a0/s3c24a0.h
+ *
+ * Copyright (c) 2004 Simtec Electronics
+ * Ben Dooks
oops, you left this one alone :-)
+ *
+ * Header file for s3c2410 machine directory
+ *
+ * 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.
+ *
+ * Modifications:
+ * 18-Aug-2004 BJD Created initial version
+ * 20-Aug-2004 BJD Added s3c2410_board struct
+ * 04-Sep-2004 BJD Added s3c2410_init_uarts() call
+ * 17-Oct-2004 BJD Moved board out to cpu
+*/
+
+struct s3c24a0_uartcfg;
+
+extern void s3c24a0_map_io(struct map_desc *, int count);
+
+extern void s3c24a0_init_uarts(struct s3c24a0_uartcfg *, int no);
+
+extern void s3c24a0_init_irq(void);
+
+struct sys_timer;
+extern struct sys_timer s3c24a0_timer;
+
+extern void s3c24a0_init_uarts(struct s3c24a0_uartcfg *cfg, int no);
diff --git a/arch/arm/mach-s3c24a0/sleep.S b/arch/arm/mach-s3c24a0/sleep.S
new file mode 100644
index 0000000..721bf51
--- /dev/null
+++ b/arch/arm/mach-s3c24a0/sleep.S
@@ -0,0 +1,145 @@
+/* linux/arch/arm/mach-s3c24a0/sleep.S
+ *
+ * Copyright (c) 2005, Sean Choi
+ * All rights reserved.
+ *
+ * S3C24A0 Power Manager (Suspend-To-RAM) support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+
+/* CONFIG_DEBUG_RESUME is dangerous if your bootloader does not
+ * reset the UART configuration, only enable if you really need this!
+*/
+
+ .text
+
+ /* s3c24a0_cpu_suspend
+ *
+ * put the cpu into sleep mode
+ *
+ * entry:
+ * r0 = sleep save block
+ */
+
+ENTRY(s3c24a0_cpu_suspend)
+ stmfd sp!, { r4 - r12, lr }
+
+ @@ get co-processor registers
+ mrc p15, 0, r4, c3, c0, 0 @ domain ID
+ mrc p15, 0, r5, c2, c0, 0 @ translation table base addr
+ mrc p15, 0, r6, c13, c0, 0 @ PID
+ mrc p15, 0, r7, c1, c0, 0 @ control reg
+
+ @ store them plus current virtual stack ptr on stack
+ mov r8, sp
+ stmfd sp!, {r4 - r8}
+
+ mov r0, sp
+ bl sleep_phys_sp
+ ldr r1, =sleep_save_sp
+ str r0, [r1]
+
+#if 0
+ @ Clear All interrupts.
+ ldr r3, =S3C24A0_VA_IRQ
+ ldr r4, [r3, #0x0] @ SRCPND load
+ ldr r5, [r3, #0x10] @ INTPND load
+ str r4, [r3, #0x0] @ SRCPND clear
+ str r5, [r3, #0x10] @ INTPND clear
+
+ ldr r3, =S3C24A0_PA_GPIO
+ ldr r4, [r3, #0x38] @ load Eint Pending register
+ str r4, [r3, #0x38] @ EINTPEND register clear
+#endif
+ @@ flush the caches to ensure everything is back out to
+ @@ SDRAM before the core powers down
+
+ bl arm926_flush_kern_cache_all
+
+ @ Now clear I and F bit in CPSR
+ mrs r1, cpsr
+ ldr r2, =0xc0
+ orr r1, r1, r2
+ msr cpsr, r1
indentation?
+ /* Sleep... Now */
+ ldr r0, =S3C24A0_VA_CLKPWR @ Clock Power management base register
+ ldr r1, [r0, #0x30] @ POWERMAN register
+ ldr r2, =0xffff0000
+ and r1, r1, r2
+ ldr r2, = 0xa3 @ sleep bit
+ orr r1, r1, r2
+ str r1, [r0, #0x30] @ POWERMAN regiseter sleep mode set
+ 1: b 1b
+
+ @@ return to the caller, after having the MMU
+ @@ turned on, this restores the last bits from the
+ @@ stack
+resume_with_mmu:
+ ldmfd sp!, { r4 - r12, pc }
+
+ .ltorg
+
+ @@ the next bits sit in the .data segment, even though they
+ @@ happen to be code... the sleep_save_sp needs to be
+ @@ accessed by the resume code before it can restore the MMU.
+ @@ This means that the variable has to be close enough for the
+ @@ code to read it... since the .text segment needs to be RO,
+ @@ the data segment can be the only place to put this code.
+
+ .data
+
+ .global sleep_save_sp
+sleep_save_sp:
+ .word 0
+
+ /* s3c24a0_cpu_resume
+ *
+ * resume code entry for bootloader to call
+ *
+ * we must put this code here in the data segment as we have no
+ * other way of restoring the stack pointer after sleep, and we
+ * must not write to the code segment (code is read-only)
+ */
+
+ENTRY(s3c24a0_cpu_resume)
+ mov r0, #PSR_I_BIT | PSR_F_BIT | SVC_MODE
+ msr cpsr_c, r0
+
+
+ mov r1, #0
+ mcr p15, 0, r1, c8, c7, 0 @@ invalidate I & D TLBs
+ mcr p15, 0, r1, c7, c7, 0 @@ invalidate I & D caches
+
+ ldr r0, sleep_save_sp @ address of restore block
+ ldmfd r0!, { r4 - r7, sp }
+ ldr r2, =resume_with_mmu
+
+ mcr p15, 0, r4, c3, c0, 0 @ domain ID
+ mcr p15, 0, r5, c2, c0, 0 @ translation table base addr
+ mcr p15, 0, r6, c13, c0, 0 @ PID
+
+ mcr p15, 0, r7, c1, c0, 0 @ turn on MMU, caches, etc.
+
+ nop @ second-to-last before mmu
+ mov pc, r2 @ go back to virtual address
+ nop
+ nop
+ nop
+
+ .ltorg
Need to check the resume sequence, pipleline is not guaranteed over the
enabling of mmu.
diff --git a/arch/arm/mach-s3c24a0/time.c b/arch/arm/mach-s3c24a0/time.c
new file mode 100644
index 0000000..fe7e7a3
--- /dev/null
+++ b/arch/arm/mach-s3c24a0/time.c
@@ -0,0 +1,299 @@
+/* linux/arch/arm/mach-s3c24a0/time.c
+ *
+ * $Id: time.c,v 1.1.1.1 2006/02/13 05:22:49 ihlee215 Exp $
+ *
+ * Copyright (C) 2005, Sean Choi
+ * All rights reserved.
+ *
+ * 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
+ *
+ * derived from linux/arch/arm/mach-s3c2410/time.c, written by
+ * Ben Dooks
+ *
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "clock.h"
+
+#define RTC_LEAP_YEAR 2000
+
+static spinlock_t s3c24a0_rtc_pie_lock = SPIN_LOCK_UNLOCKED;
+
+/*
+ * Returns microsecond since last clock interrupt. Note that interrupts
+ * will have been disabled by do_gettimeoffset()
+ * IRQs are disabled before entering here from do_gettimeofday()
+ */
+static unsigned long s3c24a0_gettimeoffset(void)
+{
+ unsigned long elapsed;
+
+ elapsed = LATCH - __raw_readl(S3C24A0_TCNTO(4));
+
+ return ((elapsed * (tick_nsec /1000)) / LATCH);
+}
+
+
+/*
+ * IRQ handler for the timer
+ */
+static irqreturn_t
+s3c24a0_timer_interrupt(int irq, void *dev_id)
+{
+ write_seqlock(&xtime_lock);
+ timer_tick();
+ write_sequnlock(&xtime_lock);
+ return IRQ_HANDLED;
+}
+
+static struct irqaction s3c24a0_timer_irq = {
+ .name = "S3C24A0 Timer Tick",
+ .flags = SA_INTERRUPT,
+ .handler = s3c24a0_timer_interrupt
+};
+
+ /*
+ * setup timer 0 for kernel function tracing.
+ */
+
+#ifdef CONFIG_KFT
+void __noinstrument s3c24a0_timer0_setup (void)
+{
+ unsigned long tcon;
+ unsigned long tcnt;
+ unsigned long tcfg1;
+ unsigned long tcfg0;
+ unsigned long mask;
+
+ /* read the current timer configuration bits */
+ tcon = __raw_readl(S3C24A0_TCON);
+ tcfg1 = __raw_readl(S3C24A0_TCFG1);
+ tcfg0 = __raw_readl(S3C24A0_TCFG0);
+
+ /*Configure Timer0 input freq. divider=1/16, Prescaler=255, one shot, interrupt disable timer counter intialized to 2^16-1 */
+ /*tcf0 is used to configure prescaler0 */
+
+ tcfg0 &= ~S3C24A0_TCFG_PRESCALER0_MASK;
+ tcfg0 |= (255);
+
+ tcfg1 &= ~S3C24A0_TCFG1_MUX0_MASK;
+ tcfg1 |= S3C24A0_TCFG1_MUX0_DIV16;
+
+ tcnt = (1<<16)-1;
+
+ __raw_writel(tcfg1, S3C24A0_TCFG1);
+ __raw_writel(tcfg0, S3C24A0_TCFG0);
+
+ __raw_writel(tcnt, S3C24A0_TCNTB(0));
+
+
+ /* Stop the timer0 */
+ tcon &= ~(15);
+ tcon |= S3C24A0_TCON_T0MANUALUPD;
+ __raw_writel(tcon,S3C24A0_TCON);
+
+ /* Mask timer0 interrupt */
+ mask = __raw_readl(S3C24A0_INTMSK);
+ mask |= 1UL << (IRQ_TIMER0 - IRQ_EINT0_2);
+ __raw_writel(mask,S3C24A0_INTMSK);
+
+ /* Start the timer0 */
+ tcon |= S3C24A0_TCON_T0START;
+ tcon &= ~S3C24A0_TCON_T0MANUALUPD;
+ __raw_writel(tcon, S3C24A0_TCON);
+
+}
+
+EXPORT_SYMBOL(s3c24a0_timer0_setup);
+
+unsigned long __noinstrument s3c24a0_timer0_read(void)
+{
+ unsigned long ticks;
+ ticks = __raw_readl(S3C24A0_TCNTO(0));
+ return ticks;
+}
+
+EXPORT_SYMBOL(s3c24a0_timer0_read);
+#endif /* CONFIG_KFT */
+
+/*
+ * Set up timer interrupt, and return the current time in seconds.
+ *
+ * Currently we only use timer4, as it is the only timer which has no
+ * other function that can be exploited externally
+ */
+static void s3c24a0_timer_setup (void)
+{
+ unsigned long tcon;
+ unsigned long tcnt;
+ unsigned long tcfg1;
+ unsigned long tcfg0;
+
+ /* read the current timer configuration bits */
+ tcon = __raw_readl(S3C24A0_TCON);
+ tcfg1 = __raw_readl(S3C24A0_TCFG1);
+ tcfg0 = __raw_readl(S3C24A0_TCFG0);
+
+ tcfg1 &= ~S3C24A0_TCFG1_MUX4_MASK;
+ tcfg1 |= S3C24A0_TCFG1_MUX4_DIV2;
+
+ tcfg0 &= ~S3C24A0_TCFG_PRESCALER1_MASK;
+ tcfg0 |= (PRESCALER) << S3C24A0_TCFG_PRESCALER1_SHIFT;
+
+ tcnt = (s3c24xx_pclk / ((PRESCALER+1)*DIVIDER)) / HZ;
+
+ __raw_writel(tcfg1, S3C24A0_TCFG1);
+ __raw_writel(tcfg0, S3C24A0_TCFG0);
+
+ __raw_writel(tcnt, S3C24A0_TCNTB(4));
+
+ /* ensure timer is stopped... */
+
+ tcon &= ~(7<<20);
+ tcon |= S3C24A0_TCON_T4RELOAD;
+ tcon |= S3C24A0_TCON_T4MANUALUPD;
+
+ __raw_writel(tcon, S3C24A0_TCON);
+ __raw_writel(tcnt, S3C24A0_TCNTB(4));
+ __raw_writel(tcnt, S3C24A0_TCMPB(4));
+
+ /* start the timer running */
+ tcon |= S3C24A0_TCON_T4START;
+ tcon &= ~S3C24A0_TCON_T4MANUALUPD;
+ __raw_writel(tcon, S3C24A0_TCON);
+}
+
+unsigned long s3c24a0_get_rtc_time(void)
+{
+ unsigned int year, mon, day, hour, min, sec;
+
+ spin_lock_irq(&s3c24a0_rtc_pie_lock);
+ read_rtc_bcd_time:
+ year = readb(S3C24A0_RTCYEAR) & Msk_RTCYEAR;
+ mon = readb(S3C24A0_RTCMON) & Msk_RTCMON;
+ day = readb(S3C24A0_RTCDATE) & Msk_RTCDATE;
+ hour = readb(S3C24A0_RTCHOUR) & Msk_RTCHOUR;
+ min = readb(S3C24A0_RTCMIN) & Msk_RTCMIN;
+ sec = readb(S3C24A0_RTCSEC) & Msk_RTCSEC;
+ if (sec == 0) {
+ /* If S3C24A0_RTCSEC is zero, reread all bcd registers.
+ See Section 17.2 READ/WRITE REGISTERS for more info. */
+ goto read_rtc_bcd_time;
+ }
+ spin_unlock_irq(&s3c24a0_rtc_pie_lock);
+
+ BCD_TO_BIN(year);
+ BCD_TO_BIN(mon);
+ BCD_TO_BIN(day);
+ BCD_TO_BIN(hour);
+ BCD_TO_BIN(min);
+ BCD_TO_BIN(sec);
+
+ year += RTC_LEAP_YEAR;
+
+ return (mktime(year, mon, day, hour, min, sec));
+}
+
+#define epoch 1970
+
+static const unsigned char days_in_mo[] =
+ { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
+
+#ifndef is_leap
+#define is_leap(year) \
+ ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
+#endif
+
+static void decodetime(unsigned long t, struct rtc_time *tval)
+{
+ unsigned long days, month, year, rem;
+
+ days = t / 86400;
+ rem = t % 86400;
+ tval->tm_hour = rem / 3600;
+ rem %= 3600;
+ tval->tm_min = rem / 60;
+ tval->tm_sec = rem % 60;
+ tval->tm_wday = (4 + days) % 7;
+
+#define LEAPS_THRU_END_OF(y) ((y)/4 - (y)/100 + (y)/400)
+
+ year = epoch;
+ while (days >= (365 + is_leap(year))) {
+ unsigned long yg = year + days / 365;
+ days -= ((yg - year) * 365 + LEAPS_THRU_END_OF(yg - 1)
+ - LEAPS_THRU_END_OF(year - 1));
+ year = yg;
+ }
+ tval->tm_year = year - 1900;
+ tval->tm_yday = days + 1;
+
+ month = 0;
+ if (days >= 31) {
+ days -= 31;
+ month++;
+ if (days >= (28 + is_leap(year))) {
+ days -= (28 + is_leap(year));
+ month++;
+ while (days >= days_in_mo[month]) {
+ days -= days_in_mo[month];
+ month++;
+ }
+ }
+ }
+ tval->tm_mon = month;
+ tval->tm_mday = days + 1;
+}
+
+static void __init s3c24a0_timer_init (void)
+{
+ xtime.tv_sec = s3c24a0_get_rtc_time();
+
+ s3c24a0_timer_setup();
+ setup_irq(IRQ_TIMER4, &s3c24a0_timer_irq);
+}
+
+struct sys_timer s3c24a0_timer = {
+ .init = s3c24a0_timer_init,
+ .offset = s3c24a0_gettimeoffset,
+ .resume = s3c24a0_timer_setup
+};
+
+
+//EXPORT_SYMBOL(s3c24a0_get_rtc_time);
+
+
Why is there code to read the rtc in here?
diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig
index aade2f7..11e8546 100644
--- a/arch/arm/mm/Kconfig
+++ b/arch/arm/mm/Kconfig
@@ -171,7 +171,7 @@ config CPU_ARM925T
# ARM926T
config CPU_ARM926T
bool "Support ARM926T processor"
- depends on ARCH_INTEGRATOR || ARCH_VERSATILE_PB || MACH_VERSATILE_AB || ARCH_OMAP730 || ARCH_OMAP16XX || MACH_REALVIEW_EB || ARCH_PNX4008 || ARCH_NETX || CPU_S3C2412 || ARCH_AT91SAM9260 || ARCH_AT91SAM9261
+ depends on ARCH_INTEGRATOR || ARCH_VERSATILE_PB || MACH_VERSATILE_AB || ARCH_OMAP730 || ARCH_OMAP16XX || MACH_REALVIEW_EB || ARCH_PNX4008 || ARCH_NETX || CPU_S3C2412 || ARCH_AT91SAM9260 || ARCH_AT91SAM9261 || MACH_S3C24A0
default y if ARCH_VERSATILE_PB || MACH_VERSATILE_AB || ARCH_OMAP730 || ARCH_OMAP16XX || ARCH_PNX4008 || ARCH_NETX || CPU_S3C2412 || ARCH_AT91SAM9260 || ARCH_AT91SAM9261
select CPU_32v5
select CPU_ABRT_EV5TJ
diff --git a/drivers/base/dma-mapping.c b/drivers/base/dma-mapping.c
index ca9186f..4489e60 100644
--- a/drivers/base/dma-mapping.c
+++ b/drivers/base/dma-mapping.c
@@ -8,7 +8,8 @@
*/
#include
-
+/* FIX ME, added to build cleanly, devres patch has broken the build */
+#include
/*
* Managed DMA API
*/
Why? Has any onlist discussion of this been done?
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index d0edbaa..88ca634 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -391,6 +391,31 @@ config SERIAL_S3C2410_CONSOLE
your boot loader about how to pass options to the kernel at
boot time.)
+config SERIAL_S3C24A0
+ tristate "Samsung S3C24A0 Serial port support"
+ depends on ARM && MACH_S3C24A0
+ select SERIAL_CORE
+ help
+ Support for the on-chip UARTs on the Samsung S3C24A0 CPU,
+ providing /dev/ttySAC0, 1 and 2 (note, some machines may not
+ provide all of these ports, depending on how the serial port
+ pins are configured.
+
+config SERIAL_S3C24A0_CONSOLE
+ bool "Support for console on S3C24A0 serial port"
+ depends on SERIAL_S3C24A0=y
+ select SERIAL_CORE_CONSOLE
+ help
+ Allow selection of the S3C24A0 on-board serial ports for use as
+ an virtual console.
+
+ Even if you say Y here, the currently visible virtual console
+ (/dev/tty0) will still be used as the system console by default, but
+ you can alter that using a kernel command line option such as
+ "console=ttySACx". (Try "man bootparam" or see the documentation of
+ your boot loader about how to pass options to the kernel at
+ boot time.)
+
config SERIAL_DZ
bool "DECstation DZ serial driver"
depends on MACH_DECSTATION && 32BIT
diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
index f3f8258..7d74d84 100644
--- a/drivers/serial/Makefile
+++ b/drivers/serial/Makefile
@@ -27,6 +27,7 @@ obj-$(CONFIG_SERIAL_CLPS711X) += clps711
obj-$(CONFIG_SERIAL_PXA) += pxa.o
obj-$(CONFIG_SERIAL_SA1100) += sa1100.o
obj-$(CONFIG_SERIAL_S3C2410) += s3c2410.o
+obj-$(CONFIG_SERIAL_S3C24A0) += s3c24a0.o
obj-$(CONFIG_SERIAL_SUNCORE) += suncore.o
obj-$(CONFIG_SERIAL_SUNHV) += sunhv.o
obj-$(CONFIG_SERIAL_SUNZILOG) += sunzilog.o
diff --git a/drivers/serial/s3c24a0.c b/drivers/serial/s3c24a0.c
new file mode 100644
index 0000000..b680e07
--- /dev/null
+++ b/drivers/serial/s3c24a0.c
@@ -0,0 +1,1485 @@
+/*
+ * linux/drivers/serial/s3c24a0.c
+ *
+ * Driver for onboard UARTs on the Samsung S3C24XX
+ *
+ * Based on drivers/char/serial.c and drivers/char/21285.c
+ *
+ * Ben Dooks, (c) 2003 Simtec Electronics
+ *
+ * Changelog:
+ *
+ * 22-Jul-2004 BJD Finished off device rewrite
+ *
+ * 21-Jul-2004 BJD Thanks to for pointing out
+ * problems with baud rate and loss of IR settings. Update
+ * to add configuration via platform_device structure
+ *
+ * 28-Sep-2004 BJD Re-write for the following items
+ * - S3C24A0 serial support
+ * - Power Management support
+ * - Fix console via IrDA devices
+ * - SysReq (Herbert Pötzl)
+ * - Break character handling (Herbert Pötzl)
+ * - spin-lock initialisation (Dimitry Andric)
+ * - added clock control
+ * - updated init code to use platform_device info
+*/
+
+/* Hote on 24A0 error handling
+ *
+ * The s3c24a0 manual has a love/hate affair with the contents of the
+ * UERSTAT register in the UART blocks, and keeps marking some of the
+ * error bits as reserved. Having checked with the s3c24a0x01,
+ * it copes with BREAKs properly, so I am happy to ignore the RESERVED
+ * feature from the latter versions of the manual.
+ *
+ * If it becomes aparrent that latter versions of the 2410 remove these
+ * bits, then action will have to be taken to differentiate the versions
+ * and change the policy on BREAK
+ *
+ * BJD, 04-Nov-2004
+*/
+
+
+#if defined(CONFIG_SERIAL_S3C24A0_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
+#define SUPPORT_SYSRQ
+#endif
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+
+#include
+//#include
+
+#include
+#include
+
+#include
+
+/* structures */
+
+struct s3c24xx_uart_info {
+ char *name;
+ unsigned int type;
+ unsigned int fifosize;
+ unsigned long rx_fifomask;
+ unsigned long rx_fifoshift;
+ unsigned long rx_fifofull;
+ unsigned long tx_fifomask;
+ unsigned long tx_fifoshift;
+ unsigned long tx_fifofull;
+
+ /* clock source control */
+
+ int (*get_clksrc)(struct uart_port *, struct s3c24xx_uart_clksrc *clk);
+ int (*set_clksrc)(struct uart_port *, struct s3c24xx_uart_clksrc *clk);
+};
+
+struct s3c24xx_uart_port {
+ unsigned char rx_claimed;
+ unsigned char tx_claimed;
+
+ struct s3c24xx_uart_info *info;
+ struct s3c24xx_uart_clksrc *clksrc;
+ struct clk *clk;
+ struct clk *baudclk;
+ struct uart_port port;
+};
+
+
+/* configuration defines */
+
+#if 0
+#if 1
+/* send debug to the low-level output routines */
+
+extern void printascii(const char *);
+
+static void
+s3c24xx_serial_dbg(const char *fmt, ...)
+{
+ va_list va;
+ char buff[256];
+
+ va_start(va, fmt);
+ vsprintf(buff, fmt, va);
+ va_end(va);
+
+ printascii(buff);
+}
+
+#define dbg(x...) s3c24xx_serial_dbg(x)
+
+#else
+#define dbg(x...) printk(KERN_DEBUG "s3c24xx: ");
+#endif
+#else /* no debug */
+#define dbg(x...) do {} while(0)
+#endif
+
+/* UART name and device definitions */
+
+#define S3C24XX_SERIAL_NAME "ttyS"
+#define S3C24XX_SERIAL_DEVFS "tts/"
+#define S3C24XX_SERIAL_MAJOR 204
+#define S3C24XX_SERIAL_MINOR 64
+
+
+/* conversion functions */
+
+#define s3c24xx_dev_to_port(__dev) (struct uart_port *)dev_get_drvdata(__dev)
+#define s3c24xx_dev_to_cfg(__dev) (struct s3c24a0_uartcfg *)((__dev)->platform_data)
+
+/* we can support 2 uarts, but not always use them */
+
+#define NR_PORTS (2)
+
+/* port irq numbers */
+
+#define TX_IRQ(port) ((port)->irq + 1)
+#define RX_IRQ(port) ((port)->irq)
+
+/* register access controls */
+
+#define portaddr(port, reg) ((port)->membase + (reg))
+
+#define rd_regb(port, reg) (__raw_readb(portaddr(port, reg)))
+#define rd_regl(port, reg) (__raw_readl(portaddr(port, reg)))
+
+#define wr_regb(port, reg, val) \
+ do { __raw_writeb(val, portaddr(port, reg)); } while(0)
+
+#define wr_regl(port, reg, val) \
+ do { __raw_writel(val, portaddr(port, reg)); } while(0)
+
+/* macros to change one thing to another */
+
+#define tx_enabled(port) ((port)->unused[0])
+#define rx_enabled(port) ((port)->unused[1])
+
+/* flag to ignore all characters comming in */
+#define RXSTAT_DUMMY_READ (0x10000000)
+
+static inline struct s3c24xx_uart_port *to_ourport(struct uart_port *port)
+{
+ return container_of(port, struct s3c24xx_uart_port, port);
+}
+
+/* translate a port to the device name */
+
+static inline const char *s3c24xx_serial_portname(struct uart_port *port)
+{
+ return to_platform_device(port->dev)->name;
+}
+
+static int s3c24xx_serial_txempty_nofifo(struct uart_port *port)
+{
+ return (rd_regl(port, S3C24A0_UTRSTAT) & S3C24A0_UTRSTAT_TXE);
+}
+
+static void s3c24xx_serial_rx_enable(struct uart_port *port)
+{
+ unsigned long flags;
+ unsigned int ucon, ufcon;
+ int count = 10000;
+
+ spin_lock_irqsave(&port->lock, flags);
+
+ while (--count && !s3c24xx_serial_txempty_nofifo(port))
+ udelay(100);
+
+ ufcon = rd_regl(port, S3C24A0_UFCON);
+ ufcon |= S3C24A0_UFCON_RESETRX;
+ wr_regl(port, S3C24A0_UFCON, ufcon);
+
+ ucon = rd_regl(port, S3C24A0_UCON);
+ ucon |= S3C24A0_UCON_RXIRQMODE;
+ wr_regl(port, S3C24A0_UCON, ucon);
+
+ rx_enabled(port) = 1;
+ spin_unlock_irqrestore(&port->lock, flags);
+}
+
+static void s3c24xx_serial_rx_disable(struct uart_port *port)
+{
+ unsigned long flags;
+ unsigned int ucon;
+
+ spin_lock_irqsave(&port->lock, flags);
+
+ ucon = rd_regl(port, S3C24A0_UCON);
+ ucon &= ~S3C24A0_UCON_RXIRQMODE;
+ wr_regl(port, S3C24A0_UCON, ucon);
+
+ rx_enabled(port) = 0;
+ spin_unlock_irqrestore(&port->lock, flags);
+}
+
+static void
+s3c24xx_serial_stop_tx(struct uart_port *port)
+{
+ if (tx_enabled(port)) {
+ disable_irq(TX_IRQ(port));
+ tx_enabled(port) = 0;
+ if (port->flags & UPF_CONS_FLOW)
+ s3c24xx_serial_rx_enable(port);
+ }
+}
+
+static void
+s3c24xx_serial_start_tx(struct uart_port *port)
+{
+ if (!tx_enabled(port)) {
+ if (port->flags & UPF_CONS_FLOW)
+ s3c24xx_serial_rx_disable(port);
+
+ enable_irq(TX_IRQ(port));
+ tx_enabled(port) = 1;
+ }
+}
+
+
+static void s3c24xx_serial_stop_rx(struct uart_port *port)
+{
+ if (rx_enabled(port)) {
+ dbg("s3c24xx_serial_stop_rx: port=%p\n", port);
+ disable_irq(RX_IRQ(port));
+ rx_enabled(port) = 0;
+ }
+}
+
+static void s3c24xx_serial_enable_ms(struct uart_port *port)
+{
+}
+
+static inline struct s3c24xx_uart_info *s3c24xx_port_to_info(struct uart_port *port)
+{
+ return to_ourport(port)->info;
+}
+
+static inline struct s3c24a0_uartcfg *s3c24xx_port_to_cfg(struct uart_port *port)
+{
+ if (port->dev == NULL)
+ return NULL;
+
+ return (struct s3c24a0_uartcfg *)port->dev->platform_data;
+}
+
+static int s3c24xx_serial_rx_fifocnt(struct s3c24xx_uart_port *ourport,
+ unsigned long ufstat)
+{
+ struct s3c24xx_uart_info *info = ourport->info;
+
+ if (ufstat & info->rx_fifofull)
+ return info->fifosize;
+
+ return (ufstat & info->rx_fifomask) >> info->rx_fifoshift;
+}
+
+
+/* ? - where has parity gone?? */
+#define S3C24A0_UERSTAT_PARITY (0x1000)
+
+static irqreturn_t
+s3c24xx_serial_rx_chars(int irq, void *dev_id)
+{
+ struct s3c24xx_uart_port *ourport = dev_id;
+ struct uart_port *port = &ourport->port;
+ struct tty_struct *tty = port->info->tty;
+ unsigned int ufcon, ch, flag, ufstat, uerstat;
+ int max_count = 64;
+
+ while (max_count-- > 0) {
+ ufcon = rd_regl(port, S3C24A0_UFCON);
+ ufstat = rd_regl(port, S3C24A0_UFSTAT);
+
+ if (s3c24xx_serial_rx_fifocnt(ourport, ufstat) == 0)
+ break;
+
+#if 0
+ FIXME : amitb - remove completely
+ if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
+ if (tty->low_latency)
+ tty_flip_buffer_push(tty);
+
+ /*
+ * If this failed then we will throw away the
+ * bytes but must do so to clear interrupts
+ */
+ }
+#endif
+
+ uerstat = rd_regl(port, S3C24A0_UERSTAT);
+ ch = rd_regb(port, S3C24A0_URXH);
+
+ if (port->flags & UPF_CONS_FLOW) {
+ int txe = s3c24xx_serial_txempty_nofifo(port);
+
+ if (rx_enabled(port)) {
+ if (!txe) {
+ rx_enabled(port) = 0;
+ continue;
+ }
+ } else {
+ if (txe) {
+ ufcon |= S3C24A0_UFCON_RESETRX;
+ wr_regl(port, S3C24A0_UFCON, ufcon);
+ rx_enabled(port) = 1;
+ goto out;
+ }
+ continue;
+ }
+ }
+
+ /* insert the character into the buffer */
+
+ flag = TTY_NORMAL;
+ port->icount.rx++;
+
+ if (uerstat & S3C24A0_UERSTAT_ANY) {
+ dbg("rxerr: port ch=0x%02x, rxs=0x%08x\n",
+ ch, uerstat);
+
+ /* check for break */
+ if (uerstat & S3C24A0_UERSTAT_BREAK) {
+ dbg("break!\n");
+ port->icount.brk++;
+ if (uart_handle_break(port))
+ goto ignore_char;
+ }
+
+ if (uerstat & S3C24A0_UERSTAT_FRAME)
+ port->icount.frame++;
+ if (uerstat & S3C24A0_UERSTAT_OVERRUN)
+ port->icount.overrun++;
+
+ uerstat &= port->read_status_mask;
+
+ if (uerstat & S3C24A0_UERSTAT_BREAK)
+ flag = TTY_BREAK;
+ else if (uerstat & S3C24A0_UERSTAT_PARITY)
+ flag = TTY_PARITY;
+ else if (uerstat & ( S3C24A0_UERSTAT_FRAME | S3C24A0_UERSTAT_OVERRUN))
+ flag = TTY_FRAME;
+ }
+
+ if (uart_handle_sysrq_char(port, ch))
+ goto ignore_char;
+
+ uart_insert_char(port, uerstat, S3C24A0_UERSTAT_OVERRUN, ch, flag);
+
+ ignore_char:
+ continue;
+ }
+ tty_flip_buffer_push(tty);
+
+ out:
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t s3c24xx_serial_tx_chars(int irq, void *id)
+{
+ struct s3c24xx_uart_port *ourport = id;
+ struct uart_port *port = &ourport->port;
+ struct circ_buf *xmit = &port->info->xmit;
+ int count = 256;
+
+ if (port->x_char) {
+ wr_regb(port, S3C24A0_UTXH, port->x_char);
+ port->icount.tx++;
+ port->x_char = 0;
+ goto out;
+ }
+
+ /* if there isnt anything more to transmit, or the uart is now
+ * stopped, disable the uart and exit
+ */
+
+ if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
+ s3c24xx_serial_stop_tx(port);
+ goto out;
+ }
+
+ /* try and drain the buffer... */
+
+ while (!uart_circ_empty(xmit) && count-- > 0) {
+ if (rd_regl(port, S3C24A0_UFSTAT) & ourport->info->tx_fifofull)
+ break;
+
+ wr_regb(port, S3C24A0_UTXH, xmit->buf[xmit->tail]);
+ xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
+ port->icount.tx++;
+ }
+
+ if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+ uart_write_wakeup(port);
+
+ if (uart_circ_empty(xmit))
+ s3c24xx_serial_stop_tx(port);
+
+ out:
+ return IRQ_HANDLED;
+}
+
+static unsigned int s3c24xx_serial_tx_empty(struct uart_port *port)
+{
+ struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port);
+ unsigned long ufstat = rd_regl(port, S3C24A0_UFSTAT);
+ unsigned long ufcon = rd_regl(port, S3C24A0_UFCON);
+
+ if (ufcon & S3C24A0_UFCON_FIFOMODE) {
+ if ((ufstat & info->tx_fifomask) != 0 ||
+ (ufstat & info->tx_fifofull))
+ return 0;
+
+ return 1;
+ }
+
+ return s3c24xx_serial_txempty_nofifo(port);
+}
+
+/* no modem control lines */
+static unsigned int s3c24xx_serial_get_mctrl(struct uart_port *port)
+{
+ unsigned int umstat = rd_regb(port,S3C24A0_UMSTAT);
+
+ if (umstat & S3C24A0_UMSTAT_CTS)
+ return TIOCM_CAR | TIOCM_DSR | TIOCM_CTS;
+ else
+ return TIOCM_CAR | TIOCM_DSR;
+}
+
+static void s3c24xx_serial_set_mctrl(struct uart_port *port, unsigned int mctrl)
+{
+ /* todo - possibly remove AFC and do manual CTS */
+}
+
+static void s3c24xx_serial_break_ctl(struct uart_port *port, int break_state)
+{
+ unsigned long flags;
+ unsigned int ucon;
+
+ spin_lock_irqsave(&port->lock, flags);
+
+ ucon = rd_regl(port, S3C24A0_UCON);
+
+ if (break_state)
+ ucon |= S3C24A0_UCON_SBREAK;
+ else
+ ucon &= ~S3C24A0_UCON_SBREAK;
+
+ wr_regl(port, S3C24A0_UCON, ucon);
+
+ spin_unlock_irqrestore(&port->lock, flags);
+}
+
+static void s3c24xx_serial_shutdown(struct uart_port *port)
+{
+ struct s3c24xx_uart_port *ourport = to_ourport(port);
+
+ if (ourport->tx_claimed) {
+ free_irq(TX_IRQ(port), ourport);
+ tx_enabled(port) = 0;
+ ourport->tx_claimed = 0;
+ }
+
+ if (ourport->rx_claimed) {
+ free_irq(RX_IRQ(port), ourport);
+ ourport->rx_claimed = 0;
+ rx_enabled(port) = 0;
+ }
+}
+
+
+static int s3c24xx_serial_startup(struct uart_port *port)
+{
+ struct s3c24xx_uart_port *ourport = to_ourport(port);
+ unsigned long flags;
+ int ret;
+
+ dbg("s3c24xx_serial_startup: port=%p (%08lx,%p)\n",
+ port->mapbase, port->membase);
+
+ local_irq_save(flags);
+
+ rx_enabled(port) = 1;
+
+ ret = request_irq(RX_IRQ(port),
+ s3c24xx_serial_rx_chars, 0,
+ s3c24xx_serial_portname(port), ourport);
+
+ if (ret != 0) {
+ printk(KERN_ERR "cannot get irq %d\n", RX_IRQ(port));
+ return ret;
+ }
+
+ ourport->rx_claimed = 1;
+
+ dbg("requesting tx irq...\n");
+
+ tx_enabled(port) = 1;
+
+ ret = request_irq(TX_IRQ(port),
+ s3c24xx_serial_tx_chars, 0,
+ s3c24xx_serial_portname(port), ourport);
+
+ if (ret) {
+ printk(KERN_ERR "cannot get irq %d\n", TX_IRQ(port));
+ goto err;
+ }
+
+ ourport->tx_claimed = 1;
+
+ dbg("s3c24xx_serial_startup ok\n");
+
+ /* the port reset code should have done the correct
+ * register setup for the port controls */
+
+ local_irq_restore(flags);
+ return ret;
+
+ err:
+ s3c24xx_serial_shutdown(port);
+ local_irq_restore(flags);
+ return ret;
+}
+
+/* power power management control */
+
+static void s3c24xx_serial_pm(struct uart_port *port, unsigned int level,
+ unsigned int old)
+{
+ struct s3c24xx_uart_port *ourport = to_ourport(port);
+
+ switch (level) {
+ case 3:
+ if (!IS_ERR(ourport->baudclk) && ourport->baudclk != NULL)
+ clk_disable(ourport->baudclk);
+
+ clk_disable(ourport->clk);
+ break;
+
+ case 0:
+ clk_enable(ourport->clk);
+
+ if (!IS_ERR(ourport->baudclk) && ourport->baudclk != NULL)
+ clk_enable(ourport->baudclk);
+
+ break;
+ default:
+ printk(KERN_ERR "s3c24xx_serial: unknown pm %d\n", level);
+ }
+}
+
+/* baud rate calculation
+ *
+ * The UARTs on the S3C24A0 can take their clocks from a number
+ * of different sources, including the peripheral clock ("pclk") and an
+ * external clock
+ *
+ * The following code goes through the clock sources, and calculates the
+ * baud clocks (and the resultant actual baud rates) and then tries to
+ * pick the closest one and select that.
+ *
+*/
+
+
+#define MAX_CLKS (8)
+
+static struct s3c24xx_uart_clksrc tmp_clksrc = {
+ .name = "pclk",
+ .min_baud = 0,
+ .max_baud = 0,
+ .divisor = 1,
+};
+
+static inline int
+s3c24xx_serial_getsource(struct uart_port *port, struct s3c24xx_uart_clksrc *c)
+{
+ struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port);
+
+ return (info->get_clksrc)(port, c);
+}
+
+static inline int
+s3c24xx_serial_setsource(struct uart_port *port, struct s3c24xx_uart_clksrc *c)
+{
+ struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port);
+
+ return (info->set_clksrc)(port, c);
+}
+
+struct baud_calc {
+ struct s3c24xx_uart_clksrc *clksrc;
+ unsigned int calc;
+ unsigned int quot;
+ struct clk *src;
+};
+
+static int s3c24xx_serial_calcbaud(struct baud_calc *calc,
+ struct uart_port *port,
+ struct s3c24xx_uart_clksrc *clksrc,
+ unsigned int baud)
+{
+ unsigned long rate;
+
+ calc->src = clk_get(port->dev, clksrc->name);
+ if (calc->src == NULL || IS_ERR(calc->src))
+ return 0;
+
+ rate = clk_get_rate(calc->src);
+
+ calc->clksrc = clksrc;
+ calc->quot = (rate + (8 * baud)) / (16 * baud);
+ calc->calc = (rate / (calc->quot * 16));
+
+ calc->quot--;
+ return 1;
+}
+
+static unsigned int s3c24xx_serial_getclk(struct uart_port *port,
+ struct s3c24xx_uart_clksrc **clksrc,
+ struct clk **clk,
+ unsigned int baud)
+{
+ struct s3c24a0_uartcfg *cfg = s3c24xx_port_to_cfg(port);
+ struct s3c24xx_uart_clksrc *clkp;
+ struct baud_calc res[MAX_CLKS];
+ struct baud_calc *resptr, *best, *sptr;
+ int i;
+
+ clkp = cfg->clocks;
+ best = NULL;
+
+ if (cfg->clocks_size < 2) {
+ if (cfg->clocks_size == 0)
+ clkp = &tmp_clksrc;
+
+ s3c24xx_serial_calcbaud(res, port, clkp, baud);
+ best = res;
+ resptr = best + 1;
+ } else {
+ resptr = res;
+
+ for (i = 0; i < cfg->clocks_size; i++, clkp++) {
+ if (s3c24xx_serial_calcbaud(resptr, port, clkp, baud))
+ resptr++;
+ }
+ }
+
+ /* ok, we now need to select the best clock we found */
+
+ if (!best) {
+ unsigned int deviation = (1<<30)|((1<<30)-1);
+ int calc_deviation;
+
+ for (sptr = res; sptr < resptr; sptr++) {
+ printk(KERN_DEBUG
+ "found clk %p (%s) quot %d, calc %d\n",
+ sptr->clksrc, sptr->clksrc->name,
+ sptr->quot, sptr->calc);
+
+ calc_deviation = baud - sptr->calc;
+ if (calc_deviation < 0)
+ calc_deviation = -calc_deviation;
+
+ if (calc_deviation < deviation) {
+ best = sptr;
+ deviation = calc_deviation;
+ }
+ }
+
+ printk(KERN_DEBUG "best %p (deviation %d)\n", best, deviation);
+ }
+
+ printk(KERN_DEBUG "selected clock %p (%s) quot %d, calc %d\n",
+ best->clksrc, best->clksrc->name, best->quot, best->calc);
+
+ /* store results to pass back */
+
+ *clksrc = best->clksrc;
+ *clk = best->src;
+
+ return best->quot;
+}
+
+static void s3c24xx_serial_set_termios(struct uart_port *port,
+ struct ktermios *termios,
+ struct ktermios *old)
+{
+ struct s3c24a0_uartcfg *cfg = s3c24xx_port_to_cfg(port);
+ struct s3c24xx_uart_port *ourport = to_ourport(port);
+ struct s3c24xx_uart_clksrc *clksrc;
+ struct clk *clk;
+ unsigned long flags;
+ unsigned int baud, quot;
+ unsigned int ulcon;
+
+ /*
+ * We don't support modem control lines.
+ */
+ termios->c_cflag &= ~(HUPCL | CRTSCTS | CMSPAR);
+ termios->c_cflag |= CLOCAL;
+
+ /*
+ * Ask the core to calculate the divisor for us.
+ */
+
+ baud = uart_get_baud_rate(port, termios, old, 0, 115200*8);
+
+ if (baud == 38400 && (port->flags & UPF_SPD_MASK) == UPF_SPD_CUST)
+ quot = port->custom_divisor;
+ else
+ quot = s3c24xx_serial_getclk(port, &clksrc, &clk, baud);
+
+ /* check to see if we need to change clock source */
+
+ if (ourport->clksrc != clksrc || ourport->baudclk != clk) {
+ s3c24xx_serial_setsource(port, clksrc);
+
+ if (ourport->baudclk != NULL && !IS_ERR(ourport->baudclk)) {
+ clk_disable(ourport->baudclk);
+ ourport->baudclk = NULL;
+ }
+
+ clk_enable(clk);
+
+ ourport->clksrc = clksrc;
+ ourport->baudclk = clk;
+ }
+
+ switch (termios->c_cflag & CSIZE) {
+ case CS5:
+ dbg("config: 5bits/char\n");
+ ulcon = S3C24A0_LCON_CS5;
+ break;
+ case CS6:
+ dbg("config: 6bits/char\n");
+ ulcon = S3C24A0_LCON_CS6;
+ break;
+ case CS7:
+ dbg("config: 7bits/char\n");
+ ulcon = S3C24A0_LCON_CS7;
+ break;
+ case CS8:
+ default:
+ dbg("config: 8bits/char\n");
+ ulcon = S3C24A0_LCON_CS8;
+ break;
+ }
+
+ /* preserve original lcon IR settings */
+ ulcon |= (cfg->ulcon & S3C24A0_LCON_IRM);
+
+ if (termios->c_cflag & CSTOPB)
+ ulcon |= S3C24A0_LCON_STOPB;
+
+ if (termios->c_cflag & PARENB) {
+ if (!(termios->c_cflag & PARODD))
+ ulcon |= S3C24A0_LCON_PODD;
+ else
+ ulcon |= S3C24A0_LCON_PEVEN;
+ } else {
+ ulcon |= S3C24A0_LCON_PNONE;
+ }
+
+ spin_lock_irqsave(&port->lock, flags);
+
+ dbg("setting ulcon to %08x, brddiv to %d\n", ulcon, quot);
+
+ wr_regl(port, S3C24A0_ULCON, ulcon);
+ wr_regl(port, S3C24A0_UBRDIV, quot);
+
+ dbg("uart: ulcon = 0x%08x, ucon = 0x%08x, ufcon = 0x%08x\n",
+ rd_regl(port, S3C24A0_ULCON),
+ rd_regl(port, S3C24A0_UCON),
+ rd_regl(port, S3C24A0_UFCON));
+
+ /*
+ * Update the per-port timeout.
+ */
+ uart_update_timeout(port, termios->c_cflag, baud);
+
+ /*
+ * Which character status flags are we interested in?
+ */
+ port->read_status_mask = S3C24A0_UERSTAT_OVERRUN;
+ if (termios->c_iflag & INPCK)
+ port->read_status_mask |= S3C24A0_UERSTAT_FRAME | S3C24A0_UERSTAT_PARITY;
+
+ /*
+ * Which character status flags should we ignore?
+ */
+ port->ignore_status_mask = 0;
+ if (termios->c_iflag & IGNPAR)
+ port->ignore_status_mask |= S3C24A0_UERSTAT_OVERRUN;
+ if (termios->c_iflag & IGNBRK && termios->c_iflag & IGNPAR)
+ port->ignore_status_mask |= S3C24A0_UERSTAT_FRAME;
+
+ /*
+ * Ignore all characters if CREAD is not set.
+ */
+ if ((termios->c_cflag & CREAD) == 0)
+ port->ignore_status_mask |= RXSTAT_DUMMY_READ;
+
+ spin_unlock_irqrestore(&port->lock, flags);
+}
+
+static const char *s3c24xx_serial_type(struct uart_port *port)
+{
+ switch (port->type) {
+ case PORT_S3C24A0:
+ return "S3C24A0";
+ default:
+ return NULL;
+ }
+}
+
+#define MAP_SIZE (0x100)
+
+static void s3c24xx_serial_release_port(struct uart_port *port)
+{
+ release_mem_region(port->mapbase, MAP_SIZE);
+}
+
+static int s3c24xx_serial_request_port(struct uart_port *port)
+{
+ const char *name = s3c24xx_serial_portname(port);
+ return request_mem_region(port->mapbase, MAP_SIZE, name) ? 0 : -EBUSY;
+}
+
+static void s3c24xx_serial_config_port(struct uart_port *port, int flags)
+{
+ struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port);
+
+ if (flags & UART_CONFIG_TYPE &&
+ s3c24xx_serial_request_port(port) == 0)
+ port->type = info->type;
+}
+
+/*
+ * verify the new serial_struct (for TIOCSSERIAL).
+ */
+static int
+s3c24xx_serial_verify_port(struct uart_port *port, struct serial_struct *ser)
+{
+ struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port);
+
+ if (ser->type != PORT_UNKNOWN && ser->type != info->type)
+ return -EINVAL;
+
+ return 0;
+}
+
+
+#ifdef CONFIG_SERIAL_S3C24A0_CONSOLE
+
+static struct console s3c24xx_serial_console;
+
+#define S3C24XX_SERIAL_CONSOLE &s3c24xx_serial_console
+#else
+#define S3C24XX_SERIAL_CONSOLE NULL
+#endif
+
+static struct uart_ops s3c24xx_serial_ops = {
+ .pm = s3c24xx_serial_pm,
+ .tx_empty = s3c24xx_serial_tx_empty,
+ .get_mctrl = s3c24xx_serial_get_mctrl,
+ .set_mctrl = s3c24xx_serial_set_mctrl,
+ .stop_tx = s3c24xx_serial_stop_tx,
+ .start_tx = s3c24xx_serial_start_tx,
+ .stop_rx = s3c24xx_serial_stop_rx,
+ .enable_ms = s3c24xx_serial_enable_ms,
+ .break_ctl = s3c24xx_serial_break_ctl,
+ .startup = s3c24xx_serial_startup,
+ .shutdown = s3c24xx_serial_shutdown,
+ .set_termios = s3c24xx_serial_set_termios,
+ .type = s3c24xx_serial_type,
+ .release_port = s3c24xx_serial_release_port,
+ .request_port = s3c24xx_serial_request_port,
+ .config_port = s3c24xx_serial_config_port,
+ .verify_port = s3c24xx_serial_verify_port,
+};
+
+
+static struct uart_driver s3c24xx_uart_drv = {
+ .owner = THIS_MODULE,
+ .dev_name = "s3c24a0_serial",
+ .nr = 2,
+ .cons = S3C24XX_SERIAL_CONSOLE,
+ .driver_name = S3C24XX_SERIAL_NAME,
+ .major = S3C24XX_SERIAL_MAJOR,
+ .minor = S3C24XX_SERIAL_MINOR,
+};
+
+static struct s3c24xx_uart_port s3c24xx_serial_ports[NR_PORTS] = {
+ [0] = {
+ .port = {
+ .lock = SPIN_LOCK_UNLOCKED,
+ .membase = 0,
+ .mapbase = 0,
+ .iotype = UPIO_MEM,
+ .irq = IRQ_RXD0,
+ .uartclk = 0,
+ .fifosize = 16,
+ .ops = &s3c24xx_serial_ops,
+ .flags = UPF_BOOT_AUTOCONF,
+ .line = 0,
+ }
+ },
+ [1] = {
+ .port = {
+ .lock = SPIN_LOCK_UNLOCKED,
+ .membase = 0,
+ .mapbase = 0,
+ .iotype = UPIO_MEM,
+ .irq = IRQ_RXD1,
+ .uartclk = 0,
+ .fifosize = 16,
+ .ops = &s3c24xx_serial_ops,
+ .flags = UPF_BOOT_AUTOCONF,
+ .line = 1,
+ }
+ }
+};
+
+
+static int s3c24xx_serial_resetport(struct uart_port *port,
+ struct s3c24a0_uartcfg *cfg)
+{
+ /* ensure registers are setup */
+
+ dbg("s3c24xx_serial_resetport: port=%p (%08lx), cfg=%p\n",
+ port, port->mapbase, cfg);
+
+ wr_regl(port, S3C24A0_UCON, cfg->ucon);
+ wr_regl(port, S3C24A0_ULCON, cfg->ulcon);
+
+ /* reset both fifos */
+
+ wr_regl(port, S3C24A0_UFCON, cfg->ufcon | S3C24A0_UFCON_RESETBOTH);
+ wr_regl(port, S3C24A0_UFCON, cfg->ufcon);
+
+ return 0;
+}
+
+/* s3c24xx_serial_init_port
+ *
+ * initialise a single serial port from the platform device given
+ */
+
+static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport,
+ struct s3c24xx_uart_info *info,
+ struct platform_device *platdev)
+{
+ struct uart_port *port = &ourport->port;
+ struct s3c24a0_uartcfg *cfg;
+ struct resource *res;
+
+ dbg("s3c24xx_serial_init_port: port=%p, platdev=%p\n", port, platdev);
+
+ if (platdev == NULL)
+ return -ENODEV;
+
+ cfg = s3c24xx_dev_to_cfg(&platdev->dev);
+
+ if (port->mapbase != 0)
+ return 0;
+
+ if (cfg->hwport > 3)
+ return -EINVAL;
+
+ /* setup info for port */
+ port->dev = &platdev->dev;
+ ourport->info = info;
+
+ /* copy the info in from provided structure */
+ ourport->port.fifosize = info->fifosize;
+
+ dbg("s3c24xx_serial_init_port: %p (hw %d)...\n", port, cfg->hwport);
+
+ port->uartclk = 1;
+
+ if (cfg->uart_flags & UPF_CONS_FLOW) {
+ dbg("s3c24xx_serial_init_port: enabling flow control\n");
+ port->flags |= UPF_CONS_FLOW;
+ }
+
+ /* sort our the physical and virtual addresses for each UART */
+
+ res = platform_get_resource(platdev, IORESOURCE_MEM, 0);
+ if (res == NULL) {
+ printk(KERN_ERR "failed to find memory resource for uart\n");
+ return -EINVAL;
+ }
+
+ dbg("resource %p (%lx..%lx)\n", res, res->start, res->end);
+
+ port->mapbase = res->start;
+ port->membase = (void __iomem *)(res->start - S3C24A0_PA_UART);
+ port->membase += S3C24A0_VA_UART;
+ port->irq = platform_get_irq(platdev, 0);
+
+ ourport->clk = clk_get(&platdev->dev, "uart");
+
+ dbg("port: map=%08x, mem=%08x, irq=%d, clock=%ld\n",
+ port->mapbase, port->membase, port->irq, port->uartclk);
+
+ /* reset the fifos (and setup the uart) */
+ s3c24xx_serial_resetport(port, cfg);
+ return 0;
+}
+
+/* Device driver serial port probe */
+
+static int probe_index = 0;
+
+int s3c24xx_serial_probe(struct device *_dev,
+ struct s3c24xx_uart_info *info)
+{
+ struct s3c24xx_uart_port *ourport;
+ struct platform_device *dev = to_platform_device(_dev);
+ int ret;
+
+ dbg("s3c24xx_serial_probe(%p, %p) %d\n", _dev, info, probe_index);
+
+ ourport = &s3c24xx_serial_ports[probe_index];
+ probe_index++;
+
+ dbg("%s: initialising port %p...\n", __FUNCTION__, ourport);
+
+ ret = s3c24xx_serial_init_port(ourport, info, dev);
+ if (ret < 0)
+ goto probe_err;
+
+ dbg("%s: adding port\n", __FUNCTION__);
+ uart_add_one_port(&s3c24xx_uart_drv, &ourport->port);
+ dev_set_drvdata(_dev, &ourport->port);
+
+ return 0;
+
+ probe_err:
+ return ret;
+}
+
+int s3c24xx_serial_remove(struct device *_dev)
+{
+ struct uart_port *port = s3c24xx_dev_to_port(_dev);
+
+ if (port)
+ uart_remove_one_port(&s3c24xx_uart_drv, port);
+
+ return 0;
+}
+
+/* UART power management code */
+
+#ifdef CONFIG_PM
+
+int s3c24xx_serial_suspend(struct device *dev, pm_message_t state)
+{
+ struct uart_port *port = s3c24xx_dev_to_port(dev);
+
+ if (port)
+ uart_suspend_port(&s3c24xx_uart_drv, port);
+
+ return 0;
+}
+
+int s3c24xx_serial_resume(struct device *dev)
+{
+ struct uart_port *port = s3c24xx_dev_to_port(dev);
+ struct s3c24xx_uart_port *ourport = to_ourport(port);
+
+ if (port) {
+ clk_enable(ourport->clk);
+ s3c24xx_serial_resetport(port, s3c24xx_port_to_cfg(port));
+ clk_disable(ourport->clk);
+
+ uart_resume_port(&s3c24xx_uart_drv, port);
+ }
+
+ return 0;
+}
+
+#else
+#define s3c24xx_serial_suspend NULL
+#define s3c24xx_serial_resume NULL
+#endif
+
+int s3c24xx_serial_init(struct device_driver *drv,
+ struct s3c24xx_uart_info *info)
+{
+ dbg("s3c24xx_serial_init(%p,%p)\n", drv, info);
+ return driver_register(drv);
+}
+
+
+/* now comes the code to initialise either the s3c24a0 serial
+ * port information
+*/
+
+/* cpu specific variations on the serial port support */
+
+#ifdef CONFIG_CPU_S3C24A0
+
+static int s3c24a0_serial_setsource(struct uart_port *port,
+ struct s3c24xx_uart_clksrc *clk)
+{
+ unsigned long ucon = rd_regl(port, S3C24A0_UCON);
+
+ if (strcmp(clk->name, "uclk") == 0)
+ ucon |= S3C24A0_UCON_UCLK;
+ else
+ ucon &= ~S3C24A0_UCON_UCLK;
+
+ wr_regl(port, S3C24A0_UCON, ucon);
+ return 0;
+}
+
+static int s3c24a0_serial_getsource(struct uart_port *port,
+ struct s3c24xx_uart_clksrc *clk)
+{
+ unsigned long ucon = rd_regl(port, S3C24A0_UCON);
+
+ clk->divisor = 1;
+ clk->name = (ucon & S3C24A0_UCON_UCLK) ? "uclk" : "pclk";
+
+ return 0;
+}
+
+static struct s3c24xx_uart_info s3c24a0_uart_inf = {
+ .name = "Samsung S3C24A0 UART",
+ .type = PORT_S3C24A0,
+ .fifosize = 16,
+ .rx_fifomask = S3C24A0_UFSTAT_RXMASK,
+ .rx_fifoshift = S3C24A0_UFSTAT_RXSHIFT,
+ .rx_fifofull = S3C24A0_UFSTAT_RXFULL,
+ .tx_fifofull = S3C24A0_UFSTAT_TXFULL,
+ .tx_fifomask = S3C24A0_UFSTAT_TXMASK,
+ .tx_fifoshift = S3C24A0_UFSTAT_TXSHIFT,
+ .get_clksrc = s3c24a0_serial_getsource,
+ .set_clksrc = s3c24a0_serial_setsource,
+};
+
+/* device management */
+
+static int s3c24a0_serial_probe(struct device *dev)
+{
+ return s3c24xx_serial_probe(dev, &s3c24a0_uart_inf);
+}
+
+static struct device_driver s3c24a0_serial_drv = {
+ .name = "s3c24a0-uart",
+ .bus = &platform_bus_type,
+ .probe = s3c24a0_serial_probe,
+ .remove = s3c24xx_serial_remove,
+ .suspend = s3c24xx_serial_suspend,
+ .resume = s3c24xx_serial_resume,
+};
+
+static inline int s3c24a0_serial_init(void)
+{
+ return s3c24xx_serial_init(&s3c24a0_serial_drv, &s3c24a0_uart_inf);
+}
+
+static inline void s3c24a0_serial_exit(void)
+{
+ driver_unregister(&s3c24a0_serial_drv);
+}
+
+#define s3c24a0_uart_inf_at &s3c24a0_uart_inf
+#endif /* CONFIG_CPU_S3C24A0 */
+
+/* module initialisation code */
+
+static int __init s3c24xx_serial_modinit(void)
+{
+ int ret;
+
+ ret = uart_register_driver(&s3c24xx_uart_drv);
+ if (ret < 0) {
+ printk(KERN_ERR "failed to register UART driver\n");
+ return -1;
+ }
+
+ s3c24a0_serial_init();
+
+ return 0;
+}
+
+static void __exit s3c24xx_serial_modexit(void)
+{
+ s3c24a0_serial_exit();
+
+ uart_unregister_driver(&s3c24xx_uart_drv);
+}
+
+
+module_init(s3c24xx_serial_modinit);
+module_exit(s3c24xx_serial_modexit);
+
+/* Console code */
+
+#ifdef CONFIG_SERIAL_S3C24A0_CONSOLE
+
+static struct uart_port *cons_uart;
+
+static int
+s3c24xx_serial_console_txrdy(struct uart_port *port, unsigned int ufcon)
+{
+ struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port);
+ unsigned long ufstat, utrstat;
+
+ if (ufcon & S3C24A0_UFCON_FIFOMODE) {
+ /* fifo mode - check ammount of data in fifo registers... */
+
+ ufstat = rd_regl(port, S3C24A0_UFSTAT);
+ return (ufstat & info->tx_fifofull) ? 0 : 1;
+ }
+
+ /* in non-fifo mode, we go and use the tx buffer empty */
+
+ utrstat = rd_regl(port, S3C24A0_UTRSTAT);
+ return (utrstat & S3C24A0_UTRSTAT_TXE) ? 1 : 0;
+}
+
+static void
+s3c24xx_serial_console_write(struct console *co, const char *s,
+ unsigned int count)
+{
+ int i;
+ unsigned int ufcon = rd_regl(cons_uart, S3C24A0_UFCON);
+
+ for (i = 0; i < count; i++) {
+ while (!s3c24xx_serial_console_txrdy(cons_uart, ufcon))
+ barrier();
+
+ wr_regb(cons_uart, S3C24A0_UTXH, s[i]);
+
+ if (s[i] == '\n') {
+ while (!s3c24xx_serial_console_txrdy(cons_uart, ufcon))
+ barrier();
+
+ wr_regb(cons_uart, S3C24A0_UTXH, '\r');
+ }
+ }
+}
+
+static void __init
+s3c24xx_serial_get_options(struct uart_port *port, int *baud,
+ int *parity, int *bits)
+{
+ struct s3c24xx_uart_clksrc clksrc;
+ struct clk *clk;
+ unsigned int ulcon;
+ unsigned int ucon;
+ unsigned int ubrdiv;
+ unsigned long rate;
+
+ ulcon = rd_regl(port, S3C24A0_ULCON);
+ ucon = rd_regl(port, S3C24A0_UCON);
+ ubrdiv = rd_regl(port, S3C24A0_UBRDIV);
+
+ dbg("s3c24xx_serial_get_options: port=%p\n"
+ "registers: ulcon=%08x, ucon=%08x, ubdriv=%08x\n",
+ port, ulcon, ucon, ubrdiv);
+
+ if ((ucon & 0xf) != 0) {
+ /* consider the serial port configured if the tx/rx mode set */
+
+ switch (ulcon & S3C24A0_LCON_CSMASK) {
+ case S3C24A0_LCON_CS5:
+ *bits = 5;
+ break;
+ case S3C24A0_LCON_CS6:
+ *bits = 6;
+ break;
+ case S3C24A0_LCON_CS7:
+ *bits = 7;
+ break;
+ default:
+ case S3C24A0_LCON_CS8:
+ *bits = 8;
+ break;
+ }
+
+ switch (ulcon & S3C24A0_LCON_PMASK) {
+ case S3C24A0_LCON_PEVEN:
+ *parity = 'e';
+ break;
+
+ case S3C24A0_LCON_PODD:
+ *parity = 'o';
+ break;
+
+ case S3C24A0_LCON_PNONE:
+ default:
+ *parity = 'n';
+ }
+
+ /* now calculate the baud rate */
+
+ s3c24xx_serial_getsource(port, &clksrc);
+
+ clk = clk_get(port->dev, clksrc.name);
+ if (!IS_ERR(clk) && clk != NULL)
+ rate = clk_get_rate(clk);
+ else
+ rate = 1;
+
+
+ *baud = rate / ( 16 * (ubrdiv + 1));
+ dbg("calculated baud %d\n", *baud);
+ }
+
+}
+
+/* s3c24xx_serial_init_ports
+ *
+ * initialise the serial ports from the machine provided initialisation
+ * data.
+*/
+
+static int s3c24xx_serial_init_ports(struct s3c24xx_uart_info *info)
+{
+ struct s3c24xx_uart_port *ptr = s3c24xx_serial_ports;
+ struct platform_device **platdev_ptr;
+ int i;
+
+ dbg("s3c24xx_serial_init_ports: initialising ports...\n");
+
+ platdev_ptr = s3c24xx_uart_devs;
+
+ for (i = 0; i < NR_PORTS; i++, ptr++, platdev_ptr++) {
+ s3c24xx_serial_init_port(ptr, info, *platdev_ptr);
+ }
+
+ return 0;
+}
+
+static int __init
+s3c24xx_serial_console_setup(struct console *co, char *options)
+{
+ struct uart_port *port;
+ int baud = 9600;
+ int bits = 8;
+ int parity = 'n';
+ int flow = 'n';
+
+ dbg("s3c24xx_serial_console_setup: co=%p (%d), %s\n",
+ co, co->index, options);
+
+ /* is this a valid port */
+
+ if (co->index == -1 || co->index >= NR_PORTS)
+ co->index = 0;
+
+ port = &s3c24xx_serial_ports[co->index].port;
+
+ /* is the port configured? */
+
+ if (port->mapbase == 0x0) {
+ co->index = 0;
+ port = &s3c24xx_serial_ports[co->index].port;
+ }
+
+ cons_uart = port;
+
+ dbg("s3c24xx_serial_console_setup: port=%p (%d)\n", port, co->index);
+
+ /*
+ * Check whether an invalid uart number has been specified, and
+ * if so, search for the first available port that does have
+ * console support.
+ */
+ if (options)
+ uart_parse_options(options, &baud, &parity, &bits, &flow);
+ else
+ s3c24xx_serial_get_options(port, &baud, &parity, &bits);
+
+ dbg("s3c24xx_serial_console_setup: baud %d\n", baud);
+
+ return uart_set_options(port, co, baud, parity, bits, flow);
+}
+
+/* s3c24xx_serial_initconsole
+ *
+ * initialise the console from one of the uart drivers
+*/
+
+static struct console s3c24xx_serial_console =
+{
+ .name = S3C24XX_SERIAL_NAME,
+ .device = uart_console_device,
+ .flags = CON_PRINTBUFFER,
+ .index = -1,
+ .write = s3c24xx_serial_console_write,
+ .setup = s3c24xx_serial_console_setup
+};
+
+#define S3C24A0_UART1_IS_USED_AS_UART
+
+static int s3c24xx_serial_initconsole(void)
+{
+ struct s3c24xx_uart_info *info;
+ struct platform_device *dev = s3c24xx_uart_devs[0];
+
+ dbg("s3c24xx_serial_initconsole\n");
+
+ /* select driver based on the cpu */
+
+ if (dev == NULL) {
+ printk(KERN_ERR "s3c24xx: no devices for console init\n");
+ return 0;
+ }
+
+ if (strcmp(dev->name, "s3c24a0-uart") == 0) {
+ info = s3c24a0_uart_inf_at;
+ } else {
+ printk(KERN_ERR "s3c24xx: no driver for %s\n", dev->name);
+ return 0;
+ }
+
+ if (info == NULL) {
+ printk(KERN_ERR "s3c24xx: no driver for console\n");
+ return 0;
+ }
+
+#ifdef S3C24A0_UART1_IS_USED_AS_UART
+ {
+ unsigned int val;
+ val = readl(S3C24A0_GPCONU);
+ val |= (GPIO_MODE_uRXD1 | GPIO_MODE_uTXD1);
+ writel(val, S3C24A0_GPCONU);
+ }
+#endif
+
+ s3c24xx_serial_console.data = &s3c24xx_uart_drv;
+ s3c24xx_serial_init_ports(info);
+
+ register_console(&s3c24xx_serial_console);
+ return 0;
+}
+
+console_initcall(s3c24xx_serial_initconsole);
+
+#endif /* CONFIG_SERIAL_S3C24A0_CONSOLE */
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Ben Dooks ");
+MODULE_DESCRIPTION("Samsung S3C24A0 Serial port driver");
Really, this should be in the s3c2410 serial driver with all the
other SoCs, more redundant code
diff --git a/include/asm-arm/arch-s3c24a0/bitfield.h b/include/asm-arm/arch-s3c24a0/bitfield.h
new file mode 100644
index 0000000..bea83b7
--- /dev/null
+++ b/include/asm-arm/arch-s3c24a0/bitfield.h
@@ -0,0 +1,116 @@
+/*
+ * FILE bitfield.h
+ *
+ * Version 1.1
+ * Author Copyright (c) Marc A. Viredaz, 1998
+ * DEC Western Research Laboratory, Palo Alto, CA
+ * Date April 1998 (April 1997)
+ * System Advanced RISC Machine (ARM)
+ * Language C or ARM Assembly
+ * Purpose Definition of macros to operate on bit fields.
+ */
+
+
+
+#ifndef __BITFIELD_H
+#define __BITFIELD_H
+
+#ifndef __ASSEMBLY__
+#define UData(Data) ((unsigned long) (Data))
+#else
+#define UData(Data) (Data)
+#endif
+
+
+/*
+ * MACRO: Fld
+ *
+ * Purpose
+ * The macro "Fld" encodes a bit field, given its size and its shift value
+ * with respect to bit 0.
+ *
+ * Note
+ * A more intuitive way to encode bit fields would have been to use their
+ * mask. However, extracting size and shift value information from a bit
+ * field's mask is cumbersome and might break the assembler (255-character
+ * line-size limit).
+ *
+ * Input
+ * Size Size of the bit field, in number of bits.
+ * Shft Shift value of the bit field with respect to bit 0.
+ *
+ * Output
+ * Fld Encoded bit field.
+ */
+
+#define Fld(Size, Shft) (((Size) << 16) + (Shft))
+
+
+/*
+ * MACROS: FSize, FShft, FMsk, FAlnMsk, F1stBit
+ *
+ * Purpose
+ * The macros "FSize", "FShft", "FMsk", "FAlnMsk", and "F1stBit" return
+ * the size, shift value, mask, aligned mask, and first bit of a
+ * bit field.
+ *
+ * Input
+ * Field Encoded bit field (using the macro "Fld").
+ *
+ * Output
+ * FSize Size of the bit field, in number of bits.
+ * FShft Shift value of the bit field with respect to bit 0.
+ * FMsk Mask for the bit field.
+ * FAlnMsk Mask for the bit field, aligned on bit 0.
+ * F1stBit First bit of the bit field.
+ */
+
+#define FSize(Field) ((Field) >> 16)
+#define FShft(Field) ((Field) & 0x0000FFFF)
+#define FMsk(Field) (((UData (1) << FSize (Field)) - 1) << FShft (Field))
+#define FAlnMsk(Field) ((UData (1) << FSize (Field)) - 1)
+#define F1stBit(Field) (UData (1) << FShft (Field))
+
+#define FClrBit(Data, Bit) (Data = (Data & ~(Bit)))
+#define FClrFld(Data, Field) (Data = (Data & ~FMsk(Field)))
+
+
+/*
+ * MACRO: FInsrt
+ *
+ * Purpose
+ * The macro "FInsrt" inserts a value into a bit field by shifting the
+ * former appropriately.
+ *
+ * Input
+ * Value Bit-field value.
+ * Field Encoded bit field (using the macro "Fld").
+ *
+ * Output
+ * FInsrt Bit-field value positioned appropriately.
+ */
+
+#define FInsrt(Value, Field) \
+ (UData (Value) << FShft (Field))
+
+
+/*
+ * MACRO: FExtr
+ *
+ * Purpose
+ * The macro "FExtr" extracts the value of a bit field by masking and
+ * shifting it appropriately.
+ *
+ * Input
+ * Data Data containing the bit-field to be extracted.
+ * Field Encoded bit field (using the macro "Fld").
+ *
+ * Output
+ * FExtr Bit-field value.
+ */
+
+#define FExtr(Data, Field) \
+ ((UData (Data) >> FShft (Field)) & FAlnMsk (Field))
+
+
+#endif /* __BITFIELD_H */
Why have this?
diff --git a/include/asm-arm/arch-s3c24a0/debug-macro.S b/include/asm-arm/arch-s3c24a0/debug-macro.S
new file mode 100644
index 0000000..bc434a2
--- /dev/null
+++ b/include/asm-arm/arch-s3c24a0/debug-macro.S
@@ -0,0 +1,42 @@
+/* linux/include/asm-arm/arch-s3c2410/debug-macro.S
+ *
+ * Debugging macro include header
+ *
+ * Copyright (C) 1994-1999 Russell King
+ * Copyright (C) 2005 Simtec Electronics
+ *
+ * Moved from linux/arch/arm/kernel/debug.S by Ben Dooks
+ *
+ * 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.
+ *
+ * Modifications :
+ * *for s3c24a0 - Amitb
+*/
+
+#include
+#include
+#include
+
+.macro addruart,rx
+ mrc p15, 0, \rx, c1, c0
+ tst \rx, #1 @ MMU enabled ?
+ moveq \rx, #0x44000000 @ physical base address
+ movne \rx, #0xe4000000 @ virtual address
+ orr \rx, \rx, #0x00400000
+.endm
+
+.macro senduart,rd,rx
+ str \rd, [\rx, #0x20] @ UTXH
+.endm
+
+.macro waituart,rd,rx
+.endm
+
+.macro busyuart,rd,rx
+1001: ldr \rd, [\rx, #0x10] @ read UTRSTAT
+ tst \rd, #1 << 2 @ TX_EMPTY ?
+ beq 1001b
+.endm
+
diff --git a/include/asm-arm/arch-s3c24a0/dma.h b/include/asm-arm/arch-s3c24a0/dma.h
new file mode 100644
index 0000000..3a67671
--- /dev/null
+++ b/include/asm-arm/arch-s3c24a0/dma.h
@@ -0,0 +1,372 @@
+/* linux/include/asm-arm/arch-s3c24a0/dma.h
+ *
+ * Samsung S3C24A0A DMA support
+ *
+ * $Id: dma.h,v 1.1.1.1 2006/02/13 05:23:03 ihlee215 Exp $
+ *
+ * Copyright (C) 2005, Sean Choi
+ * All rights reserved.
+ *
+ * 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.
+ *
+ * derived from linux/include/asm-arm/arch-s3c2410/dma.h, written by
+ * Ben Dooks
+ *
+ */
+
+#ifndef __ASM_ARCH_DMA_H
+#define __ASM_ARCH_DMA_H __FILE__
+
+#include
+#include "hardware.h"
+
+
+/*
+ * This is the maximum DMA address(physical address) that can be DMAd to.
+ *
+ */
+#define MAX_DMA_ADDRESS 0xFFFFFFFF
+#define MAX_DMA_TRANSFER_SIZE 0x100000 /* Data Unit is half word */
+
+
+/* according to the samsung port, we cannot use the regular
+ * dma channels... we must therefore provide our own interface
+ * for DMA, and allow our drivers to use that.
+ */
+
+#define MAX_DMA_CHANNELS 0
+
+
+/* we have 4 dma channels */
+#define S3C24A0_DMA_CHANNELS (4)
+
+/* types */
+
+typedef enum {
+ S3C24A0_DMA_IDLE,
+ S3C24A0_DMA_RUNNING,
+ S3C24A0_DMA_PAUSED
+} s3c24a0_dma_state_t;
+
+
+/* s3c24a0_dma_loadst_t
+ *
+ * This represents the state of the DMA engine, wrt to the loaded / running
+ * transfers. Since we don't have any way of knowing exactly the state of
+ * the DMA transfers, we need to know the state to make decisions on wether
+ * we can
+ *
+ * S3C24A0_DMA_NONE
+ *
+ * There are no buffers loaded (the channel should be inactive)
+ *
+ * S3C24A0_DMA_1LOADED
+ *
+ * There is one buffer loaded, however it has not been confirmed to be
+ * loaded by the DMA engine. This may be because the channel is not
+ * yet running, or the DMA driver decided that it was too costly to
+ * sit and wait for it to happen.
+ *
+ * S3C24A0_DMA_1RUNNING
+ *
+ * The buffer has been confirmed running, and not finisged
+ *
+ * S3C24A0_DMA_1LOADED_1RUNNING
+ *
+ * There is a buffer waiting to be loaded by the DMA engine, and one
+ * currently running.
+*/
+
+typedef enum {
+ S3C24A0_DMALOAD_NONE,
+ S3C24A0_DMALOAD_1LOADED,
+ S3C24A0_DMALOAD_1RUNNING,
+ S3C24A0_DMALOAD_1LOADED_1RUNNING,
+} s3c24a0_dma_loadst_t;
+
+typedef enum {
+ S3C24A0_RES_OK,
+ S3C24A0_RES_ERR,
+ S3C24A0_RES_ABORT
+} s3c24a0_dma_buffresult_t;
+
+
+typedef enum s3c24a0_dmasrc_e s3c24a0_dmasrc_t;
+
+enum s3c24a0_dmasrc_e {
+ S3C24A0_DMASRC_HW, /* source is memory */
+ S3C24A0_DMASRC_MEM /* source is hardware */
+};
+
+/* enum s3c24a0_chan_op_e
+ *
+ * operation codes passed to the DMA code by the user, and also used
+ * to inform the current channel owner of any changes to the system state
+*/
+
+enum s3c24a0_chan_op_e {
+ S3C24A0_DMAOP_START,
+ S3C24A0_DMAOP_STOP,
+ S3C24A0_DMAOP_PAUSE,
+ S3C24A0_DMAOP_RESUME,
+ S3C24A0_DMAOP_FLUSH,
+ S3C24A0_DMAOP_TIMEOUT, /* internal signal to handler */
+};
+
+typedef enum s3c24a0_chan_op_e s3c24a0_chan_op_t;
+
+/* flags */
+
+#define S3C24A0_DMAF_SLOW (1<<0) /* slow, so don't worry about
+ * waiting for reloads */
+#define S3C24A0_DMAF_AUTOSTART (1<<1) /* auto-start if buffer queued */
+
+/* dma buffer */
+
+typedef struct s3c24a0_dma_buf_s s3c24a0_dma_buf_t;
+
+struct s3c24a0_dma_client {
+ char *name;
+};
+
+typedef struct s3c24a0_dma_client s3c24a0_dma_client_t;
+
+/* s3c24a0_dma_buf_s
+ *
+ * internally used buffer structure to describe a queued or running
+ * buffer.
+*/
+
+struct s3c24a0_dma_buf_s {
+ s3c24a0_dma_buf_t *next;
+ int magic; /* magic */
+ int size; /* buffer size in bytes */
+ dma_addr_t data; /* start of DMA data */
+ dma_addr_t ptr; /* where the DMA got to [1] */
+ void *id; /* client's id */
+};
+
+/* [1] is this updated for both recv/send modes? */
+
+typedef struct s3c24a0_dma_chan_s s3c24a0_dma_chan_t;
+
+/* s3c24a0_dma_cbfn_t
+ *
+ * buffer callback routine type
+*/
+
+typedef void (*s3c24a0_dma_cbfn_t)(s3c24a0_dma_chan_t *, void *buf, int size,
+ s3c24a0_dma_buffresult_t result);
+
+typedef int (*s3c24a0_dma_opfn_t)(s3c24a0_dma_chan_t *,
+ s3c24a0_chan_op_t );
+
+struct s3c24a0_dma_stats_s {
+ unsigned long loads;
+ unsigned long timeout_longest;
+ unsigned long timeout_shortest;
+ unsigned long timeout_avg;
+ unsigned long timeout_failed;
+};
+
+typedef struct s3c24a0_dma_stats_s s3c24a0_dma_stats_t;
+
+/* struct s3c24a0_dma_chan_s
+ *
+ * full state information for each DMA channel
+*/
+
+struct s3c24a0_dma_chan_s {
+ /* channel state flags and information */
+ unsigned char number; /* number of this dma channel */
+ unsigned char in_use; /* channel allocated */
+ unsigned char irq_claimed; /* irq claimed for channel */
+ unsigned char irq_enabled; /* irq enabled for channel */
+ unsigned char xfer_unit; /* size of an transfer */
+
+ /* channel state */
+
+ s3c24a0_dma_state_t state;
+ s3c24a0_dma_loadst_t load_state;
+ s3c24a0_dma_client_t *client;
+
+ /* channel configuration */
+ s3c24a0_dmasrc_t source;
+ unsigned long dev_addr;
+ unsigned long load_timeout;
+ unsigned int flags; /* channel flags */
+
+ /* channel's hardware position and configuration */
+ void __iomem *regs; /* channels registers */
+ void __iomem *addr_reg; /* data address register */
+ unsigned int irq; /* channel irq */
+ unsigned long dcon; /* default value of DCON */
+
+ /* driver handles */
+ s3c24a0_dma_cbfn_t callback_fn; /* buffer done callback */
+ s3c24a0_dma_opfn_t op_fn; /* channel operation callback */
+
+ /* stats gathering */
+ s3c24a0_dma_stats_t *stats;
+ s3c24a0_dma_stats_t stats_store;
+
+ /* buffer list and information */
+ s3c24a0_dma_buf_t *curr; /* current dma buffer */
+ s3c24a0_dma_buf_t *next; /* next buffer to load */
+ s3c24a0_dma_buf_t *end; /* end of queue */
+
+ /* system device */
+ struct sys_device dev;
+};
+
+/* the currently allocated channel information */
+extern s3c24a0_dma_chan_t s3c24a0_chans[];
+
+/* note, we don't really use dma_device_t at the moment */
+typedef unsigned long dma_device_t;
+
+/* functions --------------------------------------------------------------- */
+
+/* s3c24a0_dma_request
+ *
+ * request a dma channel exclusivley
+*/
+
+extern int s3c24a0_dma_request(dmach_t channel,
+ s3c24a0_dma_client_t *, void *dev);
+
+
+/* s3c24a0_dma_ctrl
+ *
+ * change the state of the dma channel
+*/
+
+extern int s3c24a0_dma_ctrl(dmach_t channel, s3c24a0_chan_op_t op);
+
+/* s3c24a0_dma_setflags
+ *
+ * set the channel's flags to a given state
+*/
+
+extern int s3c24a0_dma_setflags(dmach_t channel,
+ unsigned int flags);
+
+/* s3c24a0_dma_free
+ *
+ * free the dma channel (will also abort any outstanding operations)
+*/
+
+extern int s3c24a0_dma_free(dmach_t channel, s3c24a0_dma_client_t *);
+
+/* s3c24a0_dma_enqueue
+ *
+ * place the given buffer onto the queue of operations for the channel.
+ * The buffer must be allocated from dma coherent memory, or the Dcache/WB
+ * drained before the buffer is given to the DMA system.
+*/
+
+extern int s3c24a0_dma_enqueue(dmach_t channel, void *id,
+ dma_addr_t data, int size);
+
+/* s3c24a0_dma_config
+ *
+ * configure the dma channel
+*/
+
+extern int s3c24a0_dma_config(dmach_t channel, int xferunit, int dcon);
+
+/* s3c24a0_dma_devconfig
+ *
+ * configure the device we're talking to
+*/
+
+extern int s3c24a0_dma_devconfig(int channel, s3c24a0_dmasrc_t source,
+ int hwcfg, unsigned long devaddr);
+
+extern int s3c24a0_dma_set_opfn(dmach_t, s3c24a0_dma_opfn_t rtn);
+extern int s3c24a0_dma_set_buffdone_fn(dmach_t, s3c24a0_dma_cbfn_t rtn);
+extern int s3c24a0_dma_getposition(dmach_t channel, dma_addr_t *src, dma_addr_t *dst);
+
+/* DMA Register definitions */
+
+#define S3C24A0_DMA_DISRC (0x00)
+#define S3C24A0_DMA_DISRCC (0x04)
+#define S3C24A0_DMA_DIDST (0x08)
+#define S3C24A0_DMA_DIDSTC (0x0C)
+#define S3C24A0_DMA_DCON (0x10)
+#define S3C24A0_DMA_DSTAT (0x14)
+#define S3C24A0_DMA_DCSRC (0x18)
+#define S3C24A0_DMA_DCDST (0x1C)
+#define S3C24A0_DMA_DMASKTRIG (0x20)
+
+#define S3C24A0_DISRCC_INC (1<<0)
+#define S3C24A0_DISRCC_APB (1<<1)
+
+#define S3C24A0_DMASKTRIG_STOP (1<<2)
+#define S3C24A0_DMASKTRIG_ON (1<<1)
+#define S3C24A0_DMASKTRIG_SWTRIG (1<<0)
+
+#define S3C24A0_DCON_DEMAND (0<<31)
+#define S3C24A0_DCON_HANDSHAKE (1<<31)
+#define S3C24A0_DCON_SYNC_PCLK (0<<30)
+#define S3C24A0_DCON_SYNC_HCLK (1<<30)
+
+#define S3C24A0_DCON_INTREQ (1<<29)
+
+#define S3C24A0_DCON_CH0_XDREQ0 (0<<24)
+#define S3C24A0_DCON_CH0_UART0 (1<<24)
+#define S3C24A0_DCON_CH0_I2SSDI (2<<24)
+#define S3C24A0_DCON_CH0_TIMER (3<<24)
+#define S3C24A0_DCON_CH0_USBEP1 (4<<24)
+#define S3C24A0_DCON_CH0_PCMOUT (5<<24)
+#define S3C24A0_DCON_CH0_MSTICK (6<<24)
+#define S3C24A0_DCON_CH0_IRDA (7<<24)
+
+#define S3C24A0_DCON_CH1_XDREQ1 (0<<24)
+#define S3C24A0_DCON_CH1_UART1 (1<<24)
+#define S3C24A0_DCON_CH1_I2SSDI (2<<24)
+#define S3C24A0_DCON_CH1_SPI (3<<24)
+#define S3C24A0_DCON_CH1_USBEP2 (4<<24)
+#define S3C24A0_DCON_CH1_PCMIN (5<<24)
+#define S3C24A0_DCON_CH1_PCMOUT (6<<24)
+#define S3C24A0_DCON_CH1_IRDA (7<<24)
+
+#define S3C24A0_DCON_CH2_I2SSDO (0<<24)
+#define S3C24A0_DCON_CH2_I2SSDI (1<<24)
+#define S3C24A0_DCON_CH2_SDI (2<<24)
+#define S3C24A0_DCON_CH2_TIMER (3<<24)
+#define S3C24A0_DCON_CH2_USBEP3 (4<<24)
+#define S3C24A0_DCON_CH2_MICIN (5<<24)
+#define S3C24A0_DCON_CH2_PCMIN (6<<24)
+/* channel 2 --> source7 is reserved */
+
+#define S3C24A0_DCON_CH3_UART2 (0<<24)
+#define S3C24A0_DCON_CH3_SDI (1<<24)
+#define S3C24A0_DCON_CH3_SPI (2<<24)
+#define S3C24A0_DCON_CH3_TIMER (3<<24)
+#define S3C24A0_DCON_CH3_USBEP4 (4<<24)
+#define S3C24A0_DCON_CH3_MSTICK (5<<24)
+#define S3C24A0_DCON_CH3_MICIN (6<<24)
+/* channel 3 --> source7 is reserved */
+
+#define S3C24A0_DCON_SRCMASK (7<<24)
+
+#define S3C24A0_DCON_HWTRIG (1<<23)
+#define S3C24A0_DCON_AUTORELOAD (0<<22)
+#define S3C24A0_DCON_NORELOAD (1<<22)
+
+#define S3C24A0_DCON_BYTE (0<<20)
+#define S3C24A0_DCON_HALFWORD (1<<20)
+#define S3C24A0_DCON_WORD (2<<20)
+
+#define S3C24A0_DCON_SRCSHIFT (24)
+
+#endif /* __ASM_ARCH_DMA_H */
diff --git a/include/asm-arm/arch-s3c24a0/entry-macro.S b/include/asm-arm/arch-s3c24a0/entry-macro.S
new file mode 100644
index 0000000..695eaa7
--- /dev/null
+++ b/include/asm-arm/arch-s3c24a0/entry-macro.S
@@ -0,0 +1,142 @@
+/*
+ * include/asm-arm/arch-s3c2410/entry-macro.S
+ *
+ * Low-level IRQ helper macros for S3C24A0-based platforms
+ *
+ * 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.
+*/
+
+/* Derived from samsung linux-2.6.10 tree */
+
+#include
+#include
+
+
+ .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
+
+30000:
+ ldr \tmp, =S3C24A0_VA_IRQ
+ ldr \irqnr, [ \tmp, #0x14 ] @ get irq no from INTOFFSET
+ cmp \irqnr,#5 @ in case of external interrupt
+ bcc 1002f
+ teq \irqnr, #14 @ LCD interrupt
+ beq 1003f
+
+ @ debug check to see if interrupt reported is the same
+ @ as the offset....
+
+ ldr \irqstat, [ \tmp, #0x10 ] @ INTPND
+ mov \irqstat, \irqstat, lsr \irqnr
+ tst \irqstat, #1
+ bne 20002f
+
+#if 1
+ stmfd r13!, { r0 - r4 , r14 }
+ ldr r1, [ \tmp, #0x14 ] @ intoffset
+ ldr r2, [ \tmp, #0x10 ] @ INTPND
+ ldr r3, [ \tmp, #0x00 ] @ SRCPND
+ adr r0, 20003f
+ bl printk
+ b 20004f
+#endif
+
+20003:
+ .ascii "<7>irq: err - bad offset %d, intpnd=%08x, srcpnd=%08x\n"
+ .byte 0
+ .align 4
+20004:
+ mov r1, #1
+ ldr \tmp, =S3C24A0_VA_IRQ
+ ldmfd r13!, { r0 - r4 , r14 }
+
+ @ try working out interript number for ourselves
+ mov \irqnr, #0
+ ldr \irqstat, [ \tmp, #0x10 ] @ INTPND
+
+10021:
+ movs \irqstat, \irqstat, lsr#1
+ bcs 30000b @ try and re-start the proccess
+ add \irqnr, \irqnr, #1
+ cmp \irqnr, #32
+ ble 10021b
+
+ @ found no interrupt, set Z flag and leave
+ movs \irqnr, #0
+ b 1001f
+
+20005:
+20002: @ exit
+ @ we base the s3c2410x interrupts at 16 and above to allow
+ @ isa peripherals to have their standard interrupts, also
+ @ ensure that Z flag is un-set on exit
+
+ @ note, we cannot be sure if we get IRQ_EINT0 (0) that
+ @ there is simply no interrupt pending, so in all other
+ @ cases we jump to say we have found something, otherwise
+ @ we check to see if the interrupt really is assrted
+ adds \irqnr, \irqnr, #IRQ_EINT0_2
+ teq \irqnr, #IRQ_EINT0_2
+ bne 1001f @ exit
+ ldr \irqstat, [ \tmp, #0x10 ] @ INTPND
+ teq \irqstat, #0
+ beq 20021f
+ b 10023f
+20021:
+ mov \irqnr, #0
+ b 1001f
+
+ @ we get here from no main or external interrupts pending
+1002:
+ teq \irqnr,#0
+ beq 20002b
+10023:
+ ldr \tmp, =S3C24A0_VA_GPIO
+ ldr \irqstat, [ \tmp, # 0x38 ] @ EXTINTPEND
+ ldr \irqnr, [ \tmp, # 0x34 ] @ EXTINTMASK
+
+ bic \irqstat, \irqstat, \irqnr @ clear masked irqs
+
+ mov \irqnr, #IRQ_EINT0 @ start extint nos
+10021:
+ movs \irqstat, \irqstat, lsr#1
+ bcs 1004f
+ add \irqnr, \irqnr, #1
+ cmp \irqnr, #IRQ_EINT18
+ ble 10021b
+
+ @ found no interrupt, set Z flag and leave
+ movs \irqnr, #0
+ b 1001f
+
+
+ @ we check to see if the interrupt really is assrted
+ adds \irqnr, \irqnr, #IRQ_EINT0_2
+
+
+
+1003:
+ @ lcd interrupt has been asserted...
+ ldr \irqstat, [ \tmp, # 0x18 ] @ load SUBPND register
+
+ and \irqstat,\irqstat,#(1<<20)|(1<<16)|(1<<15) @ mask for LCD interrupt
+ tst \irqstat, #0x100000 @ DISP FRAME interrupt
+ movne \irqnr, #IRQ_DISP_FRAME
+ tst \irqstat, #0x10000 @ DISP FIFO interrupt
+ movne \irqnr, #IRQ_DISP_FIFO
+ tst \irqstat, #0x8000 @ POST interrupt
+ movne \irqnr, #IRQ_POST
+
+1004: @ ensure Z flag clear in case our MOVS shifted out the last bit
+ teq \irqnr, #0
+1001:
+ @ exit irq routine
+ .endm
+
+
+ /* currently don't need an disable_fiq macro */
+
+ .macro disable_fiq
+ .endm
+
Firstly, copy a more up to date copy of this and secondly, it is
best not to decode the sub-interrupts in this code
diff --git a/include/asm-arm/arch-s3c24a0/fb.h b/include/asm-arm/arch-s3c24a0/fb.h
new file mode 100644
index 0000000..ae800eb
--- /dev/null
+++ b/include/asm-arm/arch-s3c24a0/fb.h
@@ -0,0 +1,96 @@
+
+#ifndef __ASM_ARM_FB_H
+#define __ASM_ARM_FB_H
+
+#include
+
+
+#ifdef CONFIG_MACH_EVT3_SMDK24A0
+#define H_FP 5 /* front porch */
+#define H_SW 2 /* Hsync width */
+#define H_BP 0 /* Back porch */
+
+#define V_FP 9 /* front porch */
+#define V_SW 2 /* Vsync width */
+#define V_BP 8 /* Back porch */
if these are machine dependant, then pass them in via platform
data.
+
+#define H_RESOLUTION 240 /* horizon pixel x resolition */
+#define V_RESOLUTION 320 /* line cnt y resolution */
+#define VFRAME_FREQ 60 /* frame rate freq */
+#else
+#define H_FP 2 /* front porch */
+#define H_SW 3 /* Hsync width */
+#define H_BP 6 /* Back porch */
+
+#define V_FP 2 /* front porch */
+#define V_SW 1 /* Vsync width */
+#define V_BP 1 /* Back porch */
+
+#define H_RESOLUTION 240 /* horizon pixel x resolition */
+#define V_RESOLUTION 320 /* line cnt y resolution */
+#define VFRAME_FREQ 70 /* frame rate freq */
+#endif
+
+#define PIXEL_CLOCK VFRAME_FREQ * LCD_PIXEL_CLOCK /* vclk = frame * pixel_count */
+#define PIXEL_BPP 16 /* RGB 5-6-5 format for SMDK24A0 EVAL BOARD */
+
+#define LCD_PIXEL_CLOCK (VFRAME_FREQ *(H_FP+H_SW+H_BP+H_RESOLUTION) * (V_FP+V_SW+V_BP+V_RESOLUTION))
+
+#define MAX_DISPLAY_BRIGHTNESS 100
+#define DEF_DISPLAY_BRIGHTNESS 50
+
+
+
+struct s3c24a0fb_mach_info {
+
+ /* Screen size */
+ int width;
+ int height;
+
+ /* Screen info */
+ int xres;
+ int yres;
+ int bpp;
+
+ unsigned long pixclock;
+
+ int hsync_len;
+ int left_margin;
+ int right_margin;
+ int vsync_len;
+ int upper_margin;
+ int lower_margin;
+ int sync;
+ int cmap_grayscale:1, cmap_inverse:1, cmap_static:1, unused:29;
signed 1-bit bitfields? looks like a lack of tabbing too
+ /* lcd configuration registers */
+ unsigned long lcdcon1;
+ unsigned long lcdcon2;
+ unsigned long lcdtcon1;
+ unsigned long lcdtcon2;
+ unsigned long lcdtcon3;
+ unsigned long lcdosd1;
+ unsigned long lcdosd2;
+ unsigned long lcdosd3;
+ unsigned long lcdsaddrb1;
+ unsigned long lcdsaddrb2;
+ unsigned long lcdsaddrf1;
+ unsigned long lcdsaddrf2;
+ unsigned long lcdeaddrb1;
+ unsigned long lcdeaddrb2;
+ unsigned long lcdeaddrf1;
+ unsigned long lcdeaddrf2;
+ unsigned long lcdvscrb1;
+ unsigned long lcdvscrb2;
+ unsigned long lcdvscrf1;
+ unsigned long lcdvscrf2;
+ unsigned long lcdintcon;
+ unsigned long lcdkeycon;
+ unsigned long lcdkeyval;
+ unsigned long lcdbgcon;
+ unsigned long lcdfgcon;
+ unsigned long lcddithcon;
+
+};
+
+#endif /* __ASM_ARM_FB_H */
diff --git a/include/asm-arm/arch-s3c24a0/hardware.h b/include/asm-arm/arch-s3c24a0/hardware.h
new file mode 100644
index 0000000..09343b3
--- /dev/null
+++ b/include/asm-arm/arch-s3c24a0/hardware.h
@@ -0,0 +1,146 @@
+/* linux/include/asm-arm/arch-s3c24a0/hardware.h
+ *
+ * S3C24A0 - hardware
+ *
+ * $Id: hardware.h,v 1.1.1.1 2006/02/13 05:23:03 ihlee215 Exp $
+ *
+ * Copyright (C) 2005, Sean Choi
+ * All rights reserved.
+ *
+ * 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.
+ *
+ * derived from linux/include/asm-arm/arch-s3c2410/hardware.h, written by
+ * Ben Dooks
+ *
+*/
+
+#ifndef __ASM_ARCH_HARDWARE_H
+#define __ASM_ARCH_HARDWARE_H
+
+#include "io.h"
+
+/* FIXME : amitb : remove this completely
+#define PCIO_BASE 0
+*/
+
+/*
+ * S3C24A0 internal I/O mappings
+ *
+ * We have the following mapping:
+ * phys virt
+ * 40000000 e0000000
+ */
+
+#define VIO_BASE 0xe0000000 /* virtual start of IO space */
+#define PIO_START 0x40000000 /* physical start of IO space */
+
+#define io_p2v(x) ((x) | 0xa0000000)
+#define io_v2p(x) ((x) & ~0xa0000000)
+
+
+
+#ifndef __ASSEMBLY__
+#include
+
+/*
+ * This __REG() version gives the same results as the one above, except
+ * that we are fooling gcc some how so it generates far better and smaller
+ * assembly code for access to contigous registers. It's a shame that gcc
+ * doesn't guess this by itself
+ */
+typedef struct {
+ volatile u32 offset[4096];
+} __regbase;
+#define __REGP(x) ((__regbase *)((x)&~4095))->offset[((x)&4095)>>2]
+#define __REG(x) __REGP(io_p2v(x))
+
+/* Let's kick gcc's ass again... */
+# define __REG2(x,y) \
+ ( __builtin_constant_p(y) ? (__REG((x) + (y))) \
+ : (*(volatile u32 *)((u32)&__REG(x) + (y))) )
+
+#define __PREG(x) (io_v2p((u32)&(x)))
NO, NO and NO!
+
+
+/* external functions for GPIO support
+ *
+ * These allow various different clients to access the same GPIO
+ * registers without conflicting. If your driver only owns the entire
+ * GPIO register, then it is safe to ioremap/__raw_{read|write} to it.
+*/
+
+/* s3c24a0_gpio_cfgpin
+ *
+ * set the configuration of the given pin to the value passed.
+ *
+ * eg:
+ * s3c24a0_gpio_cfgpin(S3C24A0_GPA0, S3C24A0_GPA0_ADDR0);
+ * s3c24a0_gpio_cfgpin(S3C24A0_GPE8, S3C24A0_GPE8_SDDAT1);
+*/
+
+extern void s3c24a0_gpio_cfgpin(unsigned int pin, unsigned int function);
+
+extern unsigned int s3c24a0_gpio_getcfg(unsigned int pin);
+
+/* s3c24a0_gpio_getirq
+ *
+ * turn the given pin number into the corresponding IRQ number
+ *
+ * returns:
+ * < 0 = no interrupt for this pin
+ * >=0 = interrupt number for the pin
+*/
+
+extern int s3c24a0_gpio_getirq(unsigned int pin);
+
+/* s3c24a0_gpio_irqfilter
+ *
+ * set the irq filtering on the given pin
+ *
+ * on = 0 => disable filtering
+ * 1 => enable filtering
+ *
+ * config = S3C24A0_EINTFLT_PCLK or S3C24A0_EINTFLT_EXTCLK orred with
+ * width of filter (0 through 63)
+ *
+ *
+*/
+
+extern int s3c24a0_gpio_irqfilter(unsigned int pin, unsigned int on,
+ unsigned int config);
+
+/* s3c24a0_gpio_pullup
+ *
+ * configure the pull-up control on the given pin
+ *
+ * to = 1 => disable the pull-up
+ * 0 => enable the pull-up
+ *
+ * eg;
+ *
+ * s3c24a0_gpio_pullup(S3C24A0_GPB0, 0);
+ * s3c24a0_gpio_pullup(S3C24A0_GPE8, 0);
+*/
+
+extern void s3c24a0_gpio_pullup(unsigned int pin, unsigned int to);
+
+extern void s3c24a0_gpio_setpin(unsigned int pin, unsigned int to);
+
+extern unsigned int s3c24a0_gpio_getpin(unsigned int pin);
+
+extern unsigned int s3c24a0_modify_misccr(unsigned int clr, unsigned int chg);
+
+#else /* __ASSEMBLY__ */
+
+# define __REG(x) io_p2v(x)
+# define __PREG(x) io_v2p(x)
+
+#endif /* __ASSEMBLY__ */
+
+#include
+#include
+
+#endif /* __ASM_ARCH_HARDWARE_H */
diff --git a/include/asm-arm/arch-s3c24a0/ide.h b/include/asm-arm/arch-s3c24a0/ide.h
new file mode 100644
index 0000000..af5d324
--- /dev/null
+++ b/include/asm-arm/arch-s3c24a0/ide.h
@@ -0,0 +1,51 @@
+/*
+ * include/asm-arm/arch-s3c24a0/ide.h
+ *
+ * $Id: ide.h,v 1.1.1.1 2006/02/13 05:23:03 ihlee215 Exp $
+ *
+ * Originally based upon linux/include/asm-arm/arch-sa1100/ide.h
+ *
+ */
+
+#include
+#include
+#include
+#include
+
+
+/*
+ * Set up a hw structure for a specified data port, control port and IRQ.
+ * This should follow whatever the default interface uses.
+ */
+static __inline__ void
+ide_init_hwif_ports(hw_regs_t * hw, int data_port, int ctrl_port, int *irq)
+{
+ ide_ioreg_t reg;
+
+ memset(hw, 0, sizeof(*hw));
+
+ reg = (ide_ioreg_t) data_port;
+
+ hw->io_ports[IDE_DATA_OFFSET] = reg + 0;
+ hw->io_ports[IDE_ERROR_OFFSET] = reg + 1;
+ hw->io_ports[IDE_NSECTOR_OFFSET] = reg + 2;
+ hw->io_ports[IDE_SECTOR_OFFSET] = reg + 3;
+ hw->io_ports[IDE_LCYL_OFFSET] = reg + 4;
+ hw->io_ports[IDE_HCYL_OFFSET] = reg + 5;
+ hw->io_ports[IDE_SELECT_OFFSET] = reg + 6;
+ hw->io_ports[IDE_STATUS_OFFSET] = reg + 7;
+
+ hw->io_ports[IDE_CONTROL_OFFSET] = (ide_ioreg_t) ctrl_port;
+
+ if (irq)
+ *irq = 0;
+}
+
+
+/*
+ * Register the standard ports for this architecture with the IDE driver.
+ */
+static __inline__ void ide_init_default_hwifs(void)
+{
+ /* Nothing to declare... */
+}
diff --git a/include/asm-arm/arch-s3c24a0/idle.h b/include/asm-arm/arch-s3c24a0/idle.h
new file mode 100644
index 0000000..bbfc5bd
--- /dev/null
+++ b/include/asm-arm/arch-s3c24a0/idle.h
@@ -0,0 +1,31 @@
+/* linux/include/asm-arm/arch-s3c24a0/idle.h
+ *
+ * S3C24A0 CPU Idle controls
+ *
+ * $Id: idle.h,v 1.1.1.1 2006/02/13 05:23:03 ihlee215 Exp $
+ *
+ * Copyright (C) 2005, Sean Choi
+ * All rights reserved.
+ *
+ * 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.
+ *
+ * derived from linux/include/asm-arm/arch-s3c2410/idle.h, written by
+ * Simtec Electronics
+ * http://www.simtec.co.uk/products/SWLINUX/
+ *
+ */
+
+#ifndef __ASM_ARCH_IDLE_H
+#define __ASM_ARCH_IDLE_H __FILE__
+
+/* This allows the over-ride of the default idle code, in case there
+ * is any other things to be done over idle (like DVS)
+*/
+
+extern void (*s3c24xx_idle)(void);
+
+extern void s3c24xx_default_idle(void);
+
+#endif /* __ASM_ARCH_IDLE_H */
Another copy of a shareable file
diff --git a/include/asm-arm/arch-s3c24a0/iic.h b/include/asm-arm/arch-s3c24a0/iic.h
new file mode 100644
index 0000000..0227653
--- /dev/null
+++ b/include/asm-arm/arch-s3c24a0/iic.h
@@ -0,0 +1,35 @@
+/* linux/include/asm-arm/arch-s3c24a0/iic.h
+ *
+ * S3C24A0 - I2C Controller platform_device info
+ *
+ * Copyright (C) 2005, Sean Choi
+ * All rights reserved.
+ *
+ * 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.
+ *
+ * derived from linux/include/asm-arm/arch-s3c24a0/hardware.h, written by
+ * Ben Dooks
+ */
+
+#ifndef __ASM_ARCH_IIC_H
+#define __ASM_ARCH_IIC_H __FILE__
+
+#define S3C_IICFLG_FILTER (1<<0) /* enable s3c24a0 filter */
+
+/* Notes:
+ * 1) All frequencies are expressed in Hz
+ * 2) A value of zero is `do not care`
+*/
+
+struct s3c24a0_platform_i2c {
+ unsigned int flags;
+ unsigned int slave_addr; /* slave address for controller */
+ unsigned long bus_freq; /* standard bus frequency */
+ unsigned long max_freq; /* max frequency for the bus */
+ unsigned long min_freq; /* min frequency for the bus */
+ unsigned int sda_delay; /* pclks (s3c2440 only) */
+};
+
+#endif /* __ASM_ARCH_IIC_H */
Why not use the s3c24xx driver?
diff --git a/include/asm-arm/arch-s3c24a0/io.h b/include/asm-arm/arch-s3c24a0/io.h
new file mode 100644
index 0000000..16e8344
--- /dev/null
+++ b/include/asm-arm/arch-s3c24a0/io.h
@@ -0,0 +1,32 @@
+/*
+ * linux/include/asm-arm/arch-s3c24a0/io.h
+ *
+ * $Id: io.h,v 1.1.1.1 2006/02/13 05:23:03 ihlee215 Exp $
+ *
+ * Copyright (C) 2005, Sean Choi
+ * All rights reserved.
+ *
+ * derived from linux/include/asm-arm/arch-rpc/io.h, written by
+ * Russell King 1997
+ *
+ */
+
+#ifndef __ASM_ARM_ARCH_IO_H
+#define __ASM_ARM_ARCH_IO_H
+
+#define IO_SPACE_LIMIT 0xffffffff
+
+#define PCIO_BASE 0
+
+/*
+ * We don't actually have real ISA nor PCI buses, but there is so many
+ * drivers out there that might just work if we fake them...
+ */
+#define __io(a) (PCIO_BASE + (a))
+#define __mem_pci(a) ((unsigned long)(a))
+#define __mem_isa(a) ((unsigned long)(a))
+
+#define iomem_valid_addr(iomem,sz) (1)
+#define iomem_to_phys(iomem) (iomem)
+
+#endif /* __ASM_ARM_ARCH_IO_H */
diff --git a/include/asm-arm/arch-s3c24a0/irqs.h b/include/asm-arm/arch-s3c24a0/irqs.h
new file mode 100644
index 0000000..e7abbcd
--- /dev/null
+++ b/include/asm-arm/arch-s3c24a0/irqs.h
@@ -0,0 +1,115 @@
+/* linux/include/asm-arm/arch-s3c24a0/irqs.h
+ *
+ * $Id: irqs.h,v 1.1.1.1 2006/02/13 05:23:03 ihlee215 Exp $
+ *
+ * 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.
+ *
+ */
+
+#ifndef __ASM_ARCH_IRQS_H
+#define __ASM_ARCH_IRQS_H __FILE__
+
+
+/* we keep the first set of CPU IRQs out of the range of
+ * the ISA space, so that the PC104 has them to itself
+ * and we don't end up having to do horrible things to the
+ * standard ISA drivers....
+ */
+
+#define S3C24A0_CPUIRQ_OFFSET (16)
+
+#define S3C24A0_IRQ(x) ((x) + S3C24A0_CPUIRQ_OFFSET)
+
+/* main cpu interrupts */
+#define IRQ_EINT0_2 S3C24A0_IRQ(0) /* 16 */
+#define IRQ_EINT3_6 S3C24A0_IRQ(1)
+#define IRQ_EINT7_10 S3C24A0_IRQ(2)
+#define IRQ_EINT11_14 S3C24A0_IRQ(3)
+#define IRQ_EINT15_18 S3C24A0_IRQ(4) /* 20 */
+#define IRQ_TICK S3C24A0_IRQ(5)
+#define IRQ_DCTQ S3C24A0_IRQ(6)
+#define IRQ_MC S3C24A0_IRQ(7)
+#define IRQ_ME S3C24A0_IRQ(8) /* 24 */
+#define IRQ_KEYPAD S3C24A0_IRQ(9)
+#define IRQ_TIMER0 S3C24A0_IRQ(10)
+#define IRQ_TIMER1 S3C24A0_IRQ(11)
+#define IRQ_TIMER2 S3C24A0_IRQ(12)
+#define IRQ_TIMER3_4 S3C24A0_IRQ(13)
+#define IRQ_LCD_POST S3C24A0_IRQ(14)
+#define IRQ_CAM_C S3C24A0_IRQ(15)
+#define IRQ_WDT_BATFLT S3C24A0_IRQ(16) /* 32 */
+#define IRQ_UART0 S3C24A0_IRQ(17)
+#define IRQ_CAM_P S3C24A0_IRQ(18)
+#define IRQ_MODEM S3C24A0_IRQ(19)
+#define IRQ_DMA S3C24A0_IRQ(20)
+#define IRQ_SDI S3C24A0_IRQ(21)
+#define IRQ_SPI0 S3C24A0_IRQ(22)
+#define IRQ_UART1 S3C24A0_IRQ(23)
+#define IRQ_AC97_NFLASH S3C24A0_IRQ(24) /* 40 */
+#define IRQ_USBD S3C24A0_IRQ(25)
+#define IRQ_USBH S3C24A0_IRQ(26)
+#define IRQ_IIC S3C24A0_IRQ(27)
+#define IRQ_IRDA_MSTICK S3C24A0_IRQ(28) /* 44 */
+#define IRQ_VLX_SPI1 S3C24A0_IRQ(29)
+#define IRQ_RTC S3C24A0_IRQ(30) /* 46 */
+#define IRQ_ADC_PENUPDN S3C24A0_IRQ(31)
+
+
+/* interrupts generated from the external interrupts sources */
+#define IRQ_EINT0 S3C24A0_IRQ(32) /* 48 */
+#define IRQ_EINT1 S3C24A0_IRQ(33)
+#define IRQ_EINT2 S3C24A0_IRQ(34)
+#define IRQ_EINT3 S3C24A0_IRQ(35)
+#define IRQ_EINT4 S3C24A0_IRQ(36)
+#define IRQ_EINT5 S3C24A0_IRQ(37)
+#define IRQ_EINT6 S3C24A0_IRQ(38)
+#define IRQ_EINT7 S3C24A0_IRQ(39)
+#define IRQ_EINT8 S3C24A0_IRQ(40)
+#define IRQ_EINT9 S3C24A0_IRQ(41)
+#define IRQ_EINT10 S3C24A0_IRQ(42)
+#define IRQ_EINT11 S3C24A0_IRQ(43)
+#define IRQ_EINT12 S3C24A0_IRQ(44)
+#define IRQ_EINT13 S3C24A0_IRQ(45)
+#define IRQ_EINT14 S3C24A0_IRQ(46)
+#define IRQ_EINT15 S3C24A0_IRQ(47)
+#define IRQ_EINT16 S3C24A0_IRQ(48)
+#define IRQ_EINT17 S3C24A0_IRQ(49)
+#define IRQ_EINT18 S3C24A0_IRQ(50)
+
+/* SUB IRQS */
+#define IRQ_RXD0 S3C24A0_IRQ(51) /* 67 */
+#define IRQ_TXD0 S3C24A0_IRQ(52)
+#define IRQ_ERR0 S3C24A0_IRQ(53)
+#define IRQ_RXD1 S3C24A0_IRQ(54)
+#define IRQ_TXD1 S3C24A0_IRQ(55)
+#define IRQ_ERR1 S3C24A0_IRQ(56)
+#define IRQ_IRDA S3C24A0_IRQ(57)
+#define IRQ_MSTICK S3C24A0_IRQ(58)
+#define IRQ_RESERVED0 S3C24A0_IRQ(59)
+#define IRQ_RESERVED1 S3C24A0_IRQ(60)
+#define IRQ_RESERVED2 S3C24A0_IRQ(61)
+#define IRQ_TIMER3 S3C24A0_IRQ(62)
+#define IRQ_TIMER4 S3C24A0_IRQ(63)
+#define IRQ_WDT S3C24A0_IRQ(64)
+#define IRQ_BATFLT S3C24A0_IRQ(65)
+#define IRQ_POST S3C24A0_IRQ(66)
+#define IRQ_DISP_FIFO S3C24A0_IRQ(67)
+#define IRQ_PENUP S3C24A0_IRQ(68)
+#define IRQ_PENDN S3C24A0_IRQ(69)
+#define IRQ_ADC S3C24A0_IRQ(70)
+#define IRQ_DISP_FRAME S3C24A0_IRQ(71)
+#define IRQ_NFLASH S3C24A0_IRQ(72)
+#define IRQ_AC97 S3C24A0_IRQ(73)
+#define IRQ_SPI1 S3C24A0_IRQ(74)
+#define IRQ_VLX S3C24A0_IRQ(75)
+#define IRQ_DMA0 S3C24A0_IRQ(76)
+#define IRQ_DMA1 S3C24A0_IRQ(77)
+#define IRQ_DMA2 S3C24A0_IRQ(78)
+#define IRQ_DMA3 S3C24A0_IRQ(79)
+
+#define NR_IRQS (IRQ_DMA3+1)
+
+
+#endif /* __ASM_ARCH_IRQ_H */
diff --git a/include/asm-arm/arch-s3c24a0/key.h b/include/asm-arm/arch-s3c24a0/key.h
new file mode 100644
index 0000000..9ffad9f
--- /dev/null
+++ b/include/asm-arm/arch-s3c24a0/key.h
@@ -0,0 +1,95 @@
+/*
+ * include/asm-arm/arch-s3c24a0/key.h
+ *
+ * $Id: key.h,v 1.1.1.1 2006/02/13 05:23:03 ihlee215 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.
+ */
+#ifndef _INCLUDE_LINUETTE_KEY_H_
+#define _INCLUDE_LINUETTE_KEY_H_
+#ifndef __ASSEMBLY__
+
+#define KEY_RELEASED 0
+#define KEY_PRESSED 1
+
+/*
+ * Definition of Generic Key Scancode
+ */
+#define SCANCODE_LEFT 0x69
+#define SCANCODE_RIGHT 0x6a
+#define SCANCODE_UP 0x67
+#define SCANCODE_DOWN 0x6c
+#define SCANCODE_ENTER 0x1c
+#define SCANCODE_PAGE_UP 0x68 /* Page Up */
+#define SCANCODE_PAGE_DOWN 0x6d /* Page Down */
+#define SCANCODE_BKSP 0x0e /* Back Space */
+
+/*
+ * Key PAD
+ */
+#define SCANCODE_PAD_0 0x52
+#define SCANCODE_PAD_1 0x4f
+#define SCANCODE_PAD_2 0x50
+#define SCANCODE_PAD_3 0x51
+#define SCANCODE_PAD_4 0x4b
+#define SCANCODE_PAD_5 0x4c
+#define SCANCODE_PAD_6 0x4d
+#define SCANCODE_PAD_7 0x47
+#define SCANCODE_PAD_8 0x48
+#define SCANCODE_PAD_9 0x49
+#define SCANCODE_PAD_MINUS 0x4a
+#define SCANCODE_PAD_PLUS 0x4e
+#define SCANCODE_PAD_ENTER 0x60
+#define SCANCODE_PAD_PERIOD 0x53
+#define SCANCODE_PAD_SLASH 0x62
+#define SCANCODE_PAD_ASTERISK 0x37
+
+/*
+ * Function Key
+ */
+#define SCANCODE_F5 0x3f
+#define SCANCODE_F6 0x40
+#define SCANCODE_F7 0x41
+#define SCANCODE_F8 0x42
+#define SCANCODE_F9 0x43
+#define SCANCODE_F10 0x44
+#define SCANCODE_F11 0x57
+#define SCANCODE_F12 0x58
+
+/*
+ * Undefined Region
+ */
+#define SCANCODE_U1 0x78 /* Unknown */
+#define SCANCODE_U2 0x79 /* Unknown */
+#define SCANCODE_U3 0x70 /* Unknown */
+#define SCANCODE_U4 0x71 /* Unknown */
+#define SCANCODE_U5 0x72 /* Unknown */
+#define SCANCODE_U6 0x73 /* Unknown */
+#define SCANCODE_U7 0x74 /* Unknown */
+#define SCANCODE_U8 0x75 /* Unknown */
+#define SCANCODE_U9 0x76 /* Unknown */
+
+/*
+ * Common key definition for PDA
+ */
+#define SCANCODE_POWER 0x7a
+#define SCANCODE_RECORD 0x7b
+#define SCANCODE_ACTION SCANCODE_ENTER
+#define SCANCODE_SLIDE_UP SCANCODE_PAGE_UP
+#define SCANCODE_SLIDE_DOWN SCANCODE_PAGE_DOWN
+#define SCANCODE_SLIDE_CENTER SCANCODE_PAD_ENTER
+
+/*
+ * Common key definition for Phone
+ */
+#define SCANCODE_ASTERISK SCANCODE_PAD_ASTERISK
+#define SCANCODE_SHARP SCANCODE_PAD_MINUS
+#define SCANCODE_SEND 0x7c
+#define SCANCODE_END 0x7d
+#define SCANCODE_MENU 0x7e
+#define NCODE_CLR 0x7f
+
+#endif /* __ASSEMBLY__ */
+#endif /* _INCLUDE_LINUETTE_KEY_H_ */
diff --git a/include/asm-arm/arch-s3c24a0/keyboard.h b/include/asm-arm/arch-s3c24a0/keyboard.h
new file mode 100644
index 0000000..c58ef59
--- /dev/null
+++ b/include/asm-arm/arch-s3c24a0/keyboard.h
@@ -0,0 +1,146 @@
+/*
+ * include/asm-arm/arch-s3c24a0/keyboard.h
+ *
+ * $Id: keyboard.h,v 1.1.1.1 2006/02/13 05:23:03 ihlee215 Exp $
+ *
+ * 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
+ */
+
+
+#ifndef _S3C24A0_KEYBOARD_H
+#define _S3C24A0_KEYBOARD_H
+
+#define kbd_disable_irq() do { } while(0);
+#define kbd_enable_irq() do { } while(0);
+
+#define k_leds(x...)
+#define k_setkeycode(x...)
+#define k_getkeycode(x...)
+#define k_unexpected_up(x...) (1)
+
+#ifdef CONFIG_S3C24X0_KEYB
+extern int elfin_kbd_init (void);
+#define kbd_init_hw() elfin_kbd_init()
+#else
+#define kbd_init_hw() do {} while(0);
+#endif
+
+/* Generic Keyboard Scan Codes */
+#define KK_NONE 0x00
+#define KK_ESC 0x01
+#define KK_F1 0x3b
+#define KK_F2 0x3c
+#define KK_F3 0x3d
+#define KK_F4 0x3e
+#define KK_F5 0x3f
+#define KK_F6 0x40
+#define KK_F7 0x41
+#define KK_F8 0x42
+#define KK_F9 0x43
+#define KK_F10 0x44
+#define KK_F11 0x57
+#define KK_F12 0x58
+#define KK_PRNT 0x63 /* PrintScreen */
+#define KK_SCRL 0x46 /* Scroll Lock */
+#define KK_BRK 0x77 /* Break */
+#define KK_AGR 0x29 /* ` */
+#define KK_1 0x02
+#define KK_2 0x03
+#define KK_3 0x04
+#define KK_4 0x05
+#define KK_5 0x06
+#define KK_6 0x07
+#define KK_7 0x08
+#define KK_8 0x09
+#define KK_9 0x0a
+#define KK_0 0x0b
+#define KK_MINS 0x0c /* - */
+#define KK_EQLS 0x0d /* = */
+#define KK_BKSP 0x0e /* BKSP */
+#define KK_INS 0x6e /* Insert */
+#define KK_HOME 0x66
+#define KK_PGUP 0x68
+#define KK_NUML 0x45
+#define KP_SLH 0x62 /* KP / */
+#define KP_STR 0x37 /* KP * */
+#define KP_MNS 0x4a /* KP - */
+#define KK_TAB 0x0f
+#define KK_Q 0x10
+#define KK_W 0x11
+#define KK_E 0x12
+#define KK_R 0x13
+#define KK_T 0x14
+#define KK_Y 0x15
+#define KK_U 0x16
+#define KK_I 0x17
+#define KK_O 0x18
+#define KK_P 0x19
+#define KK_LSBK 0x1a /* [ */
+#define KK_RSBK 0x1b /* ] */
+#define KK_ENTR 0x1c
+#define KK_DEL 0x6f
+#define KK_END 0x6b
+#define KK_PGDN 0x6d
+#define KP_7 0x47
+#define KP_8 0x48
+#define KP_9 0x49
+#define KP_PLS 0x37 /* KP + */
+#define KK_CAPS 0x3a
+#define KK_A 0x1e
+#define KK_S 0x1f
+#define KK_D 0x20
+#define KK_F 0x21
+#define KK_G 0x22
+#define KK_H 0x23
+#define KK_J 0x24
+#define KK_K 0x25
+#define KK_L 0x26
+#define KK_SEMI 0x27 /* ; */
+#define KK_SQOT 0x28 /* ' */
+#define KK_HASH 0x29 /* ` */
+#define KP_4 0x4b
+#define KP_5 0x4c
+#define KP_6 0x4d
+#define KK_LSFT 0x2a /* L SHIFT */
+#define KK_BSLH 0x2b /* \ */
+#define KK_Z 0x2c
+#define KK_X 0x2d
+#define KK_C 0x2e
+#define KK_V 0x2f
+#define KK_B 0x30
+#define KK_N 0x31
+#define KK_M 0x32
+#define KK_COMA 0x33 /* , */
+#define KK_DOT 0x34 /* . */
+#define KK_FSLH 0x35 /* / */
+#define KK_RSFT 0x36 /* R SHIFT */
+#define KK_UP 0x67
+#define KP_1 0x4f
+#define KP_2 0x50
+#define KP_3 0x51
+#define KP_ENT 0x60 /* KP Enter */
+#define KK_LCTL 0x1d /* L CTRL */
+#define KK_LALT 0x38 /* L ALT */
+#define KK_SPCE 0x39 /* SPACE */
+#define KK_RALT 0x64 /* R ALT */
+#define KK_RCTL 0x61 /* R CTRL */
+#define KK_LEFT 0x69
+#define KK_DOWN 0x6c
+#define KK_RGHT 0x6a
+#define KP_0 0x52
+#define KP_DOT 0x53 /* KP . */
+#define KK_21 0x21
+
+#endif /* _S3C24A0_KEYBOARD_H */
Should probably be using an input driver in the correct place
in the driver tree.
diff --git a/include/asm-arm/arch-s3c24a0/map.h b/include/asm-arm/arch-s3c24a0/map.h
new file mode 100644
index 0000000..04902f5
--- /dev/null
+++ b/include/asm-arm/arch-s3c24a0/map.h
@@ -0,0 +1,180 @@
+/* linux/include/asm-arm/arch-s3c24a0/map.h
+ *
+ * $Id: map.h,v 1.1.1.1 2006/02/13 05:23:03 ihlee215 Exp $
+ *
+ * Copyright (C) 2005, Sean Choi
+ * All rights reserved.
+ *
+ * S3C24A0 - Memory map definitions
+ *
+ * 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.
+ *
+ * derived from linux/include/asm-arm/arch-s3c2410/map.h, written by
+ * Ben Dooks
+*/
+
+#ifndef __ASM_ARCH_MAP_H
+#define __ASM_ARCH_MAP_H
+
+/* we have a bit of a tight squeeze to fit all our registers from
+ * 0xF00000000 upwards, since we use all of the nGCS space in some
+ * capacity, and also need to fit the S3C24A0 registers in as well...
+ *
+ * we try to ensure stuff like the IRQ registers are available for
+ * an single MOVS instruction (ie, only 8 bits of set data)
+ *
+ * Note, we are trying to remove some of these from the implementation
+ * as they are only useful to certain drivers...
+ */
We seem to have this and a seperate io_p2v and io_v2p ?
+#define S3C24A0_ADDR(x) (0xE0000000 + (x))
+
+#define S3C24A0_VA_IO_BASE 0xE0000000
+#define S3C24A0_PA_IO_BASE 0x40000000
+#define S3C24A0_SZ_IO 0x10000000
+
+/* Clock and Power management */
+#define S3C24A0_VA_CLKPWR S3C24A0_ADDR(0x00000000)
+#define S3C24A0_PA_CLKPWR (0x40000000)
+#define S3C24A0_SZ_CLKPWR SZ_1M
+
+/* interrupt controller is the first thing we put in, to make
+ * the assembly code for the irq detection easier
+ */
+#define S3C24A0_VA_IRQ S3C24A0_ADDR(0x00200000)
+#define S3C24A0_PA_IRQ (0x40200000)
+#define S3C24A0_SZ_IRQ SZ_1M
+
+/* DMA controller */
+#define S3C24A0_VA_DMA S3C24A0_ADDR(0x00400000)
+#define S3C24A0_PA_DMA (0x40400000)
+#define S3C24A0_SZ_DMA SZ_1M
+
+/* NAND flash controller */
+#define S3C24A0_VA_NAND S3C24A0_ADDR(0x00C00000)
+#define S3C24A0_PA_NAND (0x40C00000)
+#define S3C24A0_SZ_NAND SZ_1M
+
+/* SROM controller registers */
+#define S3C24A0_VA_SROM S3C24A0_ADDR(0x00C20000)
+#define S3C24A0_PA_SROM (0x40C20000)
+#define S3C24A0_SZ_SROM SZ_128K
+
+/* SDRAM controller registers */
+#define S3C24A0_VA_SDRAM S3C24A0_ADDR(0x00C40000)
+#define S3C24A0_PA_SDRAM (0x40C40000)
+#define S3C24A0_SZ_SDRAM SZ_128K
+
+/* Bus Matrix controller registers */
+#define S3C24A0_VA_BUSM S3C24A0_ADDR(0x00CE0000)
+#define S3C24A0_PA_BUSM (0x40CE0000)
+#define S3C24A0_SZ_BUSM SZ_128K
+
+/* USB host controller */
+#define S3C24A0_VA_USBHOST S3C24A0_ADDR(0x01000000)
+#define S3C24A0_PA_USBHOST (0x41000000)
+#define S3C24A0_SZ_USBHOST SZ_1M
+
+/* Modem Interface controller */
+#define S3C24A0_VA_MODEMIF S3C24A0_ADDR(0x01180000)
+#define S3C24A0_PA_MODEMIF (0x41180000)
+#define S3C24A0_SZ_MODEMIF SZ_128K
+
+/* IrDA controller */
+#define S3C24A0_VA_IRDA S3C24A0_ADDR(0x01800000)
+#define S3C24A0_PA_IRDA (0x41800000)
+#define S3C24A0_SZ_IRDA SZ_1M
+
+/* Timers */
+#define S3C24A0_VA_TIMER S3C24A0_ADDR(0x04000000)
+#define S3C24A0_PA_TIMER (0x44000000)
+#define S3C24A0_SZ_TIMER SZ_1M
+
+/* Watchdog */
+#define S3C24A0_VA_WATCHDOG S3C24A0_ADDR(0x04100000)
+#define S3C24A0_PA_WATCHDOG (0x44100000)
+#define S3C24A0_SZ_WATCHDOG SZ_1M
+
+/* RTC */
+#define S3C24A0_VA_RTC S3C24A0_ADDR(0x04200000)
+#define S3C24A0_PA_RTC (0x44200000)
+#define S3C24A0_SZ_RTC SZ_1M
+
+/* UARTs */
+#define S3C24A0_VA_UART S3C24A0_ADDR(0x04400000)
+#define S3C24A0_PA_UART (0x44400000)
+#define S3C24A0_SZ_UART SZ_1M
+
+#define S3C24A0_VA_UART0 (S3C24A0_VA_UART)
+#define S3C24A0_VA_UART1 (S3C24A0_VA_UART + 0x4000 )
+
+#define S3C24A0_PA_UART0 (S3C24A0_PA_UART)
+#define S3C24A0_PA_UART1 (S3C24A0_PA_UART + 0x4000 )
+
+/* SPI */
+#define S3C24A0_VA_SPI S3C24A0_ADDR(0x04500000)
+#define S3C24A0_PA_SPI (0x44500000)
+#define S3C24A0_SZ_SPI SZ_1M
+
+/* IIC hardware controller */
+#define S3C24A0_VA_IIC S3C24A0_ADDR(0x04600000)
+#define S3C24A0_PA_IIC (0x44600000)
+#define S3C24A0_SZ_IIC SZ_1M
+
+#define VA_IIC_BASE (S3C24A0_VA_IIC)
+
+/* IIS controller */
+#define S3C24A0_VA_IIS S3C24A0_ADDR(0x04700000)
+#define S3C24A0_PA_IIS (0x44700000)
+#define S3C24A0_SZ_IIS SZ_1M
+
+/* GPIO ports */
+#define S3C24A0_VA_GPIO S3C24A0_ADDR(0x04800000)
+#define S3C24A0_PA_GPIO (0x44800000)
+#define S3C24A0_SZ_GPIO SZ_1M
+
+/* Key Interface ports */
+#define S3C24A0_VA_KEYIF S3C24A0_ADDR(0x04900000)
+#define S3C24A0_PA_KEYIF (0x44900000)
+#define S3C24A0_SZ_KEYIF SZ_1M
+
+/* USB Device port */
+#define S3C24A0_VA_USBDEV S3C24A0_ADDR(0x04A00000)
+#define S3C24A0_PA_USBDEV (0x44A00000)
+#define S3C24A0_SZ_USBDEV SZ_1M
+
+/* AC97 port */
+#define S3C24A0_VA_AC97 S3C24A0_ADDR(0x05000000)
+#define S3C24A0_PA_AC97 (0x45000000)
+#define S3C24A0_SZ_AC97 SZ_1M
+
+/* ADC */
+#define S3C24A0_VA_ADC S3C24A0_ADDR(0x05800000)
+#define S3C24A0_PA_ADC (0x45800000)
+#define S3C24A0_SZ_ADC SZ_1M
+
+/* SDI */
+#define S3C24A0_VA_SDI S3C24A0_ADDR(0x06000000)
+#define S3C24A0_PA_SDI (0x46000000)
+#define S3C24A0_SZ_SDI SZ_1M
+
+/* Memory Stick */
+#define S3C24A0_VA_MS S3C24A0_ADDR(0x06100000)
+#define S3C24A0_PA_MS (0x46100000)
+#define S3C24A0_SZ_MS SZ_1M
+
+/* LCD controller */
+#define S3C24A0_VA_LCD S3C24A0_ADDR(0x0A000000)
+#define S3C24A0_PA_LCD (0x4A000000)
+#define S3C24A0_SZ_LCD SZ_1M
+
+
+/* VPOST */
+#define S3C24A0_VA_VPOST S3C24A0_ADDR(0x0A100000)
+#define S3C24A0_PA_VPOST (0x4A100000)
+#define S3C24A0_SZ_VPOST SZ_1M
+
+#define S3C24A0_SDRAM_PA 0x10000000
+#endif /* __ASM_ARCH_MAP_H */
diff --git a/include/asm-arm/arch-s3c24a0/memory.h b/include/asm-arm/arch-s3c24a0/memory.h
new file mode 100644
index 0000000..2c4661b
--- /dev/null
+++ b/include/asm-arm/arch-s3c24a0/memory.h
@@ -0,0 +1,100 @@
+/*
+ * linux/include/asm-arm/arch-s3c24a0/memory.h
+ *
+ * $Id: memory.h,v 1.1.1.1 2006/02/13 05:23:03 ihlee215 Exp $
+ *
+ * Copyright (C) 2005, Sean Choi
+ * All rights reserved.
+ *
+ * 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.
+ *
+*/
+
+#ifndef __ASM_ARCH_MEMORY_H
+#define __ASM_ARCH_MEMORY_H
+
+/*
+ * DRAM starts at 0x10000000
+ */
+#define PHYS_OFFSET UL(0x10000000)
+
+/*
+ * These are exactly the same on the S3C2410 as the
+ * physical memory view.
+*/
+
+#define __virt_to_bus(x) __virt_to_phys(x)
+#define __bus_to_virt(x) __phys_to_virt(x)
+
+#ifdef CONFIG_DISCONTIGMEM
+/*
+ * Because of the wide memory address space between physical RAM banks on the
+ * k2, lets use Linux's NUMA support to implement our memory map
+ * representation.
+ *
+ * The nodes are matched with the physical memory bank addresses which are
+ * incidentally the same as virtual addresses.
+ *
+ * node 0: 0x10000000 - 0x11ff_ffff --> 32M
+ * node 1: 0x18000000 - 0x19ff_ffff --> 32M
+ */
+#define MEM_SIZE1 (32*1024*1024)
+#define MEM_SIZE2 (32*1024*1024)
+
+#define NR_NODES 4
+
+/*
+ * Given a kernel address, find the home node of the underlying memory.
+ */
+#define KVADDR_TO_NID(addr) (((unsigned long)(addr) - PAGE_OFFSET ) >> NODE_MAX_MEM_SHIFT)
+
+/*
+ * Given a page frame number, convert it to a node id.
+ */
+#define PFN_TO_NID(pfn) (((pfn) - PHYS_PFN_OFFSET) >> (NODE_MAX_MEM_SHIFT - PAGE_SHIFT))
+/*
+ * Given a kaddr, ADDR_TO_MAPBASE finds the owning node of the memory
+ * and returns the mem_map of that node.
+ */
+#define ADDR_TO_MAPBASE(kaddr) NODE_MEM_MAP(KVADDR_TO_NID((unsigned long)(kaddr)))
+
+/*
+ * Given a page frame number, find the owning node of the memory
+ * and returns the mem_map of that node.
+ */
+#define PFN_TO_MAPBASE(pfn) NODE_MEM_MAP(PFN_TO_NID(pfn))
+
+/*
+ * Given a kaddr, LOCAL_MEM_MAP finds the owning node of the memory
+ * and returns the index corresponding to the appropriate page in the
+ * node's mem_map.
+ */
+#define LOCAL_MAP_NR(addr) \
+ (((unsigned long)(addr) & 0x07ffffff ) >> PAGE_SHIFT)
+
+/*The 2460 has two banks that can hold 256MB each. but have only 32MB each*/
+#define NODE_MAX_MEM_SHIFT 27
+#define NODE_MAX_MEM_SIZE (1<