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< + * + * S3C24A0 - NAND device controller platfrom_device info + * + * 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. + * + * Changelog: + * 23-Sep-2004 BJD Created file +*/ + +/* struct s3c24a0_nand_set + * + * define an set of one or more nand chips registered with an unique mtd + * + * nr_chips = number of chips in this set + * nr_partitions = number of partitions pointed to be partitions (or zero) + * name = name of set (optional) + * nr_map = map for low-layer logical to physical chip numbers (option) + * partitions = mtd partition list +*/ + +struct s3c24a0_nand_set { + int nr_chips; + int nr_partitions; + char *name; + int *nr_map; + struct mtd_partition *partitions; +}; + +struct s3c24a0_platform_nand { + /* timing information for controller, all times in nanoseconds */ + + int tacls; /* time for active CLE/ALE to nWE/nOE */ + int twrph0; /* active time for nWE/nOE */ + int twrph1; /* time for release CLE/ALE from nWE/nOE inactive */ + + int nr_sets; + struct s3c24a0_nand_set *sets; + + void (*select_chip)(struct s3c24a0_nand_set *, + int chip); +}; Again, share-able code diff --git a/include/asm-arm/arch-s3c24a0/param.h b/include/asm-arm/arch-s3c24a0/param.h new file mode 100644 index 0000000..2cc90af --- /dev/null +++ b/include/asm-arm/arch-s3c24a0/param.h @@ -0,0 +1,28 @@ +/* linux/include/asm-arm/arch-s3c24a0/param.h + * + * S3C24A0 - Machine parameters + * + * $Id: param.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/param.h, written by + * Ben Dooks + */ + +#ifndef __ASM_ARCH_PARAM_H +#define __ASM_ARCH_PARAM_H + +/* we cannot get our timer down to 100Hz with the setup as is, but we can + * manage 200 clock ticks per second... if this is a problem, we can always + * add a software pre-scaler to the evil timer systems. +*/ + +#define HZ 100 Comment and value do not agree. +#endif /* __ASM_ARCH_PARAM_H */ diff --git a/include/asm-arm/arch-s3c24a0/regs-ac97.h b/include/asm-arm/arch-s3c24a0/regs-ac97.h new file mode 100644 index 0000000..99170f0 --- /dev/null +++ b/include/asm-arm/arch-s3c24a0/regs-ac97.h @@ -0,0 +1,99 @@ +/* linux/sound/oss/s3c24a0-ac97.h + * + * $Id: regs-ac97.h,v 1.1.1.1 2006/02/13 05:23:03 ihlee215 Exp $ + * + * Copyright (C) 2005, Sean Choi + * All rights reserved. + * + * - S3C24A0A's AC97 has the same IP to S3C2440A's AC97 + * All source code is under GPLv2 + * + */ Then use the ASoC implementation which is being merged, Graeme has already submitted the register definitions to be merged in the next window. +#ifndef __S3C24XX_AC97_H_ +#define __S3C24XX_AC97_H_ + +#include + +#define AC97_CTL_BASE S3C24A0_VA_AC97 + +#define S3C24A0_AC97REG(x) ((x) + AC97_CTL_BASE) +#define S3C24A0_AC97REG_PHYS(x) ((x) + S3C24A0_PA_AC97) + +#define AC_GLBCTRL S3C24A0_AC97REG(0x00) /* global control */ +#define AC_GLBSTAT S3C24A0_AC97REG(0x04) /* global status */ +#define AC_CODEC_CMD S3C24A0_AC97REG(0x08) /* codec command */ +#define AC_CODEC_STAT S3C24A0_AC97REG(0x0c) /* codec status */ +#define AC_PCMADDR S3C24A0_AC97REG(0x10) /* PCM out/in FIFO address */ +#define AC_MICADDR S3C24A0_AC97REG(0x14) /* MIC in FIFO address */ +#define AC_PCMDATA S3C24A0_AC97REG(0x18) /* PCM out/in FIFO data */ +#define AC_MICDATA S3C24A0_AC97REG(0x1c) /* MIC in FIFO data */ + +#define AC_PCMDATA_PHYS S3C24A0_AC97REG_PHYS(0x18) /* PCM out/in FIFO data */ +#define AC_MICDATA_PHYS S3C24A0_AC97REG_PHYS(0x1c) /* MIC in FIFO data */ + +#define AC_GLBCTRL_RIE (1<<22) /* codec ready interrupt enable */ +#define AC_GLBCTRL_POUIE (1<<21) /* PCM out underrun interrupt enable */ +#define AC_GLBCTRL_PIOIE (1<<20) /* PCM in overrun interrupt enable */ +#define AC_GLBCTRL_MIOIE (1<<19) /* MIC in underrun interrupt enable */ +#define AC_GLBCTRL_POTIE (1<<18) /* PCM out threshold interrupt enable */ +#define AC_GLBCTRL_PITIE (1<<17) /* PCM in threshold interrupt enable */ +#define AC_GLBCTRL_MITIE (1<<16) /* MIC in threshold interrupt enable */ +#define fAC_GLBCTRL_POMODE Fld(2,12) /* PCM out transfer mode */ +#define AC_GLBCTRL_POMODE FMsk(fAC_GLBCTRL_POMODE) +#define AC_GLBCTRL_POMODE_OFF FInsrt(0, fAC_GLBCTRL_POMODE) /* off */ +#define AC_GLBCTRL_POMODE_PIO FInsrt(1, fAC_GLBCTRL_POMODE) /* PIO */ +#define AC_GLBCTRL_POMODE_DMA FInsrt(2, fAC_GLBCTRL_POMODE) /* DMA */ +#define fAC_GLBCTRL_PIMODE Fld(2,10) /* PCM in transfer mode */ +#define AC_GLBCTRL_PIMODE FMsk(fAC_GLBCTRL_PIMODE) +#define AC_GLBCTRL_PIMODE_OFF FInsrt(0, fAC_GLBCTRL_PIMODE) /* off */ +#define AC_GLBCTRL_PIMODE_PIO FInsrt(1, fAC_GLBCTRL_PIMODE) /* PIO */ +#define AC_GLBCTRL_PIMODE_DMA FInsrt(2, fAC_GLBCTRL_PIMODE) /* DMA */ +#define fAC_GLBCTRL_MIMODE Fld(2,8) /* MIC in transfer mode */ +#define AC_GLBCTRL_MIMODE FMsk(fAC_GLBCTRL_MIMODE) +#define AC_GLBCTRL_MIMODE_OFF FInsrt(0, fAC_GLBCTRL_MIMODE) /* off */ +#define AC_GLBCTRL_MIMODE_PIO FInsrt(1, fAC_GLBCTRL_MIMODE) /* PIO */ +#define AC_GLBCTRL_MIMODE_DMA FInsrt(2, fAC_GLBCTRL_MIMODE) /* DMA */ +#define AC_GLBCTRL_TE (1<<3) /* Transfer data enable using AC-link */ +#define AC_GLBCTRL_AE (1<<2) /* AC-link on */ +#define AC_GLBCTRL_WARM (1<<1) /* warm reset */ +#define AC_GLBCTRL_COLD (1<<0) /* cold reset */ + +#define AC_GLBSTAT_RI (1<<22) /* codec ready interrupt */ +#define AC_GLBSTAT_POUI (1<<21) /* PCM out underrun interrupt */ +#define AC_GLBSTAT_PIOI (1<<20) /* PCM in overrun interrupt */ +#define AC_GLBSTAT_MIOI (1<<19) /* MIC in overrun interrupt */ +#define AC_GLBSTAT_POTI (1<<18) /* PCM out threshold interrupt */ +#define AC_GLBSTAT_PITI (1<<17) /* PCM in threshold interrupt */ +#define AC_GLBSTAT_MITI (1<<16) /* MIC in threshold interrupt */ +#define fAC_GLBSTAT_CSTAT Fld(3,0) /* Controller main state */ +#define AC_GLBSTAT_CSTAT() FExtr(__raw_readl(AC_GLBSTAT), fAC_GLBSTAT_CSTAT) +#define AC_CSTAT_IDLE (0) +#define AC_CSTAT_INIT (1) +#define AC_CSTAT_READY (2) +#define AC_CSTAT_ACTIVE (3) +#define AC_CSTAT_LP (4) +#define AC_CSTAT_WARM (5) + +#define AC_CMD_R (1<<23) /* read enable - 0: command write, 1: status read */ + +#define fAC_CMD_ADDR Fld(7, 16) /* codec command address */ +#define AC_CMD_ADDR(x) FInsrt((x), fAC_CMD_ADDR) +#define fAC_CMD_DATA Fld(16, 0) /* codec command data */ +#define AC_CMD_DATA(x) FInsrt((x), fAC_CMD_DATA) + +#define fAC_STAT_ADDR Fld(7, 16) /* codec status address */ +#define AC_STAT_ADDR(x) FExtr((x), fAC_STAT_ADDR) +#define fAC_STAT_DATA Fld(16, 0) /* codec status data */ +#define AC_STAT_DATA(x) FExtr((x), fAC_STAT_DATA) + +#define DMA_CH0 0 +#define DMA_CH1 1 +#define DMA_CH2 2 +#define DMA_CH3 3 + +#define DMA_BUF_WR 1 +#define DMA_BUF_RD 0 + +#endif + diff --git a/include/asm-arm/arch-s3c24a0/regs-adc.h b/include/asm-arm/arch-s3c24a0/regs-adc.h new file mode 100644 index 0000000..345713f --- /dev/null +++ b/include/asm-arm/arch-s3c24a0/regs-adc.h @@ -0,0 +1,106 @@ +/* linux/include/asm/arch-s3c24a0/regs-adc.h + * + * Id: regs-adc.h + * + * S3C24A0 ADC register definitions + * + * 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_REGS_ADC_H +#define __ASM_ARCH_REGS_ADC_H + +#include "bitfield.h" + +#define S3C24A0_ADCREG(x) ((x) + S3C24A0_VA_ADC) + +#define S3C24A0_ADCCON S3C24A0_ADCREG(0x00) // R/W, ADC control register +#define S3C24A0_ADCTSC S3C24A0_ADCREG(0x04) // R/W, ADC touch screen ctl reg +#define S3C24A0_ADCDLY S3C24A0_ADCREG(0x08) // R/W, ADC start or interval delay reg +#define S3C24A0_ADCDAX S3C24A0_ADCREG(0x0c) // R , ADC conversion data reg +#define S3C24A0_ADCDAY S3C24A0_ADCREG(0x10) // R , ADC conversion data reg + +/* ADCCON */ +#define fECFLG Fld(1, 15) // R , End of conversion flag +#define ECFLG_VAL FExtr(ADCCON, fECFLG) +#define CONV_PROCESS 0 +#define CONV_END 1 + +#define fPRSCEN Fld(1, 14) +#define PRSCEN_DIS FInsrt(0, fPRSCEN) +#define PRSCEN_EN FInsrt(1, fPRSCEN) + +#define fPRSCVL Fld(8, 6) +#define PRSCVL(x) FInsrt(x, fPRSCVL) + +#define fSEL_MUX Fld(3, 3) +#define ADC_IN_SEL(x) FInsrt(x, fSEL_MUX) +#define ADC_IN0 0 +#define ADC_IN1 1 +#define ADC_IN2 2 +#define ADC_IN3 3 +#define ADC_IN4 4 +#define ADC_IN5 5 +#define ADC_IN6 6 +#define ADC_IN7 7 + +#define fSTDBM Fld(1, 2) // Standby mode select +#define STDBM_NORMAL FInsrt(0, fSTDBM) +#define STDBM_STANDBY FInsrt(1, fSTDBM) + +#define fREAD_START Fld(1, 1) +#define READ_START_DIS FInsrt(0, fREAD_START) +#define READ_START_EN FInsrt(1, fREAD_START) + +#define fENABLE_START Fld(1, 0) +#define ENABLE_START_NOOP FInsrt(0, fENABLE_START) +#define ENABLE_START_START FInsrt(1, fENABLE_START) + +/* ADCTSC */ +#define fYM_SEN Fld(1, 7) +#define YM_HIZ FInsrt(0, fYM_SEN) +#define YM_GND FInsrt(1, fYM_SEN) +#define fYP_SEN Fld(1, 6) +#define YP_EXTVLT FInsrt(0, fYP_SEN) +#define YP_AIN5 FInsrt(1, fYP_SEN) +#define fXM_SEN Fld(1, 5) +#define XM_HIZ FInsrt(0, fXM_SEN) +#define XM_GND FInsrt(1, fXM_SEN) +#define fXP_SEN Fld(1, 4) +#define XP_EXTVLT FInsrt(0, fXP_SEN) +#define XP_AIN7 FInsrt(1, fXP_SEN) +#define fPULL_UP Fld(1, 3) +#define XP_PULL_UP_EN FInsrt(0, fPULL_UP) +#define XP_PULL_UP_DIS FInsrt(1, fPULL_UP) +#define fAUTO_PST Fld(1, 2) +#define AUTO_PST_NORMAL FInsrt(0, fAUTO_PST) +#define AUTO_PST_AUTO FInsrt(1, fAUTO_PST) +#define fXY_PST Fld(2, 0) +#define XY_PST_NOOP FInsrt(0, fXY_PST) +#define XY_PST_X_POS FInsrt(1, fXY_PST) +#define XY_PST_Y_POS FInsrt(2, fXY_PST) +#define XY_PST_WAIT_INT FInsrt(3, fXY_PST) + +/* ADC Conversion DATA Field, commons */ +#define fUPDOWN Fld(1, 15) +#define fDAT_AUTO_PST Fld(1, 14) +#define fDAT_XY_PST Fld(2, 12) +#define fPST_DATA Fld(10, 0) // PST : position + +#define PST_DAT_MSK 0x3FF +#define PST_DAT_VAL(x) (FExtr(x, fPST_DATA) & PST_DAT_MSK) +/* ADCDAX */ + #define XPDATA PST_DAT_VAL(ADCDAX) +/* ADCDAY */ +#define YPDATA PST_DAT_VAL(ADCDAY) + +#endif /* __ASM_ARCH_REGS_ADC_H */ + Ah, I see what those Fld macros where for. No, this is ugly. Please also note that there is an adc/ts driver being prepared from the h1940 project. diff --git a/include/asm-arm/arch-s3c24a0/regs-busm.h b/include/asm-arm/arch-s3c24a0/regs-busm.h new file mode 100644 index 0000000..4c22cbc --- /dev/null +++ b/include/asm-arm/arch-s3c24a0/regs-busm.h @@ -0,0 +1,28 @@ +/* linux/include/asm/arch-s3c24a0/regs-busm.h + * + * Id: regs-busm.h + * + * S3C24A0 Bus Matrix register definitions + * + * 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_REGS_PM_H +#define __ASM_ARCH_REGS_PM_H + +/* + * Bus Matrix + */ +#define S3C24A0_BUSMREG(x) ((x) + S3C24A0_VA_BUSM) +#define PRIORITY0 S3C24A0_BUSMREG(0x00) +#define PRIORITY1 S3C24A0_BUSMREG(0x04) +#define PRIORITY_S_FIX 0x0 +#define PRIORITY_I_FIX 0x2 + +#endif /* __ASM_ARCH_REGS_BUSM_H */ register names should be prefixed with S3C24A0_ diff --git a/include/asm-arm/arch-s3c24a0/regs-clock.h b/include/asm-arm/arch-s3c24a0/regs-clock.h new file mode 100644 index 0000000..4dadeb6 --- /dev/null +++ b/include/asm-arm/arch-s3c24a0/regs-clock.h @@ -0,0 +1,101 @@ +/* linux/include/asm/arch-s3c24a0/regs-clock.h + * + * Id: regs-clock.h + * + * S3C24A0 clock register definitions + * + * 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/regs-clock.h, written by + * Ben Dooks + * + */ + +#ifndef __ASM_ARM_REGS_CLOCK +#define __ASM_ARM_REGS_CLOCK + +#define S3C24A0_CLKREG(x) ((x) + S3C24A0_VA_CLKPWR) + +#define S3C24A0_PLLVAL(_m,_p,_s) ((_m) << 12 | ((_p) << 4) | ((_s))) + +#define S3C24A0_LOCKTIME S3C24A0_CLKREG(0x00) +#define S3C24A0_XTALWSET S3C24A0_CLKREG(0x04) +#define S3C24A0_MPLLCON S3C24A0_CLKREG(0x10) +#define S3C24A0_UPLLCON S3C24A0_CLKREG(0x14) +#define S3C24A0_CLKCON S3C24A0_CLKREG(0x20) +#define S3C24A0_CLKSRC S3C24A0_CLKREG(0x24) +#define S3C24A0_CLKDIVN S3C24A0_CLKREG(0x28) +#define S3C24A0_POWERMAN S3C24A0_CLKREG(0x30) +#define S3C24A0_SOFTRST S3C24A0_CLKREG(0x38) + +/* CLKCON register bits */ +#define S3C24A0_CLKCON_VLX (1<<29) +#define S3C24A0_CLKCON_VPOST (1<<28) +#define S3C24A0_CLKCON_WDT (1<<27) /* reserved */ +#define S3C24A0_CLKCON_MPEGDCTQ (1<<26) +#define S3C24A0_CLKCON_VPOSTIF (1<<25) +#define S3C24A0_CLKCON_MPEG4IF (1<<24) +#define S3C24A0_CLKCON_CAM_UPLL (1<<23) +#define S3C24A0_CLKCON_LCD (1<<22) +#define S3C24A0_CLKCON_CAM_HCLK (1<<21) +#define S3C24A0_CLKCON_MPEG4 (1<<20) +#define S3C24A0_CLKCON_KEYPAD (1<<19) +#define S3C24A0_CLKCON_ADC (1<<18) +#define S3C24A0_CLKCON_SDI (1<<17) +#define S3C24A0_CLKCON_MS (1<<16) /* memory stick */ +#define S3C24A0_CLKCON_USBD (1<<15) +#define S3C24A0_CLKCON_GPIO (1<<14) +#define S3C24A0_CLKCON_IIS (1<<13) +#define S3C24A0_CLKCON_IIC (1<<12) +#define S3C24A0_CLKCON_SPI (1<<11) +#define S3C24A0_CLKCON_UART1 (1<<10) +#define S3C24A0_CLKCON_UART0 (1<<9) +#define S3C24A0_CLKCON_PWM (1<<8) +#define S3C24A0_CLKCON_USBH (1<<7) +#define S3C24A0_CLKCON_AC97 (1<<6) +#define S3C24A0_CLKCON_EAHB (1<<5) +#define S3C24A0_CLKCON_IrDA (1<<4) +#define S3C24A0_CLKCON_IDLE (1<<2) +#define S3C24A0_CLKCON_MON (1<<1) +#define S3C24A0_CLKCON_STOP (1<<0) +#define S3C24A0_CLKSRC_OSC (1<<8) /* CLKSRC */ +#define S3C24A0_CLKSRC_nUPLL (1<<7) +#define S3C24A0_CLKSRC_nPLL (1<<5) +#define S3C24A0_CLKSRC_EXT (1<<4) +#define S3C24A0_CLKDIV_HCLK (1<<1) /* CLKDIV */ +#define S3C24A0_CLKDIV_PCLK (1<<0) +#define S3C24A0_PWRMAN_MASKTS (1<<8) /* PWRMAN */ + +#define S3C24A0_PLLCON_MDIVSHIFT 12 +#define S3C24A0_PLLCON_PDIVSHIFT 4 +#define S3C24A0_PLLCON_SDIVSHIFT 0 +#define S3C24A0_PLLCON_MDIVMASK ((1<<(1+(19-12)))-1) +#define S3C24A0_PLLCON_PDIVMASK ((1<<5)-1) +#define S3C24A0_PLLCON_SDIVMASK 3 + +#ifndef __ASSEMBLY__ + +static inline unsigned int +s3c24a0_get_pll(int pllval, int baseclk) +{ + int mdiv, pdiv, sdiv; + + mdiv = pllval >> S3C24A0_PLLCON_MDIVSHIFT; + pdiv = pllval >> S3C24A0_PLLCON_PDIVSHIFT; + sdiv = pllval >> S3C24A0_PLLCON_SDIVSHIFT; + + mdiv &= S3C24A0_PLLCON_MDIVMASK; + pdiv &= S3C24A0_PLLCON_PDIVMASK; + sdiv &= S3C24A0_PLLCON_SDIVMASK; + + return (baseclk * (mdiv + 8)) / ((pdiv + 2) << sdiv); +} + +#endif /* __ASSEMBLY__ */ + +#endif /* __ASM_ARM_REGS_CLOCK */ diff --git a/include/asm-arm/arch-s3c24a0/regs-gpio-24a0.h b/include/asm-arm/arch-s3c24a0/regs-gpio-24a0.h new file mode 100644 index 0000000..2542284 --- /dev/null +++ b/include/asm-arm/arch-s3c24a0/regs-gpio-24a0.h @@ -0,0 +1,301 @@ +/* linux/include/asm/hardware/s3c24A0/regs-gpio.h + * + * Copyright (c) 2003,2004 Simtec Electronics + * http://www.simtec.co.uk/products/SWLINUX/ + * + * 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. + * + * S3C24A0 GPIO register definitions + * + * Changelog: + * 19-06-2003 BJD Created file + * 23-06-2003 BJD Updated GSTATUS registers + * 12-03-2004 BJD Updated include protection + * 20-07-2004 BJD Added GPIO pin numbers, added Port A definitions + * 04-10-2004 BJD Fixed number of bugs, added EXT IRQ filter defs + * 17-10-2004 BJD Added GSTATUS1 register definitions + * 18-11-2004 BJD Fixed definitions of GPE3, GPE4, GPE5 and GPE6 + * 18-11-2004 BJD Added S3C2440 AC97 controls +*/ + + +#ifndef __ASM_ARCH_REGS_GPIO_H +#define __ASM_ARCH_REGS_GPIO_H "$Id: regs-gpio-24a0.h,v 1.1.1.1 2006/02/13 05:23:03 ihlee215 Exp $" + +//#define S3C24A0_GPIONO(bank,offset) ((bank&0xff << 8 ) | (offset & 0xff)) + + +#define GPIO_CONL_NUM (2) +#define GPIO_CONM_NUM (1) +#define GPIO_CONU_NUM (0) +#define GPIO_CONL_BASE (0<<3) +#define GPIO_CONM_BASE (11<<3) +#define GPIO_CONU_BASE (19<<3) +#define S3C24A0_GPIO_CONL (GPIO_CONL_NUM | GPIO_CONL_BASE) +#define S3C24A0_GPIO_CONM (GPIO_CONM_NUM | GPIO_CONM_BASE) +#define S3C24A0_GPIO_CONU (GPIO_CONU_NUM | GPIO_CONU_BASE) + + +#define GPIO_OFS_SHIFT 0 +#define GPIO_CON_SHIFT 8 + +#define S3C24A0_GPIONO(c, o) ((c << GPIO_CON_SHIFT) | (o << GPIO_OFS_SHIFT)) + +#define S3C24A0_GPIO_BASE(pin) ((((pin >>GPIO_CON_SHIFT ) & 0x7) * 4 )\ + + S3C24A0_VA_GPIO) +#define S3C24A0_GPIO_PINNO(pin) ((pin) & 0xff) +#define S3C24A0_GPIO_CONBASE(pin) (((pin >> GPIO_CON_SHIFT ) >> 3 ) & 0x1F) +#define S3C24A0_GPIO_OFFSET(pin) (S3C24A0_GPIO_PINNO(pin) -\ + S3C24A0_GPIO_CONBASE(pin)) + + +/* general configuration options */ + +#define S3C24A0_GPIO_LEAVE (0xFFFFFFFF) + +/* configure GPIO ports */ + +#define S3C24A0_GPIOREG(x) ((x) + S3C24A0_VA_GPIO) + +#define S3C24A0_GPCONU S3C24A0_GPIOREG(0x00) +#define S3C24A0_GPCONM S3C24A0_GPIOREG(0x04) +#define S3C24A0_GPCONL S3C24A0_GPIOREG(0x08) +#define S3C24A0_GPDAT S3C24A0_GPIOREG(0x0C) +#define S3C24A0_GPPU S3C24A0_GPIOREG(0x10) + +#define S3C24A0_EINTMASK S3C24A0_GPIOREG(0x34) +#define S3C24A0_EINTPEND S3C24A0_GPIOREG(0x38) + +#define S3C24A0_EINTCR0 S3C24A0_GPIOREG(0x18) +#define S3C24A0_EINTCR1 S3C24A0_GPIOREG(0x1c) +#define S3C24A0_EINTCR2 S3C24A0_GPIOREG(0x20) +#define S3C24A0_EINTFLT0 S3C24A0_GPIOREG(0x24) +#define S3C24A0_EINTFLT1 S3C24A0_GPIOREG(0x28) + + +#define S3C24A0_GP0 S3C24A0_GPIONO(S3C24A0_GPIO_CONL, 0) +#define S3C24A0_GP0_INP (0x00 << 0) +#define S3C24A0_GP0_OUTP (0x01 << 0) +#define S3C24A0_GP0_EINT0 (0x02 << 0) + +#define S3C24A0_GP1 S3C24A0_GPIONO(S3C24A0_GPIO_CONL, 1) +#define S3C24A0_GP1_INP (0x00 << 2) +#define S3C24A0_GP1_OUTP (0x01 << 2) +#define S3C24A0_GP1_EINT1 (0x02 << 2) +#define S3C24A0_GP1_PWMECLK (0x03 << 2) + +#define S3C24A0_GP2 S3C24A0_GPIONO(S3C24A0_GPIO_CONL, 2) +#define S3C24A0_GP2_INP (0x00 << 4) +#define S3C24A0_GP2_OUTP (0x01 << 4) +#define S3C24A0_GP2_EINT2 (0x02 << 4) +#define S3C24A0_GP2_PWMTOUT0 (0x03 <<4) + +#define S3C24A0_GP3 S3C24A0_GPIONO(S3C24A0_GPIO_CONL, 3) +#define S3C24A0_GP3_INP (0x00 << 6) +#define S3C24A0_GP3_OUTP (0x01 << 6) +#define S3C24A0_GP3_EINT3 (0x02 << 6) +#define S3C24A0_GP3_PWMTOUT1 (0x03 <<6) + +#define S3C24A0_GP4 S3C24A0_GPIONO(S3C24A0_GPIO_CONL, 4) +#define S3C24A0_GP4_INP (0x00 << 8) +#define S3C24A0_GP4_OUTP (0x01 << 8) +#define S3C24A0_GP4_EINT4 (0x02 << 8) +#define S3C24A0_GP4_PWMTOUT2 (0x03 <<8) + +#define S3C24A0_GP5 S3C24A0_GPIONO(S3C24A0_GPIO_CONL, 5) +#define S3C24A0_GP5_INP (0x00 << 10) +#define S3C24A0_GP5_OUTP (0x01 << 10) +#define S3C24A0_GP5_EINT5 (0x02 << 10) +#define S3C24A0_GP5_PWMTOUT3 (0x03 <<10) + +#define S3C24A0_GP6 S3C24A0_GPIONO(S3C24A0_GPIO_CONL, 6) +#define S3C24A0_GP6_INP (0x00 << 12) +#define S3C24A0_GP6_OUTP (0x01 << 12) +#define S3C24A0_GP6_EINT6 (0x02 << 12) +#define S3C24A0_GP6_EXTDMAREQ0 (0x03 << 12) + +#define S3C24A0_GP7 S3C24A0_GPIONO(S3C24A0_GPIO_CONL, 7) +#define S3C24A0_GP7_INP (0x00 << 14) +#define S3C24A0_GP7_OUTP (0x01 << 14) +#define S3C24A0_GP7_EINT7 (0x02 << 14) +#define S3C24A0_GP7_EXTDMAREQ1 (0x03 << 14) + +#define S3C24A0_GP8 S3C24A0_GPIONO(S3C24A0_GPIO_CONL, 8) +#define S3C24A0_GP8_INP (0x00 << 16) +#define S3C24A0_GP8_OUTP (0x01 << 16) +#define S3C24A0_GP8_EINT8 (0x02 << 16) +#define S3C24A0_GP8_EXTDMAACK0 (0x03 << 16) + +#define S3C24A0_GP9 S3C24A0_GPIONO(S3C24A0_GPIO_CONL, 9) +#define S3C24A0_GP9_INP (0x00 << 18) +#define S3C24A0_GP9_OUTP (0x01 << 18) +#define S3C24A0_GP9_EINT9 (0x02 << 18) +#define S3C24A0_GP9_EXTDMAACK1 (0x03 << 18) + +#define S3C24A0_GP10 S3C24A0_GPIONO(S3C24A0_GPIO_CONL, 10) +#define S3C24A0_GP10_INP (0x00 << 20) +#define S3C24A0_GP10_OUTP (0x01 << 20) + +#define S3C24A0_GP11 S3C24A0_GPIONO(S3C24A0_GPIO_CONM, 11) +#define S3C24A0_GP11_INP (0x00 << 0) +#define S3C24A0_GP11_OUTP (0x01 << 0) +#define S3C24A0_GP11_EINT11 (0x02 << 0) + +#define S3C24A0_GP12 S3C24A0_GPIONO(S3C24A0_GPIO_CONM, 12) +#define S3C24A0_GP12_INP (0x00 << 2) +#define S3C24A0_GP12_OUTP (0x01 << 2) +#define S3C24A0_GP12_EINT12 (0x02 << 2) + +#define S3C24A0_GP13 S3C24A0_GPIONO(S3C24A0_GPIO_CONM, 13) +#define S3C24A0_GP13_INP (0x00 << 4) +#define S3C24A0_GP13_OUTP (0x01 << 4) +#define S3C24A0_GP13_EINT13 (0x02 << 4) + +#define S3C24A0_GP14 S3C24A0_GPIONO(S3C24A0_GPIO_CONM, 14) +#define S3C24A0_GP14_INP (0x00 << 6) +#define S3C24A0_GP14_OUTP (0x01 << 6) +#define S3C24A0_GP14_EINT14 (0x02 << 6) +#define S3C24A0_GP14_RTC_ALMINT (0x03 << 6) + +#define S3C24A0_GP15 S3C24A0_GPIONO(S3C24A0_GPIO_CONM, 15) +#define S3C24A0_GP15_INP (0x00 << 8) +#define S3C24A0_GP15_OUTP (0x01 << 8) +#define S3C24A0_GP15_EINT15 (0x02 << 8) +#define S3C24A0_GP15_SPIMOSI (0x03 << 8) + +#define S3C24A0_GP16 S3C24A0_GPIONO(S3C24A0_GPIO_CONM, 16) +#define S3C24A0_GP16_INP (0x00 << 10) +#define S3C24A0_GP16_OUTP (0x01 << 10) +#define S3C24A0_GP16_EINT16 (0x02 << 10) +#define S3C24A0_GP16_SPIMISO (0x03 << 10) + +#define S3C24A0_GP17 S3C24A0_GPIONO(S3C24A0_GPIO_CONM, 17) +#define S3C24A0_GP17_INP (0x00 << 12) +#define S3C24A0_GP17_OUTP (0x01 << 12) +#define S3C24A0_GP17_EINT17 (0x02 << 12) +#define S3C24A0_GP17_SPICLK (0x03 << 12) + +#define S3C24A0_GP18 S3C24A0_GPIONO(S3C24A0_GPIO_CONM, 18) +#define S3C24A0_GP18_INP (0x00 << 14) +#define S3C24A0_GP18_OUTP (0x01 << 14) +#define S3C24A0_GP18_EINT18 (0x02 << 14) +#define S3C24A0_GP18_KEYROW0 (0x03 << 14) + + +#define S3C24A0_GP19 S3C24A0_GPIONO(S3C24A0_GPIO_CONU, 19) +#define S3C24A0_GP19_INP (0x00 << 0) +#define S3C24A0_GP19_OUTP (0x01 << 0) +#define S3C24A0_GP19_PWMECLK (0x02 << 0) +#define S3C24A0_GP19_KEYROW1 (0x03 << 0) + + +#define S3C24A0_GP20 S3C24A0_GPIONO(S3C24A0_GPIO_CONU, 20) +#define S3C24A0_GP20_INP (0x00 << 2) +#define S3C24A0_GP20_OUTP (0x01 << 2) +#define S3C24A0_GP20_PWMTOUT0 (0x02 << 2) +#define S3C24A0_GP20_KEYROW2 (0x03 << 2) + +#define S3C24A0_GP21 S3C24A0_GPIONO(S3C24A0_GPIO_CONU, 21) +#define S3C24A0_GP21_INP (0x00 << 4) +#define S3C24A0_GP21_OUTP (0x01 << 4) +#define S3C24A0_GP21_PWMTOUT1 (0x02 << 4) +#define S3C24A0_GP21_KEYROW3 (0x03 << 4) + +#define S3C24A0_GP22 S3C24A0_GPIONO(S3C24A0_GPIO_CONU, 22) +#define S3C24A0_GP22_INP (0x00 << 6) +#define S3C24A0_GP22_OUTP (0x01 << 6) +#define S3C24A0_GP22_PWMTOUT2 (0x02 << 6) +#define S3C24A0_GP22_KEYROW4 (0x03 << 6) + + +#define S3C24A0_GP23 S3C24A0_GPIONO(S3C24A0_GPIO_CONU, 23) +#define S3C24A0_GP23_INP (0x00 << 8) +#define S3C24A0_GP23_OUTP (0x01 << 8) +#define S3C24A0_GP23_PWMTOUT3 (0x02 << 8) +#define S3C24A0_GP23_KEYCOL0 (0x03 << 8) + +#define S3C24A0_GP24 S3C24A0_GPIONO(S3C24A0_GPIO_CONU, 24) +#define S3C24A0_GP24_INP (0x00 << 10) +#define S3C24A0_GP24_OUTP (0x01 << 10) +#define S3C24A0_GP25_EXTDMAREQ0 (0x02 << 10) +#define S3C24A0_GP24_KEYCOL1 (0x03 << 10) + +#define S3C24A0_GP25 S3C24A0_GPIONO(S3C24A0_GPIO_CONU, 25) +#define S3C24A0_GP25_INP (0x00 << 12) +#define S3C24A0_GP25_OUTP (0x01 << 12) +#define S3C24A0_GP25_EXTDMAREQ1 (0x02 << 12) +#define S3C24A0_GP25_KEYCOL2 (0x03 << 12) + +#define S3C24A0_GP26 S3C24A0_GPIONO(S3C24A0_GPIO_CONU, 26) +#define S3C24A0_GP26_INP (0x00 << 14) +#define S3C24A0_GP26_OUTP (0x01 << 14) +#define S3C24A0_GP26_EXTDMAACK0 (0x02 << 14) +#define S3C24A0_GP26_KEYCOL3 (0x03 << 14) + +#define S3C24A0_GP27 S3C24A0_GPIONO(S3C24A0_GPIO_CONU, 27) +#define S3C24A0_GP27_INP (0x00 << 16) +#define S3C24A0_GP27_OUTP (0x01 << 16) +#define S3C24A0_GP27_EXTDMAACK1 (0x02 << 16) +#define S3C24A0_GP27_KEYCOL4 (0x03 << 16) + +#define S3C24A0_GP28 S3C24A0_GPIONO(S3C24A0_GPIO_CONU, 28) +#define S3C24A0_GP28_INP (0x00 << 18) +#define S3C24A0_GP28_OUTP (0x01 << 18) +#define S3C24A0_GP28_CTS1 (0x02 << 18) +#define S3C24A0_GP28_RTC_ALMINT (0x03 << 18) + +#define S3C24A0_GP29 S3C24A0_GPIONO(S3C24A0_GPIO_CONU, 29) +#define S3C24A0_GP29_INP (0x00 << 20) +#define S3C24A0_GP29_OUTP (0x01 << 20) +#define S3C24A0_GP29_RTS1 (0x02 << 20) +#define S3C24A0_GP29_IRDA_SDBW (0x03 << 20) + +#define S3C24A0_GP30 S3C24A0_GPIONO(S3C24A0_GPIO_CONU, 30) +#define S3C24A0_GP30_INP (0x00 << 22) +#define S3C24A0_GP30_OUTP (0x01 << 22) +#define S3C24A0_GP30_TXD1 (0x02 << 22) +#define S3C24A0_GP30_IRDA_TXD (0x03 << 22) + +#define S3C24A0_GP31 S3C24A0_GPIONO(S3C24A0_GPIO_CONU, 31) +#define S3C24A0_GP31_INP (0x00 << 24) +#define S3C24A0_GP31_OUTP (0x01 << 24) +#define S3C24A0_GP31_RXD1 (0x02 << 24) +#define S3C24A0_GP31_IRDA_RXD (0x03 << 24) + +/* external interrupt control... */ +/* S3C24A0_EXTINT0 -> irq sense control for EINT0..EINT7 + * S3C24A0_EXTINT1 -> irq sense control for EINT8..EINT15 + * S3C24A0_EXTINT2 -> irq sense control for EINT16..EINT23 + * + * note S3C24A0_EXTINT2 has filtering options for EINT16..EINT23 + * + * Samsung datasheet p9-25 +*/ + +#define S3C24A0_EXTINT0 S3C24A0_GPIOREG(0x18) +#define S3C24A0_EXTINT1 S3C24A0_GPIOREG(0x1C) +#define S3C24A0_EXTINT2 S3C24A0_GPIOREG(0x20) + +/* values for S3C24A0_EXTINT0/1/2 */ +#define S3C24A0_EXTINT_LOWLEV (0x00) +#define S3C24A0_EXTINT_HILEV (0x01) +#define S3C24A0_EXTINT_FALLEDGE (0x02) +#define S3C24A0_EXTINT_RISEEDGE (0x04) +#define S3C24A0_EXTINT_BOTHEDGE (0x06) + +/* interrupt filtering conrrol for EINT16..EINT23 */ +#define S3C24A0_EINFLT0 S3C24A0_GPIOREG(0x24) +#define S3C24A0_EINFLT1 S3C24A0_GPIOREG(0x28) + +/* values for interrupt filtering */ +#if 0 +#define S3C24A0_EINTFLT_PCLK (0x00) +#define S3C24A0_EINTFLT_EXTCLK (1<<7) +#define S3C24A0_EINTFLT_WIDTHMSK(x) ((x) & 0x3f) +#endif + + +#endif /* __ASM_ARCH_REGS_GPIO_H */ + diff --git a/include/asm-arm/arch-s3c24a0/regs-gpio.h b/include/asm-arm/arch-s3c24a0/regs-gpio.h new file mode 100644 index 0000000..f398b1d --- /dev/null +++ b/include/asm-arm/arch-s3c24a0/regs-gpio.h @@ -0,0 +1,182 @@ +/* linux/include/asm/arch-s3c24a0/regs-gpio.h + * + * Id: regs-gpio.h + * + * S3C24A0 GPIO register definitions + * + * 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_REGS_GPIO_H +#define __ASM_ARCH_REGS_GPIO_H + +/* + * GPIO ( chapter 20 ) + */ + +#define S3C24A0_GPIOREG(x) ((x) + S3C24A0_VA_GPIO) + +#define GPIO_CONL_NUM (2) +#define GPIO_CONM_NUM (1) +#define GPIO_CONU_NUM (0) +#define GPIO_CONL_BASE (0<<3) +#define GPIO_CONM_BASE (11<<3) +#define GPIO_CONU_BASE (19<<3) +#define GPIO_CONL (GPIO_CONL_NUM | GPIO_CONL_BASE) +#define GPIO_CONM (GPIO_CONM_NUM | GPIO_CONM_BASE) +#define GPIO_CONU (GPIO_CONU_NUM | GPIO_CONU_BASE) + +#define S3C24A0_GPCON(x) S3C24A0_GPIOREG((x) * 0x4) +#define S3C24A0_GPCONU S3C24A0_GPIOREG(0x00) +#define S3C24A0_GPCONM S3C24A0_GPIOREG(0x04) +#define S3C24A0_GPCONL S3C24A0_GPIOREG(0x08) +#define S3C24A0_GPDAT S3C24A0_GPIOREG(0x0c) +#define S3C24A0_GPUP S3C24A0_GPIOREG(0x10) + +#define S3C24A0_EINTMASK S3C24A0_GPIOREG(0x34) +#define S3C24A0_EINTPEND S3C24A0_GPIOREG(0x38) + +#define S3C24A0_EINTCR0 S3C24A0_GPIOREG(0x18) +#define S3C24A0_EINTCR1 S3C24A0_GPIOREG(0x1c) +#define S3C24A0_EINTCR2 S3C24A0_GPIOREG(0x20) +#define S3C24A0_EINTFLT0 S3C24A0_GPIOREG(0x24) +#define S3C24A0_EINTFLT1 S3C24A0_GPIOREG(0x28) + +/* values for S3C2410_EXTINT0/1/2 */ +#define S3C24A0_EXTINT_LOWLEV (0x00) +#define S3C24A0_EXTINT_HILEV (0x01) +#define S3C24A0_EXTINT_FALLEDGE (0x02) +#define S3C24A0_EXTINT_RISEEDGE (0x04) +#define S3C24A0_EXTINT_BOTHEDGE (0x06) + +#define GPIO_OFS_SHIFT 0 +#define GPIO_CON_SHIFT 8 +#define GPIO_PULLUP_SHIFT 16 +#define GPIO_MODE_SHIFT 24 +#define GPIO_OFS_MASK 0x000000ff +#define GPIO_CON_MASK 0x0000ff00 +#define GPIO_PULLUP_MASK 0x00ff0000 +#define GPIO_MODE_MASK 0xff000000 +#if 0 +#define GPIO_MODE_IN (0 << GPIO_MODE_SHIFT) +#define GPIO_MODE_OUT (1 << GPIO_MODE_SHIFT) +#define GPIO_MODE_ALT0 (2 << GPIO_MODE_SHIFT) +#define GPIO_MODE_ALT1 (3 << GPIO_MODE_SHIFT) +#define GPIO_PULLUP_EN (0 << GPIO_PULLUP_SHIFT) +#define GPIO_PULLUP_DIS (1 << GPIO_PULLUP_SHIFT) +#endif + + +#define GPIO_MODE_IN (0 ) +#define GPIO_MODE_OUT (1 ) +#define GPIO_MODE_ALT0 (2 ) +#define GPIO_MODE_ALT1 (3 ) +#define GPIO_PULLUP_EN (0 ) +#define GPIO_PULLUP_DIS (1 ) + + + +#define MAKE_GPIO_NUM(c, o) ((c << GPIO_CON_SHIFT) | (o << GPIO_OFS_SHIFT)) + +#define GRAB_MODE(x) (((x) & GPIO_MODE_MASK) >> GPIO_MODE_SHIFT) +#define GRAB_PULLUP(x) (((x) & GPIO_PULLUP_MASK) >> GPIO_PULLUP_SHIFT) +#define GRAB_OFS(x) (((x) & GPIO_OFS_MASK) >> GPIO_OFS_SHIFT) +#define GRAB_CON_NUM(x) ((((x) & GPIO_CON_MASK) >> GPIO_CON_SHIFT) & 0x07) +#define GRAB_CON_OFS(x) (GRAB_OFS(x) - (((x) & GPIO_CON_MASK) >> (GPIO_CON_SHIFT+3))) should find a better name +#define GPIO_0 MAKE_GPIO_NUM(GPIO_CONL, 0) +#define GPIO_1 MAKE_GPIO_NUM(GPIO_CONL, 1) +#define GPIO_2 MAKE_GPIO_NUM(GPIO_CONL, 2) +#define GPIO_3 MAKE_GPIO_NUM(GPIO_CONL, 3) +#define GPIO_4 MAKE_GPIO_NUM(GPIO_CONL, 4) +#define GPIO_5 MAKE_GPIO_NUM(GPIO_CONL, 5) +#define GPIO_6 MAKE_GPIO_NUM(GPIO_CONL, 6) +#define GPIO_7 MAKE_GPIO_NUM(GPIO_CONL, 7) +#define GPIO_8 MAKE_GPIO_NUM(GPIO_CONL, 8) +#define GPIO_9 MAKE_GPIO_NUM(GPIO_CONL, 9) +#define GPIO_10 MAKE_GPIO_NUM(GPIO_CONL, 10) +#define GPIO_11 MAKE_GPIO_NUM(GPIO_CONM, 11) +#define GPIO_12 MAKE_GPIO_NUM(GPIO_CONM, 12) +#define GPIO_13 MAKE_GPIO_NUM(GPIO_CONM, 13) +#define GPIO_14 MAKE_GPIO_NUM(GPIO_CONM, 14) +#define GPIO_15 MAKE_GPIO_NUM(GPIO_CONM, 15) +#define GPIO_16 MAKE_GPIO_NUM(GPIO_CONM, 16) +#define GPIO_17 MAKE_GPIO_NUM(GPIO_CONM, 17) +#define GPIO_18 MAKE_GPIO_NUM(GPIO_CONM, 18) +#define GPIO_19 MAKE_GPIO_NUM(GPIO_CONU, 19) +#define GPIO_20 MAKE_GPIO_NUM(GPIO_CONU, 20) +#define GPIO_21 MAKE_GPIO_NUM(GPIO_CONU, 21) +#define GPIO_22 MAKE_GPIO_NUM(GPIO_CONU, 22) +#define GPIO_23 MAKE_GPIO_NUM(GPIO_CONU, 23) +#define GPIO_24 MAKE_GPIO_NUM(GPIO_CONU, 24) +#define GPIO_25 MAKE_GPIO_NUM(GPIO_CONU, 25) +#define GPIO_26 MAKE_GPIO_NUM(GPIO_CONU, 26) +#define GPIO_27 MAKE_GPIO_NUM(GPIO_CONU, 27) +#define GPIO_28 MAKE_GPIO_NUM(GPIO_CONU, 28) +#define GPIO_29 MAKE_GPIO_NUM(GPIO_CONU, 29) +#define GPIO_30 MAKE_GPIO_NUM(GPIO_CONU, 30) +#define GPIO_31 MAKE_GPIO_NUM(GPIO_CONU, 31) +/* major alt. */ +#define GPIO_MODE_EINT GPIO_MODE_ALT0 +#define GPIO_MODE_RTC_ALARMINT GPIO_MODE_ALT1 +#define GPIO_MODE_IrDA GPIO_MODE_ALT1 +#define GPIO_MODE_PWM GPIO_MODE_ALT0 +#define GPIO_MODE_SPI GPIO_MODE_ALT1 +#define GPIO_MODE_EXT_DMA GPIO_MODE_ALT0 +#define GPIO_MODE_EXT_KEYP GPIO_MODE_ALT1 +#define GPIO_MODE_UART GPIO_MODE_ALT0 + +/* canonical */ +#define GPIO_MODE_IrDA_SDBW GPIO_MODE_IrDA +#define GPIO_MODE_IrDA_TXD GPIO_MODE_IrDA +#define GPIO_MODE_IrDA_RXD GPIO_MODE_IrDA +#define GPIO_MODE_PWM_ECLK GPIO_MODE_PWM +#define GPIO_MODE_PWM_TOUT GPIO_MODE_PWM +#define GPIO_MODE_PWM_TOUT0 GPIO_MODE_PWM +#define GPIO_MODE_PWM_TOUT1 GPIO_MODE_PWM +#define GPIO_MODE_PWM_TOUT2 GPIO_MODE_PWM +#define GPIO_MODE_PWM_TOUT3 GPIO_MODE_PWM +#define GPIO_MODE_SPI_MODI GPIO_MODE_SPI +#define GPIO_MODE_SPI_MISO GPIO_MODE_SPI +#define GPIO_MODE_DMAREQ0 GPIO_MODE_EXT_DMA +#define GPIO_MODE_DMAREQ1 GPIO_MODE_EXT_DMA +#define GPIO_MODE_DMAACK0 GPIO_MODE_EXT_DMA +#define GPIO_MODE_DMAACK1 GPIO_MODE_EXT_DMA +#define GPIO_MODE_KEYP_ROW0 GPIO_MODE_EXT_KEYP +#define GPIO_MODE_KEYP_ROW1 GPIO_MODE_EXT_KEYP +#define GPIO_MODE_KEYP_ROW2 GPIO_MODE_EXT_KEYP +#define GPIO_MODE_KEYP_ROW3 GPIO_MODE_EXT_KEYP +#define GPIO_MODE_KEYP_ROW4 GPIO_MODE_EXT_KEYP +#define GPIO_MODE_KEYP_COL0 GPIO_MODE_EXT_KEYP +#define GPIO_MODE_KEYP_COL1 GPIO_MODE_EXT_KEYP +#define GPIO_MODE_KEYP_COL2 GPIO_MODE_EXT_KEYP +#define GPIO_MODE_KEYP_COL3 GPIO_MODE_EXT_KEYP +#define GPIO_MODE_KEYP_COL4 GPIO_MODE_EXT_KEYP +#define GPIO_MODE_uCTSn1 GPIO_MODE_UART +#define GPIO_MODE_uRTSn1 GPIO_MODE_UART +#define GPIO_MODE_uTXD1 GPIO_MODE_UART >> 2 +#define GPIO_MODE_uRXD1 GPIO_MODE_UART this lot seem to be redundant re-definition of the above? +#define S3C24A0_ENPU S3C24A0_GPIOREG(0x40) /* normal port pullup in sleep */ +#define S3C24A0_ENPU_EN S3C24A0_GPIOREG(0x64) /* ENPU enable */ + +#if 1 +#define set_gpio_ctrl(x) \ + ({ __raw_writel(__raw_readl(S3C24A0_GPCON(GRAB_CON_NUM((x)))) & ~(0x3 << (GRAB_CON_OFS((x))*2)), S3C24A0_GPCON(GRAB_CON_NUM(x))); \ + __raw_writel(__raw_readl(S3C24A0_GPCON(GRAB_CON_NUM(x))) | (GRAB_MODE(x) << (GRAB_CON_OFS((x))*2)), S3C24A0_GPCON(GRAB_CON_NUM(x))); \ + __raw_writel(__raw_readl(S3C24A0_GPUP) & ~(1 << GRAB_OFS((x))), S3C24A0_GPUP); \ + __raw_writel(__raw_readl(S3C24A0_GPUP)|(GRAB_PULLUP((x)) << GRAB_OFS((x))),S3C24A0_GPUP); }) +#endif +#define read_gpio_bit(x) ((GPDAT & (1<> GRAB_OFS((x))) +#define write_gpio_bit(x, v) \ + ({ GPDAT &= ~(0x1 << GRAB_OFS((x))); \ + GPDAT |= ((v) << GRAB_OFS((x))); }) + +#endif /* __ASM_ARCH_REGS_GPIO_H */ bad use of macros, please do not do this. diff --git a/include/asm-arm/arch-s3c24a0/regs-iic.h b/include/asm-arm/arch-s3c24a0/regs-iic.h new file mode 100644 index 0000000..d3b9f96 --- /dev/null +++ b/include/asm-arm/arch-s3c24a0/regs-iic.h @@ -0,0 +1,62 @@ +/* linux/include/asm/arch-s3c24a0/regs-iic.h + * + * Id: regs-iic.h + * + * S3C24A0 IIC register definitions + * + * 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/regs-iic.h, written by + * Ben Dooks + * + */ + +#ifndef __ASM_ARCH_REGS_IIC_H +#define __ASM_ARCH_REGS_IIC_H __FILE__ + +/* see s3c24a0 user guide */ + +#define S3C24A0_IICREG(x) (x) + +#define S3C24A0_IICCON S3C24A0_IICREG(0x00) +#define S3C24A0_IICSTAT S3C24A0_IICREG(0x04) +#define S3C24A0_IICADD S3C24A0_IICREG(0x08) +#define S3C24A0_IICDS S3C24A0_IICREG(0x0C) +#define S3C24A0_SDADLY S3C24A0_IICREG(0x10) + +#define S3C24A0_IICCON_ACKEN (1<<7) +#define S3C24A0_IICCON_TXDIV_16 (0<<6) +#define S3C24A0_IICCON_TXDIV_512 (1<<6) +#define S3C24A0_IICCON_IRQEN (1<<5) +#define S3C24A0_IICCON_IRQPEND (1<<4) +#define S3C24A0_IICCON_SCALE(x) ((x)&15) +#define S3C24A0_IICCON_SCALEMASK (0xf) + +#define S3C24A0_IICSTAT_MASTER_RX (2<<6) +#define S3C24A0_IICSTAT_MASTER_TX (3<<6) +#define S3C24A0_IICSTAT_SLAVE_RX (0<<6) +#define S3C24A0_IICSTAT_SLAVE_TX (1<<6) +#define S3C24A0_IICSTAT_MODEMASK (3<<6) + +#define S3C24A0_IICSTAT_START (1<<5) +#define S3C24A0_IICSTAT_BUSBUSY (1<<5) +#define S3C24A0_IICSTAT_TXRXEN (1<<4) +#define S3C24A0_IICSTAT_ARBITR (1<<3) +#define S3C24A0_IICSTAT_ASSLAVE (1<<2) +#define S3C24A0_IICSTAT_ADDR0 (1<<1) +#define S3C24A0_IICSTAT_LASTBIT (1<<0) + +#define S3C24A0_IICLC_SDA_DELAY0 (0 << 0) +#define S3C24A0_IICLC_SDA_DELAY5 (1 << 0) +#define S3C24A0_IICLC_SDA_DELAY10 (2 << 0) +#define S3C24A0_IICLC_SDA_DELAY15 (3 << 0) +#define S3C24A0_IICLC_SDA_DELAY_MASK (3 << 0) + +#define S3C24A0_IICLC_FILTER_ON (1<<2) + +#endif /* __ASM_ARCH_REGS_IIC_H */ again, duplicated code, i'll bet I find a duplicated driver somewhere down the patch. diff --git a/include/asm-arm/arch-s3c24a0/regs-iis.h b/include/asm-arm/arch-s3c24a0/regs-iis.h new file mode 100644 index 0000000..d6a5d56 --- /dev/null +++ b/include/asm-arm/arch-s3c24a0/regs-iis.h @@ -0,0 +1,67 @@ +/* linux/include/asm/arch-s3c24a0/regs-iis.h + * + * Id: regs-iis.h + * + * S3C24A0 IIS register definitions + * + * 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/regs-iis.h, written by + * Ben Dooks + * + */ + +#ifndef __ASM_ARCH_REGS_IIS_H +#define __ASM_ARCH_REGS_IIS_H + +#define S3C24A0_IISCON (S3C24A0_VA_IIS + 0x00) + +#define S3C24A0_IISCON_LRINDEX (1<<8) +#define S3C24A0_IISCON_TXFIFORDY (1<<7) +#define S3C24A0_IISCON_RXFIFORDY (1<<6) +#define S3C24A0_IISCON_TXDMAEN (1<<5) +#define S3C24A0_IISCON_RXDMAEN (1<<4) +#define S3C24A0_IISCON_TXIDLE (1<<3) +#define S3C24A0_IISCON_RXIDLE (1<<2) +#define S3C24A0_IISCON_PRESCALE (1<<1) /* IIS Prescaler Enable */ +#define S3C24A0_IISCON_IISEN (1<<0) + +#define S3C24A0_IISMOD (S3C24A0_VA_IIS + 0x04) + +#define S3C24A0_IISMOD_SLAVE (1<<8) +#define S3C24A0_IISMOD_MASTER (0<<8) +#define S3C24A0_IISMOD_NOXFER (0<<6) +#define S3C24A0_IISMOD_RXMODE (1<<6) +#define S3C24A0_IISMOD_TXMODE (2<<6) +#define S3C24A0_IISMOD_TXRXMODE (3<<6) +#define S3C24A0_IISMOD_LR_LLOW (0<<5) +#define S3C24A0_IISMOD_LR_RLOW (1<<5) +#define S3C24A0_IISMOD_IIS (0<<4) +#define S3C24A0_IISMOD_MSB (1<<4) +#define S3C24A0_IISMOD_8BIT (0<<3) +#define S3C24A0_IISMOD_16BIT (1<<3) +#define S3C24A0_IISMOD_256FS (0<<2) +#define S3C24A0_IISMOD_384FS (1<<2) +#define S3C24A0_IISMOD_16FS (0<<0) +#define S3C24A0_IISMOD_32FS (1<<0) +#define S3C24A0_IISMOD_48FS (2<<0) + +#define S3C24A0_IISPSR (S3C24A0_VA_IIS + 0x08) + +#define S3C24A0_IISFCON (S3C24A0_VA_IIS + 0x0c) + +#define S3C24A0_IISFCON_TXDMA (1<<15) +#define S3C24A0_IISFCON_RXDMA (1<<14) +#define S3C24A0_IISFCON_TXENABLE (1<<13) +#define S3C24A0_IISFCON_RXENABLE (1<<12) + +#define S3C24A0_IISFIFO (S3C24A0_VA_IIS + 0x10) +#define S3C24A0_PA_IIS_FIFO 0x44700010 + +#endif /* __ASM_ARCH_REGS_IIS_H */ + diff --git a/include/asm-arm/arch-s3c24a0/regs-irda.h b/include/asm-arm/arch-s3c24a0/regs-irda.h same comment as above... ASoC should be able to support this device if it is close enough to the extand s3c24xx code. new file mode 100644 index 0000000..d20ad4a --- /dev/null +++ b/include/asm-arm/arch-s3c24a0/regs-irda.h @@ -0,0 +1,150 @@ +/* linux/include/asm/arch-s3c24a0/regs-irda.h + * + * Id: regs-irda.h + * + * S3C24A0 Irda Controller register definitions + * + * Copyright (C) 2005, Naushad + * 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_REGS_IRDA_H +#define ___ASM_ARCH_REGS_IRDA_H + +#define S3C24A0_IRDAREG(x) ((x) + S3C24A0_VA_IRDA) + +#define S3C24A0_IRDACNT S3C24A0_IRDAREG(0x00) // Control +#define S3C24A0_IRDAMDR S3C24A0_IRDAREG(0x04) // Mode Definition +#define S3C24A0_IRDACNF S3C24A0_IRDAREG(0x08) // Intr/DMA Config +#define S3C24A0_IRDAIER S3C24A0_IRDAREG(0x0C) // Intrerrupt Enable +#define S3C24A0_IRDAIIR S3C24A0_IRDAREG(0x10) // Interrupt Identification +#define S3C24A0_IRDALSR S3C24A0_IRDAREG(0x14) // Line Status +#define S3C24A0_IRDAFCR S3C24A0_IRDAREG(0x18) // Fifo Control +#define S3C24A0_IRDAPLR S3C24A0_IRDAREG(0x1C) // Preamble Length +#define S3C24A0_IRDARBR S3C24A0_IRDAREG(0x20) // Tx n Rx Buf Reg +#define S3C24A0_IRDATXNO S3C24A0_IRDAREG(0x24) // Tx Fifo Count +#define S3C24A0_IRDARXNO S3C24A0_IRDAREG(0x28) // Rx Fifo Count +#define S3C24A0_IRDATXFLL S3C24A0_IRDAREG(0x2C) // Tx Frame Lenght Low +#define S3C24A0_IRDATXFLH S3C24A0_IRDAREG(0x30) // Tx Frame Length High +#define S3C24A0_IRDARXFLL S3C24A0_IRDAREG(0x34) // Rx Frame Lenght Low +#define S3C24A0_IRDARXFLH S3C24A0_IRDAREG(0x38) // Rx Frame Length High +//#define S3C24A0_IRDATIME S3C24A0_IRDAREG(0x3c) + +/* + * Irda Control register + */ +#define S3C24A0_IRDACNT_TXENABLE (1 << 7) +#define S3C24A0_IRDACNT_RXENABLE (1 << 6) +#define S3C24A0_IRDACNT_CORELOOP (1 << 5) +#define S3C24A0_IRDACNT_MIR_HALFMODE (1 << 4) +#define S3C24A0_IRDACNT_SEND_IRPULSE (1 << 3) +#define S3C24A0_IRDACNT_FRAME_ABORT (1 << 1) +#define S3C24A0_IRDACNT_SDBW (1 << 0) + + +/* + * Irda Mode Definiton register + */ +#define S3C24A0_IRDAMDR_SIP_SELECT (1 << 4) +#define S3C24A0_IRDAMDR_TEMIC_SELECT (1 << 3) +#define S3C24A0_IRDAMDR_MODE_FIR (1 << 2) +#define S3C24A0_IRDAMDR_MODE_MIR (1 << 1) + +/* + * Irda Interrupt DMA Configuration register + */ + +#define S3C24A0_IRDACNF_DMA_MODEBIT (3 << 2) + +#define S3C24A0_IRDACNF_DMA_ENABLE (1 << 3) +#define S3C24A0_IRDACNF_DMA_RXMODE (1 << 2) +#define S3C24A0_IRDACNF_DMA_TXMODE (0 << 2) +#define S3C24A0_IRDACNF_INT_ENABLE (1 << 0) + +/* + * Irda Interrupt Enable register + */ + +#define S3C24A0_IRDAIER_LASTBYTE_2RXFIFO (1 << 7) +#define S3C24A0_IRDAIER_ERRORIND (1 << 6) +#define S3C24A0_IRDAIER_TX_UNDERRUN (1 << 5) +#define S3C24A0_IRDAIER_LASTBYTE_DETECT (1 << 4) +#define S3C24A0_IRDAIER_RX_OVERRUN (1 << 3) +#define S3C24A0_IRDAIER_LASTBYTE_READ (1 << 2) +#define S3C24A0_IRDAIER_TXFIFO_BELOWTHRESH (1 << 1) +#define S3C24A0_IRDAIER_RXFIFO_OVERTHRESH (1 << 0) + +/* + * Irda Interrupt Identification register + */ + +#define S3C24A0_IRDAIIR_LASTBYTE_2RXFIFO (1 << 7) +#define S3C24A0_IRDAIIR_ERRORIND (1 << 6) +#define S3C24A0_IRDAIIR_TX_UNDERRUN (1 << 5) +#define S3C24A0_IRDAIIR_LASTBYTE_DETECT (1 << 4) +#define S3C24A0_IRDAIIR_RX_OVERRUN (1 << 3) +#define S3C24A0_IRDAIIR_LASTBYTE_READ (1 << 2) +#define S3C24A0_IRDAIIR_TXFIFO_BELOWTHRESH (1 << 1) +#define S3C24A0_IRDAIIR_RXFIFO_OVERTHRESH (1 << 0) + +/* + * Irda Line Status register + */ + +#define S3C24A0_IRDALSR_TX_EMPTY (1 << 7) +#define S3C24A0_IRDALSR_LASTBYTE_RECEIVED (1 << 5) +#define S3C24A0_IRDALSR_FRAMELEN_ERROR (1 << 4) +#define S3C24A0_IRDALSR_PHY_ERROR (1 << 3) +#define S3C24A0_IRDALSR_CRC_ERROR (1 << 2) +#define S3C24A0_IRDALSR_RXFIFO_EMPTY (1 << 0) + +/* + * Irda Fifo Control register + */ +#define S3C24A0_IRDAFCR_FIFOTRIG_BITS (3 << 6) + +#define S3C24A0_IRDAFCR_RXFIFO64TRIG_56 (3 << 6) +#define S3C24A0_IRDAFCR_RXFIFO64TRIG_32 (2 << 6) +#define S3C24A0_IRDAFCR_RXFIFO64TRIG_16 (1 << 6) +#define S3C24A0_IRDAFCR_RXFIFO64TRIG_01 (0 << 6) + +#define S3C24A0_IRDAFCR_RXFIFO16TRIG_14 (3 << 6) +#define S3C24A0_IRDAFCR_RXFIFO16TRIG_08 (2 << 6) +#define S3C24A0_IRDAFCR_RXFIFO16TRIG_04 (1 << 6) +#define S3C24A0_IRDAFCR_RXFIFO16TRIG_01 (0 << 6) + +#define S3C24A0_IRDAFCR_FIFO_SIZEBIT (1 << 5) +#define S3C24A0_IRDAFCR_FIFO_SIZE64 (1 << 5) +#define S3C24A0_IRDAFCR_FIFO_SIZE16 (0 << 5) +#define S3C24A0_IRDAFCR_TXFIFO_CLEAR (1 << 4) +#define S3C24A0_IRDAFCR_RXFIFO_CLEAR (1 << 3) +#define S3C24A0_IRDAFCR_TXFIFO_RESET (1 << 2) +#define S3C24A0_IRDAFCR_RXFIFO_RESET (1 << 1) +#define S3C24A0_IRDAFCR_FIFO_ENABLE (1 << 0) + +/* + * Irda Preamble Lenth register + */ +#define S3C24A0_IRDAPLR_FIRPREAMB_16 (0 << 6) +#define S3C24A0_IRDAPLR_FIRPREAMB_04 (1 << 6) +#define S3C24A0_IRDAPLR_FIRPREAMB_08 (2 << 6) +#define S3C24A0_IRDAPLR_FIRPREAMB_32 (3 << 6) + +#define S3C24A0_IRDAPLR_TXFIFO64TRIG_08 (3 << 4) +#define S3C24A0_IRDAPLR_TXFIFO64TRIG_32 (2 << 4) +#define S3C24A0_IRDAPLR_TXFIFO64TRIG_48 (1 << 4) + +#define S3C24A0_IRDAPLR_TXFIFO16TRIG_02 (3 << 4) +#define S3C24A0_IRDAPLR_TXFIFO16TRIG_08 (2 << 4) +#define S3C24A0_IRDAPLR_TXFIFO16TRIG_12 (1 << 4) + +#define S3C24A0_IRDAPLR_MIRSF_BITS (0xf << 0) + + +#endif /* ___ASM_ARCH_REGS_IRDA_H */ diff --git a/include/asm-arm/arch-s3c24a0/regs-irq.h b/include/asm-arm/arch-s3c24a0/regs-irq.h new file mode 100644 index 0000000..99039a1 --- /dev/null +++ b/include/asm-arm/arch-s3c24a0/regs-irq.h @@ -0,0 +1,33 @@ +/* linux/include/asm/arch-s3c24a0/regs-irq.h + * + * Id: regs-irq.h + * + * S3C24A0 Interrupt Controller register definitions + * + * 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/regs-irq.h, written by + * Ben Dooks + * + */ + +#ifndef ___ASM_ARCH_REGS_IRQ_H +#define ___ASM_ARCH_REGS_IRQ_H + +#define S3C24A0_INTREG(x) ((x) + S3C24A0_VA_IRQ) + +#define S3C24A0_SRCPND S3C24A0_INTREG(0x00) +#define S3C24A0_INTMOD S3C24A0_INTREG(0x04) +#define S3C24A0_INTMSK S3C24A0_INTREG(0x08) +#define S3C24A0_PRIORITY S3C24A0_INTREG(0x0c) +#define S3C24A0_INTPND S3C24A0_INTREG(0x10) +#define S3C24A0_INTOFFSET S3C24A0_INTREG(0x14) +#define S3C24A0_SUBSRCPND S3C24A0_INTREG(0x18) +#define S3C24A0_INTSUBMSK S3C24A0_INTREG(0x1c) + +#endif /* ___ASM_ARCH_REGS_IRQ_H */ diff --git a/include/asm-arm/arch-s3c24a0/regs-keyif.h b/include/asm-arm/arch-s3c24a0/regs-keyif.h new file mode 100644 index 0000000..6a7024e --- /dev/null +++ b/include/asm-arm/arch-s3c24a0/regs-keyif.h @@ -0,0 +1,60 @@ +/* linux/include/asm/arch-s3c24a0/regs-keyif.h + * + * Id: regs-keyif.h + * + * S3C24A0 Key Interface register definitions + * + * 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_REGS_KEYIF_H +#define __ASM_ARCH_REGS_KEYIF_H + +#include "bitfield.h" + + +/* + * KeyIF - keypad interface + * chapter 28 + */ +#define S3C24A0_KIFREG(x) ((x) + S3C24A0_VA_KEYIF) + +#define KEYDAT S3C24A0_KIFREG(0x00) +#define KEYINTC S3C24A0_KIFREG(0x04) +#define KEYFLT0 S3C24A0_KIFREG(0x08) +#define KEYFLT1 S3C24A0_KIFREG(0x0C) +#define KEYMAN S3C24A0_KIFREG(0x10) + +#define fKEYDAT_KEYS Fld(5,0) /* RO : intput decoding data */ +#define KEYDAT_KEYS FExtr(__raw_readl(KEYDAT), fKEYDAT_KEYS) +#define KEYDAT_KEYVAL (1<<5) /* RO : 0=valid, 1=invalid */ +#define KEYDAT_KEYCLR (1<<6) /* WO : 0=noaction, 1=clear */ +#define KEYDAT_KEYEN (1<<7) /* RW : 0=disable, 1=enable */ +#define fKEYINTLV Fld(3,0) +#define KEYINTLV_LL 0 /* low level */ +#define KEYINTLV_HL 1 /* high level */ +#define KEYINTLV_RE 2 /* rising edge */ +#define KEYINTLV_FE 4 /* falling edge */ +#define KEYINTLV_BE 6 /* both edges */ +#define KEYINTLV(x) FInsrt((x), fKEYINTLV) +#define KEYINTEN (1<<3) /* interrupt enable */ +#define fKEYFLT_SELCLK Fld(1,0) +#define SELCLK_RTC 0 +#define SELCLK_GCLK 1 +#define KEYFLT_SELCLK(x) FInsrt((x),fKEYFLT_SELCLK) +#define KEYFLT_FILEN (1<<1) +#define fKEYFLT_WIDTH Fld( 14,0) +#define KEYFLT_WIDTH(x) FInsrt((x), fKEYFLT_WIDTH) +#define KEYP_STAT (((__raw_readl(S3C24A0_GPDAT) & 0x00FF0000) >> 16 ) & 0x7D ) + +#endif /* __ASM_ARCH_REGS_KEYIF_H */ + + again, use of bitfield, as well as the definiton of KEYP_STAT which is implicitly reading a value. diff --git a/include/asm-arm/arch-s3c24a0/regs-lcd.h b/include/asm-arm/arch-s3c24a0/regs-lcd.h new file mode 100644 index 0000000..238a36c --- /dev/null +++ b/include/asm-arm/arch-s3c24a0/regs-lcd.h @@ -0,0 +1,213 @@ +/* linux/include/asm/arch-s3c24a0/regs-lcd.h + * + * Id: regs-lcd.h + * + * S3C24A0 LCD register definitions + * + * 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/regs-lcd.h, written by + * Ben Dooks + * + */ + +#ifndef ___ASM_ARCH_REGS_LCD_H +#define ___ASM_ARCH_REGS_LCD_H + +#include "bitfield.h" + +#define S3C24A0_LCDREG(x) ((x) + S3C24A0_VA_LCD) + +/* LCD control registers */ +#define S3C24A0_LCDCON1 S3C24A0_LCDREG(0x00) /* LCD CONTROL 1 */ +#define S3C24A0_LCDCON2 S3C24A0_LCDREG(0x04) /* LCD CONTROL 2 */ +#define S3C24A0_LCDTCON1 S3C24A0_LCDREG(0x08) /* LCD TIME CONTROL 1 */ +#define S3C24A0_LCDTCON2 S3C24A0_LCDREG(0x0c) /* LCD TIME CONTROL 2 */ +#define S3C24A0_LCDTCON3 S3C24A0_LCDREG(0x10) /* LCD TIME CONTROL 3 */ +#define S3C24A0_LCDOSD1 S3C24A0_LCDREG(0x14) /* LCD OSD CONTROL REGISTER */ +#define S3C24A0_LCDOSD2 S3C24A0_LCDREG(0x18) /* Foreground image(OSD Image) left top position set */ +#define S3C24A0_LCDOSD3 S3C24A0_LCDREG(0x1c) /* Foreground image(OSD Image) right bottom position set */ +#define S3C24A0_LCDSADDRB1 S3C24A0_LCDREG(0x20) /* Frame buffer start address 1 (Background buffer 1) */ +#define S3C24A0_LCDSADDRB2 S3C24A0_LCDREG(0x24) /* Frame buffer start address 2 (Background buffer 2) */ +#define S3C24A0_LCDSADDRF1 S3C24A0_LCDREG(0x28) /* Frame buffer start address 1 (Foreground buffer 1) */ +#define S3C24A0_LCDSADDRF2 S3C24A0_LCDREG(0x2c) /* Frame buffer start address 2 (Foreground buffer 2) */ +#define S3C24A0_LCDEADDRB1 S3C24A0_LCDREG(0x30) /* Frame buffer end address 1 (Background buffer 1) */ +#define S3C24A0_LCDEADDRB2 S3C24A0_LCDREG(0x34) /* Frame buffer end address 2 (Background buffer 2) */ +#define S3C24A0_LCDEADDRF1 S3C24A0_LCDREG(0x38) /* Frame buffer end address 1 (Foreground buffer 1) */ +#define S3C24A0_LCDEADDRF2 S3C24A0_LCDREG(0x3c) /* Frame buffer end address 2 (Foreground buffer 2) */ +#define S3C24A0_LCDVSCRB1 S3C24A0_LCDREG(0x40) /* Virture Screen OFFSIZE and PAGE WIDTH (Background buffer 1) */ +#define S3C24A0_LCDVSCRB2 S3C24A0_LCDREG(0x44) /* Virture Screen OFFSIZE and PAGE WIDTH (Background buffer 2) */ +#define S3C24A0_LCDVSCRF1 S3C24A0_LCDREG(0x48) /* Virture Screen OFFSIZE and PAGE WIDTH (Foreground buffer 1) */ +#define S3C24A0_LCDVSCRF2 S3C24A0_LCDREG(0x4c) /* Virture Screen OFFSIZE and PAGE WIDTH (Foreground buffer 2) */ +#define S3C24A0_LCDINTCON S3C24A0_LCDREG(0x50) /* LCD Interrupt Control */ +#define S3C24A0_LCDKEYCON S3C24A0_LCDREG(0x54) /* COLOR KEY CONTROL 1 */ +#define S3C24A0_LCDKEYVAL S3C24A0_LCDREG(0x58) /* COLOR KEY CONTROL 2 */ +#define S3C24A0_LCDBGCON S3C24A0_LCDREG(0x5c) /* Background color Control */ +#define S3C24A0_LCDFGCON S3C24A0_LCDREG(0x60) /* Foreground color Control */ +#define S3C24A0_LCDDITHCON S3C24A0_LCDREG(0x64) /* LCD Dithering control active Matrix */ + +/* LCDCON1 */ +#define fBURSTLEN Fld(2,28) /* DMA's BURST length selection */ +#define BURSTLEN4 FInsrt(0x2, fBURSTLEN) +#define BURSTLEN8 FInsrt(0x1, fBURSTLEN) +#define BURSTLEN16 FInsrt(0x0, fBURSTLEN) +#define BDBCON_BUF1 (0 << 21) /* Active frame slect control background image */ +#define BDBCON_BUF2 (1 << 21) /* it will be adoted from next frame data */ +#define FDBCON_BUF1 (0 << 20) /* Active frame select control foreground image */ +#define FDBCON_BUF2 (1 << 20) /* it will adopted from next frame data */ +#define DIVEN (1 << 19) /* 1:ENABLE 0:Disable */ +#define DIVDIS (0 << 19) /* 0:disable */ +#define fCLKVAL Fld(6,13) +#define CLKVALMSK FMsk(fCLKVAL) /* clk value bit clear */ +#define CLKVAL(x) FInsrt((x), fCLKVAL) /* VCLK = HCLK / [(CLKVAL+1)x2] */ +#define CLKDIR_DIVIDE (1 << 12) /* Select the clk src as 0:direct or 1:divide using CLKVAl register */ +#define CLKDIR_DIRECT (0 << 12) /* Select the clk src as 0:direct or 1:divide using CLKVAl register */ +#define fPNRMODE Fld(2,9) /* Select Disaplay mode */ +#define PNRMODE_PRGB FInsrt(0x00, fPNRMODE) /* parallel RGB */ +#define PNRMODE_PBGR FInsrt(0x01, fPNRMODE) /* parallel BGR */ +#define PNRMODE_SRGB FInsrt(0x02, fPNRMODE) /* Serial RGB */ +#define PNRMODE_SBGR FInsrt(0x03, fPNRMODE) /* Serial RGB */ +#define fBPPMODEF Fld(3,6) /* SELECT THE BPP MODE FOR FOREGROUND IMAGE (OSD) */ +#define BPPMODEF_8_P FInsrt(0x3, fBPPMODEF) /* 8BPP palettized */ +#define BPPMODEF_8_NP FInsrt(0x4, fBPPMODEF) /* 8BPP non palettized RGB-3:3:2 */ +#define BPPMODEF_565 FInsrt(0x5, fBPPMODEF) /* 16BPP NON palettized RGB-5:6:5 */ +#define BPPMODEF_5551 FInsrt(0x6, fBPPMODEF) /* 16BPP NON palettized RGB-5:5:5:1 */ +#define BPPMODEF_18_UP FInsrt(0x7, fBPPMODEF) /* unpaked 18BPP non-palettized */ +#define fBPPMODEB Fld(4,2) /* select the BPP mode for fore ground image */ +#define MPPMODEB_1 FInsrt(0x00, fBPPMODEB) /* 1bpp */ +#define MPPMODEB_2 FInsrt(0x01, fBPPMODEB) /* 2bpp */ +#define MPPMODEB_4 FInsrt(0x02, fBPPMODEB) /* 4bpp */ +#define MPPMODEB_8 FInsrt(0x03, fBPPMODEB) /* 8bpp palettized */ +#define MPPMODEB_8N FInsrt(0x04, fBPPMODEB) /* 8bpp non palettized 3:3:2 */ +#define MPPMODEB_565 FInsrt(0x05, fBPPMODEB) /* 16bpp non palettized 5:6:5 */ +#define MPPMODEB_5551 FInsrt(0x06, fBPPMODEB) /* 16bpp non palettized 5:5:5:1 */ +#define MPPMODEB_18 FInsrt(0x07, fBPPMODEB) /* unpacked 18bpp */ +#define ENVID (1 << 1) /* 0:Disable 1:Enable LCD video output and logic immediatly */ +#define ENVID_F (1 << 0) /* 0:Dis 1:Ena wait until Current frame end. */ + +/* LCDCON2 */ +#define fPALFRM Fld(2,9) /* this bit determines the size of the palette data */ +#define PALFRM_666 FInsrt(0x01, fPALFRM) /* 18 BIT RGB-6:6:6 */ +#define PALFRM_565 FInsrt(0x02, fPALFRM) /* 16 BIT RGB-5:6:5 */ +#define PALFRM_5551 FInsrt(0x03, fPALFRM) /* 16 BIT RGB-5:5:5:1 */ +#define IVCLK_RISING (1 << 7) /* this bit controls the polarity of the VCLK active edge */ +#define IVCLK_FALLING (0 << 7) /* 1 :rising edge 0: falling edge */ +#define IHSYNC_INVERT (1 << 6) /* HSYNC polarity inverted */ +#define IHSYNC_NORMAL (0 << 6) /* HSYNC polarity normal */ +#define IVSYNC_INVERT (1 << 5) /* VSYNC polarity inverted */ +#define IVSYNC_NORMAL (0 << 5) /* VSYNC polarity normal */ +#define IVDE_INVERT (1 << 3) /* DE polarity inverted */ +#define IVDE_NORMAL (0 << 3) /* DE polarity normal */ +#define BITSWP_EN (1 << 2) /* 1:BIT Swap Enable */ +#define BITSWP_DIS (0 << 2) /* 0:BIT Swap Disable */ +#define BYTESWP_EN (1 << 1) /* 1:BYTE Swap Enable */ +#define BUTESWP_DIS (0 << 1) /* 0:BYTE Swap Disable */ +#define HAWSWP_EN (1 << 0) /* 1:HALF WORD Swap Enable */ +#define HAWSWP_DIS (0 << 0) /* 0:HALF WORD swap Disable */ + +/* LCD Time Control 1 Register */ +#define VBPD(x) FInsrt((x), Fld(8,16)) /* VSync Back porch */ +#define VFPD(x) FInsrt((x), Fld(8, 8)) /* VSync Front porch */ +#define VSPW(x) FInsrt((x), Fld(8, 0)) /* VSync level width */ +/* LCD Time Control 2 Register */ +#define HBPD(x) FInsrt((x), Fld(8,16)) /* VSync Back porch */ +#define HFPD(x) FInsrt((x), Fld(8, 8)) /* VSync Front porch */ +#define HSPW(x) FInsrt((x), Fld(8, 0)) /* VSync level width */ +/* LCD Time Control 3 register */ +#define LINEVAL(x) FInsrt((x), Fld(11,11)) /* these bits determine the vertical size of lcd panel */ +#define HOZVAL(x) FInsrt((x), Fld(11, 0)) /* these bits determine the horizontal size of lcd panel*/ /* LCD OSD Control 1 register */ +#define OSDEN (1 << 9) /* OSD Enable */ +#define OSDDIS (0 << 9) /* OSD Disable */ +#define OSD_BLD_PIX (1 << 8) /* BLENDING MODE Per pixel blending (18 BPP only) */ +#define OSD_BLD_PLANE (0 << 8) /* Per plane blending (8/16/18 BPP mode) */ +#define OSD_ALPHA(x) FInsrt((x), Fld(8,0)) /* 8-bit Alpha value for Per plane defined by Equation 28-1. */ +/* LCD OSD Control 2 Register */ +#define OSD_LEFTTOP_X(x) FInsrt((x), Fld(11,11)) /*Horizontal screen coordinate for left top pixel of OSD image */ +#define OSD_LEFTTOP_Y(x) FInsrt((y), Fld(11, 0)) /* Vertical screen coordinate for left top pixel of OSD image */ +/* LCD OSD Control 3 Register */ +/*OSD_RIGHTBOT_X,_Y <= LCD Panel size of X, Y */ +#define OSD_RIGHTBOT_X(x) FInsrt((x), Fld(11,11)) /*Hor scr coordinate for right bottom pixel of OSD image. */ +#define OSD_RIGHTBOT_Y(y) FInsrt((y), Fld(11, 0)) /* Ver scr coordinate for right bottom pixel of OSD image. */ + +/* FRAME Buffer start address Register + LCDSADDRB1 Frame buffer start address register for Background buffer 1 + LCDSADDRB2 Frame buffer start address register for Background buffer 2 + LCDSADDRF1 Frame buffer start address register for Foreground(OSD) buffer 1 + LCDSADDRF2 Frame buffer start address register for Foreground(OSD) buffer 2*/ +#define LCDBANK(x) FInsrt((x), Fld( 8,24)) /* the bank location for the video buffer in the system memory. */ +#define LCDBASEU(x) FInsrt((x), Fld(24, 0)) /* the start address of the LCD frame buffer. */ +/* FRAME BUFFER END address Register + LCDEADDRB1 Frame buffer end address register for Background buffer 1 + LCDEADDRB2 Frame buffer end address register for Background buffer 2 + LCDEADDRF1 Frame buffer end address register for Foreground(OSD) buffer 1 + LCDEADDRF2 Frame buffer end address register for Foreground(OSD) buffer 2 + LCDBASEL = LCDBASEU + (PAGEWIDTH+OFFSIZE) x (LINEVAL+1) */ +#define LCDBASEL(x) FInsrt((x), Fld(24,0)) /* the end address of the LCD frame buffer. */ +/* Virture Screen offsize and page width registers + LCDVSCRB1 Virtual screen OFFSIZE and PAGEWIDTH for Background buffer 1 + LCDVSCRB2 Virtual screen OFFSIZE and PAGEWIDTH for Background buffer 2 + LCDVSCRF1 Virtual screen OFFSIZE and PAGEWIDTH for Foreground(OSD) buffer 1 + LCDVSCRF2 Virtual screen OFFSIZE and PAGEWIDTH for Foreground(OSD) buffer 2*/ +#define OFFSIZE(x) FInsrt((x), Fld(13,13)) /* Virtual screen offset size (the number of byte). */ +#define PAGEWIDTH(x) FInsrt((x), Fld(13, 0)) /* Virtual screen page width (the number of byte). */ + +/* LCD Interrupt Control Register */ +#define fFRAME_INT2 Fld(2,10) /* LCD Frame Interrupt 2 at start of */ +#define FRAMESEL0_BP FInsrt(0x0, fFRAME_INT2) /* BACK Porch */ +#define FRAMESEL0_VS FInsrt(0x1, fFRAME_INT2) /* VSYNC */ +#define FRAMESEL0_ACT FInsrt(0x2, fFRAME_INT2) /* ACTIVE */ +#define FRAMESEL0_FP FInsrt(0x3, fFRAME_INT2) /* FRONT */ +#define fFRAME_INT1 Fld(2,8) /* LCD Frame Interrupt 1 at start of */ +#define FRAMESEL1_BP FInsrt(0x1, fFRAME_INT1) /* BACK Porch */ +#define FRAMESEL1_VS FInsrt(0x2, fFRAME_INT1) /* VSYNC */ +#define FRAMESEL1_FP FInsrt(0x3, fFRAME_INT1) /* FRONTPorch */ +#define INTFRAME_EN (1 << 7) /* LCD Frame interrupt Enable */ +#define INTFRAME_DIS (0 << 7) /* LCD Frame interrupt Disable */ +#define fFIFOSEL Fld(2,5) /* LCD FIFO INTERRUPT SELECT BIT */ +#define FIFO_ALL FInsrt(0x00, fFIFOSEL) /* All fifi or CASE */ +#define FIFO_BG FInsrt(0x01, fFIFOSEL) /* Background only */ +#define FIFO_FG FInsrt(0x02, fFIFOSEL) /* FOREGROUND FIFO ONLY */ +#define fFIFOLEVEL Fld(3,2) /* LCD FIFO interrupt level select 1~128 word */ +#define FIFO_32W FInsrt(0x00, fFIFOLEVEL) /* 32 WORD LEFT */ +#define FIFO_64W FInsrt(0x01, fFIFOLEVEL) /* 64 WORD */ +#define FIFO_96W FInsrt(0x02, fFIFOLEVEL) /* 96 WORD */ +#define FIFO_OR FInsrt(0x03, fFIFOLEVEL) /* 32,64,96 WORD */ +#define INTFIFO_EN (1<<1) +#define INTFIFO_DIS (1<<1) +#define LCD_INTEN (1 << 0) /* LCD interrupt Enable */ +#define LCD_INTDIS (0 << 0) /* LCD Interrupt Disable */ +/* LCD color key LCDKEYCON 1 register */ +#define KEYEN (1 << 25) /* color key enable, blending disable */ +#define KEYDIS (0 << 25) /* color key disable, blending enable */ +#define DIRCON_FORE (1 << 24) /* pixel from foreground image is displayed (only in OSD area) */ +#define DIRCON_BACK (0 << 24) /* pixel from background image is displayed (only in OSD area) */ +#define COMPKEY(x) FInsrt((X), Fld(24,0)) /* Each bit is correspond to the COLVAL[23:0]. */ +/* color key 2 register LCDCOLVAL */ +#define COLVAL(x) FInsrt((x), Fld(24,0)) /* Color key value for the transparent pixel effect. */ +/* Background Color MAP */ +#define BGCOLEN (1 << 24) /* Background color mapping control bit enable */ +#define BGCOLDIS (0 << 24) /* Background color mapping control bit disable */ +#define BGCOLOR(x) FInsrt((x), Fld(24,0)) /* Color Value */ +/* Foreground Color MAP LCDFGCON */ +#define FGCOLEN (1 << 24) /* Foreground color mapping control bit Enable. */ +#define FGCOLDIS (0 << 24) /* Foreground color mapping control bit Disable */ +#define FGCOLOR(x) FInsrt((x), Fld(24,0)) /* Color Value */ +/* Dithering Contrl 1 Register LCD DITHERING MODE */ +#define RDITHPOS_6BIT FInsrt(0x01, Fld(2,5)) /* Red Dither bit control 6bit */ +#define RDITHPOS_5BIT FInsrt(0x02, Fld(2,5)) /* Red Dither bit control 5bit */ +#define GDITHPOS_6BIT FInsrt(0x01, Fld(2,3)) /* Green Dither bit control 6bit */ +#define GDITHPOS_5BIT FInsrt(0x02, Fld(2,3)) /* Green Dither bit control 5bit */ +#define BDITHPOS_6BIT FInsrt(0x01, Fld(2,5)) /* Blue Dither bit control 6bit */ +#define BDITHPOS_5BIT FInsrt(0x02, Fld(2,5)) /* Blue Dither bit control 5bit */ +#define DITHEN (1 << 0) /* Dithering Enable bit */ +#define DITHDIS (0 << 0) /* Dithering Disable bit */ + +#endif /* ___ASM_ARCH_REGS_LCD_H */ + + + This is (1) unreadable and (2) trailing whitespace. diff --git a/include/asm-arm/arch-s3c24a0/regs-mem.h b/include/asm-arm/arch-s3c24a0/regs-mem.h new file mode 100644 index 0000000..651ce12 --- /dev/null +++ b/include/asm-arm/arch-s3c24a0/regs-mem.h @@ -0,0 +1,34 @@ +/* linux/include/asm/arch-s3c24a0/regs-mem.h + * + * Id: regs-mem.h + * + * S3C24A0 Memory Control register definitions + * + * 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/regs-mem.h, written by + * Ben Dooks + * + */ + +#ifndef __ASM_ARM_MEMREGS_H +#define __ASM_ARM_MEMREGS_H + +/* + * SROM Bank (chapter 2) for CS8900A + */ +#define S3C24A0_SROMREG(x) ((x) + S3C24A0_VA_SROM) +#define SROM_BW S3C24A0_SROMREG(0x00) +#define SROM_BC1 S3C24A0_SROMREG(0x08) + +/* CS8900A */ +#define SMDK_CS8900_IRQ IRQ_EINT13 +#define SMDK_CS8900_VIO 0xf0000000 +#define SMDK_CS8900_PIO (0x04000000 | (1<<24)) + +#endif /* __ASM_ARM_MEMREGS_H */ diff --git a/include/asm-arm/arch-s3c24a0/regs-nand.h b/include/asm-arm/arch-s3c24a0/regs-nand.h new file mode 100644 index 0000000..78fe5a3 --- /dev/null +++ b/include/asm-arm/arch-s3c24a0/regs-nand.h @@ -0,0 +1,506 @@ +/* linux/include/asm/arch-s3c24a0/regs-nand.h + * + * Id: regs-nand.h + * + * S3C24A0 NAND register definitions + * + * 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_ARM_REGS_NAND +#define __ASM_ARM_REGS_NAND + +#include "bitfield.h" + +#define S3C24A0_NFREG(x) (x) + +#define S3C24A0_NFCONF_EN (1<<15) +#define S3C24A0_NFCONF_512BYTE (1<<14) +#define S3C24A0_NFCONF_4STEP (1<<13) +#define S3C24A0_NFCONF_INITECC (1<<12) +#define S3C24A0_NFCONF_TACLS(x) ((x)<<12) +#define S3C24A0_NFCONF_TWRPH0(x) ((x)<<8) +#define S3C24A0_NFCONF_TWRPH1(x) ((x)<<4) + +#define S3C24A0_NFCONT_nFCE (1<<7) + + /* Flash_RnB0 */ +#define S3C24A0_NFSTAT_BUSY (1<<10) + + +#define S3C24A0_NFCONF S3C24A0_NFREG(0x00) +#define S3C24A0_NFCONT S3C24A0_NFREG(0x04) +#define S3C24A0_NFCMMD S3C24A0_NFREG(0x08) +#define S3C24A0_NFADDR S3C24A0_NFREG(0x0c) +#define S3C24A0_NFDATA S3C24A0_NFREG(0x10) +#define S3C24A0_NFMECCDATA0 S3C24A0_NFREG(0x14) +#define S3C24A0_NFMECCDATA1 S3C24A0_NFREG(0x18) +#define S3C24A0_NFMECCDATA2 S3C24A0_NFREG(0x1c) +#define S3C24A0_NFMECCDATA3 S3C24A0_NFREG(0x20) +#define S3C24A0_NFSECCDATA0 S3C24A0_NFREG(0x24) +#define S3C24A0_NFSECCDATA1 S3C24A0_NFREG(0x28) +#define S3C24A0_NFSTAT S3C24A0_NFREG(0x2c) +#define S3C24A0_NFESTAT0 S3C24A0_NFREG(0x30) +#define S3C24A0_NFESTAT1 S3C24A0_NFREG(0x34) +#define S3C24A0_NFMECC0 S3C24A0_NFREG(0x38) +#define S3C24A0_NFMECC1 S3C24A0_NFREG(0x3c) +#define S3C24A0_NFSECC S3C24A0_NFREG(0x40) +#define S3C24A0_NFSBLK S3C24A0_NFREG(0x44) +#define S3C24A0_NFEBLK S3C24A0_NFREG(0x48) + + +/* + * NFCONF + */ +#define fNFCONF_AdvanceFlash Fld(1,22) +#define fNFCONF_TCEH Fld(6,16) +#define fNFCONF_TACLS Fld(3,12) +#define fNFCONF_TWRPH0 Fld(3,8) +#define fNFCONF_X16Device Fld(1,7) +#define fNFCONF_TWRPH1 Fld(3,4) +#define fNFCONF_Hardware_nCE Fld(1,3) +#define fNFCONF_BusWidth Fld(1,2) +#define fNFCONF_PageSize Fld(1,1) +#define fNFCONF_AddressCycle Fld(1,0) + +#define m1NFCONF_AdvanceFlash FMsk(fNFCONF_AdvanceFlash) +#define m1NFCONF_TCEH FMsk(fNFCONF_TCEH) +#define m1NFCONF_TACLS FMsk(fNFCONF_TACLS) +#define m1NFCONF_TWRPH0 FMsk(fNFCONF_TWRPH0) +#define m1NFCONF_X16Device FMsk(fNFCONF_X16Device) +#define m1NFCONF_TWRPH1 FMsk(fNFCONF_TWRPH1) +#define m1NFCONF_Hardware_nCE FMsk(fNFCONF_Hardware_nCE) +#define m1NFCONF_BusWidth FMsk(fNFCONF_BusWidth) +#define m1NFCONF_PageSize FMsk(fNFCONF_PageSize) +#define m1NFCONF_AddressCycle FMsk(fNFCONF_AddressCycle) + +#define m0NFCONF_AdvanceFlash (~m1NFCONF_AdvanceFlash) +#define m0NFCONF_TCEH (~m1NFCONF_TCEH) +#define m0NFCONF_TACLS (~m1NFCONF_TACLS) +#define m0NFCONF_TWRPH0 (~m1NFCONF_TWRPH0) +#define m0NFCONF_X16Device (~m1NFCONF_X16Device) +#define m0NFCONF_TWRPH1 (~m1NFCONF_TWRPH1) +#define m0NFCONF_Hardware_nCE (~m1NFCONF_Hardware_nCE) +#define m0NFCONF_BusWidth (~m1NFCONF_BusWidth) +#define m0NFCONF_PageSize (~m1NFCONF_PageSize) +#define m0NFCONF_AddressCycle (~m1NFCONF_AddressCycle) + +#define sNFCONF_TCEH(f_) (FInsrt(f_,fNFCONF_TCEH) & m1NFCONF_TCEH) +#define sNFCONF_TACLS(f_) (FInsrt(f_,fNFCONF_TACLS) & m1NFCONF_TACLS) +#define sNFCONF_TWRPH0(f_) (FInsrt(f_,fNFCONF_TWRPH0) & m1NFCONF_TWRPH0) +#define sNFCONF_TWRPH1(f_) (FInsrt(f_,fNFCONF_TWRPH1) & m1NFCONF_TWRPH1) +#define sNFCONF_Hardware_nCE(f_) (FInsrt(f_,fNFCONF_Hardware_nCE) & m1NFCONF_Hardware_nCE) + + +/* + * NFCONT + */ +#define fNFCONT_LdStrAddr Fld(12,16) +#define fNFCONT_EnbIllegalAccINT Fld(1,15) +#define fNFCONT_EnbLoadINT Fld(1,14) +#define fNFCONT_EnbStoreINT Fld(1,13) +#define fNFCONT_EnbRnBINT Fld(1,12) +#define fNFCONT_RnB_TransMode Fld(1,11) +#define fNFCONT_SpareECCLock Fld(1,10) +#define fNFCONT_MainECCLock Fld(1,9) +#define fNFCONT_InitECC Fld(1,8) +#define fNFCONT_Reg_nCE Fld(1,7) +#define fNFCONT_LoadPageSize Fld(3,4) +#define fNFCONT_Lock_tight Fld(1,3) +#define fNFCONT_Lock Fld(1,2) +#define fNFCONT_Mode Fld(2,0) + +#define m1NFCONT_LdStrAddr FMsk(fNFCONT_LdStrAddr) +#define m1NFCONT_EnbIllegalAccINT FMsk(fNFCONT_EnbIllegalAccINT) +#define m1NFCONT_EnbLoadINT FMsk(fNFCONT_EnbLoadINT) +#define m1NFCONT_EnbStoreINT FMsk(fNFCONT_EnbStoreINT) +#define m1NFCONT_EnbRnBINT FMsk(fNFCONT_EnbRnBINT) +#define m1NFCONT_RnB_TransMode FMsk(fNFCONT_RnB_TransMode) +#define m1NFCONT_SpareECCLock FMsk(fNFCONT_SpareECCLock) +#define m1NFCONT_MainECCLock FMsk(fNFCONT_MainECCLock) +#define m1NFCONT_InitECC FMsk(fNFCONT_InitECC) +#define m1NFCONT_Reg_nCE FMsk(fNFCONT_Reg_nCE) +#define m1NFCONT_LoadPageSize FMsk(fNFCONT_LoadPageSize) +#define m1NFCONT_Lock_tight FMsk(fNFCONT_Lock_tight) +#define m1NFCONT_Lock FMsk(fNFCONT_Lock) +#define m1NFCONT_Mode FMsk(fNFCONT_Mode) + +#define m0NFCONT_LdStrAddr (~m1NFCONT_LdStrAddr) +#define m0NFCONT_EnbIllegalAccINT (~m1NFCONT_EnbIllegalAccINT) +#define m0NFCONT_EnbLoadINT (~m1NFCONT_EnbLoadINT) +#define m0NFCONT_EnbStoreINT (~m1NFCONT_EnbStoreINT) +#define m0NFCONT_EnbRnBINT (~m1NFCONT_EnbRnBINT) +#define m0NFCONT_RnB_TransMode (~m1NFCONT_RnB_TransMode) +#define m0NFCONT_SpareECCLock (~m1NFCONT_SpareECCLock) +#define m0NFCONT_MainECCLock (~m1NFCONT_MainECCLock) +#define m0NFCONT_InitECC (~m1NFCONT_InitECC) +#define m0NFCONT_Reg_nCE (~m1NFCONT_Reg_nCE) +#define m0NFCONT_LoadPageSize (~m1NFCONT_LoadPageSize) +#define m0NFCONT_Lock_tight (~m1NFCONT_Lock_tight) +#define m0NFCONT_Lock (~m1NFCONT_Lock) +#define m0NFCONT_Mode (~m1NFCONT_Mode) + +#define sNFCONT_LdStrAddr(f_) (FInsrt(f_,fNFCONT_LdStrAddr) & m1NFCONT_LdStrAddr) +#define sNFCONT_EnbIllegalAccINT(f_) (FInsrt(f_,fNFCONT_EnbIllegalAccINT) & m1NFCONT_EnbIllegalAccINT) +#define sNFCONT_EnbLoadINT(f_) (FInsrt(f_,fNFCONT_EnbLoadINT) & m1NFCONT_EnbLoadINT) +#define sNFCONT_EnbStoreINT(f_) (FInsrt(f_,fNFCONT_EnbStoreINT) & m1NFCONT_EnbStoreINT) +#define sNFCONT_EnbRnBINT(f_) (FInsrt(f_,fNFCONT_EnbRnBINT) & m1NFCONT_EnbRnBINT) +#define sNFCONT_RnB_TransMode(f_) (FInsrt(f_,fNFCONT_RnB_TransMode) & m1NFCONT_RnB_TransMode) +#define sNFCONT_SpareECCLock(f_) (FInsrt(f_,fNFCONT_SpareECCLock) & m1NFCONT_SpareECCLock) +#define sNFCONT_MainECCLock(f_) (FInsrt(f_,fNFCONT_MainECCLock) & m1NFCONT_MainECCLock) +#define sNFCONT_InitECC(f_) (FInsrt(f_,fNFCONT_InitECC) & m1NFCONT_InitECC) +#define sNFCONT_Reg_nCE(f_) (FInsrt(f_,fNFCONT_Reg_nCE) & m1NFCONT_Reg_nCE) +#define sNFCONT_LoadPageSize(f_) (FInsrt(f_,fNFCONT_LoadPageSize) & m1NFCONT_LoadPageSize) +#define sNFCONT_Lock_tight(f_) (FInsrt(f_,fNFCONT_Lock_tight) & m1NFCONT_Lock_tight) +#define sNFCONT_Lock(f_) (FInsrt(f_,fNFCONT_Lock) & m1NFCONT_Lock) +#define sNFCONT_Mode(f_) (FInsrt(f_,fNFCONT_Mode) & m1NFCONT_Mode) + + +/* + * NFCMMD + */ +#define fNFCMMD_NFCMMD1 Fld(8,8) +#define fNFCMMD_NFCMMD0 Fld(8,0) + +#define m1NFCMMD_NFCMMD1 FMsk(fNFCMMD_NFCMMD1) +#define m1NFCMMD_NFCMMD0 FMsk(fNFCMMD_NFCMMD0) + +#define m0NFCMMD_NFCMMD1 (~m1NFCMMD_NFCMMD1) +#define m0NFCMMD_NFCMMD0 (~m1NFCMMD_NFCMMD0) + +#define sNFCMMD_NFCMMD1(f_) (FInsrt(f_,fNFCMMD_NFCMMD1) & m1NFCMMD_NFCMMD1) +#define sNFCMMD_NFCMMD0(f_) (FInsrt(f_,fNFCMMD_NFCMMD0) & m1NFCMMD_NFCMMD0) + + +/* + * NFADDR + */ +#define fNFADDR_NFADDR3 Fld(8,24) +#define fNFADDR_NFADDR2 Fld(8,16) +#define fNFADDR_NFADDR1 Fld(8,8) +#define fNFADDR_NFADDR0 Fld(8,0) + +#define m1NFADDR_NFADDR3 FMsk(fNFADDR_NFADDR3) +#define m1NFADDR_NFADDR2 FMsk(fNFADDR_NFADDR2) +#define m1NFADDR_NFADDR1 FMsk(fNFADDR_NFADDR1) +#define m1NFADDR_NFADDR0 FMsk(fNFADDR_NFADDR0) + +#define m0NFADDR_NFADDR3 (~m1NFADDR_NFADDR3) +#define m0NFADDR_NFADDR2 (~m1NFADDR_NFADDR2) +#define m0NFADDR_NFADDR1 (~m1NFADDR_NFADDR1) +#define m0NFADDR_NFADDR0 (~m1NFADDR_NFADDR0) + +#define sNFADDR_NFADDR3(f_) (FInsrt(f_,fNFADDR_NFADDR3) & m1NFADDR_NFADDR3) +#define sNFADDR_NFADDR2(f_) (FInsrt(f_,fNFADDR_NFADDR2) & m1NFADDR_NFADDR2) +#define sNFADDR_NFADDR1(f_) (FInsrt(f_,fNFADDR_NFADDR1) & m1NFADDR_NFADDR1) +#define sNFADDR_NFADDR0(f_) (FInsrt(f_,fNFADDR_NFADDR0) & m1NFADDR_NFADDR0) + + +/* + * NFDATA + */ +#define fNFDATA_NFDATA1 Fld(8,8) +#define fNFDATA_NFDATA0 Fld(8,0) + +#define m1NFDATA_NFDATA1 FMsk(fNFDATA_NFDATA1) +#define m1NFDATA_NFDATA0 FMsk(fNFDATA_NFDATA0) + +#define m0NFDATA_NFDATA1 (~m1NFDATA_NFDATA1) +#define m0NFDATA_NFDATA0 (~m1NFDATA_NFDATA0) + +#define sNFDATA_NFDATA1(f_) (FInsrt(f_,fNFDATA_NFDATA1) & m1NFDATA_NFDATA1) +#define sNFDATA_NFDATA0(f_) (FInsrt(f_,fNFDATA_NFDATA0) & m1NFDATA_NFDATA0) + + +/* + * NFMECCDATA0 + */ +#define fNFMECCDATA0_ECCData0_1 Fld(8,8) +#define fNFMECCDATA0_ECCData0_0 Fld(8,0) + +#define m1NFMECCDATA0_ECCData0_1 FMsk(fNFMECCDATA0_ECCData0_1) +#define m1NFMECCDATA0_ECCData0_0 FMsk(fNFMECCDATA0_ECCData0_0) + +#define m0NFMECCDATA0_ECCData0_1 (~m1NFMECCDATA0_ECCData0_1) +#define m0NFMECCDATA0_ECCData0_0 (~m1NFMECCDATA0_ECCData0_0) + +#define sNFMECCDATA0_ECCData0_1(f_) (FInsrt(f_,fNFMECCDATA0_ECCData0_1) & m1NFMECCDATA0_ECCData0_1) +#define sNFMECCDATA0_ECCData0_0(f_) (FInsrt(f_,fNFMECCDATA0_ECCData0_0) & m1NFMECCDATA0_ECCData0_0) + +/* + * NFMECCDATA1 + */ +#define fNFMECCDATA1_ECCData1_1 Fld(8,8) +#define fNFMECCDATA1_ECCData1_0 Fld(8,0) + +#define m1NFMECCDATA1_ECCData1_1 FMsk(fNFMECCDATA1_ECCData1_1) +#define m1NFMECCDATA1_ECCData1_0 FMsk(fNFMECCDATA1_ECCData1_0) + +#define m0NFMECCDATA1_ECCData1_1 (~m1NFMECCDATA1_ECCData1_1) +#define m0NFMECCDATA1_ECCData1_0 (~m1NFMECCDATA1_ECCData1_0) + +#define sNFMECCDATA1_ECCData1_1(f_) (FInsrt(f_,fNFMECCDATA1_ECCData1_1) & m1NFMECCDATA1_ECCData1_1) +#define sNFMECCDATA1_ECCData1_0(f_) (FInsrt(f_,fNFMECCDATA1_ECCData1_0) & m1NFMECCDATA1_ECCData1_0) + +/* + * NFMECCDATA2 + */ +#define fNFMECCDATA2_ECCData2_1 Fld(8,8) +#define fNFMECCDATA2_ECCData2_0 Fld(8,0) + +#define m1NFMECCDATA2_ECCData2_1 FMsk(fNFMECCDATA2_ECCData2_1) +#define m1NFMECCDATA2_ECCData2_0 FMsk(fNFMECCDATA2_ECCData2_0) + +#define m0NFMECCDATA2_ECCData2_1 (~m1NFMECCDATA2_ECCData2_1) +#define m0NFMECCDATA2_ECCData2_0 (~m1NFMECCDATA2_ECCData2_0) + +#define sNFMECCDATA2_ECCData2_1(f_) (FInsrt(f_,fNFMECCDATA2_ECCData2_1) & m1NFMECCDATA2_ECCData2_1) +#define sNFMECCDATA2_ECCData2_0(f_) (FInsrt(f_,fNFMECCDATA2_ECCData2_0) & m1NFMECCDATA2_ECCData2_0) + +/* + * NFMECCDATA3 + */ +#define fNFMECCDATA3_ECCData3_1 Fld(8,8) +#define fNFMECCDATA3_ECCData3_0 Fld(8,0) + +#define m1NFMECCDATA3_ECCData3_1 FMsk(fNFMECCDATA3_ECCData3_1) +#define m1NFMECCDATA3_ECCData3_0 FMsk(fNFMECCDATA3_ECCData3_0) + +#define m0NFMECCDATA3_ECCData3_1 (~m1NFMECCDATA3_ECCData3_1) +#define m0NFMECCDATA3_ECCData3_0 (~m1NFMECCDATA3_ECCData3_0) + +#define sNFMECCDATA3_ECCData3_1(f_) (FInsrt(f_,fNFMECCDATA3_ECCData3_1) & m1NFMECCDATA3_ECCData3_1) +#define sNFMECCDATA3_ECCData3_0(f_) (FInsrt(f_,fNFMECCDATA3_ECCData3_0) & m1NFMECCDATA3_ECCData3_0) + + +/* + * NFSECCDATA0 + */ +#define fNFSECCDATA0_ECCData0_1 Fld(8,8) +#define fNFSECCDATA0_ECCData0_0 Fld(8,0) + +#define m1NFSECCDATA0_ECCData0_1 FMsk(fNFSECCDATA0_ECCData0_1) +#define m1NFSECCDATA0_ECCData0_0 FMsk(fNFSECCDATA0_ECCData0_0) + +#define m0NFSECCDATA0_ECCData0_1 (~m1NFSECCDATA0_ECCData0_1) +#define m0NFSECCDATA0_ECCData0_0 (~m1NFSECCDATA0_ECCData0_0) + +#define sNFSECCDATA0_ECCData0_1(f_) (FInsrt(f_,fNFSECCDATA0_ECCData0_1) & m1NFSECCDATA0_ECCData0_1) +#define sNFSECCDATA0_ECCData0_0(f_) (FInsrt(f_,fNFSECCDATA0_ECCData0_0) & m1NFSECCDATA0_ECCData0_0) + +/* + * NFSECCDATA1 + */ +#define fNFSECCDATA1_ECCData1_1 Fld(8,8) +#define fNFSECCDATA1_ECCData1_0 Fld(8,0) + +#define m1NFSECCDATA1_ECCData1_1 FMsk(fNFSECCDATA1_ECCData1_1) +#define m1NFSECCDATA1_ECCData1_0 FMsk(fNFSECCDATA1_ECCData1_0) + +#define m0NFSECCDATA1_ECCData1_1 (~m1NFSECCDATA1_ECCData1_1) +#define m0NFSECCDATA1_ECCData1_0 (~m1NFSECCDATA1_ECCData1_0) + +#define sNFSECCDATA1_ECCData1_1(f_) (FInsrt(f_,fNFSECCDATA1_ECCData1_1) & m1NFSECCDATA1_ECCData1_1) +#define sNFSECCDATA1_ECCData1_0(f_) (FInsrt(f_,fNFSECCDATA1_ECCData1_0) & m1NFSECCDATA1_ECCData1_0) + + +/* + * NFSTAT + */ +#define fNFSTAT_IllegalAccess Fld(1,16) +#define fNFSTAT_AutoLoadDone Fld(1,15) +#define fNFSTAT_AutoStoreDone Fld(1,14) +#define fNFSTAT_RnB_TransDetect Fld(1,13) +#define fNFSTAT_Flash_nCE Fld(1,12) +#define fNFSTAT_Flash_RnB1 Fld(1,11) +#define fNFSTAT_Flash_RnB0 Fld(1,10) +#define fNFSTAT_STON_A2 Fld(10,0) + +#define m1NFSTAT_IllegalAccess FMsk(fNFSTAT_IllegalAccess) +#define m1NFSTAT_AutoLoadDone FMsk(fNFSTAT_AutoLoadDone) +#define m1NFSTAT_AutoStoreDone FMsk(fNFSTAT_AutoStoreDone) +#define m1NFSTAT_RnB_TransDetect FMsk(fNFSTAT_RnB_TransDetect) +#define m1NFSTAT_Flash_nCE FMsk(fNFSTAT_Flash_nCE) +#define m1NFSTAT_Flash_RnB1 FMsk(fNFSTAT_Flash_RnB1) +#define m1NFSTAT_Flash_RnB0 FMsk(fNFSTAT_Flash_RnB0) +#define m1NFSTAT_STON_A2 FMsk(fNFSTAT_STON_A2) + +#define m0NFSTAT_IllegalAccess (~m1NFSTAT_IllegalAccess) +#define m0NFSTAT_AutoLoadDone (~m1NFSTAT_AutoLoadDone) +#define m0NFSTAT_AutoStoreDone (~m1NFSTAT_AutoStoreDone) +#define m0NFSTAT_RnB_TransDetect (~m1NFSTAT_RnB_TransDetect) +#define m0NFSTAT_Flash_nCE (~m1NFSTAT_Flash_nCE) +#define m0NFSTAT_Flash_RnB1 (~m1NFSTAT_Flash_RnB1) +#define m0NFSTAT_Flash_RnB0 (~m1NFSTAT_Flash_RnB0) +#define m0NFSTAT_STON_A2 (~m1NFSTAT_STON_A2) + +#define sNFSTAT_IllegalAccess(f_) (FInsrt(f_,fNFSTAT_IllegalAccess) & m1NFSTAT_IllegalAccess) +#define sNFSTAT_AutoLoadDone(f_) (FInsrt(f_,fNFSTAT_AutoLoadDone) & m1NFSTAT_AutoLoadDone) +#define sNFSTAT_AutoStoreDone(f_) (FInsrt(f_,fNFSTAT_AutoStoreDone) & m1NFSTAT_AutoStoreDone) +#define sNFSTAT_RnB_TransDetect(f_) (FInsrt(f_,fNFSTAT_RnB_TransDetect) & m1NFSTAT_RnB_TransDetect) + + +/* + * NFESTAT0 + */ +#define fNFESTAT0_SErrorDataNo Fld(4,21) +#define fNFESTAT0_SErrorBitNo Fld(3,18) +#define fNFESTAT0_MErrorDataNo Fld(11,7) +#define fNFESTAT0_MErrorBitNo Fld(3,4) +#define fNFESTAT0_SpareError Fld(2,2) +#define fNFESTAT0_MainError Fld(2,0) + +#define m1NFESTAT0_SErrorDataNo FMsk(fNFESTAT0_SErrorDataNo) +#define m1NFESTAT0_SErrorBitNo FMsk(fNFESTAT0_SErrorBitNo) +#define m1NFESTAT0_MErrorDataNo FMsk(fNFESTAT0_MErrorDataNo) +#define m1NFESTAT0_MErrorBitNo FMsk(fNFESTAT0_MErrorBitNo) +#define m1NFESTAT0_SpareError FMsk(fNFESTAT0_SpareError) +#define m1NFESTAT0_MainError FMsk(fNFESTAT0_MainError) + +#define m0NFESTAT0_SErrorDataNo (~m1NFESTAT0_SErrorDataNo) +#define m0NFESTAT0_SErrorBitNo (~m1NFESTAT0_SErrorBitNo) +#define m0NFESTAT0_MErrorDataNo (~m1NFESTAT0_MErrorDataNo) +#define m0NFESTAT0_MErrorBitNo (~m1NFESTAT0_MErrorBitNo) +#define m0NFESTAT0_SpareError (~m1NFESTAT0_SpareError) +#define m0NFESTAT0_MainError (~m1NFESTAT0_MainError) + +#define sNFESTAT0_SErrorDataNo(f_) (FInsrt(f_,fNFESTAT0_SErrorDataNo) & m1NFESTAT0_SErrorDataNo) +#define sNFESTAT0_SErrorBitNo(f_) (FInsrt(f_,fNFESTAT0_SErrorBitNo) & m1NFESTAT0_SErrorBitNo) +#define sNFESTAT0_MErrorDataNo(f_) (FInsrt(f_,fNFESTAT0_MErrorDataNo) & m1NFESTAT0_MErrorDataNo) +#define sNFESTAT0_MErrorBitNo(f_) (FInsrt(f_,fNFESTAT0_MErrorBitNo) & m1NFESTAT0_MErrorBitNo) +#define sNFESTAT0_SpareError(f_) (FInsrt(f_,fNFESTAT0_SpareError) & m1NFESTAT0_SpareError) +#define sNFESTAT0_MainError(f_) (FInsrt(f_,fNFESTAT0_MainError) & m1NFESTAT0_MainError) + +/* + * NFESTAT1 + */ +#define fNFESTAT1_SErrorDataNo Fld(4,21) +#define fNFESTAT1_SErrorBitNo Fld(3,18) +#define fNFESTAT1_MErrorDataNo Fld(11,7) +#define fNFESTAT1_MErrorBitNo Fld(3,4) +#define fNFESTAT1_SpareError Fld(2,2) +#define fNFESTAT1_MainError Fld(2,0) + +#define m1NFESTAT1_SErrorDataNo FMsk(fNFESTAT1_SErrorDataNo) +#define m1NFESTAT1_SErrorBitNo FMsk(fNFESTAT1_SErrorBitNo) +#define m1NFESTAT1_MErrorDataNo FMsk(fNFESTAT1_MErrorDataNo) +#define m1NFESTAT1_MErrorBitNo FMsk(fNFESTAT1_MErrorBitNo) +#define m1NFESTAT1_SpareError FMsk(fNFESTAT1_SpareError) +#define m1NFESTAT1_MainError FMsk(fNFESTAT1_MainError) + +#define m0NFESTAT1_SErrorDataNo (~m1NFESTAT1_SErrorDataNo) +#define m0NFESTAT1_SErrorBitNo (~m1NFESTAT1_SErrorBitNo) +#define m0NFESTAT1_MErrorDataNo (~m1NFESTAT1_MErrorDataNo) +#define m0NFESTAT1_MErrorBitNo (~m1NFESTAT1_MErrorBitNo) +#define m0NFESTAT1_SpareError (~m1NFESTAT1_SpareError) +#define m0NFESTAT1_MainError (~m1NFESTAT1_MainError) + +#define sNFESTAT1_SErrorDataNo(f_) (FInsrt(f_,fNFESTAT1_SErrorDataNo) & m1NFESTAT1_SErrorDataNo) +#define sNFESTAT1_SErrorBitNo(f_) (FInsrt(f_,fNFESTAT1_SErrorBitNo) & m1NFESTAT1_SErrorBitNo) +#define sNFESTAT1_MErrorDataNo(f_) (FInsrt(f_,fNFESTAT1_MErrorDataNo) & m1NFESTAT1_MErrorDataNo) +#define sNFESTAT1_MErrorBitNo(f_) (FInsrt(f_,fNFESTAT1_MErrorBitNo) & m1NFESTAT1_MErrorBitNo) +#define sNFESTAT1_SpareError(f_) (FInsrt(f_,fNFESTAT1_SpareError) & m1NFESTAT1_SpareError) +#define sNFESTAT1_MainError(f_) (FInsrt(f_,fNFESTAT1_MainError) & m1NFESTAT1_MainError) + + +/* + * NFMECC0 + */ +#define fNFMECC0_MECC0_3 Fld(8,24) +#define fNFMECC0_MECC0_2 Fld(8,16) +#define fNFMECC0_MECC0_1 Fld(8,8) +#define fNFMECC0_MECC0_0 Fld(8,0) + +#define m1NFMECC0_MECC0_3 FMsk(fNFMECC0_MECC0_3) +#define m1NFMECC0_MECC0_2 FMsk(fNFMECC0_MECC0_2) +#define m1NFMECC0_MECC0_1 FMsk(fNFMECC0_MECC0_1) +#define m1NFMECC0_MECC0_0 FMsk(fNFMECC0_MECC0_0) + +#define m0NFMECC0_MECC0_3 (~m1NFMECC0_MECC0_3) +#define m0NFMECC0_MECC0_2 (~m1NFMECC0_MECC0_2) +#define m0NFMECC0_MECC0_1 (~m1NFMECC0_MECC0_1) +#define m0NFMECC0_MECC0_0 (~m1NFMECC0_MECC0_0) + +/* + * NFMECC1 + */ +#define fNFMECC1_MECC1_3 Fld(8,24) +#define fNFMECC1_MECC1_2 Fld(8,16) +#define fNFMECC1_MECC1_1 Fld(8,8) +#define fNFMECC1_MECC1_0 Fld(8,0) + +#define m1NFMECC1_MECC1_3 FMsk(fNFMECC1_MECC1_3) +#define m1NFMECC1_MECC1_2 FMsk(fNFMECC1_MECC1_2) +#define m1NFMECC1_MECC1_1 FMsk(fNFMECC1_MECC1_1) +#define m1NFMECC1_MECC1_0 FMsk(fNFMECC1_MECC1_0) + +#define m0NFMECC1_MECC1_3 (~m1NFMECC1_MECC1_3) +#define m0NFMECC1_MECC1_2 (~m1NFMECC1_MECC1_2) +#define m0NFMECC1_MECC1_1 (~m1NFMECC1_MECC1_1) +#define m0NFMECC1_MECC1_0 (~m1NFMECC1_MECC1_0) + + +/* + * NFSECC + */ +#define fNFSECC_SECC1_1 Fld(8,24) +#define fNFSECC_SECC1_0 Fld(8,16) +#define fNFSECC_SECC0_1 Fld(8,8) +#define fNFSECC_SECC0_0 Fld(8,0) + +#define m1NFSECC_SECC1_1 FMsk(fNFSECC_SECC1_1) +#define m1NFSECC_SECC1_0 FMsk(fNFSECC_SECC1_0) +#define m1NFSECC_SECC0_1 FMsk(fNFSECC_SECC0_1) +#define m1NFSECC_SECC0_0 FMsk(fNFSECC_SECC0_0) + +#define m0NFSECC_SECC1_1 (~m1NFSECC_SECC1_1) +#define m0NFSECC_SECC1_0 (~m1NFSECC_SECC1_0) +#define m0NFSECC_SECC0_1 (~m1NFSECC_SECC0_1) +#define m0NFSECC_SECC0_0 (~m1NFSECC_SECC0_0) + + +/* + * NFSBLK + */ +#define fNFSBLK_SBLK_ADDR2 Fld(8,16) +#define fNFSBLK_SBLK_ADDR1 Fld(8,8) +#define fNFSBLK_SBLK_ADDR0 Fld(8,0) + +#define m1NFSBLK_SBLK_ADDR2 FMsk(fNFSBLK_SBLK_ADDR2) +#define m1NFSBLK_SBLK_ADDR1 FMsk(fNFSBLK_SBLK_ADDR1) +#define m1NFSBLK_SBLK_ADDR0 FMsk(fNFSBLK_SBLK_ADDR0) + +#define m0NFSBLK_SBLK_ADDR2 (~m1NFSBLK_SBLK_ADDR2) +#define m0NFSBLK_SBLK_ADDR1 (~m1NFSBLK_SBLK_ADDR1) +#define m0NFSBLK_SBLK_ADDR0 (~m1NFSBLK_SBLK_ADDR0) + +#define sNFSBLK_SBLK_ADDR2(f_) (FInsrt(f_,fNFSBLK_SBLK_ADDR2) & m1NFSBLK_SBLK_ADDR2) +#define sNFSBLK_SBLK_ADDR1(f_) (FInsrt(f_,fNFSBLK_SBLK_ADDR1) & m1NFSBLK_SBLK_ADDR1) +#define sNFSBLK_SBLK_ADDR0(f_) (FInsrt(f_,fNFSBLK_SBLK_ADDR0) & m1NFSBLK_SBLK_ADDR0) + +/* + * NFEBLK + */ +#define fNFEBLK_EBLK_ADDR2 Fld(8,16) +#define fNFEBLK_EBLK_ADDR1 Fld(8,8) +#define fNFEBLK_EBLK_ADDR0 Fld(8,0) + +#define m1NFEBLK_EBLK_ADDR2 FMsk(fNFEBLK_EBLK_ADDR2) +#define m1NFEBLK_EBLK_ADDR1 FMsk(fNFEBLK_EBLK_ADDR1) +#define m1NFEBLK_EBLK_ADDR0 FMsk(fNFEBLK_EBLK_ADDR0) + +#define m0NFEBLK_EBLK_ADDR2 (~m1NFEBLK_EBLK_ADDR2) +#define m0NFEBLK_EBLK_ADDR1 (~m1NFEBLK_EBLK_ADDR1) +#define m0NFEBLK_EBLK_ADDR0 (~m1NFEBLK_EBLK_ADDR0) + +#define sNFEBLK_EBLK_ADDR2(f_) (FInsrt(f_,fNFEBLK_EBLK_ADDR2) & m1NFEBLK_EBLK_ADDR2) +#define sNFEBLK_EBLK_ADDR1(f_) (FInsrt(f_,fNFEBLK_EBLK_ADDR1) & m1NFEBLK_EBLK_ADDR1) +#define sNFEBLK_EBLK_ADDR0(f_) (FInsrt(f_,fNFEBLK_EBLK_ADDR0) & m1NFEBLK_EBLK_ADDR0) + +#endif /* __ASM_ARM_REGS_NAND */ Firstly, again the use of the bitfield header, which is not pleasant, and secondly, this looks like more re-definition of items that could be better off using the generic driver. diff --git a/include/asm-arm/arch-s3c24a0/regs-pm.h b/include/asm-arm/arch-s3c24a0/regs-pm.h new file mode 100644 index 0000000..cf9044b --- /dev/null +++ b/include/asm-arm/arch-s3c24a0/regs-pm.h @@ -0,0 +1,49 @@ +/* linux/include/asm/arch-s3c24a0/regs-pm.h + * + * Id: regs-pm.h + * + * S3C24A0 Power Management register definitions + * + * 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_REGS_PM_H +#define __ASM_ARCH_REGS_PM_H + +/* + * Power management + */ +#define S3C24A0_PMREG(x) ((x) + S3C24A0_VA_GPIO) + +#define ALIVECON S3C24A0_PMREG(0x44) /* clock for alive mode in sleep */ +#define RSTCNT S3C24A0_PMREG(0x68) /* reset count for power settle-down */ + +#define GPDATINSLEEP S3C24A0_PMREG(0x48) +#define ENGPINSLEEP S3C24A0_PMREG(0x4c) +#define GPUPINSLEEP S3C24A0_PMREG(0x50) +#define DATRINSLEEP0 S3C24A0_PMREG(0x54) +#define DATRINSLEEP1 S3C24A0_PMREG(0x58) +#define OENINSLEEP0 S3C24A0_PMREG(0x5c) +#define OENINSLEEP1 S3C24A0_PMREG(0x60) +#define ENPUINSLEEP S3C24A0_PMREG(0x64) + +#define GPRAM0 S3C24A0_PMREG(0x80) +#define GPRAM1 S3C24A0_PMREG(0x84) +#define GPRAM2 S3C24A0_PMREG(0x88) +#define GPRAM3 S3C24A0_PMREG(0x8C) +#define GPRAM4 S3C24A0_PMREG(0x90) +#define GPRAM5 S3C24A0_PMREG(0x94) +#define GPRAM6 S3C24A0_PMREG(0x98) prefix with S3C24A0_ +#define PM_NANDREG(x) ((x) + S3C24A0_VA_NAND) + +#define PM_NFCONF PM_NANDREG(0x00) +#define PM_NFCONT PM_NANDREG(0x04) just include the right header if you are using this. do not re-define items just to make an include a little smaller. +#endif /* __ASM_ARCH_REGS_PM_H */ diff --git a/include/asm-arm/arch-s3c24a0/regs-rtc.h b/include/asm-arm/arch-s3c24a0/regs-rtc.h new file mode 100644 index 0000000..5f0628f --- /dev/null +++ b/include/asm-arm/arch-s3c24a0/regs-rtc.h @@ -0,0 +1,75 @@ +/* linux/include/asm/arch-s3c24a0/regs-rtc.h + * + * Id: regs-rtc.h + * + * S3C24A0 RTC register definitions + * + * 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/regs-rtc.h, written by + * Ben Dooks + * + */ + +#ifndef __ASM_ARCH_REGS_RTC_H +#define __ASM_ARCH_REGS_RTC_H __FILE__ + +#define S3C24A0_RTCREG(x) ((x) + S3C24A0_VA_RTC) + +#define S3C24A0_RTCCON S3C24A0_RTCREG(0x40) +#define S3C24A0_RTCCON_RTCEN (1<<0) +#define S3C24A0_RTCCON_CLKSEL (1<<1) +#define S3C24A0_RTCCON_CNTSEL (1<<2) +#define S3C24A0_RTCCON_CLKRST (1<<3) + +#define S3C24A0_TICNT S3C24A0_RTCREG(0x44) +#define S3C24A0_TICNT_ENABLE (1<<7) + +#define S3C24A0_RTCALM S3C24A0_RTCREG(0x50) +#define S3C24A0_RTCALM_ALMEN (1<<6) +#define S3C24A0_RTCALM_YEAREN (1<<5) +#define S3C24A0_RTCALM_MONEN (1<<4) +#define S3C24A0_RTCALM_DAYEN (1<<3) +#define S3C24A0_RTCALM_HOUREN (1<<2) +#define S3C24A0_RTCALM_MINEN (1<<1) +#define S3C24A0_RTCALM_SECEN (1<<0) + +#define S3C24A0_RTCALM_ALL \ + S3C24A0_RTCALM_ALMEN | S3C24A0_RTCALM_YEAREN | S3C24A0_RTCALM_MONEN |\ + S3C24A0_RTCALM_DAYEN | S3C24A0_RTCALM_HOUREN | S3C24A0_RTCALM_MINEN |\ + S3C24A0_RTCALM_SECEN + + +#define S3C24A0_ALMSEC S3C24A0_RTCREG(0x54) +#define S3C24A0_ALMMIN S3C24A0_RTCREG(0x58) +#define S3C24A0_ALMHOUR S3C24A0_RTCREG(0x5c) + +#define S3C24A0_ALMDATE S3C24A0_RTCREG(0x60) +#define S3C24A0_ALMMON S3C24A0_RTCREG(0x64) +#define S3C24A0_ALMYEAR S3C24A0_RTCREG(0x68) + +#define S3C24A0_RTCRST S3C24A0_RTCREG(0x6c) + +#define S3C24A0_RTCSEC S3C24A0_RTCREG(0x70) +#define S3C24A0_RTCMIN S3C24A0_RTCREG(0x74) +#define S3C24A0_RTCHOUR S3C24A0_RTCREG(0x78) +#define S3C24A0_RTCDATE S3C24A0_RTCREG(0x7c) +#define S3C24A0_RTCDAY S3C24A0_RTCREG(0x80) +#define S3C24A0_RTCMON S3C24A0_RTCREG(0x84) +#define S3C24A0_RTCYEAR S3C24A0_RTCREG(0x88) + +/* Mask */ +#define Msk_RTCSEC 127 +#define Msk_RTCMIN 127 +#define Msk_RTCHOUR 63 +#define Msk_RTCDAY 7 +#define Msk_RTCDATE 63 +#define Msk_RTCMON 31 +#define Msk_RTCYEAR 255 + +#endif /* __ASM_ARCH_REGS_RTC_H */ I get the feeling someone likes to cut-and-paste. diff --git a/include/asm-arm/arch-s3c24a0/regs-sdi.h b/include/asm-arm/arch-s3c24a0/regs-sdi.h new file mode 100644 index 0000000..ecc946f --- /dev/null +++ b/include/asm-arm/arch-s3c24a0/regs-sdi.h @@ -0,0 +1,162 @@ +/* linux/include/asm/arch-s3c2410/regs-sdi.h + * + * Copyright (c) 2004 Simtec Electronics + * http://www.simtec.co.uk/products/SWLINUX/ + * + * Copyright (c) 2005 Samsung Electronics + * + * 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. + * + * S3C24A0 MMC/SDIO register definitions + * + * Changelog: + * 18-Aug-2004 Ben Dooks Created initial file + * 29-Nov-2004 Koen Martens Added some missing defines, fixed duplicates + * 29-Nov-2004 Ben Dooks Updated Koen's patch + * 13-Apr-2005 Naushad Modified for SMDK24A0 +*/ + +#ifndef __ASM_ARM_REGS_SDI +#define __ASM_ARM_REGS_SDI "regs-sdi.h" + + +#define S3C24A0_SDICON (0x00) +#define S3C24A0_SDIPRE (0x04) +#define S3C24A0_SDICMDARG (0x08) +#define S3C24A0_SDICMDCON (0x0C) +#define S3C24A0_SDICMDSTAT (0x10) +#define S3C24A0_SDIRSP0 (0x14) +#define S3C24A0_SDIRSP1 (0x18) +#define S3C24A0_SDIRSP2 (0x1C) +#define S3C24A0_SDIRSP3 (0x20) +#define S3C24A0_SDITIMER (0x24) +#define S3C24A0_SDIBSIZE (0x28) +#define S3C24A0_SDIDCON (0x2C) +#define S3C24A0_SDIDCNT (0x30) +#define S3C24A0_SDIDSTA (0x34) +#define S3C24A0_SDIFSTA (0x38) +#define S3C24A0_SDIIMSK (0x3C) +#define S3C24A0_SDIDATA (0x40) + +/* SDI Control Register SDICON */ + +#define S3C24A0_SDICON_RESET (1<<8) +#define S3C24A0_SDICON_HLDMGN_HALFPCLK (0<<6) +#define S3C24A0_SDICON_HLDMGN_ONEPCLK (1<<6) +#define S3C24A0_SDICON_HLDMGN_3BY2PCLK (2<<6) +#define S3C24A0_SDICON_HLDMGN_TWOPCLK (3<<6) +#define S3C24A0_SDICON_CLOCKTYPE_MMC (1<<5) +#define S3C24A0_SDICON_BYTEORDER (1<<4) +#define S3C24A0_SDICON_SDIOIRQ (1<<3) +#define S3C24A0_SDICON_RWAITEN (1<<2) +#define S3C24A0_SDICON_CLKENABLE (1<<0) + +/* SDI Command Control Register */ + +#define S3C24A0_SDICMDCON_ABORT (1<<12) +#define S3C24A0_SDICMDCON_WITHDATA (1<<11) +#define S3C24A0_SDICMDCON_LONGRSP (1<<10) +#define S3C24A0_SDICMDCON_WAITRSP (1<<9) +#define S3C24A0_SDICMDCON_CMDSTART (1<<8) +#define S3C24A0_SDICMDCON_INDEX (0xff) + +/* SDI Command Status register */ + +#define S3C24A0_SDICMDSTAT_CRCFAIL (1<<12) +#define S3C24A0_SDICMDSTAT_CMDSENT (1<<11) +#define S3C24A0_SDICMDSTAT_CMDTIMEOUT (1<<10) +#define S3C24A0_SDICMDSTAT_RSPFIN (1<<9) +#define S3C24A0_SDICMDSTAT_XFERING (1<<8) +#define S3C24A0_SDICMDSTAT_INDEX (0xff) + +/* SDI Data control registers */ + +#define S3C24A0_SDIDCON_BURST3ENABLE (0<<22) + +#define S3C24A0_SDIDCON_BYTETX (0<<22) +#define S3C24A0_SDIDCON_HWTX (1<<22) +#define S3C24A0_SDIDCON_WORDTX (2<<22) + + + +#define S3C24A0_SDIDCON_IRQPERIOD (1<<21) +#define S3C24A0_SDIDCON_TXAFTERRESP (1<<20) +#define S3C24A0_SDIDCON_RXAFTERCMD (1<<19) +#define S3C24A0_SDIDCON_BUSYAFTERCMD (1<<18) +#define S3C24A0_SDIDCON_BLOCKMODE (1<<17) +#define S3C24A0_SDIDCON_WIDEBUS (1<<16) +#define S3C24A0_SDIDCON_DMAEN (1<<15) +//#define S3C24A0_SDIDCON_STOP (1<<14) +#define S3C24A0_SDIDCON_DATA_START (1<<14) +#define S3C24A0_SDIDCON_DATMODE (3<<12) +#define S3C24A0_SDIDCON_BLKNUM (0x7ff) + + + +/* constants for S3C2410_SDIDCON_DATMODE */ +#define S3C24A0_SDIDCON_XFER_NOOP (0<<12) +#define S3C24A0_SDIDCON_XFER_BUSYCHKSTART (1<<12) +#define S3C24A0_SDIDCON_XFER_RXSTART (2<<12) +#define S3C24A0_SDIDCON_XFER_TXSTART (3<<12) + +/* SDI Data remain counter register */ + +#define S3C24A0_SDIDCNT_BLKNUM_SHIFT (12) + + +/* SDI Data status register */ + +#define S3C24A0_SDIDSTA_NOBUSY (1<<11) +#define S3C24A0_SDIDSTA_RDYWAITREQ (1<<10) +#define S3C24A0_SDIDSTA_SDIOIRQDETECT (1<<9) +//#define S3C24A0_SDIDSTA_FIFOFAIL (1<<8) /* reserved on 2440 */ +#define S3C24A0_SDIDSTA_CRCFAIL (1<<7) +#define S3C24A0_SDIDSTA_RXCRCFAIL (1<<6) +#define S3C24A0_SDIDSTA_DATATIMEOUT (1<<5) +#define S3C24A0_SDIDSTA_XFERFINISH (1<<4) +#define S3C24A0_SDIDSTA_BUSYFINISH (1<<3) +//#define S3C24A0_SDIDSTA_SBITERR (1<<2) /* reserved on 2410a/2440 */ +#define S3C24A0_SDIDSTA_TXDATAON (1<<1) +#define S3C24A0_SDIDSTA_RXDATAON (1<<0) + + +/* SDI Fifo status register */ + +#define S3C24A0_SDIFSTA_FRST (1<<16) +#define S3C24A0_SDIFSTA_NOFAIL (0<<14) +#define S3C24A0_SDIFSTA_FAIL (1<<14) +#define S3C24A0_SDIFSTA_FAILIN_LASTTX (2<<14) +#define S3C24A0_SDIFSTA_TFDET (1<<13) +#define S3C24A0_SDIFSTA_RFDET (1<<12) +#define S3C24A0_SDIFSTA_TXHALF (1<<11) +#define S3C24A0_SDIFSTA_TXEMPTY (1<<10) +#define S3C24A0_SDIFSTA_RFLAST (1<<9) +#define S3C24A0_SDIFSTA_RFFULL (1<<8) +#define S3C24A0_SDIFSTA_RFHALF (1<<7) +#define S3C24A0_SDIFSTA_COUNTMASK (0x7f) + +/* SDI Interrupt Mask register */ + +#define S3C24A0_SDIIMSK_NOBUSY (1<<18) // for 24x0A +#define S3C24A0_SDIIMSK_RESPONSECRC (1<<17) +#define S3C24A0_SDIIMSK_CMDSENT (1<<16) +#define S3C24A0_SDIIMSK_CMDTIMEOUT (1<<15) +#define S3C24A0_SDIIMSK_RESPONSEND (1<<14) +#define S3C24A0_SDIIMSK_READWAIT (1<<13) +#define S3C24A0_SDIIMSK_SDIOIRQ (1<<12) +#define S3C24A0_SDIIMSK_FIFOFAIL (1<<11) +#define S3C24A0_SDIIMSK_CRCSTATUS (1<<10) +#define S3C24A0_SDIIMSK_DATACRC (1<<9) +#define S3C24A0_SDIIMSK_DATATIMEOUT (1<<8) +#define S3C24A0_SDIIMSK_DATAFINISH (1<<7) +#define S3C24A0_SDIIMSK_BUSYFINISH (1<<6) +//#define S3C24A0_SDIIMSK_SBITERR (1<<5) /* reserved 2440/2410a */ +#define S3C24A0_SDIIMSK_TXFIFOHALF (1<<4) +#define S3C24A0_SDIIMSK_TXFIFOEMPTY (1<<3) +#define S3C24A0_SDIIMSK_RXFIFOLAST (1<<2) +#define S3C24A0_SDIIMSK_RXFIFOFULL (1<<1) +#define S3C24A0_SDIIMSK_RXFIFOHALF (1<<0) + +#endif /* __ASM_ARM_REGS_SDI */ diff --git a/include/asm-arm/arch-s3c24a0/regs-serial.h b/include/asm-arm/arch-s3c24a0/regs-serial.h new file mode 100644 index 0000000..6955acf --- /dev/null +++ b/include/asm-arm/arch-s3c24a0/regs-serial.h @@ -0,0 +1,159 @@ +/* linux/include/asm/arch-s3c24a0/regs-serial.h + * + * Id: regs-serial.h + * + * S3C24A0 Serial UART register definitions + * + * 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/hardware/serial_s3c24a0.h, written by + * Shane Nay + * + */ + +#ifndef __ASM_ARM_REGS_SERIAL_H +#define __ASM_ARM_REGS_SERIAL_H + +#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 ) + +#define S3C24A0_URXH (0x24) +#define S3C24A0_UTXH (0x20) +#define S3C24A0_ULCON (0x00) +#define S3C24A0_UCON (0x04) +#define S3C24A0_UFCON (0x08) +#define S3C24A0_UMCON (0x0C) +#define S3C24A0_UBRDIV (0x28) +#define S3C24A0_UTRSTAT (0x10) +#define S3C24A0_UERSTAT (0x14) +#define S3C24A0_UFSTAT (0x18) +#define S3C24A0_UMSTAT (0x1C) + +#define S3C24A0_LCON_CFGMASK ((0xF<<3)|(0x3)) + +#define S3C24A0_LCON_CS5 (0x0) +#define S3C24A0_LCON_CS6 (0x1) +#define S3C24A0_LCON_CS7 (0x2) +#define S3C24A0_LCON_CS8 (0x3) +#define S3C24A0_LCON_CSMASK (0x3) + +#define S3C24A0_LCON_PNONE (0x0) +#define S3C24A0_LCON_PEVEN (0x5 << 3) +#define S3C24A0_LCON_PODD (0x4 << 3) +#define S3C24A0_LCON_PMASK (0x7 << 3) + +#define S3C24A0_LCON_STOPB (1<<2) +#define S3C24A0_LCON_IRM (1<<6) + +#define S3C24A0_UCON_UCLK (1<<10) +#define S3C24A0_UCON_SBREAK (1<<4) + +#define S3C24A0_UCON_TXILEVEL (1<<9) +#define S3C24A0_UCON_RXILEVEL (1<<8) +#define S3C24A0_UCON_TXIRQMODE (1<<2) +#define S3C24A0_UCON_RXIRQMODE (1<<0) +#define S3C24A0_UCON_RXFIFO_TOI (1<<7) + +#define S3C24A0_UCON_DEFAULT (S3C24A0_UCON_TXILEVEL | \ + S3C24A0_UCON_RXILEVEL | \ + S3C24A0_UCON_TXIRQMODE | \ + S3C24A0_UCON_RXIRQMODE | \ + S3C24A0_UCON_RXFIFO_TOI) + +#define S3C24A0_UFCON_FIFOMODE (1<<0) +#define S3C24A0_UFCON_TXTRIG0 (0<<6) +#define S3C24A0_UFCON_RXTRIG8 (1<<4) +#define S3C24A0_UFCON_RXTRIG12 (2<<4) + +#define S3C24A0_UFCON_RESETBOTH (3<<1) +#define S3C24A0_UFCON_RESETTX (1<<2) +#define S3C24A0_UFCON_RESETRX (1<<1) + +#define S3C24A0_UFCON_DEFAULT (S3C24A0_UFCON_FIFOMODE | \ + S3C24A0_UFCON_TXTRIG0 | \ + S3C24A0_UFCON_RXTRIG8 ) + +#define S3C24A0_UFSTAT_TXFULL (1<<14) +#define S3C24A0_UFSTAT_RXFULL (1<<6) +#define S3C24A0_UFSTAT_TXMASK (63<<8) +#define S3C24A0_UFSTAT_TXSHIFT (8) +#define S3C24A0_UFSTAT_RXMASK (63) +#define S3C24A0_UFSTAT_RXSHIFT (0) + +#define S3C24A0_UTRSTAT_TXE (1<<2) +#define S3C24A0_UTRSTAT_TXFE (1<<1) +#define S3C24A0_UTRSTAT_RXDR (1<<0) + +#define S3C24A0_UERSTAT_OVERRUN (1<<0) +#define S3C24A0_UERSTAT_FRAME (1<<2) +#define S3C24A0_UERSTAT_BREAK (1<<3) +#define S3C24A0_UERSTAT_ANY (S3C24A0_UERSTAT_OVERRUN | \ + S3C24A0_UERSTAT_FRAME | \ + S3C24A0_UERSTAT_BREAK) + +#define S3C24A0_UMSTAT_CTS (1<<0) +#define S3C24A0_UMSTAT_DeltaCTS (1<<2) + +#ifndef __ASSEMBLY__ + +/* struct s3c24xx_uart_clksrc + * + * this structure defines a named clock source that can be used for the + * uart, so that the best clock can be selected for the requested baud + * rate. + * + * min_baud and max_baud define the range of baud-rates this clock is + * acceptable for, if they are both zero, it is assumed any baud rate that + * can be generated from this clock will be used. + * + * divisor gives the divisor from the clock to the one seen by the uart +*/ + +struct s3c24xx_uart_clksrc { + const char *name; + unsigned int divisor; + unsigned int min_baud; + unsigned int max_baud; +}; + +/* configuration structure for per-machine configurations for the + * serial port + * + * the pointer is setup by the machine specific initialisation from the + * arch/arm/mach-s3c24a0/ directory. +*/ + +struct s3c24a0_uartcfg { + unsigned char hwport; /* hardware port number */ + unsigned char unused; + unsigned short flags; + unsigned long uart_flags; /* default uart flags */ + + unsigned long ucon; /* value of ucon for port */ + unsigned long ulcon; /* value of ulcon for port */ + unsigned long ufcon; /* value of ufcon for port */ + + struct s3c24xx_uart_clksrc *clocks; + unsigned int clocks_size; +}; + +/* s3c24xx_uart_devs + * + * this is exported from the core as we cannot use driver_register(), + * or platform_add_device() before the console_initcall() +*/ + +extern struct platform_device *s3c24xx_uart_devs[2]; + +#endif /* __ASSEMBLY__ */ + +#endif /* __ASM_ARM_REGS_SERIAL_H */ + diff --git a/include/asm-arm/arch-s3c24a0/regs-spi.h b/include/asm-arm/arch-s3c24a0/regs-spi.h new file mode 100644 index 0000000..8fa3092 --- /dev/null +++ b/include/asm-arm/arch-s3c24a0/regs-spi.h @@ -0,0 +1,58 @@ +/* linux/include/asm/arch-s3c24a0/regs-spi.h + * + * Id: regs-spi.h + * + * S3C24A0 SPI register definitions + * + * 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/regs-spi.h, written by + * Ben Dooks + * + */ + +#ifndef __ASM_ARCH_REGS_SPI_H +#define __ASM_ARCH_REGS_SPI_H + + +#define S3C24A0_SPCON (0x00) + +#define S3C24A0_SPCON_SMOD_DMA (2<<5) /* DMA mode */ +#define S3C24A0_SPCON_SMOD_INT (1<<5) /* interrupt mode */ +#define S3C24A0_SPCON_SMOD_POLL (0<<5) /* polling mode */ +#define S3C24A0_SPCON_ENSCK (1<<4) /* Enable SCK */ +#define S3C24A0_SPCON_MSTR (1<<3) /* Master/Slave select + 0: slave, 1: master */ +#define S3C24A0_SPCON_CPOL_HIGH (1<<2) /* Clock polarity select */ +#define S3C24A0_SPCON_CPOL_LOW (0<<2) /* Clock polarity select */ + +#define S3C24A0_SPCON_CPHA_FMTB (1<<1) /* Clock Phase Select */ +#define S3C24A0_SPCON_CPHA_FMTA (0<<1) /* Clock Phase Select */ + +#define S3C24A0_SPCON_TAGD (1<<0) /* Tx auto garbage data mode */ + + +#define S3C24A0_SPSTA (0x04) + +#define S3C24A0_SPSTA_DCOL (1<<2) /* Data Collision Error */ +#define S3C24A0_SPSTA_MULD (1<<1) /* Multi Master Error */ +#define S3C24A0_SPSTA_READY (1<<0) /* Data Tx/Rx ready */ + + +#define S3C24A0_SPPIN (0x08) + +#define S3C24A0_SPPIN_ENMUL (1<<2) /* Multi Master Error detect */ +#define S3C24A0_SPPIN_RESERVED (1<<1) +#define S3C24A0_SPPIN_KEEP (1<<0) /* Master Out keep */ + + +#define S3C24A0_SPPRE (0x0C) +#define S3C24A0_SPTDAT (0x10) +#define S3C24A0_SPRDAT (0x14) + +#endif /* __ASM_ARCH_REGS_SPI_H */ diff --git a/include/asm-arm/arch-s3c24a0/regs-timer.h b/include/asm-arm/arch-s3c24a0/regs-timer.h new file mode 100644 index 0000000..e110183 --- /dev/null +++ b/include/asm-arm/arch-s3c24a0/regs-timer.h @@ -0,0 +1,213 @@ +/* linux/include/asm/arch-s3c24a0/regs-timer.h + * + * Id: regs-timer.h + * + * S3C24A0 PWMTimer register definitions + * + * 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/regs-timer.h, written by + * Ben Dooks + * + */ + + +#ifndef __ASM_ARCH_REGS_TIMER_H +#define __ASM_ARCH_REGS_TIMER_H + +#include "bitfield.h" + +#define S3C24A0_TIMERREG(x) (S3C24A0_VA_TIMER + (x)) +#define S3C24A0_TIMERREG2(tmr,reg) S3C24A0_TIMERREG((reg)+0x0c+((tmr)*0x0c)) + +#define S3C24A0_TCFG0 S3C24A0_TIMERREG(0x00) +#define S3C24A0_TCFG1 S3C24A0_TIMERREG(0x04) +#define S3C24A0_TCON S3C24A0_TIMERREG(0x08) + +#define fTCFG0_DZONE Fld(8,16) /* the dead zone length (= timer 0) */ +#define fTCFG0_PRE1 Fld(8,8) /* prescaler value for time 2,3,4 */ +#define fTCFG0_PRE0 Fld(8,0) /* prescaler value for time 0,1 */ +#define SET_PRESCALER0(x) ({ TCFG0 = (TCFG0 & ~(0xff)) | (x); }) +#define GET_PRESCALER0() FExtr(TCFG0, fTCFG0_PRE0) +#define SET_PRESCALER1(x) ({ TCFG0 = (TCFG0 & ~(0xff << 8)) | ((x) << 8); }) +#define GET_PRESCALER1() FExtr(TCFG0, fTCFG0_PRE0) + +#define fTCFG1_DMA Fld(4,20) /* select DMA request channel */ +#define fTCFG1_T4MUX Fld(4,16) /* timer4 input mux */ +#define fTCFG1_T3MUX Fld(4,12) /* timer3 input mux */ +#define fTCFG1_T2MUX Fld(4,8) /* timer2 input mux */ +#define fTCFG1_T1MUX Fld(4,4) /* timer1 input mux */ +#define fTCFG1_T0MUX Fld(4,0) /* timer0 input mux */ +#define TIMER0_DIV(x) FInsrt((x), fTCFG1_T0MUX) +#define TIMER1_DIV(x) FInsrt((x), fTCFG1_T1MUX) +#define TIMER2_DIV(x) FInsrt((x), fTCFG1_T2MUX) +#define TIMER3_DIV(x) FInsrt((x), fTCFG1_T3MUX) +#define TIMER4_DIV(x) FInsrt((x), fTCFG1_T4MUX) + +#define fTCON_TIMER4 Fld(3,20) +#define fTCON_TIMER3 Fld(4,16) +#define fTCON_TIMER2 Fld(4,12) +#define fTCON_TIMER1 Fld(4,8) +#define fTCON_TIMER0 Fld(5,0) + +#define fCNTB Fld(16,0) +#define fCNTO Fld(16,0) +#define fCMPB Fld(16,0) + +#define TCFG0_DZONE(x) FInsrt((x), fTCFG0_DZONE) +#define TCFG0_PRE1(x) FInsrt((x), fTCFG0_PRE1) +#define TCFG0_PRE0(x) FInsrt((x), fTCFG0_PRE0) +#define TCON_4_AUTO (1 << 22) /* auto reload on/off for Timer 4 */ +#define TCON_4_UPDATE (1 << 21) /* manual Update TCNTB4 */ +#define TCON_4_ONOFF (1 << 20) /* 0: Stop, 1: start Timer 4 */ +#define COUNT_4_ON (TCON_4_ONOFF*1) +#define COUNT_4_OFF (TCON_4_ONOFF*0) +#define TCON_3_AUTO (1 << 19) /* auto reload on/off for Timer 3 */ +#define TCON_3_INVERT (1 << 18) /* 1: Inverter on for TOUT3 */ +#define TCON_3_MAN (1 << 17) /* manual Update TCNTB3,TCMPB3 */ +#define TCON_3_ONOFF (1 << 16) /* 0: Stop, 1: start Timer 3 */ +#define TCON_2_AUTO (1 << 15) /* auto reload on/off for Timer 3 */ +#define TCON_2_INVERT (1 << 14) /* 1: Inverter on for TOUT3 */ +#define TCON_2_MAN (1 << 13) /* manual Update TCNTB3,TCMPB3 */ +#define TCON_2_ONOFF (1 << 12) /* 0: Stop, 1: start Timer 3 */ +#define TCON_1_AUTO (1 << 11) /* auto reload on/off for Timer 3 */ +#define TCON_1_INVERT (1 << 10) /* 1: Inverter on for TOUT3 */ +#define TCON_1_MAN (1 << 9) /* manual Update TCNTB3,TCMPB3 */ +#define TCON_1_ONOFF (1 << 8) /* 0: Stop, 1: start Timer 3 */ +#define TCON_0_AUTO (1 << 3) /* auto reload on/off for Timer 3 */ +#define TCON_0_INVERT (1 << 2) /* 1: Inverter on for TOUT3 */ +#define TCON_0_MAN (1 << 1) /* manual Update TCNTB3,TCMPB3 */ +#define TCON_0_ONOFF (1 << 0) /* 0: Stop, 1: start Timer 3 */ +#define COUNT_0_ON (TCON_0_ONOFF*1) +#define COUNT_0_OFF (TCON_0_ONOFF*0) + +#define TIMER4_AUTO (1 << 22) /* auto reload on/off for Timer 4 */ +#define TIMER4_UPDATE (1 << 21) /* manual Update TCNTB4 */ +#define TIMER4_ONOFF (1 << 20) /* 0: Stop, 1: start Timer 4 */ +#define TIMER4_ON (TIMER4_ONOFF*1) +#define TIMER4_OFF (TIMER4_ONOFF*0) +#define TIMER3_ATLOAD_ON (TCON_3_AUTO*1) +#define TIMER3_ATLAOD_OFF FClrBit(TCON, TCON_3_AUTO) +#define TIMER3_IVT_ON (TCON_3_INVERT*1) +#define TIMER3_IVT_OFF (FClrBit(TCON, TCON_3_INVERT)) +#define TIMER3_MANUP (TCON_3_MAN*1) +#define TIMER3_NOP (FClrBit(TCON, TCON_3_MAN)) +#define TIMER3_ON (TCON_3_ONOFF*1) +#define TIMER3_OFF (FClrBit(TCON, TCON_3_ONOFF)) +#define TIMER2_ATLOAD_ON (TCON_2_AUTO*1) +#define TIMER2_ATLAOD_OFF FClrBit(TCON, TCON_2_AUTO) +#define TIMER2_IVT_ON (TCON_2_INVERT*1) +#define TIMER2_IVT_OFF (FClrBit(TCON, TCON_2_INVERT)) +#define TIMER2_MANUP (TCON_2_MAN*1) +#define TIMER2_NOP (FClrBit(TCON, TCON_2_MAN)) +#define TIMER2_ON (TCON_2_ONOFF*1) +#define TIMER2_OFF (FClrBit(TCON, TCON_2_ONOFF)) +#define TIMER1_ATLOAD_ON (TCON_1_AUTO*1) +#define TIMER1_ATLAOD_OFF FClrBit(TCON, TCON_1_AUTO) +#define TIMER1_IVT_ON (TCON_1_INVERT*1) +#define TIMER1_IVT_OFF (FClrBit(TCON, TCON_1_INVERT)) +#define TIMER1_MANUP (TCON_1_MAN*1) +#define TIMER1_NOP (FClrBit(TCON, TCON_1_MAN)) +#define TIMER1_ON (TCON_1_ONOFF*1) +#define TIMER1_OFF (FClrBit(TCON, TCON_1_ONOFF)) +#define TIMER0_ATLOAD_ON (TCON_0_AUTO*1) +#define TIMER0_ATLAOD_OFF FClrBit(TCON, TCON_0_AUTO) +#define TIMER0_IVT_ON (TCON_0_INVERT*1) +#define TIMER0_IVT_OFF (FClrBit(TCON, TCON_0_INVERT)) +#define TIMER0_MANUP (TCON_0_MAN*1) +#define TIMER0_NOP (FClrBit(TCON, TCON_0_MAN)) +#define TIMER0_ON (TCON_0_ONOFF*1) +#define TIMER0_OFF (FClrBit(TCON, TCON_0_ONOFF)) + +#define TCON_TIMER1_CLR FClrFld(TCON, fTCON_TIMER1); +#define TCON_TIMER2_CLR FClrFld(TCON, fTCON_TIMER2); +#define TCON_TIMER3_CLR FClrFld(TCON, fTCON_TIMER3); + + +#define S3C24A0_TCFG_PRESCALER0_MASK (255<<0) +#define S3C24A0_TCFG_PRESCALER1_MASK (255<<8) +#define S3C24A0_TCFG_PRESCALER1_SHIFT (8) +#define S3C24A0_TCFG_DEADZONE_MASK (255<<16) +#define S3C24A0_TCFG_DEADZONE_SHIFT (16) + +#define S3C24A0_TCFG1_MUX4_DIV2 (0<<16) +#define S3C24A0_TCFG1_MUX4_DIV4 (1<<16) +#define S3C24A0_TCFG1_MUX4_DIV8 (2<<16) +#define S3C24A0_TCFG1_MUX4_DIV16 (3<<16) +#define S3C24A0_TCFG1_MUX4_TCLK1 (4<<16) +#define S3C24A0_TCFG1_MUX4_MASK (15<<16) + +#define S3C24A0_TCFG1_MUX3_DIV2 (0<<12) +#define S3C24A0_TCFG1_MUX3_DIV4 (1<<12) +#define S3C24A0_TCFG1_MUX3_DIV8 (2<<12) +#define S3C24A0_TCFG1_MUX3_DIV16 (3<<12) +#define S3C24A0_TCFG1_MUX3_TCLK1 (4<<12) +#define S3C24A0_TCFG1_MUX3_MASK (15<<12) + + +#define S3C24A0_TCFG1_MUX2_DIV2 (0<<8) +#define S3C24A0_TCFG1_MUX2_DIV4 (1<<8) +#define S3C24A0_TCFG1_MUX2_DIV8 (2<<8) +#define S3C24A0_TCFG1_MUX2_DIV16 (3<<8) +#define S3C24A0_TCFG1_MUX2_TCLK1 (4<<8) +#define S3C24A0_TCFG1_MUX2_MASK (15<<8) + + +#define S3C24A0_TCFG1_MUX1_DIV2 (0<<4) +#define S3C24A0_TCFG1_MUX1_DIV4 (1<<4) +#define S3C24A0_TCFG1_MUX1_DIV8 (2<<4) +#define S3C24A0_TCFG1_MUX1_DIV16 (3<<4) +#define S3C24A0_TCFG1_MUX1_TCLK0 (4<<4) +#define S3C24A0_TCFG1_MUX1_MASK (15<<4) + +#define S3C24A0_TCFG1_MUX0_DIV2 (0<<0) +#define S3C24A0_TCFG1_MUX0_DIV4 (1<<0) +#define S3C24A0_TCFG1_MUX0_DIV8 (2<<0) +#define S3C24A0_TCFG1_MUX0_DIV16 (3<<0) +#define S3C24A0_TCFG1_MUX0_TCLK0 (4<<0) +#define S3C24A0_TCFG1_MUX0_MASK (15<<0) + +/* for each timer, we have an count buffer, an compare buffer and + * an observation buffer +*/ + +/* WARNING - timer 4 has no buffer reg, and it's observation is at +4 */ + +#define S3C24A0_TCNTB(tmr) S3C24A0_TIMERREG2(tmr, 0x00) +#define S3C24A0_TCMPB(tmr) S3C24A0_TIMERREG2(tmr, 0x04) +#define S3C24A0_TCNTO(tmr) S3C24A0_TIMERREG2(tmr, (((tmr) == 4) ? 0x04 : 0x08)) + +#define S3C24A0_TCON_T4RELOAD (1<<22) +#define S3C24A0_TCON_T4MANUALUPD (1<<21) +#define S3C24A0_TCON_T4START (1<<20) + +#define S3C24A0_TCON_T3RELOAD (1<<19) +#define S3C24A0_TCON_T3INVERT (1<<18) +#define S3C24A0_TCON_T3MANUALUPD (1<<17) +#define S3C24A0_TCON_T3START (1<<16) + +#define S3C24A0_TCON_T2RELOAD (1<<15) +#define S3C24A0_TCON_T2INVERT (1<<14) +#define S3C24A0_TCON_T2MANUALUPD (1<<13) +#define S3C24A0_TCON_T2START (1<<12) + +#define S3C24A0_TCON_T1RELOAD (1<<11) +#define S3C24A0_TCON_T1INVERT (1<<10) +#define S3C24A0_TCON_T1MANUALUPD (1<<9) +#define S3C24A0_TCON_T1START (1<<8) + +#define S3C24A0_TCON_T0DEADZONE (1<<4) +#define S3C24A0_TCON_T0RELOAD (1<<3) +#define S3C24A0_TCON_T0INVERT (1<<2) +#define S3C24A0_TCON_T0MANUALUPD (1<<1) +#define S3C24A0_TCON_T0START (1<<0) + +#endif /* __ASM_ARCH_REGS_TIMER_H */ + + + diff --git a/include/asm-arm/arch-s3c24a0/regs-udc.h b/include/asm-arm/arch-s3c24a0/regs-udc.h new file mode 100644 index 0000000..b01904c --- /dev/null +++ b/include/asm-arm/arch-s3c24a0/regs-udc.h @@ -0,0 +1,166 @@ +/* linux/include/asm/arch-s3c24a0/regs-udc.h + * + * Id: regs-udc.h + * + * S3C24A0 USB Device register definitions + * + * 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/regs-udc.h, written by + * Ben Dooks + * + */ + +#ifndef __ASM_ARCH_REGS_UDC_H +#define __ASM_ARCH_REGS_UDC_H + + +#define S3C24A0_USBDREG(x) ((x) + S3C24A0_VA_USBDEV) + +#define S3C24A0_UDC_FUNC_ADDR_REG S3C24A0_USBDREG(0x0140) +#define S3C24A0_UDC_PWR_REG S3C24A0_USBDREG(0x0144) +#define S3C24A0_UDC_EP_INT_REG S3C24A0_USBDREG(0x0148) + +#define S3C24A0_UDC_USB_INT_REG S3C24A0_USBDREG(0x0158) +#define S3C24A0_UDC_EP_INT_EN_REG S3C24A0_USBDREG(0x015c) + +#define S3C24A0_UDC_USB_INT_EN_REG S3C24A0_USBDREG(0x016c) + +#define S3C24A0_UDC_FRAME_NUM1_REG S3C24A0_USBDREG(0x0170) +#define S3C24A0_UDC_FRAME_NUM2_REG S3C24A0_USBDREG(0x0174) + +#define S3C24A0_UDC_EP0_FIFO_REG S3C24A0_USBDREG(0x01c0) +#define S3C24A0_UDC_EP1_FIFO_REG S3C24A0_USBDREG(0x01c4) +#define S3C24A0_UDC_EP2_FIFO_REG S3C24A0_USBDREG(0x01c8) +#define S3C24A0_UDC_EP3_FIFO_REG S3C24A0_USBDREG(0x01cc) +#define S3C24A0_UDC_EP4_FIFO_REG S3C24A0_USBDREG(0x01d0) + +#define S3C24A0_UDC_EP1_DMA_CON S3C24A0_USBDREG(0x0200) +#define S3C24A0_UDC_EP1_DMA_UNIT S3C24A0_USBDREG(0x0204) +#define S3C24A0_UDC_EP1_DMA_FIFO S3C24A0_USBDREG(0x0208) +#define S3C24A0_UDC_EP1_DMA_TTC_L S3C24A0_USBDREG(0x020c) +#define S3C24A0_UDC_EP1_DMA_TTC_M S3C24A0_USBDREG(0x0210) +#define S3C24A0_UDC_EP1_DMA_TTC_H S3C24A0_USBDREG(0x0214) + +#define S3C24A0_UDC_EP2_DMA_CON S3C24A0_USBDREG(0x0218) +#define S3C24A0_UDC_EP2_DMA_UNIT S3C24A0_USBDREG(0x021c) +#define S3C24A0_UDC_EP2_DMA_FIFO S3C24A0_USBDREG(0x0220) +#define S3C24A0_UDC_EP2_DMA_TTC_L S3C24A0_USBDREG(0x0224) +#define S3C24A0_UDC_EP2_DMA_TTC_M S3C24A0_USBDREG(0x0228) +#define S3C24A0_UDC_EP2_DMA_TTC_H S3C24A0_USBDREG(0x022c) + +#define S3C24A0_UDC_EP3_DMA_CON S3C24A0_USBDREG(0x0240) +#define S3C24A0_UDC_EP3_DMA_UNIT S3C24A0_USBDREG(0x0244) +#define S3C24A0_UDC_EP3_DMA_FIFO S3C24A0_USBDREG(0x0248) +#define S3C24A0_UDC_EP3_DMA_TTC_L S3C24A0_USBDREG(0x024c) +#define S3C24A0_UDC_EP3_DMA_TTC_M S3C24A0_USBDREG(0x0250) +#define S3C24A0_UDC_EP3_DMA_TTC_H S3C24A0_USBDREG(0x0254) + +#define S3C24A0_UDC_EP4_DMA_CON S3C24A0_USBDREG(0x0258) +#define S3C24A0_UDC_EP4_DMA_UNIT S3C24A0_USBDREG(0x025c) +#define S3C24A0_UDC_EP4_DMA_FIFO S3C24A0_USBDREG(0x0260) +#define S3C24A0_UDC_EP4_DMA_TTC_L S3C24A0_USBDREG(0x0264) +#define S3C24A0_UDC_EP4_DMA_TTC_M S3C24A0_USBDREG(0x0268) +#define S3C24A0_UDC_EP4_DMA_TTC_H S3C24A0_USBDREG(0x026c) + +#define S3C24A0_UDC_INDEX_REG S3C24A0_USBDREG(0x0178) + +/* indexed registers */ + +#define S3C24A0_UDC_MAXP_REG S3C24A0_USBDREG(0x0180) + +#define S3C24A0_UDC_EP0_CSR_REG S3C24A0_USBDREG(0x0184) + +#define S3C24A0_UDC_IN_CSR1_REG S3C24A0_USBDREG(0x0184) +#define S3C24A0_UDC_IN_CSR2_REG S3C24A0_USBDREG(0x0188) + +#define S3C24A0_UDC_OUT_CSR1_REG S3C24A0_USBDREG(0x0190) +#define S3C24A0_UDC_OUT_CSR2_REG S3C24A0_USBDREG(0x0194) +#define S3C24A0_UDC_OUT_FIFO_CNT1_REG S3C24A0_USBDREG(0x0198) +#define S3C24A0_UDC_OUT_FIFO_CNT2_REG S3C24A0_USBDREG(0x019c) + + + +#define S3C24A0_UDC_PWR_ISOUP (1<<7) // R/W +#define S3C24A0_UDC_PWR_RESET (1<<3) // R +#define S3C24A0_UDC_PWR_RESUME (1<<2) // R/W +#define S3C24A0_UDC_PWR_SUSPEND (1<<1) // R +#define S3C24A0_UDC_PWR_ENSUSPEND (1<<0) // R/W + +#define S3C24A0_UDC_PWR_DEFAULT 0x00 + +#define S3C24A0_UDC_INT_EP4 (1<<4) // R/W (clear only) +#define S3C24A0_UDC_INT_EP3 (1<<3) // R/W (clear only) +#define S3C24A0_UDC_INT_EP2 (1<<2) // R/W (clear only) +#define S3C24A0_UDC_INT_EP1 (1<<1) // R/W (clear only) +#define S3C24A0_UDC_INT_EP0 (1<<0) // R/W (clear only) + +#define S3C24A0_UDC_USBINT_RESET (1<<2) // R/W (clear only) +#define S3C24A0_UDC_USBINT_RESUME (1<<1) // R/W (clear only) +#define S3C24A0_UDC_USBINT_SUSPEND (1<<0) // R/W (clear only) + +#define S3C24A0_UDC_INTE_EP4 (1<<4) // R/W +#define S3C24A0_UDC_INTE_EP3 (1<<3) // R/W +#define S3C24A0_UDC_INTE_EP2 (1<<2) // R/W +#define S3C24A0_UDC_INTE_EP1 (1<<1) // R/W +#define S3C24A0_UDC_INTE_EP0 (1<<0) // R/W + +#define S3C24A0_UDC_USBINTE_RESET (1<<2) // R/W +#define S3C24A0_UDC_USBINTE_SUSPEND (1<<0) // R/W + + +#define S3C24A0_UDC_INDEX_EP0 (0x00) +#define S3C24A0_UDC_INDEX_EP1 (0x01) // ?? +#define S3C24A0_UDC_INDEX_EP2 (0x02) // ?? +#define S3C24A0_UDC_INDEX_EP3 (0x03) // ?? +#define S3C24A0_UDC_INDEX_EP4 (0x04) // ?? + +#define S3C24A0_UDC_ICSR1_CLRDT (1<<6) // R/W +#define S3C24A0_UDC_ICSR1_SENTSTL (1<<5) // R/W (clear only) +#define S3C24A0_UDC_ICSR1_SENDSTL (1<<4) // R/W +#define S3C24A0_UDC_ICSR1_FFLUSH (1<<3) // W (set only) +#define S3C24A0_UDC_ICSR1_UNDRUN (1<<2) // R/W (clear only) +#define S3C24A0_UDC_ICSR1_PKTRDY (1<<0) // R/W (set only) + +#define S3C24A0_UDC_ICSR2_AUTOSET (1<<7) // R/W +#define S3C24A0_UDC_ICSR2_ISO (1<<6) // R/W +#define S3C24A0_UDC_ICSR2_MODEIN (1<<5) // R/W +#define S3C24A0_UDC_ICSR2_DMAIEN (1<<4) // R/W + +#define S3C24A0_UDC_OCSR1_CLRDT (1<<7) // R/W +#define S3C24A0_UDC_OCSR1_SENTSTL (1<<6) // R/W (clear only) +#define S3C24A0_UDC_OCSR1_SENDSTL (1<<5) // R/W +#define S3C24A0_UDC_OCSR1_FFLUSH (1<<4) // R/W +#define S3C24A0_UDC_OCSR1_DERROR (1<<3) // R +#define S3C24A0_UDC_OCSR1_OVRRUN (1<<2) // R/W (clear only) +#define S3C24A0_UDC_OCSR1_PKTRDY (1<<0) // R/W (clear only) + +#define S3C24A0_UDC_OCSR2_AUTOCLR (1<<7) // R/W +#define S3C24A0_UDC_OCSR2_ISO (1<<6) // R/W +#define S3C24A0_UDC_OCSR2_DMAIEN (1<<5) // R/W + +#define S3C24A0_UDC_SETIX(x) \ + __raw_writel(S3C24A0_UDC_INDEX_ ## x, S3C24A0_UDC_INDEX_REG); + + +#define S3C24A0_UDC_EP0_CSR_OPKRDY (1<<0) +#define S3C24A0_UDC_EP0_CSR_IPKRDY (1<<1) +#define S3C24A0_UDC_EP0_CSR_SENTSTL (1<<2) +#define S3C24A0_UDC_EP0_CSR_DE (1<<3) +#define S3C24A0_UDC_EP0_CSR_SE (1<<4) +#define S3C24A0_UDC_EP0_CSR_SENDSTL (1<<5) +#define S3C24A0_UDC_EP0_CSR_SOPKTRDY (1<<6) +#define S3C24A0_UDC_EP0_CSR_SSE (1<<7) + +#define S3C24A0_UDC_MAXP_8 (1<<0) +#define S3C24A0_UDC_MAXP_16 (1<<1) +#define S3C24A0_UDC_MAXP_32 (1<<2) +#define S3C24A0_UDC_MAXP_64 (1<<3) + + +#endif diff --git a/include/asm-arm/arch-s3c24a0/regs-watchdog.h b/include/asm-arm/arch-s3c24a0/regs-watchdog.h new file mode 100644 index 0000000..e329dcc --- /dev/null +++ b/include/asm-arm/arch-s3c24a0/regs-watchdog.h @@ -0,0 +1,47 @@ +/* linux/include/asm/arch-s3c24a0/regs-watchdog.h + * + * Id: regs-watchdog.h + * + * S3C24A0 WatchDog register definitions + * + * 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/regs-watchdog.h, written by + * Ben Dooks + * + */ + + +#ifndef __ASM_ARCH_REGS_WATCHDOG_H +#define __ASM_ARCH_REGS_WATCHDOG_H + +#define S3C24A0_WDOGREG(x) ((x) + S3C24A0_VA_WATCHDOG) + +#define S3C24A0_WTCON S3C24A0_WDOGREG(0x00) +#define S3C24A0_WTDAT S3C24A0_WDOGREG(0x04) +#define S3C24A0_WTCNT S3C24A0_WDOGREG(0x08) + +/* the watchdog can either generate a reset pulse, or an + * interrupt. + */ + +#define S3C24A0_WTCON_RSTEN (0x01) +#define S3C24A0_WTCON_INTEN (1<<2) +#define S3C24A0_WTCON_ENABLE (1<<5) + +#define S3C24A0_WTCON_DIV16 (0<<3) +#define S3C24A0_WTCON_DIV32 (1<<3) +#define S3C24A0_WTCON_DIV64 (2<<3) +#define S3C24A0_WTCON_DIV128 (3<<3) + +#define S3C24A0_WTCON_PRESCALE(x) ((x) << 8) +#define S3C24A0_WTCON_PRESCALE_MASK (0xff00) + +#endif /* __ASM_ARCH_REGS_WATCHDOG_H */ + + diff --git a/include/asm-arm/arch-s3c24a0/system.h b/include/asm-arm/arch-s3c24a0/system.h new file mode 100644 index 0000000..0606790 --- /dev/null +++ b/include/asm-arm/arch-s3c24a0/system.h @@ -0,0 +1,93 @@ +/* linux/include/asm-arm/arch-s3c24a0/system.h + * + * $Id: system.h,v 1.1.1.1 2006/02/13 05:23:03 ihlee215 Exp $ + * + * S3C24A0 - System function defines and includes + * + * 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/dma.h, written by + * Ben Dooks + */ + +#include +#include + +#include +#include + +#include +#include + +void (*s3c24xx_idle)(void); + +void s3c24xx_default_idle(void) +{ +#if 0 + unsigned long reg = S3C24A0_CLKCON; + unsigned long tmp; + int i; + + /* S3C24A0 , It doesn't work , Hardware Idle mode */ + /* idle the system by using the idle mode which will wait for an + * interrupt to happen before restarting the system. + */ + + /* Warning: going into idle state upsets jtag scanning */ + + __raw_writel(__raw_readl(reg) | (1<<2), reg); + + /* the samsung port seems to do a loop and then unset idle.. */ + for (i = 0; i < 50; i++) { + tmp += __raw_readl(reg); /* ensure loop not optimised out */ + } + + /* this bit is not cleared on re-start... */ + + __raw_writel(__raw_readl(reg) & ~(1<<2), reg); +#else + return; +#endif +} + +static void arch_idle(void) +{ + if (s3c24xx_idle != NULL) + (s3c24xx_idle)(); + else + s3c24xx_default_idle(); +} + + +static void +arch_reset(char mode) +{ + if (mode == 's') { + cpu_reset(0); + } + + printk("arch_reset: attempting watchdog reset\n"); + + __raw_writel(0, S3C24A0_WTCON); /* disable watchdog, to be safe */ + + /* put initial values into count and data */ + __raw_writel(0x100, S3C24A0_WTCNT); + __raw_writel(0x100, S3C24A0_WTDAT); + + /* set the watchdog to go and reset... */ + __raw_writel(S3C24A0_WTCON_ENABLE|S3C24A0_WTCON_DIV16|S3C24A0_WTCON_RSTEN | + S3C24A0_WTCON_PRESCALE(0x80), S3C24A0_WTCON); + + /* wait for reset to assert... */ + mdelay(5000); + + printk(KERN_ERR "Watchdog reset failed to assert reset\n"); + + /* we'll take a jump through zero as a poor second */ + cpu_reset(0); +} diff --git a/include/asm-arm/arch-s3c24a0/timex.h b/include/asm-arm/arch-s3c24a0/timex.h new file mode 100644 index 0000000..5f3be40 --- /dev/null +++ b/include/asm-arm/arch-s3c24a0/timex.h @@ -0,0 +1,27 @@ +/* linux/include/asm-arm/arch-s3c24a0/timex.h + * + * $Id: timex.h,v 1.1.1.1 2006/02/13 05:23:03 ihlee215 Exp $ + * + * S3C2410 - time parameters + * + * 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_TIMEX_H +#define __ASM_ARCH_TIMEX_H + +#define PRESCALER 19 +#define DIVIDER 2 + +#define PCLK_INPUT 51000000 +/* CLOCK_TICK_RATE is the time of a timer count desence, minsung says*/ +#define CLOCK_TICK_RATE (PCLK_INPUT / ((PRESCALER+1) * DIVIDER)) + + +#endif /* __ASM_ARCH_TIMEX_H */ diff --git a/include/asm-arm/arch-s3c24a0/uncompress.h b/include/asm-arm/arch-s3c24a0/uncompress.h new file mode 100644 index 0000000..91c3ae7 --- /dev/null +++ b/include/asm-arm/arch-s3c24a0/uncompress.h @@ -0,0 +1,77 @@ +/* + * include/asm-arm/arch-s3c24a0/uncompress.h + * + * $Id: uncompress.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. + */ + + +/* + * The following code assumes the serial port has already been + * initialized by the bootloader. We use only UART1 on S3C24xx + */ + +#ifdef CONFIG_MACH_S3C24A0 +#define ULCON 0x0 +#define UTRSTAT 0x10 +#define UTXH 0x20 +#define UTRSTAT_TX_EMPTY (1 << 2) + +#define UART0 0x44400000 +#define UART1 0x44404000 + +#define UART(x) (*(volatile unsigned long *)(serial_port + (x))) + + +/* FIXME : amitb : remove and replace with proper putc() */ +static void putc(int ch) +{ + unsigned long serial_port; + + do { + serial_port = UART0; + if (UART(ULCON) == 0x3) + break; + serial_port = UART1; + if (UART(ULCON) == 0x3) + break; + } while (0); + + while (!(UART(UTRSTAT) & UTRSTAT_TX_EMPTY)); + + UART(UTXH) = ch; +} + +static inline void flush(void) +{ +} + +#else + +#define UART_UTRSTAT (*(volatile unsigned long *)0x44400010) +#define UART_UTXH (*(volatile unsigned long *)0x44400020) /* littel endian */ +#define UTRSTAT_TX_EMPTY (1 << 2) + +static void putstr(const char *s) +{ + while (*s) { + while (!(UART_UTRSTAT & UTRSTAT_TX_EMPTY)); + + UART_UTXH = *s; + + if (*s == '\n') { + while (!(UART_UTRSTAT & UTRSTAT_TX_EMPTY)); + + UART_UTXH = '\r'; + } + s++; + } + while (!(UART_UTRSTAT & UTRSTAT_TX_EMPTY)); +} +#endif + +#define arch_decomp_setup() +#define arch_decomp_wdog() diff --git a/include/asm-arm/arch-s3c24a0/usb-control.h b/include/asm-arm/arch-s3c24a0/usb-control.h new file mode 100644 index 0000000..8dbf07c --- /dev/null +++ b/include/asm-arm/arch-s3c24a0/usb-control.h @@ -0,0 +1,46 @@ +/* linux/include/asm-arm/arch-s3c24a0/usb-control.h + * + * $Id: usb-control.h,v 1.1.1.1 2006/02/13 05:23:03 ihlee215 Exp $ + * + * S3C24A0 - usb port information + * + * 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/usb-control.h, written by + * Ben Dooks + */ + +#ifndef __ASM_ARCH_USBCONTROL_H +#define __ASM_ARCH_USBCONTROL_H + +#define S3C_HCDFLG_USED (1) + +struct s3c24a0_hcd_port { + unsigned char flags; + unsigned char power; + unsigned char oc_status; + unsigned char oc_changed; +}; + +struct s3c24a0_hcd_info { + struct usb_hcd *hcd; + struct s3c24a0_hcd_port port[2]; + + void (*power_control)(int port, int to); + void (*enable_oc)(struct s3c24a0_hcd_info *, int on); + void (*report_oc)(struct s3c24a0_hcd_info *, int ports); +}; + +static void inline s3c24a0_report_oc(struct s3c24a0_hcd_info *info, int ports) +{ + if (info->report_oc != NULL) { + (info->report_oc)(info, ports); + } +} + +#endif /*__ASM_ARCH_USBCONTROL_H */ diff --git a/include/asm-arm/arch-s3c24a0/vmalloc.h b/include/asm-arm/arch-s3c24a0/vmalloc.h new file mode 100644 index 0000000..bf821b4 --- /dev/null +++ b/include/asm-arm/arch-s3c24a0/vmalloc.h @@ -0,0 +1,36 @@ +/* linux/include/asm-arm/arch-s3c24a0/vmalloc.h + * + * $Id: vmalloc.h,v 1.1.1.1 2006/02/13 05:23:03 ihlee215 Exp $ + * + * S3C2410 vmalloc definition + * + * 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/vmalloc.h, written by + * Ben Dooks + * + */ + +#ifndef __ASM_ARCH_VMALLOC_H +#define __ASM_ARCH_VMALLOC_H + +/* + * Just any arbitrary offset to the start of the vmalloc VM area: the + * current 8MB value just means that there will be a 8MB "hole" after the + * physical memory until the kernel virtual memory starts. That means that + * any out-of-bounds memory accesses will hopefully be caught. + * The vmalloc() routines leaves a hole of 4kB between each vmalloced + * area for the same reason. ;) + */ + +#define VMALLOC_OFFSET (8*1024*1024) +#define VMALLOC_START (((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1)) +#define VMALLOC_VMADDR(x) ((unsigned long)(x)) +#define VMALLOC_END (PAGE_OFFSET + 0x10000000) + +#endif /* __ASM_ARCH_VMALLOC_H */ diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index cf23813..665d81d 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h @@ -135,6 +135,9 @@ #define PORT_S3C2412 73 /* Xilinx uartlite */ #define PORT_UARTLITE 74 +/* FIX ME (added to make s3c24a0 serial driver work, may change ) */ +#define PORT_S3C24A0 75 + #ifdef __KERNEL__ #include In conclusion: There seems to be a lot of code in this patch which is either badly copied, or should be shared with the original port. The use of the bitfields is strongle discouraged. There are a number of formatting problems, including use of the // as a comment character (we're not writing C++ here). Also use of #if 0 to block out code.. if it is being submitted, please ensure a decision has been made! Please do not include CVS IDs