Commit 6e1c6419 authored by Linus Torvalds's avatar Linus Torvalds

Merge bk://bk.arm.linux.org.uk/linux-2.6-rmk

into ppc970.osdl.org:/home/torvalds/v2.6/linux
parents a6a9e076 010eeeac
......@@ -15,7 +15,7 @@ Configuration
-------------
To set the default configuration, use `make bast_defconfig` which
supports the commonly used features of this board
supports the commonly used features of this board.
Support
......@@ -23,15 +23,23 @@ Support
Official support information can be found on the Simtec Electronics
website, at the product page http://www.simtec.co.uk/products/EB2410ITX/
and http://www.simtec.co.uk/products/EB2410ITX/resources.html
Useful links:
- Resources Page http://www.simtec.co.uk/products/EB2410ITX/resources.html
- Board FAQ at http://www.simtec.co.uk/products/EB2410ITX/faq.html
- Bootloader info http://www.simtec.co.uk/products/SWABLE/resources.html
and FAQ http://www.simtec.co.uk/products/SWABLE/faq.html
MTD
---
The NAND and NOR onboard are currently supported in the linux-mtd cvs,
and are awaiting merge in the mainline. see the linux-mtd project at
http://www.linux-mtd.infradead.org/ for more information.
The NAND and NOR support has been merged from the linux-mtd project.
Any prolbems, see http://www.linux-mtd.infradead.org/ for more
information or up-to-date versions of linux-mtd.
IDE
......@@ -41,4 +49,10 @@ IDE
changing speed of devices, PIO Mode 4 capable drives should be used.
Maintainers
-----------
This board is maintained by Simtec Electronics.
(c) 2004 Ben Dooks, Simtec Electronics
......@@ -48,9 +48,9 @@ Machines
NAND
----
The current kernels do not have direct support for the NAND
controller, the latest linux-mtd CVS has support for this.
See http://www.linux-mtd.infradead.org/
The current kernels now have support for the s3c2410 NAND
controller. If there are any problems the latest linux-mtd
CVS can be found from http://www.linux-mtd.infradead.org/
Serial
......@@ -84,12 +84,21 @@ Clock Management
Port Contributors
-----------------
Ben Dooks
Ben Dooks (BJD)
Vincent Sanders
Herbert Potzl
Arnaud Patard
Arnaud Patard (RTP)
Roc Wu
Klaus Fetscher
Dimitry Andric
Document Changes
----------------
05 Sep 2004 - BJD - Added Document Changes section
05 Sep 2004 - BJD - Added Klaus Fetscher to list of contributors
25 Oct 2004 - BJD - Added Dimitry Andric to list of contributors
25 Oct 2004 - BJD - Updated the MTD from the 2.6.9 merge
Document Author
---------------
......
S3C24XX Suspend Support
=======================
Introduction
------------
The S3C2410 supports a low-power suspend mode, where the SDRAM is kept
in Self-Refresh mode, and all but the esential peripheral blocks are
powered down. For more information on how this works, please look
at the S3C2410 datasheets from Samsung.
Requirements
------------
1) A bootloader that can support the necessary resume operation
2) Support for at least 1 source for resume
3) CONFIG_PM enabled in the kernel
4) Any peripherals that are going to be powered down at the same
time require suspend/resume support.
Resuming
--------
The S3C2410 user manual defines the process of sending the CPU to
sleep and how it resumes. The default behaviour of the Linux code
is to set the GSTATUS3 register to the physical address of the
code to resume Linux operation.
GSTATUS4 is currently left alone by the sleep code, and is free to
use for any other purposes.
Machine Support
---------------
The machine specific functions must call the s3c2410_pm_init() function
to say that it's bootloader is capable of resuming. This can be as
simple as adding the following to the file:
late_initcall(s3c2410_pm_init);
A board can do its own setup before calling s3c2410_pm_init, if it
needs to setup anything else for power management support.
There is currently no support for over-riding the default method of
saving the resume address, if your board requires it, then contact
the maintainer and discuss what is required.
Configuration
-------------
The S3C2410 specific configuration in `System Type` defines various
aspects of how the S3C2410 suspend and resume support is configured
`S3C2410 PM Suspend debug`
This option prints messages to the serial console before and after
the actual suspend, giving detailed information on what is
happening
`S3C2410 PM Suspend Memory CRC`
Allows the entire memory to be checksummed before and after the
suspend to see if there has been any corruption of the contents.
This support requires the CRC32 function to be enabled.
`S3C2410 PM Suspend CRC Chunksize (KiB)`
Defines the size of memory each CRC chunk covers. A smaller value
will mean that the CRC data block will take more memory, but will
identify any faults with better precision
Document Author
---------------
Ben Dooks, (c) 2004 Simtec Electronics
......@@ -104,12 +104,15 @@ config DEBUG_S3C2410_PORT
before it is used.
config DEBUG_S3C2410_UART
depends on DEBUG_LL && ARCH_S3C2410
int "S3C2410 UART to use for low-level debug"
depends on ARCH_S3C2410
int "S3C2410 UART to use for low-level messages and debug"
default "0"
help
Choice for UART for kernel low-level using S3C2410 UARTS,
should be between zero and two. The port must have been
initalised by the boot-loader before use.
This will affect the port that the uncompressor code uses
to send debug information to.
endmenu
......@@ -117,6 +117,15 @@
.macro writeb, rb
str \rb, [r3, #0]
.endm
#elif defined(CONFIG_ARCH_S3C2410)
#include <config/debug/s3c2410/port.h>
.macro loadsp, rb
mov \rb, #0x50000000
add \rb, \rb, #0x4000 * CONFIG_DEBUG_S3C2410_UART
.endm
.macro writeb, rb
strb \rb, [r3, #0x20]
.endm
#else
#error no serial architecture defined
#endif
......
#
# Automatically generated make config: don't edit
# Linux kernel version: 2.6.10-rc1-bk2
# Wed Oct 27 11:31:14 2004
#
CONFIG_ARM=y
CONFIG_MMU=y
CONFIG_UID16=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
CONFIG_GENERIC_IOMAP=y
#
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
# CONFIG_CLEAN_COMPILE is not set
CONFIG_STANDALONE=y
CONFIG_BROKEN=y
CONFIG_BROKEN_ON_SMP=y
#
# General setup
#
CONFIG_LOCALVERSION=""
CONFIG_SWAP=y
CONFIG_SYSVIPC=y
# CONFIG_POSIX_MQUEUE is not set
# CONFIG_BSD_PROCESS_ACCT is not set
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
CONFIG_LOG_BUF_SHIFT=17
CONFIG_LOG_BUF_SHIFT=16
# CONFIG_HOTPLUG is not set
CONFIG_KOBJECT_UEVENT=y
# CONFIG_IKCONFIG is not set
# CONFIG_EMBEDDED is not set
CONFIG_KALLSYMS=y
......@@ -33,11 +37,9 @@ CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_EXTRA_PASS is not set
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_IOSCHED_NOOP=y
CONFIG_IOSCHED_AS=y
CONFIG_IOSCHED_DEADLINE=y
CONFIG_IOSCHED_CFQ=y
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
CONFIG_SHMEM=y
# CONFIG_TINY_SHMEM is not set
#
# Loadable module support
......@@ -46,6 +48,7 @@ CONFIG_MODULES=y
# CONFIG_MODULE_UNLOAD is not set
CONFIG_OBSOLETE_MODPARM=y
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
CONFIG_KMOD=y
#
......@@ -60,6 +63,7 @@ CONFIG_KMOD=y
# CONFIG_ARCH_INTEGRATOR is not set
# CONFIG_ARCH_IOP3XX is not set
# CONFIG_ARCH_IXP4XX is not set
# CONFIG_ARCH_IXP2000 is not set
# CONFIG_ARCH_L7200 is not set
# CONFIG_ARCH_PXA is not set
# CONFIG_ARCH_RPC is not set
......@@ -69,14 +73,29 @@ CONFIG_ARCH_S3C2410=y
# CONFIG_ARCH_LH7A40X is not set
# CONFIG_ARCH_OMAP is not set
# CONFIG_ARCH_VERSATILE_PB is not set
# CONFIG_ARCH_IMX is not set
# CONFIG_ARCH_H720X is not set
#
# S3C2410 Implementations
# S3C24XX Implementations
#
CONFIG_ARCH_BAST=y
# CONFIG_ARCH_H1940 is not set
# CONFIG_ARCH_SMDK2410 is not set
CONFIG_ARCH_H1940=y
CONFIG_ARCH_SMDK2410=y
CONFIG_MACH_VR1000=y
CONFIG_CPU_S3C2410=y
#
# S3C2410 Setup
#
CONFIG_S3C2410_DMA=y
# CONFIG_S3C2410_DMA_DEBUG is not set
# CONFIG_S3C2410_PM_DEBUG is not set
# CONFIG_S3C2410_PM_CHECK is not set
#
# h720x Implementations
#
#
# Processor Type
......@@ -108,9 +127,8 @@ CONFIG_ZBOOT_ROM_BSS=0x0
# At least one math emulation must be selected
#
CONFIG_FPE_NWFPE=y
CONFIG_FPE_NWFPE_XP=y
# CONFIG_FPE_NWFPE_XP is not set
# CONFIG_FPE_FASTFPE is not set
# CONFIG_VFP is not set
CONFIG_BINFMT_ELF=y
CONFIG_BINFMT_AOUT=y
# CONFIG_BINFMT_MISC is not set
......@@ -118,13 +136,13 @@ CONFIG_BINFMT_AOUT=y
#
# Generic Driver Options
#
CONFIG_STANDALONE=y
CONFIG_PREVENT_FIRMWARE_BUILD=y
# CONFIG_DEBUG_DRIVER is not set
# CONFIG_PM is not set
CONFIG_PM=y
# CONFIG_PREEMPT is not set
CONFIG_APM=y
# CONFIG_ARTHUR is not set
CONFIG_S3C2410_DMA=y
# CONFIG_S3C2410_DMA_DEBUG is not set
CONFIG_CMDLINE="root=/dev/hda1 ro init=/bin/bash console=ttySAC0"
CONFIG_ALIGNMENT_TRAP=y
......@@ -164,9 +182,20 @@ CONFIG_MTD_CFI=y
# CONFIG_MTD_JEDECPROBE is not set
CONFIG_MTD_GEN_PROBE=y
# CONFIG_MTD_CFI_ADV_OPTIONS is not set
CONFIG_MTD_MAP_BANK_WIDTH_1=y
CONFIG_MTD_MAP_BANK_WIDTH_2=y
CONFIG_MTD_MAP_BANK_WIDTH_4=y
# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
CONFIG_MTD_CFI_I1=y
CONFIG_MTD_CFI_I2=y
# CONFIG_MTD_CFI_I4 is not set
# CONFIG_MTD_CFI_I8 is not set
CONFIG_MTD_CFI_INTELEXT=y
# CONFIG_MTD_CFI_AMDSTD is not set
# CONFIG_MTD_CFI_STAA is not set
CONFIG_MTD_CFI_UTIL=y
# CONFIG_MTD_RAM is not set
# CONFIG_MTD_ROM is not set
# CONFIG_MTD_ABSENT is not set
......@@ -179,11 +208,13 @@ CONFIG_MTD_CFI_INTELEXT=y
# CONFIG_MTD_PHYSMAP is not set
# CONFIG_MTD_ARM_INTEGRATOR is not set
# CONFIG_MTD_EDB7312 is not set
# CONFIG_MTD_BAST is not set
#
# Self-contained MTD device drivers
#
# CONFIG_MTD_SLRAM is not set
# CONFIG_MTD_PHRAM is not set
# CONFIG_MTD_MTDRAM is not set
# CONFIG_MTD_BLKMTD is not set
......@@ -214,6 +245,16 @@ CONFIG_BLK_DEV_NBD=m
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_SIZE=4096
CONFIG_BLK_DEV_INITRD=y
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CDROM_PKTCDVD is not set
#
# IO Schedulers
#
CONFIG_IOSCHED_NOOP=y
CONFIG_IOSCHED_AS=y
CONFIG_IOSCHED_DEADLINE=y
CONFIG_IOSCHED_CFQ=y
#
# Multi-device support (RAID and LVM)
......@@ -246,6 +287,7 @@ CONFIG_IP_PNP_BOOTP=y
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
# CONFIG_INET_TUNNEL is not set
# CONFIG_IPV6 is not set
# CONFIG_NETFILTER is not set
......@@ -338,13 +380,13 @@ CONFIG_BLK_DEV_IDECD=y
CONFIG_BLK_DEV_IDETAPE=m
CONFIG_BLK_DEV_IDEFLOPPY=m
# CONFIG_IDE_TASK_IOCTL is not set
# CONFIG_IDE_TASKFILE_IO is not set
#
# IDE chipset support/bugfixes
#
CONFIG_IDE_GENERIC=y
# CONFIG_IDE_ARM is not set
CONFIG_BLK_DEV_IDE_BAST=y
# CONFIG_BLK_DEV_IDEDMA is not set
# CONFIG_IDEDMA_AUTO is not set
# CONFIG_BLK_DEV_HD is not set
......@@ -395,16 +437,16 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
# CONFIG_GAMEPORT is not set
CONFIG_SOUND_GAMEPORT=y
CONFIG_SERIO=y
# CONFIG_SERIO_I8042 is not set
CONFIG_SERIO_SERPORT=y
# CONFIG_SERIO_CT82C710 is not set
# CONFIG_SERIO_PARKBD is not set
# CONFIG_SERIO_RAW is not set
#
# Input Device Drivers
#
CONFIG_INPUT_KEYBOARD=y
# CONFIG_KEYBOARD_ATKBD is not set
CONFIG_KEYBOARD_ATKBD=y
# CONFIG_KEYBOARD_SUNKBD is not set
# CONFIG_KEYBOARD_LKKBD is not set
# CONFIG_KEYBOARD_XTKBD is not set
......@@ -431,8 +473,6 @@ CONFIG_SERIAL_NONSTANDARD=y
# CONFIG_DIGI is not set
# CONFIG_MOXA_INTELLIO is not set
# CONFIG_MOXA_SMARTIO is not set
# CONFIG_ISI is not set
# CONFIG_SYNCLINK is not set
# CONFIG_SYNCLINKMP is not set
# CONFIG_N_HDLC is not set
# CONFIG_RISCOM8 is not set
......@@ -459,7 +499,7 @@ CONFIG_SERIAL_8250_SHARE_IRQ=y
#
CONFIG_SERIAL_S3C2410=y
CONFIG_SERIAL_S3C2410_CONSOLE=y
# CONFIG_SERIAL_BAST_SIO is not set
CONFIG_SERIAL_BAST_SIO=y
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
CONFIG_UNIX98_PTYS=y
......@@ -469,7 +509,6 @@ CONFIG_PRINTER=y
# CONFIG_LP_CONSOLE is not set
CONFIG_PPDEV=y
# CONFIG_TIPAR is not set
# CONFIG_QIC02_TAPE is not set
#
# IPMI
......@@ -492,12 +531,9 @@ CONFIG_RTC=y
# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
#
# Ftape, the floppy tape device driver
#
# CONFIG_FTAPE is not set
# CONFIG_AGP is not set
# CONFIG_DRM is not set
# CONFIG_RAW_DRIVER is not set
......@@ -512,35 +548,41 @@ CONFIG_I2C_CHARDEV=m
#
CONFIG_I2C_ALGOBIT=m
# CONFIG_I2C_ALGOPCF is not set
# CONFIG_I2C_ALGOPCA is not set
#
# I2C Hardware Bus support
#
# CONFIG_I2C_AMD756 is not set
# CONFIG_I2C_AMD8111 is not set
# CONFIG_I2C_ISA is not set
# CONFIG_I2C_PARPORT is not set
# CONFIG_I2C_PARPORT_LIGHT is not set
CONFIG_I2C_S3C2410=y
# CONFIG_SCx200_ACB is not set
# CONFIG_I2C_STUB is not set
# CONFIG_I2C_PCA_ISA is not set
#
# Hardware Sensors Chip support
#
CONFIG_I2C_SENSOR=m
# CONFIG_SENSORS_ADM1021 is not set
# CONFIG_SENSORS_ADM1025 is not set
# CONFIG_SENSORS_ADM1031 is not set
# CONFIG_SENSORS_ASB100 is not set
# CONFIG_SENSORS_DS1621 is not set
# CONFIG_SENSORS_FSCHER is not set
# CONFIG_SENSORS_GL518SM is not set
# CONFIG_SENSORS_IT87 is not set
CONFIG_SENSORS_LM75=m
# CONFIG_SENSORS_LM77 is not set
CONFIG_SENSORS_LM78=m
# CONFIG_SENSORS_LM80 is not set
# CONFIG_SENSORS_LM83 is not set
CONFIG_SENSORS_LM85=m
# CONFIG_SENSORS_LM87 is not set
# CONFIG_SENSORS_LM90 is not set
# CONFIG_SENSORS_MAX1619 is not set
# CONFIG_SENSORS_VIA686A is not set
# CONFIG_SENSORS_SMSC47M1 is not set
# CONFIG_SENSORS_W83781D is not set
# CONFIG_SENSORS_W83L785TS is not set
# CONFIG_SENSORS_W83627HF is not set
......@@ -628,9 +670,14 @@ CONFIG_RAMFS=y
# CONFIG_EFS_FS is not set
CONFIG_JFFS_FS=y
CONFIG_JFFS_FS_VERBOSE=0
# CONFIG_JFFS_PROC_FS is not set
CONFIG_JFFS2_FS=y
CONFIG_JFFS2_FS_DEBUG=0
# CONFIG_JFFS2_FS_NAND is not set
# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
CONFIG_JFFS2_ZLIB=y
CONFIG_JFFS2_RTIME=y
# CONFIG_JFFS2_RUBIN is not set
# CONFIG_CRAMFS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_HPFS_FS is not set
......@@ -651,6 +698,7 @@ CONFIG_LOCKD=y
# CONFIG_EXPORTFS is not set
CONFIG_SUNRPC=y
# CONFIG_RPCSEC_GSS_KRB5 is not set
# CONFIG_RPCSEC_GSS_SPKM3 is not set
# CONFIG_SMB_FS is not set
# CONFIG_CIFS is not set
# CONFIG_NCP_FS is not set
......@@ -661,13 +709,7 @@ CONFIG_SUNRPC=y
# Partition Types
#
CONFIG_PARTITION_ADVANCED=y
CONFIG_ACORN_PARTITION=y
CONFIG_ACORN_PARTITION_CUMANA=y
CONFIG_ACORN_PARTITION_EESOX=y
CONFIG_ACORN_PARTITION_ICS=y
CONFIG_ACORN_PARTITION_ADFS=y
CONFIG_ACORN_PARTITION_POWERTEC=y
CONFIG_ACORN_PARTITION_RISCIX=y
# CONFIG_ACORN_PARTITION is not set
# CONFIG_OSF_PARTITION is not set
# CONFIG_AMIGA_PARTITION is not set
# CONFIG_ATARI_PARTITION is not set
......@@ -736,13 +778,14 @@ CONFIG_NLS_DEFAULT="iso8859-1"
# Graphics support
#
CONFIG_FB=y
CONFIG_FB_MODE_HELPERS=y
# CONFIG_FB_TILEBLITTING is not set
# CONFIG_FB_VIRTUAL is not set
#
# Console display driver support
#
# CONFIG_VGA_CONSOLE is not set
# CONFIG_MDA_CONSOLE is not set
CONFIG_DUMMY_CONSOLE=y
# CONFIG_FRAMEBUFFER_CONSOLE is not set
......@@ -763,24 +806,34 @@ CONFIG_DUMMY_CONSOLE=y
#
# USB support
#
# CONFIG_USB is not set
CONFIG_USB_ARCH_HAS_HCD=y
# CONFIG_USB_ARCH_HAS_OHCI is not set
#
# USB Gadget Support
#
# CONFIG_USB_GADGET is not set
#
# MMC/SD Card support
#
# CONFIG_MMC is not set
#
# Kernel hacking
#
CONFIG_FRAME_POINTER=y
CONFIG_DEBUG_USER=y
CONFIG_DEBUG_INFO=y
CONFIG_DEBUG_KERNEL=y
# CONFIG_DEBUG_SLAB is not set
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_SCHEDSTATS is not set
# CONFIG_DEBUG_SLAB is not set
# CONFIG_DEBUG_SPINLOCK is not set
# CONFIG_DEBUG_WAITQ is not set
# CONFIG_DEBUG_KOBJECT is not set
# CONFIG_DEBUG_BUGVERBOSE is not set
CONFIG_DEBUG_INFO=y
CONFIG_FRAME_POINTER=y
CONFIG_DEBUG_USER=y
# CONFIG_DEBUG_WAITQ is not set
# CONFIG_DEBUG_ERRORS is not set
CONFIG_DEBUG_LL=y
# CONFIG_DEBUG_ICEDCC is not set
......@@ -790,6 +843,7 @@ CONFIG_DEBUG_S3C2410_UART=0
#
# Security options
#
# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
#
......
#
# Automatically generated make config: don't edit
# Linux kernel version: 2.6.10-rc1-bk2
# Wed Oct 27 11:30:39 2004
#
CONFIG_ARM=y
CONFIG_MMU=y
CONFIG_UID16=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
CONFIG_GENERIC_IOMAP=y
#
# Code maturity level options
......@@ -17,6 +20,7 @@ CONFIG_BROKEN_ON_SMP=y
#
# General setup
#
CONFIG_LOCALVERSION=""
CONFIG_SWAP=y
CONFIG_SYSVIPC=y
# CONFIG_POSIX_MQUEUE is not set
......@@ -25,6 +29,7 @@ CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
CONFIG_LOG_BUF_SHIFT=16
# CONFIG_HOTPLUG is not set
CONFIG_KOBJECT_UEVENT=y
# CONFIG_IKCONFIG is not set
# CONFIG_EMBEDDED is not set
CONFIG_KALLSYMS=y
......@@ -32,11 +37,9 @@ CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_EXTRA_PASS is not set
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_IOSCHED_NOOP=y
CONFIG_IOSCHED_AS=y
CONFIG_IOSCHED_DEADLINE=y
CONFIG_IOSCHED_CFQ=y
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
CONFIG_SHMEM=y
# CONFIG_TINY_SHMEM is not set
#
# Loadable module support
......@@ -45,6 +48,7 @@ CONFIG_MODULES=y
# CONFIG_MODULE_UNLOAD is not set
CONFIG_OBSOLETE_MODPARM=y
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
CONFIG_KMOD=y
#
......@@ -59,6 +63,7 @@ CONFIG_KMOD=y
# CONFIG_ARCH_INTEGRATOR is not set
# CONFIG_ARCH_IOP3XX is not set
# CONFIG_ARCH_IXP4XX is not set
# CONFIG_ARCH_IXP2000 is not set
# CONFIG_ARCH_L7200 is not set
# CONFIG_ARCH_PXA is not set
# CONFIG_ARCH_RPC is not set
......@@ -68,20 +73,29 @@ CONFIG_ARCH_S3C2410=y
# CONFIG_ARCH_LH7A40X is not set
# CONFIG_ARCH_OMAP is not set
# CONFIG_ARCH_VERSATILE_PB is not set
# CONFIG_ARCH_IMX is not set
# CONFIG_ARCH_H720X is not set
#
# S3C2410 Implementations
# S3C24XX Implementations
#
CONFIG_ARCH_BAST=y
CONFIG_ARCH_H1940=y
CONFIG_ARCH_SMDK2410=y
CONFIG_MACH_VR1000=y
CONFIG_CPU_S3C2410=y
#
# S3C2410 Setup
#
CONFIG_S3C2410_DMA=y
# CONFIG_S3C2410_DMA_DEBUG is not set
# CONFIG_S3C2410_PM_DEBUG is not set
# CONFIG_S3C2410_PM_CHECK is not set
#
# h720x Implementations
#
#
# Processor Type
......@@ -113,9 +127,8 @@ CONFIG_ZBOOT_ROM_BSS=0x0
# At least one math emulation must be selected
#
CONFIG_FPE_NWFPE=y
CONFIG_FPE_NWFPE_XP=y
# CONFIG_FPE_NWFPE_XP is not set
# CONFIG_FPE_FASTFPE is not set
# CONFIG_VFP is not set
CONFIG_BINFMT_ELF=y
CONFIG_BINFMT_AOUT=y
# CONFIG_BINFMT_MISC is not set
......@@ -126,8 +139,9 @@ CONFIG_BINFMT_AOUT=y
CONFIG_STANDALONE=y
CONFIG_PREVENT_FIRMWARE_BUILD=y
# CONFIG_DEBUG_DRIVER is not set
# CONFIG_PM is not set
CONFIG_PM=y
# CONFIG_PREEMPT is not set
CONFIG_APM=y
# CONFIG_ARTHUR is not set
CONFIG_CMDLINE="root=/dev/hda1 ro init=/bin/bash console=ttySAC0"
CONFIG_ALIGNMENT_TRAP=y
......@@ -194,6 +208,7 @@ CONFIG_MTD_CFI_UTIL=y
# CONFIG_MTD_PHYSMAP is not set
# CONFIG_MTD_ARM_INTEGRATOR is not set
# CONFIG_MTD_EDB7312 is not set
# CONFIG_MTD_BAST is not set
#
# Self-contained MTD device drivers
......@@ -230,6 +245,16 @@ CONFIG_BLK_DEV_NBD=m
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_SIZE=4096
CONFIG_BLK_DEV_INITRD=y
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CDROM_PKTCDVD is not set
#
# IO Schedulers
#
CONFIG_IOSCHED_NOOP=y
CONFIG_IOSCHED_AS=y
CONFIG_IOSCHED_DEADLINE=y
CONFIG_IOSCHED_CFQ=y
#
# Multi-device support (RAID and LVM)
......@@ -262,6 +287,7 @@ CONFIG_IP_PNP_BOOTP=y
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
# CONFIG_INET_TUNNEL is not set
# CONFIG_IPV6 is not set
# CONFIG_NETFILTER is not set
......@@ -354,13 +380,13 @@ CONFIG_BLK_DEV_IDECD=y
CONFIG_BLK_DEV_IDETAPE=m
CONFIG_BLK_DEV_IDEFLOPPY=m
# CONFIG_IDE_TASK_IOCTL is not set
# CONFIG_IDE_TASKFILE_IO is not set
#
# IDE chipset support/bugfixes
#
CONFIG_IDE_GENERIC=y
# CONFIG_IDE_ARM is not set
# CONFIG_BLK_DEV_IDE_BAST is not set
# CONFIG_BLK_DEV_IDEDMA is not set
# CONFIG_IDEDMA_AUTO is not set
# CONFIG_BLK_DEV_HD is not set
......@@ -411,10 +437,10 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
# CONFIG_GAMEPORT is not set
CONFIG_SOUND_GAMEPORT=y
CONFIG_SERIO=y
# CONFIG_SERIO_I8042 is not set
CONFIG_SERIO_SERPORT=y
# CONFIG_SERIO_CT82C710 is not set
# CONFIG_SERIO_PARKBD is not set
# CONFIG_SERIO_RAW is not set
#
# Input Device Drivers
......@@ -483,7 +509,6 @@ CONFIG_PRINTER=y
# CONFIG_LP_CONSOLE is not set
CONFIG_PPDEV=y
# CONFIG_TIPAR is not set
# CONFIG_QIC02_TAPE is not set
#
# IPMI
......@@ -509,7 +534,6 @@ CONFIG_RTC=y
#
# Ftape, the floppy tape device driver
#
# CONFIG_AGP is not set
# CONFIG_DRM is not set
# CONFIG_RAW_DRIVER is not set
......@@ -524,16 +548,18 @@ CONFIG_I2C_CHARDEV=m
#
CONFIG_I2C_ALGOBIT=m
# CONFIG_I2C_ALGOPCF is not set
# CONFIG_I2C_ALGOPCA is not set
#
# I2C Hardware Bus support
#
# CONFIG_I2C_AMD756 is not set
# CONFIG_I2C_AMD8111 is not set
# CONFIG_I2C_ISA is not set
# CONFIG_I2C_PARPORT is not set
# CONFIG_I2C_PARPORT_LIGHT is not set
CONFIG_I2C_S3C2410=y
# CONFIG_SCx200_ACB is not set
# CONFIG_I2C_STUB is not set
# CONFIG_I2C_PCA_ISA is not set
#
# Hardware Sensors Chip support
......@@ -553,8 +579,10 @@ CONFIG_SENSORS_LM78=m
# CONFIG_SENSORS_LM80 is not set
# CONFIG_SENSORS_LM83 is not set
CONFIG_SENSORS_LM85=m
# CONFIG_SENSORS_LM87 is not set
# CONFIG_SENSORS_LM90 is not set
# CONFIG_SENSORS_MAX1619 is not set
# CONFIG_SENSORS_SMSC47M1 is not set
# CONFIG_SENSORS_W83781D is not set
# CONFIG_SENSORS_W83L785TS is not set
# CONFIG_SENSORS_W83627HF is not set
......@@ -670,6 +698,7 @@ CONFIG_LOCKD=y
# CONFIG_EXPORTFS is not set
CONFIG_SUNRPC=y
# CONFIG_RPCSEC_GSS_KRB5 is not set
# CONFIG_RPCSEC_GSS_SPKM3 is not set
# CONFIG_SMB_FS is not set
# CONFIG_CIFS is not set
# CONFIG_NCP_FS is not set
......@@ -749,13 +778,14 @@ CONFIG_NLS_DEFAULT="iso8859-1"
# Graphics support
#
CONFIG_FB=y
CONFIG_FB_MODE_HELPERS=y
# CONFIG_FB_TILEBLITTING is not set
# CONFIG_FB_VIRTUAL is not set
#
# Console display driver support
#
# CONFIG_VGA_CONSOLE is not set
# CONFIG_MDA_CONSOLE is not set
CONFIG_DUMMY_CONSOLE=y
# CONFIG_FRAMEBUFFER_CONSOLE is not set
......@@ -776,24 +806,34 @@ CONFIG_DUMMY_CONSOLE=y
#
# USB support
#
# CONFIG_USB is not set
CONFIG_USB_ARCH_HAS_HCD=y
# CONFIG_USB_ARCH_HAS_OHCI is not set
#
# USB Gadget Support
#
# CONFIG_USB_GADGET is not set
#
# MMC/SD Card support
#
# CONFIG_MMC is not set
#
# Kernel hacking
#
CONFIG_FRAME_POINTER=y
CONFIG_DEBUG_USER=y
CONFIG_DEBUG_INFO=y
CONFIG_DEBUG_KERNEL=y
# CONFIG_DEBUG_SLAB is not set
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_SCHEDSTATS is not set
# CONFIG_DEBUG_SLAB is not set
# CONFIG_DEBUG_SPINLOCK is not set
# CONFIG_DEBUG_WAITQ is not set
# CONFIG_DEBUG_KOBJECT is not set
# CONFIG_DEBUG_BUGVERBOSE is not set
CONFIG_DEBUG_INFO=y
CONFIG_FRAME_POINTER=y
CONFIG_DEBUG_USER=y
# CONFIG_DEBUG_WAITQ is not set
# CONFIG_DEBUG_ERRORS is not set
CONFIG_DEBUG_LL=y
# CONFIG_DEBUG_ICEDCC is not set
......@@ -803,6 +843,7 @@ CONFIG_DEBUG_S3C2410_UART=0
#
# Security options
#
# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
#
......
......@@ -538,6 +538,9 @@
#elif defined(CONFIG_ARCH_S3C2410)
#include <asm/arch/map.h>
#include <asm/arch/regs-serial.h>
#include <asm/arch/regs-gpio.h>
#define S3C2410_UART1_OFF (0x4000)
#define SHIFT_2440TXF (14-9)
.macro addruart, rx
mrc p15, 0, \rx, c1, c0
......@@ -559,7 +562,17 @@
beq 1001f @
@ FIFO enabled...
1003:
mrc p15, 0, \rd, c1, c0
tst \rd, #1
addeq \rd, \rx, #(S3C2410_PA_GPIO - S3C2410_PA_UART)
addne \rd, \rx, #(S3C2410_VA_GPIO - S3C2410_VA_UART)
bic \rd, \rd, #0xff000
ldr \rd, [ \rd, # S3C2410_GSTATUS1 - S3C2410_GPIOREG(0) ]
and \rd, \rd, #0x00ff0000
teq \rd, #0x00440000 @ is it 2440?
ldr \rd, [ \rx, # S3C2410_UFSTAT ]
moveq \rd, \rd, lsr #SHIFT_2440TXF
tst \rd, #S3C2410_UFSTAT_TXFULL
bne 1003b
b 1002f
......@@ -580,8 +593,19 @@
beq 1001f @
@ FIFO enabled...
1003:
mrc p15, 0, \rd, c1, c0
tst \rd, #1
addeq \rd, \rx, #(S3C2410_PA_GPIO - S3C2410_PA_UART)
addne \rd, \rx, #(S3C2410_VA_GPIO - S3C2410_VA_UART)
bic \rd, \rd, #0xff000
ldr \rd, [ \rd, # S3C2410_GSTATUS1 - S3C2410_GPIOREG(0) ]
and \rd, \rd, #0x00ff0000
teq \rd, #0x00440000 @ is it 2440?
ldr \rd, [ \rx, # S3C2410_UFSTAT ]
ands \rd, \rd, #15<<S3C2410_UFSTAT_TXSHIFT
andne \rd, \rd, #S3C2410_UFSTAT_TXMASK
andeq \rd, \rd, #S3C2440_UFSTAT_TXMASK
teq \rd, #0
bne 1003b
b 1002f
......
......@@ -12,12 +12,12 @@ lib-y := backtrace.o changebit.o csumipv6.o csumpartial.o \
testclearbit.o testsetbit.o uaccess.o getuser.o \
putuser.o ashldi3.o ashrdi3.o lshrdi3.o muldi3.o \
ucmpdi2.o udivdi3.o lib1funcs.o div64.o \
io-readsb.o io-writesb.o io-writesl.o
io-readsb.o io-writesb.o io-readsl.o io-writesl.o
ifeq ($(CONFIG_CPU_32v3),y)
lib-y += io-readsw-armv3.o io-writesw-armv3.o io-readsl-armv3.o
lib-y += io-readsw-armv3.o io-writesw-armv3.o
else
lib-y += io-readsw-armv4.o io-writesw-armv4.o io-readsl-armv4.o
lib-y += io-readsw-armv4.o io-writesw-armv4.o
endif
lib-$(CONFIG_ARCH_RPC) += ecard.o io-acorn.o floppydma.o
......
/*
* linux/arch/arm/lib/io-readsl-armv4.S
*
* Copyright (C) 1995-2000 Russell King
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/linkage.h>
#include <asm/assembler.h>
/*
* Note that some reads can be aligned on half-word boundaries.
*/
ENTRY(__raw_readsl)
teq r2, #0 @ do we have to check for the zero len?
moveq pc, lr
ands ip, r1, #3
bne 2f
subs r2, r2, #4
bmi 1001f
stmfd sp!, {r4, lr}
1000: ldr r3, [r0, #0]
ldr r4, [r0, #0]
ldr ip, [r0, #0]
ldr lr, [r0, #0]
subs r2, r2, #4
stmia r1!, {r3, r4, ip, lr}
bpl 1000b
ldmfd sp!, {r4, lr}
1001: tst r2, #2
ldrne r3, [r0, #0]
ldrne ip, [r0, #0]
stmneia r1!, {r3, ip}
tst r2, #1
ldrne r3, [r0, #0]
strne r3, [r1, #0]
mov pc, lr
2: cmp ip, #2
ldr ip, [r0]
blt 4f
bgt 6f
#ifndef __ARMEB__
/* little endian code */
strh ip, [r1], #2
mov ip, ip, lsr #16
3: subs r2, r2, #1
ldrne r3, [r0]
orrne ip, ip, r3, lsl #16
strne ip, [r1], #4
movne ip, r3, lsr #16
bne 3b
strh ip, [r1], #2
mov pc, lr
4: strb ip, [r1], #1
mov ip, ip, lsr #8
strh ip, [r1], #2
mov ip, ip, lsr #16
5: subs r2, r2, #1
ldrne r3, [r0]
orrne ip, ip, r3, lsl #8
strne ip, [r1], #4
movne ip, r3, lsr #24
bne 5b
strb ip, [r1], #1
mov pc, lr
6: strb ip, [r1], #1
mov ip, ip, lsr #8
7: subs r2, r2, #1
ldrne r3, [r0]
orrne ip, ip, r3, lsl #24
strne ip, [r1], #4
movne ip, r3, lsr #8
bne 7b
strh ip, [r1], #2
mov ip, ip, lsr #16
strb ip, [r1]
mov pc, lr
#else
/* big endian code */
mov r3, ip, lsr #16
strh r3, [r1], #2
3: mov r3, ip, lsl #16
subs r2, r2, #1
ldrne ip, [r0]
orrne r3, r3, ip, lsr #16
strne r3, [r1], #4
bne 3b
strh ip, [r1], #2
mov pc, lr
4: mov r3, ip, lsr #24
strb r3, [r1], #1
mov r3, ip, lsr #8
strh r3, [r1], #2
5: mov r3, ip, lsl #24
subs r2, r2, #1
ldrne ip, [r0]
orrne r3, r3, ip, lsr #8
strne r3, [r1], #4
bne 5b
strb ip, [r1], #1
mov pc, lr
6: mov r3, ip, lsr #24
strb r3, [r1], #1
7: mov r3, ip, lsl #8
subs r2, r2, #1
ldrne ip, [r0]
orrne r3, r3, ip, lsr #24
strne r3, [r1], #4
bne 7b
mov r3, ip, lsr #8
strh r3, [r1], #2
strb ip, [r1], #1
mov pc, lr
#endif
/*
* linux/arch/arm/lib/io-readsl-armv3.S
* linux/arch/arm/lib/io-readsl.S
*
* Copyright (C) 1995-2000 Russell King
*
......@@ -9,70 +9,71 @@
*/
#include <linux/linkage.h>
#include <asm/assembler.h>
#include <asm/hardware.h>
/*
* Note that some reads can be aligned on half-word boundaries.
*/
ENTRY(__raw_readsl)
teq r2, #0 @ do we have to check for the zero len?
moveq pc, lr
ands ip, r1, #3
bne 2f
bne 3f
1: ldr r3, [r0]
str r3, [r1], #4
subs r2, r2, #1
bne 1b
subs r2, r2, #4
bmi 2f
stmfd sp!, {r4, lr}
1: ldr r3, [r0, #0]
ldr r4, [r0, #0]
ldr ip, [r0, #0]
ldr lr, [r0, #0]
subs r2, r2, #4
stmia r1!, {r3, r4, ip, lr}
bpl 1b
ldmfd sp!, {r4, lr}
2: tst r2, #2
ldrne r3, [r0, #0]
ldrne ip, [r0, #0]
stmneia r1!, {r3, ip}
tst r2, #1
ldrne r3, [r0, #0]
strne r3, [r1, #0]
mov pc, lr
2: cmp ip, #2
ldr ip, [r0]
blt 4f
3: ldr r3, [r0]
cmp ip, #2
mov ip, r3, get_byte_0
strb ip, [r1], #1
bgt 6f
mov ip, r3, get_byte_1
strb ip, [r1], #1
mov ip, ip, lsr #8
beq 5f
mov ip, r3, get_byte_2
strb ip, [r1], #1
mov ip, ip, lsr #8
3: subs r2, r2, #1
4: subs r2, r2, #1
mov ip, r3, pull #24
ldrne r3, [r0]
orrne ip, ip, r3, lsl #16
orrne ip, ip, r3, push #8
strne ip, [r1], #4
movne ip, r3, lsr #16
bne 3b
strb ip, [r1], #1
mov ip, ip, lsr #8
strb ip, [r1], #1
mov pc, lr
bne 4b
b 8f
4: strb ip, [r1], #1
mov ip, ip, lsr #8
strb ip, [r1], #1
mov ip, ip, lsr #8
strb ip, [r1], #1
mov ip, ip, lsr #8
5: subs r2, r2, #1
mov ip, r3, pull #16
ldrne r3, [r0]
orrne ip, ip, r3, lsl #8
orrne ip, ip, r3, push #16
strne ip, [r1], #4
movne ip, r3, lsr #24
bne 5b
strb ip, [r1], #1
mov pc, lr
b 7f
6: strb ip, [r1], #1
mov ip, ip, lsr #8
7: subs r2, r2, #1
6: subs r2, r2, #1
mov ip, r3, pull #8
ldrne r3, [r0]
orrne ip, ip, r3, lsl #24
orrne ip, ip, r3, push #24
strne ip, [r1], #4
movne ip, r3, lsr #8
bne 7b
strb ip, [r1], #1
mov ip, ip, lsr #8
strb ip, [r1], #1
mov ip, ip, lsr #8
strb ip, [r1], #1
mov pc, lr
bne 6b
mov r3, ip, get_byte_2
strb r3, [r1, #2]
7: mov r3, ip, get_byte_1
strb r3, [r1, #1]
8: mov r3, ip, get_byte_0
strb r3, [r1, #0]
mov pc, lr
......@@ -9,53 +9,59 @@
*/
#include <linux/linkage.h>
#include <asm/assembler.h>
#include <asm/hardware.h>
ENTRY(__raw_writesl)
teq r2, #0 @ do we have to check for the zero len?
moveq pc, lr
ands ip, r1, #3
bne 2f
bne 3f
subs r2, r2, #4
bmi 2f
stmfd sp!, {r4, lr}
1: ldmia r1!, {r3, r4, ip, lr}
subs r2, r2, #4
str r3, [r0, #0]
str r4, [r0, #0]
str ip, [r0, #0]
str lr, [r0, #0]
bpl 1b
ldmfd sp!, {r4, lr}
2: tst r2, #2
ldmneia r1!, {r3, ip}
strne r3, [r0, #0]
strne ip, [r0, #0]
tst r2, #1
ldrne r3, [r1], #4
ldrne r3, [r1, #0]
strne r3, [r0, #0]
1: subs r2, r2, #2
ldrcs r3, [r1], #4
ldrcs ip, [r1], #4
strcs r3, [r0, #0]
strcs ip, [r0, #0]
bcs 1b
mov pc, lr
2: bic r1, r1, #3
cmp ip, #2
3: bic r1, r1, #3
ldr r3, [r1], #4
bgt 4f
cmp ip, #2
blt 5f
bgt 6f
3: mov ip, r3, lsr #16
4: mov ip, r3, pull #16
ldr r3, [r1], #4
subs r2, r2, #1
orr ip, ip, r3, lsl #16
str ip, [r0, #0]
bne 3b
orr ip, ip, r3, push #16
str ip, [r0]
bne 4b
mov pc, lr
4: mov ip, r3, lsr #24
5: mov ip, r3, pull #8
ldr r3, [r1], #4
subs r2, r2, #1
orr ip, ip, r3, lsl #8
str ip, [r0, #0]
bne 4b
orr ip, ip, r3, push #24
str ip, [r0]
bne 5b
mov pc, lr
5: mov ip, r3, lsr #8
6: mov ip, r3, pull #24
ldr r3, [r1], #4
subs r2, r2, #1
orr ip, ip, r3, lsl #24
str ip, [r0, #0]
bne 5b
orr ip, ip, r3, push #8
str ip, [r0]
bne 6b
mov pc, lr
if ARCH_OMAP
menu "TI OMAP Implementations"
comment "OMAP Core Type"
config ARCH_OMAP730
depends on ARCH_OMAP
bool "OMAP730 Based System"
select CPU_ARM926T
select ARCH_OMAP_OTG
config ARCH_OMAP1510
depends on ARCH_OMAP
default y
bool "OMAP1510 Based System"
select CPU_ARM925T
select CPU_DCACHE_WRITETHROUGH
config ARCH_OMAP1610
bool "OMAP1610 Based System"
select CPU_ARM926T
config ARCH_OMAP16XX
depends on ARCH_OMAP
bool "OMAP16XX Based System"
select ARCH_OMAP_OTG
config ARCH_OMAP5912
bool "OMAP5912 Based System"
select CPU_ARM926T
config ARCH_OMAP_OTG
bool
comment "OMAP Board Type"
config MACH_OMAP_INNOVATOR
bool "TI Innovator"
default y
depends on ARCH_OMAP1510 || ARCH_OMAP1610
depends on ARCH_OMAP1510 || ARCH_OMAP16XX
help
TI OMAP 1510 or 1610 Innovator board support. Say Y here if you
have such a board.
config MACH_OMAP_H2
bool "TI H2 Support"
depends on ARCH_OMAP1610
select MACH_OMAP_INNOVATOR
depends on ARCH_OMAP16XX
help
TI OMAP 1610 H2 board support. Say Y here if you have such
TI OMAP 1610/1611B H2 board support. Say Y here if you have such
a board.
config MACH_OMAP_H3
bool "TI H3 Support"
depends on ARCH_OMAP1610
depends on ARCH_OMAP16XX
help
TI OMAP 1610 H3 board support. Say Y here if you have such
TI OMAP 1710 H3 board support. Say Y here if you have such
a board.
config MACH_OMAP_H4
bool "TI H4 Support"
depends on ARCH_OMAP1610
depends on ARCH_OMAP16XX
help
TI OMAP 1610 H4 board support. Say Y here if you have such
a board.
config MACH_OMAP_OSK
bool "TI OSK Support"
depends on ARCH_OMAP5912
depends on ARCH_OMAP16XX
help
TI OMAP 5912 OSK (OMAP Starter Kit) board support. Say Y here
if you have such a board.
......@@ -64,19 +61,16 @@ config MACH_OMAP_OSK
config MACH_OMAP_PERSEUS2
bool "TI Perseus2"
depends on ARCH_OMAP730
select LEDS
select LEDS_TIMER
select LEDS_CPU
help
Support for TI OMAP 730 Perseus2 board. Say Y here if you have such
a board.
config MACH_OMAP_GENERIC
bool "Generic OMAP board"
depends on ARCH_OMAP1510 || ARCH_OMAP1610
depends on ARCH_OMAP1510 || ARCH_OMAP16XX
help
Support for generic OMAP-1510 or 1610 board with no
FPGA. Can be used as template for porting Linux to
Support for generic OMAP-1510, 1610 or 1710 board with
no FPGA. Can be used as template for porting Linux to
custom OMAP boards. Say Y here if you have a custom
board.
......@@ -84,6 +78,7 @@ comment "OMAP Feature Selections"
#config OMAP_BOOT_TAG
# bool "OMAP bootloader information passing"
# depends on ARCH_OMAP
# default n
# help
# Say Y, if you have a bootloader which passes information
......@@ -91,6 +86,7 @@ comment "OMAP Feature Selections"
config OMAP_MUX
bool "OMAP multiplexing support"
depends on ARCH_OMAP
default y
help
Pin multiplexing support for OMAP boards. If your bootloader
......@@ -106,8 +102,18 @@ config OMAP_MUX_DEBUG
This is useful if you want to find out the correct values of the
multiplexing registers.
config OMAP_MUX_WARNINGS
bool "Warn about pins the bootloader didn't set up"
depends on OMAP_MUX
default y
help
Choose Y here to warn whenever driver initialization logic needs
to change the pin multiplexing setup. When there are no warnings
printed, it's safe to deselect OMAP_MUX for your product.
choice
prompt "Low-level debug console UART"
depends on ARCH_OMAP
default OMAP_LL_DEBUG_UART1
config OMAP_LL_DEBUG_UART1
......@@ -129,7 +135,7 @@ config OMAP_ARM_195MHZ
config OMAP_ARM_192MHZ
bool "OMAP ARM 192 MHz CPU"
depends on ARCH_OMAP1610 || ARCH_OMAP5912
depends on ARCH_OMAP16XX
help
Enable 192MHz clock for OMAP CPU. If unsure, say N.
......@@ -141,29 +147,27 @@ config OMAP_ARM_182MHZ
config OMAP_ARM_168MHZ
bool "OMAP ARM 168 MHz CPU"
depends on ARCH_OMAP1510 || ARCH_OMAP1610 || ARCH_OMAP730 || ARCH_OMAP5912
depends on ARCH_OMAP1510 || ARCH_OMAP16XX || ARCH_OMAP730
help
Enable 168MHz clock for OMAP CPU. If unsure, say N.
config OMAP_ARM_120MHZ
bool "OMAP ARM 120 MHz CPU"
depends on ARCH_OMAP1510 || ARCH_OMAP1610 || ARCH_OMAP730
depends on ARCH_OMAP1510 || ARCH_OMAP16XX || ARCH_OMAP730
help
Enable 120MHz clock for OMAP CPU. If unsure, say N.
config OMAP_ARM_60MHZ
bool "OMAP ARM 60 MHz CPU"
depends on ARCH_OMAP1510 || ARCH_OMAP1610 || ARCH_OMAP730
depends on ARCH_OMAP1510 || ARCH_OMAP16XX || ARCH_OMAP730
default y
help
Enable 60MHz clock for OMAP CPU. If unsure, say Y.
config OMAP_ARM_30MHZ
bool "OMAP ARM 30 MHz CPU"
depends on ARCH_OMAP1510 || ARCH_OMAP1610 || ARCH_OMAP730
depends on ARCH_OMAP1510 || ARCH_OMAP16XX || ARCH_OMAP730
help
Enable 30MHz clock for OMAP CPU. If unsure, say N.
endmenu
endif
......@@ -3,7 +3,7 @@
#
# Common support
obj-y := common.o time.o irq.o dma.o clocks.o mux.o gpio.o mcbsp.o
obj-y := common.o time.o irq.o dma.o clock.o mux.o gpio.o mcbsp.o usb.o
obj-m :=
obj-n :=
obj- :=
......@@ -18,9 +18,7 @@ obj-$(CONFIG_MACH_OMAP_OSK) += board-osk.o
obj-$(CONFIG_MACH_OMAP_H3) += board-h3.o
# OCPI interconnect support for 1710, 1610 and 5912
obj-$(CONFIG_ARCH_OMAP1710) += ocpi.o
obj-$(CONFIG_ARCH_OMAP1610) += ocpi.o
obj-$(CONFIG_ARCH_OMAP5912) += ocpi.o
obj-$(CONFIG_ARCH_OMAP16XX) += ocpi.o
# LEDs support
led-$(CONFIG_MACH_OMAP_H2) += leds-h2p2-debug.o
......
......@@ -22,42 +22,21 @@
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
#include <asm/arch/clocks.h>
#include <asm/arch/gpio.h>
#include <asm/arch/mux.h>
#include <asm/arch/usb.h>
#include <asm/arch/board.h>
#include <asm/arch/serial.h>
#include "common.h"
static int __initdata generic_serial_ports[OMAP_MAX_NR_PORTS] = {1, 1, 1};
static void __init omap_generic_init_irq(void)
{
omap_init_irq();
}
/*
* Muxes the serial ports on
*/
#ifdef CONFIG_ARCH_OMAP1510
static void __init omap_early_serial_init(void)
{
#ifdef CONFIG_OMAP_LL_DEBUG_UART1
omap_cfg_reg(UART1_TX);
omap_cfg_reg(UART1_RTS);
#endif
#ifdef CONFIG_OMAP_LL_DEBUG_UART2
omap_cfg_reg(UART2_TX);
omap_cfg_reg(UART2_RTS);
#endif
#ifdef CONFIG_OMAP_LL_DEBUG_UART1
omap_cfg_reg(UART3_TX);
omap_cfg_reg(UART3_RX);
#endif
}
#endif
/* assume no Mini-AB port */
#ifdef CONFIG_ARCH_OMAP1510
......@@ -69,7 +48,7 @@ static struct omap_usb_config generic1510_usb_config __initdata = {
};
#endif
#ifdef CONFIG_ARCH_OMAP1610
#if defined(CONFIG_ARCH_OMAP16XX)
static struct omap_usb_config generic1610_usb_config __initdata = {
.register_host = 1,
.register_dev = 1,
......@@ -91,17 +70,17 @@ static void __init omap_generic_init(void)
*/
#ifdef CONFIG_ARCH_OMAP1510
if (cpu_is_omap1510()) {
omap_early_serial_init();
generic_config[0].data = &generic1510_usb_config;
}
#endif
#ifdef CONFIG_ARCH_OMAP1610
#if defined(CONFIG_ARCH_OMAP16XX)
if (!cpu_is_omap1510()) {
generic_config[0].data = &generic1610_usb_config;
}
#endif
omap_board_config = generic_config;
omap_board_config_size = ARRAY_SIZE(generic_config);
omap_serial_init(generic_serial_ports);
}
static void __init omap_generic_map_io(void)
......
......@@ -32,14 +32,11 @@
#include <asm/arch/clocks.h>
#include <asm/arch/gpio.h>
#include <asm/arch/usb.h>
#include <asm/arch/serial.h>
#include "common.h"
static struct map_desc h2_io_desc[] __initdata = {
{ OMAP1610_ETHR_BASE, OMAP1610_ETHR_START, OMAP1610_ETHR_SIZE,MT_DEVICE },
{ OMAP1610_NOR_FLASH_BASE, OMAP1610_NOR_FLASH_START, OMAP1610_NOR_FLASH_SIZE,
MT_DEVICE },
};
static int __initdata h2_serial_ports[OMAP_MAX_NR_PORTS] = {1, 1, 1};
static struct resource h2_smc91x_resources[] = {
[0] = {
......@@ -78,15 +75,22 @@ static struct omap_usb_config h2_usb_config __initdata = {
.hmc_mode = 19, // 0:host(off) 1:dev|otg 2:disabled
// .hmc_mode = 21, // 0:host(off) 1:dev(loopback) 2:host(loopback)
#elif defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
/* NONSTANDARD CABLE NEEDED (B-to-Mini-B) */
/* needs OTG cable, or NONSTANDARD (B-to-MiniB) */
.hmc_mode = 20, // 1:dev|otg(off) 1:host 2:disabled
#endif
.pins[1] = 3,
};
static struct omap_mmc_config h2_mmc_config __initdata = {
.mmc_blocks = 1,
.mmc1_power_pin = -1, /* tps65010 gpio3 */
.mmc1_switch_pin = OMAP_MPUIO(1),
};
static struct omap_board_config_kernel h2_config[] = {
{ OMAP_TAG_USB, &h2_usb_config },
{ OMAP_TAG_MMC, &h2_mmc_config },
};
static void __init h2_init(void)
......@@ -99,7 +103,7 @@ static void __init h2_init(void)
static void __init h2_map_io(void)
{
omap_map_io();
iotable_init(h2_io_desc, ARRAY_SIZE(h2_io_desc));
omap_serial_init(h2_serial_ports);
}
MACHINE_START(OMAP_H2, "TI-H2")
......
......@@ -30,6 +30,8 @@
#include <asm/arch/irqs.h>
#include <asm/arch/gpio.h>
#include <asm/mach-types.h>
#include <asm/arch/serial.h>
#include "common.h"
void h3_init_irq(void)
......@@ -37,6 +39,8 @@ void h3_init_irq(void)
omap_init_irq();
}
static int __initdata h3_serial_ports[OMAP_MAX_NR_PORTS] = {1, 1, 1};
static struct resource smc91x_resources[] = {
[0] = {
.start = OMAP1710_ETHR_START, /* Physical */
......@@ -66,15 +70,10 @@ static void __init h3_init(void)
(void) platform_add_devices(devices, ARRAY_SIZE(devices));
}
static struct map_desc h3_io_desc[] __initdata = {
{ OMAP1710_ETHR_BASE, OMAP1710_ETHR_START, OMAP1710_ETHR_SIZE, MT_DEVICE },
{ OMAP_NOR_FLASH_BASE, OMAP_NOR_FLASH_START, OMAP_NOR_FLASH_SIZE, MT_DEVICE },
};
static void __init h3_map_io(void)
{
omap_map_io();
iotable_init(h3_io_desc, ARRAY_SIZE(h3_io_desc));
omap_serial_init(h3_serial_ports);
}
MACHINE_START(OMAP_H3, "TI OMAP1710 H3 board")
......
......@@ -30,6 +30,7 @@
#include <asm/arch/gpio.h>
#include <asm/arch/fpga.h>
#include <asm/arch/usb.h>
#include <asm/arch/serial.h>
#include "common.h"
......@@ -43,6 +44,8 @@ static struct map_desc innovator1510_io_desc[] __initdata = {
MT_DEVICE },
};
static int __initdata innovator_serial_ports[OMAP_MAX_NR_PORTS] = {1, 1, 1};
static struct resource innovator1510_smc91x_resources[] = {
[0] = {
.start = OMAP1510_FPGA_ETHR_START, /* Physical */
......@@ -69,18 +72,12 @@ static struct platform_device *innovator1510_devices[] __initdata = {
#endif /* CONFIG_ARCH_OMAP1510 */
#ifdef CONFIG_ARCH_OMAP1610
static struct map_desc innovator1610_io_desc[] __initdata = {
{ OMAP1610_ETHR_BASE, OMAP1610_ETHR_START, OMAP1610_ETHR_SIZE,MT_DEVICE },
{ OMAP1610_NOR_FLASH_BASE, OMAP1610_NOR_FLASH_START, OMAP1610_NOR_FLASH_SIZE,
MT_DEVICE },
};
#ifdef CONFIG_ARCH_OMAP16XX
static struct resource innovator1610_smc91x_resources[] = {
[0] = {
.start = OMAP1610_ETHR_START, /* Physical */
.end = OMAP1610_ETHR_START + SZ_4K,
.start = INNOVATOR1610_ETHR_START, /* Physical */
.end = INNOVATOR1610_ETHR_START + SZ_4K,
.flags = IORESOURCE_MEM,
},
[1] = {
......@@ -101,7 +98,7 @@ static struct platform_device *innovator1610_devices[] __initdata = {
&innovator1610_smc91x_device,
};
#endif /* CONFIG_ARCH_OMAP1610 */
#endif /* CONFIG_ARCH_OMAP16XX */
void innovator_init_irq(void)
{
......@@ -116,16 +113,19 @@ void innovator_init_irq(void)
#ifdef CONFIG_ARCH_OMAP1510
static struct omap_usb_config innovator1510_usb_config __initdata = {
/* has usb host and device, but no Mini-AB port */
/* for bundled non-standard host and peripheral cables */
.hmc_mode = 4,
.register_host = 1,
.pins[1] = 6,
.pins[2] = 6, /* Conflicts with UART2 */
.register_dev = 1,
/* Assume bad Innovator wiring; Use internal host only with custom cable */
.hmc_mode = 16,
.pins[0] = 2,
};
#endif
#ifdef CONFIG_ARCH_OMAP1610
#ifdef CONFIG_ARCH_OMAP16XX
static struct omap_usb_config h2_usb_config __initdata = {
/* usb1 has a Mini-AB port and external isp1301 transceiver */
.otg = 2,
......@@ -153,7 +153,7 @@ static void __init innovator_init(void)
platform_add_devices(innovator1510_devices, ARRAY_SIZE(innovator1510_devices));
}
#endif
#ifdef CONFIG_ARCH_OMAP1610
#ifdef CONFIG_ARCH_OMAP16XX
if (!cpu_is_omap1510()) {
platform_add_devices(innovator1610_devices, ARRAY_SIZE(innovator1610_devices));
}
......@@ -163,7 +163,7 @@ static void __init innovator_init(void)
if (cpu_is_omap1510())
innovator_config[0].data = &innovator1510_usb_config;
#endif
#ifdef CONFIG_ARCH_OMAP1610
#ifdef CONFIG_ARCH_OMAP16XX
if (cpu_is_omap1610())
innovator_config[0].data = &h2_usb_config;
#endif
......@@ -187,11 +187,7 @@ static void __init innovator_map_io(void)
fpga_read(OMAP1510_FPGA_BOARD_REV));
}
#endif
#ifdef CONFIG_ARCH_OMAP1610
if (!cpu_is_omap1510()) {
iotable_init(innovator1610_io_desc, ARRAY_SIZE(innovator1610_io_desc));
}
#endif
omap_serial_init(innovator_serial_ports);
}
MACHINE_START(OMAP_INNOVATOR, "TI-Innovator")
......
......@@ -38,15 +38,18 @@
#include <asm/arch/clocks.h>
#include <asm/arch/gpio.h>
#include <asm/arch/fpga.h>
#include <asm/arch/usb.h>
#include <asm/arch/serial.h>
#include "common.h"
static struct map_desc osk5912_io_desc[] __initdata = {
{ OMAP_OSK_ETHR_BASE, OMAP_OSK_ETHR_START, OMAP_OSK_ETHR_SIZE,MT_DEVICE },
{ OMAP_OSK_NOR_FLASH_BASE, OMAP_OSK_NOR_FLASH_START, OMAP_OSK_NOR_FLASH_SIZE,
MT_DEVICE },
};
static int __initdata osk_serial_ports[OMAP_MAX_NR_PORTS] = {1, 0, 0};
static struct resource osk5912_smc91x_resources[] = {
[0] = {
.start = OMAP_OSK_ETHR_START, /* Physical */
......@@ -76,16 +79,29 @@ void osk_init_irq(void)
omap_init_irq();
}
static struct omap_usb_config osk_usb_config __initdata = {
/* has usb host and device, but no Mini-AB port */
.register_host = 1,
.hmc_mode = 16,
.pins[0] = 2,
};
static struct omap_board_config_kernel osk_config[] = {
{ OMAP_TAG_USB, &osk_usb_config },
};
static void __init osk_init(void)
{
platform_add_devices(osk5912_devices, ARRAY_SIZE(osk5912_devices));
omap_board_config = osk_config;
omap_board_config_size = ARRAY_SIZE(osk_config);
}
static void __init osk_map_io(void)
{
omap_map_io();
iotable_init(osk5912_io_desc, ARRAY_SIZE(osk5912_io_desc));
omap_serial_init(osk_serial_ports);
}
MACHINE_START(OMAP_OSK, "TI-OSK")
......
......@@ -24,6 +24,7 @@
#include <asm/arch/gpio.h>
#include <asm/arch/mux.h>
#include <asm/arch/fpga.h>
#include <asm/arch/serial.h>
#include "common.h"
......@@ -45,6 +46,8 @@ static struct resource smc91x_resources[] = {
},
};
static int __initdata p2_serial_ports[OMAP_MAX_NR_PORTS] = {1, 1, 0};
static struct platform_device smc91x_device = {
.name = "smc91x",
.id = 0,
......@@ -104,6 +107,7 @@ static void __init omap_perseus2_map_io(void)
* It is used as the Ethernet controller interrupt
*/
omap_writel(omap_readl(OMAP730_IO_CONF_9) & 0x1FFFFFFF, OMAP730_IO_CONF_9);
omap_serial_init(p2_serial_ports);
}
MACHINE_START(OMAP_PERSEUS2, "OMAP730 Perseus2")
......
/*
* linux/arch/arm/mach-omap/clock.c
*
* Copyright (C) 2004 Nokia corporation
* Written by Tuukka Tikkanen <tuukka.tikkanen@elektrobit.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/errno.h>
#include <linux/err.h>
#include <asm/semaphore.h>
#include <asm/hardware/clock.h>
#include <asm/arch/board.h>
#include "clock.h"
static LIST_HEAD(clocks);
static DECLARE_MUTEX(clocks_sem);
static spinlock_t clockfw_lock = SPIN_LOCK_UNLOCKED;
static void propagate_rate(struct clk * clk);
/* MPU virtual clock functions */
static int select_table_rate(unsigned long rate);
static long round_to_table_rate(unsigned long rate);
void clk_setdpll(__u16, __u16);
struct mpu_rate rate_table[] = {
/* MPU MHz, xtal MHz, dpll1 MHz, CKCTL, DPLL_CTL
* armdiv, dspdiv, dspmmu, tcdiv, perdiv, lcddiv
*/
#if defined(CONFIG_OMAP_ARM_195MHZ) && defined(CONFIG_ARCH_OMAP730)
{ 195000000, 13000000, 195000000, 0x050e, 0x2790 }, /* 1/1/2/2/4/8 */
#endif
#if defined(CONFIG_OMAP_ARM_192MHZ) && defined(CONFIG_ARCH_OMAP16XX)
{ 192000000, 19200000, 192000000, 0x050f, 0x2510 }, /* 1/1/2/2/8/8 */
{ 192000000, 12000000, 192000000, 0x050f, 0x2810 }, /* 1/1/2/2/8/8 */
{ 96000000, 12000000, 192000000, 0x055f, 0x2810 }, /* 2/2/2/2/8/8 */
{ 48000000, 12000000, 192000000, 0x0ccf, 0x2810 }, /* 4/4/4/4/8/8 */
{ 24000000, 12000000, 192000000, 0x0fff, 0x2810 }, /* 8/8/8/8/8/8 */
#endif
#if defined(CONFIG_OMAP_ARM_182MHZ) && defined(CONFIG_ARCH_OMAP730)
{ 182000000, 13000000, 182000000, 0x050e, 0x2710 }, /* 1/1/2/2/4/8 */
#endif
#if defined(CONFIG_OMAP_ARM_168MHZ)
{ 168000000, 12000000, 168000000, 0x010f, 0x2710 }, /* 1/1/1/2/8/8 */
#endif
#if defined(CONFIG_OMAP_ARM_120MHZ)
{ 120000000, 12000000, 120000000, 0x010a, 0x2510 }, /* 1/1/1/2/4/4 */
#endif
#if defined(CONFIG_OMAP_ARM_96MHZ)
{ 96000000, 12000000, 96000000, 0x0005, 0x2410 }, /* 1/1/1/1/2/2 */
#endif
#if defined(CONFIG_OMAP_ARM_60MHZ)
{ 60000000, 12000000, 60000000, 0x0005, 0x2290 }, /* 1/1/1/1/2/2 */
#endif
#if defined(CONFIG_OMAP_ARM_30MHZ)
{ 30000000, 12000000, 60000000, 0x0555, 0x2290 }, /* 2/2/2/2/2/2 */
#endif
{ 0, 0, 0, 0, 0 },
};
static void ckctl_recalc(struct clk * clk)
{
int dsor;
/* Calculate divisor encoded as 2-bit exponent */
dsor = 1 << (3 & (omap_readw(ARM_CKCTL) >> clk->rate_offset));
if (unlikely(clk->rate == clk->parent->rate / dsor))
return; /* No change, quick exit */
clk->rate = clk->parent->rate / dsor;
if (unlikely(clk->flags & RATE_PROPAGATES))
propagate_rate(clk);
}
static void followparent_recalc(struct clk * clk)
{
clk->rate = clk->parent->rate;
}
static void watchdog_recalc(struct clk * clk)
{
clk->rate = clk->parent->rate / 14;
}
static struct clk ck_ref = {
.name = "ck_ref",
.rate = 12000000,
.flags = ALWAYS_ENABLED,
};
static struct clk ck_dpll1 = {
.name = "ck_dpll1",
.parent = &ck_ref,
.flags = RATE_PROPAGATES | ALWAYS_ENABLED,
};
static struct clk ck_dpll1out = {
.name = "ck_dpll1out",
.parent = &ck_dpll1,
.flags = DOES_NOT_EXIST_ON_1510,
.enable_reg = ARM_IDLECT2,
.enable_bit = EN_CKOUT_ARM,
.recalc = &followparent_recalc,
};
static struct clk arm_ck = {
.name = "arm_ck",
.parent = &ck_dpll1,
.flags = RATE_CKCTL | RATE_PROPAGATES | ALWAYS_ENABLED,
.rate_offset = CKCTL_ARMDIV_OFFSET,
.recalc = &ckctl_recalc,
};
static struct clk armper_ck = {
.name = "armper_ck",
.parent = &ck_dpll1,
.flags = RATE_CKCTL,
.enable_reg = ARM_IDLECT2,
.enable_bit = EN_PERCK,
.rate_offset = CKCTL_PERDIV_OFFSET,
.recalc = &ckctl_recalc,
};
static struct clk arm_gpio_ck = {
.name = "arm_gpio_ck",
.parent = &ck_dpll1,
.flags = DOES_NOT_EXIST_ON_1610,
.enable_reg = ARM_IDLECT2,
.enable_bit = EN_GPIOCK,
.recalc = &followparent_recalc,
};
static struct clk armxor_ck = {
.name = "armxor_ck",
.parent = &ck_ref,
.enable_reg = ARM_IDLECT2,
.enable_bit = EN_XORPCK,
.recalc = &followparent_recalc,
};
static struct clk armtim_ck = {
.name = "armtim_ck",
.parent = &ck_ref,
.enable_reg = ARM_IDLECT2,
.enable_bit = EN_TIMCK,
.recalc = &followparent_recalc,
};
static struct clk armwdt_ck = {
.name = "armwdt_ck",
.parent = &ck_ref,
.enable_reg = ARM_IDLECT2,
.enable_bit = EN_WDTCK,
.recalc = &watchdog_recalc,
};
static struct clk arminth_ck1610 = {
.name = "arminth_ck",
.parent = &arm_ck,
.flags = DOES_NOT_EXIST_ON_1510,
.recalc = &followparent_recalc,
/* Note: On 1610/1710 frequency can be divided by 2 by programming
* ARM_CKCTL:ARM_INTHCK_SEL(14) to 1
*
* 1510 version is in TC clocks.
*/
};
static struct clk dsp_ck = {
.name = "dsp_ck",
.parent = &ck_dpll1,
.flags = RATE_CKCTL,
.enable_reg = ARM_CKCTL,
.enable_bit = EN_DSPCK,
.rate_offset = CKCTL_DSPDIV_OFFSET,
.recalc = &ckctl_recalc,
};
static struct clk dspmmu_ck = {
.name = "dspmmu_ck",
.parent = &ck_dpll1,
.flags = RATE_CKCTL | ALWAYS_ENABLED,
.rate_offset = CKCTL_DSPMMUDIV_OFFSET,
.recalc = &ckctl_recalc,
};
static struct clk tc_ck = {
.name = "tc_ck",
.parent = &ck_dpll1,
.flags = RATE_CKCTL | RATE_PROPAGATES | ALWAYS_ENABLED,
.rate_offset = CKCTL_TCDIV_OFFSET,
.recalc = &ckctl_recalc,
};
static struct clk arminth_ck1510 = {
.name = "arminth_ck",
.parent = &tc_ck,
.flags = DOES_NOT_EXIST_ON_1610,
.recalc = &followparent_recalc,
/* Note: On 1510 frequency follows TC_CK
*
* 1610/1710 version is in MPU clocks.
*/
};
static struct clk tipb_ck = {
.name = "tibp_ck",
.parent = &tc_ck,
.flags = DOES_NOT_EXIST_ON_1610,
.recalc = &followparent_recalc,
};
static struct clk l3_ocpi_ck = {
.name = "l3_ocpi_ck",
.parent = &tc_ck,
.flags = DOES_NOT_EXIST_ON_1510,
.enable_reg = ARM_IDLECT3,
.enable_bit = EN_OCPI_CK,
.recalc = &followparent_recalc,
};
static struct clk tc1_ck = {
.name = "tc1_ck",
.parent = &tc_ck,
.flags = DOES_NOT_EXIST_ON_1510,
.enable_reg = ARM_IDLECT3,
.enable_bit = EN_TC1_CK,
.recalc = &followparent_recalc,
};
static struct clk tc2_ck = {
.name = "tc2_ck",
.parent = &tc_ck,
.flags = DOES_NOT_EXIST_ON_1510,
.enable_reg = ARM_IDLECT3,
.enable_bit = EN_TC2_CK,
.recalc = &followparent_recalc,
};
static struct clk dma_ck = {
.name = "dma_ck",
.parent = &tc_ck,
.recalc = &followparent_recalc,
};
static struct clk dma_lcdfree_ck = {
.name = "dma_lcdfree_ck",
.parent = &tc_ck,
.flags = DOES_NOT_EXIST_ON_1510,
.recalc = &followparent_recalc,
};
static struct clk api_ck = {
.name = "api_ck",
.parent = &tc_ck,
.enable_reg = ARM_IDLECT2,
.enable_bit = EN_APICK,
.recalc = &followparent_recalc,
};
static struct clk lb_ck = {
.name = "lb_ck",
.parent = &tc_ck,
.flags = DOES_NOT_EXIST_ON_1610,
.enable_reg = ARM_IDLECT2,
.enable_bit = EN_LBCK,
.recalc = &followparent_recalc,
};
static struct clk rhea1_ck = {
.name = "rhea1_ck",
.parent = &tc_ck,
.flags = DOES_NOT_EXIST_ON_1510,
.recalc = &followparent_recalc,
};
static struct clk rhea2_ck = {
.name = "rhea2_ck",
.parent = &tc_ck,
.flags = DOES_NOT_EXIST_ON_1510,
.recalc = &followparent_recalc,
};
static struct clk lcd_ck = {
.name = "lcd_ck",
.parent = &ck_dpll1,
.flags = RATE_CKCTL,
.enable_reg = ARM_IDLECT2,
.enable_bit = EN_LCDCK,
.rate_offset = CKCTL_LCDDIV_OFFSET,
.recalc = &ckctl_recalc,
};
static struct clk uart1_ck = {
.name = "uart1_ck",
/* Direct from ULPD, no parent */
.rate = 48000000,
.flags = RATE_FIXED | ENABLE_REG_32BIT,
.enable_reg = MOD_CONF_CTRL_0,
.enable_bit = 29,
/* (Only on 1510)
* The "enable bit" actually chooses between 48MHz and 12MHz.
*/
};
static struct clk uart2_ck = {
.name = "uart2_ck",
/* Direct from ULPD, no parent */
.rate = 48000000,
.flags = RATE_FIXED | ENABLE_REG_32BIT,
.enable_reg = MOD_CONF_CTRL_0,
.enable_bit = 30,
/* (1510/1610/1710)
* The "enable bit" actually chooses between 48MHz and 12MHz/32kHz.
*/
};
static struct clk uart3_ck = {
.name = "uart3_ck",
/* Direct from ULPD, no parent */
.rate = 48000000,
.flags = RATE_FIXED | ENABLE_REG_32BIT,
.enable_reg = MOD_CONF_CTRL_0,
.enable_bit = 31,
/* (Only on 1510)
* The "enable bit" actually chooses between 48MHz and 12MHz.
*/
};
static struct clk usb_ck1610 = {
.name = "usb_ck",
/* Direct from ULPD, no parent */
.rate = 48000000,
.flags = RATE_FIXED | ENABLE_REG_32BIT |
DOES_NOT_EXIST_ON_1510,
.enable_reg = ULPD_CLOCK_CTRL,
.enable_bit = USB_MCLK_EN,
};
static struct clk usb_ck1510 = {
.name = "usb_ck",
/* Direct from ULPD, no parent */
.rate = 48000000,
.flags = RATE_FIXED | DOES_NOT_EXIST_ON_1610,
};
static struct clk usb_hhc_ck = {
.name = "usb_hhc_ck",
/* Direct from ULPD, no parent */
.rate = 48000000, /* Actually 2 clocks, 12MHz and 48MHz */
.flags = RATE_FIXED | ENABLE_REG_32BIT,
.enable_reg = MOD_CONF_CTRL_0,
.enable_bit = USB_HOST_HHC_UHOST_EN,
};
/* To be done --
static struct clk mclk = {
.name = "mclk",
};
static struct clk bclk = {
.name = "bclk",
};
-- to be done */
static struct clk mmc_ck = {
.name = "mmc1_ck",
.parent = &armxor_ck, /* (1510) */
.rate = 48000000,
.flags = RATE_FIXED | ENABLE_REG_32BIT |
DOES_NOT_EXIST_ON_1610,
.enable_reg = MOD_CONF_CTRL_0,
.enable_bit = 23,
};
static struct clk mmc1_ck = {
.name = "mmc1_ck",
/* Direct from ULPD, no parent (1610/1710) */
.rate = 48000000,
.flags = RATE_FIXED | ENABLE_REG_32BIT |
DOES_NOT_EXIST_ON_1510,
.enable_reg = MOD_CONF_CTRL_0,
.enable_bit = 23,
};
static struct clk mmc2_ck = {
.name = "mmc2_ck",
/* Direct from ULPD, no parent */
.rate = 48000000,
.flags = RATE_FIXED | ENABLE_REG_32BIT |
DOES_NOT_EXIST_ON_1510,
.enable_reg = MOD_CONF_CTRL_0,
.enable_bit = 20,
};
static struct clk virtual_ck_mpu = {
.name = "mpu",
.flags = VIRTUAL_CLOCK | ALWAYS_ENABLED,
.parent = &arm_ck, /* Is smarter alias for */
.recalc = &followparent_recalc,
.set_rate = &select_table_rate,
.round_rate = &round_to_table_rate,
};
static struct clk * onchip_clks[] = {
/* non-ULPD clocks */
&ck_ref,
&ck_dpll1,
/* CK_GEN1 clocks */
&ck_dpll1out,
&arm_ck,
&armper_ck,
&arm_gpio_ck,
&armxor_ck,
&armtim_ck,
&armwdt_ck,
&arminth_ck1510,
&arminth_ck1610,
/* CK_GEN2 clocks */
&dsp_ck,
&dspmmu_ck,
/* CK_GEN3 clocks */
&tc_ck,
&tipb_ck,
&l3_ocpi_ck,
&tc1_ck,
&tc2_ck,
&dma_ck,
&dma_lcdfree_ck,
&api_ck,
&lb_ck,
&rhea1_ck,
&rhea2_ck,
&lcd_ck,
/* ULPD clocks */
&uart1_ck,
&uart2_ck,
&uart3_ck,
&usb_ck1510,
&usb_ck1610,
&usb_hhc_ck,
/* To be done --
&mclk,
&bclk,
-- to be done */
&mmc_ck, /* 1510 */
&mmc1_ck, /* 1610/1710 */
&mmc2_ck,
/* Virtual clocks */
&virtual_ck_mpu,
};
struct clk *clk_get(struct device *dev, const char *id)
{
struct clk *p, *clk = ERR_PTR(-ENOENT);
down(&clocks_sem);
list_for_each_entry(p, &clocks, node) {
if (strcmp(id, p->name) == 0 && try_module_get(p->owner)) {
clk = p;
break;
}
}
up(&clocks_sem);
return clk;
}
EXPORT_SYMBOL(clk_get);
void clk_put(struct clk *clk)
{
if (clk && !IS_ERR(clk))
module_put(clk->owner);
}
EXPORT_SYMBOL(clk_put);
int __clk_enable(struct clk *clk)
{
__u16 regval16;
__u32 regval32;
if (clk->flags & ALWAYS_ENABLED)
return 0;
if (unlikely(clk->enable_reg == 0)) {
printk("Enable for %s without enable enabled\n", clk->name);
return 0;
}
if (clk->flags & ENABLE_REG_32BIT) {
regval32 = omap_readl(clk->enable_reg);
regval32 |= (1 << clk->enable_bit);
omap_writel(regval32, clk->enable_reg);
} else {
regval16 = omap_readw(clk->enable_reg);
regval16 |= (1 << clk->enable_bit);
omap_writew(regval16, clk->enable_reg);
}
return 0;
}
void __clk_disable(struct clk *clk)
{
__u16 regval16;
__u32 regval32;
if (clk->enable_reg == 0)
return;
if (clk->flags & ENABLE_REG_32BIT) {
regval32 = omap_readl(clk->enable_reg);
regval32 &= ~(1 << clk->enable_bit);
omap_writel(regval32, clk->enable_reg);
} else {
regval16 = omap_readw(clk->enable_reg);
regval16 &= ~(1 << clk->enable_bit);
omap_writew(regval16, clk->enable_reg);
}
}
void __clk_unuse(struct clk *clk)
{
if (clk->usecount > 0 && !(--clk->usecount)) {
__clk_disable(clk);
if (likely(clk->parent))
__clk_unuse(clk->parent);
}
}
int __clk_use(struct clk *clk)
{
int ret = 0;
if (clk->usecount++ == 0) {
if (likely(clk->parent))
ret = __clk_use(clk->parent);
if (unlikely(ret != 0)) {
clk->usecount--;
return ret;
}
ret = __clk_enable(clk);
if (unlikely(ret != 0) && clk->parent) {
__clk_unuse(clk->parent);
clk->usecount--;
}
}
return ret;
}
int clk_enable(struct clk *clk)
{
unsigned long flags;
int ret;
spin_lock_irqsave(&clockfw_lock, flags);
ret = __clk_enable(clk);
spin_unlock_irqrestore(&clockfw_lock, flags);
return ret;
}
EXPORT_SYMBOL(clk_enable);
void clk_disable(struct clk *clk)
{
unsigned long flags;
spin_lock_irqsave(&clockfw_lock, flags);
__clk_disable(clk);
spin_unlock_irqrestore(&clockfw_lock, flags);
}
EXPORT_SYMBOL(clk_disable);
int clk_use(struct clk *clk)
{
unsigned long flags;
int ret = 0;
spin_lock_irqsave(&clockfw_lock, flags);
ret = __clk_use(clk);
spin_unlock_irqrestore(&clockfw_lock, flags);
return ret;
}
EXPORT_SYMBOL(clk_use);
void clk_unuse(struct clk *clk)
{
unsigned long flags;
spin_lock_irqsave(&clockfw_lock, flags);
__clk_unuse(clk);
spin_unlock_irqrestore(&clockfw_lock, flags);
}
EXPORT_SYMBOL(clk_unuse);
unsigned long clk_get_rate(struct clk *clk)
{
if (clk->rate == 0) {
printk("Get rate for %s without cached clock\n", clk->name);
}
return clk->rate;
}
EXPORT_SYMBOL(clk_get_rate);
static __u16 verify_ckctl_value(__u16 newval)
{
/* This function checks for following limitations set
* by the hardware (all conditions must be true):
* DSPMMU_CK == DSP_CK or DSPMMU_CK == DSP_CK/2
* ARM_CK >= TC_CK
* DSP_CK >= TC_CK
* DSPMMU_CK >= TC_CK
*
* In addition following rules are enforced:
* LCD_CK <= TC_CK
* ARMPER_CK <= TC_CK
*
* However, maximum frequencies are not checked for!
*/
__u8 per_exp;
__u8 lcd_exp;
__u8 arm_exp;
__u8 dsp_exp;
__u8 tc_exp;
__u8 dspmmu_exp;
per_exp = (newval >> CKCTL_PERDIV_OFFSET) & 3;
lcd_exp = (newval >> CKCTL_LCDDIV_OFFSET) & 3;
arm_exp = (newval >> CKCTL_ARMDIV_OFFSET) & 3;
dsp_exp = (newval >> CKCTL_DSPDIV_OFFSET) & 3;
tc_exp = (newval >> CKCTL_TCDIV_OFFSET) & 3;
dspmmu_exp = (newval >> CKCTL_DSPMMUDIV_OFFSET) & 3;
if (dspmmu_exp < dsp_exp)
dspmmu_exp = dsp_exp;
if (dspmmu_exp > dsp_exp+1)
dspmmu_exp = dsp_exp+1;
if (tc_exp < arm_exp)
tc_exp = arm_exp;
if (tc_exp < dspmmu_exp)
tc_exp = dspmmu_exp;
if (tc_exp > lcd_exp)
lcd_exp = tc_exp;
if (tc_exp > per_exp)
per_exp = tc_exp;
newval &= 0xf000;
newval |= per_exp << CKCTL_PERDIV_OFFSET;
newval |= lcd_exp << CKCTL_LCDDIV_OFFSET;
newval |= arm_exp << CKCTL_ARMDIV_OFFSET;
newval |= dsp_exp << CKCTL_DSPDIV_OFFSET;
newval |= tc_exp << CKCTL_TCDIV_OFFSET;
newval |= dspmmu_exp << CKCTL_DSPMMUDIV_OFFSET;
return newval;
}
static int calc_dsor_exp(struct clk *clk, unsigned long rate)
{
/* Note: If target frequency is too low, this function will return 4,
* which is invalid value. Caller must check for this value and act
* accordingly.
*
* Note: This function does not check for following limitations set
* by the hardware (all conditions must be true):
* DSPMMU_CK == DSP_CK or DSPMMU_CK == DSP_CK/2
* ARM_CK >= TC_CK
* DSP_CK >= TC_CK
* DSPMMU_CK >= TC_CK
*/
unsigned long realrate;
struct clk * parent;
unsigned dsor_exp;
if (unlikely(!(clk->flags & RATE_CKCTL)))
return -EINVAL;
parent = clk->parent;
if (unlikely(parent == 0))
return -EIO;
realrate = parent->rate;
for (dsor_exp=0; dsor_exp<4; dsor_exp++) {
if (realrate <= rate)
break;
realrate /= 2;
}
return dsor_exp;
}
long clk_round_rate(struct clk *clk, unsigned long rate)
{
int dsor_exp;
if (clk->flags & RATE_FIXED)
return clk->rate;
if (clk->flags & RATE_CKCTL) {
dsor_exp = calc_dsor_exp(clk, rate);
if (dsor_exp < 0)
return dsor_exp;
if (dsor_exp > 3)
dsor_exp = 3;
return clk->parent->rate / (1 << dsor_exp);
}
if(clk->round_rate != 0)
return clk->round_rate(rate);
return clk->rate;
}
EXPORT_SYMBOL(clk_round_rate);
static void propagate_rate(struct clk * clk)
{
struct clk ** clkp;
for (clkp = onchip_clks; clkp < onchip_clks+ARRAY_SIZE(onchip_clks); clkp++) {
if (likely((*clkp)->parent != clk)) continue;
if (likely((*clkp)->recalc))
(*clkp)->recalc(*clkp);
}
}
static int select_table_rate(unsigned long rate)
{
/* Find the highest supported frequency <= rate and switch to it */
struct mpu_rate * ptr;
for (ptr = rate_table; ptr->rate; ptr++) {
if (ptr->xtal != ck_ref.rate)
continue;
/* DPLL1 cannot be reprogrammed without risking system crash */
if (likely(ck_dpll1.rate!=0) && ptr->pll_rate != ck_dpll1.rate)
continue;
/* Can check only after xtal frequency check */
if (ptr->rate <= rate)
break;
}
if (!ptr->rate)
return -EINVAL;
if (unlikely(ck_dpll1.rate == 0)) {
omap_writew(ptr->dpllctl_val, DPLL_CTL);
ck_dpll1.rate = ptr->pll_rate;
}
omap_writew(ptr->ckctl_val, ARM_CKCTL);
propagate_rate(&ck_dpll1);
return 0;
}
static long round_to_table_rate(unsigned long rate)
{
/* Find the highest supported frequency <= rate */
struct mpu_rate * ptr;
long highest_rate;
highest_rate = -EINVAL;
for (ptr = rate_table; ptr->rate; ptr++) {
if (ptr->xtal != ck_ref.rate)
continue;
highest_rate = ptr->rate;
/* Can check only after xtal frequency check */
if (ptr->rate <= rate)
break;
}
return highest_rate;
}
int clk_set_rate(struct clk *clk, unsigned long rate)
{
int ret = -EINVAL;
int dsor_exp;
__u16 regval;
unsigned long flags;
if (clk->flags & RATE_CKCTL) {
dsor_exp = calc_dsor_exp(clk, rate);
if (dsor_exp > 3)
dsor_exp = -EINVAL;
if (dsor_exp < 0)
return dsor_exp;
spin_lock_irqsave(&clockfw_lock, flags);
regval = omap_readw(ARM_CKCTL);
regval &= ~(3 << clk->rate_offset);
regval |= dsor_exp << clk->rate_offset;
regval = verify_ckctl_value(regval);
omap_writew(regval, ARM_CKCTL);
clk->rate = clk->parent->rate / (1 << dsor_exp);
spin_unlock_irqrestore(&clockfw_lock, flags);
ret = 0;
} else if(clk->set_rate != 0) {
spin_lock_irqsave(&clockfw_lock, flags);
ret = clk->set_rate(rate);
spin_unlock_irqrestore(&clockfw_lock, flags);
}
if (unlikely(ret == 0 && (clk->flags & RATE_PROPAGATES)))
propagate_rate(clk);
return ret;
}
EXPORT_SYMBOL(clk_set_rate);
int clk_register(struct clk *clk)
{
down(&clocks_sem);
list_add(&clk->node, &clocks);
up(&clocks_sem);
return 0;
}
EXPORT_SYMBOL(clk_register);
void clk_unregister(struct clk *clk)
{
down(&clocks_sem);
list_del(&clk->node);
up(&clocks_sem);
}
EXPORT_SYMBOL(clk_unregister);
int __init clk_init(void)
{
struct clk ** clkp;
const struct omap_clock_config *info;
int crystal_type = 0; /* Default 12 MHz */
for (clkp = onchip_clks; clkp < onchip_clks+ARRAY_SIZE(onchip_clks); clkp++) {
if ((((*clkp)->flags & DOES_NOT_EXIST_ON_1510) &&
cpu_is_omap1510()) ||
(((*clkp)->flags & DOES_NOT_EXIST_ON_1610) &&
(cpu_is_omap1610() || cpu_is_omap1710()))) {
(*clkp)->parent = 0;
continue;
}
clk_register(*clkp);
}
info = omap_get_config(OMAP_TAG_CLOCK, struct omap_clock_config);
if (info != NULL) {
if (!cpu_is_omap1510())
crystal_type = info->system_clock_type;
}
#if defined(CONFIG_ARCH_OMAP730)
ck_ref.rate = 13000000;
#elif defined(CONFIG_ARCH_OMAP16XX)
if (crystal_type == 2)
ck_ref.rate = 19200000;
#endif
/* We want to be in syncronous scalable mode */
omap_writew(0x1000, ARM_SYSST);
/* Find the highest supported frequency and enable it */
if (select_table_rate(~0)) {
printk("System frequencies not set. Check your config.\n");
/* Guess sane values (60MHz) */
omap_writew(0x2290, DPLL_CTL);
omap_writew(0x1005, ARM_CKCTL);
ck_dpll1.rate = 60000000;
propagate_rate(&ck_dpll1);
printk("Clocking rate (xtal/DPLL1/MPU): %ld/%ld/%ld\n",
ck_ref.rate, ck_dpll1.rate, arm_ck.rate);
}
/* Cache rates for clocks connected to ck_ref (not dpll1) */
propagate_rate(&ck_ref);
#ifdef CONFIG_MACH_OMAP_PERSEUS2
/* Select slicer output as OMAP input clock */
omap_writew(omap_readw(OMAP730_PCC_UPLD_CTRL) & ~0x1, OMAP730_PCC_UPLD_CTRL);
#endif
/* Turn off DSP and ARM_TIMXO. Make sure ARM_INTHCK is not divided */
omap_writew(omap_readw(ARM_CKCTL) & 0x0fff, ARM_CKCTL);
/* Put DSP/MPUI into reset until needed */
omap_writew(0, ARM_RSTCT1);
omap_writew(1, ARM_RSTCT2);
omap_writew(0x400, ARM_IDLECT1);
/*
* According to OMAP5910 Erratum SYS_DMA_1, bit DMACK_REQ (bit 8)
* of the ARM_IDLECT2 register must be set to zero. The power-on
* default value of this bit is one.
*/
omap_writew(0x0000, ARM_IDLECT2); /* Turn LCD clock off also */
/*
* Only enable those clocks we will need, let the drivers
* enable other clocks as necessary
*/
clk_use(&armper_ck);
clk_use(&armxor_ck);
clk_use(&armtim_ck);
if (cpu_is_omap1510())
clk_enable(&arm_gpio_ck);
start_mputimer1(0xffffffff);
return 0;
}
/*
* linux/arch/arm/mach-omap/clock.h
*
* Copyright (C) 2004 Nokia corporation
* Written by Tuukka Tikkanen <tuukka.tikkanen@elektrobit.com>
* Based on clocks.h by Tony Lindgren, Gordon McNutt and RidgeRun, Inc
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef __ARCH_ARM_OMAP_CLOCK_H
#define __ARCH_ARM_OMAP_CLOCK_H
struct module;
struct clk {
struct list_head node;
struct module *owner;
const char *name;
struct clk *parent;
unsigned long rate;
__s8 usecount;
__u8 flags;
__u32 enable_reg;
__u8 enable_bit;
__u8 rate_offset;
void (*recalc)(struct clk *);
int (*set_rate)(unsigned long);
long (*round_rate)(unsigned long);
};
struct mpu_rate {
unsigned long rate;
unsigned long xtal;
unsigned long pll_rate;
__u16 ckctl_val;
__u16 dpllctl_val;
};
/* Clock flags */
#define RATE_CKCTL 1
#define RATE_FIXED 2
#define RATE_PROPAGATES 4
#define VIRTUAL_CLOCK 8
#define ALWAYS_ENABLED 16
#define ENABLE_REG_32BIT 32
#define DOES_NOT_EXIST_ON_1510 64
#define DOES_NOT_EXIST_ON_1610 128 /* Including 1710 */
/* ARM_CKCTL bit shifts */
#define CKCTL_PERDIV_OFFSET 0
#define CKCTL_LCDDIV_OFFSET 2
#define CKCTL_ARMDIV_OFFSET 4
#define CKCTL_DSPDIV_OFFSET 6
#define CKCTL_TCDIV_OFFSET 8
#define CKCTL_DSPMMUDIV_OFFSET 10
/*#define ARM_TIMXO 12*/
#define EN_DSPCK 13
/*#define ARM_INTHCK_SEL 14*/ /* Divide-by-2 for mpu inth_ck */
/* ARM_IDLECT1 bit shifts */
/*#define IDLWDT_ARM 0*/
/*#define IDLXORP_ARM 1*/
/*#define IDLPER_ARM 2*/
/*#define IDLLCD_ARM 3*/
/*#define IDLLB_ARM 4*/
/*#define IDLHSAB_ARM 5*/
/*#define IDLIF_ARM 6*/
/*#define IDLDPLL_ARM 7*/
/*#define IDLAPI_ARM 8*/
/*#define IDLTIM_ARM 9*/
/*#define SETARM_IDLE 11*/
/* ARM_IDLECT2 bit shifts */
#define EN_WDTCK 0
#define EN_XORPCK 1
#define EN_PERCK 2
#define EN_LCDCK 3
#define EN_LBCK 4 /* Not on 1610/1710 */
/*#define EN_HSABCK 5*/
#define EN_APICK 6
#define EN_TIMCK 7
#define DMACK_REQ 8
#define EN_GPIOCK 9 /* Not on 1610/1710 */
/*#define EN_LBFREECK 10*/
#define EN_CKOUT_ARM 11
/* ARM_IDLECT3 bit shifts */
#define EN_OCPI_CK 0
#define EN_TC1_CK 2
#define EN_TC2_CK 4
/* Various register defines for clock controls scattered around OMAP chip */
#define USB_MCLK_EN 4 /* In ULPD_CLKC_CTRL */
#define USB_HOST_HHC_UHOST_EN 9 /* In MOD_CONF_CTRL_0 */
int clk_register(struct clk *clk);
void clk_unregister(struct clk *clk);
int clk_init(void);
#endif
/*
* Clock interface for OMAP
*
* Copyright (C) 2001 RidgeRun, Inc
* Written by Gordon McNutt <gmcnutt@ridgerun.com>
* Updated 2004 for Linux 2.6 by Tony Lindgren <tony@atomide.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
* NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/types.h>
#include <linux/spinlock.h>
#include <asm/errno.h>
#include <asm/io.h>
#include <asm/arch/clocks.h>
#include <asm/arch/board.h>
extern void start_mputimer1(unsigned long load_val);
/* Input clock in MHz */
static unsigned int source_clock = 12;
/*
* We use one spinlock for all clock registers for now. We may want to
* change this to be clock register specific later on. Before we can do
* that, we need to map out the shared clock registers.
*/
static spinlock_t clock_lock = SPIN_LOCK_UNLOCKED;
typedef struct {
char *name;
__u8 flags;
ck_t parent;
unsigned long rate_reg; /* Clock rate register */
unsigned long enbl_reg; /* Enable register */
unsigned long idle_reg; /* Idle register */
unsigned long slct_reg; /* Select register */
__s8 rate_shift; /* Clock rate bit shift */
__s8 enbl_shift; /* Clock enable bit shift */
__s8 idle_shift; /* Clock idle bit shift */
__s8 slct_shift; /* Clock select bit shift */
} ck_info_t;
#define CK_NAME(ck) ck_info_table[ck].name
#define CK_FLAGS(ck) ck_info_table[ck].flags
#define CK_PARENT(ck) ck_info_table[ck].parent
#define CK_RATE_REG(ck) ck_info_table[ck].rate_reg
#define CK_ENABLE_REG(ck) ck_info_table[ck].enbl_reg
#define CK_IDLE_REG(ck) ck_info_table[ck].idle_reg
#define CK_SELECT_REG(ck) ck_info_table[ck].slct_reg
#define CK_RATE_SHIFT(ck) ck_info_table[ck].rate_shift
#define CK_ENABLE_SHIFT(ck) ck_info_table[ck].enbl_shift
#define CK_IDLE_SHIFT(ck) ck_info_table[ck].idle_shift
#define CK_SELECT_SHIFT(ck) ck_info_table[ck].slct_shift
#define CK_CAN_CHANGE_RATE(cl) (CK_FLAGS(ck) & CK_RATEF)
#define CK_CAN_DISABLE(cl) (CK_FLAGS(ck) & CK_ENABLEF)
#define CK_CAN_IDLE(cl) (CK_FLAGS(ck) & CK_IDLEF)
#define CK_CAN_SWITCH(cl) (CK_FLAGS(ck) & CK_SELECTF)
static ck_info_t ck_info_table[] = {
{
.name = "clkin",
.flags = 0,
.parent = OMAP_CLKIN,
}, {
.name = "ck_gen1",
.flags = CK_RATEF | CK_IDLEF,
.rate_reg = DPLL_CTL,
.idle_reg = ARM_IDLECT1,
.idle_shift = IDLDPLL_ARM,
.parent = OMAP_CLKIN,
}, {
.name = "ck_gen2",
.flags = 0,
.parent = OMAP_CK_GEN1,
}, {
.name = "ck_gen3",
.flags = 0,
.parent = OMAP_CK_GEN1,
}, {
.name = "tc_ck",
.flags = CK_RATEF | CK_IDLEF,
.parent = OMAP_CK_GEN3,
.rate_reg = ARM_CKCTL, /* ARM_CKCTL[TCDIV(9:8)] */
.idle_reg = ARM_IDLECT1,
.rate_shift = TCDIV,
.idle_shift = IDLIF_ARM
}, {
.name = "arm_ck",
.flags = CK_IDLEF | CK_RATEF,
.parent = OMAP_CK_GEN1,
.rate_reg = ARM_CKCTL, /* ARM_CKCTL[ARMDIV(5:4)] */
.idle_reg = ARM_IDLECT1,
.rate_shift = ARMDIV,
.idle_shift = SETARM_IDLE,
}, {
.name = "mpuper_ck",
.flags = CK_RATEF | CK_IDLEF | CK_ENABLEF,
.parent = OMAP_CK_GEN1,
.rate_reg = ARM_CKCTL, /* ARM_CKCTL[PERDIV(1:0)] */
.enbl_reg = ARM_IDLECT2,
.idle_reg = ARM_IDLECT1,
.rate_shift = PERDIV,
.enbl_shift = EN_PERCK,
.idle_shift = IDLPER_ARM
}, {
.name = "arm_gpio_ck",
.flags = CK_ENABLEF,
.parent = OMAP_CK_GEN1,
.enbl_reg = ARM_IDLECT2,
.enbl_shift = EN_GPIOCK
}, {
.name = "mpuxor_ck",
.flags = CK_ENABLEF | CK_IDLEF,
.parent = OMAP_CLKIN,
.idle_reg = ARM_IDLECT1,
.enbl_reg = ARM_IDLECT2,
.idle_shift = IDLXORP_ARM,
.enbl_shift = EN_XORPCK
}, {
.name = "mputim_ck",
.flags = CK_IDLEF | CK_ENABLEF | CK_SELECTF,
.parent = OMAP_CLKIN,
.idle_reg = ARM_IDLECT1,
.enbl_reg = ARM_IDLECT2,
.slct_reg = ARM_CKCTL,
.idle_shift = IDLTIM_ARM,
.enbl_shift = EN_TIMCK,
.slct_shift = ARM_TIMXO
}, {
.name = "mpuwd_ck",
.flags = CK_IDLEF | CK_ENABLEF,
.parent = OMAP_CLKIN,
.idle_reg = ARM_IDLECT1,
.enbl_reg = ARM_IDLECT2,
.idle_shift = IDLWDT_ARM,
.enbl_shift = EN_WDTCK,
}, {
.name = "dsp_ck",
.flags = CK_RATEF | CK_ENABLEF,
.parent = OMAP_CK_GEN2,
.rate_reg = ARM_CKCTL, /* ARM_CKCTL[DSPDIV(7:6)] */
.enbl_reg = ARM_CKCTL,
.rate_shift = DSPDIV,
.enbl_shift = EN_DSPCK,
}, {
.name = "dspmmu_ck",
.flags = CK_RATEF | CK_ENABLEF,
.parent = OMAP_CK_GEN2,
.rate_reg = ARM_CKCTL, /* ARM_CKCTL[DSPMMUDIV(11:10)] */
.enbl_reg = ARM_CKCTL,
.rate_shift = DSPMMUDIV,
.enbl_shift = EN_DSPCK,
}, {
.name = "dma_ck",
.flags = CK_RATEF | CK_IDLEF | CK_ENABLEF,
.parent = OMAP_CK_GEN3,
.rate_reg = ARM_CKCTL, /* ARM_CKCTL[TCDIV(9:8)] */
.idle_reg = ARM_IDLECT1,
.enbl_reg = ARM_IDLECT2,
.rate_shift = TCDIV,
.idle_shift = IDLIF_ARM,
.enbl_shift = DMACK_REQ
}, {
.name = "api_ck",
.flags = CK_RATEF | CK_IDLEF | CK_ENABLEF,
.parent = OMAP_CK_GEN3,
.rate_reg = ARM_CKCTL, /* ARM_CKCTL[TCDIV(9:8)] */
.idle_reg = ARM_IDLECT1,
.enbl_reg = ARM_IDLECT2,
.rate_shift = TCDIV,
.idle_shift = IDLAPI_ARM,
.enbl_shift = EN_APICK,
}, {
.name = "hsab_ck",
.flags = CK_RATEF | CK_IDLEF | CK_ENABLEF,
.parent = OMAP_CK_GEN3,
.rate_reg = ARM_CKCTL, /* ARM_CKCTL[TCDIV(9:8)] */
.idle_reg = ARM_IDLECT1,
.enbl_reg = ARM_IDLECT2,
.rate_shift = TCDIV,
.idle_shift = IDLHSAB_ARM,
.enbl_shift = EN_HSABCK,
}, {
.name = "lbfree_ck",
.flags = CK_RATEF | CK_ENABLEF,
.parent = OMAP_CK_GEN3,
.rate_reg = ARM_CKCTL, /* ARM_CKCTL[TCDIV(9:8)] */
.enbl_reg = ARM_IDLECT2,
.rate_shift = TCDIV,
.enbl_shift = EN_LBFREECK,
}, {
.name = "lb_ck",
.flags = CK_RATEF | CK_IDLEF | CK_ENABLEF,
.parent = OMAP_CK_GEN3,
.rate_reg = ARM_CKCTL, /* ARM_CKCTL[TCDIV(9:8)] */
.idle_reg = ARM_IDLECT1,
.enbl_reg = ARM_IDLECT2,
.rate_shift = TCDIV,
.idle_shift = IDLLB_ARM,
.enbl_shift = EN_LBCK,
}, {
.name = "lcd_ck",
.flags = CK_RATEF | CK_IDLEF | CK_ENABLEF,
.parent = OMAP_CK_GEN3,
.rate_reg = ARM_CKCTL, /* ARM_CKCTL[LCDDIV(3:2)] */
.idle_reg = ARM_IDLECT1,
.enbl_reg = ARM_IDLECT2,
.rate_shift = LCDDIV,
.idle_shift = IDLLCD_ARM,
.enbl_shift = EN_LCDCK,
},
};
/*****************************************************************************/
#define CK_IN_RANGE(ck) (!((ck < OMAP_CK_MIN) || (ck > OMAP_CK_MAX)))
int ck_auto_unclock = 1;
int ck_debug = 0;
#define CK_MAX_PLL_FREQ OMAP_CK_MAX_RATE
static __u32 ck_valid_table[CK_MAX_PLL_FREQ / 32 + 1];
static __u8 ck_lookup_table[CK_MAX_PLL_FREQ];
int
ck_set_input(ck_t ck, ck_t input)
{
int ret = 0, shift;
unsigned short reg;
unsigned long flags;
if (!CK_IN_RANGE(ck) || !CK_CAN_SWITCH(ck)) {
ret = -EINVAL;
goto exit;
}
reg = omap_readw(CK_SELECT_REG(ck));
shift = CK_SELECT_SHIFT(ck);
spin_lock_irqsave(&clock_lock, flags);
if (input == OMAP_CLKIN) {
reg &= ~(1 << shift);
omap_writew(reg, CK_SELECT_REG(ck));
goto exit;
} else if (input == CK_PARENT(ck)) {
reg |= (1 << shift);
omap_writew(reg, CK_SELECT_REG(ck));
goto exit;
}
ret = -EINVAL;
exit:
spin_unlock_irqrestore(&clock_lock, flags);
return ret;
}
int
ck_get_input(ck_t ck, ck_t * input)
{
int ret = -EINVAL;
unsigned long flags;
if (!CK_IN_RANGE(ck))
goto exit;
ret = 0;
spin_lock_irqsave(&clock_lock, flags);
if (CK_CAN_SWITCH(ck)) {
int shift;
unsigned short reg;
reg = omap_readw(CK_SELECT_REG(ck));
shift = CK_SELECT_SHIFT(ck);
if (reg & (1 << shift)) {
*input = CK_PARENT(ck);
goto exit;
}
}
*input = OMAP_CLKIN;
exit:
spin_unlock_irqrestore(&clock_lock, flags);
return ret;
}
static int
__ck_set_pll_rate(ck_t ck, int rate)
{
unsigned short pll;
unsigned long flags;
if ((rate < 0) || (rate > CK_MAX_PLL_FREQ))
return -EINVAL;
/* Scan downward for the closest matching frequency */
while (rate && !test_bit(rate, (unsigned long *)&ck_valid_table))
rate--;
if (!rate) {
printk(KERN_ERR "%s: couldn't find a matching rate\n",
__FUNCTION__);
return -EINVAL;
}
spin_lock_irqsave(&clock_lock, flags);
pll = omap_readw(CK_RATE_REG(ck));
/* Clear the rate bits */
pll &= ~(0x1f << 5);
/* Set the rate bits */
pll |= (ck_lookup_table[rate - 1] << 5);
omap_writew(pll, CK_RATE_REG(ck));
spin_unlock_irqrestore(&clock_lock, flags);
return 0;
}
static int
__ck_set_clkm_rate(ck_t ck, int rate)
{
int shift, prate, div, ret;
unsigned short reg;
unsigned long flags;
spin_lock_irqsave(&clock_lock, flags);
/*
* We can only set this clock's value to a fraction of its
* parent's value. The interface says I'll round down when necessary.
* So first let's get the parent's current rate.
*/
prate = ck_get_rate(CK_PARENT(ck));
/*
* Let's just start with the highest fraction and keep searching
* down through available rates until we find one less than or equal
* to the desired rate.
*/
for (div = 0; div < 4; div++) {
if (prate <= rate)
break;
prate = prate / 2;
}
/*
* Oops. Looks like the caller wants a rate lower than we can support.
*/
if (div == 5) {
printk(KERN_ERR "%s: %d is too low\n",
__FUNCTION__, rate);
ret = -EINVAL;
goto exit;
}
/*
* One more detail: if this clock supports more than one parent, then
* we're going to automatically switch over to the parent which runs
* through the divisor. For omap this is not ambiguous because for all
* such clocks one choice is always OMAP_CLKIN (which doesn't run
* through the divisor) and the other is whatever I encoded as
* CK_PARENT. Note that I wait until we get this far because I don't
* want to switch the input until we're sure this is going to work.
*/
if (CK_CAN_SWITCH(ck))
if ((ret = ck_set_input(ck, CK_PARENT(ck))) < 0) {
BUG();
goto exit;
}
/*
* At last, we can set the divisor. Clear the old rate bits and
* set the new ones.
*/
reg = omap_readw(CK_RATE_REG(ck));
shift = CK_RATE_SHIFT(ck);
reg &= ~(3 << shift);
reg |= (div << shift);
omap_writew(reg, CK_RATE_REG(ck));
/* And return the new (actual, after rounding down) rate. */
ret = prate;
exit:
spin_unlock_irqrestore(&clock_lock, flags);
return ret;
}
int
ck_set_rate(ck_t ck, int rate)
{
int ret = -EINVAL;
if (!CK_IN_RANGE(ck) || !CK_CAN_CHANGE_RATE(ck))
goto exit;
switch (ck) {
default:
ret = __ck_set_clkm_rate(ck, rate);
break;
case OMAP_CK_GEN1:
ret = __ck_set_pll_rate(ck, rate);
break;
};
exit:
return ret;
}
static int
__ck_get_pll_rate(ck_t ck)
{
int m, d;
unsigned short pll = omap_readw(CK_RATE_REG(ck));
m = (pll & (0x1f << 7)) >> 7;
m = m ? m : 1;
d = (pll & (3 << 5)) >> 5;
d++;
return ((source_clock * m) / d);
}
static int
__ck_get_clkm_rate(ck_t ck)
{
static int bits2div[] = { 1, 2, 4, 8 };
int in, bits, reg, shift;
reg = omap_readw(CK_RATE_REG(ck));
shift = CK_RATE_SHIFT(ck);
in = ck_get_rate(CK_PARENT(ck));
bits = (reg & (3 << shift)) >> shift;
return (in / bits2div[bits]);
}
int
ck_get_rate(ck_t ck)
{
int ret = 0;
ck_t parent;
if (!CK_IN_RANGE(ck)) {
ret = -EINVAL;
goto exit;
}
switch (ck) {
case OMAP_CK_GEN1:
ret = __ck_get_pll_rate(ck);
break;
case OMAP_CLKIN:
ret = source_clock;
break;
case OMAP_MPUXOR_CK:
case OMAP_CK_GEN2:
case OMAP_CK_GEN3:
case OMAP_ARM_GPIO_CK:
ret = ck_get_rate(CK_PARENT(ck));
break;
case OMAP_ARM_CK:
case OMAP_MPUPER_CK:
case OMAP_DSP_CK:
case OMAP_DSPMMU_CK:
case OMAP_LCD_CK:
case OMAP_TC_CK:
case OMAP_DMA_CK:
case OMAP_API_CK:
case OMAP_HSAB_CK:
case OMAP_LBFREE_CK:
case OMAP_LB_CK:
ret = __ck_get_clkm_rate(ck);
break;
case OMAP_MPUTIM_CK:
ck_get_input(ck, &parent);
ret = ck_get_rate(parent);
break;
case OMAP_MPUWD_CK:
/* Note that this evaluates to zero if source_clock is 12MHz. */
ret = source_clock / 14;
break;
default:
ret = -EINVAL;
break;
}
exit:
return ret;
}
int
ck_enable(ck_t ck)
{
unsigned short reg;
int ret = -EINVAL, shift;
unsigned long flags;
if (!CK_IN_RANGE(ck))
goto exit;
if (ck_debug)
printk(KERN_DEBUG "%s: %s\n", __FUNCTION__, CK_NAME(ck));
ret = 0;
if (!CK_CAN_DISABLE(ck))
/* Then it must be on... */
goto exit;
spin_lock_irqsave(&clock_lock, flags);
reg = omap_readw(CK_ENABLE_REG(ck));
shift = CK_ENABLE_SHIFT(ck);
reg |= (1 << shift);
omap_writew(reg, CK_ENABLE_REG(ck));
spin_unlock_irqrestore(&clock_lock, flags);
exit:
return ret;
}
int
ck_disable(ck_t ck)
{
unsigned short reg;
int ret = -EINVAL, shift;
unsigned long flags;
if (!CK_IN_RANGE(ck))
goto exit;
if (ck_debug)
printk(KERN_DEBUG "%s: %s\n", __FUNCTION__, CK_NAME(ck));
if (!CK_CAN_DISABLE(ck))
goto exit;
ret = 0;
if (ck == OMAP_CLKIN)
return -EINVAL;
spin_lock_irqsave(&clock_lock, flags);
reg = omap_readw(CK_ENABLE_REG(ck));
shift = CK_ENABLE_SHIFT(ck);
reg &= ~(1 << shift);
omap_writew(reg, CK_ENABLE_REG(ck));
spin_unlock_irqrestore(&clock_lock, flags);
exit:
return ret;
}
int ck_valid_rate(int rate)
{
return test_bit(rate, (unsigned long *)&ck_valid_table);
}
static void
__ck_make_lookup_table(void)
{
__u8 m, d;
memset(ck_valid_table, 0, sizeof (ck_valid_table));
for (m = 1; m < 32; m++)
for (d = 1; d < 5; d++) {
int rate = ((source_clock * m) / (d));
if (rate > CK_MAX_PLL_FREQ)
continue;
if (test_bit(rate, (unsigned long *)&ck_valid_table))
continue;
set_bit(rate, (unsigned long *)&ck_valid_table);
ck_lookup_table[rate - 1] = (m << 2) | (d - 1);
}
}
int __init
init_ck(void)
{
const struct omap_clock_config *info;
int crystal_type = 0; /* Default 12 MHz */
__ck_make_lookup_table();
info = omap_get_config(OMAP_TAG_CLOCK, struct omap_clock_config);
if (info != NULL) {
if (!cpu_is_omap1510())
crystal_type = info->system_clock_type;
}
/* We want to be in syncronous scalable mode */
omap_writew(0x1000, ARM_SYSST);
#if defined(CONFIG_OMAP_ARM_30MHZ)
omap_writew(0x1555, ARM_CKCTL);
omap_writew(0x2290, DPLL_CTL);
#elif defined(CONFIG_OMAP_ARM_60MHZ)
omap_writew(0x1005, ARM_CKCTL);
omap_writew(0x2290, DPLL_CTL);
#elif defined(CONFIG_OMAP_ARM_96MHZ)
omap_writew(0x1005, ARM_CKCTL);
omap_writew(0x2410, DPLL_CTL);
#elif defined(CONFIG_OMAP_ARM_120MHZ)
omap_writew(0x110a, ARM_CKCTL);
omap_writew(0x2510, DPLL_CTL);
#elif defined(CONFIG_OMAP_ARM_168MHZ)
omap_writew(0x110f, ARM_CKCTL);
omap_writew(0x2710, DPLL_CTL);
#elif defined(CONFIG_OMAP_ARM_182MHZ) && defined(CONFIG_ARCH_OMAP730)
omap_writew(0x250E, ARM_CKCTL);
omap_writew(0x2710, DPLL_CTL);
#elif defined(CONFIG_OMAP_ARM_192MHZ) && (defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP5912) \
|| defined(CONFIG_ARCH_OMAP1710))
omap_writew(0x150f, ARM_CKCTL);
if (crystal_type == 2) {
source_clock = 13; /* MHz */
omap_writew(0x2510, DPLL_CTL);
} else
omap_writew(0x2810, DPLL_CTL);
#elif defined(CONFIG_OMAP_ARM_195MHZ) && defined(CONFIG_ARCH_OMAP730)
omap_writew(0x250E, ARM_CKCTL);
omap_writew(0x2790, DPLL_CTL);
#else
#error "OMAP MHZ not set, please run make xconfig"
#endif
#ifdef CONFIG_MACH_OMAP_PERSEUS2
/* Select slicer output as OMAP input clock */
omap_writew(omap_readw(OMAP730_PCC_UPLD_CTRL) & ~0x1, OMAP730_PCC_UPLD_CTRL);
#endif
/* Turn off some other junk the bootloader might have turned on */
/* Turn off DSP, ARM_INTHCK, ARM_TIMXO */
omap_writew(omap_readw(ARM_CKCTL) & 0x0fff, ARM_CKCTL);
/* Put DSP/MPUI into reset until needed */
omap_writew(0, ARM_RSTCT1);
omap_writew(1, ARM_RSTCT2);
omap_writew(0x400, ARM_IDLECT1);
/*
* According to OMAP5910 Erratum SYS_DMA_1, bit DMACK_REQ (bit 8)
* of the ARM_IDLECT2 register must be set to zero. The power-on
* default value of this bit is one.
*/
omap_writew(0x0000, ARM_IDLECT2); /* Turn LCD clock off also */
/*
* Only enable those clocks we will need, let the drivers
* enable other clocks as necessary
*/
ck_enable(OMAP_MPUPER_CK);
ck_enable(OMAP_ARM_GPIO_CK);
ck_enable(OMAP_MPUXOR_CK);
//ck_set_rate(OMAP_MPUTIM_CK, OMAP_CLKIN);
ck_enable(OMAP_MPUTIM_CK);
start_mputimer1(0xffffffff);
return 0;
}
EXPORT_SYMBOL(ck_get_rate);
EXPORT_SYMBOL(ck_set_rate);
EXPORT_SYMBOL(ck_enable);
EXPORT_SYMBOL(ck_disable);
......@@ -14,65 +14,194 @@
#include <linux/delay.h>
#include <linux/pm.h>
#include <linux/console.h>
#include <linux/serial.h>
#include <linux/tty.h>
#include <linux/serial_core.h>
#include <asm/hardware.h>
#include <asm/system.h>
#include <asm/pgtable.h>
#include <asm/mach/map.h>
#include <asm/arch/clocks.h>
#include <asm/arch/board.h>
#include <asm/hardware/clock.h>
#include <asm/io.h>
#include <asm/mach-types.h>
#include <asm/arch/board.h>
#include <asm/arch/mux.h>
#include <asm/arch/fpga.h>
#include <asm/arch/serial.h>
#include "clock.h"
#define DEBUG 1
struct omap_id {
u16 jtag_id; /* Used to determine OMAP type */
u8 die_rev; /* Processor revision */
u32 omap_id; /* OMAP revision */
u32 type; /* Cpu id bits [31:08], cpu class bits [07:00] */
};
/* Register values to detect the OMAP version */
static struct omap_id omap_ids[] __initdata = {
{ .jtag_id = 0x355f, .die_rev = 0x0, .omap_id = 0x03320000, .type = 0x07300100},
{ .jtag_id = 0xb55f, .die_rev = 0x0, .omap_id = 0x03320000, .type = 0x07300300},
{ .jtag_id = 0xb470, .die_rev = 0x0, .omap_id = 0x03310100, .type = 0x15100000},
{ .jtag_id = 0xb576, .die_rev = 0x0, .omap_id = 0x03320000, .type = 0x16100000},
{ .jtag_id = 0xb576, .die_rev = 0x2, .omap_id = 0x03320100, .type = 0x16110000},
{ .jtag_id = 0xb576, .die_rev = 0x3, .omap_id = 0x03320100, .type = 0x16100c00},
{ .jtag_id = 0xb576, .die_rev = 0x0, .omap_id = 0x03320200, .type = 0x16100d00},
{ .jtag_id = 0xb613, .die_rev = 0x0, .omap_id = 0x03320300, .type = 0x1610ef00},
{ .jtag_id = 0xb613, .die_rev = 0x0, .omap_id = 0x03320300, .type = 0x1610ef00},
{ .jtag_id = 0xb576, .die_rev = 0x1, .omap_id = 0x03320100, .type = 0x16110000},
{ .jtag_id = 0xb58c, .die_rev = 0x2, .omap_id = 0x03320200, .type = 0x16110b00},
{ .jtag_id = 0xb58c, .die_rev = 0x3, .omap_id = 0x03320200, .type = 0x16110c00},
{ .jtag_id = 0xb65f, .die_rev = 0x0, .omap_id = 0x03320400, .type = 0x16212300},
{ .jtag_id = 0xb65f, .die_rev = 0x1, .omap_id = 0x03320400, .type = 0x16212300},
{ .jtag_id = 0xb65f, .die_rev = 0x1, .omap_id = 0x03320500, .type = 0x16212300},
{ .jtag_id = 0xb5f7, .die_rev = 0x0, .omap_id = 0x03330000, .type = 0x17100000},
{ .jtag_id = 0xb5f7, .die_rev = 0x1, .omap_id = 0x03330100, .type = 0x17100000},
{ .jtag_id = 0xb5f7, .die_rev = 0x2, .omap_id = 0x03330100, .type = 0x17100000},
};
/*
* ----------------------------------------------------------------------------
* OMAP revision check
*
* Since we use the cpu_is_omapnnnn() macros, there's a chance that a board
* switches to an updated core. We want to print out the OMAP revision early.
*
* We use the system_serial registers for the revision information so we
* can see it in /proc/cpuinfo.
*
* If the OMAP detection gets more complicated, we may want to expand this
* to store the OMAP version and replace the current cpu_is_omapnnnn() macros.
*
* ----------------------------------------------------------------------------
* Get OMAP type from PROD_ID.
* 1710 has the PROD_ID in bits 15:00, not in 16:01 as documented in TRM.
* 1510 PROD_ID is empty, and 1610 PROD_ID does not make sense.
* Undocumented register in TEST BLOCK is used as fallback; This seems to
* work on 1510, 1610 & 1710. The official way hopefully will work in future
* processors.
*/
static u16 __init omap_get_jtag_id(void)
{
u32 prod_id, omap_id;
prod_id = omap_readl(OMAP_PRODUCTION_ID_1);
omap_id = omap_readl(OMAP32_ID_1);
/* Check for unusable OMAP_PRODUCTION_ID_1 on 1611B/5912 and 730 */
if (((prod_id >> 20) == 0) || (prod_id == omap_id))
prod_id = 0;
else
prod_id &= 0xffff;
if (prod_id)
return prod_id;
/* Use OMAP32_ID_1 as fallback */
prod_id = ((omap_id >> 12) & 0xffff);
return prod_id;
}
/*
* Get OMAP revision from DIE_REV.
* Early 1710 processors may have broken OMAP_DIE_ID, it contains PROD_ID.
* Undocumented register in the TEST BLOCK is used as fallback.
* REVISIT: This does not seem to work on 1510
*/
static u8 __init omap_get_die_rev(void)
{
u32 die_rev;
die_rev = omap_readl(OMAP_DIE_ID_1);
/* Check for broken OMAP_DIE_ID on early 1710 */
if (((die_rev >> 12) & 0xffff) == omap_get_jtag_id())
die_rev = 0;
die_rev = (die_rev >> 17) & 0xf;
if (die_rev)
return die_rev;
die_rev = (omap_readl(OMAP32_ID_1) >> 28) & 0xf;
return die_rev;
}
static void __init omap_check_revision(void)
{
system_serial_high = omap_readl(OMAP_ID_BASE);
system_serial_low = OMAP_ID_REG;
system_rev = (OMAP_ID_REG >> ID_SHIFT) & ID_MASK;
printk("OMAP revision: %d.%d (0x%08x) id: 0x%08x detected as OMAP-",
(system_serial_high >> 20) & 0xf,
(system_serial_high >> 16) & 0xf,
system_serial_high, system_serial_low);
switch (system_rev) {
case OMAP_ID_730:
printk("730\n");
system_rev = 0x730;
break;
case OMAP_ID_1510:
printk("1510\n");
system_rev = 0x1510;
int i;
u16 jtag_id;
u8 die_rev;
u32 omap_id;
u8 cpu_type;
jtag_id = omap_get_jtag_id();
die_rev = omap_get_die_rev();
omap_id = omap_readl(OMAP32_ID_0);
#ifdef DEBUG
printk("OMAP_DIE_ID_0: 0x%08x\n", omap_readl(OMAP_DIE_ID_0));
printk("OMAP_DIE_ID_1: 0x%08x DIE_REV: %i\n",
omap_readl(OMAP_DIE_ID_1),
(omap_readl(OMAP_DIE_ID_1) >> 17) & 0xf);
printk("OMAP_PRODUCTION_ID_0: 0x%08x\n", omap_readl(OMAP_PRODUCTION_ID_0));
printk("OMAP_PRODUCTION_ID_1: 0x%08x JTAG_ID: 0x%04x\n",
omap_readl(OMAP_PRODUCTION_ID_1),
omap_readl(OMAP_PRODUCTION_ID_1) & 0xffff);
printk("OMAP32_ID_0: 0x%08x\n", omap_readl(OMAP32_ID_0));
printk("OMAP32_ID_1: 0x%08x\n", omap_readl(OMAP32_ID_1));
printk("JTAG_ID: 0x%04x DIE_REV: %i\n", jtag_id, die_rev);
#endif
system_serial_high = omap_readl(OMAP_DIE_ID_0);
system_serial_low = omap_readl(OMAP_DIE_ID_1);
/* First check only the major version in a safe way */
for (i = 0; i < ARRAY_SIZE(omap_ids); i++) {
if (jtag_id == (omap_ids[i].jtag_id)) {
system_rev = omap_ids[i].type;
break;
}
}
/* Check if we can find the die revision */
for (i = 0; i < ARRAY_SIZE(omap_ids); i++) {
if (jtag_id == omap_ids[i].jtag_id && die_rev == omap_ids[i].die_rev) {
system_rev = omap_ids[i].type;
break;
}
}
/* Finally check also the omap_id */
for (i = 0; i < ARRAY_SIZE(omap_ids); i++) {
if (jtag_id == omap_ids[i].jtag_id
&& die_rev == omap_ids[i].die_rev
&& omap_id == omap_ids[i].omap_id) {
system_rev = omap_ids[i].type;
break;
}
}
/* Add the cpu class info (7xx, 15xx, 16xx, 24xx) */
cpu_type = system_rev >> 24;
switch (cpu_type) {
case 0x07:
system_rev |= 0x07;
break;
case OMAP_ID_1610:
printk("1610\n");
system_rev = 0x1610;
case 0x15:
system_rev |= 0x15;
break;
case OMAP_ID_1710:
printk("1710\n");
system_rev = 0x1710;
case 0x16:
case 0x17:
system_rev |= 0x16;
break;
case OMAP_ID_5912:
printk("5912/1611B\n");
system_rev = 0x5912;
case 0x24:
system_rev |= 0x24;
break;
default:
printk("unknown, please add support!\n");
printk("Unknown OMAP cpu type: 0x%02x\n", cpu_type);
}
printk("OMAP%04x", system_rev >> 16);
if ((system_rev >> 8) & 0xff)
printk("%x", (system_rev >> 8) & 0xff);
printk(" revision %i handled as %02xxx id: %08x%08x\n",
die_rev, system_rev & 0xff, system_serial_low,
system_serial_high);
}
/*
......@@ -104,25 +233,23 @@ static struct map_desc omap1510_io_desc[] __initdata = {
};
#endif
#if defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP1710)
#if defined(CONFIG_ARCH_OMAP16XX)
static struct map_desc omap1610_io_desc[] __initdata = {
{ OMAP1610_DSP_BASE, OMAP1610_DSP_START, OMAP1610_DSP_SIZE, MT_DEVICE },
{ OMAP1610_DSPREG_BASE, OMAP1610_DSPREG_START, OMAP1610_DSPREG_SIZE, MT_DEVICE },
{ OMAP1610_SRAM_BASE, OMAP1610_SRAM_START, OMAP1610_SRAM_SIZE, MT_DEVICE }
{ OMAP16XX_DSP_BASE, OMAP16XX_DSP_START, OMAP16XX_DSP_SIZE, MT_DEVICE },
{ OMAP16XX_DSPREG_BASE, OMAP16XX_DSPREG_START, OMAP16XX_DSPREG_SIZE, MT_DEVICE },
{ OMAP16XX_SRAM_BASE, OMAP16XX_SRAM_START, OMAP1610_SRAM_SIZE, MT_DEVICE }
};
#endif
#ifdef CONFIG_ARCH_OMAP5912
static struct map_desc omap5912_io_desc[] __initdata = {
{ OMAP5912_DSP_BASE, OMAP5912_DSP_START, OMAP5912_DSP_SIZE, MT_DEVICE },
{ OMAP5912_DSPREG_BASE, OMAP5912_DSPREG_START, OMAP5912_DSPREG_SIZE, MT_DEVICE },
{ OMAP16XX_DSP_BASE, OMAP16XX_DSP_START, OMAP16XX_DSP_SIZE, MT_DEVICE },
{ OMAP16XX_DSPREG_BASE, OMAP16XX_DSPREG_START, OMAP16XX_DSPREG_SIZE, MT_DEVICE },
/*
* The OMAP5912 has 250kByte internal SRAM. Because the mapping is baseed on page
* size (4kByte), it seems that the last 2kByte (=0x800) of the 250kByte are not mapped.
* Add additional 2kByte (0x800) so that the last page is mapped and the last 2kByte
* can be used.
*/
{ OMAP5912_SRAM_BASE, OMAP5912_SRAM_START, OMAP5912_SRAM_SIZE + 0x800, MT_DEVICE }
{ OMAP16XX_SRAM_BASE, OMAP16XX_SRAM_START, OMAP5912_SRAM_SIZE + 0x800, MT_DEVICE }
};
#endif
......@@ -137,6 +264,9 @@ static void __init _omap_map_io(void)
iotable_init(omap_io_desc, ARRAY_SIZE(omap_io_desc));
omap_check_revision();
/* clear BM to canonicalize CS0 (not CS3) at 0000:0000 */
omap_writel(omap_readl(EMIFS_CONFIG) & 0x0d, EMIFS_CONFIG);
#ifdef CONFIG_ARCH_OMAP730
if (cpu_is_omap730()) {
iotable_init(omap730_io_desc, ARRAY_SIZE(omap730_io_desc));
......@@ -147,12 +277,10 @@ static void __init _omap_map_io(void)
iotable_init(omap1510_io_desc, ARRAY_SIZE(omap1510_io_desc));
}
#endif
#if defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP1710)
#if defined(CONFIG_ARCH_OMAP16XX)
if (cpu_is_omap1610() || cpu_is_omap1710()) {
iotable_init(omap1610_io_desc, ARRAY_SIZE(omap1610_io_desc));
}
#endif
#ifdef CONFIG_ARCH_OMAP5912
if (cpu_is_omap5912()) {
iotable_init(omap5912_io_desc, ARRAY_SIZE(omap5912_io_desc));
}
......@@ -166,7 +294,7 @@ static void __init _omap_map_io(void)
/* Must init clocks early to assure that timer interrupt works
*/
init_ck();
clk_init();
}
/*
......@@ -178,26 +306,144 @@ void omap_map_io(void)
_omap_map_io();
}
static struct uart_port omap_serial_ports[] = {
{
.membase = (char*)IO_ADDRESS(OMAP_UART1_BASE),
.mapbase = (unsigned long)OMAP_UART1_BASE,
.irq = INT_UART1,
.flags = UPF_SKIP_TEST,
.iotype = UPIO_MEM,
.regshift = 2,
.uartclk = OMAP16XX_BASE_BAUD * 16,
.line = 0,
.type = PORT_OMAP,
.fifosize = 64
} , {
.membase = (char*)IO_ADDRESS(OMAP_UART2_BASE),
.mapbase = (unsigned long)OMAP_UART2_BASE,
.irq = INT_UART2,
.flags = UPF_SKIP_TEST,
.iotype = UPIO_MEM,
.regshift = 2,
.uartclk = OMAP16XX_BASE_BAUD * 16,
.line = 1,
.type = PORT_OMAP,
.fifosize = 64
} , {
.membase = (char*)IO_ADDRESS(OMAP_UART3_BASE),
.mapbase = (unsigned long)OMAP_UART3_BASE,
.irq = INT_UART3,
.flags = UPF_SKIP_TEST,
.iotype = UPIO_MEM,
.regshift = 2,
.uartclk = OMAP16XX_BASE_BAUD * 16,
.line = 2,
.type = PORT_OMAP,
.fifosize = 64
}
};
/*
* Note that on Innovator-1510 UART2 pins conflict with USB2.
* By default UART2 does not work on Innovator-1510 if you have
* USB OHCI enabled. To use UART2, you must disable USB2 first.
*/
void __init omap_serial_init(int ports[OMAP_MAX_NR_PORTS])
{
int i;
if (cpu_is_omap730()) {
omap_serial_ports[0].regshift = 0;
omap_serial_ports[1].regshift = 0;
omap_serial_ports[0].irq = INT_730_UART_MODEM_1;
omap_serial_ports[1].irq = INT_730_UART_MODEM_IRDA_2;
}
if (cpu_is_omap1510()) {
omap_serial_ports[0].uartclk = OMAP1510_BASE_BAUD * 16;
omap_serial_ports[1].uartclk = OMAP1510_BASE_BAUD * 16;
omap_serial_ports[2].uartclk = OMAP1510_BASE_BAUD * 16;
}
for (i = 0; i < OMAP_MAX_NR_PORTS; i++) {
unsigned long port;
unsigned char regshift;
unsigned char reg;
if (ports[i] != 1)
continue;
switch (i) {
case 0:
if (cpu_is_omap1510()) {
omap_cfg_reg(UART1_TX);
omap_cfg_reg(UART1_RTS);
if (machine_is_omap_innovator()) {
reg = fpga_read(OMAP1510_FPGA_POWER);
reg |= OMAP1510_FPGA_PCR_COM1_EN;
fpga_write(reg, OMAP1510_FPGA_POWER);
udelay(1);
}
}
break;
case 1:
if (cpu_is_omap1510()) {
omap_cfg_reg(UART2_TX);
omap_cfg_reg(UART2_RTS);
if (machine_is_omap_innovator()) {
reg = fpga_read(OMAP1510_FPGA_POWER);
reg |= OMAP1510_FPGA_PCR_COM2_EN;
fpga_write(reg, OMAP1510_FPGA_POWER);
udelay(1);
}
}
break;
case 2:
if (cpu_is_omap1510()) {
omap_cfg_reg(UART3_TX);
omap_cfg_reg(UART3_RX);
}
break;
}
/* Reset port */
if (!cpu_is_omap1510()) {
port = (unsigned long)omap_serial_ports[i].membase;
regshift = omap_serial_ports[i].regshift;
writeb(0x01, port + (UART_SYSC << regshift));
while (!(readb(port + (UART_SYSC << regshift)) & 0x01));
}
//early_serial_setup(&omap_serial_ports[i]);
}
}
#define NO_LENGTH_CHECK 0xffffffff
extern int omap_bootloader_tag_len;
extern u8 omap_bootloader_tag[];
struct omap_board_config_kernel *omap_board_config;
int omap_board_config_size = 0;
const void *__omap_get_config(u16 tag, size_t len)
static const void *get_config(u16 tag, size_t len, int skip, size_t *len_out)
{
struct omap_board_config_entry *info = NULL;
struct omap_board_config_kernel *kinfo = NULL;
int i;
#ifdef CONFIG_OMAP_BOOT_TAG
struct omap_board_config_entry *info = NULL;
if (omap_bootloader_tag_len > 4)
info = (struct omap_board_config_entry *) omap_bootloader_tag;
while (info != NULL) {
u8 *next;
if (info->tag == tag)
break;
if (info->tag == tag) {
if (skip == 0)
break;
skip--;
}
next = (u8 *) info + sizeof(*info) + info->len;
if (next >= omap_bootloader_tag + omap_bootloader_tag_len)
......@@ -208,11 +454,13 @@ const void *__omap_get_config(u16 tag, size_t len)
if (info != NULL) {
/* Check the length as a lame attempt to check for
* binary inconsistancy. */
if (info->len != len) {
if (len != NO_LENGTH_CHECK && info->len != len) {
printk(KERN_ERR "OMAP peripheral config: Length mismatch with tag %x (want %d, got %d)\n",
tag, len, info->len);
return NULL;
}
if (len_out != NULL)
*len_out = info->len;
return info->data;
}
#endif
......@@ -228,8 +476,19 @@ const void *__omap_get_config(u16 tag, size_t len)
return NULL;
return kinfo->data;
}
const void *__omap_get_config(u16 tag, size_t len, int nr)
{
return get_config(tag, len, nr, NULL);
}
EXPORT_SYMBOL(__omap_get_config);
const void *omap_get_var_config(u16 tag, size_t *len)
{
return get_config(tag, NO_LENGTH_CHECK, 0, len);
}
EXPORT_SYMBOL(omap_get_var_config);
static int __init omap_add_serial_console(void)
{
const struct omap_uart_config *info;
......
......@@ -31,5 +31,6 @@ struct sys_timer;
extern void omap_map_io(void);
extern struct sys_timer omap_timer;
extern void omap_serial_init(int ports[]);
#endif /* __ARCH_ARM_MACH_OMAP_COMMON_H */
......@@ -4,6 +4,8 @@
* Copyright (C) 2003 Nokia Corporation
* Author: Juha Yrjl <juha.yrjola@nokia.com>
* DMA channel linking for 1610 by Samuel Ortiz <samuel.ortiz@nokia.com>
* Graphics DMA and LCD DMA graphics tranformations
* by Imre Deak <imre.deak@nokia.com>
*
* Support functions for the OMAP internal DMA channels.
*
......@@ -26,6 +28,8 @@
#include <asm/dma.h>
#include <asm/io.h>
#include <asm/arch/tc.h>
#define OMAP_DMA_ACTIVE 0x01
#define OMAP_DMA_CCR_EN (1 << 7)
......@@ -87,6 +91,34 @@ static void clear_lch_regs(int lch)
omap_writew(0, lch_base + i);
}
void omap_set_dma_priority(int dst_port, int priority)
{
unsigned long reg;
u32 l;
switch (dst_port) {
case OMAP_DMA_PORT_OCP_T1: /* FFFECC00 */
reg = OMAP_TC_OCPT1_PRIOR;
break;
case OMAP_DMA_PORT_OCP_T2: /* FFFECCD0 */
reg = OMAP_TC_OCPT2_PRIOR;
break;
case OMAP_DMA_PORT_EMIFF: /* FFFECC08 */
reg = OMAP_TC_EMIFF_PRIOR;
break;
case OMAP_DMA_PORT_EMIFS: /* FFFECC04 */
reg = OMAP_TC_EMIFS_PRIOR;
break;
default:
BUG();
return;
}
l = omap_readl(reg);
l &= ~(0xf << 8);
l |= (priority & 0xf) << 8;
omap_writel(l, reg);
}
void omap_set_dma_transfer_params(int lch, int data_type, int elem_count,
int frame_count, int sync_mode)
{
......@@ -113,51 +145,38 @@ void omap_set_dma_transfer_params(int lch, int data_type, int elem_count,
omap_writew(frame_count, OMAP_DMA_CFN(lch));
}
void omap_set_dma_constant_fill(int lch, u32 color)
void omap_set_dma_color_mode(int lch, enum omap_dma_color_mode mode, u32 color)
{
u16 w;
#ifdef CONFIG_DEBUG_KERNEL
if (omap_dma_in_1510_mode()) {
printk(KERN_ERR "OMAP DMA constant fill not available in 1510 mode.");
BUG();
return;
}
#endif
w = omap_readw(OMAP_DMA_CCR2(lch)) & ~0x03;
w |= 0x01;
omap_writew(w, OMAP_DMA_CCR2(lch));
BUG_ON(omap_dma_in_1510_mode());
omap_writew((u16)color, OMAP_DMA_COLOR_L(lch));
omap_writew((u16)(color >> 16), OMAP_DMA_COLOR_U(lch));
w = omap_readw(OMAP_DMA_LCH_CTRL(lch)) & ~0x0f;
w |= 1; /* Channel type G */
omap_writew(w, OMAP_DMA_LCH_CTRL(lch));
}
void omap_set_dma_transparent_copy(int lch, u32 color)
{
u16 w;
#ifdef CONFIG_DEBUG_KERNEL
if (omap_dma_in_1510_mode()) {
printk(KERN_ERR "OMAP DMA transparent copy not available in 1510 mode.");
w = omap_readw(OMAP_DMA_CCR2(lch)) & ~0x03;
switch (mode) {
case OMAP_DMA_CONSTANT_FILL:
w |= 0x01;
break;
case OMAP_DMA_TRANSPARENT_COPY:
w |= 0x02;
break;
case OMAP_DMA_COLOR_DIS:
break;
default:
BUG();
}
#endif
w = omap_readw(OMAP_DMA_CCR2(lch)) & ~0x03;
w |= 0x02;
omap_writew(w, OMAP_DMA_CCR2(lch));
omap_writew((u16)color, OMAP_DMA_COLOR_L(lch));
omap_writew((u16)(color >> 16), OMAP_DMA_COLOR_U(lch));
w = omap_readw(OMAP_DMA_LCH_CTRL(lch)) & ~0x0f;
w |= 1; /* Channel type G */
/* Default is channel type 2D */
if (mode) {
omap_writew((u16)color, OMAP_DMA_COLOR_L(lch));
omap_writew((u16)(color >> 16), OMAP_DMA_COLOR_U(lch));
w |= 1; /* Channel type G */
}
omap_writew(w, OMAP_DMA_LCH_CTRL(lch));
}
void omap_set_dma_src_params(int lch, int src_port, int src_amode,
unsigned long src_start)
{
......@@ -192,22 +211,24 @@ void omap_set_dma_src_data_pack(int lch, int enable)
omap_writew(w, OMAP_DMA_CSDP(lch));
}
void omap_set_dma_src_burst_mode(int lch, int burst_mode)
void omap_set_dma_src_burst_mode(int lch, enum omap_dma_burst_mode burst_mode)
{
u16 w;
w = omap_readw(OMAP_DMA_CSDP(lch)) & ~(0x03 << 7);
switch (burst_mode) {
case OMAP_DMA_DATA_BURST_DIS:
break;
case OMAP_DMA_DATA_BURST_4:
w |= (0x01 << 7);
break;
case OMAP_DMA_DATA_BURST_8:
w |= (0x03 << 7);
break;
/* not supported by current hardware
* w |= (0x03 << 7);
* fall through
*/
default:
printk(KERN_ERR "Invalid DMA burst mode\n");
BUG();
return;
}
omap_writew(w, OMAP_DMA_CSDP(lch));
}
......@@ -246,12 +267,14 @@ void omap_set_dma_dest_data_pack(int lch, int enable)
omap_writew(w, OMAP_DMA_CSDP(lch));
}
void omap_set_dma_dest_burst_mode(int lch, int burst_mode)
void omap_set_dma_dest_burst_mode(int lch, enum omap_dma_burst_mode burst_mode)
{
u16 w;
w = omap_readw(OMAP_DMA_CSDP(lch)) & ~(0x03 << 14);
switch (burst_mode) {
case OMAP_DMA_DATA_BURST_DIS:
break;
case OMAP_DMA_DATA_BURST_4:
w |= (0x01 << 14);
break;
......@@ -474,7 +497,7 @@ int omap_request_dma(int dev_id, const char *dev_name,
chan->data = data;
chan->enabled_irqs = OMAP_DMA_TOUT_IRQ | OMAP_DMA_DROP_IRQ | OMAP_DMA_BLOCK_IRQ;
if (cpu_is_omap1610() || cpu_is_omap5912() || cpu_is_omap730() || cpu_is_omap1710()) {
if (cpu_is_omap16xx() || cpu_is_omap730()) {
/* If the sync device is set, configure it dynamically. */
if (dev_id != 0) {
set_gdma_dev(free_ch + 1, dev_id);
......@@ -571,8 +594,15 @@ static struct lcd_dma_info {
void (* callback)(u16 status, void *data);
void *cb_data;
int active;
unsigned long addr, size;
int rotate, data_type, xres, yres;
int vxres;
int mirror;
int xscale, yscale;
int ext_ctrl;
int src_port;
int single_transfer;
} lcd_dma;
void omap_set_lcd_dma_b1(unsigned long addr, u16 fb_xres, u16 fb_yres,
......@@ -584,14 +614,70 @@ void omap_set_lcd_dma_b1(unsigned long addr, u16 fb_xres, u16 fb_yres,
lcd_dma.yres = fb_yres;
}
void omap_set_lcd_dma_src_port(int port)
{
lcd_dma.src_port = port;
}
void omap_set_lcd_dma_ext_controller(int external)
{
lcd_dma.ext_ctrl = external;
}
void omap_set_lcd_dma_single_transfer(int single)
{
lcd_dma.single_transfer = single;
}
void omap_set_lcd_dma_b1_rotation(int rotate)
{
if (omap_dma_in_1510_mode()) {
printk(KERN_ERR "DMA rotation is not supported in 1510 mode\n");
BUG();
return;
}
lcd_dma.rotate = rotate;
}
void omap_set_lcd_dma_b1_mirror(int mirror)
{
if (omap_dma_in_1510_mode()) {
printk(KERN_ERR "DMA mirror is not supported in 1510 mode\n");
BUG();
}
lcd_dma.mirror = mirror;
}
void omap_set_lcd_dma_b1_vxres(unsigned long vxres)
{
if (omap_dma_in_1510_mode()) {
printk(KERN_ERR "DMA virtual resulotion is not supported "
"in 1510 mode\n");
BUG();
}
lcd_dma.vxres = vxres;
}
void omap_set_lcd_dma_b1_scale(unsigned int xscale, unsigned int yscale)
{
if (omap_dma_in_1510_mode()) {
printk(KERN_ERR "DMA scale is not supported in 1510 mode\n");
BUG();
}
lcd_dma.xscale = xscale;
lcd_dma.yscale = yscale;
}
static void set_b1_regs(void)
{
unsigned long top, bottom;
int es;
u16 w, en, fn;
s16 ei;
s32 fi;
u32 l;
u16 w;
unsigned long en, fn;
long ei, fi;
unsigned long vxres;
unsigned int xscale, yscale;
switch (lcd_dma.data_type) {
case OMAP_DMA_DATA_TYPE_S8:
......@@ -608,25 +694,81 @@ static void set_b1_regs(void)
return;
}
if (lcd_dma.rotate == 0) {
top = lcd_dma.addr;
bottom = lcd_dma.addr + (lcd_dma.xres * lcd_dma.yres - 1) * es;
/* 1510 DMA requires the bottom address to be 2 more than the
* actual last memory access location. */
if (omap_dma_in_1510_mode() &&
lcd_dma.data_type == OMAP_DMA_DATA_TYPE_S32)
bottom += 2;
vxres = lcd_dma.vxres ? lcd_dma.vxres : lcd_dma.xres;
xscale = lcd_dma.xscale ? lcd_dma.xscale : 1;
yscale = lcd_dma.yscale ? lcd_dma.yscale : 1;
BUG_ON(vxres < lcd_dma.xres);
#define PIXADDR(x,y) (lcd_dma.addr + ((y) * vxres * yscale + (x) * xscale) * es)
#define PIXSTEP(sx, sy, dx, dy) (PIXADDR(dx, dy) - PIXADDR(sx, sy) - es + 1)
switch (lcd_dma.rotate) {
case 0:
if (!lcd_dma.mirror) {
top = PIXADDR(0, 0);
bottom = PIXADDR(lcd_dma.xres - 1, lcd_dma.yres - 1);
/* 1510 DMA requires the bottom address to be 2 more
* than the actual last memory access location. */
if (omap_dma_in_1510_mode() &&
lcd_dma.data_type == OMAP_DMA_DATA_TYPE_S32)
bottom += 2;
ei = PIXSTEP(0, 0, 1, 0);
fi = PIXSTEP(lcd_dma.xres - 1, 0, 0, 1);
} else {
top = PIXADDR(lcd_dma.xres - 1, 0);
bottom = PIXADDR(0, lcd_dma.yres - 1);
ei = PIXSTEP(1, 0, 0, 0);
fi = PIXSTEP(0, 0, lcd_dma.xres - 1, 1);
}
en = lcd_dma.xres;
fn = lcd_dma.yres;
ei = 0;
fi = 0;
} else {
top = lcd_dma.addr + (lcd_dma.xres - 1) * es;
bottom = lcd_dma.addr + (lcd_dma.yres - 1) * lcd_dma.xres * es;
break;
case 90:
if (!lcd_dma.mirror) {
top = PIXADDR(0, lcd_dma.yres - 1);
bottom = PIXADDR(lcd_dma.xres - 1, 0);
ei = PIXSTEP(0, 1, 0, 0);
fi = PIXSTEP(0, 0, 1, lcd_dma.yres - 1);
} else {
top = PIXADDR(lcd_dma.xres - 1, lcd_dma.yres - 1);
bottom = PIXADDR(0, 0);
ei = PIXSTEP(0, 1, 0, 0);
fi = PIXSTEP(1, 0, 0, lcd_dma.yres - 1);
}
en = lcd_dma.yres;
fn = lcd_dma.xres;
break;
case 180:
if (!lcd_dma.mirror) {
top = PIXADDR(lcd_dma.xres - 1, lcd_dma.yres - 1);
bottom = PIXADDR(0, 0);
ei = PIXSTEP(1, 0, 0, 0);
fi = PIXSTEP(0, 1, lcd_dma.xres - 1, 0);
} else {
top = PIXADDR(0, lcd_dma.yres - 1);
bottom = PIXADDR(lcd_dma.xres - 1, 0);
ei = PIXSTEP(0, 0, 1, 0);
fi = PIXSTEP(lcd_dma.xres - 1, 1, 0, 0);
}
en = lcd_dma.xres;
fn = lcd_dma.yres;
break;
case 270:
if (!lcd_dma.mirror) {
top = PIXADDR(lcd_dma.xres - 1, 0);
bottom = PIXADDR(0, lcd_dma.yres - 1);
ei = PIXSTEP(0, 0, 0, 1);
fi = PIXSTEP(1, lcd_dma.yres - 1, 0, 0);
} else {
top = PIXADDR(0, 0);
bottom = PIXADDR(lcd_dma.xres - 1, lcd_dma.yres - 1);
ei = PIXSTEP(0, 0, 0, 1);
fi = PIXSTEP(0, lcd_dma.yres - 1, 1, 0);
}
en = lcd_dma.yres;
fn = lcd_dma.xres;
ei = (lcd_dma.xres - 1) * es + 1;
fi = -(lcd_dma.xres * (lcd_dma.yres - 1) + 2) * 2 + 1;
break;
default:
BUG();
return; /* Supress warning about uninitialized vars */
}
if (omap_dma_in_1510_mode()) {
......@@ -652,33 +794,50 @@ static void set_b1_regs(void)
w |= lcd_dma.data_type;
omap_writew(w, OMAP1610_DMA_LCD_CSDP);
if (!lcd_dma.rotate)
w = omap_readw(OMAP1610_DMA_LCD_CTRL);
/* Always set the source port as SDRAM for now*/
w &= ~(0x03 << 6);
if (lcd_dma.ext_ctrl)
w |= 1 << 8;
else
w &= ~(1 << 8);
if (lcd_dma.callback != NULL)
w |= 1 << 1; /* Block interrupt enable */
else
w &= ~(1 << 1);
omap_writew(w, OMAP1610_DMA_LCD_CTRL);
if (!(lcd_dma.rotate || lcd_dma.mirror ||
lcd_dma.vxres || lcd_dma.xscale || lcd_dma.yscale))
return;
/* Rotation stuff */
l = omap_readw(OMAP1610_DMA_LCD_CSDP);
/* Disable burst access */
l &= ~(0x03 << 7);
omap_writew(l, OMAP1610_DMA_LCD_CSDP);
l = omap_readw(OMAP1610_DMA_LCD_CCR);
w = omap_readw(OMAP1610_DMA_LCD_CCR);
/* Set the double-indexed addressing mode */
l |= (0x03 << 12);
omap_writew(l, OMAP1610_DMA_LCD_CCR);
w |= (0x03 << 12);
omap_writew(w, OMAP1610_DMA_LCD_CCR);
omap_writew(ei, OMAP1610_DMA_LCD_SRC_EI_B1);
omap_writew(fi >> 16, OMAP1610_DMA_LCD_SRC_FI_B1_U);
omap_writew(fi, OMAP1610_DMA_LCD_SRC_FI_B1_L);
}
void omap_set_lcd_dma_b1_rotation(int rotate)
static irqreturn_t lcd_dma_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
{
if (omap_dma_in_1510_mode()) {
printk(KERN_ERR "DMA rotation is not supported in 1510 mode\n");
BUG();
return;
u16 w;
w = omap_readw(OMAP1610_DMA_LCD_CTRL);
if (unlikely(!(w & (1 << 3)))) {
printk(KERN_WARNING "Spurious LCD DMA IRQ\n");
return IRQ_NONE;
}
lcd_dma.rotate = rotate;
/* Ack the IRQ */
w |= (1 << 3);
omap_writew(w, OMAP1610_DMA_LCD_CTRL);
lcd_dma.active = 0;
if (lcd_dma.callback != NULL)
lcd_dma.callback(w, lcd_dma.cb_data);
return IRQ_HANDLED;
}
int omap_request_lcd_dma(void (* callback)(u16 status, void *data),
......@@ -695,6 +854,15 @@ int omap_request_lcd_dma(void (* callback)(u16 status, void *data),
spin_unlock_irq(&lcd_dma.lock);
lcd_dma.callback = callback;
lcd_dma.cb_data = data;
lcd_dma.active = 0;
lcd_dma.single_transfer = 0;
lcd_dma.rotate = 0;
lcd_dma.vxres = 0;
lcd_dma.mirror = 0;
lcd_dma.xscale = 0;
lcd_dma.yscale = 0;
lcd_dma.ext_ctrl = 0;
lcd_dma.src_port = 0;
return 0;
}
......@@ -714,23 +882,53 @@ void omap_free_lcd_dma(void)
spin_unlock(&lcd_dma.lock);
}
void omap_start_lcd_dma(void)
void omap_enable_lcd_dma(void)
{
u16 w;
/* Set the Enable bit only if an external controller is
* connected. Otherwise the OMAP internal controller will
* start the transfer when it gets enabled.
*/
if (enable_1510_mode || !lcd_dma.ext_ctrl)
return;
w = omap_readw(OMAP1610_DMA_LCD_CCR);
w |= 1 << 7;
omap_writew(w, OMAP1610_DMA_LCD_CCR);
lcd_dma.active = 1;
}
void omap_setup_lcd_dma(void)
{
BUG_ON(lcd_dma.active);
if (!enable_1510_mode) {
/* Set some reasonable defaults */
omap_writew(0x5440, OMAP1610_DMA_LCD_CCR);
omap_writew(0x9102, OMAP1610_DMA_LCD_CSDP);
omap_writew(0x0004, OMAP1610_DMA_LCD_LCH_CTRL);
omap_writew(0x5740, OMAP1610_DMA_LCD_CCR);
}
set_b1_regs();
if (!enable_1510_mode)
omap_writew(omap_readw(OMAP1610_DMA_LCD_CCR) | 1, OMAP1610_DMA_LCD_CCR);
if (!enable_1510_mode) {
u16 w;
w = omap_readw(OMAP1610_DMA_LCD_CCR);
/* If DMA was already active set the end_prog bit to have
* the programmed register set loaded into the active
* register set.
*/
w |= 1 << 11; /* End_prog */
if (!lcd_dma.single_transfer)
w |= (3 << 8); /* Auto_init, repeat */
omap_writew(w, OMAP1610_DMA_LCD_CCR);
}
}
void omap_stop_lcd_dma(void)
{
if (!enable_1510_mode)
omap_writew(omap_readw(OMAP1610_DMA_LCD_CCR) & ~1, OMAP1610_DMA_LCD_CCR);
lcd_dma.active = 0;
if (!enable_1510_mode && lcd_dma.ext_ctrl)
omap_writew(omap_readw(OMAP1610_DMA_LCD_CCR) & ~(1 << 7),
OMAP1610_DMA_LCD_CCR);
}
static int __init omap_init_dma(void)
......@@ -741,7 +939,7 @@ static int __init omap_init_dma(void)
printk(KERN_INFO "DMA support for OMAP1510 initialized\n");
dma_chan_count = 9;
enable_1510_mode = 1;
} else if (cpu_is_omap1610() || cpu_is_omap5912() || cpu_is_omap730() || cpu_is_omap1710()) {
} else if (cpu_is_omap16xx() || cpu_is_omap730()) {
printk(KERN_INFO "OMAP DMA hardware version %d\n",
omap_readw(OMAP_DMA_HW_ID));
printk(KERN_INFO "DMA capabilities: %08x:%08x:%04x:%04x:%04x\n",
......@@ -756,7 +954,7 @@ static int __init omap_init_dma(void)
w = omap_readw(OMAP_DMA_GSCR);
w |= 1 << 3;
omap_writew(w, OMAP_DMA_GSCR);
dma_chan_count = OMAP_LOGICAL_DMA_CH_COUNT;
dma_chan_count = 16;
} else
dma_chan_count = 9;
} else {
......@@ -790,11 +988,21 @@ static int __init omap_init_dma(void)
return r;
}
}
r = request_irq(INT_DMA_LCD, lcd_dma_irq_handler, 0, "LCD DMA", NULL);
if (r != 0) {
int i;
printk(KERN_ERR "unable to request IRQ for LCD DMA (error %d)\n", r);
for (i = 0; i < dma_chan_count; i++)
free_irq(dma_irq[i], (void *) (i + 1));
return r;
}
return 0;
}
arch_initcall(omap_init_dma);
EXPORT_SYMBOL(omap_set_dma_priority);
EXPORT_SYMBOL(omap_request_dma);
EXPORT_SYMBOL(omap_free_dma);
EXPORT_SYMBOL(omap_start_dma);
......@@ -803,8 +1011,7 @@ EXPORT_SYMBOL(omap_enable_dma_irq);
EXPORT_SYMBOL(omap_disable_dma_irq);
EXPORT_SYMBOL(omap_set_dma_transfer_params);
EXPORT_SYMBOL(omap_set_dma_constant_fill);
EXPORT_SYMBOL(omap_set_dma_transparent_copy);
EXPORT_SYMBOL(omap_set_dma_color_mode);
EXPORT_SYMBOL(omap_set_dma_src_params);
EXPORT_SYMBOL(omap_set_dma_src_index);
......@@ -821,7 +1028,14 @@ EXPORT_SYMBOL(omap_dma_unlink_lch);
EXPORT_SYMBOL(omap_request_lcd_dma);
EXPORT_SYMBOL(omap_free_lcd_dma);
EXPORT_SYMBOL(omap_start_lcd_dma);
EXPORT_SYMBOL(omap_enable_lcd_dma);
EXPORT_SYMBOL(omap_setup_lcd_dma);
EXPORT_SYMBOL(omap_stop_lcd_dma);
EXPORT_SYMBOL(omap_set_lcd_dma_b1);
EXPORT_SYMBOL(omap_set_lcd_dma_single_transfer);
EXPORT_SYMBOL(omap_set_lcd_dma_ext_controller);
EXPORT_SYMBOL(omap_set_lcd_dma_b1_rotation);
EXPORT_SYMBOL(omap_set_lcd_dma_b1_vxres);
EXPORT_SYMBOL(omap_set_lcd_dma_b1_scale);
EXPORT_SYMBOL(omap_set_lcd_dma_b1_mirror);
......@@ -94,7 +94,7 @@ struct gpio_bank {
#define METHOD_GPIO_1610 2
#define METHOD_GPIO_730 3
#if defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP1710) || defined(CONFIG_ARCH_OMAP5912)
#if defined(CONFIG_ARCH_OMAP16XX)
static struct gpio_bank gpio_bank_1610[5] = {
{ OMAP_MPUIO_BASE, INT_MPUIO, IH_MPUIO_BASE, METHOD_MPUIO},
{ OMAP1610_GPIO1_BASE, INT_GPIO_BANK1, IH_GPIO_BASE, METHOD_GPIO_1610 },
......@@ -135,8 +135,8 @@ static inline struct gpio_bank *get_gpio_bank(int gpio)
return &gpio_bank[1];
}
#endif
#if defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP1710) || defined(CONFIG_ARCH_OMAP5912)
if (cpu_is_omap1610() || cpu_is_omap1710() || cpu_is_omap5912()) {
#if defined(CONFIG_ARCH_OMAP16XX)
if (cpu_is_omap16xx()) {
if (OMAP_GPIO_IS_MPUIO(gpio))
return &gpio_bank[0];
return &gpio_bank[1 + (gpio >> 4)];
......@@ -172,8 +172,8 @@ static inline int gpio_valid(int gpio)
if (cpu_is_omap1510() && gpio < 16)
return 0;
#endif
#if defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP1710) || defined(CONFIG_ARCH_OMAP5912)
if ((cpu_is_omap1610() || cpu_is_omap1710() || cpu_is_omap5912()) && gpio < 64)
#if defined(CONFIG_ARCH_OMAP16XX)
if ((cpu_is_omap16xx()) && gpio < 64)
return 0;
#endif
#ifdef CONFIG_ARCH_OMAP730
......@@ -554,7 +554,7 @@ static void gpio_irq_handler(unsigned int irq, struct irqdesc *desc,
if (bank->method == METHOD_GPIO_1510)
isr_reg = bank->base + OMAP1510_GPIO_INT_STATUS;
#endif
#if defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP1710) || defined(CONFIG_ARCH_OMAP5912)
#if defined(CONFIG_ARCH_OMAP16XX)
if (bank->method == METHOD_GPIO_1610)
isr_reg = bank->base + OMAP1610_GPIO_IRQSTATUS1;
#endif
......@@ -588,7 +588,7 @@ static void gpio_ack_irq(unsigned int irq)
if (bank->method == METHOD_GPIO_1510)
__raw_writew(1 << (gpio & 0x0f), bank->base + OMAP1510_GPIO_INT_STATUS);
#endif
#if defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP1710) || defined(CONFIG_ARCH_OMAP5912)
#if defined(CONFIG_ARCH_OMAP16XX)
if (bank->method == METHOD_GPIO_1610)
__raw_writew(1 << (gpio & 0x0f), bank->base + OMAP1610_GPIO_IRQSTATUS1);
#endif
......@@ -668,8 +668,8 @@ static int __init _omap_gpio_init(void)
gpio_bank = gpio_bank_1510;
}
#endif
#if defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP1710) || defined(CONFIG_ARCH_OMAP5912)
if (cpu_is_omap1610() || cpu_is_omap1710() || cpu_is_omap5912()) {
#if defined(CONFIG_ARCH_OMAP16XX)
if (cpu_is_omap16xx()) {
int rev;
gpio_bank_count = 5;
......@@ -702,7 +702,7 @@ static int __init _omap_gpio_init(void)
__raw_writew(0x0000, bank->base + OMAP1510_GPIO_INT_STATUS);
}
#endif
#if defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP1710) || defined(CONFIG_ARCH_OMAP5912)
#if defined(CONFIG_ARCH_OMAP16XX)
if (bank->method == METHOD_GPIO_1610) {
__raw_writew(0x0000, bank->base + OMAP1610_GPIO_IRQENABLE1);
__raw_writew(0xffff, bank->base + OMAP1610_GPIO_IRQSTATUS1);
......@@ -722,7 +722,7 @@ static int __init _omap_gpio_init(void)
set_irq_chip(j, &mpuio_irq_chip);
else
set_irq_chip(j, &gpio_irq_chip);
set_irq_handler(j, do_level_IRQ);
set_irq_handler(j, do_edge_IRQ);
set_irq_flags(j, IRQF_VALID);
}
set_irq_chained_handler(bank->irq, gpio_irq_handler);
......
......@@ -140,12 +140,11 @@ static struct omap_irq_bank omap1510_irq_banks[] = {
};
#endif
#if defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP5912) \
|| defined(CONFIG_ARCH_OMAP1710)
#if defined(CONFIG_ARCH_OMAP16XX)
static struct omap_irq_bank omap1610_irq_banks[] = {
{ .base_reg = OMAP_IH1_BASE, .trigger_map = 0xb3fefe8f },
{ .base_reg = OMAP_IH2_BASE, .trigger_map = 0xfffff7ff },
{ .base_reg = OMAP_IH2_BASE, .trigger_map = 0xfdb7c1fd },
{ .base_reg = OMAP_IH2_BASE + 0x100, .trigger_map = 0xfffff7ff },
{ .base_reg = OMAP_IH2_BASE + 0x200, .trigger_map = 0xffffffff },
};
......@@ -173,9 +172,8 @@ void __init omap_init_irq(void)
irq_bank_count = ARRAY_SIZE(omap1510_irq_banks);
}
#endif
#if defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP5912) \
|| defined(CONFIG_ARCH_OMAP1710)
if (cpu_is_omap1610() || cpu_is_omap5912() || cpu_is_omap1710()) {
#if defined(CONFIG_ARCH_OMAP16XX)
if (cpu_is_omap16xx()) {
irq_banks = omap1610_irq_banks;
irq_bank_count = ARRAY_SIZE(omap1610_irq_banks);
}
......
......@@ -18,6 +18,7 @@
#include <linux/wait.h>
#include <linux/completion.h>
#include <linux/interrupt.h>
#include <linux/err.h>
#include <asm/delay.h>
#include <asm/io.h>
......@@ -28,6 +29,8 @@
#include <asm/arch/irqs.h>
#include <asm/arch/mcbsp.h>
#include <asm/hardware/clock.h>
#ifdef CONFIG_MCBSP_DEBUG
#define DBG(x...) printk(x)
#else
......@@ -61,6 +64,8 @@ struct omap_mcbsp {
};
static struct omap_mcbsp mcbsp[OMAP_MAX_MCBSP_COUNT];
static struct clk *mcbsp_dsp_ck = 0;
static struct clk *mcbsp_api_ck = 0;
static void omap_mcbsp_dump_reg(u8 id)
......@@ -153,8 +158,8 @@ void omap_mcbsp_config(unsigned int id, const struct omap_mcbsp_reg_cfg * config
OMAP_MCBSP_WRITE(io_base, XCR1, config->xcr1);
OMAP_MCBSP_WRITE(io_base, SRGR2, config->srgr2);
OMAP_MCBSP_WRITE(io_base, SRGR1, config->srgr1);
OMAP_MCBSP_WRITE(io_base, SRGR2, config->mcr2);
OMAP_MCBSP_WRITE(io_base, SRGR1, config->mcr1);
OMAP_MCBSP_WRITE(io_base, MCR2, config->mcr2);
OMAP_MCBSP_WRITE(io_base, MCR1, config->mcr1);
OMAP_MCBSP_WRITE(io_base, PCR0, config->pcr0);
}
......@@ -181,6 +186,7 @@ static int omap_mcbsp_check(unsigned int id)
return -1;
}
#define EN_XORPCK 1
#define DSP_RSTCT2 0xe1008014
static void omap_mcbsp_dsp_request(void)
......@@ -188,10 +194,8 @@ static void omap_mcbsp_dsp_request(void)
if (cpu_is_omap1510() || cpu_is_omap1610() || cpu_is_omap1710()) {
omap_writew((omap_readw(ARM_RSTCT1) | (1 << 1) | (1 << 2)),
ARM_RSTCT1);
omap_writew((omap_readw(ARM_CKCTL) | 1 << EN_DSPCK),
ARM_CKCTL);
omap_writew((omap_readw(ARM_IDLECT2) | (1 << EN_APICK)),
ARM_IDLECT2);
clk_enable(mcbsp_dsp_ck);
clk_enable(mcbsp_api_ck);
/* enable 12MHz clock to mcbsp 1 & 3 */
__raw_writew(__raw_readw(DSP_IDLECT2) | (1 << EN_XORPCK),
......@@ -588,7 +592,7 @@ static const struct omap_mcbsp_info mcbsp_1510[] = {
};
#endif
#if defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP1710)
#if defined(CONFIG_ARCH_OMAP16XX)
static const struct omap_mcbsp_info mcbsp_1610[] = {
[0] = { .virt_base = OMAP1610_MCBSP1_BASE,
.dma_rx_sync = OMAP_DMA_MCBSP1_RX,
......@@ -614,6 +618,18 @@ static int __init omap_mcbsp_init(void)
static const struct omap_mcbsp_info *mcbsp_info;
printk("Initializing OMAP McBSP system\n");
mcbsp_dsp_ck = clk_get(0, "dsp_ck");
if (IS_ERR(mcbsp_dsp_ck)) {
printk(KERN_ERR "mcbsp: could not acquire dsp_ck handle.\n");
return PTR_ERR(mcbsp_dsp_ck);
}
mcbsp_api_ck = clk_get(0, "api_ck");
if (IS_ERR(mcbsp_dsp_ck)) {
printk(KERN_ERR "mcbsp: could not acquire api_ck handle.\n");
return PTR_ERR(mcbsp_api_ck);
}
#ifdef CONFIG_ARCH_OMAP730
if (cpu_is_omap730()) {
mcbsp_info = mcbsp_730;
......@@ -626,7 +642,7 @@ static int __init omap_mcbsp_init(void)
mcbsp_count = ARRAY_SIZE(mcbsp_1510);
}
#endif
#if defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP1710)
#if defined(CONFIG_ARCH_OMAP16XX)
if (cpu_is_omap1610() || cpu_is_omap1710()) {
mcbsp_info = mcbsp_1610;
mcbsp_count = ARRAY_SIZE(mcbsp_1610);
......
......@@ -32,18 +32,26 @@
#define __MUX_C__
#include <asm/arch/mux.h>
#ifdef CONFIG_OMAP_MUX
/*
* Sets the Omap MUX and PULL_DWN registers based on the table
*/
int omap_cfg_reg(const reg_cfg_t reg_cfg)
int __init_or_module
omap_cfg_reg(const reg_cfg_t reg_cfg)
{
#ifdef CONFIG_OMAP_MUX
static spinlock_t mux_spin_lock = SPIN_LOCK_UNLOCKED;
unsigned long flags;
reg_cfg_set *cfg;
unsigned int reg_orig = 0, reg = 0, pu_pd_orig = 0, pu_pd = 0,
pull_orig = 0, pull = 0;
unsigned int mask, warn = 0;
if (reg_cfg > ARRAY_SIZE(reg_cfg_table)) {
printk(KERN_ERR "MUX: reg_cfg %d\n", reg_cfg);
return -EINVAL;
}
cfg = &reg_cfg_table[reg_cfg];
......@@ -56,12 +64,20 @@ int omap_cfg_reg(const reg_cfg_t reg_cfg)
/* Check the mux register in question */
if (cfg->mux_reg) {
unsigned tmp1, tmp2;
reg_orig = omap_readl(cfg->mux_reg);
/* The mux registers always seem to be 3 bits long */
reg = reg_orig & ~(0x7 << cfg->mask_offset);
mask = (0x7 << cfg->mask_offset);
tmp1 = reg_orig & mask;
reg = reg_orig & ~mask;
tmp2 = (cfg->mask << cfg->mask_offset);
reg |= tmp2;
reg |= (cfg->mask << cfg->mask_offset);
if (tmp1 != tmp2)
warn = 1;
omap_writel(reg, cfg->mux_reg);
}
......@@ -70,12 +86,18 @@ int omap_cfg_reg(const reg_cfg_t reg_cfg)
if (!cpu_is_omap1510()) {
if (cfg->pu_pd_reg && cfg->pull_val) {
pu_pd_orig = omap_readl(cfg->pu_pd_reg);
mask = 1 << cfg->pull_bit;
if (cfg->pu_pd_val) {
if (!(pu_pd_orig & mask))
warn = 1;
/* Use pull up */
pu_pd = pu_pd_orig | (1 << cfg->pull_bit);
pu_pd = pu_pd_orig | mask;
} else {
if (pu_pd_orig & mask)
warn = 1;
/* Use pull down */
pu_pd = pu_pd_orig & ~(1 << cfg->pull_bit);
pu_pd = pu_pd_orig & ~mask;
}
omap_writel(pu_pd, cfg->pu_pd_reg);
}
......@@ -84,21 +106,32 @@ int omap_cfg_reg(const reg_cfg_t reg_cfg)
/* Check for an associated pull down register */
if (cfg->pull_reg) {
pull_orig = omap_readl(cfg->pull_reg);
mask = 1 << cfg->pull_bit;
if (cfg->pull_val) {
if (pull_orig & mask)
warn = 1;
/* Low bit = pull enabled */
pull = pull_orig & ~(1 << cfg->pull_bit);
pull = pull_orig & ~mask;
} else {
if (!(pull_orig & mask))
warn = 1;
/* High bit = pull disabled */
pull = pull_orig | (1 << cfg->pull_bit);
pull = pull_orig | mask;
}
omap_writel(pull, cfg->pull_reg);
}
if (warn) {
#ifdef CONFIG_OMAP_MUX_WARNINGS
printk(KERN_WARNING "MUX: initialized %s\n", cfg->name);
#endif
}
#ifdef CONFIG_OMAP_MUX_DEBUG
if (cfg->debug) {
printk("Omap: Setting register %s\n", cfg->name);
if (cfg->debug || warn) {
printk("MUX: Setting register %s\n", cfg->name);
printk(" %s (0x%08x) = 0x%08x -> 0x%08x\n",
cfg->mux_reg_name, cfg->mux_reg, reg_orig, reg);
......@@ -118,8 +151,13 @@ int omap_cfg_reg(const reg_cfg_t reg_cfg)
spin_unlock_irqrestore(&mux_spin_lock, flags);
#endif
#ifdef CONFIG_OMAP_MUX_ERRORS
return warn ? -ETXTBSY : 0;
#else
return 0;
#endif
}
EXPORT_SYMBOL(omap_cfg_reg);
#endif /* CONFIG_OMAP_MUX */
......@@ -59,20 +59,12 @@ int ocpi_enable(void)
/* Make sure there's clock for OCPI */
#if defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP1710)
#if defined(CONFIG_ARCH_OMAP16XX)
if (cpu_is_omap1610() || cpu_is_omap1710()) {
val = omap_readl(OMAP1610_ARM_IDLECT3);
val = omap_readl(OMAP16XX_ARM_IDLECT3);
val |= EN_OCPI_CK;
val &= ~IDLOCPI_ARM;
omap_writel(val, OMAP1610_ARM_IDLECT3);
}
#endif
#ifdef CONFIG_ARCH_OMAP5912
if (cpu_is_omap5912()) {
val = omap_readl(OMAP5912_ARM_IDLECT3);
val |= EN_OCPI_CK;
val &= ~IDLOCPI_ARM;
omap_writel(val, OMAP5912_ARM_IDLECT3);
omap_writel(val, OMAP16XX_ARM_IDLECT3);
}
#endif
/* Enable access for OHCI in OCPI */
......
/*
* linux/arch/arm/mach-omap/pm.c
*
* OMAP Power Management Routines
*
* Original code for the SA11x0:
* Copyright (c) 2001 Cliff Brake <cbrake@accelent.com>
*
* Modified for the PXA250 by Nicolas Pitre:
* Copyright (c) 2002 Monta Vista Software, Inc.
*
* Modified for the OMAP1510 by David Singleton:
* Copyright (c) 2002 Monta Vista Software, Inc.
*
* Cleanup 2004 for OMAP1510/1610 by Dirk Behme <dirk.behme@de.bosch.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
* NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/pm.h>
#include <linux/sched.h>
#include <linux/proc_fs.h>
#include <linux/pm.h>
#include <asm/io.h>
#include <asm/mach-types.h>
#include <asm/arch/omap16xx.h>
#include <asm/arch/pm.h>
#include <asm/arch/mux.h>
#include <asm/arch/tps65010.h>
#include "clock.h"
static unsigned int arm_sleep_save[ARM_SLEEP_SAVE_SIZE];
static unsigned short ulpd_sleep_save[ULPD_SLEEP_SAVE_SIZE];
static unsigned int mpui1510_sleep_save[MPUI1510_SLEEP_SAVE_SIZE];
static unsigned int mpui1610_sleep_save[MPUI1610_SLEEP_SAVE_SIZE];
/*
* Let's power down on idle, but only if we are really
* idle, because once we start down the path of
* going idle we continue to do idle even if we get
* a clock tick interrupt . .
*/
void omap_pm_idle(void)
{
int (*func_ptr)(void) = 0;
unsigned int mask32 = 0;
/*
* If the DSP is being used let's just idle the CPU, the overhead
* to wake up from Big Sleep is big, milliseconds versus micro
* seconds for wait for interrupt.
*/
local_irq_disable();
local_fiq_disable();
if (need_resched()) {
local_fiq_enable();
local_irq_enable();
return;
}
mask32 = omap_readl(ARM_SYSST);
local_fiq_enable();
local_irq_enable();
if ((mask32 & DSP_IDLE) == 0) {
__asm__ volatile ("mcr p15, 0, r0, c7, c0, 4");
} else {
if (cpu_is_omap1510()) {
func_ptr = (void *)(OMAP1510_SRAM_IDLE_SUSPEND);
} else if (cpu_is_omap1610() || cpu_is_omap1710()) {
func_ptr = (void *)(OMAP1610_SRAM_IDLE_SUSPEND);
} else if (cpu_is_omap5912()) {
func_ptr = (void *)(OMAP5912_SRAM_IDLE_SUSPEND);
}
func_ptr();
}
}
/*
* Configuration of the wakeup event is board specific. For the
* moment we put it into this helper function. Later it may move
* to board specific files.
*/
static void omap_pm_wakeup_setup(void)
{
/*
* Enable ARM XOR clock and release peripheral from reset by
* writing 1 to PER_EN bit in ARM_RSTCT2, this is required
* for UART configuration to use UART2 to wake up.
*/
omap_writel(omap_readl(ARM_IDLECT2) | ENABLE_XORCLK, ARM_IDLECT2);
omap_writel(omap_readl(ARM_RSTCT2) | PER_EN, ARM_RSTCT2);
omap_writew(MODEM_32K_EN, ULPD_CLOCK_CTRL);
/*
* Turn off all interrupts except L1-2nd level cascade,
* and the L2 wakeup interrupts: keypad and UART2.
*/
omap_writel(~IRQ_LEVEL2, OMAP_IH1_MIR);
if (cpu_is_omap1510()) {
omap_writel(~(IRQ_UART2 | IRQ_KEYBOARD), OMAP_IH2_MIR);
}
if (cpu_is_omap16xx()) {
omap_writel(~(IRQ_UART2 | IRQ_KEYBOARD), OMAP_IH2_0_MIR);
omap_writel(~0x0, OMAP_IH2_1_MIR);
omap_writel(~0x0, OMAP_IH2_2_MIR);
omap_writel(~0x0, OMAP_IH2_3_MIR);
}
/* New IRQ agreement */
omap_writel(1, OMAP_IH1_CONTROL);
/* external PULL to down, bit 22 = 0 */
omap_writel(omap_readl(PULL_DWN_CTRL_2) & ~(1<<22), PULL_DWN_CTRL_2);
}
void omap_pm_suspend(void)
{
unsigned int mask32 = 0;
unsigned long arg0 = 0, arg1 = 0;
int (*func_ptr)(unsigned short, unsigned short) = 0;
unsigned short save_dsp_idlect2;
printk("PM: OMAP%x is entering deep sleep now ...\n", system_rev);
if (machine_is_omap_osk()) {
/* Stop LED1 (D9) blink */
tps65010_set_led(LED1, OFF);
}
/*
* Step 1: turn off interrupts
*/
local_irq_disable();
local_fiq_disable();
/*
* Step 2: save registers
*
* The omap is a strange/beautiful device. The caches, memory
* and register state are preserved across power saves.
* We have to save and restore very little register state to
* idle the omap.
*
* Save interrupt, MPUI, ARM and UPLD control registers.
*/
if (cpu_is_omap1510()) {
MPUI1510_SAVE(OMAP_IH1_MIR);
MPUI1510_SAVE(OMAP_IH2_MIR);
MPUI1510_SAVE(MPUI_CTRL);
MPUI1510_SAVE(MPUI_DSP_BOOT_CONFIG);
MPUI1510_SAVE(MPUI_DSP_API_CONFIG);
MPUI1510_SAVE(EMIFS_CONFIG);
MPUI1510_SAVE(EMIFF_SDRAM_CONFIG);
} else if (cpu_is_omap16xx()) {
MPUI1610_SAVE(OMAP_IH1_MIR);
MPUI1610_SAVE(OMAP_IH2_0_MIR);
MPUI1610_SAVE(OMAP_IH2_1_MIR);
MPUI1610_SAVE(OMAP_IH2_2_MIR);
MPUI1610_SAVE(OMAP_IH2_3_MIR);
MPUI1610_SAVE(MPUI_CTRL);
MPUI1610_SAVE(MPUI_DSP_BOOT_CONFIG);
MPUI1610_SAVE(MPUI_DSP_API_CONFIG);
MPUI1610_SAVE(EMIFS_CONFIG);
MPUI1610_SAVE(EMIFF_SDRAM_CONFIG);
}
ARM_SAVE(ARM_CKCTL);
ARM_SAVE(ARM_IDLECT1);
ARM_SAVE(ARM_IDLECT2);
ARM_SAVE(ARM_EWUPCT);
ARM_SAVE(ARM_RSTCT1);
ARM_SAVE(ARM_RSTCT2);
ARM_SAVE(ARM_SYSST);
ULPD_SAVE(ULPD_CLOCK_CTRL);
ULPD_SAVE(ULPD_STATUS_REQ);
/*
* Step 3: LOW_PWR signal enabling
*
* Allow the LOW_PWR signal to be visible on MPUIO5 ball.
*/
if (cpu_is_omap1510()) {
/* POWER_CTRL_REG = 0x1 (LOW_POWER is available) */
omap_writew(omap_readw(ULPD_POWER_CTRL) |
OMAP1510_ULPD_LOW_POWER_REQ, ULPD_POWER_CTRL);
} else if (cpu_is_omap16xx()) {
/* POWER_CTRL_REG = 0x1 (LOW_POWER is available) */
omap_writew(omap_readw(ULPD_POWER_CTRL) |
OMAP1610_ULPD_LOW_POWER_REQ, ULPD_POWER_CTRL);
}
/* configure LOW_PWR pin */
omap_cfg_reg(T20_1610_LOW_PWR);
/*
* Step 4: OMAP DSP Shutdown
*/
/* Set DSP_RST = 1 and DSP_EN = 0, put DSP block into reset */
omap_writel((omap_readl(ARM_RSTCT1) | DSP_RST) & ~DSP_ENABLE,
ARM_RSTCT1);
/* Set DSP boot mode to DSP-IDLE, DSP_BOOT_MODE = 0x2 */
omap_writel(DSP_IDLE_MODE, MPUI_DSP_BOOT_CONFIG);
/* Set EN_DSPCK = 0, stop DSP block clock */
omap_writel(omap_readl(ARM_CKCTL) & ~DSP_CLOCK_ENABLE, ARM_CKCTL);
/* Stop any DSP domain clocks */
omap_writel(omap_readl(ARM_IDLECT2) | (1<<EN_APICK), ARM_IDLECT2);
save_dsp_idlect2 = __raw_readw(DSP_IDLECT2);
__raw_writew(0, DSP_IDLECT2);
/*
* Step 5: Wakeup Event Setup
*/
omap_pm_wakeup_setup();
/*
* Step 6a: ARM and Traffic controller shutdown
*
* Step 6 starts here with clock and watchdog disable
*/
/* stop clocks */
mask32 = omap_readl(ARM_IDLECT2);
mask32 &= ~(1<<EN_WDTCK); /* bit 0 -> 0 (WDT clock) */
mask32 |= (1<<EN_XORPCK); /* bit 1 -> 1 (XORPCK clock) */
mask32 &= ~(1<<EN_PERCK); /* bit 2 -> 0 (MPUPER_CK clock) */
mask32 &= ~(1<<EN_LCDCK); /* bit 3 -> 0 (LCDC clock) */
mask32 &= ~(1<<EN_LBCK); /* bit 4 -> 0 (local bus clock) */
mask32 |= (1<<EN_APICK); /* bit 6 -> 1 (MPUI clock) */
mask32 &= ~(1<<EN_TIMCK); /* bit 7 -> 0 (MPU timer clock) */
mask32 &= ~(1<<DMACK_REQ); /* bit 8 -> 0 (DMAC clock) */
mask32 &= ~(1<<EN_GPIOCK); /* bit 9 -> 0 (GPIO clock) */
omap_writel(mask32, ARM_IDLECT2);
/* disable ARM watchdog */
omap_writel(0x00F5, OMAP_WDT_TIMER_MODE);
omap_writel(0x00A0, OMAP_WDT_TIMER_MODE);
/*
* Step 6b: ARM and Traffic controller shutdown
*
* Step 6 continues here. Prepare jump to power management
* assembly code in internal SRAM.
*
* Since the omap_cpu_suspend routine has been copied to
* SRAM, we'll do an indirect procedure call to it and pass the
* contents of arm_idlect1 and arm_idlect2 so it can restore
* them when it wakes up and it will return.
*/
arg0 = arm_sleep_save[ARM_SLEEP_SAVE_ARM_IDLECT1];
arg1 = arm_sleep_save[ARM_SLEEP_SAVE_ARM_IDLECT2];
if (cpu_is_omap1510()) {
func_ptr = (void *)(OMAP1510_SRAM_API_SUSPEND);
} else if (cpu_is_omap1610() || cpu_is_omap1710()) {
func_ptr = (void *)(OMAP1610_SRAM_API_SUSPEND);
} else if (cpu_is_omap5912()) {
func_ptr = (void *)(OMAP5912_SRAM_API_SUSPEND);
}
/*
* Step 6c: ARM and Traffic controller shutdown
*
* Jump to assembly code. The processor will stay there
* until wake up.
*/
func_ptr(arg0, arg1);
/*
* If we are here, processor is woken up!
*/
if (cpu_is_omap1510()) {
/* POWER_CTRL_REG = 0x0 (LOW_POWER is disabled) */
omap_writew(omap_readw(ULPD_POWER_CTRL) &
~OMAP1510_ULPD_LOW_POWER_REQ, ULPD_POWER_CTRL);
} else if (cpu_is_omap16xx()) {
/* POWER_CTRL_REG = 0x0 (LOW_POWER is disabled) */
omap_writew(omap_readw(ULPD_POWER_CTRL) &
~OMAP1610_ULPD_LOW_POWER_REQ, ULPD_POWER_CTRL);
}
/* Restore DSP clocks */
omap_writel(omap_readl(ARM_IDLECT2) | (1<<EN_APICK), ARM_IDLECT2);
__raw_writew(save_dsp_idlect2, DSP_IDLECT2);
ARM_RESTORE(ARM_IDLECT2);
/*
* Restore ARM state, except ARM_IDLECT1/2 which omap_cpu_suspend did
*/
ARM_RESTORE(ARM_CKCTL);
ARM_RESTORE(ARM_EWUPCT);
ARM_RESTORE(ARM_RSTCT1);
ARM_RESTORE(ARM_RSTCT2);
ARM_RESTORE(ARM_SYSST);
ULPD_RESTORE(ULPD_CLOCK_CTRL);
ULPD_RESTORE(ULPD_STATUS_REQ);
if (cpu_is_omap1510()) {
MPUI1510_RESTORE(MPUI_CTRL);
MPUI1510_RESTORE(MPUI_DSP_BOOT_CONFIG);
MPUI1510_RESTORE(MPUI_DSP_API_CONFIG);
MPUI1510_RESTORE(EMIFS_CONFIG);
MPUI1510_RESTORE(EMIFF_SDRAM_CONFIG);
MPUI1510_RESTORE(OMAP_IH1_MIR);
MPUI1510_RESTORE(OMAP_IH2_MIR);
} else if (cpu_is_omap16xx()) {
MPUI1610_RESTORE(MPUI_CTRL);
MPUI1610_RESTORE(MPUI_DSP_BOOT_CONFIG);
MPUI1610_RESTORE(MPUI_DSP_API_CONFIG);
MPUI1610_RESTORE(EMIFS_CONFIG);
MPUI1610_RESTORE(EMIFF_SDRAM_CONFIG);
MPUI1610_RESTORE(OMAP_IH1_MIR);
MPUI1610_RESTORE(OMAP_IH2_0_MIR);
MPUI1610_RESTORE(OMAP_IH2_1_MIR);
MPUI1610_RESTORE(OMAP_IH2_2_MIR);
MPUI1610_RESTORE(OMAP_IH2_3_MIR);
}
/*
* Reenable interrupts
*/
local_irq_enable();
local_fiq_enable();
printk("PM: OMAP%x is re-starting from deep sleep...\n", system_rev);
if (machine_is_omap_osk()) {
/* Let LED1 (D9) blink again */
tps65010_set_led(LED1, BLINK);
}
}
#if defined(DEBUG) && defined(CONFIG_PROC_FS)
static int g_read_completed;
/*
* Read system PM registers for debugging
*/
static int omap_pm_read_proc(
char *page_buffer,
char **my_first_byte,
off_t virtual_start,
int length,
int *eof,
void *data)
{
int my_buffer_offset = 0;
char * const my_base = page_buffer;
ARM_SAVE(ARM_CKCTL);
ARM_SAVE(ARM_IDLECT1);
ARM_SAVE(ARM_IDLECT2);
ARM_SAVE(ARM_EWUPCT);
ARM_SAVE(ARM_RSTCT1);
ARM_SAVE(ARM_RSTCT2);
ARM_SAVE(ARM_SYSST);
ULPD_SAVE(ULPD_IT_STATUS);
ULPD_SAVE(ULPD_CLOCK_CTRL);
ULPD_SAVE(ULPD_SOFT_REQ);
ULPD_SAVE(ULPD_STATUS_REQ);
ULPD_SAVE(ULPD_DPLL_CTRL);
ULPD_SAVE(ULPD_POWER_CTRL);
if (cpu_is_omap1510()) {
MPUI1510_SAVE(MPUI_CTRL);
MPUI1510_SAVE(MPUI_DSP_STATUS);
MPUI1510_SAVE(MPUI_DSP_BOOT_CONFIG);
MPUI1510_SAVE(MPUI_DSP_API_CONFIG);
MPUI1510_SAVE(EMIFF_SDRAM_CONFIG);
MPUI1510_SAVE(EMIFS_CONFIG);
} else if (cpu_is_omap16xx()) {
MPUI1610_SAVE(MPUI_CTRL);
MPUI1610_SAVE(MPUI_DSP_STATUS);
MPUI1610_SAVE(MPUI_DSP_BOOT_CONFIG);
MPUI1610_SAVE(MPUI_DSP_API_CONFIG);
MPUI1610_SAVE(EMIFF_SDRAM_CONFIG);
MPUI1610_SAVE(EMIFS_CONFIG);
}
if (virtual_start == 0) {
g_read_completed = 0;
my_buffer_offset += sprintf(my_base + my_buffer_offset,
"ARM_CKCTL_REG: 0x%-8x \n"
"ARM_IDLECT1_REG: 0x%-8x \n"
"ARM_IDLECT2_REG: 0x%-8x \n"
"ARM_EWUPCT_REG: 0x%-8x \n"
"ARM_RSTCT1_REG: 0x%-8x \n"
"ARM_RSTCT2_REG: 0x%-8x \n"
"ARM_SYSST_REG: 0x%-8x \n"
"ULPD_IT_STATUS_REG: 0x%-4x \n"
"ULPD_CLOCK_CTRL_REG: 0x%-4x \n"
"ULPD_SOFT_REQ_REG: 0x%-4x \n"
"ULPD_DPLL_CTRL_REG: 0x%-4x \n"
"ULPD_STATUS_REQ_REG: 0x%-4x \n"
"ULPD_POWER_CTRL_REG: 0x%-4x \n",
ARM_SHOW(ARM_CKCTL),
ARM_SHOW(ARM_IDLECT1),
ARM_SHOW(ARM_IDLECT2),
ARM_SHOW(ARM_EWUPCT),
ARM_SHOW(ARM_RSTCT1),
ARM_SHOW(ARM_RSTCT2),
ARM_SHOW(ARM_SYSST),
ULPD_SHOW(ULPD_IT_STATUS),
ULPD_SHOW(ULPD_CLOCK_CTRL),
ULPD_SHOW(ULPD_SOFT_REQ),
ULPD_SHOW(ULPD_DPLL_CTRL),
ULPD_SHOW(ULPD_STATUS_REQ),
ULPD_SHOW(ULPD_POWER_CTRL));
if (cpu_is_omap1510()) {
my_buffer_offset += sprintf(my_base + my_buffer_offset,
"MPUI1510_CTRL_REG 0x%-8x \n"
"MPUI1510_DSP_STATUS_REG: 0x%-8x \n"
"MPUI1510_DSP_BOOT_CONFIG_REG: 0x%-8x \n"
"MPUI1510_DSP_API_CONFIG_REG: 0x%-8x \n"
"MPUI1510_SDRAM_CONFIG_REG: 0x%-8x \n"
"MPUI1510_EMIFS_CONFIG_REG: 0x%-8x \n",
MPUI1510_SHOW(MPUI_CTRL),
MPUI1510_SHOW(MPUI_DSP_STATUS),
MPUI1510_SHOW(MPUI_DSP_BOOT_CONFIG),
MPUI1510_SHOW(MPUI_DSP_API_CONFIG),
MPUI1510_SHOW(EMIFF_SDRAM_CONFIG),
MPUI1510_SHOW(EMIFS_CONFIG));
} else if (cpu_is_omap16xx()) {
my_buffer_offset += sprintf(my_base + my_buffer_offset,
"MPUI1610_CTRL_REG 0x%-8x \n"
"MPUI1610_DSP_STATUS_REG: 0x%-8x \n"
"MPUI1610_DSP_BOOT_CONFIG_REG: 0x%-8x \n"
"MPUI1610_DSP_API_CONFIG_REG: 0x%-8x \n"
"MPUI1610_SDRAM_CONFIG_REG: 0x%-8x \n"
"MPUI1610_EMIFS_CONFIG_REG: 0x%-8x \n",
MPUI1610_SHOW(MPUI_CTRL),
MPUI1610_SHOW(MPUI_DSP_STATUS),
MPUI1610_SHOW(MPUI_DSP_BOOT_CONFIG),
MPUI1610_SHOW(MPUI_DSP_API_CONFIG),
MPUI1610_SHOW(EMIFF_SDRAM_CONFIG),
MPUI1610_SHOW(EMIFS_CONFIG));
}
g_read_completed++;
} else if (g_read_completed >= 1) {
*eof = 1;
return 0;
}
g_read_completed++;
*my_first_byte = page_buffer;
return my_buffer_offset;
}
static void omap_pm_init_proc(void)
{
struct proc_dir_entry *entry;
entry = create_proc_read_entry("driver/omap_pm",
S_IWUSR | S_IRUGO, NULL,
omap_pm_read_proc, 0);
}
#endif /* DEBUG && CONFIG_PROC_FS */
/*
* omap_pm_prepare - Do preliminary suspend work.
* @state: suspend state we're entering.
*
*/
//#include <asm/arch/hardware.h>
static int omap_pm_prepare(u32 state)
{
int error = 0;
switch (state)
{
case PM_SUSPEND_STANDBY:
case PM_SUSPEND_MEM:
break;
case PM_SUSPEND_DISK:
return -ENOTSUPP;
default:
return -EINVAL;
}
return error;
}
/*
* omap_pm_enter - Actually enter a sleep state.
* @state: State we're entering.
*
*/
static int omap_pm_enter(u32 state)
{
switch (state)
{
case PM_SUSPEND_STANDBY:
case PM_SUSPEND_MEM:
omap_pm_suspend();
break;
case PM_SUSPEND_DISK:
return -ENOTSUPP;
default:
return -EINVAL;
}
return 0;
}
/**
* omap_pm_finish - Finish up suspend sequence.
* @state: State we're coming out of.
*
* This is called after we wake back up (or if entering the sleep state
* failed).
*/
static int omap_pm_finish(u32 state)
{
return 0;
}
struct pm_ops omap_pm_ops ={
.pm_disk_mode = 0,
.prepare = omap_pm_prepare,
.enter = omap_pm_enter,
.finish = omap_pm_finish,
};
static int __init omap_pm_init(void)
{
printk("Power Management for TI OMAP.\n");
pm_idle = omap_pm_idle;
/*
* We copy the assembler sleep/wakeup routines to SRAM.
* These routines need to be in SRAM as that's the only
* memory the MPU can see when it wakes up.
*/
#ifdef CONFIG_ARCH_OMAP1510
if (cpu_is_omap1510()) {
memcpy((void *)OMAP1510_SRAM_IDLE_SUSPEND,
omap1510_idle_loop_suspend,
omap1510_idle_loop_suspend_sz);
memcpy((void *)OMAP1510_SRAM_API_SUSPEND, omap1510_cpu_suspend,
omap1510_cpu_suspend_sz);
} else
#endif
if (cpu_is_omap1610() || cpu_is_omap1710()) {
memcpy((void *)OMAP1610_SRAM_IDLE_SUSPEND,
omap1610_idle_loop_suspend,
omap1610_idle_loop_suspend_sz);
memcpy((void *)OMAP1610_SRAM_API_SUSPEND, omap1610_cpu_suspend,
omap1610_cpu_suspend_sz);
} else if (cpu_is_omap5912()) {
memcpy((void *)OMAP5912_SRAM_IDLE_SUSPEND,
omap1610_idle_loop_suspend,
omap1610_idle_loop_suspend_sz);
memcpy((void *)OMAP5912_SRAM_API_SUSPEND, omap1610_cpu_suspend,
omap1610_cpu_suspend_sz);
}
pm_set_ops(&omap_pm_ops);
#if defined(DEBUG) && defined(CONFIG_PROC_FS)
omap_pm_init_proc();
#endif
return 0;
}
__initcall(omap_pm_init);
/*
* linux/arch/arm/mach-omap/sleep.S
*
* Low-level OMAP1510/1610 sleep/wakeUp support
*
* Initial SA1110 code:
* Copyright (c) 2001 Cliff Brake <cbrake@accelent.com>
*
* Adapted for PXA by Nicolas Pitre:
* Copyright (c) 2002 Monta Vista Software, Inc.
*
* Support for OMAP1510/1610 by Dirk Behme <dirk.behme@de.bosch.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
* NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/config.h>
#include <linux/linkage.h>
#include <asm/assembler.h>
#include <asm/arch/io.h>
#include <asm/arch/pm.h>
.text
/*
* Forces OMAP into idle state
*
* omapXXXX_idle_loop_suspend()
*
* Note: This code get's copied to internal SRAM at boot. When the OMAP
* wakes up it continues execution at the point it went to sleep.
*
* Note: Because of slightly different configuration values we have
* processor specific functions here.
*/
#ifdef CONFIG_ARCH_OMAP1510
ENTRY(omap1510_idle_loop_suspend)
stmfd sp!, {r0 - r12, lr} @ save registers on stack
@ load base address of ARM_IDLECT1 and ARM_IDLECT2
mov r4, #CLKGEN_REG_ASM_BASE & 0xff000000
orr r4, r4, #CLKGEN_REG_ASM_BASE & 0x00ff0000
orr r4, r4, #CLKGEN_REG_ASM_BASE & 0x0000ff00
@ turn off clock domains
@ get ARM_IDLECT2 into r2
ldrh r2, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
mov r5, #OMAP1510_IDLE_CLOCK_DOMAINS & 0xff
orr r5,r5, #OMAP1510_IDLE_CLOCK_DOMAINS & 0xff00
strh r5, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
@ request ARM idle
@ get ARM_IDLECT1 into r1
ldrh r1, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
orr r3, r1, #OMAP1510_IDLE_LOOP_REQUEST & 0xffff
strh r3, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
mov r5, #IDLE_WAIT_CYCLES & 0xff
orr r5, r5, #IDLE_WAIT_CYCLES & 0xff00
l_1510: subs r5, r5, #1
bne l_1510
/*
* Let's wait for the next clock tick to wake us up.
*/
mov r0, #0
mcr p15, 0, r0, c7, c0, 4 @ wait for interrupt
/*
* omap1510_idle_loop_suspend()'s resume point.
*
* It will just start executing here, so we'll restore stuff from the
* stack, reset the ARM_IDLECT1 and ARM_IDLECT2.
*/
@ restore ARM_IDLECT1 and ARM_IDLECT2 and return
@ r1 has ARM_IDLECT1 and r2 still has ARM_IDLECT2
strh r2, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
strh r1, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
ldmfd sp!, {r0 - r12, pc} @ restore regs and return
ENTRY(omap1510_idle_loop_suspend_sz)
.word . - omap1510_idle_loop_suspend
#endif /* CONFIG_ARCH_OMAP1510 */
#if defined(CONFIG_ARCH_OMAP16XX)
ENTRY(omap1610_idle_loop_suspend)
stmfd sp!, {r0 - r12, lr} @ save registers on stack
@ load base address of ARM_IDLECT1 and ARM_IDLECT2
mov r4, #CLKGEN_REG_ASM_BASE & 0xff000000
orr r4, r4, #CLKGEN_REG_ASM_BASE & 0x00ff0000
orr r4, r4, #CLKGEN_REG_ASM_BASE & 0x0000ff00
@ turn off clock domains
@ get ARM_IDLECT2 into r2
ldrh r2, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
mov r5, #OMAP1610_IDLE_CLOCK_DOMAINS & 0xff
orr r5,r5, #OMAP1610_IDLE_CLOCK_DOMAINS & 0xff00
strh r5, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
@ request ARM idle
@ get ARM_IDLECT1 into r1
ldrh r1, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
orr r3, r1, #OMAP1610_IDLE_LOOP_REQUEST & 0xffff
strh r3, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
mov r5, #IDLE_WAIT_CYCLES & 0xff
orr r5, r5, #IDLE_WAIT_CYCLES & 0xff00
l_1610: subs r5, r5, #1
bne l_1610
/*
* Let's wait for the next clock tick to wake us up.
*/
mov r0, #0
mcr p15, 0, r0, c7, c0, 4 @ wait for interrupt
/*
* omap1610_idle_loop_suspend()'s resume point.
*
* It will just start executing here, so we'll restore stuff from the
* stack, reset the ARM_IDLECT1 and ARM_IDLECT2.
*/
@ restore ARM_IDLECT1 and ARM_IDLECT2 and return
@ r1 has ARM_IDLECT1 and r2 still has ARM_IDLECT2
strh r2, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
strh r1, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
ldmfd sp!, {r0 - r12, pc} @ restore regs and return
ENTRY(omap1610_idle_loop_suspend_sz)
.word . - omap1610_idle_loop_suspend
#endif /* CONFIG_ARCH_OMAP16XX */
/*
* Forces OMAP into deep sleep state
*
* omapXXXX_cpu_suspend()
*
* The values of the registers ARM_IDLECT1 and ARM_IDLECT2 are passed
* as arg0 and arg1 from caller. arg0 is stored in register r0 and arg1
* in register r1.
*
* Note: This code get's copied to internal SRAM at boot. When the OMAP
* wakes up it continues execution at the point it went to sleep.
*
* Note: Because of errata work arounds we have processor specific functions
* here. They are mostly the same, but slightly different.
*
*/
#ifdef CONFIG_ARCH_OMAP1510
ENTRY(omap1510_cpu_suspend)
@ save registers on stack
stmfd sp!, {r0 - r12, lr}
@ load base address of Traffic Controller
mov r4, #TCMIF_ASM_BASE & 0xff000000
orr r4, r4, #TCMIF_ASM_BASE & 0x00ff0000
orr r4, r4, #TCMIF_ASM_BASE & 0x0000ff00
@ work around errata of OMAP1510 PDE bit for TC shut down
@ clear PDE bit
ldr r5, [r4, #EMIFS_CONFIG_ASM_OFFSET & 0xff]
bic r5, r5, #PDE_BIT & 0xff
str r5, [r4, #EMIFS_CONFIG_ASM_OFFSET & 0xff]
@ set PWD_EN bit
and r5, r5, #PWD_EN_BIT & 0xff
str r5, [r4, #EMIFS_CONFIG_ASM_OFFSET & 0xff]
@ prepare to put SDRAM into self-refresh manually
ldr r5, [r4, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff]
orr r5, r5, #SELF_REFRESH_MODE & 0xff000000
orr r5, r5, #SELF_REFRESH_MODE & 0x000000ff
str r5, [r4, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff]
@ prepare to put EMIFS to Sleep
ldr r5, [r4, #EMIFS_CONFIG_ASM_OFFSET & 0xff]
orr r5, r5, #IDLE_EMIFS_REQUEST & 0xff
str r5, [r4, #EMIFS_CONFIG_ASM_OFFSET & 0xff]
@ load base address of ARM_IDLECT1 and ARM_IDLECT2
mov r4, #CLKGEN_REG_ASM_BASE & 0xff000000
orr r4, r4, #CLKGEN_REG_ASM_BASE & 0x00ff0000
orr r4, r4, #CLKGEN_REG_ASM_BASE & 0x0000ff00
@ turn off clock domains
mov r5, #OMAP1510_IDLE_CLOCK_DOMAINS & 0xff
orr r5,r5, #OMAP1510_IDLE_CLOCK_DOMAINS & 0xff00
strh r5, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
@ request ARM idle
mov r3, #OMAP1510_DEEP_SLEEP_REQUEST & 0xff
orr r3, r3, #OMAP1510_DEEP_SLEEP_REQUEST & 0xff00
strh r3, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
mov r5, #IDLE_WAIT_CYCLES & 0xff
orr r5, r5, #IDLE_WAIT_CYCLES & 0xff00
l_1510_2:
subs r5, r5, #1
bne l_1510_2
/*
* Let's wait for the next wake up event to wake us up. r0 can't be
* used here because r0 holds ARM_IDLECT1
*/
mov r2, #0
mcr p15, 0, r2, c7, c0, 4 @ wait for interrupt
/*
* omap1510_cpu_suspend()'s resume point.
*
* It will just start executing here, so we'll restore stuff from the
* stack, reset the ARM_IDLECT1 and ARM_IDLECT2.
*/
strh r1, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
strh r0, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
@ restore regs and return
ldmfd sp!, {r0 - r12, pc}
ENTRY(omap1510_cpu_suspend_sz)
.word . - omap1510_cpu_suspend
#endif /* CONFIG_ARCH_OMAP1510 */
#if defined(CONFIG_ARCH_OMAP16XX)
ENTRY(omap1610_cpu_suspend)
@ save registers on stack
stmfd sp!, {r0 - r12, lr}
@ load base address of Traffic Controller
mov r4, #TCMIF_ASM_BASE & 0xff000000
orr r4, r4, #TCMIF_ASM_BASE & 0x00ff0000
orr r4, r4, #TCMIF_ASM_BASE & 0x0000ff00
@ prepare to put SDRAM into self-refresh manually
ldr r5, [r4, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff]
orr r5, r5, #SELF_REFRESH_MODE & 0xff000000
orr r5, r5, #SELF_REFRESH_MODE & 0x000000ff
str r5, [r4, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff]
@ prepare to put EMIFS to Sleep
ldr r5, [r4, #EMIFS_CONFIG_ASM_OFFSET & 0xff]
orr r5, r5, #IDLE_EMIFS_REQUEST & 0xff
str r5, [r4, #EMIFS_CONFIG_ASM_OFFSET & 0xff]
@ load base address of ARM_IDLECT1 and ARM_IDLECT2
mov r4, #CLKGEN_REG_ASM_BASE & 0xff000000
orr r4, r4, #CLKGEN_REG_ASM_BASE & 0x00ff0000
orr r4, r4, #CLKGEN_REG_ASM_BASE & 0x0000ff00
@ turn off clock domains
mov r5, #OMAP1610_IDLE_CLOCK_DOMAINS & 0xff
orr r5,r5, #OMAP1610_IDLE_CLOCK_DOMAINS & 0xff00
strh r5, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
@ work around errata of OMAP1610/5912. Enable (!) peripheral
@ clock to let the chip go into deep sleep
ldrh r5, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
orr r5,r5, #EN_PERCK_BIT & 0xff
strh r5, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
@ request ARM idle
mov r3, #OMAP1610_DEEP_SLEEP_REQUEST & 0xff
orr r3, r3, #OMAP1610_DEEP_SLEEP_REQUEST & 0xff00
strh r3, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
mov r5, #IDLE_WAIT_CYCLES & 0xff
orr r5, r5, #IDLE_WAIT_CYCLES & 0xff00
l_1610_2:
subs r5, r5, #1
bne l_1610_2
/*
* Let's wait for the next wake up event to wake us up. r0 can't be
* used here because r0 holds ARM_IDLECT1
*/
mov r2, #0
mcr p15, 0, r2, c7, c0, 4 @ wait for interrupt
/*
* omap1610_cpu_suspend()'s resume point.
*
* It will just start executing here, so we'll restore stuff from the
* stack, reset the ARM_IDLECT1 and ARM_IDLECT2.
*/
strh r1, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
strh r0, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
@ restore regs and return
ldmfd sp!, {r0 - r12, pc}
ENTRY(omap1610_cpu_suspend_sz)
.word . - omap1610_cpu_suspend
#endif /* CONFIG_ARCH_OMAP16XX */
......@@ -41,7 +41,6 @@
#include <asm/irq.h>
#include <asm/mach/irq.h>
#include <asm/mach/time.h>
#include <asm/arch/clocks.h>
#ifndef __instrument
#define __instrument
......
......@@ -48,8 +48,10 @@
*/
/* TESTED ON:
* - 1611B H2 (with usb1 mini-AB)
* - 1510 Innovator with built-in transceiver (custom cable feeding 5V VBUS)
* - 1611B H2 (with usb1 mini-AB) using standard Mini-B or OTG cables
* - 1510 Innovator UDC with bundled usb0 cable
* - 1510 Innovator OHCI with bundled usb1/usb2 cable
* - 1510 Innovator OHCI with custom usb0 cable, feeding 5V VBUS
* - 1710 custom development board using alternate pin group
*/
......@@ -92,7 +94,10 @@ static u32 __init omap_usb0_init(unsigned nwires, unsigned is_device)
u32 syscon1 = 0;
if (nwires == 0) {
USB_TRANSCEIVER_CTRL_REG &= ~(1 << 3);
if (!cpu_is_omap15xx()) {
/* pulldown D+/D- */
USB_TRANSCEIVER_CTRL_REG &= ~(3 << 1);
}
return 0;
}
......@@ -101,36 +106,30 @@ static u32 __init omap_usb0_init(unsigned nwires, unsigned is_device)
* USB0_VP and USB0_VM are always set on 1510, there's no muxing
* available for them.
*/
if (nwires >= 2 && !cpu_is_omap1510()) {
if (nwires >= 2 && !cpu_is_omap15xx()) {
omap_cfg_reg(AA9_USB0_VP);
omap_cfg_reg(R9_USB0_VM);
}
if (is_device)
omap_cfg_reg(W4_USB_PUEN);
/* internal transceiver */
if (nwires == 2) {
if (cpu_is_omap1510()) {
/* This works for OHCI on 1510-Innovator, nothing to mux */
if (cpu_is_omap15xx()) {
/* This works for OHCI on 1510-Innovator */
return 0;
}
#if 0
/* NOTE: host OR device mode for now, no OTG */
USB_TRANSCEIVER_CTRL_REG &= ~(3 << 4);
USB_TRANSCEIVER_CTRL_REG &= ~(7 << 4);
if (is_device) {
omap_cfg_reg(W4_USB_PUEN);
omap_cfg_reg(R18_1510_USB_GPIO0);
// omap_cfg_reg(USB0_VBUS);
// omap_cfg_reg(USB0_PUEN);
// USB_TRANSCEIVER_CTRL_REG.CONF_USB0_PORT_R = 7
// when USB0_PUEN is needed
} else /* host mode needs D+ and D- pulldowns */
USB_TRANSCEIVER_CTRL_REG &= ~(3 << 1);
return 3 << 16;
#else
/* FIXME: 1610 needs to return the right value here */
printk(KERN_ERR "usb0 internal transceiver, nyet\n");
return 0;
#endif
}
/* alternate pin config, external transceiver */
......@@ -170,7 +169,7 @@ static u32 __init omap_usb1_init(unsigned nwires)
{
u32 syscon1 = 0;
if (nwires != 6)
if (nwires != 6 && !cpu_is_omap15xx())
USB_TRANSCEIVER_CTRL_REG &= ~CONF_USB1_UNI_R;
if (nwires == 0)
return 0;
......@@ -178,11 +177,11 @@ static u32 __init omap_usb1_init(unsigned nwires)
/* external transceiver */
omap_cfg_reg(USB1_TXD);
omap_cfg_reg(USB1_TXEN);
if (cpu_is_omap1510()) {
if (cpu_is_omap15xx()) {
omap_cfg_reg(USB1_SEO);
omap_cfg_reg(USB1_SPEED);
// SUSP
} else if (cpu_is_omap1610() || cpu_is_omap5912() || cpu_is_omap1710()) {
} else if (cpu_is_omap16xx()) {
omap_cfg_reg(W13_1610_USB1_SE0);
omap_cfg_reg(R13_1610_USB1_SPEED);
// SUSP
......@@ -203,7 +202,8 @@ static u32 __init omap_usb1_init(unsigned nwires)
syscon1 = 3;
omap_cfg_reg(USB1_VP);
omap_cfg_reg(USB1_VM);
USB_TRANSCEIVER_CTRL_REG |= CONF_USB1_UNI_R;
if (!cpu_is_omap15xx())
USB_TRANSCEIVER_CTRL_REG |= CONF_USB1_UNI_R;
break;
default:
printk(KERN_ERR "illegal usb%d %d-wire transceiver\n",
......@@ -216,31 +216,32 @@ static u32 __init omap_usb2_init(unsigned nwires, unsigned alt_pingroup)
{
u32 syscon1 = 0;
if (alt_pingroup)
if (alt_pingroup || nwires == 0)
return 0;
if (nwires != 6)
if (nwires != 6 && !cpu_is_omap15xx())
USB_TRANSCEIVER_CTRL_REG &= ~CONF_USB2_UNI_R;
if (nwires == 0)
return 0;
/* external transceiver */
if (cpu_is_omap1510()) {
if (cpu_is_omap15xx()) {
omap_cfg_reg(USB2_TXD);
omap_cfg_reg(USB2_TXEN);
omap_cfg_reg(USB2_SEO);
if (nwires != 3)
omap_cfg_reg(USB2_RCV);
} else if (cpu_is_omap1610() || cpu_is_omap5912() || cpu_is_omap1710()) {
/* there is no USB2_SPEED */
} else if (cpu_is_omap16xx()) {
omap_cfg_reg(V6_USB2_TXD);
omap_cfg_reg(W9_USB2_TXEN);
omap_cfg_reg(W5_USB2_SE0);
if (nwires != 3)
omap_cfg_reg(Y5_USB2_RCV);
// FIXME omap_cfg_reg(USB2_SPEED);
} else {
pr_debug("usb unrecognized\n");
}
// omap_cfg_reg(USB2_SUSP);
// FIXME omap_cfg_reg(USB2_SPEED);
switch (nwires) {
case 3:
......@@ -251,14 +252,14 @@ static u32 __init omap_usb2_init(unsigned nwires, unsigned alt_pingroup)
break;
case 6:
syscon1 = 3;
if (cpu_is_omap1510()) {
if (cpu_is_omap15xx()) {
omap_cfg_reg(USB2_VP);
omap_cfg_reg(USB2_VM);
} else {
omap_cfg_reg(AA9_USB2_VP);
omap_cfg_reg(R9_USB2_VM);
USB_TRANSCEIVER_CTRL_REG |= CONF_USB2_UNI_R;
}
USB_TRANSCEIVER_CTRL_REG |= CONF_USB2_UNI_R;
break;
default:
printk(KERN_ERR "illegal usb%d %d-wire transceiver\n",
......@@ -337,7 +338,7 @@ static struct platform_device ohci_device = {
.dev = {
.release = usb_release,
.dma_mask = &ohci_dmamask,
.coherent_dma_mask = 0x0fffffff,
.coherent_dma_mask = 0xffffffff,
},
.num_resources = ARRAY_SIZE(ohci_resources),
.resource = ohci_resources,
......@@ -375,7 +376,11 @@ static struct platform_device otg_device = {
// FIXME correct answer depends on hmc_mode,
// as does any nonzero value for config->otg port number
#ifdef CONFIG_USB_GADGET_OMAP
#define is_usb0_device(config) 1
#else
#define is_usb0_device(config) 0
#endif
/*-------------------------------------------------------------------------*/
......@@ -420,7 +425,7 @@ omap_otg_init(struct omap_usb_config *config)
if (alt_pingroup)
printk(", usb2 alt %d wires", config->pins[2]);
else if (config->pins[0])
printk(", usb0 %d wires%s", config->pins[2],
printk(", usb0 %d wires%s", config->pins[0],
is_usb0_device(config) ? " (dev)" : "");
if (config->pins[1])
printk(", usb1 %d wires", config->pins[1]);
......@@ -477,6 +482,19 @@ static inline void omap_otg_init(struct omap_usb_config *config) {}
#ifdef CONFIG_ARCH_OMAP1510
#define ULPD_SOFT_REQ_REG __REG16(ULPD_SOFT_REQ)
#define SOFT_UDC_REQ (1 << 4)
#define SOFT_DPLL_REQ (1 << 0)
#define ULPD_DPLL_CTRL_REG __REG16(ULPD_DPLL_CTRL)
#define DPLL_IOB (1 << 13)
#define DPLL_PLL_ENABLE (1 << 4)
#define DPLL_LOCK (1 << 0)
#define ULPD_APLL_CTRL_REG __REG16(ULPD_APLL_CTRL)
#define APLL_NDPLL_SWITCH (1 << 0)
static void __init omap_1510_usb_init(struct omap_usb_config *config)
{
int status;
......@@ -490,16 +508,43 @@ static void __init omap_1510_usb_init(struct omap_usb_config *config)
val |= (config->hmc_mode << 1);
omap_writel(val, MOD_CONF_CTRL_0);
// FIXME this has a UDC controller too
printk("USB: hmc %d", config->hmc_mode);
if (config->pins[0])
printk(", usb0 %d wires%s", config->pins[0],
is_usb0_device(config) ? " (dev)" : "");
if (config->pins[1])
printk(", usb1 %d wires", config->pins[1]);
if (config->pins[2])
printk(", usb2 %d wires", config->pins[2]);
printk("\n");
/* use DPLL for 48 MHz function clock */
pr_debug("APLL %04x DPLL %04x REQ %04x\n", ULPD_APLL_CTRL_REG,
ULPD_DPLL_CTRL_REG, ULPD_SOFT_REQ_REG);
ULPD_APLL_CTRL_REG &= ~APLL_NDPLL_SWITCH;
ULPD_DPLL_CTRL_REG |= DPLL_IOB | DPLL_PLL_ENABLE;
ULPD_SOFT_REQ_REG |= SOFT_UDC_REQ | SOFT_DPLL_REQ;
while (!(ULPD_DPLL_CTRL_REG & DPLL_LOCK))
cpu_relax();
#ifdef CONFIG_USB_GADGET_OMAP
if (config->register_dev) {
udc_device.dev.platform_data = config;
status = platform_device_register(&udc_device);
if (status)
pr_debug("can't register UDC device, %d\n", status);
/* udc driver gates 48MHz by D+ pullup */
}
#endif
#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
if (config->otg || config->register_host) {
if (config->register_host) {
ohci_device.dev.platform_data = config;
status = platform_device_register(&ohci_device);
if (status)
pr_debug("can't register OHCI device, %d\n", status);
/* hcd explicitly gates 48MHz */
}
// FIXME completely untested ...
#endif
}
......@@ -524,12 +569,9 @@ omap_usb_init(void)
}
platform_data = *config;
if (cpu_is_omap730()
|| cpu_is_omap1610()
|| cpu_is_omap1710()
|| cpu_is_omap5912())
if (cpu_is_omap730() || cpu_is_omap16xx())
omap_otg_init(&platform_data);
else if (cpu_is_omap1510())
else if (cpu_is_omap15xx())
omap_1510_usb_init(&platform_data);
else {
printk(KERN_ERR "USB: No init for your chip yet\n");
......
......@@ -72,4 +72,31 @@ config S3C2410_DMA_DEBUG
the CPU time doing so.
config S3C2410_PM_DEBUG
bool "S3C2410 PM Suspend debug"
depends on ARCH_S3C2410 && PM
help
Say Y here if you want verbose debugging from the PM Suspend and
Resume code. See `Documentation/arm/Samsing-S3C24XX/Suspend.txt`
for more information.
config S3C2410_PM_CHECK
bool "S3C2410 PM Suspend Memory CRC"
depends on ARCH_S3C2410 && PM && CRC32
help
Enable the PM code's memory area checksum over sleep. This option
will generate CRCs of all blocks of memory, and store them before
going to sleep. The blocks are then checked on resume for any
errors.
config S3C2410_PM_CHECK_CHUNKSIZE
int "S3C2410 PM Suspend CRC Chunksize (KiB)"
depends on ARCH_S3C2410 && PM && S3C2410_PM_CHECK
default 64
help
Set the chunksize in Kilobytes of the CRC for checking memory
corruption over suspend and resume. A smaller value will mean that
the CRC data block will take more memory, but wil identify any
faults with better precision.
endif
......@@ -15,6 +15,10 @@ obj- :=
obj-$(CONFIG_CPU_S3C2410) += s3c2410.o
obj-$(CONFIG_S3C2410_DMA) += dma.o
# Power Management support
obj-$(CONFIG_PM) += pm.o sleep.o
# S3C2440 support
obj-$(CONFIG_CPU_S3C2440) += s3c2440.o s3c2440-dsc.o
......
......@@ -59,7 +59,7 @@ static DECLARE_MUTEX(clocks_sem);
/* old functions */
void s3c2410_clk_enable(unsigned int clocks, unsigned int enable)
void inline s3c2410_clk_enable(unsigned int clocks, unsigned int enable)
{
unsigned long clkcon;
unsigned long flags;
......@@ -72,11 +72,26 @@ void s3c2410_clk_enable(unsigned int clocks, unsigned int enable)
if (enable)
clkcon |= clocks;
/* ensure none of the special function bits set */
clkcon &= ~(S3C2410_CLKCON_IDLE|S3C2410_CLKCON_POWER);
__raw_writel(clkcon, S3C2410_CLKCON);
local_irq_restore(flags);
}
/* enable and disable calls for use with the clk struct */
static int clk_null_enable(struct clk *clk, int enable)
{
return 0;
}
int s3c2410_clkcon_enable(struct clk *clk, int enable)
{
s3c2410_clk_enable(clk->ctrlbit, enable);
return 0;
}
/* Clock API calls */
......@@ -105,15 +120,16 @@ void clk_put(struct clk *clk)
int clk_enable(struct clk *clk)
{
if (clk->ctrlbit != 0)
s3c2410_clk_enable(clk->ctrlbit, 1);
if (IS_ERR(clk))
return -EINVAL;
return 0;
return (clk->enable)(clk, 1);
}
void clk_disable(struct clk *clk)
{
s3c2410_clk_enable(clk->ctrlbit, 0);
if (!IS_ERR(clk))
(clk->enable)(clk, 0);
}
......@@ -131,8 +147,11 @@ void clk_unuse(struct clk *clk)
unsigned long clk_get_rate(struct clk *clk)
{
if (clk->parent != NULL)
return clk->parent->rate;
if (clk->rate != 0)
return clk->rate;
while (clk->parent != NULL && clk->rate == 0)
clk = clk->parent;
return clk->rate;
}
......@@ -186,67 +205,105 @@ static struct clk clk_p = {
.ctrlbit = 0
};
/* clocks that could be registered by external code */
struct clk s3c24xx_dclk0 = {
.name = "dclk0",
};
struct clk s3c24xx_dclk1 = {
.name = "dclk1",
};
struct clk s3c24xx_clkout0 = {
.name = "clkout1",
};
struct clk s3c24xx_clkout1 = {
.name = "clkout1",
};
struct clk s3c24xx_uclk = {
.name = "uclk",
};
/* clock definitions */
static struct clk init_clocks[] = {
{ .name = "nand",
.parent = &clk_h,
.enable = s3c2410_clkcon_enable,
.ctrlbit = S3C2410_CLKCON_NAND
},
{ .name = "lcd",
.parent = &clk_h,
.enable = s3c2410_clkcon_enable,
.ctrlbit = S3C2410_CLKCON_LCDC
},
{ .name = "usb-host",
.parent = &clk_h,
.enable = s3c2410_clkcon_enable,
.ctrlbit = S3C2410_CLKCON_USBH
},
{ .name = "usb-device",
.parent = &clk_h,
.enable = s3c2410_clkcon_enable,
.ctrlbit = S3C2410_CLKCON_USBD
},
{ .name = "timers",
.parent = &clk_p,
.enable = s3c2410_clkcon_enable,
.ctrlbit = S3C2410_CLKCON_PWMT
},
{ .name = "sdi",
.parent = &clk_p,
.enable = s3c2410_clkcon_enable,
.ctrlbit = S3C2410_CLKCON_SDI
},
{ .name = "uart0",
.parent = &clk_p,
.enable = s3c2410_clkcon_enable,
.ctrlbit = S3C2410_CLKCON_UART0
},
{ .name = "uart1",
.parent = &clk_p,
.enable = s3c2410_clkcon_enable,
.ctrlbit = S3C2410_CLKCON_UART1
},
{ .name = "uart2",
.parent = &clk_p,
.enable = s3c2410_clkcon_enable,
.ctrlbit = S3C2410_CLKCON_UART2
},
{ .name = "gpio",
.parent = &clk_p,
.enable = s3c2410_clkcon_enable,
.ctrlbit = S3C2410_CLKCON_GPIO
},
{ .name = "rtc",
.parent = &clk_p,
.enable = s3c2410_clkcon_enable,
.ctrlbit = S3C2410_CLKCON_RTC
},
{ .name = "adc",
.parent = &clk_p,
.enable = s3c2410_clkcon_enable,
.ctrlbit = S3C2410_CLKCON_ADC
},
{ .name = "i2c",
.parent = &clk_p,
.enable = s3c2410_clkcon_enable,
.ctrlbit = S3C2410_CLKCON_IIC
},
{ .name = "iis",
.parent = &clk_p,
.enable = s3c2410_clkcon_enable,
.ctrlbit = S3C2410_CLKCON_IIS
},
{ .name = "spi",
.parent = &clk_p,
.enable = s3c2410_clkcon_enable,
.ctrlbit = S3C2410_CLKCON_SPI
},
{ .name = "watchdog",
......@@ -262,6 +319,9 @@ int s3c2410_register_clock(struct clk *clk)
clk->owner = THIS_MODULE;
atomic_set(&clk->used, 0);
if (clk->enable == NULL)
clk->enable = clk_null_enable;
/* add to the list of available clocks */
down(&clocks_sem);
......@@ -273,7 +333,7 @@ int s3c2410_register_clock(struct clk *clk)
/* initalise all the clocks */
static int __init s3c2410_init_clocks(void)
int __init s3c2410_init_clocks(void)
{
struct clk *clkp = init_clocks;
int ptr;
......@@ -287,8 +347,25 @@ static int __init s3c2410_init_clocks(void)
clk_p.rate = s3c24xx_pclk;
clk_f.rate = s3c24xx_fclk;
/* set the enabled clocks to a minimal (known) state */
__raw_writel(S3C2410_CLKCON_PWMT | S3C2410_CLKCON_UART0 | S3C2410_CLKCON_UART1 | S3C2410_CLKCON_UART2 | S3C2410_CLKCON_GPIO | S3C2410_CLKCON_RTC, S3C2410_CLKCON);
/* it looks like just setting the register here is not good
* enough, and causes the odd hang at initial boot time, so
* do all of them indivdually.
*
* I think disabling the LCD clock if the LCD is active is
* very dangerous, and therefore the bootloader should be
* careful to not enable the LCD clock if it is not needed.
*
* and of course, this looks neater
*/
s3c2410_clk_enable(S3C2410_CLKCON_NAND, 0);
s3c2410_clk_enable(S3C2410_CLKCON_USBH, 0);
s3c2410_clk_enable(S3C2410_CLKCON_USBD, 0);
s3c2410_clk_enable(S3C2410_CLKCON_ADC, 0);
s3c2410_clk_enable(S3C2410_CLKCON_IIC, 0);
s3c2410_clk_enable(S3C2410_CLKCON_SPI, 0);
/* assume uart clocks are correctly setup */
/* register our clocks */
......@@ -312,5 +389,4 @@ static int __init s3c2410_init_clocks(void)
return 0;
}
arch_initcall(s3c2410_init_clocks);
......@@ -2,7 +2,7 @@
* linux/arch/arm/mach-s3c2410/clock.h
*
* Copyright (c) 2004 Simtec Electronics
* Written by Ben Dooks, <ben@simtec.co.uk>
* Written by 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
......@@ -17,11 +17,30 @@ struct clk {
atomic_t used;
unsigned long rate;
unsigned long ctrlbit;
int (*enable)(struct clk *, int enable);
};
/* other clocks which may be registered by board support */
extern struct clk s3c24xx_dclk0;
extern struct clk s3c24xx_dclk1;
extern struct clk s3c24xx_clkout0;
extern struct clk s3c24xx_clkout1;
extern struct clk s3c24xx_uclk;
/* processor clock settings, in Hz */
extern unsigned long s3c24xx_xtal;
extern unsigned long s3c24xx_pclk;
extern unsigned long s3c24xx_hclk;
extern unsigned long s3c24xx_fclk;
/* exports for arch/arm/mach-s3c2410
*
* Please DO NOT use these outside of arch/arm/mach-s3c2410
*/
extern int s3c2410_clkcon_enable(struct clk *clk, int enable);
extern int s3c2410_register_clock(struct clk *clk);
extern int s3c2410_init_clocks(void);
......@@ -38,6 +38,7 @@
#include <asm/arch/regs-gpio.h>
#include "cpu.h"
#include "clock.h"
#include "s3c2410.h"
#include "s3c2440.h"
......@@ -112,6 +113,26 @@ s3c_lookup_cpu(unsigned long idcode)
return NULL;
}
/* board information */
static struct s3c24xx_board *board;
void s3c24xx_set_board(struct s3c24xx_board *b)
{
int i;
board = b;
if (b->clocks_count != 0) {
struct clk **ptr = b->clocks;;
for (i = b->clocks_count; i > 0; i--, ptr++)
s3c2410_register_clock(*ptr);
}
}
/* cpu information */
static struct cpu_table *cpu;
void __init s3c24xx_init_io(struct map_desc *mach_desc, int size)
......@@ -141,12 +162,29 @@ void __init s3c24xx_init_io(struct map_desc *mach_desc, int size)
static int __init s3c_arch_init(void)
{
int ret;
// do the correct init for cpu
if (cpu == NULL)
panic("s3c_arch_init: NULL cpu\n");
return (cpu->init)();
ret = (cpu->init)();
if (ret != 0)
return ret;
if (board != NULL) {
ret = platform_add_devices(board->devices, board->devices_count);
if (ret) {
printk(KERN_ERR "s3c24xx: failed to add board devices (%d)\n", ret);
}
/* mask any error, we may not need all these board
* devices */
ret = 0;
}
return ret;
}
arch_initcall(s3c_arch_init);
......@@ -11,6 +11,7 @@
*
* Modifications:
* 24-Aug-2004 BJD Start of generic S3C24XX support
* 18-Oct-2004 BJD Moved board struct into this file
*/
#define IODESC_ENT(x) { S3C2410_VA_##x, S3C2410_PA_##x, S3C2410_SZ_##x, MT_DEVICE }
......@@ -38,3 +39,21 @@ extern void s3c2440_map_io(struct map_desc *mach_desc, int size);
#endif
extern void s3c24xx_init_io(struct map_desc *mach_desc, int size);
/* the board structure is used at first initialsation time
* to get info such as the devices to register for this
* board. This is done because platfrom_add_devices() cannot
* be called from the map_io entry.
*/
struct s3c24xx_board {
struct platform_device **devices;
unsigned int devices_count;
struct clk **clocks;
unsigned int clocks_count;
};
extern void s3c24xx_set_board(struct s3c24xx_board *board);
......@@ -33,9 +33,11 @@
*
* 05-Oct-2004 Ben Dooks <ben@simtec.co.uk>
* Tidy up KF's patch and sort out new release
*
* 05-Oct-2004 Ben Dooks <ben@simtec.co.uk>
* Add support for power management controls
*/
#include <linux/init.h>
#include <linux/module.h>
#include <linux/interrupt.h>
......@@ -52,10 +54,73 @@
#include <asm/arch/regs-irq.h>
#include <asm/arch/regs-gpio.h>
#include "pm.h"
#define irqdbf(x...)
#define irqdbf2(x...)
#define EXTINT_OFF (IRQ_EINT4 - 4)
/* wakeup irq control */
#ifdef CONFIG_PM
/* state for IRQs over sleep */
/* default is to allow for EINT0..EINT15, and IRQ_RTC as wakeup sources
*
* set bit to 1 in allow bitfield to enable the wakeup settings on it
*/
unsigned long s3c_irqwake_intallow = 1L << (IRQ_RTC - IRQ_EINT0) | 0xfL;
unsigned long s3c_irqwake_intmask = 0xffffffffL;
unsigned long s3c_irqwake_eintallow = 0x0000fff0L;
unsigned long s3c_irqwake_eintmask = 0xffffffffL;
static int
s3c_irq_wake(unsigned int irqno, unsigned int state)
{
unsigned long irqbit = 1 << (irqno - IRQ_EINT0);
if (!(s3c_irqwake_intallow & irqbit))
return -ENOENT;
printk(KERN_INFO "wake %s for irq %d\n",
state ? "enabled" : "disabled", irqno);
if (!state)
s3c_irqwake_intmask |= irqbit;
else
s3c_irqwake_intmask &= irqbit;
return 0;
}
static int
s3c_irqext_wake(unsigned int irqno, unsigned int state)
{
unsigned long bit = 1L << (irqno - EXTINT_OFF);
if (!(s3c_irqwake_eintallow & bit))
return -ENOENT;
printk(KERN_INFO "wake %s for irq %d\n",
state ? "enabled" : "disabled", irqno);
if (!state)
s3c_irqwake_eintmask |= bit;
else
s3c_irqwake_eintmask &= ~bit;
return 0;
}
#else
#define s3c_irqext_wake NULL
#define s3c_irq_wake NULL
#endif
static void
s3c_irq_mask(unsigned int irqno)
{
......@@ -109,21 +174,21 @@ s3c_irq_unmask(unsigned int irqno)
static struct irqchip s3c_irq_level_chip = {
.ack = s3c_irq_maskack,
.mask = s3c_irq_mask,
.unmask = s3c_irq_unmask
.unmask = s3c_irq_unmask,
.wake = s3c_irq_wake
};
static struct irqchip s3c_irq_chip = {
.ack = s3c_irq_ack,
.mask = s3c_irq_mask,
.unmask = s3c_irq_unmask
.unmask = s3c_irq_unmask,
.wake = s3c_irq_wake
};
/* S3C2410_EINTMASK
* S3C2410_EINTPEND
*/
#define EXTINT_OFF (IRQ_EINT4 - 4)
static void
s3c_irqext_mask(unsigned int irqno)
{
......@@ -276,14 +341,16 @@ static struct irqchip s3c_irqext_chip = {
.mask = s3c_irqext_mask,
.unmask = s3c_irqext_unmask,
.ack = s3c_irqext_ack,
.type = s3c_irqext_type
.type = s3c_irqext_type,
.wake = s3c_irqext_wake
};
static struct irqchip s3c_irq_eint0t4 = {
.ack = s3c_irq_ack,
.mask = s3c_irq_mask,
.unmask = s3c_irq_unmask,
.type = s3c_irqext_type
.wake = s3c_irq_wake,
.type = s3c_irqext_type,
};
/* mask values for the parent registers for each of the interrupt types */
......
......@@ -18,6 +18,7 @@
* 05-Sep-2003 BJD Moved to v2.6 kernel
* 06-Jan-2003 BJD Updates for <arch/map.h>
* 18-Jan-2003 BJD Added serial port configuration
* 05-Oct-2004 BJD Power management code
*/
#include <linux/kernel.h>
......@@ -33,6 +34,7 @@
#include <asm/mach/irq.h>
#include <asm/arch/bast-map.h>
#include <asm/arch/bast-irq.h>
#include <asm/hardware.h>
#include <asm/io.h>
......@@ -41,11 +43,16 @@
//#include <asm/debug-ll.h>
#include <asm/arch/regs-serial.h>
#include <asm/arch/regs-gpio.h>
#include <asm/arch/regs-mem.h>
#include "s3c2410.h"
#include "devs.h"
#include "cpu.h"
#include "usb-simtec.h"
#include "pm.h"
#define COPYRIGHT ", (c) 2004 Simtec Electronics"
/* macros for virtual address mods for the io space entries */
#define VA_C5(item) ((item) + BAST_VAM_CS5)
......@@ -207,7 +214,7 @@ static struct platform_device *bast_devices[] __initdata = {
&bast_device_nor
};
static struct s3c2410_board bast_board __initdata = {
static struct s3c24xx_board bast_board __initdata = {
.devices = bast_devices,
.devices_count = ARRAY_SIZE(bast_devices)
};
......@@ -216,7 +223,7 @@ void __init bast_map_io(void)
{
s3c24xx_init_io(bast_iodesc, ARRAY_SIZE(bast_iodesc));
s3c2410_init_uarts(bast_uartcfgs, ARRAY_SIZE(bast_uartcfgs));
s3c2410_set_board(&bast_board);
s3c24xx_set_board(&bast_board);
usb_simtec_init();
}
......@@ -225,6 +232,36 @@ void __init bast_init_irq(void)
s3c2410_init_irq();
}
#ifdef CONFIG_PM
/* bast_init_pm
*
* enable the power management functions for the EB2410ITX
*/
static __init int bast_init_pm(void)
{
unsigned long gstatus4;
if (!machine_is_bast())
return 0;
printk(KERN_INFO "BAST Power Manangement" COPYRIGHT "\n");
gstatus4 = (__raw_readl(S3C2410_BANKCON7) & 0x3) << 30;
gstatus4 |= (__raw_readl(S3C2410_BANKCON6) & 0x3) << 28;
gstatus4 |= (__raw_readl(S3C2410_BANKSIZE) & S3C2410_BANKSIZE_MASK);
printk(KERN_DEBUG "setting GSTATUS4 to %08lx\n", gstatus4);
__raw_writel(gstatus4, S3C2410_GSTATUS4);
return s3c2410_pm_init();
}
late_initcall(bast_init_pm);
#endif
MACHINE_START(BAST, "Simtec-BAST")
MAINTAINER("Ben Dooks <ben@simtec.co.uk>")
BOOT_MEM(S3C2410_SDRAM_PA, S3C2410_PA_UART, S3C2410_VA_UART)
......
......@@ -18,6 +18,7 @@
* 17-Feb-2003 BJD Copied to mach-ipaq.c
* 21-Aug-2004 BJD Added struct s3c2410_board
* 04-Sep-2004 BJD Changed uart init, renamed ipaq_ -> h1940_
* 18-Oct-2004 BJD Updated new board structure name
*/
#include <linux/kernel.h>
......@@ -92,7 +93,7 @@ static struct platform_device *h1940_devices[] __initdata = {
&s3c_device_iis,
};
static struct s3c2410_board h1940_board __initdata = {
static struct s3c24xx_board h1940_board __initdata = {
.devices = h1940_devices,
.devices_count = ARRAY_SIZE(h1940_devices)
};
......@@ -101,7 +102,7 @@ void __init h1940_map_io(void)
{
s3c24xx_init_io(h1940_iodesc, ARRAY_SIZE(h1940_iodesc));
s3c2410_init_uarts(h1940_uartcfgs, ARRAY_SIZE(h1940_uartcfgs));
s3c2410_set_board(&h1940_board);
s3c24xx_set_board(&h1940_board);
}
void __init h1940_init_irq(void)
......
......@@ -96,7 +96,7 @@ static struct platform_device *smdk2410_devices[] __initdata = {
&s3c_device_iis,
};
static struct s3c2410_board smdk2410_board __initdata = {
static struct s3c24xx_board smdk2410_board __initdata = {
.devices = smdk2410_devices,
.devices_count = ARRAY_SIZE(smdk2410_devices)
};
......@@ -105,7 +105,7 @@ void __init smdk2410_map_io(void)
{
s3c24xx_init_io(smdk2410_iodesc, ARRAY_SIZE(smdk2410_iodesc));
s3c2410_init_uarts(smdk2410_uartcfgs, ARRAY_SIZE(smdk2410_uartcfgs));
s3c2410_set_board(&smdk2410_board);
s3c24xx_set_board(&smdk2410_board);
}
void __init smdk2410_init_irq(void)
......
......@@ -16,6 +16,7 @@
* 21-Aug-2004 BJD Added struct s3c2410_board
* 06-Aug-2004 BJD Fixed call to time initialisation
* 05-Apr-2004 BJD Copied to make mach-vr1000.c
* 18-Oct-2004 BJD Updated board struct
*/
#include <linux/kernel.h>
......@@ -151,7 +152,7 @@ static struct platform_device *vr1000_devices[] __initdata = {
&s3c_device_iis,
};
static struct s3c2410_board vr1000_board __initdata = {
static struct s3c24xx_board vr1000_board __initdata = {
.devices = vr1000_devices,
.devices_count = ARRAY_SIZE(vr1000_devices)
};
......@@ -161,7 +162,7 @@ void __init vr1000_map_io(void)
{
s3c24xx_init_io(vr1000_iodesc, ARRAY_SIZE(vr1000_iodesc));
s3c2410_init_uarts(vr1000_uartcfgs, ARRAY_SIZE(vr1000_uartcfgs));
s3c2410_set_board(&vr1000_board);
s3c24xx_set_board(&vr1000_board);
usb_simtec_init();
}
......
/* linux/arch/arm/mach-s3c2410/pm.c
*
* Copyright (c) 2004 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
*
* S3C2410 Power Manager (Suspend-To-RAM) support
*
* See Documentation/arm/Samsung-S3C24XX/Suspend.txt for more information
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Parts based on arch/arm/mach-pxa/pm.c
*
*/
#include <linux/config.h>
#include <linux/init.h>
#include <linux/suspend.h>
#include <linux/errno.h>
#include <linux/time.h>
#include <linux/interrupt.h>
#include <linux/crc32.h>
#include <linux/ioport.h>
#include <asm/hardware.h>
#include <asm/io.h>
#include <asm/arch/regs-clock.h>
#include <asm/arch/regs-gpio.h>
#include <asm/arch/regs-mem.h>
#include <asm/arch/regs-irq.h>
#include <asm/mach/time.h>
#include "pm.h"
/* for external use */
unsigned long s3c_pm_flags;
/* cache functions from arch/arm/mm/proc-arm920.S */
extern void arm920_flush_kern_cache_all(void);
#define PFX "s3c24xx-pm: "
/* sleep save info */
struct sleep_save {
unsigned long reg;
unsigned long val;
};
#define SAVE_ITEM(x) \
{ .reg = (x) }
static struct sleep_save core_save[] = {
SAVE_ITEM(S3C2410_LOCKTIME),
SAVE_ITEM(S3C2410_CLKCON)
};
/* this lot should be really saved by the IRQ code */
static struct sleep_save irq_save[] = {
SAVE_ITEM(S3C2410_EINTMASK),
SAVE_ITEM(S3C2410_INTMSK),
SAVE_ITEM(S3C2410_EINFLT0),
SAVE_ITEM(S3C2410_EINFLT1),
SAVE_ITEM(S3C2410_EINFLT2),
SAVE_ITEM(S3C2410_EINFLT3)
};
static struct sleep_save gpio_save[] = {
SAVE_ITEM(S3C2410_GPACON),
SAVE_ITEM(S3C2410_GPADAT),
SAVE_ITEM(S3C2410_GPBCON),
SAVE_ITEM(S3C2410_GPBDAT),
SAVE_ITEM(S3C2410_GPBUP),
SAVE_ITEM(S3C2410_GPCCON),
SAVE_ITEM(S3C2410_GPCDAT),
SAVE_ITEM(S3C2410_GPCUP),
SAVE_ITEM(S3C2410_GPDCON),
SAVE_ITEM(S3C2410_GPDDAT),
SAVE_ITEM(S3C2410_GPDUP),
SAVE_ITEM(S3C2410_GPECON),
SAVE_ITEM(S3C2410_GPEDAT),
SAVE_ITEM(S3C2410_GPEUP),
SAVE_ITEM(S3C2410_GPFCON),
SAVE_ITEM(S3C2410_GPFDAT),
SAVE_ITEM(S3C2410_GPFUP),
SAVE_ITEM(S3C2410_GPGCON),
SAVE_ITEM(S3C2410_GPGDAT),
SAVE_ITEM(S3C2410_GPGUP),
SAVE_ITEM(S3C2410_GPHCON),
SAVE_ITEM(S3C2410_GPHDAT),
SAVE_ITEM(S3C2410_GPHUP),
};
#ifdef CONFIG_S3C2410_PM_DEBUG
/* debug
*
* we send the debug to printascii() to allow it to be seen if the
* system never wakes up from the sleep
*/
extern void printascii(const char *);
static void pm_dbg(const char *fmt, ...)
{
va_list va;
char buff[256];
va_start(va, fmt);
vsprintf(buff, fmt, va);
va_end(va);
printascii(buff);
}
#define DBG(fmt...) pm_dbg(fmt)
#else
#define DBG(fmt...) printk(KERN_DEBUG fmt)
#endif
#if defined(CONFIG_S3C2410_PM_CHECK) && CONFIG_S3C2410_PM_CHECK_CHUNKSIZE != 0
/* suspend checking code...
*
* this next area does a set of crc checks over all the installed
* memory, so the system can verify if the resume was ok.
*
* CONFIG_S3C2410_PM_CHECK_CHUNKSIZE defines the block-size for the CRC,
* increasing it will mean that the area corrupted will be less easy to spot,
* and reducing the size will cause the CRC save area to grow
*/
#define CHECK_CHUNKSIZE (CONFIG_S3C2410_PM_CHECK_CHUNKSIZE * 1024)
static u32 crc_size; /* size needed for the crc block */
static u32 *crcs; /* allocated over suspend/resume */
typedef u32 *(run_fn_t)(struct resource *ptr, u32 *arg);
/* s3c2410_pm_run_res
*
* go thorugh the given resource list, and look for system ram
*/
static void s3c2410_pm_run_res(struct resource *ptr, run_fn_t fn, u32 *arg)
{
while (ptr != NULL) {
if (ptr->child != NULL)
s3c2410_pm_run_res(ptr->child, fn, arg);
if ((ptr->flags & IORESOURCE_MEM) &&
strcmp(ptr->name, "System RAM") == 0) {
DBG("Found system RAM at %08lx..%08lx\n",
ptr->start, ptr->end);
arg = (fn)(ptr, arg);
}
ptr = ptr->sibling;
}
}
static void s3c2410_pm_run_sysram(run_fn_t fn, u32 *arg)
{
s3c2410_pm_run_res(&iomem_resource, fn, arg);
}
static u32 *s3c2410_pm_countram(struct resource *res, u32 *val)
{
u32 size = (u32)(res->end - res->start)+1;
size += CHECK_CHUNKSIZE-1;
size /= CHECK_CHUNKSIZE;
DBG("Area %08lx..%08lx, %d blocks\n", res->start, res->end, size);
*val += size * sizeof(u32);
return val;
}
/* s3c2410_pm_prepare_check
*
* prepare the necessary information for creating the CRCs. This
* must be done before the final save, as it will require memory
* allocating, and thus touching bits of the kernel we do not
* know about.
*/
static void s3c2410_pm_check_prepare(void)
{
crc_size = 0;
s3c2410_pm_run_sysram(s3c2410_pm_countram, &crc_size);
DBG("s3c2410_pm_prepare_check: %u checks needed\n", crc_size);
crcs = kmalloc(crc_size+4, GFP_KERNEL);
if (crcs == NULL)
printk(KERN_ERR "Cannot allocated CRC save area\n");
}
static u32 *s3c2410_pm_makecheck(struct resource *res, u32 *val)
{
unsigned long addr, left;
for (addr = res->start; addr < res->end;
addr += CHECK_CHUNKSIZE) {
left = res->end - addr;
if (left > CHECK_CHUNKSIZE)
left = CHECK_CHUNKSIZE;
*val = crc32_le(~0, phys_to_virt(addr), left);
val++;
}
return val;
}
/* s3c2410_pm_check_store
*
* compute the CRC values for the memory blocks before the final
* sleep.
*/
static void s3c2410_pm_check_store(void)
{
if (crcs != NULL)
s3c2410_pm_run_sysram(s3c2410_pm_makecheck, crcs);
}
/* in_region
*
* return TRUE if the area defined by ptr..ptr+size contatins the
* what..what+whatsz
*/
static inline int in_region(void *ptr, int size, void *what, size_t whatsz)
{
if ((what+whatsz) < ptr)
return 0;
if (what > (ptr+size))
return 0;
return 1;
}
static u32 *s3c2410_pm_runcheck(struct resource *res, u32 *val)
{
void *save_at = phys_to_virt(s3c2410_sleep_save_phys);
unsigned long addr;
unsigned long left;
void *ptr;
u32 calc;
for (addr = res->start; addr < res->end;
addr += CHECK_CHUNKSIZE) {
left = res->end - addr;
if (left > CHECK_CHUNKSIZE)
left = CHECK_CHUNKSIZE;
ptr = phys_to_virt(addr);
if (in_region(ptr, left, crcs, crc_size)) {
DBG("skipping %08lx, has crc block in\n", addr);
goto skip_check;
}
if (in_region(ptr, left, save_at, 32*4 )) {
DBG("skipping %08lx, has save block in\n", addr);
goto skip_check;
}
/* calculate and check the checksum */
calc = crc32_le(~0, ptr, left);
if (calc != *val) {
printk(KERN_ERR PFX "Restore CRC error at "
"%08lx (%08x vs %08x)\n", addr, calc, *val);
DBG("Restore CRC error at %08lx (%08x vs %08x)\n",
addr, calc, *val);
}
skip_check:
val++;
}
return val;
}
/* s3c2410_pm_check_restore
*
* check the CRCs after the restore event and free the memory used
* to hold them
*/
static void s3c2410_pm_check_restore(void)
{
if (crcs != NULL) {
s3c2410_pm_run_sysram(s3c2410_pm_runcheck, crcs);
kfree(crcs);
crcs = NULL;
}
}
#else
#define s3c2410_pm_check_prepare() do { } while(0)
#define s3c2410_pm_check_restore() do { } while(0)
#define s3c2410_pm_check_store() do { } while(0)
#endif
/* helper functions to save and restore register state */
static void s3c2410_pm_do_save(struct sleep_save *ptr, int count)
{
for (; count > 0; count--, ptr++) {
ptr->val = __raw_readl(ptr->reg);
DBG("saved %08lx value %08lx\n", ptr->reg, ptr->val);
}
}
static void s3c2410_pm_do_restore(struct sleep_save *ptr, int count)
{
for (; count > 0; count--, ptr++) {
DBG("restore %08lx (restore %08lx, current %08x)\n",
ptr->reg, ptr->val, __raw_readl(ptr->reg));
__raw_writel(ptr->val, ptr->reg);
}
}
/* s3c2410_pm_show_resume_irqs
*
* print any IRQs asserted at resume time (ie, we woke from)
*/
static void s3c2410_pm_show_resume_irqs(int start, unsigned long which,
unsigned long mask)
{
int i;
which &= ~mask;
for (i = 0; i <= 31; i++) {
if ((which) & (1L<<i)) {
DBG("IRQ %d asserted at resume\n", start+i);
}
}
}
/* s3c2410_pm_check_resume_pin
*
* check to see if the pin is configured correctly for sleep mode, and
* make any necessary adjustments if it is not
*/
static void s3c2410_pm_check_resume_pin(unsigned int pin, unsigned int irqoffs)
{
unsigned long irqstate;
unsigned long pinstate;
int irq = s3c2410_gpio_getirq(pin);
if (irqoffs < 4)
irqstate = s3c_irqwake_intmask & (1L<<irqoffs);
else
irqstate = s3c_irqwake_eintmask & (1L<<irqoffs);
pinstate = s3c2410_gpio_getcfg(pin);
pinstate >>= S3C2410_GPIO_OFFSET(pin)*2;
if (!irqstate) {
if (pinstate == 0x02)
DBG("Leaving IRQ %d (pin %d) enabled\n", irq, pin);
} else {
if (pinstate == 0x02) {
DBG("Disabling IRQ %d (pin %d)\n", irq, pin);
s3c2410_gpio_cfgpin(pin, 0x00);
}
}
}
/* s3c2410_pm_configure_extint
*
* configure all external interrupt pins
*/
static void s3c2410_pm_configure_extint(void)
{
int pin;
/* for each of the external interrupts (EINT0..EINT15) we
* need to check wether it is an external interrupt source,
* and then configure it as an input if it is not
*/
for (pin = S3C2410_GPF0; pin <= S3C2410_GPF7; pin++) {
s3c2410_pm_check_resume_pin(pin, pin - S3C2410_GPF0);
}
for (pin = S3C2410_GPG0; pin <= S3C2410_GPG7; pin++) {
s3c2410_pm_check_resume_pin(pin, (pin - S3C2410_GPG0)+8);
}
}
#define any_allowed(mask, allow) (((mask) & (allow)) != (allow))
/* s3c2410_pm_enter
*
* central control for sleep/resume process
*/
static int s3c2410_pm_enter(u32 state)
{
unsigned long regs_save[16];
unsigned long tmp;
DBG("s3c2410_pm_enter(%d)\n", state);
if (state != PM_SUSPEND_MEM) {
printk(KERN_ERR PFX "error: only PM_SUSPEND_MEM supported\n");
return -EINVAL;
}
/* check if we have anything to wake-up with... bad things seem
* to happen if you suspend with no wakeup (system will often
* require a full power-cycle)
*/
if (!any_allowed(s3c_irqwake_intmask, s3c_irqwake_intallow) &&
!any_allowed(s3c_irqwake_eintmask, s3c_irqwake_eintallow)) {
printk(KERN_ERR PFX "No sources enabled for wake-up!\n");
printk(KERN_ERR PFX "Aborting sleep\n");
return -EINVAL;
}
/* prepare check area if configured */
s3c2410_pm_check_prepare();
/* store the physical address of the register recovery block */
s3c2410_sleep_save_phys = virt_to_phys(regs_save);
DBG("s3c2410_sleep_save_phys=0x%08lx\n", s3c2410_sleep_save_phys);
/* ensure at least GESTATUS3 has the resume address */
__raw_writel(virt_to_phys(s3c2410_cpu_resume), S3C2410_GSTATUS3);
DBG("GSTATUS3 0x%08x\n", __raw_readl(S3C2410_GSTATUS3));
DBG("GSTATUS4 0x%08x\n", __raw_readl(S3C2410_GSTATUS4));
/* save all necessary core registers not covered by the drivers */
s3c2410_pm_do_save(gpio_save, ARRAY_SIZE(gpio_save));
s3c2410_pm_do_save(irq_save, ARRAY_SIZE(irq_save));
s3c2410_pm_do_save(core_save, ARRAY_SIZE(core_save));
/* set the irq configuration for wake */
s3c2410_pm_configure_extint();
DBG("sleep: irq wakeup masks: %08lx,%08lx\n",
s3c_irqwake_intmask, s3c_irqwake_eintmask);
__raw_writel(s3c_irqwake_intmask, S3C2410_INTMSK);
__raw_writel(s3c_irqwake_eintmask, S3C2410_EINTMASK);
/* ack any outstanding external interrupts before we go to sleep */
__raw_writel(S3C2410_EINTPEND, __raw_readl(S3C2410_EINTPEND));
/* flush cache back to ram */
arm920_flush_kern_cache_all();
s3c2410_pm_check_store();
// need to make some form of time-delta
/* send the cpu to sleep... */
__raw_writel(0x00, S3C2410_CLKCON); /* turn off clocks over sleep */
s3c2410_cpu_suspend(regs_save);
/* unset the return-from-sleep flag, to ensure reset */
tmp = __raw_readl(S3C2410_GSTATUS2);
tmp &= S3C2410_GSTATUs2_OFFRESET;
__raw_writel(tmp, S3C2410_GSTATUS2);
/* check what irq (if any) restored the system */
DBG("post sleep: IRQs 0x%08x, 0x%08x\n",
__raw_readl(S3C2410_SRCPND),
__raw_readl(S3C2410_EINTPEND));
s3c2410_pm_show_resume_irqs(IRQ_EINT0, __raw_readl(S3C2410_SRCPND),
s3c_irqwake_intmask);
s3c2410_pm_show_resume_irqs(IRQ_EINT4-4, __raw_readl(S3C2410_EINTPEND),
s3c_irqwake_eintmask);
DBG("post sleep, restoring state...\n");
s3c2410_pm_do_restore(core_save, ARRAY_SIZE(core_save));
s3c2410_pm_do_restore(gpio_save, ARRAY_SIZE(gpio_save));
s3c2410_pm_do_restore(irq_save, ARRAY_SIZE(irq_save));
DBG("post sleep, preparing to return\n");
s3c2410_pm_check_restore();
/* ok, let's return from sleep */
DBG("S3C2410 PM Resume (post-restore)\n");
return 0;
}
/*
* Called after processes are frozen, but before we shut down devices.
*/
static int s3c2410_pm_prepare(u32 state)
{
return 0;
}
/*
* Called after devices are re-setup, but before processes are thawed.
*/
static int s3c2410_pm_finish(u32 state)
{
return 0;
}
/*
* Set to PM_DISK_FIRMWARE so we can quickly veto suspend-to-disk.
*/
static struct pm_ops s3c2410_pm_ops = {
.pm_disk_mode = PM_DISK_FIRMWARE,
.prepare = s3c2410_pm_prepare,
.enter = s3c2410_pm_enter,
.finish = s3c2410_pm_finish,
};
/* s3c2410_pm_init
*
* Attach the power management functions. This should be called
* from the board specific initialisation if the board supports
* it.
*/
int __init s3c2410_pm_init(void)
{
printk("S3C2410 Power Management, (c) 2004 Simtec Electronics\n");
pm_set_ops(&s3c2410_pm_ops);
return 0;
}
/* linux/arch/arm/mach-s3c2410/pm.h
*
* Copyright (c) 2004 Simtec Electronics
* Written by 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.
*/
/* s3c2410_pm_init
*
* called from board at initialisation time to setup the power
* management
*/
extern __init int s3c2410_pm_init(void);
/* configuration for the IRQ mask over sleep */
extern unsigned long s3c_irqwake_intmask;
extern unsigned long s3c_irqwake_eintmask;
/* IRQ masks for IRQs allowed to go to sleep (see irq.c) */
extern unsigned long s3c_irqwake_intallow;
extern unsigned long s3c_irqwake_eintallow;
/* Flags for PM Control */
extern unsigned long s3c_pm_flags;
/* from sleep.S */
extern void s3c2410_cpu_suspend(unsigned long *saveblk);
extern void s3c2410_cpu_resume(void);
extern unsigned long s3c2410_sleep_save_phys;
......@@ -189,13 +189,12 @@ void __init s3c2410_map_io(struct map_desc *mach_desc, int mach_size)
printk("S3C2410: core %ld.%03ld MHz, memory %ld.%03ld MHz, peripheral %ld.%03ld MHz\n",
print_mhz(s3c24xx_fclk), print_mhz(s3c24xx_hclk),
print_mhz(s3c24xx_pclk));
}
static struct s3c2410_board *board;
/* initialise the clocks here, to allow other things like the
* console to use them
*/
void s3c2410_set_board(struct s3c2410_board *b)
{
board = b;
s3c2410_init_clocks();
}
int __init s3c2410_init(void)
......@@ -205,22 +204,5 @@ int __init s3c2410_init(void)
printk("S3C2410: Initialising architecture\n");
ret = platform_add_devices(uart_devices, ARRAY_SIZE(uart_devices));
if (ret)
return ret;
if (board != NULL) {
if (board->devices != NULL) {
ret = platform_add_devices(board->devices,
board->devices_count);
if (ret) {
printk(KERN_ERR "s3c2410: failed to add board devices (%d)\n", ret);
}
}
/* not adding board devices may not be fatal */
ret = 0;
}
return ret;
}
......@@ -13,6 +13,7 @@
* 18-Aug-2004 BJD Created initial version
* 20-Aug-2004 BJD Added s3c2410_board struct
* 04-Sep-2004 BJD Added s3c2410_init_uarts() call
* 17-Oct-2004 BJD Moved board out to cpu
*/
struct s3c2410_uartcfg;
......@@ -26,18 +27,4 @@ extern void s3c2410_init_irq(void);
struct sys_timer;
extern struct sys_timer s3c2410_timer;
/* the board structure is used at first initialsation time
* to get info such as the devices to register for this
* board. This is done because platfrom_add_devices() cannot
* be called from the map_io entry.
*
*/
struct s3c2410_board {
struct platform_device **devices;
unsigned int devices_count;
};
extern void s3c2410_set_board(struct s3c2410_board *board);
extern void s3c2410_init_uarts(struct s3c2410_uartcfg *cfg, int no);
......@@ -120,6 +120,20 @@ static struct platform_device *uart_devices[] __initdata = {
&s3c_uart2
};
/* s3c2440 specific clock sources */
static struct clk s3c2440_clk_cam = {
.name = "camera",
.enable = s3c2410_clkcon_enable,
.ctrlbit = S3C2440_CLKCON_CAMERA
};
static struct clk s3c2440_clk_ac97 = {
.name = "ac97",
.enable = s3c2410_clkcon_enable,
.ctrlbit = S3C2440_CLKCON_CAMERA
};
void __init s3c2440_map_io(struct map_desc *mach_desc, int size)
{
unsigned long clkdiv;
......@@ -167,6 +181,23 @@ void __init s3c2440_map_io(struct map_desc *mach_desc, int size)
printk("S3C2440: core %ld.%03ld MHz, memory %ld.%03ld MHz, peripheral %ld.%03ld MHz\n",
print_mhz(s3c24xx_fclk), print_mhz(s3c24xx_hclk),
print_mhz(s3c24xx_pclk));
/* initialise the clocks here, to allow other things like the
* console to use them, and to add new ones after the initialisation
*/
s3c2410_init_clocks();
/* add s3c2440 specific clocks */
s3c2440_clk_cam.parent = clk_get(NULL, "hclk");
s3c2440_clk_ac97.parent = clk_get(NULL, "pclk");
s3c2410_register_clock(&clk_ac97);
s3c2410_register_clock(&clk_cam);
clk_disable(&clk_ac97);
clk_disable(&clk_cam);
}
......@@ -178,11 +209,6 @@ int __init s3c2440_init(void)
printk("S3C2440: Initialising architecture\n");
ret = platform_add_devices(uart_devices, ARRAY_SIZE(uart_devices));
if (ret)
return ret;
// todo: board specific inits?
return ret;
}
/* linux/arch/arm/mach-s3c2410/sleep.S
*
* Copyright (c) 2004 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
*
* S3C2410 Power Manager (Suspend-To-RAM) support
*
* Based on PXA/SA1100 sleep code by:
* Nicolas Pitre, (c) 2002 Monta Vista Software Inc
* Cliff Brake, (c) 2001
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <linux/config.h>
#include <linux/linkage.h>
#include <asm/assembler.h>
#include <asm/hardware.h>
#include <asm/arch/map.h>
#include <asm/arch/regs-gpio.h>
#include <asm/arch/regs-clock.h>
#include <asm/arch/regs-mem.h>
#include <asm/arch/regs-serial.h>
#define CONFIG_DEBUG_RESUME
.text
/* s3c2410_cpu_suspend
*
* put the cpu into sleep mode
*
* entry:
* r0 = sleep save block
*/
ENTRY(s3c2410_cpu_suspend)
stmfd sp!, { r4 - r12, lr }
@@ store co-processor registers
mrc p15, 0, r4, c15, c1, 0 @ CP access register
mrc p15, 0, r5, c13, c0, 0 @ PID
mrc p15, 0, r6, c3, c0, 0 @ Domain ID
mrc p15, 0, r7, c2, c0, 0 @ translation table base address
mrc p15, 0, r8, c2, c0, 0 @ auxiliary control register
mrc p15, 0, r9, c1, c0, 0 @ control register
stmia r0, { r4 - r13 }
@@ flush the caches to ensure everything is back out to
@@ SDRAM before the core powers down
bl arm920_flush_kern_cache_all
@@ prepare cpu to sleep
ldr r4, =S3C2410_REFRESH
ldr r5, =S3C2410_MISCCR
ldr r6, =S3C2410_CLKCON
ldr r7, [ r4 ] @ get REFRESH (and ensure in TLB)
ldr r8, [ r5 ] @ get MISCCR (and ensure in TLB)
ldr r9, [ r6 ] @ get CLKCON (and ensure in TLB)
orr r7, r7, #S3C2410_REFRESH_SELF @ SDRAM sleep command
orr r8, r8, #S3C2410_MISCCR_SDSLEEP @ SDRAM power-down signals
orr r9, r9, #S3C2410_CLKCON_POWER @ power down command
teq pc, #0 @ first as a trial-run to load cache
bl s3c2410_do_sleep
teq r0, r0 @ now do it for real
b s3c2410_do_sleep @
@@ align next bit of code to cache line
.align 8
s3c2410_do_sleep:
streq r7, [ r4 ] @ SDRAM sleep command
streq r8, [ r5 ] @ SDRAM power-down config
streq r9, [ r6 ] @ CPU sleep
1: beq 1b
mov pc, r14
@@ return to the caller, after having the MMU
@@ turned on, this restores the last bits from the
@@ stack
resume_with_mmu:
ldmfd sp!, { r4 - r12, pc }
.ltorg
@@ the next bits sit in the .data segment, even though they
@@ happen to be code... the s3c2410_sleep_save_phys needs to be
@@ accessed by the resume code before it can restore the MMU.
@@ This means that the variable has to be close enough for the
@@ code to read it... since the .text segment needs to be RO,
@@ the data segment can be the only place to put this code.
.data
.global s3c2410_sleep_save_phys
s3c2410_sleep_save_phys:
.word 0
/* s3c2410_cpu_resume
*
* resume code entry for bootloader to call
*
* we must put this code here in the data segment as we have no
* other way of restoring the stack pointer after sleep, and we
* must not write to the code segment (code is read-only)
*/
ENTRY(s3c2410_cpu_resume)
mov r0, #PSR_I_BIT | PSR_F_BIT | MODE_SVC
msr cpsr_c, r0
@@ load UART to allow us to print the two characters for
@@ resume debug
mov r2, #S3C2410_PA_UART & 0xff000000
orr r2, r2, #S3C2410_PA_UART & 0xff000
#ifdef CONFIG_DEBUG_RESUME
mov r3, #'L'
strb r3, [ r2, #S3C2410_UTXH ]
1001:
ldrb r14, [ r3, #S3C2410_UTRSTAT ]
tst r14, #S3C2410_UTRSTAT_TXE
beq 1001b
#endif /* CONFIG_DEBUG_RESUME */
mov r1, #0
mcr p15, 0, r1, c8, c7, 0 @@ invalidate I & D TLBs
mcr p15, 0, r1, c7, c7, 0 @@ invalidate I & D caches
ldr r0, s3c2410_sleep_save_phys @ address of restore block
ldmia r0, { r4 - r13 }
mcr p15, 0, r4, c15, c1, 0 @ CP access register
mcr p15, 0, r5, c13, c0, 0 @ PID
mcr p15, 0, r6, c3, c0, 0 @ Domain ID
mcr p15, 0, r7, c2, c0, 0 @ translation table base
mcr p15, 0, r8, c1, c1, 0 @ auxilliary control
#ifdef CONFIG_DEBUG_RESUME
mov r3, #'R'
strb r3, [ r2, #S3C2410_UTXH ]
#endif
ldr r2, =resume_with_mmu
mcr p15, 0, r9, c1, c0, 0 @ turn on MMU, etc
nop @ second-to-last before mmu
mov pc, r2 @ go back to virtual address
.ltorg
/* linux/include/asm-arm/arch-s3c2410/time.h
/* linux/arch/arm/mach-s3c2410/time.c
*
* Copyright (C) 2003 Simtec Electronics <linux@simtec.co.uk>
* Ben Dooks, <ben@simtec.co.uk>
* Copyright (C) 2003,2004 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 as published by
......@@ -39,10 +39,6 @@
static unsigned long timer_startval;
static unsigned long timer_ticks_usec;
/* with an 12MHz clock, we get 12 ticks per-usec
*/
/***
* Returns microsecond since last clock interrupt. Note that interrupts
* will have been disabled by do_gettimeoffset()
......@@ -106,7 +102,7 @@ static struct irqaction s3c2410_timer_irq = {
* Currently we only use timer4, as it is the only timer which has no
* other function that can be exploited externally
*/
static void __init s3c2410_timer_init (void)
static void s3c2410_timer_setup (void)
{
unsigned long tcon;
unsigned long tcnt;
......@@ -126,6 +122,9 @@ static void __init s3c2410_timer_init (void)
if (machine_is_bast() || machine_is_vr1000()) {
timer_ticks_usec = 12; /* timer is at 12MHz */
tcnt = (timer_ticks_usec * (1000*1000)) / HZ;
tcfg1 &= ~S3C2410_TCFG1_MUX4_MASK;
tcfg1 |= S3C2410_TCFG1_MUX4_TCLK1;
}
/* for the h1940, we use the pclk from the core to generate
......@@ -138,7 +137,8 @@ static void __init s3c2410_timer_init (void)
* of 11.25MHz, and a tcnt of 56250.
*/
if (machine_is_h1940() || machine_is_smdk2410() ) {
if (machine_is_h1940() || machine_is_smdk2410() ||
machine_is_rx3715()) {
timer_ticks_usec = s3c24xx_pclk / (1000*1000);
timer_ticks_usec /= 6;
......@@ -151,7 +151,6 @@ static void __init s3c2410_timer_init (void)
tcnt = (s3c24xx_pclk / 6) / HZ;
}
printk("setup_timer tcon=%08lx, tcnt %04lx, tcfg %08lx,%08lx\n",
tcon, tcnt, tcfg0, tcfg1);
......@@ -177,15 +176,20 @@ static void __init s3c2410_timer_init (void)
__raw_writel(tcnt, S3C2410_TCNTB(4));
__raw_writel(tcnt, S3C2410_TCMPB(4));
setup_irq(IRQ_TIMER4, &s3c2410_timer_irq);
/* start the timer running */
tcon |= S3C2410_TCON_T4START;
tcon &= ~S3C2410_TCON_T4MANUALUPD;
__raw_writel(tcon, S3C2410_TCON);
}
static void __init s3c2410_timer_init (void)
{
s3c2410_timer_setup();
setup_irq(IRQ_TIMER4, &s3c2410_timer_irq);
}
struct sys_timer s3c2410_timer = {
.init = s3c2410_timer_init,
.offset = s3c2410_gettimeoffset,
.resume = s3c2410_timer_setup
};
......@@ -13,6 +13,7 @@
*
* Modifications:
* 14-Sep-2004 BJD Created
* 18-Oct-2004 BJD Cleanups, and added code to report OC cleared
*/
#define DEBUG
......@@ -51,10 +52,8 @@ usb_simtec_powercontrol(int port, int to)
{
pr_debug("usb_simtec_powercontrol(%d,%d)\n", port, to);
if (port == 1) {
if (port == 1)
s3c2410_gpio_setpin(S3C2410_GPB4, to ? 0:1);
pr_debug("GPBDAT now %08x\n", __raw_readl(S3C2410_GPBDAT));
}
}
static irqreturn_t
......@@ -67,6 +66,7 @@ usb_simtec_ocirq(int irq, void *pw, struct pt_regs *regs)
s3c2410_report_oc(info, 3);
} else {
pr_debug("usb_simtec: over-current irq (oc cleared)\n");
s3c2410_report_oc(info, 0);
}
return IRQ_HANDLED;
......@@ -77,16 +77,15 @@ static void usb_simtec_enableoc(struct s3c2410_hcd_info *info, int on)
int ret;
if (on) {
pr_debug("claiming usb overccurent\n");
ret = request_irq(IRQ_USBOC, usb_simtec_ocirq, SA_INTERRUPT,
"usb-oc", info);
"USB Over-current", info);
if (ret != 0) {
printk(KERN_ERR "failed to request usb oc irq\n");
}
set_irq_type(IRQ_USBOC, IRQT_BOTHEDGE);
} else {
free_irq(IRQ_USBOC, NULL);
free_irq(IRQ_USBOC, info);
}
}
......@@ -110,14 +109,5 @@ int usb_simtec_init(void)
s3c2410_gpio_cfgpin(S3C2410_GPB4, S3C2410_GPB4_OUTP);
s3c2410_gpio_setpin(S3C2410_GPB4, 1);
pr_debug("GPB: CON=%08x, DAT=%08x\n",
__raw_readl(S3C2410_GPBCON), __raw_readl(S3C2410_GPBDAT));
if (0) {
s3c2410_modify_misccr(S3C2410_MISCCR_USBHOST,
S3C2410_MISCCR_USBDEV);
}
return 0;
}
......@@ -36,10 +36,14 @@
#define OMAP1610_ETHR_SIZE SZ_4K
#define OMAP1610_ETHR_START 0x04000000
/* Intel STRATA NOR flash at CS3 */
#define OMAP1610_NOR_FLASH_BASE 0xD8000000
#define OMAP1610_NOR_FLASH_SIZE SZ_32M
#define OMAP1610_NOR_FLASH_START 0x0C000000
/* Intel STRATA NOR flash at CS3 or CS2B(NAND Boot) */
#define OMAP_NOR_FLASH_SIZE SZ_32M
#define OMAP_NOR_FLASH_START1 0x0C000000 /* CS3 */
#define OMAP_NOR_FLASH_START2 0x0A000000 /* CS2B */
/* Samsung NAND flash at CS2B or CS3(NAND Boot) */
#define OMAP_NAND_FLASH_START1 0x0A000000 /* CS2B */
#define OMAP_NAND_FLASH_START2 0x0C000000 /* CS3 */
#endif /* __ASM_ARCH_OMAP_H2_H */
......@@ -32,10 +32,14 @@
#define OMAP1710_ETHR_SIZE SZ_4K
#define OMAP1710_ETHR_START 0x04000000
/* Intel STRATA NOR flash at CS3 */
#define OMAP_NOR_FLASH_BASE 0xD8000000
#define OMAP_NOR_FLASH_SIZE SZ_32M
#define OMAP_NOR_FLASH_START 0x00000000
/* Intel STRATA NOR flash at CS3 or CS2B(NAND Boot) */
#define OMAP_NOR_FLASH_SIZE SZ_32M
#define OMAP_NOR_FLASH_START1 0x0C000000 /* CS3 */
#define OMAP_NOR_FLASH_START2 0x0A000000 /* CS2B */
/* Samsung NAND flash at CS2B or CS3(NAND Boot) */
#define OMAP_NAND_FLASH_START1 0x0A000000 /* CS2B */
#define OMAP_NAND_FLASH_START2 0x0C000000 /* CS3 */
#define MAXIRQNUM (IH_BOARD_BASE)
#define MAXFIQNUM MAXIRQNUM
......@@ -43,65 +47,5 @@
#define NR_IRQS (MAXIRQNUM + 1)
#define OMAP_MCBSP1_BASE OMAP1610_MCBSP1_BASE
#define AUDIO_DRR2 (OMAP_MCBSP1_BASE + 0x00)
#define AUDIO_DRR1 (OMAP_MCBSP1_BASE + 0x02)
#define AUDIO_DXR2 (OMAP_MCBSP1_BASE + 0x04)
#define AUDIO_DXR1 (OMAP_MCBSP1_BASE + 0x06)
#define AUDIO_SPCR2 (OMAP_MCBSP1_BASE + 0x08)
#define AUDIO_SPCR1 (OMAP_MCBSP1_BASE + 0x0a)
#define AUDIO_RCR2 (OMAP_MCBSP1_BASE + 0x0c)
#define AUDIO_RCR1 (OMAP_MCBSP1_BASE + 0x0e)
#define AUDIO_XCR2 (OMAP_MCBSP1_BASE + 0x10)
#define AUDIO_XCR1 (OMAP_MCBSP1_BASE + 0x12)
#define AUDIO_SRGR2 (OMAP_MCBSP1_BASE + 0x14)
#define AUDIO_SRGR1 (OMAP_MCBSP1_BASE + 0x16)
#define AUDIO_MCR2 (OMAP_MCBSP1_BASE + 0x18)
#define AUDIO_MCR1 (OMAP_MCBSP1_BASE + 0x1a)
#define AUDIO_RCERA (OMAP_MCBSP1_BASE + 0x1c)
#define AUDIO_RCERB (OMAP_MCBSP1_BASE + 0x1e)
#define AUDIO_XCERA (OMAP_MCBSP1_BASE + 0x20)
#define AUDIO_XCERB (OMAP_MCBSP1_BASE + 0x22)
#define AUDIO_PCR0 (OMAP_MCBSP1_BASE + 0x24)
/* UART3 Registers Maping through MPU bus */
#define OMAP_MPU_UART3_BASE 0xFFFB9800 /* UART3 through MPU bus */
#define UART3_RHR (OMAP_MPU_UART3_BASE + 0)
#define UART3_THR (OMAP_MPU_UART3_BASE + 0)
#define UART3_DLL (OMAP_MPU_UART3_BASE + 0)
#define UART3_IER (OMAP_MPU_UART3_BASE + 4)
#define UART3_DLH (OMAP_MPU_UART3_BASE + 4)
#define UART3_IIR (OMAP_MPU_UART3_BASE + 8)
#define UART3_FCR (OMAP_MPU_UART3_BASE + 8)
#define UART3_EFR (OMAP_MPU_UART3_BASE + 8)
#define UART3_LCR (OMAP_MPU_UART3_BASE + 0x0C)
#define UART3_MCR (OMAP_MPU_UART3_BASE + 0x10)
#define UART3_XON1_ADDR1 (OMAP_MPU_UART3_BASE + 0x10)
#define UART3_XON2_ADDR2 (OMAP_MPU_UART3_BASE + 0x14)
#define UART3_LSR (OMAP_MPU_UART3_BASE + 0x14)
#define UART3_TCR (OMAP_MPU_UART3_BASE + 0x18)
#define UART3_MSR (OMAP_MPU_UART3_BASE + 0x18)
#define UART3_XOFF1 (OMAP_MPU_UART3_BASE + 0x18)
#define UART3_XOFF2 (OMAP_MPU_UART3_BASE + 0x1C)
#define UART3_SPR (OMAP_MPU_UART3_BASE + 0x1C)
#define UART3_TLR (OMAP_MPU_UART3_BASE + 0x1C)
#define UART3_MDR1 (OMAP_MPU_UART3_BASE + 0x20)
#define UART3_MDR2 (OMAP_MPU_UART3_BASE + 0x24)
#define UART3_SFLSR (OMAP_MPU_UART3_BASE + 0x28)
#define UART3_TXFLL (OMAP_MPU_UART3_BASE + 0x28)
#define UART3_RESUME (OMAP_MPU_UART3_BASE + 0x2C)
#define UART3_TXFLH (OMAP_MPU_UART3_BASE + 0x2C)
#define UART3_SFREGL (OMAP_MPU_UART3_BASE + 0x30)
#define UART3_RXFLL (OMAP_MPU_UART3_BASE + 0x30)
#define UART3_SFREGH (OMAP_MPU_UART3_BASE + 0x34)
#define UART3_RXFLH (OMAP_MPU_UART3_BASE + 0x34)
#define UART3_BLR (OMAP_MPU_UART3_BASE + 0x38)
#define UART3_ACREG (OMAP_MPU_UART3_BASE + 0x3C)
#define UART3_DIV16 (OMAP_MPU_UART3_BASE + 0x3C)
#define UART3_SCR (OMAP_MPU_UART3_BASE + 0x40)
#define UART3_SSR (OMAP_MPU_UART3_BASE + 0x44)
#define UART3_EBLR (OMAP_MPU_UART3_BASE + 0x48)
#define UART3_OSC_12M_SEL (OMAP_MPU_UART3_BASE + 0x4C)
#define UART3_MVR (OMAP_MPU_UART3_BASE + 0x50)
#endif /* __ASM_ARCH_OMAP_H3_H */
......@@ -71,17 +71,11 @@ unsigned char fpga_read(int reg);
#endif /* CONFIG_ARCH_OMAP1510 */
#if defined (CONFIG_ARCH_OMAP1610)
#if defined (CONFIG_ARCH_OMAP16XX)
/* At OMAP1610 Innovator the Ethernet is directly connected to CS1 */
#define OMAP1610_ETHR_BASE 0xE8000000
#define OMAP1610_ETHR_SIZE SZ_4K
#define OMAP1610_ETHR_START 0x04000000
/* Intel STRATA NOR flash at CS3 */
#define OMAP1610_NOR_FLASH_BASE 0xD8000000
#define OMAP1610_NOR_FLASH_SIZE SZ_32M
#define OMAP1610_NOR_FLASH_START 0x0C000000
#define INNOVATOR1610_ETHR_START 0x04000000
#define INNOVATOR1610_ETHR_SIZE SZ_4K
#endif /* CONFIG_ARCH_OMAP1610 */
#endif /* __ASM_ARCH_OMAP_INNOVATOR_H */
......@@ -17,7 +17,12 @@
#define OMAP_TAG_CLOCK 0x4f01
#define OMAP_TAG_MMC 0x4f02
#define OMAP_TAG_UART 0x4f03
#define OMAP_TAG_USB 0x4f04
#define OMAP_TAG_USB 0x4f04
#define OMAP_TAG_LCD 0x4f05
#define OMAP_TAG_GPIO_SWITCH 0x4f06
#define OMAP_TAG_BOOT_REASON 0x4f80
#define OMAP_TAG_FLASH_PART 0x4f81
struct omap_clock_config {
/* 0 for 12 MHz, 1 for 13 MHz and 2 for 19.2 MHz */
......@@ -26,8 +31,8 @@ struct omap_clock_config {
struct omap_mmc_config {
u8 mmc_blocks;
s8 mmc1_power_pin, mmc2_power_pin;
s8 mmc1_switch_pin, mmc2_switch_pin;
s16 mmc1_power_pin, mmc2_power_pin;
s16 mmc1_switch_pin, mmc2_switch_pin;
};
struct omap_uart_config {
......@@ -63,6 +68,38 @@ struct omap_usb_config {
u8 pins[3];
};
struct omap_lcd_config {
char panel_name[16];
char ctrl_name[16];
};
/* Cover:
* high -> closed
* low -> open
* Connection:
* high -> connected
* low -> disconnected
*/
#define OMAP_GPIO_SWITCH_TYPE_COVER 0x0000
#define OMAP_GPIO_SWITCH_TYPE_CONNECTION 0x0001
#define OMAP_GPIO_SWITCH_FLAG_INVERTED 0x0001
struct omap_gpio_switch_config {
char name[12];
u16 gpio;
int flags:4;
int type:4;
int key_code:24; /* Linux key code */
};
struct omap_flash_part_config {
char part_table[0];
};
struct omap_boot_reason_config {
char reason_str[12];
};
struct omap_board_config_entry {
u16 tag;
u16 len;
......@@ -74,10 +111,14 @@ struct omap_board_config_kernel {
const void *data;
};
extern const void *__omap_get_config(u16 tag, size_t len);
extern const void *__omap_get_config(u16 tag, size_t len, int nr);
#define omap_get_config(tag, type) \
((const type *) __omap_get_config((tag), sizeof(type)))
((const type *) __omap_get_config((tag), sizeof(type), 0))
#define omap_get_nr_config(tag, type, nr) \
((const type *) __omap_get_config((tag), sizeof(type), (nr)))
extern const void *omap_get_var_config(u16 tag, size_t *len);
extern struct omap_board_config_kernel *omap_board_config;
extern int omap_board_config_size;
......
/*
* linux/include/asm-arm/arch-omap/cpu.h
*
* OMAP cpu type detection
*
* Copyright (C) 2004 Nokia Corporation
*
* Written by Tony Lindgren <tony.lindgren@nokia.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#ifndef __ASM_ARCH_OMAP_CPU_H
#define __ASM_ARCH_OMAP_CPU_H
extern unsigned int system_rev;
#define OMAP_DIE_ID_0 0xfffe1800
#define OMAP_DIE_ID_1 0xfffe1804
#define OMAP_PRODUCTION_ID_0 0xfffe2000
#define OMAP_PRODUCTION_ID_1 0xfffe2004
#define OMAP32_ID_0 0xfffed400
#define OMAP32_ID_1 0xfffed404
/*
* Test if multicore OMAP support is needed
*/
#undef MULTI_OMAP
#undef OMAP_NAME
#ifdef CONFIG_ARCH_OMAP730
# ifdef OMAP_NAME
# undef MULTI_OMAP
# define MULTI_OMAP
# else
# define OMAP_NAME omap730
# endif
#endif
#ifdef CONFIG_ARCH_OMAP1510
# ifdef OMAP_NAME
# undef MULTI_OMAP
# define MULTI_OMAP
# else
# define OMAP_NAME omap1510
# endif
#endif
#ifdef CONFIG_ARCH_OMAP16XX
# ifdef OMAP_NAME
# undef MULTI_OMAP
# define MULTI_OMAP
# else
# define OMAP_NAME omap1610
# endif
#endif
#ifdef CONFIG_ARCH_OMAP16XX
# ifdef OMAP_NAME
# undef MULTI_OMAP
# define MULTI_OMAP
# else
# define OMAP_NAME omap1710
# endif
#endif
/*
* Generate various OMAP cpu specific macros, and cpu class
* specific macros
*/
#define GET_OMAP_TYPE ((system_rev >> 24) & 0xff)
#define GET_OMAP_CLASS (system_rev & 0xff)
#define IS_OMAP_TYPE(type, id) \
static inline int is_omap ##type (void) \
{ \
return (GET_OMAP_TYPE == (id)) ? 1 : 0; \
}
#define IS_OMAP_CLASS(class, id) \
static inline int is_omap ##class (void) \
{ \
return (GET_OMAP_CLASS == (id)) ? 1 : 0; \
}
IS_OMAP_TYPE(730, 0x07)
IS_OMAP_TYPE(1510, 0x15)
IS_OMAP_TYPE(1610, 0x16)
IS_OMAP_TYPE(5912, 0x16)
IS_OMAP_TYPE(1710, 0x17)
IS_OMAP_TYPE(2420, 0x24)
IS_OMAP_CLASS(7xx, 0x07)
IS_OMAP_CLASS(15xx, 0x15)
IS_OMAP_CLASS(16xx, 0x16)
IS_OMAP_CLASS(24xx, 0x24)
/*
* Macros to group OMAP types into cpu classes.
* These can be used in most places.
* cpu_is_omap15xx(): True for 1510 and 5910
* cpu_is_omap16xx(): True for 1610, 5912 and 1710
*/
#if defined(MULTI_OMAP)
# define cpu_is_omap7xx() is_omap7xx()
# define cpu_is_omap15xx() is_omap15xx()
# if !(defined(CONFIG_ARCH_OMAP1510) || defined(CONFIG_ARCH_OMAP730))
# define cpu_is_omap16xx() 1
# else
# define cpu_is_omap16xx() is_omap16xx()
# endif
#else
# if defined(CONFIG_ARCH_OMAP730)
# define cpu_is_omap7xx() 1
# else
# define cpu_is_omap7xx() 0
# endif
# if defined(CONFIG_ARCH_OMAP1510)
# define cpu_is_omap15xx() 1
# else
# define cpu_is_omap15xx() 0
# endif
# if defined(CONFIG_ARCH_OMAP16XX)
# define cpu_is_omap16xx() 1
# else
# define cpu_is_omap16xx() 0
# endif
#endif
#if defined(MULTI_OMAP)
# define cpu_is_omap730() is_omap730()
# define cpu_is_omap1510() is_omap1510()
# define cpu_is_omap1610() is_omap1610()
# define cpu_is_omap5912() is_omap5912()
# define cpu_is_omap1710() is_omap1710()
#else
# if defined(CONFIG_ARCH_OMAP730)
# define cpu_is_omap730() 1
# else
# define cpu_is_omap730() 0
# endif
# if defined(CONFIG_ARCH_OMAP1510)
# define cpu_is_omap1510() 1
# else
# define cpu_is_omap1510() 0
# endif
# if defined(CONFIG_ARCH_OMAP16XX)
# define cpu_is_omap1610() 1
# else
# define cpu_is_omap1610() 0
# endif
# if defined(CONFIG_ARCH_OMAP16XX)
# define cpu_is_omap5912() 1
# else
# define cpu_is_omap5912() 0
# endif
# if defined(CONFIG_ARCH_OMAP16XX)
# define cpu_is_omap1610() is_omap1610()
# define cpu_is_omap5912() is_omap5912()
# define cpu_is_omap1710() is_omap1710()
# else
# define cpu_is_omap1610() 0
# define cpu_is_omap5912() 0
# define cpu_is_omap1710() 0
# endif
# if defined(CONFIG_ARCH_OMAP2420)
# define cpu_is_omap2420() 1
# else
# define cpu_is_omap2420() 0
# endif
#endif
#endif
......@@ -194,11 +194,19 @@ enum {
OMAP_LCD_DMA_B2_BOTTOM
};
enum {
enum omap_dma_burst_mode {
OMAP_DMA_DATA_BURST_DIS = 0,
OMAP_DMA_DATA_BURST_4,
OMAP_DMA_DATA_BURST_8
};
enum omap_dma_color_mode {
OMAP_DMA_COLOR_DIS = 0,
OMAP_DMA_CONSTANT_FILL,
OMAP_DMA_TRANSPARENT_COPY
};
extern void omap_set_dma_priority(int dst_port, int priority);
extern int omap_request_dma(int dev_id, const char *dev_name,
void (* callback)(int lch, u16 ch_status, void *data),
void *data, int *dma_ch);
......@@ -210,20 +218,22 @@ extern void omap_stop_dma(int lch);
extern void omap_set_dma_transfer_params(int lch, int data_type,
int elem_count, int frame_count,
int sync_mode);
extern void omap_set_dma_constant_fill(int lch, u32 color);
extern void omap_set_dma_transparent_copy(int lch, u32 color);
extern void omap_set_dma_color_mode(int lch, enum omap_dma_color_mode mode,
u32 color);
extern void omap_set_dma_src_params(int lch, int src_port, int src_amode,
unsigned long src_start);
extern void omap_set_dma_src_index(int lch, int eidx, int fidx);
extern void omap_set_dma_src_data_pack(int lch, int enable);
extern void omap_set_dma_src_burst_mode(int lch, int burst_mode);
extern void omap_set_dma_src_burst_mode(int lch,
enum omap_dma_burst_mode burst_mode);
extern void omap_set_dma_dest_params(int lch, int dest_port, int dest_amode,
unsigned long dest_start);
extern void omap_set_dma_dest_index(int lch, int eidx, int fidx);
extern void omap_set_dma_dest_data_pack(int lch, int enable);
extern void omap_set_dma_dest_burst_mode(int lch, int burst_mode);
extern void omap_set_dma_dest_burst_mode(int lch,
enum omap_dma_burst_mode burst_mode);
extern void omap_dma_link_lch (int lch_head, int lch_queue);
extern void omap_dma_unlink_lch (int lch_head, int lch_queue);
......@@ -235,10 +245,16 @@ extern int omap_dma_in_1510_mode(void);
extern int omap_request_lcd_dma(void (* callback)(u16 status, void *data),
void *data);
extern void omap_free_lcd_dma(void);
extern void omap_start_lcd_dma(void);
extern void omap_setup_lcd_dma(void);
extern void omap_enable_lcd_dma(void);
extern void omap_stop_lcd_dma(void);
extern void omap_set_lcd_dma_ext_controller(int external);
extern void omap_set_lcd_dma_single_transfer(int single);
extern void omap_set_lcd_dma_b1(unsigned long addr, u16 fb_xres, u16 fb_yres,
int data_type);
extern void omap_set_lcd_dma_b1_rotation(int rotate);
extern void omap_set_lcd_dma_b1_vxres(unsigned long vxres);
extern void omap_set_lcd_dma_b1_mirror(int mirror);
extern void omap_set_lcd_dma_b1_scale(unsigned int xscale, unsigned int yscale);
#endif /* __ASM_ARCH_DMA_H */
......@@ -40,6 +40,7 @@
#include <linux/config.h>
#ifndef __ASSEMBLER__
#include <asm/types.h>
#include <asm/arch/cpu.h>
#endif
#include <asm/arch/io.h>
......@@ -64,6 +65,7 @@
#define ARM_RSTCT1 (CLKGEN_REG_BASE + 0x10)
#define ARM_RSTCT2 (CLKGEN_REG_BASE + 0x14)
#define ARM_SYSST (CLKGEN_REG_BASE + 0x18)
#define ARM_IDLECT3 (CLKGEN_REG_BASE + 0x24)
#define CK_RATEF 1
#define CK_IDLEF 2
......@@ -140,12 +142,12 @@
#define MPUTIM_AR (1<<1)
#define MPUTIM_ST (1<<0)
/* Watchdog */
#define OMAP_WATCHDOG_BASE (0xfffec800)
#define OMAP_WDT_TIMER (OMAP_WATCHDOG_BASE + 0x0)
#define OMAP_WDT_LOAD_TIM (OMAP_WATCHDOG_BASE + 0x4)
#define OMAP_WDT_READ_TIM (OMAP_WATCHDOG_BASE + 0x4)
#define OMAP_WDT_TIMER_MODE (OMAP_WATCHDOG_BASE + 0x8)
/* Watchdog timer within the OMAP3.2 gigacell */
#define OMAP_MPU_WATCHDOG_BASE (0xfffec800)
#define OMAP_WDT_TIMER (OMAP_MPU_WATCHDOG_BASE + 0x0)
#define OMAP_WDT_LOAD_TIM (OMAP_MPU_WATCHDOG_BASE + 0x4)
#define OMAP_WDT_READ_TIM (OMAP_MPU_WATCHDOG_BASE + 0x4)
#define OMAP_WDT_TIMER_MODE (OMAP_MPU_WATCHDOG_BASE + 0x8)
/*
* ---------------------------------------------------------------------------
......@@ -186,22 +188,22 @@
* ---------------------------------------------------------------------------
*/
#define TCMIF_BASE 0xfffecc00
#define IMIF_PRIO_REG __REG32(TCMIF_BASE + 0x00)
#define EMIFS_PRIO_REG __REG32(TCMIF_BASE + 0x04)
#define EMIFF_PRIO_REG __REG32(TCMIF_BASE + 0x08)
#define EMIFS_CONFIG_REG __REG32(TCMIF_BASE + 0x0c)
#define EMIFS_CS0_CONFIG_REG __REG32(TCMIF_BASE + 0x10)
#define EMIFS_CS1_CONFIG_REG __REG32(TCMIF_BASE + 0x14)
#define EMIFS_CS2_CONFIG_REG __REG32(TCMIF_BASE + 0x18)
#define EMIFS_CS3_CONFIG_REG __REG32(TCMIF_BASE + 0x1c)
#define EMIFF_SDRAM_CONFIG_REG __REG32(TCMIF_BASE + 0x20)
#define EMIFF_MRS_REG __REG32(TCMIF_BASE + 0x24)
#define TC_TIMEOUT1_REG __REG32(TCMIF_BASE + 0x28)
#define TC_TIMEOUT2_REG __REG32(TCMIF_BASE + 0x2c)
#define TC_TIMEOUT3_REG __REG32(TCMIF_BASE + 0x30)
#define TC_ENDIANISM_REG __REG32(TCMIF_BASE + 0x34)
#define EMIFF_SDRAM_CONFIG_2_REG __REG32(TCMIF_BASE + 0x3c)
#define EMIF_CFG_DYNAMIC_WS_REG __REG32(TCMIF_BASE + 0x40)
#define IMIF_PRIO (TCMIF_BASE + 0x00)
#define EMIFS_PRIO (TCMIF_BASE + 0x04)
#define EMIFF_PRIO (TCMIF_BASE + 0x08)
#define EMIFS_CONFIG (TCMIF_BASE + 0x0c)
#define EMIFS_CS0_CONFIG (TCMIF_BASE + 0x10)
#define EMIFS_CS1_CONFIG (TCMIF_BASE + 0x14)
#define EMIFS_CS2_CONFIG (TCMIF_BASE + 0x18)
#define EMIFS_CS3_CONFIG (TCMIF_BASE + 0x1c)
#define EMIFF_SDRAM_CONFIG (TCMIF_BASE + 0x20)
#define EMIFF_MRS (TCMIF_BASE + 0x24)
#define TC_TIMEOUT1 (TCMIF_BASE + 0x28)
#define TC_TIMEOUT2 (TCMIF_BASE + 0x2c)
#define TC_TIMEOUT3 (TCMIF_BASE + 0x30)
#define TC_ENDIANISM (TCMIF_BASE + 0x34)
#define EMIFF_SDRAM_CONFIG_2 (TCMIF_BASE + 0x3c)
#define EMIF_CFG_DYNAMIC_WS (TCMIF_BASE + 0x40)
/*
* ----------------------------------------------------------------------------
......@@ -235,6 +237,7 @@
#define PULL_DWN_CTRL_1 0xfffe1044
#define PULL_DWN_CTRL_2 0xfffe1048
#define PULL_DWN_CTRL_3 0xfffe104c
#define PULL_DWN_CTRL_4 0xfffe10ac
/* OMAP-1610 specific multiplexing registers */
#define FUNC_MUX_CTRL_E 0xfffe1090
......@@ -248,6 +251,9 @@
#define PU_PD_SEL_3 0xfffe10c0
#define PU_PD_SEL_4 0xfffe10c4
/* Timer32K for 1610 and 1710*/
#define OMAP_TIMER32K_BASE 0xFFFBC400
/*
* ---------------------------------------------------------------------------
* TIPB bus interface
......@@ -277,62 +283,24 @@
/*
* ---------------------------------------------------------------------------
* Processor differentiation
* Processor specific defines
* ---------------------------------------------------------------------------
*/
#define OMAP_ID_BASE (0xfffed400)
#define OMAP_ID_REG __REG32(OMAP_ID_BASE + 0x04)
#define ID_SHIFT 12
#define ID_MASK 0x7fff
/* See also uncompress.h */
#define OMAP_ID_730 0x355F
#define OMAP_ID_1510 0x3470
#define OMAP_ID_1610 0x3576
#define OMAP_ID_1710 0x35F7
#define OMAP_ID_5912 0x358C
#define OMAP_ID_1611 0x358C
#ifdef CONFIG_ARCH_OMAP730
#include "omap730.h"
#define cpu_is_omap730() (((OMAP_ID_REG >> ID_SHIFT) & ID_MASK) == OMAP_ID_730)
#else
#define cpu_is_omap730() 0
#endif
#ifdef CONFIG_ARCH_OMAP1510
#include "omap1510.h"
#define cpu_is_omap1510() (((OMAP_ID_REG >> ID_SHIFT) & ID_MASK) == OMAP_ID_1510)
#else
#define cpu_is_omap1510() 0
#endif
#ifdef CONFIG_ARCH_OMAP1610
#include "omap1610.h"
#define cpu_is_omap1610() (((OMAP_ID_REG >> ID_SHIFT) & ID_MASK) == OMAP_ID_1610) || \
(((OMAP_ID_REG >> ID_SHIFT) & ID_MASK) == OMAP_ID_1611)
#else
#define cpu_is_omap1610() 0
#endif
#ifdef CONFIG_ARCH_OMAP1710
#include "omap1610.h"
#define cpu_is_omap1710() (((OMAP_ID_REG >> ID_SHIFT) & ID_MASK) == OMAP_ID_1710)
#else
#define cpu_is_omap1710() 0
#endif
#ifdef CONFIG_ARCH_OMAP5912
#include "omap5912.h"
#define cpu_is_omap5912() (((OMAP_ID_REG >> ID_SHIFT) & ID_MASK) == OMAP_ID_5912)
#else
#define cpu_is_omap5912() 0
#ifdef CONFIG_ARCH_OMAP16XX
#include "omap16xx.h"
#endif
/*
* ---------------------------------------------------------------------------
* Board differentiation
* Board specific defines
* ---------------------------------------------------------------------------
*/
......
......@@ -192,8 +192,6 @@
#define INT_730_TIMER32K (22 + IH2_BASE)
#define INT_730_MMC_SDIO (23 + IH2_BASE)
#define INT_730_UPLD (24 + IH2_BASE)
#define INT_730_RTC_TIMER (25 + IH2_BASE)
#define INT_730_RTC_ALARM (26 + IH2_BASE)
#define INT_730_USB_HHC_1 (27 + IH2_BASE)
#define INT_730_USB_HHC_2 (28 + IH2_BASE)
#define INT_730_USB_GENI (29 + IH2_BASE)
......@@ -224,24 +222,6 @@
#define INT_730_DMA_CH15 (62 + IH2_BASE)
#define INT_730_NAND (63 + IH2_BASE)
/* OMAP-730 differences */
#ifdef CONFIG_ARCH_OMAP730
#undef INT_IH2_IRQ
#define INT_IH2_IRQ INT_730_IH2_IRQ
#undef INT_KEYBOARD
#define INT_KEYBOARD INT_730_MPUIO_KEYPAD
#undef INT_UART1
#define INT_UART1 INT_730_UART_MODEM_1
#undef INT_UART2
#define INT_UART2 INT_730_UART_MODEM_IRDA_2
#undef INT_MPUIO
#define INT_MPUIO INT_730_MPUIO
#undef INT_RTC_TIMER
#define INT_RTC_TIMER INT_730_RTC_TIMER
#undef INT_RTC_ALARM
#define INT_RTC_ALARM INT_730_RTC_ALARM
#endif
/* Max. 128 level 2 IRQs (OMAP1610), 192 GPIOs (OMAP730) and
* 16 MPUIO lines */
#define OMAP_MAX_GPIO_LINES 192
......@@ -260,7 +240,7 @@ extern void omap_init_irq(void);
#include <asm/arch/hardware.h>
#ifndef NR_IRQS
#define NR_IRQS 256
#define NR_IRQS IH_BOARD_BASE
#endif
#endif
......@@ -29,7 +29,7 @@
#define OMAP730_MCBSP1_BASE 0xfffb1000
#define OMAP730_MCBSP2_BASE 0xfffb1800
#define OMAP1510_MCBSP1_BASE 0xe1011000
#define OMAP1510_MCBSP1_BASE 0xe1011800
#define OMAP1510_MCBSP2_BASE 0xfffb1000
#define OMAP1510_MCBSP3_BASE 0xe1017000
......
......@@ -59,12 +59,14 @@
* OMAP-1510 bus address is translated into a Local Bus address if the
* OMAP bus type is lbus. We do the address translation based on the
* device overriding the defaults used in the dma-mapping API.
* Note that the is_lbus_device() test is not very efficient on 1510
* because of the strncmp().
*/
#ifdef CONFIG_ARCH_OMAP1510
#define virt_to_lbus(x) ((x) - PAGE_OFFSET + OMAP1510_LB_OFFSET)
#define lbus_to_virt(x) ((x) - OMAP1510_LB_OFFSET + PAGE_OFFSET)
#define is_lbus_device(dev) (cpu_is_omap1510() && dev && dev->coherent_dma_mask == 0x0fffffff)
#define is_lbus_device(dev) (cpu_is_omap1510() && dev && (strncmp(dev->bus_id, "ohci", 4) == 0))
#define __arch_page_to_dma(dev, page) ({is_lbus_device(dev) ? \
(dma_addr_t)virt_to_lbus(page_address(page)) : \
......
......@@ -43,9 +43,7 @@
#define PU_PD_SEL_NA 0 /* No pu_pd reg available */
#define PULL_DWN_CTRL_NA 0 /* No pull-down control needed */
#define DEBUG_MUX
#ifdef DEBUG_MUX
#ifdef CONFIG_OMAP_MUX_DEBUG
#define MUX_REG(reg, mode_offset, mode) .mux_reg_name = "FUNC_MUX_CTRL_"#reg, \
.mux_reg = FUNC_MUX_CTRL_##reg, \
.mask_offset = mode_offset, \
......@@ -73,7 +71,7 @@
#define PU_PD_REG(reg, status) .pu_pd_reg = PU_PD_SEL_##reg, \
.pu_pd_val = status,
#endif // DEBUG_MUX
#endif /* CONFIG_OMAP_MUX_DEBUG */
#define MUX_CFG(desc, mux_reg, mode_offset, mode, \
pull_reg, pull_bit, pull_status, \
......@@ -134,6 +132,7 @@ typedef enum {
UART3_RTS,
UART3_CLKREQ,
UART3_BCLK, /* 12MHz clock out */
Y15_1610_UART3_RTS,
/* PWT & PWL */
PWT,
......@@ -174,8 +173,13 @@ typedef enum {
R19_1510_GPIO1,
M14_1510_GPIO2,
/* OMAP1610 GPIO */
Y15_1610_GPIO17,
/* OMAP-1710 GPIO */
R18_1710_GPIO0,
V2_1710_GPIO10,
N21_1710_GPIO14,
W15_1710_GPIO40,
/* MPUIO */
......@@ -244,6 +248,10 @@ typedef enum {
P15_1610_UWIRE_CS0,
N15_1610_UWIRE_CS1,
/* OMAP-1610 Flash */
L3_1610_FLASH_CS2B_OE,
M8_1610_FLASH_CS2B_WE,
/* First MMC */
MMC_CMD,
MMC_DAT1,
......@@ -310,7 +318,8 @@ typedef enum {
* Table of various FUNC_MUX and PULL_DWN combinations for each device.
* See also reg_cfg_t above for the lookup table.
*/
static reg_cfg_set reg_cfg_table[] = {
static reg_cfg_set __initdata_or_module
reg_cfg_table[] = {
/*
* description mux mode mux pull pull pull pu_pd pu dbg
* reg offset mode reg bit ena reg
......@@ -331,6 +340,7 @@ MUX_CFG("UART3_CTS", 5, 12, 2, 0, 24, 0, NA, 0, 0)
MUX_CFG("UART3_RTS", 5, 15, 2, 0, 25, 0, NA, 0, 0)
MUX_CFG("UART3_CLKREQ", 9, 27, 0, 2, 5, 0, NA, 0, 0)
MUX_CFG("UART3_BCLK", A, 0, 0, 2, 6, 0, NA, 0, 0)
MUX_CFG("Y15_1610_UART3_RTS", A, 0, 1, 2, 6, 0, NA, 0, 0)
/* PWT & PWL, conflicts with UART3 */
MUX_CFG("PWT", 6, 0, 2, 0, 30, 0, NA, 0, 0)
......@@ -371,9 +381,14 @@ MUX_CFG("R18_1510_GPIO0", 7, 9, 0, 1, 11, 1, 0, 0, 1)
MUX_CFG("R19_1510_GPIO1", 7, 6, 0, 1, 10, 1, 0, 0, 1)
MUX_CFG("M14_1510_GPIO2", 7, 3, 0, 1, 9, 1, 0, 0, 1)
/* OMAP1610 GPIO */
MUX_CFG("Y15_1610_GPIO17", A, 0, 7, 2, 6, 0, NA, 0, 1)
/* OMAP-1710 GPIO */
MUX_CFG("R18_1710_GPIO0", 7, 9, 0, 1, 11, 1, 1, 1, 1)
MUX_CFG("W15_1710_GPIO40", 9, 27, 7, 2, 5, 1, 2, 1, 1)
MUX_CFG("R18_1710_GPIO0", 7, 9, 0, 1, 11, 1, 1, 1, 1)
MUX_CFG("V2_1710_GPIO10", F, 27, 1, 4, 3, 1, 4, 1, 1)
MUX_CFG("N21_1710_GPIO14", 6, 9, 0, 1, 1, 1, 1, 1, 1)
MUX_CFG("W15_1710_GPIO40", 9, 27, 7, 2, 5, 1, 2, 1, 1)
/* MPUIO */
MUX_CFG("MPUIO2", 7, 18, 0, 1, 1, 1, NA, 0, 1)
......@@ -442,6 +457,10 @@ MUX_CFG("N14_1610_UWIRE_CS0", 8, 9, 1, 1, 21, 0, 1, 1, 1)
MUX_CFG("P15_1610_UWIRE_CS3", 8, 12, 1, 1, 22, 0, 1, 1, 1)
MUX_CFG("N15_1610_UWIRE_CS1", 7, 18, 2, 1, 14, 0, NA, 0, 1)
/* OMAP-1610 Flash */
MUX_CFG("L3_1610_FLASH_CS2B_OE",10, 6, 1, NA, 0, 0, NA, 0, 1)
MUX_CFG("M8_1610_FLASH_CS2B_WE",10, 3, 1, NA, 0, 0, NA, 0, 1)
/* First MMC interface, same on 1510, 1610 and 1710 */
MUX_CFG("MMC_CMD", A, 27, 0, 2, 15, 1, 2, 1, 1)
MUX_CFG("MMC_DAT1", A, 24, 0, 2, 14, 1, 2, 1, 1)
......@@ -501,6 +520,12 @@ MUX_CFG("T20_1610_LOW_PWR", 7, 12, 1, NA, 0, 0, NA, 0, 0)
#endif /* __MUX_C__ */
#ifdef CONFIG_OMAP_MUX
/* setup pin muxing in Linux */
extern int omap_cfg_reg(reg_cfg_t reg_cfg);
#else
/* boot loader does it all (no warnings from CONFIG_OMAP_MUX_WARNINGS) */
static inline int omap_cfg_reg(reg_cfg_t reg_cfg) { return 0; }
#endif
#endif
/* linux/include/asm-arm/arch-omap/omap1610.h
/* linux/include/asm-arm/arch-omap/omap16xx.h
*
* Hardware definitions for TI OMAP1610 processor.
* Hardware definitions for TI OMAP1610/5912/1710 processors.
*
* Cleanup for Linux-2.6 by Dirk Behme <dirk.behme@de.bosch.com>
*
......@@ -25,8 +25,8 @@
* 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef __ASM_ARCH_OMAP1610_H
#define __ASM_ARCH_OMAP1610_H
#ifndef __ASM_ARCH_OMAP16XX_H
#define __ASM_ARCH_OMAP16XX_H
/*
* ----------------------------------------------------------------------------
......@@ -36,17 +36,18 @@
/* Syntax: XX_BASE = Virtual base address, XX_START = Physical base address */
#define OMAP1610_SRAM_BASE 0xD0000000
#define OMAP16XX_SRAM_BASE 0xD0000000
#define OMAP1610_SRAM_SIZE (SZ_16K)
#define OMAP1610_SRAM_START 0x20000000
#define OMAP5912_SRAM_SIZE 0x3E800
#define OMAP16XX_SRAM_START 0x20000000
#define OMAP1610_DSP_BASE 0xE0000000
#define OMAP1610_DSP_SIZE 0x28000
#define OMAP1610_DSP_START 0xE0000000
#define OMAP16XX_DSP_BASE 0xE0000000
#define OMAP16XX_DSP_SIZE 0x28000
#define OMAP16XX_DSP_START 0xE0000000
#define OMAP1610_DSPREG_BASE 0xE1000000
#define OMAP1610_DSPREG_SIZE SZ_128K
#define OMAP1610_DSPREG_START 0xE1000000
#define OMAP16XX_DSPREG_BASE 0xE1000000
#define OMAP16XX_DSPREG_SIZE SZ_128K
#define OMAP16XX_DSPREG_START 0xE1000000
/*
* ----------------------------------------------------------------------------
......@@ -54,7 +55,8 @@
* ----------------------------------------------------------------------------
*/
#define OMAP1610_SRAM_IDLE_SUSPEND (OMAP1610_SRAM_BASE + OMAP1610_SRAM_SIZE - 0x200)
#define OMAP1610_SRAM_IDLE_SUSPEND (OMAP16XX_SRAM_BASE + OMAP1610_SRAM_SIZE - 0x200)
#define OMAP5912_SRAM_IDLE_SUSPEND (OMAP16XX_SRAM_BASE + OMAP5912_SRAM_SIZE - 0x200)
#define OMAP1610_SRAM_API_SUSPEND (OMAP1610_SRAM_IDLE_SUSPEND + 0x100)
/*
......@@ -104,18 +106,18 @@
* Clocks
* ----------------------------------------------------------------------------
*/
#define OMAP1610_ARM_IDLECT3 (CLKGEN_REG_BASE + 0x24)
#define OMAP16XX_ARM_IDLECT3 (CLKGEN_REG_BASE + 0x24)
/*
* ----------------------------------------------------------------------------
* Pin configuration registers
* ----------------------------------------------------------------------------
*/
#define OMAP1610_CONF_VOLTAGE_VDDSHV6 (1 << 8)
#define OMAP1610_CONF_VOLTAGE_VDDSHV7 (1 << 9)
#define OMAP1610_CONF_VOLTAGE_VDDSHV8 (1 << 10)
#define OMAP1610_CONF_VOLTAGE_VDDSHV9 (1 << 11)
#define OMAP1610_SUBLVDS_CONF_VALID (1 << 13)
#define OMAP16XX_CONF_VOLTAGE_VDDSHV6 (1 << 8)
#define OMAP16XX_CONF_VOLTAGE_VDDSHV7 (1 << 9)
#define OMAP16XX_CONF_VOLTAGE_VDDSHV8 (1 << 10)
#define OMAP16XX_CONF_VOLTAGE_VDDSHV9 (1 << 11)
#define OMAP16XX_SUBLVDS_CONF_VALID (1 << 13)
/*
* ---------------------------------------------------------------------------
......@@ -123,7 +125,55 @@
* ---------------------------------------------------------------------------
*/
#define TIPB_SWITCH_BASE (0xfffbc800)
#define OMAP1610_MMCSD2_SSW_MPU_CONF (TIPB_SWITCH_BASE + 0x160)
#define OMAP16XX_MMCSD2_SSW_MPU_CONF (TIPB_SWITCH_BASE + 0x160)
/* UART3 Registers Maping through MPU bus */
#define UART3_RHR (OMAP_UART3_BASE + 0)
#define UART3_THR (OMAP_UART3_BASE + 0)
#define UART3_DLL (OMAP_UART3_BASE + 0)
#define UART3_IER (OMAP_UART3_BASE + 4)
#define UART3_DLH (OMAP_UART3_BASE + 4)
#define UART3_IIR (OMAP_UART3_BASE + 8)
#define UART3_FCR (OMAP_UART3_BASE + 8)
#define UART3_EFR (OMAP_UART3_BASE + 8)
#define UART3_LCR (OMAP_UART3_BASE + 0x0C)
#define UART3_MCR (OMAP_UART3_BASE + 0x10)
#define UART3_XON1_ADDR1 (OMAP_UART3_BASE + 0x10)
#define UART3_XON2_ADDR2 (OMAP_UART3_BASE + 0x14)
#define UART3_LSR (OMAP_UART3_BASE + 0x14)
#define UART3_TCR (OMAP_UART3_BASE + 0x18)
#define UART3_MSR (OMAP_UART3_BASE + 0x18)
#define UART3_XOFF1 (OMAP_UART3_BASE + 0x18)
#define UART3_XOFF2 (OMAP_UART3_BASE + 0x1C)
#define UART3_SPR (OMAP_UART3_BASE + 0x1C)
#define UART3_TLR (OMAP_UART3_BASE + 0x1C)
#define UART3_MDR1 (OMAP_UART3_BASE + 0x20)
#define UART3_MDR2 (OMAP_UART3_BASE + 0x24)
#define UART3_SFLSR (OMAP_UART3_BASE + 0x28)
#define UART3_TXFLL (OMAP_UART3_BASE + 0x28)
#define UART3_RESUME (OMAP_UART3_BASE + 0x2C)
#define UART3_TXFLH (OMAP_UART3_BASE + 0x2C)
#define UART3_SFREGL (OMAP_UART3_BASE + 0x30)
#define UART3_RXFLL (OMAP_UART3_BASE + 0x30)
#define UART3_SFREGH (OMAP_UART3_BASE + 0x34)
#define UART3_RXFLH (OMAP_UART3_BASE + 0x34)
#define UART3_BLR (OMAP_UART3_BASE + 0x38)
#define UART3_ACREG (OMAP_UART3_BASE + 0x3C)
#define UART3_DIV16 (OMAP_UART3_BASE + 0x3C)
#define UART3_SCR (OMAP_UART3_BASE + 0x40)
#define UART3_SSR (OMAP_UART3_BASE + 0x44)
#define UART3_EBLR (OMAP_UART3_BASE + 0x48)
#define UART3_OSC_12M_SEL (OMAP_UART3_BASE + 0x4C)
#define UART3_MVR (OMAP_UART3_BASE + 0x50)
#endif /* __ASM_ARCH_OMAP1610_H */
/*
* ----------------------------------------------------------------------------
* Pulse-Width Light
* ----------------------------------------------------------------------------
*/
#define OMAP16XX_PWL_BASE (0xfffb5800)
#define OMAP16XX_PWL_ENABLE (OMAP16XX_PWL_BASE + 0x00)
#define OMAP16XX_PWL_CLK_ENABLE (OMAP16XX_PWL_BASE + 0x04)
#endif /* __ASM_ARCH_OMAP16XX_H */
/* linux/include/asm-arm/arch-omap/omap5912.h
*
* Hardware definitions for TI OMAP5912 processor.
*
* Written by Dirk Behme <dirk.behme@de.bosch.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
* NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef __ASM_ARCH_OMAP5912_H
#define __ASM_ARCH_OMAP5912_H
/*
* ----------------------------------------------------------------------------
* Base addresses
* ----------------------------------------------------------------------------
*/
/* Syntax: XX_BASE = Virtual base address, XX_START = Physical base address */
/* OMAP5912 internal SRAM size is 250kByte */
#define OMAP5912_SRAM_BASE 0xD0000000
#define OMAP5912_SRAM_SIZE 0x3E800
#define OMAP5912_SRAM_START 0x20000000
#define OMAP5912_DSP_BASE 0xE0000000
#define OMAP5912_DSP_SIZE 0x50000
#define OMAP5912_DSP_START 0xE0000000
#define OMAP5912_DSPREG_BASE 0xE1000000
#define OMAP5912_DSPREG_SIZE SZ_128K
#define OMAP5912_DSPREG_START 0xE1000000
/*
* ----------------------------------------------------------------------------
* Memory used by power management
* ----------------------------------------------------------------------------
*/
#define OMAP5912_SRAM_IDLE_SUSPEND (OMAP5912_SRAM_BASE + OMAP5912_SRAM_SIZE - 0x200)
#define OMAP5912_SRAM_API_SUSPEND (OMAP5912_SRAM_IDLE_SUSPEND + 0x100)
/*
* ---------------------------------------------------------------------------
* Interrupts
* ---------------------------------------------------------------------------
*/
#define OMAP_IH2_0_BASE (0xfffe0000)
#define OMAP_IH2_1_BASE (0xfffe0100)
#define OMAP_IH2_2_BASE (0xfffe0200)
#define OMAP_IH2_3_BASE (0xfffe0300)
#define OMAP_IH2_0_ITR (OMAP_IH2_0_BASE + 0x00)
#define OMAP_IH2_0_MIR (OMAP_IH2_0_BASE + 0x04)
#define OMAP_IH2_0_SIR_IRQ (OMAP_IH2_0_BASE + 0x10)
#define OMAP_IH2_0_SIR_FIQ (OMAP_IH2_0_BASE + 0x14)
#define OMAP_IH2_0_CONTROL (OMAP_IH2_0_BASE + 0x18)
#define OMAP_IH2_0_ILR0 (OMAP_IH2_0_BASE + 0x1c)
#define OMAP_IH2_0_ISR (OMAP_IH2_0_BASE + 0x9c)
#define OMAP_IH2_1_ITR (OMAP_IH2_1_BASE + 0x00)
#define OMAP_IH2_1_MIR (OMAP_IH2_1_BASE + 0x04)
#define OMAP_IH2_1_SIR_IRQ (OMAP_IH2_1_BASE + 0x10)
#define OMAP_IH2_1_SIR_FIQ (OMAP_IH2_1_BASE + 0x14)
#define OMAP_IH2_1_CONTROL (OMAP_IH2_1_BASE + 0x18)
#define OMAP_IH2_1_ILR1 (OMAP_IH2_1_BASE + 0x1c)
#define OMAP_IH2_1_ISR (OMAP_IH2_1_BASE + 0x9c)
#define OMAP_IH2_2_ITR (OMAP_IH2_2_BASE + 0x00)
#define OMAP_IH2_2_MIR (OMAP_IH2_2_BASE + 0x04)
#define OMAP_IH2_2_SIR_IRQ (OMAP_IH2_2_BASE + 0x10)
#define OMAP_IH2_2_SIR_FIQ (OMAP_IH2_2_BASE + 0x14)
#define OMAP_IH2_2_CONTROL (OMAP_IH2_2_BASE + 0x18)
#define OMAP_IH2_2_ILR2 (OMAP_IH2_2_BASE + 0x1c)
#define OMAP_IH2_2_ISR (OMAP_IH2_2_BASE + 0x9c)
#define OMAP_IH2_3_ITR (OMAP_IH2_3_BASE + 0x00)
#define OMAP_IH2_3_MIR (OMAP_IH2_3_BASE + 0x04)
#define OMAP_IH2_3_SIR_IRQ (OMAP_IH2_3_BASE + 0x10)
#define OMAP_IH2_3_SIR_FIQ (OMAP_IH2_3_BASE + 0x14)
#define OMAP_IH2_3_CONTROL (OMAP_IH2_3_BASE + 0x18)
#define OMAP_IH2_3_ILR3 (OMAP_IH2_3_BASE + 0x1c)
#define OMAP_IH2_3_ISR (OMAP_IH2_3_BASE + 0x9c)
/*
* ----------------------------------------------------------------------------
* System control registers
* ----------------------------------------------------------------------------
*/
#define OMAP5912_ARM_IDLECT3 (CLKGEN_REG_BASE + 0x24)
#endif /* __ASM_ARCH_OMAP5912_H */
/*
* FILE NAME include/asm/arch-omap/pm.h
* linux/include/asm/arch-omap/pm.h
*
* BRIEF MODULE DESCRIPTION
* Header file for OMAP Power Management Routines
*
* Author: MontaVista Software, Inc.
* support@mvista.com
*
* Copyright 2002 MontaVista Software Inc.
*
* Cleanup 2004 for Linux 2.6 by Dirk Behme <dirk.behme@de.bosch.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
......@@ -29,158 +31,199 @@
* 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
* List of global OMAP registers to preserve. All registers are 16 bits
* and must be accessed with 16 read/writes.
* More ones like CP and general purpose register values are preserved
* with the stack pointer in sleep.S.
*/
#ifndef __ASM_ARCH_OMAP_PM_H
#define __ASM_ARCH_OMAP_PM_H
#define ARM_REG_BASE (0xfffece00)
#define ARM_ASM_IDLECT1 (ARM_REG_BASE + 0x4)
#define ARM_ASM_IDLECT2 (ARM_REG_BASE + 0x8)
#define ARM_ASM_RSTCT1 (ARM_REG_BASE + 0x10)
#define ARM_ASM_RSTCT2 (ARM_REG_BASE + 0x14)
#define ARM_ASM_SYSST (ARM_REG_BASE + 0x18)
/*
* Traffic Controller Memory Interface Registers
* ----------------------------------------------------------------------------
* Register and offset definitions to be used in PM assembler code
* ----------------------------------------------------------------------------
*/
#define TCMIF_BASE 0xfffecc00
#define EMIFS_ASM_CONFIG_REG (TCMIF_BASE + 0x0c)
#define EMIFF_ASM_SDRAM_CONFIG (TCMIF_BASE + 0x20)
#define IRQ_MIR1 (OMAP_IH1_BASE + IRQ_MIR)
#ifdef CONFIG_ARCH_OMAP1510
#define IRQ_MIR2 (OMAP_IH2_BASE + IRQ_MIR)
#else /* CONFIG_ARCH_OMAP1610 */
#define IRQ_MIR2_0 (OMAP_IH2_0_BASE + IRQ_MIR)
#define IRQ_MIR2_1 (OMAP_IH2_1_BASE + IRQ_MIR)
#define IRQ_MIR2_2 (OMAP_IH2_2_BASE + IRQ_MIR)
#define IRQ_MIR2_3 (OMAP_IH2_3_BASE + IRQ_MIR)
#endif
#define CLKGEN_REG_ASM_BASE io_p2v(0xfffece00)
#define ARM_IDLECT1_ASM_OFFSET 0x04
#define ARM_IDLECT2_ASM_OFFSET 0x08
#define TCMIF_ASM_BASE io_p2v(0xfffecc00)
#define EMIFS_CONFIG_ASM_OFFSET 0x0c
#define EMIFF_SDRAM_CONFIG_ASM_OFFSET 0x20
/*
* ----------------------------------------------------------------------------
* Powermanagement bitmasks
* ----------------------------------------------------------------------------
*/
#define IDLE_WAIT_CYCLES 0x00000fff
#define PERIPHERAL_ENABLE 0x2
#ifdef CONFIG_ARCH_OMAP1510
#define DEEP_SLEEP_REQUEST 0x0ec7
#define BIG_SLEEP_REQUEST 0x0cc5
#define IDLE_LOOP_REQUEST 0x0c00
#define IDLE_CLOCK_DOMAINS 0x2
#else /* CONFIG_ARCH_OMAP1610 */
#define DEEP_SLEEP_REQUEST 0x17c7
#define BIG_SLEEP_REQUEST TBD
#define IDLE_LOOP_REQUEST 0x0400
#define IDLE_CLOCK_DOMAINS 0x09c7
#endif
#define SELF_REFRESH_MODE 0x0c000001
#define IDLE_EMIFS_REQUEST 0xc
#define MODEM_32K_EN 0x1
#define PER_EN 0x1
#ifndef __ASSEMBLER__
extern void omap_pm_idle(void);
extern void omap_pm_suspend(void);
extern int omap_cpu_suspend(unsigned short, unsigned short);
extern int omap_idle_loop_suspend(void);
#ifdef CONFIG_ARCH_OMAP1510
#define OMAP_SRAM_IDLE_SUSPEND 0xd002F000
#define OMAP_SRAM_API_SUSPEND 0xd002F200
#else /* CONFIG_ARCH_OMAP1610 */
#define OMAP_SRAM_IDLE_SUSPEND 0xd0000400
#define OMAP_SRAM_API_SUSPEND 0xd0000600
#endif
#define CPU_SUSPEND_SIZE 200
#define ARM_REG_BASE (0xfffece00)
#define ARM_ASM_IDLECT1 (ARM_REG_BASE + 0x4)
#define ARM_ASM_IDLECT2 (ARM_REG_BASE + 0x8)
#define ARM_ASM_RSTCT1 (ARM_REG_BASE + 0x10)
#define ARM_ASM_RSTCT2 (ARM_REG_BASE + 0x14)
#define ARM_ASM_SYSST (ARM_REG_BASE + 0x18)
#define TCMIF_BASE 0xfffecc00
#define PM_EMIFS_CONFIG_REG (TCMIF_BASE + 0x0c)
#define PM_EMIFF_SDRAM_CONFIG (TCMIF_BASE + 0x20)
#define FUNC_MUX_CTRL_LOW_PWR (0xfffe1020)
#ifdef CONFIG_ARCH_OMAP1510
#define ULPD_LOW_POWER_REQ 0x0001
#else /* CONFIG_ARCH_OMAP1610 */
#define ULPD_LOW_POWER_REQ 0x3
#endif
#define ULPD_LOW_PWR 0x1000
#define ULPD_LOW_POWER_EN 0x0001
#define CPU_SUSPEND_SIZE 200
#define ULPD_LOW_POWER_EN 0x0001
#define DSP_IDLE_DELAY 10
#define DSP_IDLE 0x0040
#define DSP_RST 0x0004
#define DSP_ENABLE 0x0002
#define SUFFICIENT_DSP_RESET_TIME 1000
#define DEFAULT_MPUI_CONFIG 0x05cf
#define ENABLE_XORCLK 0x2
#define DSP_RESET 0x2000
#define DSP_CLOCK_ENABLE 0x2000
#define DSP_IDLE_MODE 0x2
#define TC_IDLE_REQUEST (0x0000000c)
#define EMIFF_CONFIG_REG EMIFF_SDRAM_CONFIG
#define IRQ_LEVEL2 (1<<0)
#define IRQ_KEYBOARD (1<<1)
#define IRQ_UART2 (1<<15)
#define PDE_BIT 0x08
#define PWD_EN_BIT 0x04
#define EN_PERCK_BIT 0x04
#define OMAP1510_DEEP_SLEEP_REQUEST 0x0ec7
#define OMAP1510_BIG_SLEEP_REQUEST 0x0cc5
#define OMAP1510_IDLE_LOOP_REQUEST 0x0c00
#define OMAP1510_IDLE_CLOCK_DOMAINS 0x2
#define OMAP1510_ULPD_LOW_POWER_REQ 0x0001
#define ARM_SAVE(x) arm_sleep_save[ARM_SLEEP_SAVE_##x] = omap_readw(x)
#define ARM_RESTORE(x) omap_writew((unsigned short)arm_sleep_save[ARM_SLEEP_SAVE_##x], x)
#define OMAP1610_DEEP_SLEEP_REQUEST 0x17c7
#define OMAP1610_BIG_SLEEP_REQUEST TBD
#define OMAP1610_IDLE_LOOP_REQUEST 0x0400
#define OMAP1610_IDLE_CLOCK_DOMAINS 0x09c7
#define OMAP1610_ULPD_LOW_POWER_REQ 0x3
#ifndef OMAP1510_SRAM_IDLE_SUSPEND
#define OMAP1510_SRAM_IDLE_SUSPEND 0
#endif
#ifndef OMAP1610_SRAM_IDLE_SUSPEND
#define OMAP1610_SRAM_IDLE_SUSPEND 0
#endif
#ifndef OMAP5912_SRAM_IDLE_SUSPEND
#define OMAP5912_SRAM_IDLE_SUSPEND 0
#endif
#ifndef OMAP1510_SRAM_API_SUSPEND
#define OMAP1510_SRAM_API_SUSPEND 0
#endif
#ifndef OMAP1610_SRAM_API_SUSPEND
#define OMAP1610_SRAM_API_SUSPEND 0
#endif
#ifndef OMAP5912_SRAM_API_SUSPEND
#define OMAP5912_SRAM_API_SUSPEND 0
#endif
#if !defined(CONFIG_ARCH_OMAP1510) && \
!defined(CONFIG_ARCH_OMAP16XX)
#error "Power management for this processor not implemented yet"
#endif
#ifndef __ASSEMBLER__
extern void omap_pm_idle(void);
extern void omap_pm_suspend(void);
extern int omap1510_cpu_suspend(unsigned short, unsigned short);
extern int omap1610_cpu_suspend(unsigned short, unsigned short);
extern int omap1510_idle_loop_suspend(void);
extern int omap1610_idle_loop_suspend(void);
extern unsigned int omap1510_cpu_suspend_sz;
extern unsigned int omap1510_idle_loop_suspend_sz;
extern unsigned int omap1610_cpu_suspend_sz;
extern unsigned int omap1610_idle_loop_suspend_sz;
#define ARM_SAVE(x) arm_sleep_save[ARM_SLEEP_SAVE_##x] = omap_readl(x)
#define ARM_RESTORE(x) omap_writel((arm_sleep_save[ARM_SLEEP_SAVE_##x]), (x))
#define ARM_SHOW(x) arm_sleep_save[ARM_SLEEP_SAVE_##x]
#define ULPD_SAVE(x) ulpd_sleep_save[ULPD_SLEEP_SAVE_##x] = omap_readw(x)
#define ULPD_RESTORE(x) omap_writew((unsigned short)ulpd_sleep_save[ULPD_SLEEP_SAVE_##x], x)
#define ULPD_RESTORE(x) omap_writew((ulpd_sleep_save[ULPD_SLEEP_SAVE_##x]), (x))
#define ULPD_SHOW(x) ulpd_sleep_save[ULPD_SLEEP_SAVE_##x]
#define MPUI_SAVE(x) mpui_sleep_save[MPUI_SLEEP_SAVE_##x] = omap_readl(x)
#define MPUI_RESTORE(x) omap_writel((unsigned int)mpui_sleep_save[MPUI_SLEEP_SAVE_##x], x)
#define MPUI_SHOW(x) (unsigned int)mpui_sleep_save[MPUI_SLEEP_SAVE_##x]
#define MPUI1510_SAVE(x) mpui1510_sleep_save[MPUI1510_SLEEP_SAVE_##x] = omap_readl(x)
#define MPUI1510_RESTORE(x) omap_writel((mpui1510_sleep_save[MPUI1510_SLEEP_SAVE_##x]), (x))
#define MPUI1510_SHOW(x) mpui1510_sleep_save[MPUI1510_SLEEP_SAVE_##x]
#define MPUI1610_SAVE(x) mpui1610_sleep_save[MPUI1610_SLEEP_SAVE_##x] = omap_readl(x)
#define MPUI1610_RESTORE(x) omap_writel((mpui1610_sleep_save[MPUI1610_SLEEP_SAVE_##x]), (x))
#define MPUI1610_SHOW(x) mpui1610_sleep_save[MPUI1610_SLEEP_SAVE_##x]
/*
* List of global OMAP registers to preserve.
* More ones like CP and general purpose register values are preserved
* with the stack pointer in sleep.S.
*/
enum arm_save_state {
ARM_SLEEP_SAVE_START = 0,
/*
* 9 MPU control registers, all 16 bits
* MPU control registers 32 bits
*/
ARM_SLEEP_SAVE_ARM_CKCTL, ARM_SLEEP_SAVE_ARM_IDLECT1,
ARM_SLEEP_SAVE_ARM_IDLECT2, ARM_SLEEP_SAVE_ARM_EWUPCT,
ARM_SLEEP_SAVE_ARM_RSTCT1, ARM_SLEEP_SAVE_ARM_RSTCT2,
ARM_SLEEP_SAVE_ARM_CKCTL,
ARM_SLEEP_SAVE_ARM_IDLECT1,
ARM_SLEEP_SAVE_ARM_IDLECT2,
ARM_SLEEP_SAVE_ARM_EWUPCT,
ARM_SLEEP_SAVE_ARM_RSTCT1,
ARM_SLEEP_SAVE_ARM_RSTCT2,
ARM_SLEEP_SAVE_ARM_SYSST,
ARM_SLEEP_SAVE_SIZE
};
enum ulpd_save_state {
ULPD_SLEEP_SAVE_START = 0,
ULPD_SLEEP_SAVE_ULPD_IT_STATUS_REG, ULPD_SLEEP_SAVE_ULPD_CLOCK_CTRL_REG,
ULPD_SLEEP_SAVE_ULPD_SOFT_REQ_REG, ULPD_SLEEP_SAVE_ULPD_STATUS_REQ_REG,
ULPD_SLEEP_SAVE_ULPD_DPLL_CTRL_REG, ULPD_SLEEP_SAVE_ULPD_POWER_CTRL_REG,
/*
* ULPD registers 16 bits
*/
ULPD_SLEEP_SAVE_ULPD_IT_STATUS,
ULPD_SLEEP_SAVE_ULPD_CLOCK_CTRL,
ULPD_SLEEP_SAVE_ULPD_SOFT_REQ,
ULPD_SLEEP_SAVE_ULPD_STATUS_REQ,
ULPD_SLEEP_SAVE_ULPD_DPLL_CTRL,
ULPD_SLEEP_SAVE_ULPD_POWER_CTRL,
ULPD_SLEEP_SAVE_SIZE
};
enum mpui_save_state {
enum mpui1510_save_state {
MPUI1510_SLEEP_SAVE_START = 0,
/*
* MPUI registers 32 bits
*/
MPUI_SLEEP_SAVE_MPUI_CTRL_REG, MPUI_SLEEP_SAVE_MPUI_DSP_BOOT_CONFIG,
MPUI_SLEEP_SAVE_MPUI_DSP_API_CONFIG,
MPUI_SLEEP_SAVE_MPUI_DSP_STATUS_REG,
MPUI_SLEEP_SAVE_PM_EMIFF_SDRAM_CONFIG,
MPUI_SLEEP_SAVE_PM_EMIFS_CONFIG_REG,
MPUI_SLEEP_SAVE_IRQ_MIR1,
#ifdef CONFIG_ARCH_OMAP1510
MPUI_SLEEP_SAVE_IRQ_MIR2,
#else /* CONFIG_ARCH_OMAP1610 */
MPUI_SLEEP_SAVE_IRQ_MIR2_0,
MPUI_SLEEP_SAVE_IRQ_MIR2_1,
MPUI_SLEEP_SAVE_IRQ_MIR2_2,
MPUI_SLEEP_SAVE_IRQ_MIR2_3,
MPUI1510_SLEEP_SAVE_MPUI_CTRL,
MPUI1510_SLEEP_SAVE_MPUI_DSP_BOOT_CONFIG,
MPUI1510_SLEEP_SAVE_MPUI_DSP_API_CONFIG,
MPUI1510_SLEEP_SAVE_MPUI_DSP_STATUS,
MPUI1510_SLEEP_SAVE_EMIFF_SDRAM_CONFIG,
MPUI1510_SLEEP_SAVE_EMIFS_CONFIG,
MPUI1510_SLEEP_SAVE_OMAP_IH1_MIR,
MPUI1510_SLEEP_SAVE_OMAP_IH2_MIR,
#if defined(CONFIG_ARCH_OMAP1510)
MPUI1510_SLEEP_SAVE_SIZE
#else
MPUI1510_SLEEP_SAVE_SIZE = 0
#endif
MPUI_SLEEP_SAVE_SIZE
};
#endif /* ASSEMBLER */
enum mpui1610_save_state {
MPUI1610_SLEEP_SAVE_START = 0,
/*
* MPUI registers 32 bits
*/
MPUI1610_SLEEP_SAVE_MPUI_CTRL,
MPUI1610_SLEEP_SAVE_MPUI_DSP_BOOT_CONFIG,
MPUI1610_SLEEP_SAVE_MPUI_DSP_API_CONFIG,
MPUI1610_SLEEP_SAVE_MPUI_DSP_STATUS,
MPUI1610_SLEEP_SAVE_EMIFF_SDRAM_CONFIG,
MPUI1610_SLEEP_SAVE_EMIFS_CONFIG,
MPUI1610_SLEEP_SAVE_OMAP_IH1_MIR,
MPUI1610_SLEEP_SAVE_OMAP_IH2_0_MIR,
MPUI1610_SLEEP_SAVE_OMAP_IH2_1_MIR,
MPUI1610_SLEEP_SAVE_OMAP_IH2_2_MIR,
MPUI1610_SLEEP_SAVE_OMAP_IH2_3_MIR,
#if defined(CONFIG_ARCH_OMAP16XX)
MPUI1610_SLEEP_SAVE_SIZE
#else
MPUI1610_SLEEP_SAVE_SIZE = 0
#endif
};
#endif /* ASSEMBLER */
#endif /* __ASM_ARCH_OMAP_PM_H */
......@@ -12,6 +12,8 @@
#define OMAP_UART1_BASE (unsigned char *)0xfffb0000
#define OMAP_UART2_BASE (unsigned char *)0xfffb0800
#define OMAP_UART3_BASE (unsigned char *)0xfffb9800
#define OMAP_MAX_NR_PORTS 3
#define PORT_OMAP 16 /* Temporary */
#ifndef __ASSEMBLY__
......@@ -19,7 +21,9 @@
#include <asm/irq.h>
#define OMAP1510_BASE_BAUD (12000000/16)
#define OMAP1610_BASE_BAUD (48000000/16)
#define OMAP16XX_BASE_BAUD (48000000/16)
#define UART_SYSC 0x15
/* OMAP FCR trigger redefinitions */
#define UART_FCR_R_TRIGGER_8 0x00 /* Mask for receive trigger set at 8 */
......
/*
* linux/include/asm-arm/arch-omap/tc.h
*
* OMAP Traffic Controller
*
* Copyright (C) 2004 Nokia Corporation
* Author: Imre Deak <imre.deak@nokia.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __ASM_ARCH_TC_H
#define __ASM_ARCH_TC_H
#define OMAP_TC_OCPT1_PRIOR 0xFFFECC00
#define OMAP_TC_EMIFS_PRIOR 0xFFFECC04
#define OMAP_TC_EMIFF_PRIOR 0xFFFECC08
#define OMAP_TC_OCPT2_PRIOR 0xFFFECCD0
/* EMIF Slow Interface Configuration Register */
#define OMAP_EMIFS_CONFIG_REG __REG32(EMIFS_CONFIG)
#define OMAP_EMIFS_CONFIG_FR (1 << 4)
#define OMAP_EMIFS_CONFIG_PDE (1 << 3)
#define OMAP_EMIFS_CONFIG_PWD_EN (1 << 2)
#define OMAP_EMIFS_CONFIG_BM (1 << 1)
#define OMAP_EMIFS_CONFIG_WP (1 << 0)
/* external EMIFS chipselect regions */
#define OMAP_CS1_PHYS 0x04000000
#define OMAP_CS1_SIZE SZ_64M
#define OMAP_CS1A_PHYS OMAP_CS1_PHYS
#define OMAP_CS1A_SIZE SZ_32M
#define OMAP_CS1B_PHYS (OMAP_CS1A_PHYS + OMAP_CS1A_SIZE)
#define OMAP_CS1B_SIZE SZ_32M
#define OMAP_CS2_PHYS 0x08000000
#define OMAP_CS2_SIZE SZ_64M
#define OMAP_CS2A_PHYS OMAP_CS2_PHYS
#define OMAP_CS2A_SIZE SZ_32M
#define OMAP_CS2B_PHYS (OMAP_CS2A_PHYS + OMAP_CS2A_SIZE)
#define OMAP_CS2B_SIZE SZ_32M
#define OMAP_CS3_PHYS 0x0c000000
#define OMAP_CS3_SIZE SZ_64M
#endif /* __ASM_ARCH_TC_H */
......@@ -28,8 +28,6 @@
#if !defined(__ASM_ARCH_OMAP_TIMEX_H)
#define __ASM_ARCH_OMAP_TIMEX_H
#include <asm/arch/clocks.h>
/* TC clock */
#define CLOCK_TICK_RATE ((OMAP_CK_MAX_RATE*1000000)/2)
#define CLOCK_TICK_RATE (HZ * 100000UL)
#endif /* __ASM_ARCH_OMAP_TIMEX_H */
......@@ -20,10 +20,13 @@
#include <linux/config.h>
#include <linux/types.h>
#include <linux/serial_reg.h>
#include <asm/hardware.h>
#include <asm/arch/serial.h>
unsigned int system_rev;
#define UART_OMAP_MDR1 0x08 /* mode definition register */
#define OMAP_ID_730 0x355F
#define ID_MASK 0x7fff
#define check_port(base, shift) ((base[UART_OMAP_MDR1 << shift] & 7) == 0)
#define omap_get_id() ((*(volatile unsigned int *)(0xfffed404)) >> 12) & ID_MASK
......@@ -31,7 +34,7 @@ static void
putstr(const char *s)
{
volatile u8 * uart = 0;
int shift = 0;
int shift;
#ifdef CONFIG_OMAP_LL_DEBUG_UART3
uart = (volatile u8 *)(OMAP_UART3_BASE);
......@@ -46,21 +49,11 @@ putstr(const char *s)
/* MMU is not on, so cpu_is_omapXXXX() won't work here */
unsigned int omap_id = omap_get_id();
if (omap_id == OMAP_ID_1510 || omap_id == OMAP_ID_1610 ||
omap_id == OMAP_ID_1710 || omap_id == OMAP_ID_5912) {
shift = 2;
} else if (omap_id == OMAP_ID_730) {
if (omap_id == OMAP_ID_730)
shift = 0;
} else {
/* Assume nothing for unknown OMAP processors.
* Add an entry for your OMAP type to select
* the default serial console here. If the
* serial port is enabled, we'll use it to
* display status messages. Else we'll be
* quiet.
*/
return;
}
else
shift = 2;
if (check_port(uart, shift))
break;
/* Silent boot if no serial ports are enabled. */
......
/* linux/include/asm-arm/arch-s3c2410/bast-pmu.h
*
* (c) 2003,2004 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
* Vincent Sanders <vince@simtec.co.uk>
*
* Machine BAST - Power Management chip
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Changelog:
* 08-Oct-2003 BJD Initial creation
*/
#ifndef __ASM_ARCH_BASTPMU_H
#define __ASM_ARCH_BASTPMU_H "08_OCT_2004"
#define BASTPMU_REG_IDENT (0x00)
#define BASTPMU_REG_VERSION (0x01)
#define BASTPMU_REG_DDCCTRL (0x02)
#define BASTPMU_REG_POWER (0x03)
#define BASTPMU_REG_RESET (0x04)
#define BASTPMU_REG_GWO (0x05)
#define BASTPMU_REG_WOL (0x06)
#define BASTPMU_REG_WOR (0x07)
#define BASTPMU_REG_UID (0x09)
#define BASTPMU_EEPROM (0xC0)
#define BASTPMU_EEP_UID (BASTPMU_EEPROM + 0)
#define BASTPMU_EEP_WOL (BASTPMU_EEPROM + 8)
#define BASTPMU_EEP_WOR (BASTPMU_EEPROM + 9)
#define BASTPMU_IDENT_0 0x53
#define BASTPMU_IDENT_1 0x42
#define BASTPMU_IDENT_2 0x50
#define BASTPMU_IDENT_3 0x4d
#define BASTPMU_RESET_GUARD (0x55)
#endif /* __ASM_ARCH_BASTPMU_H */
/* linux/include/asm-arm/arch-s3c2410/iic.h
*
* (c) 2004 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
*
* S3C2410 - I2C Controller platfrom_device info
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Changelog:
* 05-Oct-2004 BJD Created file
* 19-Oct-2004 BJD Updated for s3c2440
*/
#ifndef __ASM_ARCH_IIC_H
#define __ASM_ARCH_IIC_H __FILE__
#define S3C_IICFLG_FILTER (1<<0) /* enable s3c2440 filter */
/* Notes:
* 1) All frequencies are expressed in Hz
* 2) A value of zero is `do not care`
*/
struct s3c2410_platform_i2c {
unsigned int flags;
unsigned int slave_addr; /* slave address for controller */
unsigned long bus_freq; /* standard bus frequency */
unsigned long max_freq; /* max frequency for the bus */
unsigned long min_freq; /* min frequency for the bus */
unsigned int sda_delay; /* pclks (s3c2440 only) */
};
#endif /* __ASM_ARCH_IIC_H */
......@@ -13,8 +13,8 @@
* 03-Oct-2004 BJD Initial include for Linux
*/
#ifndef __ASM_ARCH_IIC_H
#define __ASM_ARCH_IIC_H __FILE__
#ifndef __ASM_ARCH_REGS_IIC_H
#define __ASM_ARCH_REGS_IIC_H __FILE__
/* see s3c2410x user guide, v1.1, section 9 (p447) for more info */
......@@ -47,4 +47,4 @@
#define S3C2410_IICSTAT_ADDR0 (1<<1)
#define S3C2410_IICSTAT_LASTBIT (1<<0)
#endif /* __ASM_ARCH_IIC_H */
#endif /* __ASM_ARCH_REGS_IIC_H */
......@@ -29,7 +29,7 @@
#define S3C2410_LCDCON5 S3C2410_LCDREG(0x10)
#define S3C2410_LCDCON1_CLKVAL(x) ((x) << 8)
#define S3C2410_LCDCON1_MMODE (1<<6)
#define S3C2410_LCDCON1_MMODE (1<<7)
#define S3C2410_LCDCON1_DSCAN4 (0<<5)
#define S3C2410_LCDCON1_STN4 (1<<5)
#define S3C2410_LCDCON1_STN8 (2<<5)
......@@ -48,15 +48,15 @@
#define S3C2410_LCDCON1_TFT16BPP (12<<1)
#define S3C2410_LCDCON1_TFT24BPP (13<<1)
#define S3C2410_LCDCON1_ENVDI (1)
#define S3C2410_LCDCON1_ENVID (1)
#define S3C2410_LCDCON2_VBPD(x) ((x) << 24)
#define S3C2410_LCDCON2_LINEVAL(x) ((x) << 14)
#define S3C2410_LCDCON2_VFPD(x) ((x) << 6)
#define S3C2410_LCDCON2_VSPW(x) ((x) << 0)
#define S3C2410_LCDCON3_HBPD(x) ((x) << 25)
#define S3C2410_LCDCON3_WDLY(x) ((x) << 25)
#define S3C2410_LCDCON3_HBPD(x) ((x) << 19)
#define S3C2410_LCDCON3_WDLY(x) ((x) << 19)
#define S3C2410_LCDCON3_HOZVAL(x) ((x) << 8)
#define S3C2410_LCDCON3_HFPD(x) ((x) << 0)
#define S3C2410_LCDCON3_LINEBLANK(x)((x) << 0)
......@@ -84,6 +84,12 @@
#define S3C2410_LCDSADDR2 S3C2410_LCDREG(0x18)
#define S3C2410_LCDSADDR3 S3C2410_LCDREG(0x1C)
#define S3C2410_LCDBANK(x) ((x) << 21)
#define S3C2410_LCDBASEU(x) (x)
#define S3C2410_OFFSIZE(x) ((x) << 11)
#define S3C2410_PAGEWIDTH(x) (x)
/* colour lookup and miscellaneous controls */
#define S3C2410_REDLUT S3C2410_LCDREG(0x20)
......
......@@ -66,6 +66,7 @@
#define S3C2410_LCON_PMASK (0x7 << 3)
#define S3C2410_LCON_STOPB (1<<2)
#define S3C2410_LCON_IRM (1<<6)
#define S3C2410_UCON_UCLK (1<<10)
#define S3C2410_UCON_SBREAK (1<<4)
......@@ -97,6 +98,14 @@
#define S3C2410_UFSTAT_RXMASK (15<<0)
#define S3C2410_UFSTAT_RXSHIFT (0)
#define S3C2440_UFSTAT_TXFULL (1<<14)
#define S3C2440_UFSTAT_RXFULL (1<<6)
#define S3C2440_UFSTAT_TXSHIFT (8)
#define S3C2440_UFSTAT_RXSHIFT (0)
#define S3C2440_UFSTAT_TXMASK (63<<8)
#define S3C2440_UFSTAT_RXMASK (63)
#define S3C2410_UTRSTAT_TXE (1<<2)
#define S3C2410_UTRSTAT_TXFE (1<<1)
#define S3C2410_UTRSTAT_RXDR (1<<0)
......
......@@ -8,8 +8,9 @@
* the License, or (at your option) any later version.
*
* Changelog:
* 01-08-2004 initial creation
* 12-09-2004 cleanup for submission
* 01-08-2004 Initial creation
* 12-09-2004 Cleanup for submission
* 24-10-2004 Fixed S3C2410_UDC_MAXP_REG definition
*/
#ifndef __ASM_ARCH_REGS_UDC_H
......@@ -68,7 +69,7 @@
/* indexed registers */
#define S3C2410_UDC_MAXP_REG S3C2410_USBDREG(0x018c)
#define S3C2410_UDC_MAXP_REG S3C2410_USBDREG(0x0180)
#define S3C2410_UDC_EP0_CSR_REG S3C2410_USBDREG(0x0184)
......
......@@ -13,21 +13,29 @@
* 22-May-2003 BJD Created
* 08-Sep-2003 BJD Moved to linux v2.6
* 12-Mar-2004 BJD Updated header protection
* 12-Oct-2004 BJD Take account of debug uart configuration
*/
#ifndef __ASM_ARCH_UNCOMPRESS_H
#define __ASM_ARCH_UNCOMPRESS_H
#include <config/debug/s3c2410/port.h>
/* defines for UART registers */
#include "asm/arch/regs-serial.h"
#include "asm/arch/regs-gpio.h"
#include <asm/arch/map.h>
/* working in physical space... */
#undef S3C2410_GPIOREG
#define S3C2410_GPIOREG(x) ((S3C2410_PA_GPIO + (x)))
/* how many bytes we allow into the FIFO at a time in FIFO mode */
#define FIFO_MAX (14)
#if 1
#define uart_base S3C2410_PA_UART
#define uart_base S3C2410_PA_UART + (0x4000 * CONFIG_DEBUG_S3C2410_UART)
#else
static unsigned int uart_base = S3C2410_PA_UART;
#endif
......@@ -74,6 +82,10 @@ arch_decomp_setup(void)
static void
putc(char ch)
{
int cpuid = *((volatile unsigned int *)S3C2410_GSTATUS1);
cpuid &= S3C2410_GSTATUS1_IDMASK;
if (ch == '\n')
putc('\r'); /* expand newline to \r\n */
......@@ -82,8 +94,14 @@ putc(char ch)
while (1) {
level = uart_rd(S3C2410_UFSTAT);
level &= S3C2410_UFSTAT_TXMASK;
level >>= S3C2410_UFSTAT_TXSHIFT;
if (cpuid == S3C2410_GSTATUS1_2440) {
level &= S3C2440_UFSTAT_TXMASK;
level >>= S3C2440_UFSTAT_TXSHIFT;
} else {
level &= S3C2410_UFSTAT_TXMASK;
level >>= S3C2410_UFSTAT_TXSHIFT;
}
if (level < FIFO_MAX)
break;
......@@ -92,7 +110,7 @@ putc(char ch)
} else {
/* not using fifos */
while ((uart_rd(S3C2410_UTRSTAT) & S3C2410_UTRSTAT_TXFE) != S3C2410_UTRSTAT_TXFE);
while ((uart_rd(S3C2410_UTRSTAT) & S3C2410_UTRSTAT_TXE) != S3C2410_UTRSTAT_TXE);
}
/* write byte to transmission register */
......
......@@ -62,19 +62,19 @@ typedef struct {
#undef __FD_SET
#define __FD_SET(fd, fdsetp) \
(((fd_set *)fdsetp)->fds_bits[fd >> 5] |= (1<<(fd & 31)))
(((fd_set *)(fdsetp))->fds_bits[(fd) >> 5] |= (1<<((fd) & 31)))
#undef __FD_CLR
#define __FD_CLR(fd, fdsetp) \
(((fd_set *)fdsetp)->fds_bits[fd >> 5] &= ~(1<<(fd & 31)))
(((fd_set *)(fdsetp))->fds_bits[(fd) >> 5] &= ~(1<<((fd) & 31)))
#undef __FD_ISSET
#define __FD_ISSET(fd, fdsetp) \
((((fd_set *)fdsetp)->fds_bits[fd >> 5] & (1<<(fd & 31))) != 0)
((((fd_set *)(fdsetp))->fds_bits[(fd) >> 5] & (1<<((fd) & 31))) != 0)
#undef __FD_ZERO
#define __FD_ZERO(fdsetp) \
(memset (fdsetp, 0, sizeof (*(fd_set *)fdsetp)))
(memset (fdsetp, 0, sizeof (*(fd_set *)(fdsetp))))
#endif
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment