diff options
author | Ben Dooks <ben-linux@fluff.org> | 2008-12-18 14:52:04 +0000 |
---|---|---|
committer | Ben Dooks <ben-linux@fluff.org> | 2008-12-18 14:52:04 +0000 |
commit | 7f2754378f3522a42daafdbb9d2385f341008454 (patch) | |
tree | 7a6223f270cdf53067a70c2e86b2190d3577c23d | |
parent | c6ad115876763e4f15055982ecb9579cb7abab5f (diff) | |
parent | a9c5d23ac724a3b908833cafbbbd49abe4741b86 (diff) |
Merge branch 'next-s3c64xx' into next-merged
80 files changed, 4849 insertions, 216 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 4546f8b2ce8..f512b5530ef 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -517,6 +517,13 @@ config ARCH_S3C2410 BAST (<http://www.simtec.co.uk/products/EB110ITX/>), the IPAQ 1940 or the Samsung SMDK2410 development board (and derivatives). +config ARCH_S3C64XX + bool "Samsung S3C64XX" + select GENERIC_GPIO + select HAVE_CLK + help + Samsung S3C64XX series based systems + config ARCH_SHARK bool "Shark" select CPU_SA110 @@ -620,6 +627,7 @@ source "arch/arm/mach-orion5x/Kconfig" source "arch/arm/mach-kirkwood/Kconfig" source "arch/arm/plat-s3c24xx/Kconfig" +source "arch/arm/plat-s3c64xx/Kconfig" source "arch/arm/plat-s3c/Kconfig" if ARCH_S3C2410 @@ -631,6 +639,11 @@ source "arch/arm/mach-s3c2442/Kconfig" source "arch/arm/mach-s3c2443/Kconfig" endif +if ARCH_S3C64XX +source "arch/arm/mach-s3c6400/Kconfig" +source "arch/arm/mach-s3c6410/Kconfig" +endif + source "arch/arm/mach-lh7a40x/Kconfig" source "arch/arm/mach-imx/Kconfig" diff --git a/arch/arm/Makefile b/arch/arm/Makefile index 260864f3f01..3ce88d719ce 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -121,7 +121,10 @@ endif machine-$(CONFIG_ARCH_OMAP3) := omap2 plat-$(CONFIG_ARCH_OMAP) := omap machine-$(CONFIG_ARCH_S3C2410) := s3c2410 s3c2400 s3c2412 s3c2440 s3c2442 s3c2443 + machine-$(CONFIG_ARCH_S3C24A0) := s3c24a0 plat-$(CONFIG_PLAT_S3C24XX) := s3c24xx s3c + machine-$(CONFIG_ARCH_S3C64XX) := s3c6400 s3c6410 + plat-$(CONFIG_PLAT_S3C64XX) := s3c64xx s3c machine-$(CONFIG_ARCH_LH7A40X) := lh7a40x machine-$(CONFIG_ARCH_VERSATILE) := versatile machine-$(CONFIG_ARCH_IMX) := imx diff --git a/arch/arm/common/vic.c b/arch/arm/common/vic.c index f1e4b8f60ca..ecf0bfbab10 100644 --- a/arch/arm/common/vic.c +++ b/arch/arm/common/vic.c @@ -69,12 +69,12 @@ void __init vic_init(void __iomem *base, unsigned int irq_start, /* * Make sure we clear all existing interrupts */ - writel(0, base + VIC_VECT_ADDR); + writel(0, base + VIC_PL190_VECT_ADDR); for (i = 0; i < 19; i++) { unsigned int value; - value = readl(base + VIC_VECT_ADDR); - writel(value, base + VIC_VECT_ADDR); + value = readl(base + VIC_PL190_VECT_ADDR); + writel(value, base + VIC_PL190_VECT_ADDR); } for (i = 0; i < 16; i++) { @@ -82,7 +82,7 @@ void __init vic_init(void __iomem *base, unsigned int irq_start, writel(VIC_VECT_CNTL_ENABLE | i, reg); } - writel(32, base + VIC_DEF_VECT_ADDR); + writel(32, base + VIC_PL190_DEF_VECT_ADDR); for (i = 0; i < 32; i++) { unsigned int irq = irq_start + i; diff --git a/arch/arm/configs/s3c6400_defconfig b/arch/arm/configs/s3c6400_defconfig new file mode 100644 index 00000000000..3a50716d443 --- /dev/null +++ b/arch/arm/configs/s3c6400_defconfig @@ -0,0 +1,733 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.27 +# Fri Oct 17 09:20:54 2008 +# +CONFIG_ARM=y +CONFIG_SYS_SUPPORTS_APM_EMULATION=y +CONFIG_GENERIC_GPIO=y +# CONFIG_GENERIC_TIME is not set +# CONFIG_GENERIC_CLOCKEVENTS is not set +CONFIG_MMU=y +CONFIG_NO_IOPORT=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_HAVE_LATENCYTOP_SUPPORT=y +CONFIG_LOCKDEP_SUPPORT=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_GENERIC_HARDIRQS_NO__DO_IRQ=y +CONFIG_VECTORS_BASE=0xffff0000 +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" + +# +# General setup +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_INIT_ENV_ARG_LIMIT=32 +CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y +CONFIG_SWAP=y +# CONFIG_SYSVIPC is not set +# CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_IKCONFIG is not set +CONFIG_LOG_BUF_SHIFT=17 +# CONFIG_CGROUPS is not set +# CONFIG_GROUP_SCHED is not set +CONFIG_SYSFS_DEPRECATED=y +CONFIG_SYSFS_DEPRECATED_V2=y +# CONFIG_RELAY is not set +CONFIG_NAMESPACES=y +# CONFIG_UTS_NS is not set +# CONFIG_USER_NS is not set +# CONFIG_PID_NS is not set +CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SYSCTL=y +# CONFIG_EMBEDDED is not set +CONFIG_UID16=y +CONFIG_SYSCTL_SYSCALL=y +CONFIG_KALLSYMS=y +CONFIG_KALLSYMS_ALL=y +# CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_COMPAT_BRK=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_ANON_INODES=y +CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y +CONFIG_EVENTFD=y +CONFIG_SHMEM=y +CONFIG_AIO=y +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_SLUB_DEBUG=y +# CONFIG_SLAB is not set +CONFIG_SLUB=y +# CONFIG_SLOB is not set +# CONFIG_PROFILING is not set +# CONFIG_MARKERS is not set +CONFIG_HAVE_OPROFILE=y +# CONFIG_KPROBES is not set +CONFIG_HAVE_KPROBES=y +CONFIG_HAVE_KRETPROBES=y +CONFIG_HAVE_CLK=y +CONFIG_HAVE_GENERIC_DMA_COHERENT=y +CONFIG_SLABINFO=y +CONFIG_RT_MUTEXES=y +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 +CONFIG_MODULES=y +# CONFIG_MODULE_FORCE_LOAD is not set +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 +CONFIG_BLOCK=y +CONFIG_LBD=y +# CONFIG_BLK_DEV_IO_TRACE is not set +CONFIG_LSF=y +# CONFIG_BLK_DEV_BSG is not set +# CONFIG_BLK_DEV_INTEGRITY is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +# CONFIG_DEFAULT_AS is not set +# CONFIG_DEFAULT_DEADLINE is not set +CONFIG_DEFAULT_CFQ=y +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="cfq" +CONFIG_CLASSIC_RCU=y + +# +# 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_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_IOP13XX is not set +# CONFIG_ARCH_IOP32X is not set +# CONFIG_ARCH_IOP33X is not set +# CONFIG_ARCH_IXP23XX is not set +# CONFIG_ARCH_IXP2000 is not set +# CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_L7200 is not set +# CONFIG_ARCH_KIRKWOOD is not set +# CONFIG_ARCH_KS8695 is not set +# CONFIG_ARCH_NS9XXX is not set +# CONFIG_ARCH_LOKI is not set +# CONFIG_ARCH_MV78XX0 is not set +# CONFIG_ARCH_MXC is not set +# CONFIG_ARCH_ORION5X 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_ARCH_S3C24A0 is not set +CONFIG_ARCH_S3C64XX=y +# CONFIG_ARCH_SHARK is not set +# CONFIG_ARCH_LH7A40X is not set +# CONFIG_ARCH_DAVINCI is not set +# CONFIG_ARCH_OMAP is not set +# CONFIG_ARCH_MSM7X00A is not set +CONFIG_PLAT_S3C64XX=y +CONFIG_CPU_S3C6400_INIT=y +CONFIG_CPU_S3C6400_CLOCK=y +CONFIG_PLAT_S3C=y + +# +# Boot options +# +CONFIG_S3C_BOOT_ERROR_RESET=y + +# +# Power management +# +CONFIG_S3C_LOWLEVEL_UART_PORT=0 +CONFIG_CPU_S3C6410=y +CONFIG_MACH_SMDK6410=y + +# +# Processor Type +# +CONFIG_CPU_32=y +CONFIG_CPU_V6=y +CONFIG_CPU_32v6K=y +CONFIG_CPU_32v6=y +CONFIG_CPU_ABRT_EV6=y +CONFIG_CPU_PABRT_NOIFAR=y +CONFIG_CPU_CACHE_V6=y +CONFIG_CPU_CACHE_VIPT=y +CONFIG_CPU_COPY_V6=y +CONFIG_CPU_TLB_V6=y +CONFIG_CPU_HAS_ASID=y +CONFIG_CPU_CP15=y +CONFIG_CPU_CP15_MMU=y + +# +# Processor Features +# +CONFIG_ARM_THUMB=y +# CONFIG_CPU_ICACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_DISABLE is not set +# CONFIG_CPU_BPREDICT_DISABLE is not set +# CONFIG_OUTER_CACHE is not set +CONFIG_ARM_VIC=y + +# +# Bus support +# +# CONFIG_PCI_SYSCALL is not set +# CONFIG_ARCH_SUPPORTS_MSI is not set +# CONFIG_PCCARD is not set + +# +# Kernel Features +# +CONFIG_VMSPLIT_3G=y +# CONFIG_VMSPLIT_2G is not set +# CONFIG_VMSPLIT_1G is not set +CONFIG_PAGE_OFFSET=0xC0000000 +# CONFIG_PREEMPT is not set +CONFIG_HZ=100 +CONFIG_AEABI=y +CONFIG_OABI_COMPAT=y +CONFIG_ARCH_FLATMEM_HAS_HOLES=y +# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set +# CONFIG_ARCH_SELECT_MEMORY_MODEL 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_PAGEFLAGS_EXTENDED=y +CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_RESOURCES_64BIT is not set +CONFIG_ZONE_DMA_FLAG=0 +CONFIG_VIRT_TO_BUS=y +CONFIG_ALIGNMENT_TRAP=y + +# +# Boot options +# +CONFIG_ZBOOT_ROM_TEXT=0 +CONFIG_ZBOOT_ROM_BSS=0 +CONFIG_CMDLINE="console=ttySAC0,115200 root=/dev/ram init=/bin/bash initrd=0x51000000,4M" +# CONFIG_XIP_KERNEL is not set +# CONFIG_KEXEC is not set + +# +# CPU Power Management +# +# CONFIG_CPU_IDLE is not set + +# +# Floating point emulation +# + +# +# At least one emulation must be selected +# +# CONFIG_FPE_NWFPE is not set +# CONFIG_FPE_FASTFPE is not set +CONFIG_VFP=y + +# +# Userspace binary formats +# +CONFIG_BINFMT_ELF=y +CONFIG_HAVE_AOUT=y +# CONFIG_BINFMT_AOUT is not set +# CONFIG_BINFMT_MISC is not set + +# +# Power management options +# +# CONFIG_PM is not set +CONFIG_ARCH_SUSPEND_POSSIBLE=y +# CONFIG_NET is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y +CONFIG_FIRMWARE_IN_KERNEL=y +CONFIG_EXTRA_FIRMWARE="" +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_DEBUG_DEVRES is not set +# CONFIG_SYS_HYPERVISOR is not set +# CONFIG_MTD is not set +# CONFIG_PARPORT is not set +CONFIG_BLK_DEV=y +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=y +# CONFIG_BLK_DEV_CRYPTOLOOP is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=4096 +# CONFIG_BLK_DEV_XIP is not set +# CONFIG_CDROM_PKTCDVD is not set +CONFIG_MISC_DEVICES=y +# CONFIG_EEPROM_93CX6 is not set +# CONFIG_ENCLOSURE_SERVICES is not set +CONFIG_HAVE_IDE=y +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +# CONFIG_SCSI is not set +# CONFIG_SCSI_DMA is not set +# CONFIG_SCSI_NETLINK is not set +# CONFIG_ATA is not set +# CONFIG_MD is not set + +# +# Input device support +# +CONFIG_INPUT=y +# CONFIG_INPUT_FF_MEMLESS is not set +# CONFIG_INPUT_POLLDEV is not set + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +CONFIG_INPUT_KEYBOARD=y +CONFIG_KEYBOARD_ATKBD=y +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_LKKBD is not set +# CONFIG_KEYBOARD_XTKBD is not set +# CONFIG_KEYBOARD_NEWTON is not set +# CONFIG_KEYBOARD_STOWAWAY is not set +# CONFIG_KEYBOARD_GPIO is not set +CONFIG_INPUT_MOUSE=y +CONFIG_MOUSE_PS2=y +CONFIG_MOUSE_PS2_ALPS=y +CONFIG_MOUSE_PS2_LOGIPS2PP=y +CONFIG_MOUSE_PS2_SYNAPTICS=y +CONFIG_MOUSE_PS2_LIFEBOOK=y +CONFIG_MOUSE_PS2_TRACKPOINT=y +# CONFIG_MOUSE_PS2_TOUCHKIT is not set +# CONFIG_MOUSE_SERIAL is not set +# CONFIG_MOUSE_APPLETOUCH is not set +# CONFIG_MOUSE_BCM5974 is not set +# CONFIG_MOUSE_VSXXXAA is not set +# CONFIG_MOUSE_GPIO is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TABLET is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +CONFIG_SERIO=y +CONFIG_SERIO_SERPORT=y +CONFIG_SERIO_LIBPS2=y +# CONFIG_SERIO_RAW is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_CONSOLE_TRANSLATIONS=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_VT_HW_CONSOLE_BINDING is not set +CONFIG_DEVKMEM=y +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +# CONFIG_SERIAL_8250_CONSOLE is not set +CONFIG_SERIAL_8250_NR_UARTS=4 +CONFIG_SERIAL_8250_RUNTIME_UARTS=4 +# CONFIG_SERIAL_8250_EXTENDED is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_SAMSUNG=y +# CONFIG_SERIAL_SAMSUNG_DEBUG is not set +CONFIG_SERIAL_SAMSUNG_CONSOLE=y +CONFIG_SERIAL_S3C6400=y +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 +# CONFIG_IPMI_HANDLER is not set +CONFIG_HW_RANDOM=y +# CONFIG_NVRAM is not set +# CONFIG_R3964 is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_TCG_TPM is not set +# CONFIG_I2C is not set +# CONFIG_SPI is not set +CONFIG_ARCH_REQUIRE_GPIOLIB=y +CONFIG_GPIOLIB=y +# CONFIG_DEBUG_GPIO is not set +# CONFIG_GPIO_SYSFS is not set + +# +# I2C GPIO expanders: +# + +# +# PCI GPIO expanders: +# + +# +# SPI GPIO expanders: +# +# CONFIG_W1 is not set +# CONFIG_POWER_SUPPLY is not set +CONFIG_HWMON=y +# CONFIG_HWMON_VID is not set +# CONFIG_SENSORS_F71805F is not set +# CONFIG_SENSORS_F71882FG is not set +# CONFIG_SENSORS_IT87 is not set +# CONFIG_SENSORS_PC87360 is not set +# CONFIG_SENSORS_PC87427 is not set +# CONFIG_SENSORS_SMSC47M1 is not set +# CONFIG_SENSORS_SMSC47B397 is not set +# CONFIG_SENSORS_VT1211 is not set +# CONFIG_SENSORS_W83627HF is not set +# CONFIG_SENSORS_W83627EHF is not set +# CONFIG_HWMON_DEBUG_CHIP is not set +# CONFIG_THERMAL is not set +# CONFIG_THERMAL_HWMON is not set +# CONFIG_WATCHDOG is not set + +# +# Sonics Silicon Backplane +# +CONFIG_SSB_POSSIBLE=y +# CONFIG_SSB is not set + +# +# Multifunction device drivers +# +# CONFIG_MFD_CORE is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_MFD_ASIC3 is not set +# CONFIG_HTC_EGPIO is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_UCB1400_CORE is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_MFD_T7L66XB is not set +# CONFIG_MFD_TC6387XB is not set +# CONFIG_MFD_TC6393XB is not set +# CONFIG_MFD_WM8400 is not set + +# +# Multimedia devices +# + +# +# Multimedia core support +# +# CONFIG_VIDEO_DEV is not set +# CONFIG_VIDEO_MEDIA is not set + +# +# Multimedia drivers +# +# CONFIG_DAB is not set + +# +# Graphics support +# +# CONFIG_VGASTATE is not set +# CONFIG_VIDEO_OUTPUT_CONTROL is not set +# CONFIG_FB is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set + +# +# Display device support +# +# CONFIG_DISPLAY_SUPPORT is not set + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y +# CONFIG_SOUND is not set +CONFIG_HID_SUPPORT=y +CONFIG_HID=y +CONFIG_HID_DEBUG=y +# CONFIG_HIDRAW is not set +# CONFIG_HID_PID is not set + +# +# Special HID drivers +# +# CONFIG_HID_COMPAT is not set +CONFIG_USB_SUPPORT=y +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 + +# +# Enable Host or Gadget support to see Inventra options +# + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# +# CONFIG_USB_GADGET is not set +CONFIG_MMC=y +CONFIG_MMC_DEBUG=y +CONFIG_MMC_UNSAFE_RESUME=y + +# +# MMC/SD/SDIO Card Drivers +# +CONFIG_MMC_BLOCK=y +CONFIG_MMC_BLOCK_BOUNCE=y +CONFIG_SDIO_UART=y +# CONFIG_MMC_TEST is not set + +# +# MMC/SD/SDIO Host Controller Drivers +# +CONFIG_MMC_SDHCI=y +# CONFIG_MEMSTICK is not set +# CONFIG_ACCESSIBILITY is not set +# CONFIG_NEW_LEDS is not set +CONFIG_RTC_LIB=y +# CONFIG_RTC_CLASS is not set +# CONFIG_DMADEVICES is not set + +# +# Voltage and Current regulators +# +# CONFIG_REGULATOR is not set +# CONFIG_REGULATOR_FIXED_VOLTAGE is not set +# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set +# CONFIG_REGULATOR_BQ24022 is not set +# CONFIG_UIO 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=y +CONFIG_EXT3_FS_XATTR=y +CONFIG_EXT3_FS_POSIX_ACL=y +CONFIG_EXT3_FS_SECURITY=y +# CONFIG_EXT4_FS is not set +CONFIG_JBD=y +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +CONFIG_FS_POSIX_ACL=y +CONFIG_FILE_LOCKING=y +# CONFIG_XFS_FS is not set +# CONFIG_GFS2_FS is not set +CONFIG_DNOTIFY=y +CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set +CONFIG_GENERIC_ACL=y + +# +# 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_PROC_PAGE_MONITOR=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +CONFIG_TMPFS_POSIX_ACL=y +# CONFIG_HUGETLB_PAGE is not set +# 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_MINIX_FS is not set +# CONFIG_OMFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +CONFIG_ROMFS_FS=y +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_NLS is not set + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +CONFIG_ENABLE_WARN_DEPRECATED=y +CONFIG_ENABLE_MUST_CHECK=y +CONFIG_FRAME_WARN=1024 +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_DETECT_SOFTLOCKUP=y +# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set +CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0 +CONFIG_SCHED_DEBUG=y +# CONFIG_SCHEDSTATS is not set +# CONFIG_TIMER_STATS is not set +# CONFIG_DEBUG_OBJECTS is not set +# CONFIG_SLUB_DEBUG_ON is not set +# CONFIG_SLUB_STATS is not set +CONFIG_DEBUG_RT_MUTEXES=y +CONFIG_DEBUG_PI_LIST=y +# CONFIG_RT_MUTEX_TESTER is not set +CONFIG_DEBUG_SPINLOCK=y +CONFIG_DEBUG_MUTEXES=y +# CONFIG_DEBUG_LOCK_ALLOC is not set +# CONFIG_PROVE_LOCKING is not set +# CONFIG_LOCK_STAT is not set +CONFIG_DEBUG_SPINLOCK_SLEEP=y +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_DEBUG_KOBJECT is not set +CONFIG_DEBUG_BUGVERBOSE=y +CONFIG_DEBUG_INFO=y +# CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_WRITECOUNT is not set +CONFIG_DEBUG_MEMORY_INIT=y +# CONFIG_DEBUG_LIST is not set +# CONFIG_DEBUG_SG is not set +CONFIG_FRAME_POINTER=y +# CONFIG_BOOT_PRINTK_DELAY is not set +# CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_RCU_CPU_STALL_DETECTOR is not set +# CONFIG_BACKTRACE_SELF_TEST is not set +# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set +# CONFIG_FAULT_INJECTION is not set +# CONFIG_LATENCYTOP is not set +CONFIG_SYSCTL_SYSCALL_CHECK=y +CONFIG_HAVE_FTRACE=y +CONFIG_HAVE_DYNAMIC_FTRACE=y +# CONFIG_FTRACE is not set +# CONFIG_SCHED_TRACER is not set +# CONFIG_CONTEXT_SWITCH_TRACER is not set +# CONFIG_SAMPLES is not set +CONFIG_HAVE_ARCH_KGDB=y +# CONFIG_KGDB is not set +CONFIG_DEBUG_USER=y +CONFIG_DEBUG_ERRORS=y +# CONFIG_DEBUG_STACK_USAGE is not set +CONFIG_DEBUG_LL=y +# CONFIG_DEBUG_ICEDCC is not set +CONFIG_DEBUG_S3C_PORT=y +CONFIG_DEBUG_S3C_UART=0 + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set +# CONFIG_SECURITYFS is not set +# CONFIG_SECURITY_FILE_CAPABILITIES is not set +# CONFIG_CRYPTO is not set + +# +# Library routines +# +CONFIG_BITREVERSE=y +# CONFIG_CRC_CCITT is not set +# CONFIG_CRC16 is not set +# CONFIG_CRC_T10DIF is not set +# CONFIG_CRC_ITU_T is not set +CONFIG_CRC32=y +# CONFIG_CRC7 is not set +# CONFIG_LIBCRC32C is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_PLIST=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_DMA=y diff --git a/arch/arm/include/asm/hardware/vic.h b/arch/arm/include/asm/hardware/vic.h index 263f2c362a3..f87328d4a18 100644 --- a/arch/arm/include/asm/hardware/vic.h +++ b/arch/arm/include/asm/hardware/vic.h @@ -29,15 +29,17 @@ #define VIC_INT_SOFT 0x18 #define VIC_INT_SOFT_CLEAR 0x1c #define VIC_PROTECT 0x20 -#define VIC_VECT_ADDR 0x30 -#define VIC_DEF_VECT_ADDR 0x34 +#define VIC_PL190_VECT_ADDR 0x30 /* PL190 only */ +#define VIC_PL190_DEF_VECT_ADDR 0x34 /* PL190 only */ -#define VIC_VECT_ADDR0 0x100 /* 0 to 15 */ -#define VIC_VECT_CNTL0 0x200 /* 0 to 15 */ +#define VIC_VECT_ADDR0 0x100 /* 0 to 15 (0..31 PL192) */ +#define VIC_VECT_CNTL0 0x200 /* 0 to 15 (0..31 PL192) */ #define VIC_ITCR 0x300 /* VIC test control register */ #define VIC_VECT_CNTL_ENABLE (1 << 5) +#define VIC_PL192_VECT_ADDR 0xF00 + #ifndef __ASSEMBLY__ void vic_init(void __iomem *base, unsigned int irq_start, u32 vic_sources); #endif diff --git a/arch/arm/mach-s3c2410/include/mach/map.h b/arch/arm/mach-s3c2410/include/mach/map.h index 23c470c2e5b..918e3463297 100644 --- a/arch/arm/mach-s3c2410/include/mach/map.h +++ b/arch/arm/mach-s3c2410/include/mach/map.h @@ -13,34 +13,20 @@ #ifndef __ASM_ARCH_MAP_H #define __ASM_ARCH_MAP_H +#include <plat/map-base.h> #include <plat/map.h> #define S3C2410_ADDR(x) S3C_ADDR(x) -/* interrupt controller is the first thing we put in, to make - * the assembly code for the irq detection easier - */ -#define S3C24XX_VA_IRQ S3C_VA_IRQ -#define S3C2410_PA_IRQ (0x4A000000) -#define S3C24XX_SZ_IRQ SZ_1M - -/* memory controller registers */ -#define S3C24XX_VA_MEMCTRL S3C_VA_MEM -#define S3C2410_PA_MEMCTRL (0x48000000) -#define S3C24XX_SZ_MEMCTRL SZ_1M - /* USB host controller */ #define S3C2410_PA_USBHOST (0x49000000) -#define S3C24XX_SZ_USBHOST SZ_1M /* DMA controller */ #define S3C2410_PA_DMA (0x4B000000) #define S3C24XX_SZ_DMA SZ_1M /* Clock and Power management */ -#define S3C24XX_VA_CLKPWR S3C_VA_SYS #define S3C2410_PA_CLKPWR (0x4C000000) -#define S3C24XX_SZ_CLKPWR SZ_1M /* LCD controller */ #define S3C2410_PA_LCD (0x4D000000) @@ -48,48 +34,12 @@ /* NAND flash controller */ #define S3C2410_PA_NAND (0x4E000000) -#define S3C24XX_SZ_NAND SZ_1M - -/* UARTs */ -#define S3C24XX_VA_UART S3C_VA_UART -#define S3C2410_PA_UART (0x50000000) -#define S3C24XX_SZ_UART SZ_1M - -/* Timers */ -#define S3C24XX_VA_TIMER S3C_VA_TIMER -#define S3C2410_PA_TIMER (0x51000000) -#define S3C24XX_SZ_TIMER SZ_1M - -/* USB Device port */ -#define S3C2410_PA_USBDEV (0x52000000) -#define S3C24XX_SZ_USBDEV SZ_1M - -/* Watchdog */ -#define S3C24XX_VA_WATCHDOG S3C_VA_WATCHDOG -#define S3C2410_PA_WATCHDOG (0x53000000) -#define S3C24XX_SZ_WATCHDOG SZ_1M /* IIC hardware controller */ #define S3C2410_PA_IIC (0x54000000) -#define S3C24XX_SZ_IIC SZ_1M /* IIS controller */ #define S3C2410_PA_IIS (0x55000000) -#define S3C24XX_SZ_IIS SZ_1M - -/* GPIO ports */ - -/* the calculation for the VA of this must ensure that - * it is the same distance apart from the UART in the - * phsyical address space, as the initial mapping for the IO - * is done as a 1:1 maping. This puts it (currently) at - * 0xFA800000, which is not in the way of any current mapping - * by the base system. -*/ - -#define S3C2410_PA_GPIO (0x56000000) -#define S3C24XX_VA_GPIO ((S3C2410_PA_GPIO - S3C24XX_PA_UART) + S3C24XX_VA_UART) -#define S3C24XX_SZ_GPIO SZ_1M /* RTC */ #define S3C2410_PA_RTC (0x57000000) @@ -97,15 +47,12 @@ /* ADC */ #define S3C2410_PA_ADC (0x58000000) -#define S3C24XX_SZ_ADC SZ_1M /* SPI */ #define S3C2410_PA_SPI (0x59000000) -#define S3C24XX_SZ_SPI SZ_1M /* SDI */ #define S3C2410_PA_SDI (0x5A000000) -#define S3C24XX_SZ_SDI SZ_1M /* CAMIF */ #define S3C2440_PA_CAMIF (0x4F000000) @@ -120,13 +67,6 @@ #define S3C2443_PA_HSMMC (0x4A800000) #define S3C2443_SZ_HSMMC (256) -/* ISA style IO, for each machine to sort out mappings for, if it - * implements it. We reserve two 16M regions for ISA. - */ - -#define S3C24XX_VA_ISA_WORD S3C2410_ADDR(0x02000000) -#define S3C24XX_VA_ISA_BYTE S3C2410_ADDR(0x03000000) - /* physical addresses of all the chip-select areas */ #define S3C2410_CS0 (0x00000000) @@ -158,21 +98,9 @@ #define S3C24XX_PA_RTC S3C2410_PA_RTC #define S3C24XX_PA_ADC S3C2410_PA_ADC #define S3C24XX_PA_SPI S3C2410_PA_SPI +#define S3C24XX_PA_SDI S3C2410_PA_SDI +#define S3C24XX_PA_NAND S3C2410_PA_NAND -/* deal with the registers that move under the 2412/2413 */ - -#if defined(CONFIG_CPU_S3C2412) || defined(CONFIG_CPU_S3C2413) -#ifndef __ASSEMBLY__ -extern void __iomem *s3c24xx_va_gpio2; -#endif -#ifdef CONFIG_CPU_S3C2412_ONLY -#define S3C24XX_VA_GPIO2 (S3C24XX_VA_GPIO + 0x10) -#else -#define S3C24XX_VA_GPIO2 s3c24xx_va_gpio2 -#endif -#else -#define s3c24xx_va_gpio2 S3C24XX_VA_GPIO -#define S3C24XX_VA_GPIO2 S3C24XX_VA_GPIO -#endif +#define S3C_PA_UART S3C24XX_PA_UART #endif /* __ASM_ARCH_MAP_H */ diff --git a/arch/arm/mach-s3c2410/include/mach/tick.h b/arch/arm/mach-s3c2410/include/mach/tick.h new file mode 100644 index 00000000000..544da41979d --- /dev/null +++ b/arch/arm/mach-s3c2410/include/mach/tick.h @@ -0,0 +1,15 @@ +/* linux/arch/arm/mach-s3c2410/include/mach/tick.h + * + * Copyright 2008 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * http://armlinux.simtec.co.uk/ + * + * S3C2410 - timer tick support + */ + +#define SRCPND_TIMER4 (1<<(IRQ_TIMER4 - IRQ_EINT0)) + +static inline int s3c24xx_ostimer_pending(void) +{ + return __raw_readl(S3C2410_SRCPND) & SRCPND_TIMER4; +} diff --git a/arch/arm/mach-s3c2410/include/mach/uncompress.h b/arch/arm/mach-s3c2410/include/mach/uncompress.h index ab39491beee..c9432103750 100644 --- a/arch/arm/mach-s3c2410/include/mach/uncompress.h +++ b/arch/arm/mach-s3c2410/include/mach/uncompress.h @@ -1,3 +1,4 @@ + /* arch/arm/mach-s3c2410/include/mach/uncompress.h * * Copyright (c) 2003, 2007 Simtec Electronics diff --git a/arch/arm/mach-s3c2412/clock.c b/arch/arm/mach-s3c2412/clock.c index 96d9eb15424..a037df5e1c2 100644 --- a/arch/arm/mach-s3c2412/clock.c +++ b/arch/arm/mach-s3c2412/clock.c @@ -93,12 +93,6 @@ static int s3c2412_upll_enable(struct clk *clk, int enable) /* clock selections */ -/* CPU EXTCLK input */ -static struct clk clk_ext = { - .name = "extclk", - .id = -1, -}; - static struct clk clk_erefclk = { .name = "erefclk", .id = -1, @@ -773,5 +767,6 @@ int __init s3c2412_baseclk_add(void) s3c2412_clkcon_enable(clkp, 0); } + s3c_pwmclk_init(); return 0; } diff --git a/arch/arm/mach-s3c2443/clock.c b/arch/arm/mach-s3c2443/clock.c index 1df8429242b..fdd4ec335a7 100644 --- a/arch/arm/mach-s3c2443/clock.c +++ b/arch/arm/mach-s3c2443/clock.c @@ -147,12 +147,6 @@ static unsigned long s3c2443_roundrate_clksrc256(struct clk *clk, /* clock selections */ -/* CPU EXTCLK input */ -static struct clk clk_ext = { - .name = "ext", - .id = -1, -}; - static struct clk clk_mpllref = { .name = "mpllref", .parent = &clk_xtal, @@ -167,14 +161,6 @@ static struct clk clk_mpll = { }; #endif -static struct clk clk_epllref; - -static struct clk clk_epll = { - .name = "epll", - .parent = &clk_epllref, - .id = -1, -}; - static struct clk clk_i2s_ext = { .name = "i2s-ext", .id = -1, @@ -1072,6 +1058,7 @@ void __init s3c2443_init_clocks(int xtal) } clk_epll.rate = s3c2443_get_epll(epllcon, xtal); + clk_epll.parent = &clk_epllref; clk_usb_bus.parent = &clk_usb_bus_host; /* ensure usb bus clock is within correct rate of 48MHz */ @@ -1120,4 +1107,6 @@ void __init s3c2443_init_clocks(int xtal) (clkp->enable)(clkp, 0); } + + s3c_pwmclk_init(); } diff --git a/arch/arm/mach-s3c24a0/include/mach/debug-macro.S b/arch/arm/mach-s3c24a0/include/mach/debug-macro.S new file mode 100644 index 00000000000..f0ef0ab475f --- /dev/null +++ b/arch/arm/mach-s3c24a0/include/mach/debug-macro.S @@ -0,0 +1,28 @@ +/* arch/arm/mach-s3c2410/include/mach/debug-macro.S + * + * 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. +*/ + +/* pull in the relevant register and map files. */ + +#include <mach/map.h> +#include <plat/regs-serial.h> + + .macro addruart, rx + mrc p15, 0, \rx, c1, c0 + tst \rx, #1 + ldreq \rx, = S3C24XX_PA_UART + ldrne \rx, = S3C24XX_VA_UART +#if CONFIG_DEBUG_S3C_UART != 0 + add \rx, \rx, #(S3C2410_UART1_OFF * CONFIG_DEBUG_S3C_UART) +#endif + .endm + +/* include the reset of the code which will do the work, we're only + * compiling for a single cpu processor type so the default of s3c2440 + * will be fine with us. + */ + +#include <plat/debug-macro.S> diff --git a/arch/arm/mach-s3c24a0/include/mach/io.h b/arch/arm/mach-s3c24a0/include/mach/io.h new file mode 100644 index 00000000000..c163364773b --- /dev/null +++ b/arch/arm/mach-s3c24a0/include/mach/io.h @@ -0,0 +1,16 @@ +/* arch/arm/mach-s3c24a0/include/mach/io.h + * + * Copyright 2008 Simtec Electronics + * Ben Dooks <ben-linux@fluff.org> + * + * IO access and mapping routines for the S3C24A0 + */ + +#ifndef __ASM_ARM_ARCH_IO_H +#define __ASM_ARM_ARCH_IO_H + +/* No current ISA/PCI bus support. */ +#define __io(a) ((void __iomem *)(a)) +#define __mem_pci(a) (a) + +#endif diff --git a/arch/arm/mach-s3c24a0/include/mach/irqs.h b/arch/arm/mach-s3c24a0/include/mach/irqs.h new file mode 100644 index 00000000000..ae8c0e35978 --- /dev/null +++ b/arch/arm/mach-s3c24a0/include/mach/irqs.h @@ -0,0 +1,115 @@ +/* linux/arch/arm/mach-s3c24a0/include/mach/irqs.h + * + * Copyright (c) 2003-2005 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * + * 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_24A0_IRQS_H +#define __ASM_ARCH_24A0_IRQS_H __FILE__ + +#define IRQ_EINT0t2 S3C2410_IRQ(0) /* 16 */ +/* for generic entry-macro.S */ +#define IRQ_EINT0 IRQ_EINT0t2 + +#define IRQ_EINT3t6 S3C2410_IRQ(1) +#define IRQ_EINT7t10 S3C2410_IRQ(2) +#define IRQ_EINT11t14 S3C2410_IRQ(3) +#define IRQ_EINT15t18 S3C2410_IRQ(4) /* 20 */ +#define IRQ_TICK S3C2410_IRQ(5) +#define IRQ_DCTQ S3C2410_IRQ(6) +#define IRQ_MC S3C2410_IRQ(7) +#define IRQ_ME S3C2410_IRQ(8) /* 24 */ +#define IRQ_KEYPAD S3C2410_IRQ(9) +#define IRQ_TIMER0 S3C2410_IRQ(10) +#define IRQ_TIMER1 S3C2410_IRQ(11) +#define IRQ_TIMER2 S3C2410_IRQ(12) +#define IRQ_TIMER3_4 S3C2410_IRQ(13) +#define IRQ_OS_TIMER IRQ_TIMER3_4 +#define IRQ_LCD S3C2410_IRQ(14) +#define IRQ_CAM_C S3C2410_IRQ(15) +#define IRQ_WDT_BATFLT S3C2410_IRQ(16) /* 32 */ +#define IRQ_UART0 S3C2410_IRQ(17) +#define IRQ_CAM_P S3C2410_IRQ(18) +#define IRQ_MODEM S3C2410_IRQ(19) +#define IRQ_DMA S3C2410_IRQ(20) +#define IRQ_SDI S3C2410_IRQ(21) +#define IRQ_SPI0 S3C2410_IRQ(22) +#define IRQ_UART1 S3C2410_IRQ(23) +#define IRQ_AC97_NFLASH S3C2410_IRQ(24) /* 40 */ +#define IRQ_USBD S3C2410_IRQ(25) +#define IRQ_USBH S3C2410_IRQ(26) +#define IRQ_IIC S3C2410_IRQ(27) +#define IRQ_IRDA_MSTICK S3C2410_IRQ(28) /* 44 */ +#define IRQ_VLX_SPI1 S3C2410_IRQ(29) +#define IRQ_RTC S3C2410_IRQ(30) /* 46 */ +#define IRQ_ADC_PEN S3C2410_IRQ(31) + +/* interrupts generated from the external interrupts sources */ +#define IRQ_EINT00 S3C2410_IRQ(32) /* 48 */ +#define IRQ_EINT1 S3C2410_IRQ(33) +#define IRQ_EINT2 S3C2410_IRQ(34) +#define IRQ_EINT3 S3C2410_IRQ(35) +#define IRQ_EINT4 S3C2410_IRQ(36) +#define IRQ_EINT5 S3C2410_IRQ(37) +#define IRQ_EINT6 S3C2410_IRQ(38) +#define IRQ_EINT7 S3C2410_IRQ(39) +#define IRQ_EINT8 S3C2410_IRQ(40) +#define IRQ_EINT9 S3C2410_IRQ(41) +#define IRQ_EINT10 S3C2410_IRQ(42) +#define IRQ_EINT11 S3C2410_IRQ(43) +#define IRQ_EINT12 S3C2410_IRQ(44) +#define IRQ_EINT13 S3C2410_IRQ(45) +#define IRQ_EINT14 S3C2410_IRQ(46) +#define IRQ_EINT15 S3C2410_IRQ(47) +#define IRQ_EINT16 S3C2410_IRQ(48) +#define IRQ_EINT17 S3C2410_IRQ(49) +#define IRQ_EINT18 S3C2410_IRQ(50) + +/* SUB IRQS */ +#define IRQ_S3CUART_RX0 S3C2410_IRQ(51) /* 67 */ +#define IRQ_S3CUART_TX0 S3C2410_IRQ(52) +#define IRQ_S3CUART_ERR0 S3C2410_IRQ(53) + +#define IRQ_S3CUART_RX1 S3C2410_IRQ(54) +#define IRQ_S3CUART_TX1 S3C2410_IRQ(55) +#define IRQ_S3CUART_ERR1 S3C2410_IRQ(56) + +#define IRQ_S3CUART_RX2 (0x0) +#define IRQ_S3CUART_TX2 (0x0) +#define IRQ_S3CUART_ERR2 (0x0) + + +#define IRQ_IRDA S3C2410_IRQ(57) +#define IRQ_MSTICK S3C2410_IRQ(58) +#define IRQ_RESERVED0 S3C2410_IRQ(59) +#define IRQ_RESERVED1 S3C2410_IRQ(60) +#define IRQ_RESERVED2 S3C2410_IRQ(61) +#define IRQ_TIMER3 S3C2410_IRQ(62) +#define IRQ_TIMER4 S3C2410_IRQ(63) +#define IRQ_WDT S3C2410_IRQ(64) +#define IRQ_BATFLT S3C2410_IRQ(65) +#define IRQ_POST S3C2410_IRQ(66) +#define IRQ_DISP_FIFO S3C2410_IRQ(67) +#define IRQ_PENUP S3C2410_IRQ(68) +#define IRQ_PENDN S3C2410_IRQ(69) +#define IRQ_ADC S3C2410_IRQ(70) +#define IRQ_DISP_FRAME S3C2410_IRQ(71) +#define IRQ_NFLASH S3C2410_IRQ(72) +#define IRQ_AC97 S3C2410_IRQ(73) +#define IRQ_SPI1 S3C2410_IRQ(74) +#define IRQ_VLX S3C2410_IRQ(75) +#define IRQ_DMA0 S3C2410_IRQ(76) +#define IRQ_DMA1 S3C2410_IRQ(77) +#define IRQ_DMA2 S3C2410_IRQ(78) +#define IRQ_DMA3 S3C2410_IRQ(79) + +#define IRQ_TC (0x0) + +#define NR_IRQS (IRQ_DMA3+1) + +#endif /* __ASM_ARCH_24A0_IRQS_H */ diff --git a/arch/arm/mach-s3c24a0/include/mach/map.h b/arch/arm/mach-s3c24a0/include/mach/map.h new file mode 100644 index 00000000000..6667355a47a --- /dev/null +++ b/arch/arm/mach-s3c24a0/include/mach/map.h @@ -0,0 +1,85 @@ +/* linux/arch/arm/mach-s3c24a0/include/mach/map.h + * + * Copyright 2003,2007 Simtec Electronics + * http://armlinux.simtec.co.uk/ + * Ben Dooks <ben@simtec.co.uk> + * + * 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. +*/ + +#ifndef __ASM_ARCH_24A0_MAP_H +#define __ASM_ARCH_24A0_MAP_H __FILE__ + +#include <plat/map-base.h> +#include <plat/map.h> + +#define S3C24A0_PA_IO_BASE (0x40000000) +#define S3C24A0_PA_CLKPWR (0x40000000) +#define S3C24A0_PA_IRQ (0x40200000) +#define S3C24A0_PA_DMA (0x40400000) +#define S3C24A0_PA_MEMCTRL (0x40C00000) +#define S3C24A0_PA_NAND (0x40C00000) +#define S3C24A0_PA_SROM (0x40C20000) +#define S3C24A0_PA_SDRAM (0x40C40000) +#define S3C24A0_PA_BUSM (0x40CE0000) +#define S3C24A0_PA_USBHOST (0x41000000) +#define S3C24A0_PA_MODEMIF (0x41180000) +#define S3C24A0_PA_IRDA (0x41800000) +#define S3C24A0_PA_TIMER (0x44000000) +#define S3C24A0_PA_WATCHDOG (0x44100000) +#define S3C24A0_PA_RTC (0x44200000) +#define S3C24A0_PA_UART (0x44400000) +#define S3C24A0_PA_UART0 (S3C24A0_PA_UART) +#define S3C24A0_PA_UART1 (S3C24A0_PA_UART + 0x4000) +#define S3C24A0_PA_SPI (0x44500000) +#define S3C24A0_PA_IIC (0x44600000) +#define S3C24A0_PA_IIS (0x44700000) +#define S3C24A0_PA_GPIO (0x44800000) +#define S3C24A0_PA_KEYIF (0x44900000) +#define S3C24A0_PA_USBDEV (0x44A00000) +#define S3C24A0_PA_AC97 (0x45000000) +#define S3C24A0_PA_ADC (0x45800000) +#define S3C24A0_PA_SDI (0x46000000) +#define S3C24A0_PA_MS (0x46100000) +#define S3C24A0_PA_LCD (0x4A000000) +#define S3C24A0_PA_VPOST (0x4A100000) + +/* physical addresses of all the chip-select areas */ + +#define S3C24A0_CS0 (0x00000000) +#define S3C24A0_CS1 (0x04000000) +#define S3C24A0_CS2 (0x08000000) +#define S3C24A0_CS3 (0x0C000000) +#define S3C24A0_CS4 (0x10000000) +#define S3C24A0_CS5 (0x40000000) + +#define S3C24A0_SDRAM_PA (S3C24A0_CS4) + +/* Use a single interface for common resources between S3C24XX cpus */ + +#define S3C24XX_PA_IRQ S3C24A0_PA_IRQ +#define S3C24XX_PA_MEMCTRL S3C24A0_PA_MEMCTRL +#define S3C24XX_PA_USBHOST S3C24A0_PA_USBHOST +#define S3C24XX_PA_DMA S3C24A0_PA_DMA +#define S3C24XX_PA_CLKPWR S3C24A0_PA_CLKPWR +#define S3C24XX_PA_LCD S3C24A0_PA_LCD +#define S3C24XX_PA_UART S3C24A0_PA_UART +#define S3C24XX_PA_TIMER S3C24A0_PA_TIMER +#define S3C24XX_PA_USBDEV S3C24A0_PA_USBDEV +#define S3C24XX_PA_WATCHDOG S3C24A0_PA_WATCHDOG +#define S3C24XX_PA_IIC S3C24A0_PA_IIC +#define S3C24XX_PA_IIS S3C24A0_PA_IIS +#define S3C24XX_PA_GPIO S3C24A0_PA_GPIO +#define S3C24XX_PA_RTC S3C24A0_PA_RTC +#define S3C24XX_PA_ADC S3C24A0_PA_ADC +#define S3C24XX_PA_SPI S3C24A0_PA_SPI +#define S3C24XX_PA_SDI S3C24A0_PA_SDI +#define S3C24XX_PA_NAND S3C24A0_PA_NAND + +#define S3C_PA_UART S3C24A0_PA_UART + +#endif /* __ASM_ARCH_24A0_MAP_H */ diff --git a/arch/arm/mach-s3c24a0/include/mach/memory.h b/arch/arm/mach-s3c24a0/include/mach/memory.h new file mode 100644 index 00000000000..585211ca018 --- /dev/null +++ b/arch/arm/mach-s3c24a0/include/mach/memory.h @@ -0,0 +1,19 @@ +/* linux/arch/arm/mach-s3c24a0/include/mach/memory.h + * from linux/include/asm-arm/arch-rpc/memory.h + * + * Copyright (C) 1996,1997,1998 Russell King. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#ifndef __ASM_ARCH_24A0_MEMORY_H +#define __ASM_ARCH_24A0_MEMORY_H __FILE__ + +#define PHYS_OFFSET UL(0x10000000) + +#define __virt_to_bus(x) __virt_to_phys(x) +#define __bus_to_virt(x) __phys_to_virt(x) + +#endif diff --git a/arch/arm/mach-s3c24a0/include/mach/regs-clock.h b/arch/arm/mach-s3c24a0/include/mach/regs-clock.h new file mode 100644 index 00000000000..af2abd756c3 --- /dev/null +++ b/arch/arm/mach-s3c24a0/include/mach/regs-clock.h @@ -0,0 +1,88 @@ +/* linux/arch/arm/mach-s3c24a0/include/mach/regs-clock.h + * + * Copyright (c) 2003,2004,2005,2006 Simtec Electronics <linux@simtec.co.uk> + * http://armlinux.simtec.co.uk/ + * + * 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 clock register definitions +*/ + +#ifndef __ASM_ARCH_24A0_REGS_CLOCK_H +#define __ASM_ARCH_24A0_REGS_CLOCK_H __FILE__ + +#define S3C24A0_MPLLCON S3C2410_CLKREG(0x10) +#define S3C24A0_UPLLCON S3C2410_CLKREG(0x14) +#define S3C24A0_CLKCON S3C2410_CLKREG(0x20) +#define S3C24A0_CLKSRC S3C2410_CLKREG(0x24) +#define S3C24A0_CLKDIVN S3C2410_CLKREG(0x28) + +/* 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_LCDC (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_PWMT (1<<8) +#define S3C24A0_CLKCON_USBH (1<<7) +#define S3C24A0_CLKCON_AC97 (1<<6) +#define S3C24A0_CLKCON_IrDA (1<<4) +#define S3C24A0_CLKCON_IDLE (1<<2) +#define S3C24A0_CLKCON_MON (1<<1) +#define S3C24A0_CLKCON_STOP (1<<0) + +/* CLKSRC register bits */ + +#define S3C24A0_CLKSRC_OSC (1<<8) /* CLKSRC */ +#define S3C24A0_CLKSRC_UPLL (1<<7) +#define S3C24A0_CLKSRC_MPLL (1<<5) +#define S3C24A0_CLKSRC_EXT (1<<4) + +/* Use a single interface with the common code, for s3c24xx */ + +#define S3C2410_MPLLCON S3C24A0_MPLLCON +#define S3C2410_UPLLCON S3C24A0_UPLLCON +#define S3C2410_CLKCON S3C24A0_CLKCON +#define S3C2410_CLKSLOW S3C24A0_CLKSRC +#define S3C2410_CLKDIVN S3C24A0_CLKDIVN + +#define S3C2410_CLKCON_IDLE S3C24A0_CLKCON_IDLE +#define S3C2410_CLKCON_POWER S3C24A0_CLKCON_STOP +#define S3C2410_CLKCON_LCDC S3C24A0_CLKCON_LCDC +#define S3C2410_CLKCON_USBH S3C24A0_CLKCON_USBH +#define S3C2410_CLKCON_USBD S3C24A0_CLKCON_USBD +#define S3C2410_CLKCON_PWMT S3C24A0_CLKCON_PWMT +#define S3C2410_CLKCON_SDI S3C24A0_CLKCON_SDI +#define S3C2410_CLKCON_UART0 S3C24A0_CLKCON_UART0 +#define S3C2410_CLKCON_UART1 S3C24A0_CLKCON_UART1 +#define S3C2410_CLKCON_GPIO S3C24A0_CLKCON_GPIO +#define S3C2410_CLKCON_ADC S3C24A0_CLKCON_ADC +#define S3C2410_CLKCON_IIC S3C24A0_CLKCON_IIC +#define S3C2410_CLKCON_IIS S3C24A0_CLKCON_IIS +#define S3C2410_CLKCON_SPI S3C24A0_CLKCON_SPI + +#define S3C2410_CLKSLOW_UCLK_OFF S3C24A0_CLKSRC_UPLL +#define S3C2410_CLKSLOW_MPLL_OFF S3C24A0_CLKSRC_MPLL +#define S3C2410_CLKSLOW_SLOW (0xFF) +#define S3C2410_CLKSLOW_GET_SLOWVAL(x) (0x1) + +#endif /* __ASM_ARCH_24A0_REGS_CLOCK_H */ diff --git a/arch/arm/mach-s3c24a0/include/mach/regs-irq.h b/arch/arm/mach-s3c24a0/include/mach/regs-irq.h new file mode 100644 index 00000000000..6086f6f189e --- /dev/null +++ b/arch/arm/mach-s3c24a0/include/mach/regs-irq.h @@ -0,0 +1,25 @@ +/* linux/arch/arm/mach-s3c24a0/include/mach/regs-irq.h + * + * Copyright (c) 2003 Simtec Electronics <linux@simtec.co.uk> + * 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. +*/ + + +#ifndef ___ASM_ARCH_24A0_REGS_IRQ_H +#define ___ASM_ARCH_24A0_REGS_IRQ_H __FILE__ + + +#define S3C2410_EINTMASK S3C2410_EINTREG(0x034) +#define S3C2410_EINTPEND S3C2410_EINTREG(0X038) + +#define S3C24XX_EINTMASK S3C24XX_EINTREG(0x034) +#define S3C24XX_EINTPEND S3C24XX_EINTREG(0X038) + +#endif /* __ASM_ARCH_24A0_REGS_IRQ_H */ + + + diff --git a/arch/arm/mach-s3c24a0/include/mach/system.h b/arch/arm/mach-s3c24a0/include/mach/system.h new file mode 100644 index 00000000000..bd1bd195765 --- /dev/null +++ b/arch/arm/mach-s3c24a0/include/mach/system.h @@ -0,0 +1,25 @@ +/* linux/arch/arm/mach-s3c24a0/include/mach/system.h + * + * Copyright 2008 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * + * S3C24A0 - System function defines and includes + * + * 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 <mach/hardware.h> +#include <asm/io.h> + +#include <mach/map.h> + +static void arch_idle(void) +{ + /* currently no specific idle support. */ +} + +void (*s3c24xx_reset_hook)(void); + +#include <asm/plat-s3c24xx/system-reset.h> diff --git a/arch/arm/mach-s3c24a0/include/mach/tick.h b/arch/arm/mach-s3c24a0/include/mach/tick.h new file mode 100644 index 00000000000..9dea8ba6fb7 --- /dev/null +++ b/arch/arm/mach-s3c24a0/include/mach/tick.h @@ -0,0 +1,15 @@ +/* linux/arch/arm/mach-s3c24a0/include/mach/tick.h + * + * Copyright 2008 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * http://armlinux.simtec.co.uk/ + * + * S3C24A0 - timer tick support + */ + +#define SUBSRC_TIMER4 (1 << (IRQ_TIMER4 - IRQ_S3CUART_RX0)) + +static inline int s3c24xx_ostimer_pending(void) +{ + return __raw_readl(S3C2410_SUBSRCPND) & SUBSRC_TIMER4; +} diff --git a/arch/arm/mach-s3c24a0/include/mach/timex.h b/arch/arm/mach-s3c24a0/include/mach/timex.h new file mode 100644 index 00000000000..98573424a01 --- /dev/null +++ b/arch/arm/mach-s3c24a0/include/mach/timex.h @@ -0,0 +1,18 @@ +/* linux/arch/arm/mach-s3c24a0/include/mach/timex.h + * + * Copyright (c) 2008 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * + * S3C2410 - time parameters + * + * 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 CLOCK_TICK_RATE 12000000 + +#endif /* __ASM_ARCH_TIMEX_H */ diff --git a/arch/arm/mach-s3c24a0/include/mach/vmalloc.h b/arch/arm/mach-s3c24a0/include/mach/vmalloc.h new file mode 100644 index 00000000000..4d4fe484958 --- /dev/null +++ b/arch/arm/mach-s3c24a0/include/mach/vmalloc.h @@ -0,0 +1,17 @@ +/* linux/include/asm-arm/arch-s3c24ao/vmalloc.h + * + * Copyright 2008 Simtec Electronics <linux@simtec.co.uk> + + * 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 vmalloc definition +*/ + +#ifndef __ASM_ARCH_VMALLOC_H +#define __ASM_ARCH_VMALLOC_H + +#define VMALLOC_END (0xE0000000) + +#endif /* __ASM_ARCH_VMALLOC_H */ diff --git a/arch/arm/mach-s3c6400/Kconfig b/arch/arm/mach-s3c6400/Kconfig new file mode 100644 index 00000000000..6da82b5c09b --- /dev/null +++ b/arch/arm/mach-s3c6400/Kconfig @@ -0,0 +1,8 @@ +# arch/arm/mach-s3c6400/Kconfig +# +# Copyright 2008 Openmoko, Inc. +# Simtec Electronics, Ben Dooks <ben@simtec.co.uk> +# +# Licensed under GPLv2 + +# Currently nothing here, this will be added later diff --git a/arch/arm/mach-s3c6400/Makefile b/arch/arm/mach-s3c6400/Makefile new file mode 100644 index 00000000000..8f397db25b8 --- /dev/null +++ b/arch/arm/mach-s3c6400/Makefile @@ -0,0 +1,15 @@ +# arch/arm/mach-s3c6400/Makefile +# +# Copyright 2008 Openmoko, Inc. +# Copyright 2008 Simtec Electronics +# +# Licensed under GPLv2 + +obj-y := +obj-m := +obj-n := +obj- := + +# Core support for S3C6400 system + +obj-n += blank.o diff --git a/arch/arm/mach-s3c6400/Makefile.boot b/arch/arm/mach-s3c6400/Makefile.boot new file mode 100644 index 00000000000..ba41fdc0a58 --- /dev/null +++ b/arch/arm/mach-s3c6400/Makefile.boot @@ -0,0 +1,2 @@ + zreladdr-y := 0x50008000 +params_phys-y := 0x50000100 diff --git a/arch/arm/mach-s3c6400/include/mach/debug-macro.S b/arch/arm/mach-s3c6400/include/mach/debug-macro.S new file mode 100644 index 00000000000..b18ac5266df --- /dev/null +++ b/arch/arm/mach-s3c6400/include/mach/debug-macro.S @@ -0,0 +1,39 @@ +/* arch/arm/mach-s3c6400/include/mach/debug-macro.S + * + * Copyright 2008 Openmoko, Inc. + * Copyright 2008 Simtec Electronics + * http://armlinux.simtec.co.uk/ + * Ben Dooks <ben@simtec.co.uk> + * + * 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. +*/ + +/* pull in the relevant register and map files. */ + +#include <mach/map.h> +#include <plat/regs-serial.h> + + /* note, for the boot process to work we have to keep the UART + * virtual address aligned to an 1MiB boundary for the L1 + * mapping the head code makes. We keep the UART virtual address + * aligned and add in the offset when we load the value here. + */ + + .macro addruart, rx + mrc p15, 0, \rx, c1, c0 + tst \rx, #1 + ldreq \rx, = S3C_PA_UART + ldrne \rx, = (S3C_VA_UART + S3C_PA_UART & 0xfffff) +#if CONFIG_DEBUG_S3C_UART != 0 + add \rx, \rx, #(0x400 * CONFIG_DEBUG_S3C_UART) +#endif + .endm + +/* include the reset of the code which will do the work, we're only + * compiling for a single cpu processor type so the default of s3c2440 + * will be fine with us. + */ + +#include <plat/debug-macro.S> diff --git a/arch/arm/mach-s3c6400/include/mach/dma.h b/arch/arm/mach-s3c6400/include/mach/dma.h new file mode 100644 index 00000000000..9771ac2cb07 --- /dev/null +++ b/arch/arm/mach-s3c6400/include/mach/dma.h @@ -0,0 +1,16 @@ +/* linux/arch/arm/mach-s3c6400/include/mach/dma.h + * + * Copyright 2008 Openmoko, Inc. + * Copyright 2008 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * http://armlinux.simtec.co.uk/ + * + * S3C6400 - DMA support + */ + +#ifndef __ASM_ARCH_DMA_H +#define __ASM_ARCH_DMA_H __FILE__ + +/* currently nothing here, placeholder */ + +#endif /* __ASM_ARCH_IRQ_H */ diff --git a/arch/arm/mach-s3c6400/include/mach/entry-macro.S b/arch/arm/mach-s3c6400/include/mach/entry-macro.S new file mode 100644 index 00000000000..fbd90d2cf35 --- /dev/null +++ b/arch/arm/mach-s3c6400/include/mach/entry-macro.S @@ -0,0 +1,44 @@ +/* arch/arm/mach-s3c6400/include/mach/entry-macro.S + * + * Copyright 2008 Openmoko, Inc. + * Copyright 2008 Simtec Electronics + * http://armlinux.simtec.co.uk/ + * Ben Dooks <ben@simtec.co.uk> + * + * Low-level IRQ helper macros for the Samsung S3C64XX series + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. +*/ + +#include <asm/hardware/vic.h> +#include <mach/map.h> +#include <plat/irqs.h> + + .macro disable_fiq + .endm + + .macro get_irqnr_preamble, base, tmp + ldr \base, =S3C_VA_VIC0 + .endm + + .macro arch_ret_to_user, tmp1, tmp2 + .endm + + .macro get_irqnr_and_base, irqnr, irqstat, base, tmp + + @ check the vic0 + mov \irqnr, # S3C_IRQ_OFFSET + 31 + ldr \irqstat, [ \base, # VIC_IRQ_STATUS ] + teq \irqstat, #0 + + @ otherwise try vic1 + addeq \tmp, \base, #(S3C_VA_VIC1 - S3C_VA_VIC0) + addeq \irqnr, \irqnr, #32 + ldreq \irqstat, [ \tmp, # VIC_IRQ_STATUS ] + teqeq \irqstat, #0 + + clzne \irqstat, \irqstat + subne \irqnr, \irqnr, \irqstat + .endm diff --git a/arch/arm/mach-s3c6400/include/mach/gpio.h b/arch/arm/mach-s3c6400/include/mach/gpio.h new file mode 100644 index 00000000000..8b4254a23d9 --- /dev/null +++ b/arch/arm/mach-s3c6400/include/mach/gpio.h @@ -0,0 +1,22 @@ +/* arch/arm/mach-s3c6400/include/mach/gpio.h + * + * Copyright 2008 Openmoko, Inc. + * Copyright 2008 Simtec Electronics + * http://armlinux.simtec.co.uk/ + * Ben Dooks <ben@simtec.co.uk> + * + * S3C6400 - GPIO lib 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. +*/ + +#define gpio_get_value __gpio_get_value +#define gpio_set_value __gpio_set_value +#define gpio_cansleep __gpio_cansleep +#define gpio_to_irq __gpio_to_irq + +#define ARCH_NR_GPIOS 188 + +#include <asm-generic/gpio.h> diff --git a/arch/arm/mach-s3c6400/include/mach/hardware.h b/arch/arm/mach-s3c6400/include/mach/hardware.h new file mode 100644 index 00000000000..862d033e57a --- /dev/null +++ b/arch/arm/mach-s3c6400/include/mach/hardware.h @@ -0,0 +1,16 @@ +/* linux/arch/arm/mach-s3c6400/include/mach/hardware.h + * + * Copyright 2008 Openmoko, Inc. + * Copyright 2008 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * http://armlinux.simtec.co.uk/ + * + * S3C6400 - Hardware support + */ + +#ifndef __ASM_ARCH_HARDWARE_H +#define __ASM_ARCH_HARDWARE_H __FILE__ + +/* currently nothing here, placeholder */ + +#endif /* __ASM_ARCH_IRQ_H */ diff --git a/arch/arm/mach-s3c6400/include/mach/irqs.h b/arch/arm/mach-s3c6400/include/mach/irqs.h new file mode 100644 index 00000000000..b38c47cffc2 --- /dev/null +++ b/arch/arm/mach-s3c6400/include/mach/irqs.h @@ -0,0 +1,20 @@ +/* linux/arch/arm/mach-s3c6400/include/mach/irqs.h + * + * Copyright 2008 Openmoko, Inc. + * Copyright 2008 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * http://armlinux.simtec.co.uk/ + * + * S3C6400 - IRQ definitions + */ + +#ifndef __ASM_ARCH_IRQS_H +#define __ASM_ARCH_IRQS_H __FILE__ + +#ifndef __ASM_ARM_IRQ_H +#error "Do not include this directly, instead #include <asm/irq.h>" +#endif + +#include <plat/irqs.h> + +#endif /* __ASM_ARCH_IRQ_H */ diff --git a/arch/arm/mach-s3c6400/include/mach/map.h b/arch/arm/mach-s3c6400/include/mach/map.h new file mode 100644 index 00000000000..618f09d637b --- /dev/null +++ b/arch/arm/mach-s3c6400/include/mach/map.h @@ -0,0 +1,53 @@ +/* linux/arch/arm/mach-s3c6400/include/mach/map.h + * + * Copyright 2008 Openmoko, Inc. + * Copyright 2008 Simtec Electronics + * http://armlinux.simtec.co.uk/ + * Ben Dooks <ben@simtec.co.uk> + * + * S3C64XX - 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. +*/ + +#ifndef __ASM_ARCH_MAP_H +#define __ASM_ARCH_MAP_H __FILE__ + +#include <plat/map-base.h> + +#define S3C_PA_UART (0x7F005000) +#define S3C_PA_UART0 (S3C_PA_UART + 0x00) +#define S3C_PA_UART1 (S3C_PA_UART + 0x400) +#define S3C_PA_UART2 (S3C_PA_UART + 0x800) +#define S3C_PA_UART3 (S3C_PA_UART + 0xC00) +#define S3C_UART_OFFSET (0x400) + +/* See notes on UART VA mapping in debug-macro.S */ +#define S3C_VA_UARTx(x) (S3C_VA_UART + (S3C_PA_UART & 0xfffff) + ((x) * S3C_UART_OFFSET)) + +#define S3C_VA_UART0 S3C_VA_UARTx(0) +#define S3C_VA_UART1 S3C_VA_UARTx(1) +#define S3C_VA_UART2 S3C_VA_UARTx(2) +#define S3C_VA_UART3 S3C_VA_UARTx(3) + +#define S3C64XX_PA_SYSCON (0x7E00F000) +#define S3C64XX_PA_TIMER (0x7F006000) + +#define S3C64XX_PA_GPIO (0x7F008000) +#define S3C64XX_VA_GPIO S3C_ADDR(0x00500000) +#define S3C64XX_SZ_GPIO SZ_4K + +#define S3C64XX_PA_SDRAM (0x50000000) +#define S3C64XX_PA_VIC0 (0x71200000) +#define S3C64XX_PA_VIC1 (0x71300000) + +/* place VICs close together */ +#define S3C_VA_VIC0 (S3C_VA_IRQ + 0x00) +#define S3C_VA_VIC1 (S3C_VA_IRQ + 0x10000) + +/* compatibiltiy defines. */ +#define S3C_PA_TIMER S3C64XX_PA_TIMER + +#endif /* __ASM_ARCH_6400_MAP_H */ diff --git a/arch/arm/mach-s3c6400/include/mach/memory.h b/arch/arm/mach-s3c6400/include/mach/memory.h new file mode 100644 index 00000000000..38c381132f2 --- /dev/null +++ b/arch/arm/mach-s3c6400/include/mach/memory.h @@ -0,0 +1,21 @@ +/* arch/arm/mach-s3c6400/include/mach/memory.h + * + * Copyright 2008 Openmoko, Inc. + * Copyright 2008 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * http://armlinux.simtec.co.uk/ + * + * 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 + +#define PHYS_OFFSET UL(0x50000000) + +#define __virt_to_bus(x) __virt_to_phys(x) +#define __bus_to_virt(x) __phys_to_virt(x) + +#endif diff --git a/arch/arm/mach-s3c6400/include/mach/pwm-clock.h b/arch/arm/mach-s3c6400/include/mach/pwm-clock.h new file mode 100644 index 00000000000..b25bedee0d5 --- /dev/null +++ b/arch/arm/mach-s3c6400/include/mach/pwm-clock.h @@ -0,0 +1,56 @@ +/* linux/arch/arm/mach-s3c6400/include/mach/pwm-clock.h + * + * Copyright 2008 Openmoko, Inc. + * Copyright 2008 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * http://armlinux.simtec.co.uk/ + * + * S3C64xx - pwm clock and timer support + */ + +/** + * pwm_cfg_src_is_tclk() - return whether the given mux config is a tclk + * @tcfg: The timer TCFG1 register bits shifted down to 0. + * + * Return true if the given configuration from TCFG1 is a TCLK instead + * any of the TDIV clocks. + */ +static inline int pwm_cfg_src_is_tclk(unsigned long tcfg) +{ + return tcfg >= S3C64XX_TCFG1_MUX_TCLK; +} + +/** + * tcfg_to_divisor() - convert tcfg1 setting to a divisor + * @tcfg1: The tcfg1 setting, shifted down. + * + * Get the divisor value for the given tcfg1 setting. We assume the + * caller has already checked to see if this is not a TCLK source. + */ +static inline unsigned long tcfg_to_divisor(unsigned long tcfg1) +{ + return 1 << tcfg1; +} + +/** + * pwm_tdiv_has_div1() - does the tdiv setting have a /1 + * + * Return true if we have a /1 in the tdiv setting. + */ +static inline unsigned int pwm_tdiv_has_div1(void) +{ + return 1; +} + +/** + * pwm_tdiv_div_bits() - calculate TCFG1 divisor value. + * @div: The divisor to calculate the bit information for. + * + * Turn a divisor into the necessary bit field for TCFG1. + */ +static inline unsigned long pwm_tdiv_div_bits(unsigned int div) +{ + return ilog2(div); +} + +#define S3C_TCFG1_MUX_TCLK S3C64XX_TCFG1_MUX_TCLK diff --git a/arch/arm/mach-s3c6400/include/mach/regs-irq.h b/arch/arm/mach-s3c6400/include/mach/regs-irq.h new file mode 100644 index 00000000000..bcce68a0bb7 --- /dev/null +++ b/arch/arm/mach-s3c6400/include/mach/regs-irq.h @@ -0,0 +1,20 @@ +/* linux/arch/arm/mach-s3c6400/include/mach/regs-irq.h + * + * Copyright 2008 Openmoko, Inc. + * Copyright 2008 Simtec Electronics + * http://armlinux.simtec.co.uk/ + * Ben Dooks <ben@simtec.co.uk> + * + * S3C64XX - IRQ register 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. +*/ + +#ifndef __ASM_ARCH_REGS_IRQ_H +#define __ASM_ARCH_REGS_IRQ_H __FILE__ + +#include <asm/hardware/vic.h> + +#endif /* __ASM_ARCH_6400_REGS_IRQ_H */ diff --git a/arch/arm/mach-s3c6400/include/mach/system.h b/arch/arm/mach-s3c6400/include/mach/system.h new file mode 100644 index 00000000000..652bbc403f0 --- /dev/null +++ b/arch/arm/mach-s3c6400/include/mach/system.h @@ -0,0 +1,24 @@ +/* linux/arch/arm/mach-s3c6400/include/mach/system.h + * + * Copyright 2008 Openmoko, Inc. + * Copyright 2008 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * http://armlinux.simtec.co.uk/ + * + * S3C6400 - system implementation + */ + +#ifndef __ASM_ARCH_SYSTEM_H +#define __ASM_ARCH_SYSTEM_H __FILE__ + +static void arch_idle(void) +{ + /* nothing here yet */ +} + +static void arch_reset(char mode) +{ + /* nothing here yet */ +} + +#endif /* __ASM_ARCH_IRQ_H */ diff --git a/arch/arm/mach-s3c6400/include/mach/tick.h b/arch/arm/mach-s3c6400/include/mach/tick.h new file mode 100644 index 00000000000..d9c0dc7014e --- /dev/null +++ b/arch/arm/mach-s3c6400/include/mach/tick.h @@ -0,0 +1,29 @@ +/* linux/arch/arm/mach-s3c6400/include/mach/tick.h + * + * Copyright 2008 Openmoko, Inc. + * Copyright 2008 Simtec Electronics + * http://armlinux.simtec.co.uk/ + * Ben Dooks <ben@simtec.co.uk> + * + * S3C64XX - Timer tick support 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. +*/ + +#ifndef __ASM_ARCH_TICK_H +#define __ASM_ARCH_TICK_H __FILE__ + +/* note, the timer interrutps turn up in 2 places, the vic and then + * the timer block. We take the VIC as the base at the moment. + */ +static inline u32 s3c24xx_ostimer_pending(void) +{ + u32 pend = __raw_readl(S3C_VA_VIC0 + VIC_RAW_STATUS); + return pend & 1 << (IRQ_TIMER4_VIC - S3C64XX_IRQ_VIC0(0)); +} + +#define TICK_MAX (0xffffffff) + +#endif /* __ASM_ARCH_6400_TICK_H */ diff --git a/arch/arm/mach-s3c6400/include/mach/uncompress.h b/arch/arm/mach-s3c6400/include/mach/uncompress.h new file mode 100644 index 00000000000..c6a82a20bf2 --- /dev/null +++ b/arch/arm/mach-s3c6400/include/mach/uncompress.h @@ -0,0 +1,28 @@ +/* arch/arm/mach-s3c6400/include/mach/uncompress.h + * + * Copyright 2008 Openmoko, Inc. + * Copyright 2008 Simtec Electronics + * http://armlinux.simtec.co.uk/ + * Ben Dooks <ben@simtec.co.uk> + * + * S3C6400 - uncompress code + * + * 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_UNCOMPRESS_H +#define __ASM_ARCH_UNCOMPRESS_H + +#include <mach/map.h> +#include <plat/uncompress.h> + +static void arch_detect_cpu(void) +{ + /* we do not need to do any cpu detection here at the moment. */ + fifo_mask = S3C2440_UFSTAT_TXMASK; + fifo_max = 63 << S3C2440_UFSTAT_TXSHIFT; +} + +#endif /* __ASM_ARCH_UNCOMPRESS_H */ diff --git a/arch/arm/mach-s3c6410/Kconfig b/arch/arm/mach-s3c6410/Kconfig new file mode 100644 index 00000000000..75b1244cf8a --- /dev/null +++ b/arch/arm/mach-s3c6410/Kconfig @@ -0,0 +1,21 @@ +# arch/arm/mach-s3c6410/Kconfig +# +# Copyright 2008 Openmoko, Inc. +# Copyright 2008 Simtec Electronics +# +# Licensed under GPLv2 + +# Configuration options for the S3C6410 CPU + +config CPU_S3C6410 + bool + select CPU_S3C6400_INIT + select CPU_S3C6400_CLOCK + help + Enable S3C6410 CPU support + +config MACH_SMDK6410 + bool "SMDK6410" + select CPU_S3C6410 + help + Machine support for the Samsung SMDK6410 diff --git a/arch/arm/mach-s3c6410/Makefile b/arch/arm/mach-s3c6410/Makefile new file mode 100644 index 00000000000..4a20a009990 --- /dev/null +++ b/arch/arm/mach-s3c6410/Makefile @@ -0,0 +1,19 @@ +# arch/arm/plat-s3c6410/Makefile +# +# Copyright 2008 Openmoko, Inc. +# Copyright 2008 Simtec Electronics +# +# Licensed under GPLv2 + +obj-y := +obj-m := +obj-n := +obj- := + +# Core support for S3C6410 system + +obj-$(CONFIG_CPU_S3C6410) += cpu.o + +# machine support + +obj-$(CONFIG_MACH_SMDK6410) += mach-smdk6410.o diff --git a/arch/arm/mach-s3c6410/cpu.c b/arch/arm/mach-s3c6410/cpu.c new file mode 100644 index 00000000000..975cf88f0e8 --- /dev/null +++ b/arch/arm/mach-s3c6410/cpu.c @@ -0,0 +1,91 @@ +/* linux/arch/arm/mach-s3c6410/cpu.c + * + * Copyright 2008 Simtec Electronics + * Copyright 2008 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * http://armlinux.simtec.co.uk/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#include <linux/kernel.h> +#include <linux/types.h> +#include <linux/interrupt.h> +#include <linux/list.h> +#include <linux/timer.h> +#include <linux/init.h> +#include <linux/clk.h> +#include <linux/io.h> +#include <linux/sysdev.h> +#include <linux/serial_core.h> +#include <linux/platform_device.h> + +#include <asm/mach/arch.h> +#include <asm/mach/map.h> +#include <asm/mach/irq.h> + +#include <mach/hardware.h> +#include <asm/irq.h> + +#include <plat/cpu-freq.h> +#include <plat/regs-serial.h> + +#include <plat/cpu.h> +#include <plat/devs.h> +#include <plat/clock.h> +#include <plat/s3c6400.h> +#include <plat/s3c6410.h> + +/* Initial IO mappings */ + +static struct map_desc s3c6410_iodesc[] __initdata = { +}; + +/* s3c6410_map_io + * + * register the standard cpu IO areas +*/ + +void __init s3c6410_map_io(void) +{ + iotable_init(s3c6410_iodesc, ARRAY_SIZE(s3c6410_iodesc)); +} + +void __init s3c6410_init_clocks(int xtal) +{ + printk(KERN_DEBUG "%s: initialising clocks\n", __func__); + s3c24xx_register_baseclocks(xtal); + s3c64xx_register_clocks(); + s3c6400_register_clocks(); + s3c6400_setup_clocks(); +} + +void __init s3c6410_init_irq(void) +{ + /* VIC0 is missing IRQ7, VIC1 is fully populated. */ + s3c64xx_init_irq(~0 & ~(1 << 7), ~0); +} + +struct sysdev_class s3c6410_sysclass = { + .name = "s3c6410-core", +}; + +static struct sys_device s3c6410_sysdev = { + .cls = &s3c6410_sysclass, +}; + +static int __init s3c6410_core_init(void) +{ + return sysdev_class_register(&s3c6410_sysclass); +} + +core_initcall(s3c6410_core_init); + +int __init s3c6410_init(void) +{ + printk("S3C6410: Initialising architecture\n"); + + return sysdev_register(&s3c6410_sysdev); +} diff --git a/arch/arm/mach-s3c6410/mach-smdk6410.c b/arch/arm/mach-s3c6410/mach-smdk6410.c new file mode 100644 index 00000000000..9213a8ba283 --- /dev/null +++ b/arch/arm/mach-s3c6410/mach-smdk6410.c @@ -0,0 +1,89 @@ +/* linux/arch/arm/mach-s3c6410/mach-smdk6410.c + * + * Copyright 2008 Openmoko, Inc. + * Copyright 2008 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * http://armlinux.simtec.co.uk/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * +*/ + +#include <linux/kernel.h> +#include <linux/types.h> +#include <linux/interrupt.h> +#include <linux/list.h> +#include <linux/timer.h> +#include <linux/init.h> +#include <linux/serial_core.h> +#include <linux/platform_device.h> +#include <linux/io.h> + +#include <asm/mach/arch.h> +#include <asm/mach/map.h> +#include <asm/mach/irq.h> + +#include <mach/hardware.h> +#include <mach/map.h> + +#include <asm/irq.h> +#include <asm/mach-types.h> + +#include <plat/regs-serial.h> + +#include <plat/s3c6410.h> +#include <plat/clock.h> +#include <plat/devs.h> +#include <plat/cpu.h> + +#define UCON S3C2410_UCON_DEFAULT | S3C2410_UCON_UCLK +#define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB +#define UFCON S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE + +static struct s3c2410_uartcfg smdk6410_uartcfgs[] __initdata = { + [0] = { + .hwport = 0, + .flags = 0, + .ucon = 0x3c5, + .ulcon = 0x03, + .ufcon = 0x51, + }, + [1] = { + .hwport = 1, + .flags = 0, + .ucon = 0x3c5, + .ulcon = 0x03, + .ufcon = 0x51, + }, +}; + +struct map_desc smdk6410_iodesc[] = {}; + +static struct platform_device *smdk6410_devices[] __initdata = { +}; + +static void __init smdk6410_map_io(void) +{ + s3c64xx_init_io(smdk6410_iodesc, ARRAY_SIZE(smdk6410_iodesc)); + s3c24xx_init_clocks(12000000); + s3c24xx_init_uarts(smdk6410_uartcfgs, ARRAY_SIZE(smdk6410_uartcfgs)); +} + +static void __init smdk6410_machine_init(void) +{ + platform_add_devices(smdk6410_devices, ARRAY_SIZE(smdk6410_devices)); +} + +MACHINE_START(SMDK6410, "SMDK6410") + /* Maintainer: Ben Dooks <ben@fluff.org> */ + .phys_io = S3C_PA_UART & 0xfff00000, + .io_pg_offst = (((u32)S3C_VA_UART) >> 18) & 0xfffc, + .boot_params = S3C64XX_PA_SDRAM + 0x100, + + .init_irq = s3c6410_init_irq, + .map_io = smdk6410_map_io, + .init_machine = smdk6410_machine_init, + .timer = &s3c24xx_timer, +MACHINE_END diff --git a/arch/arm/plat-s3c/Kconfig b/arch/arm/plat-s3c/Kconfig index 10c1dd3cd46..adb9060ec91 100644 --- a/arch/arm/plat-s3c/Kconfig +++ b/arch/arm/plat-s3c/Kconfig @@ -6,8 +6,8 @@ config PLAT_S3C bool - depends on ARCH_S3C2410 - default y if ARCH_S3C2410 + depends on ARCH_S3C2410 || ARCH_S3C24A0 || ARCH_S3C64XX + default y select NO_IOPORT help Base platform code for any Samsung S3C device @@ -16,24 +16,24 @@ config PLAT_S3C config CPU_LLSERIAL_S3C2410_ONLY bool - depends on ARCH_S3C2410 + depends on PLAT_S3C default y if CPU_LLSERIAL_S3C2410 && !CPU_LLSERIAL_S3C2440 config CPU_LLSERIAL_S3C2440_ONLY bool - depends on ARCH_S3C2410 + depends on PLAT_S3C default y if CPU_LLSERIAL_S3C2440 && !CPU_LLSERIAL_S3C2410 config CPU_LLSERIAL_S3C2410 bool - depends on ARCH_S3C2410 + depends on PLAT_S3C help Selected if there is an S3C2410 (or register compatible) serial low-level implementation needed config CPU_LLSERIAL_S3C2440 bool - depends on ARCH_S3C2410 + depends on PLAT_S3C help Selected if there is an S3C2440 (or register compatible) serial low-level implementation needed diff --git a/arch/arm/plat-s3c/clock.c b/arch/arm/plat-s3c/clock.c index da7ac07c7a0..1054d18828f 100644 --- a/arch/arm/plat-s3c/clock.c +++ b/arch/arm/plat-s3c/clock.c @@ -239,6 +239,16 @@ struct clk clk_xtal = { .ctrlbit = 0, }; +struct clk clk_ext = { + .name = "ext", + .id = -1, +}; + +struct clk clk_epll = { + .name = "epll", + .id = -1, +}; + struct clk clk_mpll = { .name = "mpll", .id = -1, diff --git a/arch/arm/plat-s3c/include/plat/clock.h b/arch/arm/plat-s3c/include/plat/clock.h index d871609738f..a10622eed43 100644 --- a/arch/arm/plat-s3c/include/plat/clock.h +++ b/arch/arm/plat-s3c/include/plat/clock.h @@ -45,7 +45,13 @@ extern struct clk clk_h; extern struct clk clk_p; extern struct clk clk_mpll; extern struct clk clk_upll; +extern struct clk clk_epll; extern struct clk clk_xtal; +extern struct clk clk_ext; + +/* S3C64XX specific clocks */ +extern struct clk clk_27m; +extern struct clk clk_48m; /* exports for arch/arm/mach-s3c2410 * @@ -61,6 +67,8 @@ extern int s3c24xx_register_clocks(struct clk **clk, int nr_clks); extern int s3c24xx_register_baseclocks(unsigned long xtal); +extern void s3c64xx_register_clocks(void); + extern void s3c24xx_setup_clocks(unsigned long fclk, unsigned long hclk, unsigned long pclk); @@ -70,3 +78,11 @@ extern void s3c2412_setup_clocks(void); extern void s3c244x_setup_clocks(void); extern void s3c2443_setup_clocks(void); +/* S3C64XX specific functions and clocks */ + +extern int s3c64xx_sclk_ctrl(struct clk *clk, int enable); + +/* Init for pwm clock code */ + +extern void s3c_pwmclk_init(void); + diff --git a/arch/arm/plat-s3c/include/plat/cpu.h b/arch/arm/plat-s3c/include/plat/cpu.h index 011157ea871..e62ae0fcfe5 100644 --- a/arch/arm/plat-s3c/include/plat/cpu.h +++ b/arch/arm/plat-s3c/include/plat/cpu.h @@ -44,8 +44,10 @@ extern void s3c_init_cpu(unsigned long idcode, /* core initialisation functions */ extern void s3c24xx_init_irq(void); +extern void s3c64xx_init_irq(u32 vic0, u32 vic1); extern void s3c24xx_init_io(struct map_desc *mach_desc, int size); +extern void s3c64xx_init_io(struct map_desc *mach_desc, int size); extern void s3c24xx_init_uarts(struct s3c2410_uartcfg *cfg, int no); diff --git a/arch/arm/plat-s3c/include/plat/debug-macro.S b/arch/arm/plat-s3c/include/plat/debug-macro.S index 4aa7e2e6c00..3634d4e3708 100644 --- a/arch/arm/plat-s3c/include/plat/debug-macro.S +++ b/arch/arm/plat-s3c/include/plat/debug-macro.S @@ -20,7 +20,7 @@ .endm #ifndef fifo_level -#define fifo_level fifo_level_s3c2410 +#define fifo_level fifo_level_s3c2440 #endif .macro fifo_full_s3c2440 rd, rx diff --git a/arch/arm/plat-s3c/include/plat/devs.h b/arch/arm/plat-s3c/include/plat/devs.h index badaac9d64a..a689c7c5ac2 100644 --- a/arch/arm/plat-s3c/include/plat/devs.h +++ b/arch/arm/plat-s3c/include/plat/devs.h @@ -17,6 +17,7 @@ struct s3c24xx_uart_resources { }; extern struct s3c24xx_uart_resources s3c2410_uart_resources[]; +extern struct s3c24xx_uart_resources s3c64xx_uart_resources[]; extern struct platform_device *s3c24xx_uart_devs[]; extern struct platform_device *s3c24xx_uart_src[]; diff --git a/arch/arm/plat-s3c/include/plat/map.h b/arch/arm/plat-s3c/include/plat/map-base.h index b84289d32a5..b84289d32a5 100644 --- a/arch/arm/plat-s3c/include/plat/map.h +++ b/arch/arm/plat-s3c/include/plat/map-base.h diff --git a/arch/arm/plat-s3c/include/plat/regs-serial.h b/arch/arm/plat-s3c/include/plat/regs-serial.h index a0daa647b92..3ca28585cf8 100644 --- a/arch/arm/plat-s3c/include/plat/regs-serial.h +++ b/arch/arm/plat-s3c/include/plat/regs-serial.h @@ -77,6 +77,12 @@ #define S3C2440_UCON_FCLK (3<<10) #define S3C2443_UCON_EPLL (3<<10) +#define S3C6400_UCON_CLKMASK (3<<10) +#define S3C6400_UCON_PCLK (0<<10) +#define S3C6400_UCON_PCLK2 (2<<10) +#define S3C6400_UCON_UCLK0 (1<<10) +#define S3C6400_UCON_UCLK1 (3<<10) + #define S3C2440_UCON2_FCLK_EN (1<<15) #define S3C2440_UCON0_DIVMASK (15 << 12) #define S3C2440_UCON1_DIVMASK (15 << 12) @@ -149,6 +155,14 @@ #define S3C2410_UFSTAT_RXMASK (15<<0) #define S3C2410_UFSTAT_RXSHIFT (0) +/* UFSTAT S3C24A0 */ +#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) + /* UFSTAT S3C2443 same as S3C2440 */ #define S3C2440_UFSTAT_TXFULL (1<<14) #define S3C2440_UFSTAT_RXFULL (1<<6) diff --git a/arch/arm/plat-s3c/include/plat/regs-timer.h b/arch/arm/plat-s3c/include/plat/regs-timer.h index cc0eedd53e3..d097d92f8cc 100644 --- a/arch/arm/plat-s3c/include/plat/regs-timer.h +++ b/arch/arm/plat-s3c/include/plat/regs-timer.h @@ -10,7 +10,6 @@ * S3C2410 Timer configuration */ - #ifndef __ASM_ARCH_REGS_TIMER_H #define __ASM_ARCH_REGS_TIMER_H @@ -21,6 +20,8 @@ #define S3C2410_TCFG1 S3C_TIMERREG(0x04) #define S3C2410_TCON S3C_TIMERREG(0x08) +#define S3C64XX_TINT_CSTAT S3C_TIMERREG(0x44) + #define S3C2410_TCFG_PRESCALER0_MASK (255<<0) #define S3C2410_TCFG_PRESCALER1_MASK (255<<8) #define S3C2410_TCFG_PRESCALER1_SHIFT (8) @@ -72,6 +73,14 @@ #define S3C2410_TCFG1_MUX_TCLK (4<<0) #define S3C2410_TCFG1_MUX_MASK (15<<0) +#define S3C64XX_TCFG1_MUX_DIV1 (0<<0) +#define S3C64XX_TCFG1_MUX_DIV2 (1<<0) +#define S3C64XX_TCFG1_MUX_DIV4 (2<<0) +#define S3C64XX_TCFG1_MUX_DIV8 (3<<0) +#define S3C64XX_TCFG1_MUX_DIV16 (4<<0) +#define S3C64XX_TCFG1_MUX_TCLK (5<<0) /* 3 sets of TCLK */ +#define S3C64XX_TCFG1_MUX_MASK (15<<0) + #define S3C2410_TCFG1_SHIFT(x) ((x) * 4) /* for each timer, we have an count buffer, an compare buffer and diff --git a/arch/arm/plat-s3c/include/plat/uncompress.h b/arch/arm/plat-s3c/include/plat/uncompress.h index 2c39a309aeb..6061de87f22 100644 --- a/arch/arm/plat-s3c/include/plat/uncompress.h +++ b/arch/arm/plat-s3c/include/plat/uncompress.h @@ -37,7 +37,7 @@ static void arch_detect_cpu(void); /* how many bytes we allow into the FIFO at a time in FIFO mode */ #define FIFO_MAX (14) -#define uart_base S3C24XX_PA_UART + (0x4000*CONFIG_S3C_LOWLEVEL_UART_PORT) +#define uart_base S3C_PA_UART + (S3C_UART_OFFSET * CONFIG_S3C_LOWLEVEL_UART_PORT) static __inline__ void uart_wr(unsigned int reg, unsigned int val) diff --git a/arch/arm/plat-s3c/pwm-clock.c b/arch/arm/plat-s3c/pwm-clock.c index e07d82891a9..a318215ab53 100644 --- a/arch/arm/plat-s3c/pwm-clock.c +++ b/arch/arm/plat-s3c/pwm-clock.c @@ -14,20 +14,20 @@ #include <linux/kernel.h> #include <linux/list.h> #include <linux/errno.h> +#include <linux/log2.h> #include <linux/clk.h> #include <linux/err.h> #include <linux/io.h> #include <mach/hardware.h> +#include <mach/map.h> #include <asm/irq.h> -#include <mach/regs-clock.h> -#include <mach/regs-gpio.h> - #include <plat/clock.h> #include <plat/cpu.h> #include <plat/regs-timer.h> +#include <mach/pwm-clock.h> /* Each of the timers 0 through 5 go through the following * clock tree, with the inputs depending on the timers. @@ -168,11 +168,6 @@ static inline struct pwm_tdiv_clk *to_tdiv(struct clk *clk) return container_of(clk, struct pwm_tdiv_clk, clk); } -static inline unsigned long tcfg_to_divisor(unsigned long tcfg1) -{ - return 1 << (1 + tcfg1); -} - static unsigned long clk_pwm_tdiv_get_rate(struct clk *clk) { unsigned long tcfg1 = __raw_readl(S3C2410_TCFG1); @@ -181,7 +176,7 @@ static unsigned long clk_pwm_tdiv_get_rate(struct clk *clk) tcfg1 >>= S3C2410_TCFG1_SHIFT(clk->id); tcfg1 &= S3C2410_TCFG1_MUX_MASK; - if (tcfg1 == S3C2410_TCFG1_MUX_TCLK) + if (pwm_cfg_src_is_tclk(tcfg1)) divisor = to_tdiv(clk)->divisor; else divisor = tcfg_to_divisor(tcfg1); @@ -198,7 +193,9 @@ static unsigned long clk_pwm_tdiv_round_rate(struct clk *clk, parent_rate = clk_get_rate(clk->parent); divisor = parent_rate / rate; - if (divisor <= 2) + if (divisor <= 1 && pwm_tdiv_has_div1()) + divisor = 1; + else if (divisor <= 2) divisor = 2; else if (divisor <= 4) divisor = 4; @@ -212,25 +209,7 @@ static unsigned long clk_pwm_tdiv_round_rate(struct clk *clk, static unsigned long clk_pwm_tdiv_bits(struct pwm_tdiv_clk *divclk) { - unsigned long bits; - - switch (divclk->divisor) { - case 2: - bits = S3C2410_TCFG1_MUX_DIV2; - break; - case 4: - bits = S3C2410_TCFG1_MUX_DIV4; - break; - case 8: - bits = S3C2410_TCFG1_MUX_DIV8; - break; - case 16: - default: - bits = S3C2410_TCFG1_MUX_DIV16; - break; - } - - return bits; + return pwm_tdiv_div_bits(divclk->divisor); } static void clk_pwm_tdiv_update(struct pwm_tdiv_clk *divclk) @@ -271,7 +250,7 @@ static int clk_pwm_tdiv_set_rate(struct clk *clk, unsigned long rate) /* Update the current MUX settings if we are currently * selected as the clock source for this clock. */ - if (tcfg1 != S3C2410_TCFG1_MUX_TCLK) + if (!pwm_cfg_src_is_tclk(tcfg1)) clk_pwm_tdiv_update(divclk); return 0; @@ -358,7 +337,7 @@ static int clk_pwm_tin_set_parent(struct clk *clk, struct clk *parent) unsigned long shift = S3C2410_TCFG1_SHIFT(id); if (parent == s3c24xx_pwmclk_tclk(id)) - bits = S3C2410_TCFG1_MUX_TCLK << shift; + bits = S3C_TCFG1_MUX_TCLK << shift; else if (parent == s3c24xx_pwmclk_tdiv(id)) bits = clk_pwm_tdiv_bits(to_tdiv(parent)) << shift; else @@ -420,7 +399,7 @@ static __init int clk_pwm_tin_register(struct clk *pwm) tcfg1 >>= S3C2410_TCFG1_SHIFT(id); tcfg1 &= S3C2410_TCFG1_MUX_MASK; - if (tcfg1 == S3C2410_TCFG1_MUX_TCLK) + if (pwm_cfg_src_is_tclk(tcfg1)) parent = s3c24xx_pwmclk_tclk(id); else parent = s3c24xx_pwmclk_tdiv(id); @@ -428,7 +407,16 @@ static __init int clk_pwm_tin_register(struct clk *pwm) return clk_set_parent(pwm, parent); } -static __init int s3c24xx_pwmclk_init(void) +/** + * s3c_pwmclk_init() - initialise pwm clocks + * + * Initialise and register the clocks which provide the inputs for the + * pwm timer blocks. + * + * Note, this call is required by the time core, so must be called after + * the base clocks are added and before any of the initcalls are run. + */ +__init void s3c_pwmclk_init(void) { struct clk *clk_timers; unsigned int clk; @@ -437,7 +425,7 @@ static __init int s3c24xx_pwmclk_init(void) clk_timers = clk_get(NULL, "timers"); if (IS_ERR(clk_timers)) { printk(KERN_ERR "%s: no parent clock\n", __func__); - return -EINVAL; + return; } for (clk = 0; clk < ARRAY_SIZE(clk_timer_scaler); clk++) { @@ -445,7 +433,7 @@ static __init int s3c24xx_pwmclk_init(void) ret = s3c24xx_register_clock(&clk_timer_scaler[clk]); if (ret < 0) { printk(KERN_ERR "error adding pwm scaler%d clock\n", clk); - goto err; + return; } } @@ -453,7 +441,7 @@ static __init int s3c24xx_pwmclk_init(void) ret = s3c24xx_register_clock(&clk_timer_tclk[clk]); if (ret < 0) { printk(KERN_ERR "error adding pww tclk%d\n", clk); - goto err; + return; } } @@ -461,7 +449,7 @@ static __init int s3c24xx_pwmclk_init(void) ret = clk_pwm_tdiv_register(clk); if (ret < 0) { printk(KERN_ERR "error adding pwm%d tdiv clock\n", clk); - goto err; + return; } } @@ -469,14 +457,7 @@ static __init int s3c24xx_pwmclk_init(void) ret = clk_pwm_tin_register(&clk_tin[clk]); if (ret < 0) { printk(KERN_ERR "error adding pwm%d tin clock\n", clk); - goto err; + return; } } - - return 0; - - err: - return ret; } - -arch_initcall(s3c24xx_pwmclk_init); diff --git a/arch/arm/plat-s3c/time.c b/arch/arm/plat-s3c/time.c index c6861a05a29..3b27b29da47 100644 --- a/arch/arm/plat-s3c/time.c +++ b/arch/arm/plat-s3c/time.c @@ -26,6 +26,7 @@ #include <linux/err.h> #include <linux/clk.h> #include <linux/io.h> +#include <linux/platform_device.h> #include <asm/system.h> #include <asm/leds.h> @@ -36,6 +37,7 @@ #include <plat/regs-timer.h> #include <mach/regs-irq.h> #include <asm/mach/time.h> +#include <mach/tick.h> #include <plat/clock.h> #include <plat/cpu.h> @@ -43,6 +45,10 @@ static unsigned long timer_startval; static unsigned long timer_usec_ticks; +#ifndef TICK_MAX +#define TICK_MAX (0xffff) +#endif + #define TIMER_USEC_SHIFT 16 /* we use the shifted arithmetic to work out the ratio of timer ticks @@ -91,12 +97,9 @@ static inline unsigned long timer_ticks_to_usec(unsigned long ticks) * IRQs are disabled before entering here from do_gettimeofday() */ -#define SRCPND_TIMER4 (1<<(IRQ_TIMER4 - IRQ_EINT0)) - static unsigned long s3c2410_gettimeoffset (void) { unsigned long tdone; - unsigned long irqpend; unsigned long tval; /* work out how many ticks have gone since last timer interrupt */ @@ -106,8 +109,7 @@ static unsigned long s3c2410_gettimeoffset (void) /* check to see if there is an interrupt pending */ - irqpend = __raw_readl(S3C2410_SRCPND); - if (irqpend & SRCPND_TIMER4) { + if (s3c24xx_ostimer_pending()) { /* re-read the timer, and try and fix up for the missed * interrupt. Note, the interrupt may go off before the * timer has re-loaded from wrapping. @@ -146,6 +148,10 @@ static struct irqaction s3c2410_timer_irq = { machine_is_anubis() || \ machine_is_osiris()) +static struct clk *tin; +static struct clk *tdiv; +static struct clk *timerclk; + /* * Set up timer interrupt, and return the current time in seconds. * @@ -159,13 +165,7 @@ static void s3c2410_timer_setup (void) unsigned long tcfg1; unsigned long tcfg0; - tcnt = 0xffff; /* default value for tcnt */ - - /* read the current timer configuration bits */ - - tcon = __raw_readl(S3C2410_TCON); - tcfg1 = __raw_readl(S3C2410_TCFG1); - tcfg0 = __raw_readl(S3C2410_TCFG0); + tcnt = TICK_MAX; /* default value for tcnt */ /* configure the system for whichever machine is in use */ @@ -174,11 +174,13 @@ static void s3c2410_timer_setup (void) timer_usec_ticks = timer_mask_usec_ticks(1, 12000000); tcnt = 12000000 / HZ; + tcfg1 = __raw_readl(S3C2410_TCFG1); tcfg1 &= ~S3C2410_TCFG1_MUX4_MASK; tcfg1 |= S3C2410_TCFG1_MUX4_TCLK1; + __raw_writel(tcfg1, S3C2410_TCFG1); } else { unsigned long pclk; - struct clk *clk; + struct clk *tscaler; /* for the h1940 (and others), we use the pclk from the core * to generate the timer values. since values around 50 to @@ -189,29 +191,25 @@ static void s3c2410_timer_setup (void) * (8.45 ticks per usec) */ - /* this is used as default if no other timer can be found */ - - clk = clk_get(NULL, "timers"); - if (IS_ERR(clk)) - panic("failed to get clock for system timer"); - - clk_enable(clk); - - pclk = clk_get_rate(clk); + pclk = clk_get_rate(timerclk); /* configure clock tick */ timer_usec_ticks = timer_mask_usec_ticks(6, pclk); - tcfg1 &= ~S3C2410_TCFG1_MUX4_MASK; - tcfg1 |= S3C2410_TCFG1_MUX4_DIV2; + tscaler = clk_get_parent(tdiv); - tcfg0 &= ~S3C2410_TCFG_PRESCALER1_MASK; - tcfg0 |= ((6 - 1) / 2) << S3C2410_TCFG_PRESCALER1_SHIFT; + clk_set_rate(tscaler, pclk / 3); + clk_set_rate(tdiv, pclk / 6); + clk_set_parent(tin, tdiv); - tcnt = (pclk / 6) / HZ; + tcnt = clk_get_rate(tin) / HZ; } + tcon = __raw_readl(S3C2410_TCON); + tcfg0 = __raw_readl(S3C2410_TCFG0); + tcfg1 = __raw_readl(S3C2410_TCFG1); + /* timers reload after counting zero, so reduce the count by 1 */ tcnt--; @@ -220,7 +218,7 @@ static void s3c2410_timer_setup (void) tcon, tcnt, tcfg0, tcfg1, timer_usec_ticks); /* check to see if timer is within 16bit range... */ - if (tcnt > 0xffff) { + if (tcnt > TICK_MAX) { panic("setup_timer: HZ is too small, cannot configure timer!"); return; } @@ -247,8 +245,35 @@ static void s3c2410_timer_setup (void) __raw_writel(tcon, S3C2410_TCON); } +static void __init s3c2410_timer_resources(void) +{ + struct platform_device tmpdev; + + tmpdev.dev.bus = &platform_bus_type; + tmpdev.id = 4; + + timerclk = clk_get(NULL, "timers"); + if (IS_ERR(timerclk)) + panic("failed to get clock for system timer"); + + clk_enable(timerclk); + + if (!use_tclk1_12()) { + tin = clk_get(&tmpdev.dev, "pwm-tin"); + if (IS_ERR(tin)) + panic("failed to get pwm-tin clock for system timer"); + + tdiv = clk_get(&tmpdev.dev, "pwm-tdiv"); + if (IS_ERR(tdiv)) + panic("failed to get pwm-tdiv clock for system timer"); + } + + clk_enable(tin); +} + static void __init s3c2410_timer_init(void) { + s3c2410_timer_resources(); s3c2410_timer_setup(); setup_irq(IRQ_TIMER4, &s3c2410_timer_irq); } diff --git a/arch/arm/plat-s3c24xx/Kconfig b/arch/arm/plat-s3c24xx/Kconfig index 0e07de2c9a9..2c8a2f5d75f 100644 --- a/arch/arm/plat-s3c24xx/Kconfig +++ b/arch/arm/plat-s3c24xx/Kconfig @@ -6,8 +6,8 @@ config PLAT_S3C24XX bool - depends on ARCH_S3C2410 - default y if ARCH_S3C2410 + depends on ARCH_S3C2410 || ARCH_S3C24A0 + default y select NO_IOPORT select ARCH_REQUIRE_GPIOLIB help diff --git a/arch/arm/plat-s3c24xx/devs.c b/arch/arm/plat-s3c24xx/devs.c index 6a33dbc494f..9826efb91e4 100644 --- a/arch/arm/plat-s3c24xx/devs.c +++ b/arch/arm/plat-s3c24xx/devs.c @@ -192,8 +192,8 @@ void __init s3c24xx_fb_set_platdata(struct s3c2410fb_mach_info *pd) static struct resource s3c_nand_resource[] = { [0] = { - .start = S3C2410_PA_NAND, - .end = S3C2410_PA_NAND + S3C24XX_SZ_NAND - 1, + .start = S3C24XX_PA_NAND, + .end = S3C24XX_PA_NAND + S3C24XX_SZ_NAND - 1, .flags = IORESOURCE_MEM, } }; @@ -390,8 +390,8 @@ struct platform_device s3c_device_hwmon = { static struct resource s3c_sdi_resource[] = { [0] = { - .start = S3C2410_PA_SDI, - .end = S3C2410_PA_SDI + S3C24XX_SZ_SDI - 1, + .start = S3C24XX_PA_SDI, + .end = S3C24XX_PA_SDI + S3C24XX_SZ_SDI - 1, .flags = IORESOURCE_MEM, }, [1] = { diff --git a/arch/arm/plat-s3c24xx/include/mach/pwm-clock.h b/arch/arm/plat-s3c24xx/include/mach/pwm-clock.h new file mode 100644 index 00000000000..a087de21bc2 --- /dev/null +++ b/arch/arm/plat-s3c24xx/include/mach/pwm-clock.h @@ -0,0 +1,55 @@ +/* linux/arch/arm/plat-s3c24xx/include/mach/pwm-clock.h + * + * Copyright 2008 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * http://armlinux.simtec.co.uk/ + * + * S3C24xx - pwm clock and timer support + */ + +/** + * pwm_cfg_src_is_tclk() - return whether the given mux config is a tclk + * @cfg: The timer TCFG1 register bits shifted down to 0. + * + * Return true if the given configuration from TCFG1 is a TCLK instead + * any of the TDIV clocks. + */ +static inline int pwm_cfg_src_is_tclk(unsigned long tcfg) +{ + return tcfg == S3C2410_TCFG1_MUX_TCLK; +} + +/** + * tcfg_to_divisor() - convert tcfg1 setting to a divisor + * @tcfg1: The tcfg1 setting, shifted down. + * + * Get the divisor value for the given tcfg1 setting. We assume the + * caller has already checked to see if this is not a TCLK source. + */ +static inline unsigned long tcfg_to_divisor(unsigned long tcfg1) +{ + return 1 << (1 + tcfg1); +} + +/** + * pwm_tdiv_has_div1() - does the tdiv setting have a /1 + * + * Return true if we have a /1 in the tdiv setting. + */ +static inline unsigned int pwm_tdiv_has_div1(void) +{ + return 0; +} + +/** + * pwm_tdiv_div_bits() - calculate TCFG1 divisor value. + * @div: The divisor to calculate the bit information for. + * + * Turn a divisor into the necessary bit field for TCFG1. + */ +static inline unsigned long pwm_tdiv_div_bits(unsigned int div) +{ + return ilog2(div) - 1; +} + +#define S3C_TCFG1_MUX_TCLK S3C2410_TCFG1_MUX_TCLK diff --git a/arch/arm/plat-s3c24xx/include/plat/map.h b/arch/arm/plat-s3c24xx/include/plat/map.h new file mode 100644 index 00000000000..e7be0c0d370 --- /dev/null +++ b/arch/arm/plat-s3c24xx/include/plat/map.h @@ -0,0 +1,100 @@ +/* linux/include/asm-arm/plat-s3c24xx/map.h + * + * Copyright (c) 2008 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * + * S3C24XX - 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. +*/ + +#ifndef __ASM_PLAT_S3C24XX_MAP_H +#define __ASM_PLAT_S3C24XX_MAP_H + +/* interrupt controller is the first thing we put in, to make + * the assembly code for the irq detection easier + */ +#define S3C24XX_VA_IRQ S3C_VA_IRQ +#define S3C2410_PA_IRQ (0x4A000000) +#define S3C24XX_SZ_IRQ SZ_1M + +/* memory controller registers */ +#define S3C24XX_VA_MEMCTRL S3C_VA_MEM +#define S3C2410_PA_MEMCTRL (0x48000000) +#define S3C24XX_SZ_MEMCTRL SZ_1M + +/* UARTs */ +#define S3C24XX_VA_UART S3C_VA_UART +#define S3C2410_PA_UART (0x50000000) +#define S3C24XX_SZ_UART SZ_1M +#define S3C_UART_OFFSET (0x4000) + +/* Timers */ +#define S3C24XX_VA_TIMER S3C_VA_TIMER +#define S3C2410_PA_TIMER (0x51000000) +#define S3C24XX_SZ_TIMER SZ_1M + +/* Clock and Power management */ +#define S3C24XX_VA_CLKPWR S3C_VA_SYS +#define S3C24XX_SZ_CLKPWR SZ_1M + +/* USB Device port */ +#define S3C2410_PA_USBDEV (0x52000000) +#define S3C24XX_SZ_USBDEV SZ_1M + +/* Watchdog */ +#define S3C24XX_VA_WATCHDOG S3C_VA_WATCHDOG +#define S3C2410_PA_WATCHDOG (0x53000000) +#define S3C24XX_SZ_WATCHDOG SZ_1M + +/* Standard size definitions for peripheral blocks. */ + +#define S3C24XX_SZ_IIC SZ_1M +#define S3C24XX_SZ_IIS SZ_1M +#define S3C24XX_SZ_ADC SZ_1M +#define S3C24XX_SZ_SPI SZ_1M +#define S3C24XX_SZ_SDI SZ_1M +#define S3C24XX_SZ_NAND SZ_1M +#define S3C24XX_SZ_USBHOST SZ_1M + +/* GPIO ports */ + +/* the calculation for the VA of this must ensure that + * it is the same distance apart from the UART in the + * phsyical address space, as the initial mapping for the IO + * is done as a 1:1 maping. This puts it (currently) at + * 0xFA800000, which is not in the way of any current mapping + * by the base system. +*/ + +#define S3C2410_PA_GPIO (0x56000000) +#define S3C24XX_VA_GPIO ((S3C24XX_PA_GPIO - S3C24XX_PA_UART) + S3C24XX_VA_UART) +#define S3C24XX_SZ_GPIO SZ_1M + + +/* ISA style IO, for each machine to sort out mappings for, if it + * implements it. We reserve two 16M regions for ISA. + */ + +#define S3C24XX_VA_ISA_WORD S3C2410_ADDR(0x02000000) +#define S3C24XX_VA_ISA_BYTE S3C2410_ADDR(0x03000000) + +/* deal with the registers that move under the 2412/2413 */ + +#if defined(CONFIG_CPU_S3C2412) || defined(CONFIG_CPU_S3C2413) +#ifndef __ASSEMBLY__ +extern void __iomem *s3c24xx_va_gpio2; +#endif +#ifdef CONFIG_CPU_S3C2412_ONLY +#define S3C24XX_VA_GPIO2 (S3C24XX_VA_GPIO + 0x10) +#else +#define S3C24XX_VA_GPIO2 s3c24xx_va_gpio2 +#endif +#else +#define s3c24xx_va_gpio2 S3C24XX_VA_GPIO +#define S3C24XX_VA_GPIO2 S3C24XX_VA_GPIO +#endif + +#endif /* __ASM_PLAT_S3C24XX_MAP_H */ diff --git a/arch/arm/plat-s3c24xx/s3c2410-clock.c b/arch/arm/plat-s3c24xx/s3c2410-clock.c index 4e07943c1e2..b61bdb79373 100644 --- a/arch/arm/plat-s3c24xx/s3c2410-clock.c +++ b/arch/arm/plat-s3c24xx/s3c2410-clock.c @@ -272,5 +272,6 @@ int __init s3c2410_baseclk_add(void) (clkslow & S3C2410_CLKSLOW_MPLL_OFF) ? "off" : "on", (clkslow & S3C2410_CLKSLOW_UCLK_OFF) ? "off" : "on"); + s3c_pwmclk_init(); return 0; } diff --git a/arch/arm/plat-s3c64xx/Kconfig b/arch/arm/plat-s3c64xx/Kconfig new file mode 100644 index 00000000000..bd832ba0cf7 --- /dev/null +++ b/arch/arm/plat-s3c64xx/Kconfig @@ -0,0 +1,36 @@ +# arch/arm/plat-s3c64xx/Kconfig +# +# Copyright 2008 Openmoko, Inc. +# Copyright 2008 Simtec Electronics +# Ben Dooks <ben@simtec.co.uk> +# +# Licensed under GPLv2 + +config PLAT_S3C64XX + bool + depends on ARCH_S3C64XX + select PLAT_S3C + select ARM_VIC + default y + select NO_IOPORT + select ARCH_REQUIRE_GPIOLIB + help + Base platform code for any Samsung S3C64XX device + +if PLAT_S3C64XX + +# Configuration options shared by all S3C64XX implementations + +config CPU_S3C6400_INIT + bool + help + Common initialisation code for the S3C6400 that is shared + by other CPUs in the series, such as the S3C6410. + +config CPU_S3C6400_CLOCK + bool + help + Common clock support code for the S3C6400 that is shared + by other CPUs in the series, such as the S3C6410. + +endif diff --git a/arch/arm/plat-s3c64xx/Makefile b/arch/arm/plat-s3c64xx/Makefile new file mode 100644 index 00000000000..9c09b081980 --- /dev/null +++ b/arch/arm/plat-s3c64xx/Makefile @@ -0,0 +1,24 @@ +# arch/arm/plat-s3c64xx/Makefile +# +# Copyright 2008 Openmoko, Inc. +# Copyright 2008 Simtec Electronics +# +# Licensed under GPLv2 + +obj-y := +obj-m := +obj-n := dummy.o +obj- := + +# Core files + +obj-y += dev-uart.o +obj-y += cpu.o +obj-y += irq.o +obj-y += irq-eint.o +obj-y += clock.o + +# CPU support + +obj-$(CONFIG_CPU_S3C6400_INIT) += s3c6400-init.o +obj-$(CONFIG_CPU_S3C6400_CLOCK) += s3c6400-clock.o diff --git a/arch/arm/plat-s3c64xx/clock.c b/arch/arm/plat-s3c64xx/clock.c new file mode 100644 index 00000000000..5a1e97e1f8f --- /dev/null +++ b/arch/arm/plat-s3c64xx/clock.c @@ -0,0 +1,282 @@ +/* linux/arch/arm/plat-s3c64xx/clock.c + * + * Copyright 2008 Openmoko, Inc. + * Copyright 2008 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * http://armlinux.simtec.co.uk/ + * + * S3C64XX Base clock 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. +*/ + +#include <linux/init.h> +#include <linux/module.h> +#include <linux/interrupt.h> +#include <linux/ioport.h> +#include <linux/delay.h> +#include <linux/io.h> + +#include <mach/hardware.h> +#include <mach/map.h> + +#include <plat/regs-sys.h> +#include <plat/regs-clock.h> +#include <plat/cpu.h> +#include <plat/devs.h> +#include <plat/clock.h> + +struct clk clk_27m = { + .name = "clk_27m", + .id = -1, + .rate = 27000000, +}; + +static int clk_48m_ctrl(struct clk *clk, int enable) +{ + unsigned long flags; + u32 val; + + /* can't rely on clock lock, this register has other usages */ + local_irq_save(flags); + + val = __raw_readl(S3C64XX_OTHERS); + if (enable) + val |= S3C64XX_OTHERS_USBMASK; + else + val &= ~S3C64XX_OTHERS_USBMASK; + + __raw_writel(val, S3C64XX_OTHERS); + local_irq_restore(flags); + + return 0; +} + +struct clk clk_48m = { + .name = "clk_48m", + .id = -1, + .rate = 48000000, + .enable = clk_48m_ctrl, +}; + +static int inline s3c64xx_gate(void __iomem *reg, + struct clk *clk, + int enable) +{ + unsigned int ctrlbit = clk->ctrlbit; + u32 con; + + con = __raw_readl(reg); + + if (enable) + con |= ctrlbit; + else + con &= ~ctrlbit; + + __raw_writel(con, reg); + return 0; +} + +static int s3c64xx_pclk_ctrl(struct clk *clk, int enable) +{ + return s3c64xx_gate(S3C_PCLK_GATE, clk, enable); +} + +static int s3c64xx_hclk_ctrl(struct clk *clk, int enable) +{ + return s3c64xx_gate(S3C_HCLK_GATE, clk, enable); +} + +int s3c64xx_sclk_ctrl(struct clk *clk, int enable) +{ + return s3c64xx_gate(S3C_SCLK_GATE, clk, enable); +} + +static struct clk init_clocks_disable[] = { + { + .name = "nand", + .id = -1, + .parent = &clk_h, + }, { + .name = "adc", + .id = -1, + .parent = &clk_p, + .enable = s3c64xx_pclk_ctrl, + .ctrlbit = S3C_CLKCON_PCLK_TSADC, + }, { + .name = "i2c", + .id = -1, + .parent = &clk_p, + .enable = s3c64xx_pclk_ctrl, + .ctrlbit = S3C_CLKCON_PCLK_IIC, + }, { + .name = "iis", + .id = 0, + .parent = &clk_p, + .enable = s3c64xx_pclk_ctrl, + .ctrlbit = S3C_CLKCON_PCLK_IIS0, + }, { + .name = "iis", + .id = 1, + .parent = &clk_p, + .enable = s3c64xx_pclk_ctrl, + .ctrlbit = S3C_CLKCON_PCLK_IIS1, + }, { + .name = "spi", + .id = 0, + .parent = &clk_p, + .enable = s3c64xx_pclk_ctrl, + .ctrlbit = S3C_CLKCON_PCLK_SPI0, + }, { + .name = "spi", + .id = 1, + .parent = &clk_p, + .enable = s3c64xx_pclk_ctrl, + .ctrlbit = S3C_CLKCON_PCLK_SPI1, + }, { + .name = "48m", + .id = 0, + .parent = &clk_48m, + .enable = s3c64xx_sclk_ctrl, + .ctrlbit = S3C_CLKCON_SCLK_MMC0_48, + }, { + .name = "48m", + .id = 1, + .parent = &clk_48m, + .enable = s3c64xx_sclk_ctrl, + .ctrlbit = S3C_CLKCON_SCLK_MMC1_48, + }, { + .name = "48m", + .id = 2, + .parent = &clk_48m, + .enable = s3c64xx_sclk_ctrl, + .ctrlbit = S3C_CLKCON_SCLK_MMC2_48, + }, +}; + +static struct clk init_clocks[] = { + { + .name = "lcd", + .id = -1, + .parent = &clk_h, + .enable = s3c64xx_hclk_ctrl, + .ctrlbit = S3C_CLKCON_HCLK_LCD, + }, { + .name = "gpio", + .id = -1, + .parent = &clk_p, + .enable = s3c64xx_pclk_ctrl, + .ctrlbit = S3C_CLKCON_PCLK_GPIO, + }, { + .name = "usb-host", + .id = -1, + .parent = &clk_h, + .enable = s3c64xx_hclk_ctrl, + .ctrlbit = S3C_CLKCON_SCLK_UHOST, + }, { + .name = "hsmmc", + .id = 0, + .parent = &clk_h, + .enable = s3c64xx_hclk_ctrl, + .ctrlbit = S3C_CLKCON_HCLK_HSMMC0, + }, { + .name = "hsmmc", + .id = 1, + .parent = &clk_h, + .enable = s3c64xx_hclk_ctrl, + .ctrlbit = S3C_CLKCON_HCLK_HSMMC1, + }, { + .name = "hsmmc", + .id = 2, + .parent = &clk_h, + .enable = s3c64xx_hclk_ctrl, + .ctrlbit = S3C_CLKCON_HCLK_HSMMC2, + }, { + .name = "timers", + .id = -1, + .parent = &clk_p, + .enable = s3c64xx_pclk_ctrl, + .ctrlbit = S3C_CLKCON_PCLK_PWM, + }, { + .name = "uart", + .id = 0, + .parent = &clk_p, + .enable = s3c64xx_pclk_ctrl, + .ctrlbit = S3C_CLKCON_PCLK_UART0, + }, { + .name = "uart", + .id = 1, + .parent = &clk_p, + .enable = s3c64xx_pclk_ctrl, + .ctrlbit = S3C_CLKCON_PCLK_UART1, + }, { + .name = "uart", + .id = 2, + .parent = &clk_p, + .enable = s3c64xx_pclk_ctrl, + .ctrlbit = S3C_CLKCON_PCLK_UART2, + }, { + .name = "uart", + .id = 3, + .parent = &clk_p, + .enable = s3c64xx_pclk_ctrl, + .ctrlbit = S3C_CLKCON_PCLK_UART3, + }, { + .name = "rtc", + .id = -1, + .parent = &clk_p, + .enable = s3c64xx_pclk_ctrl, + .ctrlbit = S3C_CLKCON_PCLK_RTC, + }, { + .name = "watchdog", + .id = -1, + .parent = &clk_p, + .ctrlbit = S3C_CLKCON_PCLK_WDT, + }, { + .name = "ac97", + .id = -1, + .parent = &clk_p, + .ctrlbit = S3C_CLKCON_PCLK_AC97, + } +}; + +static struct clk *clks[] __initdata = { + &clk_ext, + &clk_epll, + &clk_27m, + &clk_48m, +}; + +void s3c64xx_register_clocks(void) +{ + struct clk *clkp; + int ret; + int ptr; + + s3c24xx_register_clocks(clks, ARRAY_SIZE(clks)); + + clkp = init_clocks; + for (ptr = 0; ptr < ARRAY_SIZE(init_clocks); ptr++, clkp++) { + ret = s3c24xx_register_clock(clkp); + if (ret < 0) { + printk(KERN_ERR "Failed to register clock %s (%d)\n", + clkp->name, ret); + } + } + + clkp = init_clocks_disable; + for (ptr = 0; ptr < ARRAY_SIZE(init_clocks_disable); ptr++, clkp++) { + + ret = s3c24xx_register_clock(clkp); + if (ret < 0) { + printk(KERN_ERR "Failed to register clock %s (%d)\n", + clkp->name, ret); + } + + (clkp->enable)(clkp, 0); + } + + s3c_pwmclk_init(); +} diff --git a/arch/arm/plat-s3c64xx/cpu.c b/arch/arm/plat-s3c64xx/cpu.c new file mode 100644 index 00000000000..36182fcfaeb --- /dev/null +++ b/arch/arm/plat-s3c64xx/cpu.c @@ -0,0 +1,115 @@ +/* linux/arch/arm/plat-s3c64xx/cpu.c + * + * Copyright 2008 Openmoko, Inc. + * Copyright 2008 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * http://armlinux.simtec.co.uk/ + * + * S3C64XX 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. +*/ + +#include <linux/init.h> +#include <linux/module.h> +#include <linux/interrupt.h> +#include <linux/ioport.h> +#include <linux/serial_core.h> +#include <linux/platform_device.h> +#include <linux/delay.h> +#include <linux/io.h> + +#include <mach/hardware.h> +#include <mach/map.h> + +#include <asm/mach/arch.h> +#include <asm/mach/map.h> + +#include <plat/regs-serial.h> + +#include <plat/cpu.h> +#include <plat/devs.h> +#include <plat/clock.h> + +#include <plat/s3c6400.h> +#include <plat/s3c6410.h> + +/* table of supported CPUs */ + +static const char name_s3c6400[] = "S3C6400"; +static const char name_s3c6410[] = "S3C6410"; + +static struct cpu_table cpu_ids[] __initdata = { + { + .idcode = 0x36400000, + .idmask = 0xfffff000, + .map_io = s3c6400_map_io, + .init_clocks = s3c6400_init_clocks, + .init_uarts = s3c6400_init_uarts, + .init = s3c6400_init, + .name = name_s3c6400, + }, { + .idcode = 0x36410100, + .idmask = 0xffffff00, + .map_io = s3c6410_map_io, + .init_clocks = s3c6410_init_clocks, + .init_uarts = s3c6410_init_uarts, + .init = s3c6410_init, + .name = name_s3c6410, + }, +}; + +/* minimal IO mapping */ + +/* see notes on uart map in arch/arm/mach-s3c6400/include/mach/debug-macro.S */ +#define UART_OFFS (S3C_PA_UART & 0xfffff) + +static struct map_desc s3c_iodesc[] __initdata = { + { + .virtual = (unsigned long)S3C_VA_SYS, + .pfn = __phys_to_pfn(S3C64XX_PA_SYSCON), + .length = SZ_4K, + .type = MT_DEVICE, + }, { + .virtual = (unsigned long)(S3C_VA_UART + UART_OFFS), + .pfn = __phys_to_pfn(S3C_PA_UART), + .length = SZ_4K, + .type = MT_DEVICE, + }, { + .virtual = (unsigned long)S3C_VA_VIC0, + .pfn = __phys_to_pfn(S3C64XX_PA_VIC0), + .length = SZ_16K, + .type = MT_DEVICE, + }, { + .virtual = (unsigned long)S3C_VA_VIC1, + .pfn = __phys_to_pfn(S3C64XX_PA_VIC1), + .length = SZ_16K, + .type = MT_DEVICE, + }, { + .virtual = (unsigned long)S3C_VA_TIMER, + .pfn = __phys_to_pfn(S3C_PA_TIMER), + .length = SZ_16K, + .type = MT_DEVICE, + }, { + .virtual = (unsigned long)S3C64XX_VA_GPIO, + .pfn = __phys_to_pfn(S3C64XX_PA_GPIO), + .length = SZ_4K, + .type = MT_DEVICE, + }, +}; + +/* read cpu identification code */ + +void __init s3c64xx_init_io(struct map_desc *mach_desc, int size) +{ + unsigned long idcode; + + /* initialise the io descriptors we need for initialisation */ + iotable_init(s3c_iodesc, ARRAY_SIZE(s3c_iodesc)); + iotable_init(mach_desc, size); + + idcode = __raw_readl(S3C_VA_SYS + 0x118); + s3c_init_cpu(idcode, cpu_ids, ARRAY_SIZE(cpu_ids)); +} diff --git a/arch/arm/plat-s3c64xx/dev-uart.c b/arch/arm/plat-s3c64xx/dev-uart.c new file mode 100644 index 00000000000..62c11a6fc7b --- /dev/null +++ b/arch/arm/plat-s3c64xx/dev-uart.c @@ -0,0 +1,176 @@ +/* linux/arch/arm/plat-s3c64xx/dev-uart.c + * + * Copyright 2008 Openmoko, Inc. + * Copyright 2008 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * http://armlinux.simtec.co.uk/ + * + * Base S3C64XX UART resource and 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. + * +*/ + +#include <linux/kernel.h> +#include <linux/types.h> +#include <linux/interrupt.h> +#include <linux/list.h> +#include <linux/platform_device.h> + +#include <asm/mach/arch.h> +#include <asm/mach/irq.h> +#include <mach/hardware.h> +#include <mach/map.h> + +#include <plat/devs.h> + +/* Serial port registrations */ + +/* 64xx uarts are closer together */ + +static struct resource s3c64xx_uart0_resource[] = { + [0] = { + .start = S3C_PA_UART0, + .end = S3C_PA_UART0 + 0x100, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_S3CUART_RX0, + .end = IRQ_S3CUART_RX0, + .flags = IORESOURCE_IRQ, + }, + [2] = { + .start = IRQ_S3CUART_TX0, + .end = IRQ_S3CUART_TX0, + .flags = IORESOURCE_IRQ, + + }, + [3] = { + .start = IRQ_S3CUART_ERR0, + .end = IRQ_S3CUART_ERR0, + .flags = IORESOURCE_IRQ, + } +}; + +static struct resource s3c64xx_uart1_resource[] = { + [0] = { + .start = S3C_PA_UART1, + .end = S3C_PA_UART1 + 0x100, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_S3CUART_RX1, + .end = IRQ_S3CUART_RX1, + .flags = IORESOURCE_IRQ, + }, + [2] = { + .start = IRQ_S3CUART_TX1, + .end = IRQ_S3CUART_TX1, + .flags = IORESOURCE_IRQ, + + }, + [3] = { + .start = IRQ_S3CUART_ERR1, + .end = IRQ_S3CUART_ERR1, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct resource s3c6xx_uart2_resource[] = { + [0] = { + .start = S3C_PA_UART2, + .end = S3C_PA_UART2 + 0x100, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_S3CUART_RX2, + .end = IRQ_S3CUART_RX2, + .flags = IORESOURCE_IRQ, + }, + [2] = { + .start = IRQ_S3CUART_TX2, + .end = IRQ_S3CUART_TX2, + .flags = IORESOURCE_IRQ, + + }, + [3] = { + .start = IRQ_S3CUART_ERR2, + .end = IRQ_S3CUART_ERR2, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct resource s3c64xx_uart3_resource[] = { + [0] = { + .start = S3C_PA_UART3, + .end = S3C_PA_UART3 + 0x100, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_S3CUART_RX3, + .end = IRQ_S3CUART_RX3, + .flags = IORESOURCE_IRQ, + }, + [2] = { + .start = IRQ_S3CUART_TX3, + .end = IRQ_S3CUART_TX3, + .flags = IORESOURCE_IRQ, + + }, + [3] = { + .start = IRQ_S3CUART_ERR3, + .end = IRQ_S3CUART_ERR3, + .flags = IORESOURCE_IRQ, + }, +}; + + +struct s3c24xx_uart_resources s3c64xx_uart_resources[] __initdata = { + [0] = { + .resources = s3c64xx_uart0_resource, + .nr_resources = ARRAY_SIZE(s3c64xx_uart0_resource), + }, + [1] = { + .resources = s3c64xx_uart1_resource, + .nr_resources = ARRAY_SIZE(s3c64xx_uart1_resource), + }, + [2] = { + .resources = s3c6xx_uart2_resource, + .nr_resources = ARRAY_SIZE(s3c6xx_uart2_resource), + }, + [3] = { + .resources = s3c64xx_uart3_resource, + .nr_resources = ARRAY_SIZE(s3c64xx_uart3_resource), + }, +}; + +/* uart devices */ + +static struct platform_device s3c24xx_uart_device0 = { + .id = 0, +}; + +static struct platform_device s3c24xx_uart_device1 = { + .id = 1, +}; + +static struct platform_device s3c24xx_uart_device2 = { + .id = 2, +}; + +static struct platform_device s3c24xx_uart_device3 = { + .id = 3, +}; + +struct platform_device *s3c24xx_uart_src[4] = { + &s3c24xx_uart_device0, + &s3c24xx_uart_device1, + &s3c24xx_uart_device2, + &s3c24xx_uart_device3, +}; + +struct platform_device *s3c24xx_uart_devs[4] = { +}; + diff --git a/arch/arm/plat-s3c64xx/include/plat/irqs.h b/arch/arm/plat-s3c64xx/include/plat/irqs.h new file mode 100644 index 00000000000..bc25689c3f8 --- /dev/null +++ b/arch/arm/plat-s3c64xx/include/plat/irqs.h @@ -0,0 +1,196 @@ +/* linux/arch/arm/plat-s3c64xx/include/mach/irqs.h + * + * Copyright 2008 Openmoko, Inc. + * Copyright 2008 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * http://armlinux.simtec.co.uk/ + * + * S3C64XX - Common IRQ support + */ + +#ifndef __ASM_PLAT_S3C64XX_IRQS_H +#define __ASM_PLAT_S3C64XX_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.... + * + * note, since we're using the VICs, our start must be a + * mulitple of 32 to allow the common code to work + */ + +#define S3C_IRQ_OFFSET (32) + +#define S3C_IRQ(x) ((x) + S3C_IRQ_OFFSET) + +#define S3C_VIC0_BASE S3C_IRQ(0) +#define S3C_VIC1_BASE S3C_IRQ(32) + +/* UART interrupts, each UART has 4 intterupts per channel so + * use the space between the ISA and S3C main interrupts. Note, these + * are not in the same order as the S3C24XX series! */ + +#define IRQ_S3CUART_BASE0 (16) +#define IRQ_S3CUART_BASE1 (20) +#define IRQ_S3CUART_BASE2 (24) +#define IRQ_S3CUART_BASE3 (28) + +#define UART_IRQ_RXD (0) +#define UART_IRQ_ERR (1) +#define UART_IRQ_TXD (2) +#define UART_IRQ_MODEM (3) + +#define IRQ_S3CUART_RX0 (IRQ_S3CUART_BASE0 + UART_IRQ_RXD) +#define IRQ_S3CUART_TX0 (IRQ_S3CUART_BASE0 + UART_IRQ_TXD) +#define IRQ_S3CUART_ERR0 (IRQ_S3CUART_BASE0 + UART_IRQ_ERR) + +#define IRQ_S3CUART_RX1 (IRQ_S3CUART_BASE1 + UART_IRQ_RXD) +#define IRQ_S3CUART_TX1 (IRQ_S3CUART_BASE1 + UART_IRQ_TXD) +#define IRQ_S3CUART_ERR1 (IRQ_S3CUART_BASE1 + UART_IRQ_ERR) + +#define IRQ_S3CUART_RX2 (IRQ_S3CUART_BASE2 + UART_IRQ_RXD) +#define IRQ_S3CUART_TX2 (IRQ_S3CUART_BASE2 + UART_IRQ_TXD) +#define IRQ_S3CUART_ERR2 (IRQ_S3CUART_BASE2 + UART_IRQ_ERR) + +#define IRQ_S3CUART_RX3 (IRQ_S3CUART_BASE3 + UART_IRQ_RXD) +#define IRQ_S3CUART_TX3 (IRQ_S3CUART_BASE3 + UART_IRQ_TXD) +#define IRQ_S3CUART_ERR3 (IRQ_S3CUART_BASE3 + UART_IRQ_ERR) + +/* VIC based IRQs */ + +#define S3C64XX_IRQ_VIC0(x) (S3C_VIC0_BASE + (x)) +#define S3C64XX_IRQ_VIC1(x) (S3C_VIC1_BASE + (x)) + +/* VIC0 */ + +#define IRQ_EINT0_3 S3C64XX_IRQ_VIC0(0) +#define IRQ_EINT4_11 S3C64XX_IRQ_VIC0(1) +#define IRQ_RTC_TIC S3C64XX_IRQ_VIC0(2) +#define IRQ_CAMIF_C S3C64XX_IRQ_VIC0(3) +#define IRQ_CAMIF_P S3C64XX_IRQ_VIC0(4) +#define IRQ_CAMIF_MC S3C64XX_IRQ_VIC0(5) +#define IRQ_S3C6410_IIS S3C64XX_IRQ_VIC0(6) +#define IRQ_S3C6400_CAMIF_MP S3C64XX_IRQ_VIC0(6) +#define IRQ_CAMIF_WE_C S3C64XX_IRQ_VIC0(7) +#define IRQ_S3C6410_G3D S3C64XX_IRQ_VIC0(8) +#define IRQ_S3C6400_CAMIF_WE_P S3C64XX_IRQ_VIC0(8) +#define IRQ_POST0 S3C64XX_IRQ_VIC0(9) +#define IRQ_ROTATOR S3C64XX_IRQ_VIC0(10) +#define IRQ_2D S3C64XX_IRQ_VIC0(11) +#define IRQ_TVENC S3C64XX_IRQ_VIC0(12) +#define IRQ_SCALER S3C64XX_IRQ_VIC0(13) +#define IRQ_BATF S3C64XX_IRQ_VIC0(14) +#define IRQ_JPEG S3C64XX_IRQ_VIC0(15) +#define IRQ_MFC S3C64XX_IRQ_VIC0(16) +#define IRQ_SDMA0 S3C64XX_IRQ_VIC0(17) +#define IRQ_SDMA1 S3C64XX_IRQ_VIC0(18) +#define IRQ_ARM_DMAERR S3C64XX_IRQ_VIC0(19) +#define IRQ_ARM_DMA S3C64XX_IRQ_VIC0(20) +#define IRQ_ARM_DMAS S3C64XX_IRQ_VIC0(21) +#define IRQ_KEYPAD S3C64XX_IRQ_VIC0(22) +#define IRQ_TIMER0_VIC S3C64XX_IRQ_VIC0(23) +#define IRQ_TIMER1_VIC S3C64XX_IRQ_VIC0(24) +#define IRQ_TIMER2_VIC S3C64XX_IRQ_VIC0(25) +#define IRQ_WDT S3C64XX_IRQ_VIC0(26) +#define IRQ_TIMER3_VIC S3C64XX_IRQ_VIC0(27) +#define IRQ_TIMER4_VIC S3C64XX_IRQ_VIC0(28) +#define IRQ_LCD_FIFO S3C64XX_IRQ_VIC0(29) +#define IRQ_LCD_VSYNC S3C64XX_IRQ_VIC0(30) +#define IRQ_LCD_SYSTEM S3C64XX_IRQ_VIC0(31) + +/* VIC1 */ + +#define IRQ_EINT12_19 S3C64XX_IRQ_VIC1(0) +#define IRQ_EINT20_27 S3C64XX_IRQ_VIC1(1) +#define IRQ_PCM0 S3C64XX_IRQ_VIC1(2) +#define IRQ_PCM1 S3C64XX_IRQ_VIC1(3) +#define IRQ_AC97 S3C64XX_IRQ_VIC1(4) +#define IRQ_UART0 S3C64XX_IRQ_VIC1(5) +#define IRQ_UART1 S3C64XX_IRQ_VIC1(6) +#define IRQ_UART2 S3C64XX_IRQ_VIC1(7) +#define IRQ_UART3 S3C64XX_IRQ_VIC1(8) +#define IRQ_DMA0 S3C64XX_IRQ_VIC1(9) +#define IRQ_DMA1 S3C64XX_IRQ_VIC1(10) +#define IRQ_ONENAND0 S3C64XX_IRQ_VIC1(11) +#define IRQ_ONENAND1 S3C64XX_IRQ_VIC1(12) +#define IRQ_NFC S3C64XX_IRQ_VIC1(13) +#define IRQ_CFCON S3C64XX_IRQ_VIC1(14) +#define IRQ_UHOST S3C64XX_IRQ_VIC1(15) +#define IRQ_SPI0 S3C64XX_IRQ_VIC1(16) +#define IRQ_SPI1 S3C64XX_IRQ_VIC1(17) +#define IRQ_IIC S3C64XX_IRQ_VIC1(18) +#define IRQ_HSItx S3C64XX_IRQ_VIC1(19) +#define IRQ_HSIrx S3C64XX_IRQ_VIC1(20) +#define IRQ_RESERVED S3C64XX_IRQ_VIC1(21) +#define IRQ_MSM S3C64XX_IRQ_VIC1(22) +#define IRQ_HOSTIF S3C64XX_IRQ_VIC1(23) +#define IRQ_HSMMC0 S3C64XX_IRQ_VIC1(24) +#define IRQ_HSMMC1 S3C64XX_IRQ_VIC1(25) +#define IRQ_HSMMC2 IRQ_SPI1 /* shared with SPI1 */ +#define IRQ_OTG S3C64XX_IRQ_VIC1(26) +#define IRQ_IRDA S3C64XX_IRQ_VIC1(27) +#define IRQ_RTC_ALARM S3C64XX_IRQ_VIC1(28) +#define IRQ_SEC S3C64XX_IRQ_VIC1(29) +#define IRQ_PENDN S3C64XX_IRQ_VIC1(30) +#define IRQ_TC IRQ_PENDN +#define IRQ_ADC S3C64XX_IRQ_VIC1(31) + +#define S3C64XX_TIMER_IRQ(x) S3C_IRQ(64 + (x)) + +#define IRQ_TIMER0 S3C64XX_TIMER_IRQ(0) +#define IRQ_TIMER1 S3C64XX_TIMER_IRQ(1) +#define IRQ_TIMER2 S3C64XX_TIMER_IRQ(2) +#define IRQ_TIMER3 S3C64XX_TIMER_IRQ(3) +#define IRQ_TIMER4 S3C64XX_TIMER_IRQ(4) + +/* Since the IRQ_EINT(x) are a linear mapping on current s3c64xx series + * we just defined them as an IRQ_EINT(x) macro from S3C_IRQ_EINT_BASE + * which we place after the pair of VICs. */ + +#define S3C_IRQ_EINT_BASE S3C_IRQ(64+5) + +#define S3C_EINT(x) ((x) + S3C_IRQ_EINT_BASE) +#define IRQ_EINT(x) S3C_EINT(x) + +/* Next the external interrupt groups. These are similar to the IRQ_EINT(x) + * that they are sourced from the GPIO pins but with a different scheme for + * priority and source indication. + * + * The IRQ_EINT(x) can be thought of as 'group 0' of the available GPIO + * interrupts, but for historical reasons they are kept apart from these + * next interrupts. + * + * Use IRQ_EINT_GROUP(group, offset) to get the number for use in the + * machine specific support files. + */ + +#define IRQ_EINT_GROUP1_NR (15) +#define IRQ_EINT_GROUP2_NR (8) +#define IRQ_EINT_GROUP3_NR (5) +#define IRQ_EINT_GROUP4_NR (14) +#define IRQ_EINT_GROUP5_NR (7) +#define IRQ_EINT_GROUP6_NR (10) +#define IRQ_EINT_GROUP7_NR (16) +#define IRQ_EINT_GROUP8_NR (15) +#define IRQ_EINT_GROUP9_NR (9) + +#define IRQ_EINT_GROUP_BASE S3C_EINT(28) +#define IRQ_EINT_GROUP1_BASE (IRQ_EINT_GROUP_BASE + 0x00) +#define IRQ_EINT_GROUP2_BASE (IRQ_EINT_GROUP1_BASE + IRQ_EINT_GROUP1_NR) +#define IRQ_EINT_GROUP3_BASE (IRQ_EINT_GROUP2_BASE + IRQ_EINT_GROUP2_NR) +#define IRQ_EINT_GROUP4_BASE (IRQ_EINT_GROUP3_BASE + IRQ_EINT_GROUP3_NR) +#define IRQ_EINT_GROUP5_BASE (IRQ_EINT_GROUP4_BASE + IRQ_EINT_GROUP4_NR) +#define IRQ_EINT_GROUP6_BASE (IRQ_EINT_GROUP5_BASE + IRQ_EINT_GROUP5_NR) +#define IRQ_EINT_GROUP7_BASE (IRQ_EINT_GROUP6_BASE + IRQ_EINT_GROUP6_NR) +#define IRQ_EINT_GROUP8_BASE (IRQ_EINT_GROUP7_BASE + IRQ_EINT_GROUP7_NR) +#define IRQ_EINT_GROUP9_BASE (IRQ_EINT_GROUP8_BASE + IRQ_EINT_GROUP8_NR) + +#define IRQ_EINT_GROUP(group, no) (IRQ_EINT_GROUP##group##__BASE + (x)) + +/* Set the default NR_IRQS */ + +#define NR_IRQS (IRQ_EINT_GROUP9_BASE + IRQ_EINT_GROUP9_NR + 1) + +#endif /* __ASM_PLAT_S3C64XX_IRQS_H */ + diff --git a/arch/arm/plat-s3c64xx/include/plat/pll.h b/arch/arm/plat-s3c64xx/include/plat/pll.h new file mode 100644 index 00000000000..90bbd72fdc4 --- /dev/null +++ b/arch/arm/plat-s3c64xx/include/plat/pll.h @@ -0,0 +1,74 @@ +/* arch/arm/plat-s3c64xx/include/plat/pll.h + * + * Copyright 2008 Openmoko, Inc. + * Copyright 2008 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * http://armlinux.simtec.co.uk/ + * + * S3C64XX PLL code + * + * 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. +*/ + +#define S3C6400_PLL_MDIV_MASK ((1 << (25-16+1)) - 1) +#define S3C6400_PLL_PDIV_MASK ((1 << (13-8+1)) - 1) +#define S3C6400_PLL_SDIV_MASK ((1 << (2-0+1)) - 1) +#define S3C6400_PLL_MDIV_SHIFT (16) +#define S3C6400_PLL_PDIV_SHIFT (8) +#define S3C6400_PLL_SDIV_SHIFT (0) + +#include <asm/div64.h> + +static inline unsigned long s3c6400_get_pll(unsigned long baseclk, + u32 pllcon) +{ + u32 mdiv, pdiv, sdiv; + u64 fvco = baseclk; + + mdiv = (pllcon >> S3C6400_PLL_MDIV_SHIFT) & S3C6400_PLL_MDIV_MASK; + pdiv = (pllcon >> S3C6400_PLL_PDIV_SHIFT) & S3C6400_PLL_PDIV_MASK; + sdiv = (pllcon >> S3C6400_PLL_SDIV_SHIFT) & S3C6400_PLL_SDIV_MASK; + + fvco *= mdiv; + do_div(fvco, (pdiv << sdiv)); + + return (unsigned long)fvco; +} + +#define S3C6400_EPLL_MDIV_MASK ((1 << (23-16)) - 1) +#define S3C6400_EPLL_PDIV_MASK ((1 << (13-8)) - 1) +#define S3C6400_EPLL_SDIV_MASK ((1 << (2-0)) - 1) +#define S3C6400_EPLL_MDIV_SHIFT (16) +#define S3C6400_EPLL_PDIV_SHIFT (8) +#define S3C6400_EPLL_SDIV_SHIFT (0) +#define S3C6400_EPLL_KDIV_MASK (0xffff) + +static inline unsigned long s3c6400_get_epll(unsigned long baseclk) +{ + unsigned long result; + u32 epll0 = __raw_readl(S3C_EPLL_CON0); + u32 epll1 = __raw_readl(S3C_EPLL_CON1); + u32 mdiv, pdiv, sdiv, kdiv; + u64 tmp; + + mdiv = (epll0 >> S3C6400_EPLL_MDIV_SHIFT) & S3C6400_EPLL_MDIV_MASK; + pdiv = (epll0 >> S3C6400_EPLL_PDIV_SHIFT) & S3C6400_EPLL_PDIV_MASK; + sdiv = (epll0 >> S3C6400_EPLL_SDIV_SHIFT) & S3C6400_EPLL_SDIV_MASK; + kdiv = epll1 & S3C6400_EPLL_KDIV_MASK; + + /* We need to multiple baseclk by mdiv (the integer part) and kdiv + * which is in 2^16ths, so shift mdiv up (does not overflow) and + * add kdiv before multiplying. The use of tmp is to avoid any + * overflows before shifting bac down into result when multipling + * by the mdiv and kdiv pair. + */ + + tmp = baseclk; + tmp *= (mdiv << 16) + kdiv; + do_div(tmp, (pdiv << sdiv)); + result = tmp >> 16; + + return result; +} diff --git a/arch/arm/plat-s3c64xx/include/plat/regs-clock.h b/arch/arm/plat-s3c64xx/include/plat/regs-clock.h new file mode 100644 index 00000000000..b1082c16324 --- /dev/null +++ b/arch/arm/plat-s3c64xx/include/plat/regs-clock.h @@ -0,0 +1,224 @@ +/* arch/arm/plat-s3c64xx/include/plat/regs-clock.h + * + * Copyright 2008 Openmoko, Inc. + * Copyright 2008 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * http://armlinux.simtec.co.uk/ + * + * S3C64XX clock register 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. +*/ + +#ifndef __PLAT_REGS_CLOCK_H +#define __PLAT_REGS_CLOCK_H __FILE__ + +#define S3C_CLKREG(x) (S3C_VA_SYS + (x)) + +#define S3C_APLL_LOCK S3C_CLKREG(0x00) +#define S3C_MPLL_LOCK S3C_CLKREG(0x04) +#define S3C_EPLL_LOCK S3C_CLKREG(0x08) +#define S3C_APLL_CON S3C_CLKREG(0x0C) +#define S3C_MPLL_CON S3C_CLKREG(0x10) +#define S3C_EPLL_CON0 S3C_CLKREG(0x14) +#define S3C_EPLL_CON1 S3C_CLKREG(0x18) +#define S3C_CLK_SRC S3C_CLKREG(0x1C) +#define S3C_CLK_DIV0 S3C_CLKREG(0x20) +#define S3C_CLK_DIV1 S3C_CLKREG(0x24) +#define S3C_CLK_DIV2 S3C_CLKREG(0x28) +#define S3C_CLK_OUT S3C_CLKREG(0x2C) +#define S3C_HCLK_GATE S3C_CLKREG(0x30) +#define S3C_PCLK_GATE S3C_CLKREG(0x34) +#define S3C_SCLK_GATE S3C_CLKREG(0x38) + +/* CLKDIV0 */ +#define S3C6400_CLKDIV0_MFC_MASK (0xf << 28) +#define S3C6400_CLKDIV0_MFC_SHIFT (28) +#define S3C6400_CLKDIV0_JPEG_MASK (0xf << 24) +#define S3C6400_CLKDIV0_JPEG_SHIFT (24) +#define S3C6400_CLKDIV0_CAM_MASK (0xf << 20) +#define S3C6400_CLKDIV0_CAM_SHIFT (20) +#define S3C6400_CLKDIV0_SECURITY_MASK (0x3 << 18) +#define S3C6400_CLKDIV0_SECURITY_SHIFT (18) +#define S3C6400_CLKDIV0_PCLK_MASK (0xf << 12) +#define S3C6400_CLKDIV0_PCLK_SHIFT (12) +#define S3C6400_CLKDIV0_HCLK2_MASK (0x7 << 9) +#define S3C6400_CLKDIV0_HCLK2_SHIFT (9) +#define S3C6400_CLKDIV0_HCLK_MASK (0x1 << 8) +#define S3C6400_CLKDIV0_HCLK_SHIFT (8) +#define S3C6400_CLKDIV0_MPLL_MASK (0x1 << 4) +#define S3C6400_CLKDIV0_MPLL_SHIFT (4) +#define S3C6400_CLKDIV0_ARM_MASK (0x3 << 0) +#define S3C6410_CLKDIV0_ARM_MASK (0x7 << 0) +#define S3C6400_CLKDIV0_ARM_SHIFT (0) + +/* CLKDIV1 */ +#define S3C6410_CLKDIV1_FIMC_MASK (0xf << 24) +#define S3C6410_CLKDIV1_FIMC_SHIFT (24) +#define S3C6400_CLKDIV1_UHOST_MASK (0xf << 20) +#define S3C6400_CLKDIV1_UHOST_SHIFT (20) +#define S3C6400_CLKDIV1_SCALER_MASK (0xf << 16) +#define S3C6400_CLKDIV1_SCALER_SHIFT (16) +#define S3C6400_CLKDIV1_LCD_MASK (0xf << 12) +#define S3C6400_CLKDIV1_LCD_SHIFT (12) +#define S3C6400_CLKDIV1_MMC2_MASK (0xf << 8) +#define S3C6400_CLKDIV1_MMC2_SHIFT (8) +#define S3C6400_CLKDIV1_MMC1_MASK (0xf << 4) +#define S3C6400_CLKDIV1_MMC1_SHIFT (4) +#define S3C6400_CLKDIV1_MMC0_MASK (0xf << 0) +#define S3C6400_CLKDIV1_MMC0_SHIFT (0) + +/* CLKDIV2 */ +#define S3C6410_CLKDIV2_AUDIO2_MASK (0xf << 24) +#define S3C6410_CLKDIV2_AUDIO2_SHIFT (24) +#define S3C6400_CLKDIV2_IRDA_MASK (0xf << 20) +#define S3C6400_CLKDIV2_IRDA_SHIFT (20) +#define S3C6400_CLKDIV2_UART_MASK (0xf << 16) +#define S3C6400_CLKDIV2_UART_SHIFT (16) +#define S3C6400_CLKDIV2_AUDIO1_MASK (0xf << 12) +#define S3C6400_CLKDIV2_AUDIO1_SHIFT (12) +#define S3C6400_CLKDIV2_AUDIO0_MASK (0xf << 8) +#define S3C6400_CLKDIV2_AUDIO0_SHIFT (8) +#define S3C6400_CLKDIV2_SPI1_MASK (0xf << 4) +#define S3C6400_CLKDIV2_SPI1_SHIFT (4) +#define S3C6400_CLKDIV2_SPI0_MASK (0xf << 0) +#define S3C6400_CLKDIV2_SPI0_SHIFT (0) + +/* HCLK GATE Registers */ +#define S3C_CLKCON_HCLK_BUS (1<<30) +#define S3C_CLKCON_HCLK_SECUR (1<<29) +#define S3C_CLKCON_HCLK_SDMA1 (1<<28) +#define S3C_CLKCON_HCLK_SDMA2 (1<<27) +#define S3C_CLKCON_HCLK_UHOST (1<<26) +#define S3C_CLKCON_HCLK_IROM (1<<25) +#define S3C_CLKCON_HCLK_DDR1 (1<<24) +#define S3C_CLKCON_HCLK_DDR0 (1<<23) +#define S3C_CLKCON_HCLK_MEM1 (1<<22) +#define S3C_CLKCON_HCLK_MEM0 (1<<21) +#define S3C_CLKCON_HCLK_USB (1<<20) +#define S3C_CLKCON_HCLK_HSMMC2 (1<<19) +#define S3C_CLKCON_HCLK_HSMMC1 (1<<18) +#define S3C_CLKCON_HCLK_HSMMC0 (1<<17) +#define S3C_CLKCON_HCLK_MDP (1<<16) +#define S3C_CLKCON_HCLK_DHOST (1<<15) +#define S3C_CLKCON_HCLK_IHOST (1<<14) +#define S3C_CLKCON_HCLK_DMA1 (1<<13) +#define S3C_CLKCON_HCLK_DMA0 (1<<12) +#define S3C_CLKCON_HCLK_JPEG (1<<11) +#define S3C_CLKCON_HCLK_CAMIF (1<<10) +#define S3C_CLKCON_HCLK_SCALER (1<<9) +#define S3C_CLKCON_HCLK_2D (1<<8) +#define S3C_CLKCON_HCLK_TV (1<<7) +#define S3C_CLKCON_HCLK_POST0 (1<<5) +#define S3C_CLKCON_HCLK_ROT (1<<4) +#define S3C_CLKCON_HCLK_LCD (1<<3) +#define S3C_CLKCON_HCLK_TZIC (1<<2) +#define S3C_CLKCON_HCLK_INTC (1<<1) +#define S3C_CLKCON_HCLK_MFC (1<<0) + +/* PCLK GATE Registers */ +#define S3C6410_CLKCON_PCLK_I2C1 (1<<27) +#define S3C6410_CLKCON_PCLK_IIS2 (1<<26) +#define S3C_CLKCON_PCLK_SKEY (1<<24) +#define S3C_CLKCON_PCLK_CHIPID (1<<23) +#define S3C_CLKCON_PCLK_SPI1 (1<<22) +#define S3C_CLKCON_PCLK_SPI0 (1<<21) +#define S3C_CLKCON_PCLK_HSIRX (1<<20) +#define S3C_CLKCON_PCLK_HSITX (1<<19) +#define S3C_CLKCON_PCLK_GPIO (1<<18) +#define S3C_CLKCON_PCLK_IIC (1<<17) +#define S3C_CLKCON_PCLK_IIS1 (1<<16) +#define S3C_CLKCON_PCLK_IIS0 (1<<15) +#define S3C_CLKCON_PCLK_AC97 (1<<14) +#define S3C_CLKCON_PCLK_TZPC (1<<13) +#define S3C_CLKCON_PCLK_TSADC (1<<12) +#define S3C_CLKCON_PCLK_KEYPAD (1<<11) +#define S3C_CLKCON_PCLK_IRDA (1<<10) +#define S3C_CLKCON_PCLK_PCM1 (1<<9) +#define S3C_CLKCON_PCLK_PCM0 (1<<8) +#define S3C_CLKCON_PCLK_PWM (1<<7) +#define S3C_CLKCON_PCLK_RTC (1<<6) +#define S3C_CLKCON_PCLK_WDT (1<<5) +#define S3C_CLKCON_PCLK_UART3 (1<<4) +#define S3C_CLKCON_PCLK_UART2 (1<<3) +#define S3C_CLKCON_PCLK_UART1 (1<<2) +#define S3C_CLKCON_PCLK_UART0 (1<<1) +#define S3C_CLKCON_PCLK_MFC (1<<0) + +/* SCLK GATE Registers */ +#define S3C_CLKCON_SCLK_UHOST (1<<30) +#define S3C_CLKCON_SCLK_MMC2_48 (1<<29) +#define S3C_CLKCON_SCLK_MMC1_48 (1<<28) +#define S3C_CLKCON_SCLK_MMC0_48 (1<<27) +#define S3C_CLKCON_SCLK_MMC2 (1<<26) +#define S3C_CLKCON_SCLK_MMC1 (1<<25) +#define S3C_CLKCON_SCLK_MMC0 (1<<24) +#define S3C_CLKCON_SCLK_SPI1_48 (1<<23) +#define S3C_CLKCON_SCLK_SPI0_48 (1<<22) +#define S3C_CLKCON_SCLK_SPI1 (1<<21) +#define S3C_CLKCON_SCLK_SPI0 (1<<20) +#define S3C_CLKCON_SCLK_DAC27 (1<<19) +#define S3C_CLKCON_SCLK_TV27 (1<<18) +#define S3C_CLKCON_SCLK_SCALER27 (1<<17) +#define S3C_CLKCON_SCLK_SCALER (1<<16) +#define S3C_CLKCON_SCLK_LCD27 (1<<15) +#define S3C_CLKCON_SCLK_LCD (1<<14) +#define S3C6400_CLKCON_SCLK_POST1_27 (1<<13) +#define S3C6410_CLKCON_FIMC (1<<13) +#define S3C_CLKCON_SCLK_POST0_27 (1<<12) +#define S3C6400_CLKCON_SCLK_POST1 (1<<11) +#define S3C6410_CLKCON_SCLK_AUDIO2 (1<<11) +#define S3C_CLKCON_SCLK_POST0 (1<<10) +#define S3C_CLKCON_SCLK_AUDIO1 (1<<9) +#define S3C_CLKCON_SCLK_AUDIO0 (1<<8) +#define S3C_CLKCON_SCLK_SECUR (1<<7) +#define S3C_CLKCON_SCLK_IRDA (1<<6) +#define S3C_CLKCON_SCLK_UART (1<<5) +#define S3C_CLKCON_SCLK_ONENAND (1<<4) +#define S3C_CLKCON_SCLK_MFC (1<<3) +#define S3C_CLKCON_SCLK_CAM (1<<2) +#define S3C_CLKCON_SCLK_JPEG (1<<1) + +/* CLKSRC */ + +#define S3C6400_CLKSRC_APLL_MOUT (1 << 0) +#define S3C6400_CLKSRC_MPLL_MOUT (1 << 1) +#define S3C6400_CLKSRC_EPLL_MOUT (1 << 2) +#define S3C6400_CLKSRC_APLL_MOUT_SHIFT (0) +#define S3C6400_CLKSRC_MPLL_MOUT_SHIFT (1) +#define S3C6400_CLKSRC_EPLL_MOUT_SHIFT (2) +#define S3C6400_CLKSRC_MFC (1 << 4) + +#define S3C6410_CLKSRC_TV27_MASK (0x1 << 31) +#define S3C6410_CLKSRC_TV27_SHIFT (31) +#define S3C6410_CLKSRC_DAC27_MASK (0x1 << 30) +#define S3C6410_CLKSRC_DAC27_SHIFT (30) +#define S3C6400_CLKSRC_SCALER_MASK (0x3 << 28) +#define S3C6400_CLKSRC_SCALER_SHIFT (28) +#define S3C6400_CLKSRC_LCD_MASK (0x3 << 26) +#define S3C6400_CLKSRC_LCD_SHIFT (26) +#define S3C6400_CLKSRC_IRDA_MASK (0x3 << 24) +#define S3C6400_CLKSRC_IRDA_SHIFT (24) +#define S3C6400_CLKSRC_MMC2_MASK (0x3 << 22) +#define S3C6400_CLKSRC_MMC2_SHIFT (22) +#define S3C6400_CLKSRC_MMC1_MASK (0x3 << 20) +#define S3C6400_CLKSRC_MMC1_SHIFT (20) +#define S3C6400_CLKSRC_MMC0_MASK (0x3 << 18) +#define S3C6400_CLKSRC_MMC0_SHIFT (18) +#define S3C6400_CLKSRC_SPI1_MASK (0x3 << 16) +#define S3C6400_CLKSRC_SPI1_SHIFT (16) +#define S3C6400_CLKSRC_SPI0_MASK (0x3 << 14) +#define S3C6400_CLKSRC_SPI0_SHIFT (14) +#define S3C6400_CLKSRC_UART_MASK (0x1 << 13) +#define S3C6400_CLKSRC_UART_SHIFT (13) +#define S3C6400_CLKSRC_AUDIO1_MASK (0x7 << 10) +#define S3C6400_CLKSRC_AUDIO1_SHIFT (10) +#define S3C6400_CLKSRC_AUDIO0_MASK (0x7 << 7) +#define S3C6400_CLKSRC_AUDIO0_SHIFT (7) +#define S3C6400_CLKSRC_UHOST_MASK (0x3 << 5) +#define S3C6400_CLKSRC_UHOST_SHIFT (5) + + +#endif /* _PLAT_REGS_CLOCK_H */ diff --git a/arch/arm/plat-s3c64xx/include/plat/regs-sys.h b/arch/arm/plat-s3c64xx/include/plat/regs-sys.h new file mode 100644 index 00000000000..d8ed8291709 --- /dev/null +++ b/arch/arm/plat-s3c64xx/include/plat/regs-sys.h @@ -0,0 +1,24 @@ +/* arch/arm/plat-s3c64xx/include/plat/regs-sys.h + * + * Copyright 2008 Openmoko, Inc. + * Copyright 2008 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * http://armlinux.simtec.co.uk/ + * + * S3C64XX system register 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. +*/ + +#ifndef __PLAT_REGS_SYS_H +#define __PLAT_REGS_SYS_H __FILE__ + +#define S3C_SYSREG(x) (S3C_VA_SYS + (x)) + +#define S3C64XX_OTHERS S3C_SYSREG(0x900) + +#define S3C64XX_OTHERS_USBMASK (1 << 16) + +#endif /* _PLAT_REGS_SYS_H */ diff --git a/arch/arm/plat-s3c64xx/include/plat/s3c6400.h b/arch/arm/plat-s3c64xx/include/plat/s3c6400.h new file mode 100644 index 00000000000..571eaa2e54f --- /dev/null +++ b/arch/arm/plat-s3c64xx/include/plat/s3c6400.h @@ -0,0 +1,35 @@ +/* arch/arm/plat-s3c64xx/include/plat/s3c6400.h + * + * Copyright 2008 Openmoko, Inc. + * Copyright 2008 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * http://armlinux.simtec.co.uk/ + * + * Header file for s3c6400 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. +*/ + +/* Common init code for S3C6400 related SoCs */ + +extern void s3c6400_common_init_uarts(struct s3c2410_uartcfg *cfg, int no); +extern void s3c6400_register_clocks(void); +extern void s3c6400_setup_clocks(void); + +#ifdef CONFIG_CPU_S3C6400 + +extern int s3c6400_init(void); +extern void s3c6400_map_io(void); +extern void s3c6400_init_clocks(int xtal); + +#define s3c6400_init_uarts s3c6400_common_init_uarts + +#else +#define s3c6400_init_clocks NULL +#define s3c6400_init_uarts NULL +#define s3c6400_map_io NULL +#define s3c6400_init NULL +#endif + diff --git a/arch/arm/plat-s3c64xx/include/plat/s3c6410.h b/arch/arm/plat-s3c64xx/include/plat/s3c6410.h new file mode 100644 index 00000000000..50dcdd6f680 --- /dev/null +++ b/arch/arm/plat-s3c64xx/include/plat/s3c6410.h @@ -0,0 +1,29 @@ +/* arch/arm/plat-s3c64xx/include/plat/s3c6410.h + * + * Copyright 2008 Openmoko, Inc. + * Copyright 2008 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * http://armlinux.simtec.co.uk/ + * + * Header file for s3c6410 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. +*/ + +#ifdef CONFIG_CPU_S3C6410 + +extern int s3c6410_init(void); +extern void s3c6410_init_irq(void); +extern void s3c6410_map_io(void); +extern void s3c6410_init_clocks(int xtal); + +#define s3c6410_init_uarts s3c6400_common_init_uarts + +#else +#define s3c6410_init_clocks NULL +#define s3c6410_init_uarts NULL +#define s3c6410_map_io NULL +#define s3c6410_init NULL +#endif diff --git a/arch/arm/plat-s3c64xx/irq-eint.c b/arch/arm/plat-s3c64xx/irq-eint.c new file mode 100644 index 00000000000..1f7cc0067f5 --- /dev/null +++ b/arch/arm/plat-s3c64xx/irq-eint.c @@ -0,0 +1,202 @@ +/* arch/arm/plat-s3c64xx/irq-eint.c + * + * Copyright 2008 Openmoko, Inc. + * Copyright 2008 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * http://armlinux.simtec.co.uk/ + * + * S3C64XX - Interrupt handling for IRQ_EINT(x) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/kernel.h> +#include <linux/interrupt.h> +#include <linux/irq.h> +#include <linux/io.h> + +#include <asm/hardware/vic.h> + +#include <plat/regs-irqtype.h> + +#include <mach/map.h> +#include <plat/cpu.h> + +/* GPIO is 0x7F008xxx, */ +#define S3C64XX_GPIOREG(x) (S3C64XX_VA_GPIO + (x)) + +#define S3C64XX_EINT0CON0 S3C64XX_GPIOREG(0x900) +#define S3C64XX_EINT0CON1 S3C64XX_GPIOREG(0x904) +#define S3C64XX_EINT0FLTCON0 S3C64XX_GPIOREG(0x910) +#define S3C64XX_EINT0FLTCON1 S3C64XX_GPIOREG(0x914) +#define S3C64XX_EINT0FLTCON2 S3C64XX_GPIOREG(0x918) +#define S3C64XX_EINT0FLTCON3 S3C64XX_GPIOREG(0x91C) + +#define S3C64XX_EINT0MASK S3C64XX_GPIOREG(0x920) +#define S3C64XX_EINT0PEND S3C64XX_GPIOREG(0x924) + + +#define eint_offset(irq) ((irq) - IRQ_EINT(0)) +#define eint_irq_to_bit(irq) (1 << eint_offset(irq)) + +static inline void s3c_irq_eint_mask(unsigned int irq) +{ + u32 mask; + + mask = __raw_readl(S3C64XX_EINT0MASK); + mask |= eint_irq_to_bit(irq); + __raw_writel(mask, S3C64XX_EINT0MASK); +} + +static void s3c_irq_eint_unmask(unsigned int irq) +{ + u32 mask; + + mask = __raw_readl(S3C64XX_EINT0MASK); + mask |= eint_irq_to_bit(irq); + __raw_writel(mask, S3C64XX_EINT0MASK); +} + +static inline void s3c_irq_eint_ack(unsigned int irq) +{ + __raw_writel(eint_irq_to_bit(irq), S3C64XX_EINT0PEND); +} + +static void s3c_irq_eint_maskack(unsigned int irq) +{ + /* compiler should in-line these */ + s3c_irq_eint_mask(irq); + s3c_irq_eint_ack(irq); +} + +static int s3c_irq_eint_set_type(unsigned int irq, unsigned int type) +{ + int offs = eint_offset(irq); + int shift; + u32 ctrl, mask; + u32 newvalue = 0; + void __iomem *reg; + + if (offs > 27) + return -EINVAL; + + if (offs <= 15) + reg = S3C64XX_EINT0CON0; + else + reg = S3C64XX_EINT0CON1; + + switch (type) { + case IRQ_TYPE_NONE: + printk(KERN_WARNING "No edge setting!\n"); + break; + + case IRQ_TYPE_EDGE_RISING: + newvalue = S3C2410_EXTINT_RISEEDGE; + break; + + case IRQ_TYPE_EDGE_FALLING: + newvalue = S3C2410_EXTINT_FALLEDGE; + break; + + case IRQ_TYPE_EDGE_BOTH: + newvalue = S3C2410_EXTINT_BOTHEDGE; + break; + + case IRQ_TYPE_LEVEL_LOW: + newvalue = S3C2410_EXTINT_LOWLEV; + break; + + case IRQ_TYPE_LEVEL_HIGH: + newvalue = S3C2410_EXTINT_HILEV; + break; + + default: + printk(KERN_ERR "No such irq type %d", type); + return -1; + } + + shift = (offs / 2) * 4; + mask = 0x7 << shift; + + ctrl = __raw_readl(reg); + ctrl &= ~mask; + ctrl |= newvalue << shift; + __raw_writel(ctrl, reg); + + return 0; +} + +static struct irq_chip s3c_irq_eint = { + .name = "s3c-eint", + .mask = s3c_irq_eint_mask, + .unmask = s3c_irq_eint_unmask, + .mask_ack = s3c_irq_eint_maskack, + .ack = s3c_irq_eint_ack, + .set_type = s3c_irq_eint_set_type, +}; + +/* s3c_irq_demux_eint + * + * This function demuxes the IRQ from the group0 external interrupts, + * from IRQ_EINT(0) to IRQ_EINT(27). It is designed to be inlined into + * the specific handlers s3c_irq_demux_eintX_Y. + */ +static inline void s3c_irq_demux_eint(unsigned int start, unsigned int end) +{ + u32 status = __raw_readl(S3C64XX_EINT0PEND); + u32 mask = __raw_readl(S3C64XX_EINT0MASK); + unsigned int irq; + + status &= ~mask; + status >>= start; + status &= (1 << (end - start + 1)) - 1; + + for (irq = IRQ_EINT(start); irq <= IRQ_EINT(end); irq++) { + if (status & 1) + generic_handle_irq(irq); + + status >>= 1; + } +} + +static void s3c_irq_demux_eint0_3(unsigned int irq, struct irq_desc *desc) +{ + s3c_irq_demux_eint(0, 3); +} + +static void s3c_irq_demux_eint4_11(unsigned int irq, struct irq_desc *desc) +{ + s3c_irq_demux_eint(4, 11); +} + +static void s3c_irq_demux_eint12_19(unsigned int irq, struct irq_desc *desc) +{ + s3c_irq_demux_eint(12, 19); +} + +static void s3c_irq_demux_eint20_27(unsigned int irq, struct irq_desc *desc) +{ + s3c_irq_demux_eint(20, 27); +} + +int __init s3c64xx_init_irq_eint(void) +{ + int irq; + + for (irq = IRQ_EINT(0); irq <= IRQ_EINT(27); irq++) { + set_irq_chip(irq, &s3c_irq_eint); + set_irq_handler(irq, handle_level_irq); + set_irq_flags(irq, IRQF_VALID); + } + + set_irq_chained_handler(IRQ_EINT0_3, s3c_irq_demux_eint0_3); + set_irq_chained_handler(IRQ_EINT4_11, s3c_irq_demux_eint4_11); + set_irq_chained_handler(IRQ_EINT12_19, s3c_irq_demux_eint12_19); + set_irq_chained_handler(IRQ_EINT20_27, s3c_irq_demux_eint20_27); + + return 0; +} + +arch_initcall(s3c64xx_init_irq_eint); diff --git a/arch/arm/plat-s3c64xx/irq.c b/arch/arm/plat-s3c64xx/irq.c new file mode 100644 index 00000000000..a94f1d5e819 --- /dev/null +++ b/arch/arm/plat-s3c64xx/irq.c @@ -0,0 +1,257 @@ +/* arch/arm/plat-s3c64xx/irq.c + * + * Copyright 2008 Openmoko, Inc. + * Copyright 2008 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * http://armlinux.simtec.co.uk/ + * + * S3C64XX - Interrupt handling + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/kernel.h> +#include <linux/interrupt.h> +#include <linux/irq.h> +#include <linux/io.h> + +#include <asm/hardware/vic.h> + +#include <mach/map.h> +#include <plat/regs-timer.h> +#include <plat/cpu.h> + +/* Timer interrupt handling */ + +static void s3c_irq_demux_timer(unsigned int base_irq, unsigned int sub_irq) +{ + generic_handle_irq(sub_irq); +} + +static void s3c_irq_demux_timer0(unsigned int irq, struct irq_desc *desc) +{ + s3c_irq_demux_timer(irq, IRQ_TIMER0); +} + +static void s3c_irq_demux_timer1(unsigned int irq, struct irq_desc *desc) +{ + s3c_irq_demux_timer(irq, IRQ_TIMER1); +} + +static void s3c_irq_demux_timer2(unsigned int irq, struct irq_desc *desc) +{ + s3c_irq_demux_timer(irq, IRQ_TIMER2); +} + +static void s3c_irq_demux_timer3(unsigned int irq, struct irq_desc *desc) +{ + s3c_irq_demux_timer(irq, IRQ_TIMER3); +} + +static void s3c_irq_demux_timer4(unsigned int irq, struct irq_desc *desc) +{ + s3c_irq_demux_timer(irq, IRQ_TIMER4); +} + +/* We assume the IRQ_TIMER0..IRQ_TIMER4 range is continuous. */ + +static void s3c_irq_timer_mask(unsigned int irq) +{ + u32 reg = __raw_readl(S3C64XX_TINT_CSTAT); + + reg &= 0x1f; /* mask out pending interrupts */ + reg &= ~(1 << (irq - IRQ_TIMER0)); + __raw_writel(reg, S3C64XX_TINT_CSTAT); +} + +static void s3c_irq_timer_unmask(unsigned int irq) +{ + u32 reg = __raw_readl(S3C64XX_TINT_CSTAT); + + reg &= 0x1f; /* mask out pending interrupts */ + reg |= 1 << (irq - IRQ_TIMER0); + __raw_writel(reg, S3C64XX_TINT_CSTAT); +} + +static void s3c_irq_timer_ack(unsigned int irq) +{ + u32 reg = __raw_readl(S3C64XX_TINT_CSTAT); + + reg &= 0x1f; + reg |= (1 << 5) << (irq - IRQ_TIMER0); + __raw_writel(reg, S3C64XX_TINT_CSTAT); +} + +static struct irq_chip s3c_irq_timer = { + .name = "s3c-timer", + .mask = s3c_irq_timer_mask, + .unmask = s3c_irq_timer_unmask, + .ack = s3c_irq_timer_ack, +}; + +struct uart_irq { + void __iomem *regs; + unsigned int base_irq; + unsigned int parent_irq; +}; + +/* Note, we make use of the fact that the parent IRQs, IRQ_UART[0..3] + * are consecutive when looking up the interrupt in the demux routines. + */ +static struct uart_irq uart_irqs[] = { + [0] = { + .regs = S3C_VA_UART0, + .base_irq = IRQ_S3CUART_BASE0, + .parent_irq = IRQ_UART0, + }, + [1] = { + .regs = S3C_VA_UART1, + .base_irq = IRQ_S3CUART_BASE1, + .parent_irq = IRQ_UART1, + }, + [2] = { + .regs = S3C_VA_UART2, + .base_irq = IRQ_S3CUART_BASE2, + .parent_irq = IRQ_UART2, + }, + [3] = { + .regs = S3C_VA_UART3, + .base_irq = IRQ_S3CUART_BASE3, + .parent_irq = IRQ_UART3, + }, +}; + +static inline void __iomem *s3c_irq_uart_base(unsigned int irq) +{ + struct uart_irq *uirq = get_irq_chip_data(irq); + return uirq->regs; +} + +static inline unsigned int s3c_irq_uart_bit(unsigned int irq) +{ + return irq & 3; +} + +/* UART interrupt registers, not worth adding to seperate include header */ +#define S3C64XX_UINTP 0x30 +#define S3C64XX_UINTSP 0x34 +#define S3C64XX_UINTM 0x38 + +static void s3c_irq_uart_mask(unsigned int irq) +{ + void __iomem *regs = s3c_irq_uart_base(irq); + unsigned int bit = s3c_irq_uart_bit(irq); + u32 reg; + + reg = __raw_readl(regs + S3C64XX_UINTM); + reg |= (1 << bit); + __raw_writel(reg, regs + S3C64XX_UINTM); +} + +static void s3c_irq_uart_maskack(unsigned int irq) +{ + void __iomem *regs = s3c_irq_uart_base(irq); + unsigned int bit = s3c_irq_uart_bit(irq); + u32 reg; + + reg = __raw_readl(regs + S3C64XX_UINTM); + reg |= (1 << bit); + __raw_writel(reg, regs + S3C64XX_UINTM); + __raw_writel(1 << bit, regs + S3C64XX_UINTP); +} + +static void s3c_irq_uart_unmask(unsigned int irq) +{ + void __iomem *regs = s3c_irq_uart_base(irq); + unsigned int bit = s3c_irq_uart_bit(irq); + u32 reg; + + reg = __raw_readl(regs + S3C64XX_UINTM); + reg &= ~(1 << bit); + __raw_writel(reg, regs + S3C64XX_UINTM); +} + +static void s3c_irq_uart_ack(unsigned int irq) +{ + void __iomem *regs = s3c_irq_uart_base(irq); + unsigned int bit = s3c_irq_uart_bit(irq); + + __raw_writel(1 << bit, regs + S3C64XX_UINTP); +} + +static void s3c_irq_demux_uart(unsigned int irq, struct irq_desc *desc) +{ + struct uart_irq *uirq = &uart_irqs[irq - IRQ_UART0]; + u32 pend = __raw_readl(uirq->regs + S3C64XX_UINTP); + int base = uirq->base_irq; + + if (pend & (1 << 0)) + generic_handle_irq(base); + if (pend & (1 << 1)) + generic_handle_irq(base + 1); + if (pend & (1 << 2)) + generic_handle_irq(base + 2); + if (pend & (1 << 3)) + generic_handle_irq(base + 3); +} + +static struct irq_chip s3c_irq_uart = { + .name = "s3c-uart", + .mask = s3c_irq_uart_mask, + .unmask = s3c_irq_uart_unmask, + .mask_ack = s3c_irq_uart_maskack, + .ack = s3c_irq_uart_ack, +}; + +static void __init s3c64xx_uart_irq(struct uart_irq *uirq) +{ + void *reg_base = uirq->regs; + unsigned int irq; + int offs; + + /* mask all interrupts at the start. */ + __raw_writel(0xf, reg_base + S3C64XX_UINTM); + + for (offs = 0; offs < 3; offs++) { + irq = uirq->base_irq + offs; + + set_irq_chip(irq, &s3c_irq_uart); + set_irq_chip_data(irq, uirq); + set_irq_handler(irq, handle_level_irq); + set_irq_flags(irq, IRQF_VALID); + } + + set_irq_chained_handler(uirq->parent_irq, s3c_irq_demux_uart); +} + +void __init s3c64xx_init_irq(u32 vic0_valid, u32 vic1_valid) +{ + int uart, irq; + + printk(KERN_DEBUG "%s: initialising interrupts\n", __func__); + + /* initialise the pair of VICs */ + vic_init(S3C_VA_VIC0, S3C_VIC0_BASE, vic0_valid); + vic_init(S3C_VA_VIC1, S3C_VIC1_BASE, vic1_valid); + + /* add the timer sub-irqs */ + + set_irq_chained_handler(IRQ_TIMER0_VIC, s3c_irq_demux_timer0); + set_irq_chained_handler(IRQ_TIMER1_VIC, s3c_irq_demux_timer1); + set_irq_chained_handler(IRQ_TIMER2_VIC, s3c_irq_demux_timer2); + set_irq_chained_handler(IRQ_TIMER3_VIC, s3c_irq_demux_timer3); + set_irq_chained_handler(IRQ_TIMER4_VIC, s3c_irq_demux_timer4); + + for (irq = IRQ_TIMER0; irq <= IRQ_TIMER4; irq++) { + set_irq_chip(irq, &s3c_irq_timer); + set_irq_handler(irq, handle_level_irq); + set_irq_flags(irq, IRQF_VALID); + } + + for (uart = 0; uart < ARRAY_SIZE(uart_irqs); uart++) + s3c64xx_uart_irq(&uart_irqs[uart]); +} + + diff --git a/arch/arm/plat-s3c64xx/s3c6400-clock.c b/arch/arm/plat-s3c64xx/s3c6400-clock.c new file mode 100644 index 00000000000..8d9a0cada66 --- /dev/null +++ b/arch/arm/plat-s3c64xx/s3c6400-clock.c @@ -0,0 +1,655 @@ +/* linux/arch/arm/plat-s3c64xx/s3c6400-clock.c + * + * Copyright 2008 Openmoko, Inc. + * Copyright 2008 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * http://armlinux.simtec.co.uk/ + * + * S3C6400 based common clock 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. +*/ + +#include <linux/init.h> +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/list.h> +#include <linux/errno.h> +#include <linux/err.h> +#include <linux/clk.h> +#include <linux/sysdev.h> +#include <linux/io.h> + +#include <mach/hardware.h> +#include <mach/map.h> + +#include <plat/cpu-freq.h> + +#include <plat/regs-clock.h> +#include <plat/clock.h> +#include <plat/cpu.h> +#include <plat/pll.h> + +/* fin_apll, fin_mpll and fin_epll are all the same clock, which we call + * ext_xtal_mux for want of an actual name from the manual. +*/ + +struct clk clk_ext_xtal_mux = { + .name = "ext_xtal", + .id = -1, +}; + +#define clk_fin_apll clk_ext_xtal_mux +#define clk_fin_mpll clk_ext_xtal_mux +#define clk_fin_epll clk_ext_xtal_mux + +#define clk_fout_mpll clk_mpll + +struct clk_sources { + unsigned int nr_sources; + struct clk **sources; +}; + +struct clksrc_clk { + struct clk clk; + unsigned int mask; + unsigned int shift; + + struct clk_sources *sources; + + unsigned int divider_shift; + void __iomem *reg_divider; +}; + +struct clk clk_fout_apll = { + .name = "fout_apll", + .id = -1, +}; + +static struct clk *clk_src_apll_list[] = { + [0] = &clk_fin_apll, + [1] = &clk_fout_apll, +}; + +static struct clk_sources clk_src_apll = { + .sources = clk_src_apll_list, + .nr_sources = ARRAY_SIZE(clk_src_apll_list), +}; + +struct clksrc_clk clk_mout_apll = { + .clk = { + .name = "mout_apll", + .id = -1, + }, + .shift = S3C6400_CLKSRC_APLL_MOUT_SHIFT, + .mask = S3C6400_CLKSRC_APLL_MOUT, + .sources = &clk_src_apll, +}; + +struct clk clk_fout_epll = { + .name = "fout_epll", + .id = -1, +}; + +static struct clk *clk_src_epll_list[] = { + [0] = &clk_fin_epll, + [1] = &clk_fout_epll, +}; + +static struct clk_sources clk_src_epll = { + .sources = clk_src_epll_list, + .nr_sources = ARRAY_SIZE(clk_src_epll_list), +}; + +struct clksrc_clk clk_mout_epll = { + .clk = { + .name = "mout_epll", + .id = -1, + }, + .shift = S3C6400_CLKSRC_EPLL_MOUT_SHIFT, + .mask = S3C6400_CLKSRC_EPLL_MOUT, + .sources = &clk_src_epll, +}; + +static struct clk *clk_src_mpll_list[] = { + [0] = &clk_fin_mpll, + [1] = &clk_fout_mpll, +}; + +static struct clk_sources clk_src_mpll = { + .sources = clk_src_mpll_list, + .nr_sources = ARRAY_SIZE(clk_src_mpll_list), +}; + +struct clksrc_clk clk_mout_mpll = { + .clk = { + .name = "mout_mpll", + .id = -1, + }, + .shift = S3C6400_CLKSRC_MPLL_MOUT_SHIFT, + .mask = S3C6400_CLKSRC_MPLL_MOUT, + .sources = &clk_src_mpll, +}; + +static unsigned long s3c64xx_clk_doutmpll_get_rate(struct clk *clk) +{ + unsigned long rate = clk_get_rate(clk->parent); + + printk(KERN_DEBUG "%s: parent is %ld\n", __func__, rate); + + if (__raw_readl(S3C_CLK_DIV0) & S3C6400_CLKDIV0_MPLL_MASK) + rate /= 2; + + return rate; +} + +struct clk clk_dout_mpll = { + .name = "dout_mpll", + .id = -1, + .parent = &clk_mout_mpll.clk, + .get_rate = s3c64xx_clk_doutmpll_get_rate, +}; + +static struct clk *clkset_spi_mmc_list[] = { + &clk_mout_epll.clk, + &clk_dout_mpll, + &clk_fin_epll, + &clk_27m, +}; + +static struct clk_sources clkset_spi_mmc = { + .sources = clkset_spi_mmc_list, + .nr_sources = ARRAY_SIZE(clkset_spi_mmc_list), +}; + +static struct clk *clkset_irda_list[] = { + &clk_mout_epll.clk, + &clk_dout_mpll, + NULL, + &clk_27m, +}; + +static struct clk_sources clkset_irda = { + .sources = clkset_irda_list, + .nr_sources = ARRAY_SIZE(clkset_irda_list), +}; + +static struct clk *clkset_uart_list[] = { + &clk_mout_epll.clk, + &clk_dout_mpll, + NULL, + NULL +}; + +static struct clk_sources clkset_uart = { + .sources = clkset_uart_list, + .nr_sources = ARRAY_SIZE(clkset_uart_list), +}; + +static struct clk *clkset_uhost_list[] = { + &clk_mout_epll.clk, + &clk_dout_mpll, + &clk_fin_epll, + &clk_48m, +}; + +static struct clk_sources clkset_uhost = { + .sources = clkset_uhost_list, + .nr_sources = ARRAY_SIZE(clkset_uhost_list), +}; + + +/* The peripheral clocks are all controlled via clocksource followed + * by an optional divider and gate stage. We currently roll this into + * one clock which hides the intermediate clock from the mux. + * + * Note, the JPEG clock can only be an even divider... + * + * The scaler and LCD clocks depend on the S3C64XX version, and also + * have a common parent divisor so are not included here. + */ + +static inline struct clksrc_clk *to_clksrc(struct clk *clk) +{ + return container_of(clk, struct clksrc_clk, clk); +} + +static unsigned long s3c64xx_getrate_clksrc(struct clk *clk) +{ + struct clksrc_clk *sclk = to_clksrc(clk); + unsigned long rate = clk_get_rate(clk->parent); + u32 clkdiv = __raw_readl(sclk->reg_divider); + + clkdiv >>= sclk->divider_shift; + clkdiv &= 0xf; + clkdiv++; + + rate /= clkdiv; + return rate; +} + +static int s3c64xx_setrate_clksrc(struct clk *clk, unsigned long rate) +{ + struct clksrc_clk *sclk = to_clksrc(clk); + void __iomem *reg = sclk->reg_divider; + unsigned int div; + u32 val; + + rate = clk_round_rate(clk, rate); + div = clk_get_rate(clk->parent) / rate; + + val = __raw_readl(reg); + val &= ~sclk->mask; + val |= (rate - 1) << sclk->shift; + __raw_writel(val, reg); + + return 0; +} + +static int s3c64xx_setparent_clksrc(struct clk *clk, struct clk *parent) +{ + struct clksrc_clk *sclk = to_clksrc(clk); + struct clk_sources *srcs = sclk->sources; + u32 clksrc = __raw_readl(S3C_CLK_SRC); + int src_nr = -1; + int ptr; + + for (ptr = 0; ptr < srcs->nr_sources; ptr++) + if (srcs->sources[ptr] == parent) { + src_nr = ptr; + break; + } + + if (src_nr >= 0) { + clksrc &= ~sclk->mask; + clksrc |= src_nr << sclk->shift; + + __raw_writel(clksrc, S3C_CLK_SRC); + return 0; + } + + return -EINVAL; +} + +static unsigned long s3c64xx_roundrate_clksrc(struct clk *clk, + unsigned long rate) +{ + unsigned long parent_rate = clk_get_rate(clk->parent); + int div; + + if (rate > parent_rate) + rate = parent_rate; + else { + div = rate / parent_rate; + + if (div == 0) + div = 1; + if (div > 16) + div = 16; + + rate = parent_rate / div; + } + + return rate; +} + +static struct clksrc_clk clk_mmc0 = { + .clk = { + .name = "mmc_bus", + .id = 0, + .ctrlbit = S3C_CLKCON_SCLK_MMC0, + .enable = s3c64xx_sclk_ctrl, + .set_parent = s3c64xx_setparent_clksrc, + .get_rate = s3c64xx_getrate_clksrc, + .set_rate = s3c64xx_setrate_clksrc, + .round_rate = s3c64xx_roundrate_clksrc, + }, + .shift = S3C6400_CLKSRC_MMC0_SHIFT, + .mask = S3C6400_CLKSRC_MMC0_MASK, + .sources = &clkset_spi_mmc, + .divider_shift = S3C6400_CLKDIV1_MMC0_SHIFT, + .reg_divider = S3C_CLK_DIV1, +}; + +static struct clksrc_clk clk_mmc1 = { + .clk = { + .name = "mmc_bus", + .id = 1, + .ctrlbit = S3C_CLKCON_SCLK_MMC1, + .enable = s3c64xx_sclk_ctrl, + .get_rate = s3c64xx_getrate_clksrc, + .set_rate = s3c64xx_setrate_clksrc, + .set_parent = s3c64xx_setparent_clksrc, + .round_rate = s3c64xx_roundrate_clksrc, + }, + .shift = S3C6400_CLKSRC_MMC1_SHIFT, + .mask = S3C6400_CLKSRC_MMC1_MASK, + .sources = &clkset_spi_mmc, + .divider_shift = S3C6400_CLKDIV1_MMC1_SHIFT, + .reg_divider = S3C_CLK_DIV1, +}; + +static struct clksrc_clk clk_mmc2 = { + .clk = { + .name = "mmc_bus", + .id = 2, + .ctrlbit = S3C_CLKCON_SCLK_MMC2, + .enable = s3c64xx_sclk_ctrl, + .get_rate = s3c64xx_getrate_clksrc, + .set_rate = s3c64xx_setrate_clksrc, + .set_parent = s3c64xx_setparent_clksrc, + .round_rate = s3c64xx_roundrate_clksrc, + }, + .shift = S3C6400_CLKSRC_MMC2_SHIFT, + .mask = S3C6400_CLKSRC_MMC2_MASK, + .sources = &clkset_spi_mmc, + .divider_shift = S3C6400_CLKDIV1_MMC2_SHIFT, + .reg_divider = S3C_CLK_DIV1, +}; + +static struct clksrc_clk clk_usbhost = { + .clk = { + .name = "usb-host-bus", + .id = -1, + .ctrlbit = S3C_CLKCON_SCLK_UHOST, + .enable = s3c64xx_sclk_ctrl, + .set_parent = s3c64xx_setparent_clksrc, + .get_rate = s3c64xx_getrate_clksrc, + .set_rate = s3c64xx_setrate_clksrc, + .round_rate = s3c64xx_roundrate_clksrc, + }, + .shift = S3C6400_CLKSRC_UHOST_SHIFT, + .mask = S3C6400_CLKSRC_UHOST_MASK, + .sources = &clkset_uhost, + .divider_shift = S3C6400_CLKDIV1_UHOST_SHIFT, + .reg_divider = S3C_CLK_DIV1, +}; + +static struct clksrc_clk clk_uart_uclk1 = { + .clk = { + .name = "uclk1", + .id = -1, + .ctrlbit = S3C_CLKCON_SCLK_UART, + .enable = s3c64xx_sclk_ctrl, + .set_parent = s3c64xx_setparent_clksrc, + .get_rate = s3c64xx_getrate_clksrc, + .set_rate = s3c64xx_setrate_clksrc, + .round_rate = s3c64xx_roundrate_clksrc, + }, + .shift = S3C6400_CLKSRC_UART_SHIFT, + .mask = S3C6400_CLKSRC_UART_MASK, + .sources = &clkset_uart, + .divider_shift = S3C6400_CLKDIV2_UART_SHIFT, + .reg_divider = S3C_CLK_DIV2, +}; + +/* Where does UCLK0 come from? */ + +static struct clksrc_clk clk_spi0 = { + .clk = { + .name = "spi-bus", + .id = 0, + .ctrlbit = S3C_CLKCON_SCLK_SPI0, + .enable = s3c64xx_sclk_ctrl, + .set_parent = s3c64xx_setparent_clksrc, + .get_rate = s3c64xx_getrate_clksrc, + .set_rate = s3c64xx_setrate_clksrc, + .round_rate = s3c64xx_roundrate_clksrc, + }, + .shift = S3C6400_CLKSRC_SPI0_SHIFT, + .mask = S3C6400_CLKSRC_SPI0_MASK, + .sources = &clkset_spi_mmc, + .divider_shift = S3C6400_CLKDIV2_SPI0_SHIFT, + .reg_divider = S3C_CLK_DIV2, +}; + +static struct clksrc_clk clk_spi1 = { + .clk = { + .name = "spi-bus", + .id = 1, + .ctrlbit = S3C_CLKCON_SCLK_SPI1, + .enable = s3c64xx_sclk_ctrl, + .set_parent = s3c64xx_setparent_clksrc, + .get_rate = s3c64xx_getrate_clksrc, + .set_rate = s3c64xx_setrate_clksrc, + .round_rate = s3c64xx_roundrate_clksrc, + }, + .shift = S3C6400_CLKSRC_SPI1_SHIFT, + .mask = S3C6400_CLKSRC_SPI1_MASK, + .sources = &clkset_spi_mmc, + .divider_shift = S3C6400_CLKDIV2_SPI1_SHIFT, + .reg_divider = S3C_CLK_DIV2, +}; + +static struct clk clk_iis_cd0 = { + .name = "iis_cdclk0", + .id = -1, +}; + +static struct clk clk_iis_cd1 = { + .name = "iis_cdclk1", + .id = -1, +}; + +static struct clk clk_pcm_cd = { + .name = "pcm_cdclk", + .id = -1, +}; + +static struct clk *clkset_audio0_list[] = { + [0] = &clk_mout_epll.clk, + [1] = &clk_dout_mpll, + [2] = &clk_fin_epll, + [3] = &clk_iis_cd0, + [4] = &clk_pcm_cd, +}; + +static struct clk_sources clkset_audio0 = { + .sources = clkset_audio0_list, + .nr_sources = ARRAY_SIZE(clkset_audio0_list), +}; + +static struct clksrc_clk clk_audio0 = { + .clk = { + .name = "audio-bus", + .id = 0, + .ctrlbit = S3C_CLKCON_SCLK_AUDIO0, + .enable = s3c64xx_sclk_ctrl, + .set_parent = s3c64xx_setparent_clksrc, + .get_rate = s3c64xx_getrate_clksrc, + .set_rate = s3c64xx_setrate_clksrc, + .round_rate = s3c64xx_roundrate_clksrc, + }, + .shift = S3C6400_CLKSRC_AUDIO0_SHIFT, + .mask = S3C6400_CLKSRC_AUDIO0_MASK, + .sources = &clkset_audio0, + .divider_shift = S3C6400_CLKDIV2_AUDIO0_SHIFT, + .reg_divider = S3C_CLK_DIV2, +}; + +static struct clk *clkset_audio1_list[] = { + [0] = &clk_mout_epll.clk, + [1] = &clk_dout_mpll, + [2] = &clk_fin_epll, + [3] = &clk_iis_cd1, + [4] = &clk_pcm_cd, +}; + +static struct clk_sources clkset_audio1 = { + .sources = clkset_audio1_list, + .nr_sources = ARRAY_SIZE(clkset_audio1_list), +}; + +static struct clksrc_clk clk_audio1 = { + .clk = { + .name = "audio-bus", + .id = 1, + .ctrlbit = S3C_CLKCON_SCLK_AUDIO1, + .enable = s3c64xx_sclk_ctrl, + .set_parent = s3c64xx_setparent_clksrc, + .get_rate = s3c64xx_getrate_clksrc, + .set_rate = s3c64xx_setrate_clksrc, + .round_rate = s3c64xx_roundrate_clksrc, + }, + .shift = S3C6400_CLKSRC_AUDIO1_SHIFT, + .mask = S3C6400_CLKSRC_AUDIO1_MASK, + .sources = &clkset_audio1, + .divider_shift = S3C6400_CLKDIV2_AUDIO1_SHIFT, + .reg_divider = S3C_CLK_DIV2, +}; + +static struct clksrc_clk clk_irda = { + .clk = { + .name = "irda-bus", + .id = 0, + .ctrlbit = S3C_CLKCON_SCLK_IRDA, + .enable = s3c64xx_sclk_ctrl, + .set_parent = s3c64xx_setparent_clksrc, + .get_rate = s3c64xx_getrate_clksrc, + .set_rate = s3c64xx_setrate_clksrc, + .round_rate = s3c64xx_roundrate_clksrc, + }, + .shift = S3C6400_CLKSRC_IRDA_SHIFT, + .mask = S3C6400_CLKSRC_IRDA_MASK, + .sources = &clkset_irda, + .divider_shift = S3C6400_CLKDIV2_IRDA_SHIFT, + .reg_divider = S3C_CLK_DIV2, +}; + +/* Clock initialisation code */ + +static struct clksrc_clk *init_parents[] = { + &clk_mout_apll, + &clk_mout_epll, + &clk_mout_mpll, + &clk_mmc0, + &clk_mmc1, + &clk_mmc2, + &clk_usbhost, + &clk_uart_uclk1, + &clk_spi0, + &clk_spi1, + &clk_audio0, + &clk_audio1, + &clk_irda, +}; + +static void __init_or_cpufreq s3c6400_set_clksrc(struct clksrc_clk *clk) +{ + struct clk_sources *srcs = clk->sources; + u32 clksrc = __raw_readl(S3C_CLK_SRC); + + clksrc &= clk->mask; + clksrc >>= clk->shift; + + if (clksrc > srcs->nr_sources || !srcs->sources[clksrc]) { + printk(KERN_ERR "%s: bad source %d\n", + clk->clk.name, clksrc); + return; + } + + clk->clk.parent = srcs->sources[clksrc]; + + printk(KERN_INFO "%s: source is %s (%d), rate is %ld\n", + clk->clk.name, clk->clk.parent->name, clksrc, + clk_get_rate(&clk->clk)); +} + +#define GET_DIV(clk, field) ((((clk) & field##_MASK) >> field##_SHIFT) + 1) + +void __init_or_cpufreq s3c6400_setup_clocks(void) +{ + struct clk *xtal_clk; + unsigned long xtal; + unsigned long fclk; + unsigned long hclk; + unsigned long hclk2; + unsigned long pclk; + unsigned long epll; + unsigned long apll; + unsigned long mpll; + unsigned int ptr; + u32 clkdiv0; + + printk(KERN_DEBUG "%s: registering clocks\n", __func__); + + clkdiv0 = __raw_readl(S3C_CLK_DIV0); + printk(KERN_DEBUG "%s: clkdiv0 = %08x\n", __func__, clkdiv0); + + xtal_clk = clk_get(NULL, "xtal"); + BUG_ON(IS_ERR(xtal_clk)); + + xtal = clk_get_rate(xtal_clk); + clk_put(xtal_clk); + + printk(KERN_DEBUG "%s: xtal is %ld\n", __func__, xtal); + + epll = s3c6400_get_epll(xtal); + mpll = s3c6400_get_pll(xtal, __raw_readl(S3C_MPLL_CON)); + apll = s3c6400_get_pll(xtal, __raw_readl(S3C_APLL_CON)); + + fclk = mpll; + + printk(KERN_INFO "S3C64XX: PLL settings, A=%ld, M=%ld, E=%ld\n", + apll, mpll, epll); + + hclk2 = mpll / GET_DIV(clkdiv0, S3C6400_CLKDIV0_HCLK2); + hclk = hclk2 / GET_DIV(clkdiv0, S3C6400_CLKDIV0_HCLK); + pclk = hclk2 / GET_DIV(clkdiv0, S3C6400_CLKDIV0_PCLK); + + printk(KERN_INFO "S3C64XX: HCLK2=%ld, HCLK=%ld, PCLK=%ld\n", + hclk2, hclk, pclk); + + clk_fout_mpll.rate = mpll; + clk_fout_epll.rate = epll; + clk_fout_apll.rate = apll; + + clk_h.rate = hclk; + clk_p.rate = pclk; + clk_f.rate = fclk; + + for (ptr = 0; ptr < ARRAY_SIZE(init_parents); ptr++) + s3c6400_set_clksrc(init_parents[ptr]); +} + +static struct clk *clks[] __initdata = { + &clk_ext_xtal_mux, + &clk_iis_cd0, + &clk_iis_cd1, + &clk_pcm_cd, + &clk_mout_epll.clk, + &clk_fout_epll, + &clk_mout_mpll.clk, + &clk_dout_mpll, + &clk_mmc0.clk, + &clk_mmc1.clk, + &clk_mmc2.clk, + &clk_usbhost.clk, + &clk_uart_uclk1.clk, + &clk_spi0.clk, + &clk_spi1.clk, + &clk_audio0.clk, + &clk_audio1.clk, + &clk_irda.clk, +}; + +void __init s3c6400_register_clocks(void) +{ + struct clk *clkp; + int ret; + int ptr; + + for (ptr = 0; ptr < ARRAY_SIZE(clks); ptr++) { + clkp = clks[ptr]; + ret = s3c24xx_register_clock(clkp); + if (ret < 0) { + printk(KERN_ERR "Failed to register clock %s (%d)\n", + clkp->name, ret); + } + } + + clk_mpll.parent = &clk_mout_mpll.clk; + clk_epll.parent = &clk_mout_epll.clk; +} diff --git a/arch/arm/plat-s3c64xx/s3c6400-init.c b/arch/arm/plat-s3c64xx/s3c6400-init.c new file mode 100644 index 00000000000..6c28f39df09 --- /dev/null +++ b/arch/arm/plat-s3c64xx/s3c6400-init.c @@ -0,0 +1,29 @@ +/* linux/arch/arm/plat-s3c64xx/s3c6400-init.c + * + * Copyright 2008 Openmoko, Inc. + * Copyright 2008 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * http://armlinux.simtec.co.uk/ + * + * S3C6400 - CPU initialisation (common with other S3C64XX chips) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/kernel.h> +#include <linux/types.h> +#include <linux/init.h> + +#include <plat/cpu.h> +#include <plat/devs.h> +#include <plat/s3c6400.h> +#include <plat/s3c6410.h> + +/* uart registration process */ + +void __init s3c6400_common_init_uarts(struct s3c2410_uartcfg *cfg, int no) +{ + s3c24xx_init_uartdevs("s3c6400-uart", s3c64xx_uart_resources, cfg, no); +} diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 579d63a81aa..e4ae499e587 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -447,7 +447,7 @@ config SERIAL_CLPS711X_CONSOLE config SERIAL_SAMSUNG tristate "Samsung SoC serial support" - depends on ARM && PLAT_S3C24XX + depends on ARM && PLAT_S3C select SERIAL_CORE help Support for the on-chip UARTs on the Samsung S3C24XX series CPUs, @@ -508,7 +508,20 @@ config SERIAL_S3C2440 help Serial port support for the Samsung S3C2440 and S3C2442 SoC +config SERIAL_S3C24A0 + tristate "Samsung S3C24A0 Serial port support" + depends on SERIAL_SAMSUNG && CPU_S3C24A0 + default y if CPU_S3C24A0 + help + Serial port support for the Samsung S3C24A0 SoC +config SERIAL_S3C6400 + tristate "Samsung S3C6400/S3C6410 Serial port support" + depends on SERIAL_SAMSUNG && (CPU_S3C600 || CPU_S3C6410) + default y + help + Serial port support for the Samsung S3C6400 and S3C6410 + SoCs config SERIAL_DZ bool "DECstation DZ serial driver" diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile index 0c17c8ddb19..dfe775ac45b 100644 --- a/drivers/serial/Makefile +++ b/drivers/serial/Makefile @@ -41,6 +41,8 @@ obj-$(CONFIG_SERIAL_S3C2400) += s3c2400.o obj-$(CONFIG_SERIAL_S3C2410) += s3c2410.o obj-$(CONFIG_SERIAL_S3C2412) += s3c2412.o obj-$(CONFIG_SERIAL_S3C2440) += s3c2440.o +obj-$(CONFIG_SERIAL_S3C24A0) += s3c24a0.o +obj-$(CONFIG_SERIAL_S3C6400) += s3c6400.o obj-$(CONFIG_SERIAL_IP22_ZILOG) += ip22zilog.o obj-$(CONFIG_SERIAL_MUX) += mux.o obj-$(CONFIG_SERIAL_68328) += 68328serial.o diff --git a/drivers/serial/s3c24a0.c b/drivers/serial/s3c24a0.c new file mode 100644 index 00000000000..ebf2fd3c8f7 --- /dev/null +++ b/drivers/serial/s3c24a0.c @@ -0,0 +1,118 @@ +/* linux/drivers/serial/s3c24a0.c + * + * Driver for Samsung S3C24A0 SoC onboard UARTs. + * + * Based on drivers/serial/s3c2410.c + * + * Author: Sandeep Patil <sandeep.patil@azingo.com> + * + * Ben Dooks, Copyright (c) 2003-2005,2008 Simtec Electronics + * http://armlinux.simtec.co.uk/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#include <linux/module.h> +#include <linux/ioport.h> +#include <linux/platform_device.h> +#include <linux/init.h> +#include <linux/serial_core.h> +#include <linux/serial.h> +#include <linux/io.h> +#include <linux/irq.h> + +#include <mach/hardware.h> + +#include <plat/regs-serial.h> +#include <mach/regs-gpio.h> + +#include "samsung.h" + +static int s3c24a0_serial_setsource(struct uart_port *port, + struct s3c24xx_uart_clksrc *clk) +{ + unsigned long ucon = rd_regl(port, S3C2410_UCON); + + if (strcmp(clk->name, "uclk") == 0) + ucon |= S3C2410_UCON_UCLK; + else + ucon &= ~S3C2410_UCON_UCLK; + + wr_regl(port, S3C2410_UCON, ucon); + return 0; +} + +static int s3c24a0_serial_getsource(struct uart_port *port, + struct s3c24xx_uart_clksrc *clk) +{ + unsigned long ucon = rd_regl(port, S3C2410_UCON); + + clk->divisor = 1; + clk->name = (ucon & S3C2410_UCON_UCLK) ? "uclk" : "pclk"; + + return 0; +} + +static int s3c24a0_serial_resetport(struct uart_port *port, + struct s3c2410_uartcfg *cfg) +{ + dbg("s3c24a0_serial_resetport: port=%p (%08lx), cfg=%p\n", + port, port->mapbase, cfg); + + wr_regl(port, S3C2410_UCON, cfg->ucon); + wr_regl(port, S3C2410_ULCON, cfg->ulcon); + + /* reset both fifos */ + + wr_regl(port, S3C2410_UFCON, cfg->ufcon | S3C2410_UFCON_RESETBOTH); + wr_regl(port, S3C2410_UFCON, cfg->ufcon); + + return 0; +} + +static struct s3c24xx_uart_info s3c24a0_uart_inf = { + .name = "Samsung S3C24A0 UART", + .type = PORT_S3C2410, + .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, + .reset_port = s3c24a0_serial_resetport, +}; + +static int s3c24a0_serial_probe(struct platform_device *dev) +{ + return s3c24xx_serial_probe(dev, &s3c24a0_uart_inf); +} + +static struct platform_driver s3c24a0_serial_drv = { + .probe = s3c24a0_serial_probe, + .remove = s3c24xx_serial_remove, + .driver = { + .name = "s3c24a0-uart", + .owner = THIS_MODULE, + }, +}; + +s3c24xx_console_init(&s3c24a0_serial_drv, &s3c24a0_uart_inf); + +static int __init s3c24a0_serial_init(void) +{ + return s3c24xx_serial_init(&s3c24a0_serial_drv, &s3c24a0_uart_inf); +} + +static void __exit s3c24a0_serial_exit(void) +{ + platform_driver_unregister(&s3c24a0_serial_drv); +} + +module_init(s3c24a0_serial_init); +module_exit(s3c24a0_serial_exit); + diff --git a/drivers/serial/s3c6400.c b/drivers/serial/s3c6400.c new file mode 100644 index 00000000000..06936d13393 --- /dev/null +++ b/drivers/serial/s3c6400.c @@ -0,0 +1,151 @@ +/* linux/drivers/serial/s3c6400.c + * + * Driver for Samsung S3C6400 and S3C6410 SoC onboard UARTs. + * + * Copyright 2008 Openmoko, Inc. + * Copyright 2008 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * http://armlinux.simtec.co.uk/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#include <linux/module.h> +#include <linux/ioport.h> +#include <linux/io.h> +#include <linux/platform_device.h> +#include <linux/init.h> +#include <linux/serial_core.h> +#include <linux/serial.h> + +#include <asm/irq.h> +#include <mach/hardware.h> + +#include <plat/regs-serial.h> + +#include "samsung.h" + +static int s3c6400_serial_setsource(struct uart_port *port, + struct s3c24xx_uart_clksrc *clk) +{ + unsigned long ucon = rd_regl(port, S3C2410_UCON); + + if (strcmp(clk->name, "uclk0") == 0) { + ucon &= ~S3C6400_UCON_CLKMASK; + ucon |= S3C6400_UCON_UCLK0; + } else if (strcmp(clk->name, "uclk1") == 0) + ucon |= S3C6400_UCON_UCLK1; + else if (strcmp(clk->name, "pclk") == 0) { + /* See notes about transitioning from UCLK to PCLK */ + ucon &= ~S3C6400_UCON_UCLK0; + } else { + printk(KERN_ERR "unknown clock source %s\n", clk->name); + return -EINVAL; + } + + wr_regl(port, S3C2410_UCON, ucon); + return 0; +} + + +static int s3c6400_serial_getsource(struct uart_port *port, + struct s3c24xx_uart_clksrc *clk) +{ + u32 ucon = rd_regl(port, S3C2410_UCON); + + clk->divisor = 1; + + switch (ucon & S3C6400_UCON_CLKMASK) { + case S3C6400_UCON_UCLK0: + clk->name = "uclk0"; + break; + + case S3C6400_UCON_UCLK1: + clk->name = "uclk1"; + break; + + case S3C6400_UCON_PCLK: + case S3C6400_UCON_PCLK2: + clk->name = "pclk"; + break; + } + + return 0; +} + +static int s3c6400_serial_resetport(struct uart_port *port, + struct s3c2410_uartcfg *cfg) +{ + unsigned long ucon = rd_regl(port, S3C2410_UCON); + + dbg("s3c6400_serial_resetport: port=%p (%08lx), cfg=%p\n", + port, port->mapbase, cfg); + + /* ensure we don't change the clock settings... */ + + ucon &= S3C6400_UCON_CLKMASK; + + wr_regl(port, S3C2410_UCON, ucon | cfg->ucon); + wr_regl(port, S3C2410_ULCON, cfg->ulcon); + + /* reset both fifos */ + + wr_regl(port, S3C2410_UFCON, cfg->ufcon | S3C2410_UFCON_RESETBOTH); + wr_regl(port, S3C2410_UFCON, cfg->ufcon); + + return 0; +} + +static struct s3c24xx_uart_info s3c6400_uart_inf = { + .name = "Samsung S3C6400 UART", + .type = PORT_S3C6400, + .fifosize = 64, + .rx_fifomask = S3C2440_UFSTAT_RXMASK, + .rx_fifoshift = S3C2440_UFSTAT_RXSHIFT, + .rx_fifofull = S3C2440_UFSTAT_RXFULL, + .tx_fifofull = S3C2440_UFSTAT_TXFULL, + .tx_fifomask = S3C2440_UFSTAT_TXMASK, + .tx_fifoshift = S3C2440_UFSTAT_TXSHIFT, + .get_clksrc = s3c6400_serial_getsource, + .set_clksrc = s3c6400_serial_setsource, + .reset_port = s3c6400_serial_resetport, +}; + +/* device management */ + +static int s3c6400_serial_probe(struct platform_device *dev) +{ + dbg("s3c6400_serial_probe: dev=%p\n", dev); + return s3c24xx_serial_probe(dev, &s3c6400_uart_inf); +} + +static struct platform_driver s3c6400_serial_drv = { + .probe = s3c6400_serial_probe, + .remove = s3c24xx_serial_remove, + .driver = { + .name = "s3c6400-uart", + .owner = THIS_MODULE, + }, +}; + +s3c24xx_console_init(&s3c6400_serial_drv, &s3c6400_uart_inf); + +static int __init s3c6400_serial_init(void) +{ + return s3c24xx_serial_init(&s3c6400_serial_drv, &s3c6400_uart_inf); +} + +static void __exit s3c6400_serial_exit(void) +{ + platform_driver_unregister(&s3c6400_serial_drv); +} + +module_init(s3c6400_serial_init); +module_exit(s3c6400_serial_exit); + +MODULE_DESCRIPTION("Samsung S3C6400,S3C6410 SoC Serial port driver"); +MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:s3c6400-uart"); diff --git a/drivers/serial/samsung.c b/drivers/serial/samsung.c index ebeda832c8a..ba2e8685f9f 100644 --- a/drivers/serial/samsung.c +++ b/drivers/serial/samsung.c @@ -47,9 +47,9 @@ #include <asm/irq.h> #include <mach/hardware.h> +#include <mach/map.h> #include <plat/regs-serial.h> -#include <mach/regs-gpio.h> #include "samsung.h" @@ -61,17 +61,12 @@ /* we can support 3 uarts, but not always use them */ -#ifdef CONFIG_CPU_S3C2400 +#if defined(CONFIG_CPU_S3C2400) || defined(CONFIG_CPU_S3C24A0) #define NR_PORTS (2) #else #define NR_PORTS (3) #endif -/* port irq numbers */ - -#define TX_IRQ(port) ((port)->irq + 1) -#define RX_IRQ(port) ((port)->irq) - /* macros to change one thing to another */ #define tx_enabled(port) ((port)->unused[0]) @@ -137,8 +132,10 @@ static void s3c24xx_serial_rx_disable(struct uart_port *port) static void s3c24xx_serial_stop_tx(struct uart_port *port) { + struct s3c24xx_uart_port *ourport = to_ourport(port); + if (tx_enabled(port)) { - disable_irq(TX_IRQ(port)); + disable_irq(ourport->tx_irq); tx_enabled(port) = 0; if (port->flags & UPF_CONS_FLOW) s3c24xx_serial_rx_enable(port); @@ -147,11 +144,13 @@ static void s3c24xx_serial_stop_tx(struct uart_port *port) static void s3c24xx_serial_start_tx(struct uart_port *port) { + struct s3c24xx_uart_port *ourport = to_ourport(port); + if (!tx_enabled(port)) { if (port->flags & UPF_CONS_FLOW) s3c24xx_serial_rx_disable(port); - enable_irq(TX_IRQ(port)); + enable_irq(ourport->tx_irq); tx_enabled(port) = 1; } } @@ -159,9 +158,11 @@ static void s3c24xx_serial_start_tx(struct uart_port *port) static void s3c24xx_serial_stop_rx(struct uart_port *port) { + struct s3c24xx_uart_port *ourport = to_ourport(port); + if (rx_enabled(port)) { dbg("s3c24xx_serial_stop_rx: port=%p\n", port); - disable_irq(RX_IRQ(port)); + disable_irq(ourport->rx_irq); rx_enabled(port) = 0; } } @@ -385,13 +386,13 @@ 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); + free_irq(ourport->tx_irq, ourport); tx_enabled(port) = 0; ourport->tx_claimed = 0; } if (ourport->rx_claimed) { - free_irq(RX_IRQ(port), ourport); + free_irq(ourport->rx_irq, ourport); ourport->rx_claimed = 0; rx_enabled(port) = 0; } @@ -408,12 +409,11 @@ static int s3c24xx_serial_startup(struct uart_port *port) rx_enabled(port) = 1; - ret = request_irq(RX_IRQ(port), - s3c24xx_serial_rx_chars, 0, + ret = request_irq(ourport->rx_irq, s3c24xx_serial_rx_chars, 0, s3c24xx_serial_portname(port), ourport); if (ret != 0) { - printk(KERN_ERR "cannot get irq %d\n", RX_IRQ(port)); + printk(KERN_ERR "cannot get irq %d\n", ourport->rx_irq); return ret; } @@ -423,12 +423,11 @@ static int s3c24xx_serial_startup(struct uart_port *port) tx_enabled(port) = 1; - ret = request_irq(TX_IRQ(port), - s3c24xx_serial_tx_chars, 0, + ret = request_irq(ourport->tx_irq, s3c24xx_serial_tx_chars, 0, s3c24xx_serial_portname(port), ourport); if (ret) { - printk(KERN_ERR "cannot get irq %d\n", TX_IRQ(port)); + printk(KERN_ERR "cannot get irq %d\n", ourport->tx_irq); goto err; } @@ -756,6 +755,8 @@ static const char *s3c24xx_serial_type(struct uart_port *port) return "S3C2440"; case PORT_S3C2412: return "S3C2412"; + case PORT_S3C6400: + return "S3C6400/10"; default: return NULL; } @@ -1034,18 +1035,26 @@ static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport, dbg("resource %p (%lx..%lx)\n", res, res->start, res->end); - port->mapbase = res->start; - port->membase = S3C24XX_VA_UART + (res->start - S3C24XX_PA_UART); + port->mapbase = res->start; + port->membase = S3C_VA_UART + res->start - (S3C_PA_UART & 0xfff00000); ret = platform_get_irq(platdev, 0); if (ret < 0) port->irq = 0; - else + else { port->irq = ret; + ourport->rx_irq = ret; + ourport->tx_irq = ret + 1; + } + + ret = platform_get_irq(platdev, 1); + if (ret > 0) + ourport->tx_irq = ret; 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); + dbg("port: map=%08x, mem=%08x, irq=%d (%d,%d), clock=%ld\n", + port->mapbase, port->membase, port->irq, + ourport->rx_irq, ourport->tx_irq, port->uartclk); /* reset the fifos (and setup the uart) */ s3c24xx_serial_resetport(port, cfg); diff --git a/drivers/serial/samsung.h b/drivers/serial/samsung.h index be263423205..571d6b90d20 100644 --- a/drivers/serial/samsung.h +++ b/drivers/serial/samsung.h @@ -36,6 +36,9 @@ struct s3c24xx_uart_port { unsigned int pm_level; unsigned long baudclk_rate; + unsigned int rx_irq; + unsigned int tx_irq; + struct s3c24xx_uart_info *info; struct s3c24xx_uart_clksrc *clksrc; struct clk *clk; diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index 4e4f1277f3b..feb3b939ec4 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h @@ -158,6 +158,8 @@ /* SH-SCI */ #define PORT_SCIFA 83 +#define PORT_S3C6400 84 + #ifdef __KERNEL__ #include <linux/compiler.h> |