Merge master.kernel.org:/home/rmk/linux-2.6-arm

This commit is contained in:
Linus Torvalds
2005-09-07 17:00:53 -07:00
58 changed files with 2507 additions and 833 deletions

View File

@@ -7,7 +7,8 @@
* so we have to figure out the machine for ourselves...
*
* Support for Poodle, Corgi (SL-C700), Shepherd (SL-C750)
* and Husky (SL-C760).
* Husky (SL-C760), Tosa (SL-C6000), Spitz (SL-C3000),
* Akita (SL-C1000) and Borzoi (SL-C3100).
*
*/
@@ -23,6 +24,22 @@
__SharpSL_start:
/* Check for TC6393 - if found we have a Tosa */
ldr r7, .TOSAID
mov r1, #0x10000000 @ Base address of TC6393 chip
mov r6, #0x03
ldrh r3, [r1, #8] @ Load TC6393XB Revison: This is 0x0003
cmp r6, r3
beq .SHARPEND @ Success -> tosa
/* Check for pxa270 - if found, branch */
mrc p15, 0, r4, c0, c0 @ Get Processor ID
and r4, r4, #0xffffff00
ldr r3, .PXA270ID
cmp r4, r3
beq .PXA270
/* Check for w100 - if not found we have a Poodle */
ldr r1, .W100ADDR @ Base address of w100 chip + regs offset
mov r6, #0x31 @ Load Magic Init value
@@ -30,7 +47,7 @@ __SharpSL_start:
mov r5, #0x3000
.W100LOOP:
subs r5, r5, #1
bne .W100LOOP
bne .W100LOOP
mov r6, #0x30 @ Load 2nd Magic Init value
str r6, [r1, #0x280] @ to SCRATCH_UMSK
@@ -40,45 +57,52 @@ __SharpSL_start:
cmp r6, r3
bne .SHARPEND @ We have no w100 - Poodle
mrc p15, 0, r6, c0, c0 @ Get Processor ID
and r6, r6, #0xffffff00
/* Check for pxa250 - if found we have a Corgi */
ldr r7, .CORGIID
ldr r3, .PXA255ID
cmp r6, r3
cmp r4, r3
blo .SHARPEND @ We have a PXA250 - Corgi
mov r1, #0x0c000000 @ Base address of NAND chip
ldrb r3, [r1, #24] @ Load FLASHCTL
bic r3, r3, #0x11 @ SET NCE
orr r3, r3, #0x0a @ SET CLR + FLWP
strb r3, [r1, #24] @ Save to FLASHCTL
mov r2, #0x90 @ Command "readid"
strb r2, [r1, #20] @ Save to FLASHIO
bic r3, r3, #2 @ CLR CLE
orr r3, r3, #4 @ SET ALE
strb r3, [r1, #24] @ Save to FLASHCTL
mov r2, #0 @ Address 0x00
strb r2, [r1, #20] @ Save to FLASHIO
bic r3, r3, #4 @ CLR ALE
strb r3, [r1, #24] @ Save to FLASHCTL
.SHARP1:
ldrb r3, [r1, #24] @ Load FLASHCTL
tst r3, #32 @ Is chip ready?
beq .SHARP1
ldrb r2, [r1, #20] @ NAND Manufacturer ID
ldrb r3, [r1, #20] @ NAND Chip ID
/* Check for 64MiB flash - if found we have a Shepherd */
bl get_flash_ids
ldr r7, .SHEPHERDID
cmp r3, #0x76 @ 64MiB flash
beq .SHARPEND @ We have Shepherd
/* Must be a Husky */
ldr r7, .HUSKYID @ Must be Husky
b .SHARPEND
.PXA270:
/* Check for 16MiB flash - if found we have Spitz */
bl get_flash_ids
ldr r7, .SPITZID
cmp r3, #0x73 @ 16MiB flash
beq .SHARPEND @ We have Spitz
/* Check for a second SCOOP chip - if found we have Borzoi */
ldr r1, .SCOOP2ADDR
ldr r7, .BORZOIID
mov r6, #0x0140
strh r6, [r1]
ldrh r6, [r1]
cmp r6, #0x0140
beq .SHARPEND @ We have Borzoi
/* Must be Akita */
ldr r7, .AKITAID
b .SHARPEND @ We have Borzoi
.PXA255ID:
.word 0x69052d00 @ PXA255 Processor ID
.PXA270ID:
.word 0x69054100 @ PXA270 Processor ID
.W100ID:
.word 0x57411002 @ w100 Chip ID
.W100ADDR:
.word 0x08010000 @ w100 Chip ID Reg Address
.SCOOP2ADDR:
.word 0x08800040
.POODLEID:
.word MACH_TYPE_POODLE
.CORGIID:
@@ -87,6 +111,41 @@ __SharpSL_start:
.word MACH_TYPE_SHEPHERD
.HUSKYID:
.word MACH_TYPE_HUSKY
.TOSAID:
.word MACH_TYPE_TOSA
.SPITZID:
.word MACH_TYPE_SPITZ
.AKITAID:
.word MACH_TYPE_AKITA
.BORZOIID:
.word MACH_TYPE_BORZOI
/*
* Return: r2 - NAND Manufacturer ID
* r3 - NAND Chip ID
* Corrupts: r1
*/
get_flash_ids:
mov r1, #0x0c000000 @ Base address of NAND chip
ldrb r3, [r1, #24] @ Load FLASHCTL
bic r3, r3, #0x11 @ SET NCE
orr r3, r3, #0x0a @ SET CLR + FLWP
strb r3, [r1, #24] @ Save to FLASHCTL
mov r2, #0x90 @ Command "readid"
strb r2, [r1, #20] @ Save to FLASHIO
bic r3, r3, #2 @ CLR CLE
orr r3, r3, #4 @ SET ALE
strb r3, [r1, #24] @ Save to FLASHCTL
mov r2, #0 @ Address 0x00
strb r2, [r1, #20] @ Save to FLASHIO
bic r3, r3, #4 @ CLR ALE
strb r3, [r1, #24] @ Save to FLASHCTL
.fids1:
ldrb r3, [r1, #24] @ Load FLASHCTL
tst r3, #32 @ Is chip ready?
beq .fids1
ldrb r2, [r1, #20] @ NAND Manufacturer ID
ldrb r3, [r1, #20] @ NAND Chip ID
mov pc, lr
.SHARPEND:

View File

@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
# Linux kernel version: 2.6.13-rc2
# Fri Jul 8 04:49:34 2005
# Linux kernel version: 2.6.13
# Mon Sep 5 18:07:12 2005
#
CONFIG_ARM=y
CONFIG_MMU=y
@@ -102,9 +102,11 @@ CONFIG_OMAP_MUX_WARNINGS=y
# CONFIG_OMAP_MPU_TIMER is not set
CONFIG_OMAP_32K_TIMER=y
CONFIG_OMAP_32K_TIMER_HZ=128
# CONFIG_OMAP_DM_TIMER is not set
CONFIG_OMAP_LL_DEBUG_UART1=y
# CONFIG_OMAP_LL_DEBUG_UART2 is not set
# CONFIG_OMAP_LL_DEBUG_UART3 is not set
CONFIG_OMAP_SERIAL_WAKE=y
#
# OMAP Core Type
@@ -166,7 +168,6 @@ CONFIG_ISA_DMA_API=y
#
# Kernel Features
#
# CONFIG_SMP is not set
CONFIG_PREEMPT=y
CONFIG_NO_IDLE_HZ=y
# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
@@ -229,6 +230,68 @@ CONFIG_BINFMT_AOUT=y
CONFIG_PM=y
# CONFIG_APM is not set
#
# Networking
#
CONFIG_NET=y
#
# Networking options
#
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
# CONFIG_NET_KEY is not set
CONFIG_INET=y
# CONFIG_IP_MULTICAST is not set
# CONFIG_IP_ADVANCED_ROUTER is not set
CONFIG_IP_FIB_HASH=y
CONFIG_IP_PNP=y
CONFIG_IP_PNP_DHCP=y
CONFIG_IP_PNP_BOOTP=y
# CONFIG_IP_PNP_RARP is not set
# CONFIG_NET_IPIP is not set
# CONFIG_NET_IPGRE is not set
# CONFIG_ARPD is not set
# CONFIG_SYN_COOKIES is not set
# 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_IP_TCPDIAG=y
# CONFIG_IP_TCPDIAG_IPV6 is not set
# CONFIG_TCP_CONG_ADVANCED is not set
CONFIG_TCP_CONG_BIC=y
# CONFIG_IPV6 is not set
# CONFIG_NETFILTER is not set
#
# SCTP Configuration (EXPERIMENTAL)
#
# CONFIG_IP_SCTP is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
# CONFIG_VLAN_8021Q is not set
# CONFIG_DECNET is not set
# CONFIG_LLC2 is not set
# CONFIG_IPX is not set
# CONFIG_ATALK is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_NET_SCHED is not set
# CONFIG_NET_CLS_ROUTE is not set
#
# Network testing
#
# CONFIG_NET_PKTGEN is not set
# CONFIG_HAMRADIO is not set
# CONFIG_IRDA is not set
# CONFIG_BT is not set
#
# Device Drivers
#
@@ -243,78 +306,7 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
#
# Memory Technology Devices (MTD)
#
CONFIG_MTD=y
CONFIG_MTD_DEBUG=y
CONFIG_MTD_DEBUG_VERBOSE=3
# CONFIG_MTD_CONCAT is not set
CONFIG_MTD_PARTITIONS=y
# CONFIG_MTD_REDBOOT_PARTS is not set
CONFIG_MTD_CMDLINE_PARTS=y
# CONFIG_MTD_AFS_PARTS is not set
#
# User Modules And Translation Layers
#
CONFIG_MTD_CHAR=y
CONFIG_MTD_BLOCK=y
# CONFIG_FTL is not set
# CONFIG_NFTL is not set
# CONFIG_INFTL is not set
#
# RAM/ROM/Flash chip drivers
#
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
# CONFIG_MTD_XIP is not set
#
# Mapping drivers for chip access
#
# CONFIG_MTD_COMPLEX_MAPPINGS is not set
# CONFIG_MTD_PHYSMAP is not set
# CONFIG_MTD_ARM_INTEGRATOR is not set
# CONFIG_MTD_EDB7312 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
# CONFIG_MTD_BLOCK2MTD is not set
#
# Disk-On-Chip Device Drivers
#
# CONFIG_MTD_DOC2000 is not set
# CONFIG_MTD_DOC2001 is not set
# CONFIG_MTD_DOC2001PLUS is not set
#
# NAND Flash Device Drivers
#
# CONFIG_MTD_NAND is not set
# CONFIG_MTD is not set
#
# Parallel port support
@@ -403,72 +395,8 @@ CONFIG_SCSI_PROC_FS=y
#
#
# Networking support
# Network device support
#
CONFIG_NET=y
#
# Networking options
#
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
# CONFIG_NET_KEY is not set
CONFIG_INET=y
# CONFIG_IP_MULTICAST is not set
# CONFIG_IP_ADVANCED_ROUTER is not set
CONFIG_IP_FIB_HASH=y
CONFIG_IP_PNP=y
CONFIG_IP_PNP_DHCP=y
CONFIG_IP_PNP_BOOTP=y
# CONFIG_IP_PNP_RARP is not set
# CONFIG_NET_IPIP is not set
# CONFIG_NET_IPGRE is not set
# CONFIG_ARPD is not set
# CONFIG_SYN_COOKIES is not set
# 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_IP_TCPDIAG=y
# CONFIG_IP_TCPDIAG_IPV6 is not set
# CONFIG_TCP_CONG_ADVANCED is not set
CONFIG_TCP_CONG_BIC=y
# CONFIG_IPV6 is not set
# CONFIG_NETFILTER is not set
#
# SCTP Configuration (EXPERIMENTAL)
#
# CONFIG_IP_SCTP is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
# CONFIG_VLAN_8021Q is not set
# CONFIG_DECNET is not set
# CONFIG_LLC2 is not set
# CONFIG_IPX is not set
# CONFIG_ATALK is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
#
# QoS and/or fair queueing
#
# CONFIG_NET_SCHED is not set
# CONFIG_NET_CLS_ROUTE is not set
#
# Network testing
#
# CONFIG_NET_PKTGEN is not set
# CONFIG_NETPOLL is not set
# CONFIG_NET_POLL_CONTROLLER is not set
# CONFIG_HAMRADIO is not set
# CONFIG_IRDA is not set
# CONFIG_BT is not set
CONFIG_NETDEVICES=y
# CONFIG_DUMMY is not set
# CONFIG_BONDING is not set
@@ -518,6 +446,8 @@ CONFIG_SLIP_COMPRESSED=y
# CONFIG_SLIP_MODE_SLIP6 is not set
# CONFIG_SHAPER is not set
# CONFIG_NETCONSOLE is not set
# CONFIG_NETPOLL is not set
# CONFIG_NET_POLL_CONTROLLER is not set
#
# ISDN subsystem
@@ -615,77 +545,15 @@ CONFIG_WATCHDOG_NOWAYOUT=y
#
# I2C support
#
CONFIG_I2C=y
CONFIG_I2C_CHARDEV=y
#
# I2C Algorithms
#
# CONFIG_I2C_ALGOBIT is not set
# CONFIG_I2C_ALGOPCF is not set
# CONFIG_I2C_ALGOPCA is not set
#
# I2C Hardware Bus support
#
# CONFIG_I2C_ISA is not set
# CONFIG_I2C_PARPORT_LIGHT is not set
# CONFIG_I2C_STUB is not set
# CONFIG_I2C_PCA_ISA is not set
#
# Hardware Sensors Chip support
#
# CONFIG_I2C is not set
# CONFIG_I2C_SENSOR is not set
# CONFIG_SENSORS_ADM1021 is not set
# CONFIG_SENSORS_ADM1025 is not set
# CONFIG_SENSORS_ADM1026 is not set
# CONFIG_SENSORS_ADM1031 is not set
# CONFIG_SENSORS_ADM9240 is not set
# CONFIG_SENSORS_ASB100 is not set
# CONFIG_SENSORS_ATXP1 is not set
# CONFIG_SENSORS_DS1621 is not set
# CONFIG_SENSORS_FSCHER is not set
# CONFIG_SENSORS_FSCPOS is not set
# CONFIG_SENSORS_GL518SM is not set
# CONFIG_SENSORS_GL520SM is not set
# CONFIG_SENSORS_IT87 is not set
# CONFIG_SENSORS_LM63 is not set
# CONFIG_SENSORS_LM75 is not set
# CONFIG_SENSORS_LM77 is not set
# CONFIG_SENSORS_LM78 is not set
# CONFIG_SENSORS_LM80 is not set
# CONFIG_SENSORS_LM83 is not set
# CONFIG_SENSORS_LM85 is not set
# CONFIG_SENSORS_LM87 is not set
# CONFIG_SENSORS_LM90 is not set
# CONFIG_SENSORS_LM92 is not set
# CONFIG_SENSORS_MAX1619 is not set
# CONFIG_SENSORS_PC87360 is not set
# CONFIG_SENSORS_SMSC47B397 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
# CONFIG_SENSORS_W83627EHF is not set
CONFIG_ISP1301_OMAP=y
#
# Other I2C Chip support
# Hardware Monitoring support
#
# CONFIG_SENSORS_DS1337 is not set
# CONFIG_SENSORS_DS1374 is not set
# CONFIG_SENSORS_EEPROM is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_PCF8591 is not set
# CONFIG_SENSORS_RTC8564 is not set
CONFIG_ISP1301_OMAP=y
CONFIG_TPS65010=y
# CONFIG_SENSORS_MAX6875 is not set
# CONFIG_I2C_DEBUG_CORE is not set
# CONFIG_I2C_DEBUG_ALGO is not set
# CONFIG_I2C_DEBUG_BUS is not set
# CONFIG_I2C_DEBUG_CHIP is not set
CONFIG_HWMON=y
# CONFIG_HWMON_DEBUG_CHIP is not set
#
# Misc devices
@@ -756,15 +624,9 @@ CONFIG_SOUND=y
# Open Sound System
#
CONFIG_SOUND_PRIME=y
# CONFIG_SOUND_BT878 is not set
# CONFIG_SOUND_FUSION is not set
# CONFIG_SOUND_CS4281 is not set
# CONFIG_SOUND_SONICVIBES is not set
# CONFIG_SOUND_TRIDENT is not set
# CONFIG_SOUND_MSNDCLAS is not set
# CONFIG_SOUND_MSNDPIN is not set
# CONFIG_SOUND_OSS is not set
# CONFIG_SOUND_TVMIXER is not set
# CONFIG_SOUND_AD1980 is not set
#
@@ -810,6 +672,7 @@ CONFIG_EXT2_FS=y
# CONFIG_JBD is not set
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
# CONFIG_FS_POSIX_ACL is not set
#
# XFS support
@@ -817,6 +680,7 @@ CONFIG_EXT2_FS=y
# CONFIG_XFS_FS is not set
# CONFIG_MINIX_FS is not set
CONFIG_ROMFS_FS=y
CONFIG_INOTIFY=y
# CONFIG_QUOTA is not set
CONFIG_DNOTIFY=y
# CONFIG_AUTOFS_FS is not set
@@ -857,15 +721,6 @@ CONFIG_RAMFS=y
# CONFIG_BEFS_FS is not set
# CONFIG_BFS_FS is not set
# CONFIG_EFS_FS is not set
# CONFIG_JFFS_FS is not set
CONFIG_JFFS2_FS=y
CONFIG_JFFS2_FS_DEBUG=2
# CONFIG_JFFS2_FS_NAND is not set
# CONFIG_JFFS2_FS_NOR_ECC 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=y
# CONFIG_VXFS_FS is not set
# CONFIG_HPFS_FS is not set
@@ -1007,4 +862,3 @@ CONFIG_CRYPTO_DES=y
CONFIG_CRC32=y
# CONFIG_LIBCRC32C is not set
CONFIG_ZLIB_INFLATE=y
CONFIG_ZLIB_DEFLATE=y

View File

@@ -60,7 +60,7 @@ static unsigned long iop321_gettimeoffset(void)
/*
* Now convert them to usec.
*/
usec = (unsigned long)(elapsed * (tick_nsec / 1000)) / LATCH;
usec = (unsigned long)(elapsed / (CLOCK_TICK_RATE/1000000));
return usec;
}

View File

@@ -58,7 +58,7 @@ static unsigned long iop331_gettimeoffset(void)
/*
* Now convert them to usec.
*/
usec = (unsigned long)(elapsed * (tick_nsec / 1000)) / LATCH;
usec = (unsigned long)(elapsed / (CLOCK_TICK_RATE/1000000));
return usec;
}

View File

@@ -382,7 +382,7 @@ static void ixp2000_GPIO_irq_unmask(unsigned int irq)
static struct irqchip ixp2000_GPIO_irq_chip = {
.ack = ixp2000_GPIO_irq_mask_ack,
.mask = ixp2000_GPIO_irq_mask,
.unmask = ixp2000_GPIO_irq_unmask
.unmask = ixp2000_GPIO_irq_unmask,
.set_type = ixp2000_GPIO_irq_type,
};

View File

@@ -179,17 +179,17 @@ static void ixp4xx_irq_level_unmask(unsigned int irq)
}
static struct irqchip ixp4xx_irq_level_chip = {
.ack = ixp4xx_irq_mask,
.mask = ixp4xx_irq_mask,
.unmask = ixp4xx_irq_level_unmask,
.type = ixp4xx_set_irq_type
.ack = ixp4xx_irq_mask,
.mask = ixp4xx_irq_mask,
.unmask = ixp4xx_irq_level_unmask,
.set_type = ixp4xx_set_irq_type,
};
static struct irqchip ixp4xx_irq_edge_chip = {
.ack = ixp4xx_irq_ack,
.mask = ixp4xx_irq_mask,
.unmask = ixp4xx_irq_unmask,
.type = ixp4xx_set_irq_type
.ack = ixp4xx_irq_ack,
.mask = ixp4xx_irq_mask,
.unmask = ixp4xx_irq_unmask,
.set_type = ixp4xx_set_irq_type,
};
static void ixp4xx_config_irq(unsigned irq, enum ixp4xx_irq_type type)

View File

@@ -165,10 +165,10 @@ static struct omap_irq_bank omap1610_irq_banks[] = {
#endif
static struct irqchip omap_irq_chip = {
.ack = omap_mask_ack_irq,
.mask = omap_mask_irq,
.unmask = omap_unmask_irq,
.wake = omap_wake_irq,
.ack = omap_mask_ack_irq,
.mask = omap_mask_irq,
.unmask = omap_unmask_irq,
.set_wake = omap_wake_irq,
};
void __init omap_init_irq(void)

View File

@@ -2,6 +2,13 @@ if ARCH_S3C2410
menu "S3C24XX Implementations"
config MACH_ANUBIS
bool "Simtec Electronics ANUBIS"
select CPU_S3C2440
help
Say Y gere if you are using the Simtec Electronics ANUBIS
development system
config ARCH_BAST
bool "Simtec Electronics BAST (EB2410ITX)"
select CPU_S3C2410
@@ -11,6 +18,14 @@ config ARCH_BAST
Product page: <http://www.simtec.co.uk/products/EB2410ITX/>.
config BAST_PC104_IRQ
bool "BAST PC104 IRQ support"
depends on ARCH_BAST
default y
help
Say Y here to enable the PC104 IRQ routing on the
Simtec BAST (EB2410ITX)
config ARCH_H1940
bool "IPAQ H1940"
select CPU_S3C2410

View File

@@ -26,8 +26,13 @@ obj-$(CONFIG_CPU_S3C2440) += s3c2440.o s3c2440-dsc.o
obj-$(CONFIG_CPU_S3C2440) += s3c2440-irq.o
obj-$(CONFIG_CPU_S3C2440) += s3c2440-clock.o
# bast extras
obj-$(CONFIG_BAST_PC104_IRQ) += bast-irq.o
# machine specific support
obj-$(CONFIG_MACH_ANUBIS) += mach-anubis.o
obj-$(CONFIG_ARCH_BAST) += mach-bast.o usb-simtec.o
obj-$(CONFIG_ARCH_H1940) += mach-h1940.o
obj-$(CONFIG_MACH_N30) += mach-n30.o

View File

@@ -1,6 +1,6 @@
/* linux/arch/arm/mach-s3c2410/bast-irq.c
*
* Copyright (c) 2004 Simtec Electronics
* Copyright (c) 2003,2005 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
*
* http://www.simtec.co.uk/products/EB2410ITX/
@@ -21,7 +21,8 @@
*
* Modifications:
* 08-Jan-2003 BJD Moved from central IRQ code
*/
* 21-Aug-2005 BJD Fixed missing code and compile errors
*/
#include <linux/init.h>
@@ -30,12 +31,19 @@
#include <linux/ptrace.h>
#include <linux/sysdev.h>
#include <asm/mach-types.h>
#include <asm/hardware.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <asm/mach/irq.h>
#include <asm/hardware/s3c2410/irq.h>
#include <asm/arch/regs-irq.h>
#include <asm/arch/bast-map.h>
#include <asm/arch/bast-irq.h>
#include "irq.h"
#if 0
#include <asm/debug-ll.h>
@@ -79,15 +87,15 @@ bast_pc104_mask(unsigned int irqno)
temp = __raw_readb(BAST_VA_PC104_IRQMASK);
temp &= ~bast_pc104_irqmasks[irqno];
__raw_writeb(temp, BAST_VA_PC104_IRQMASK);
if (temp == 0)
bast_extint_mask(IRQ_ISA);
}
static void
bast_pc104_ack(unsigned int irqno)
bast_pc104_maskack(unsigned int irqno)
{
bast_extint_ack(IRQ_ISA);
struct irqdesc *desc = irq_desc + IRQ_ISA;
bast_pc104_mask(irqno);
desc->chip->ack(IRQ_ISA);
}
static void
@@ -98,14 +106,12 @@ bast_pc104_unmask(unsigned int irqno)
temp = __raw_readb(BAST_VA_PC104_IRQMASK);
temp |= bast_pc104_irqmasks[irqno];
__raw_writeb(temp, BAST_VA_PC104_IRQMASK);
bast_extint_unmask(IRQ_ISA);
}
static struct bast_pc104_chip = {
static struct irqchip bast_pc104_chip = {
.mask = bast_pc104_mask,
.unmask = bast_pc104_unmask,
.ack = bast_pc104_ack
.ack = bast_pc104_maskack
};
static void
@@ -119,14 +125,49 @@ bast_irq_pc104_demux(unsigned int irq,
stat = __raw_readb(BAST_VA_PC104_IRQREQ) & 0xf;
for (i = 0; i < 4 && stat != 0; i++) {
if (stat & 1) {
irqno = bast_pc104_irqs[i];
desc = irq_desc + irqno;
if (unlikely(stat == 0)) {
/* ack if we get an irq with nothing (ie, startup) */
desc_handle_irq(irqno, desc, regs);
desc = irq_desc + IRQ_ISA;
desc->chip->ack(IRQ_ISA);
} else {
/* handle the IRQ */
for (i = 0; stat != 0; i++, stat >>= 1) {
if (stat & 1) {
irqno = bast_pc104_irqs[i];
desc_handle_irq(irqno, irq_desc + irqno, regs);
}
}
stat >>= 1;
}
}
static __init int bast_irq_init(void)
{
unsigned int i;
if (machine_is_bast()) {
printk(KERN_INFO "BAST PC104 IRQ routing, (c) 2005 Simtec Electronics\n");
/* zap all the IRQs */
__raw_writeb(0x0, BAST_VA_PC104_IRQMASK);
set_irq_chained_handler(IRQ_ISA, bast_irq_pc104_demux);
/* reigster our IRQs */
for (i = 0; i < 4; i++) {
unsigned int irqno = bast_pc104_irqs[i];
set_irq_chip(irqno, &bast_pc104_chip);
set_irq_handler(irqno, do_level_IRQ);
set_irq_flags(irqno, IRQF_VALID);
}
}
return 0;
}
arch_initcall(bast_irq_init);

View File

@@ -0,0 +1,270 @@
/* linux/arch/arm/mach-s3c2410/mach-anubis.c
*
* Copyright (c) 2003-2005 Simtec Electronics
* http://armlinux.simtec.co.uk/
* Ben Dooks <ben@simtec.co.uk>
*
*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Modifications:
* 02-May-2005 BJD Copied from mach-bast.c
*/
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/interrupt.h>
#include <linux/list.h>
#include <linux/timer.h>
#include <linux/init.h>
#include <linux/device.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
#include <asm/mach/irq.h>
#include <asm/arch/anubis-map.h>
#include <asm/arch/anubis-irq.h>
#include <asm/arch/anubis-cpld.h>
#include <asm/hardware.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/mach-types.h>
#include <asm/arch/regs-serial.h>
#include <asm/arch/regs-gpio.h>
#include <asm/arch/regs-mem.h>
#include <asm/arch/regs-lcd.h>
#include <asm/arch/nand.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/nand_ecc.h>
#include <linux/mtd/partitions.h>
#include "clock.h"
#include "devs.h"
#include "cpu.h"
#define COPYRIGHT ", (c) 2005 Simtec Electronics"
static struct map_desc anubis_iodesc[] __initdata = {
/* ISA IO areas */
{ (u32)S3C24XX_VA_ISA_BYTE, 0x0, SZ_16M, MT_DEVICE },
{ (u32)S3C24XX_VA_ISA_WORD, 0x0, SZ_16M, MT_DEVICE },
/* we could possibly compress the next set down into a set of smaller tables
* pagetables, but that would mean using an L2 section, and it still means
* we cannot actually feed the same register to an LDR due to 16K spacing
*/
/* CPLD control registers */
{ (u32)ANUBIS_VA_CTRL1, ANUBIS_PA_CTRL1, SZ_4K, MT_DEVICE },
{ (u32)ANUBIS_VA_CTRL2, ANUBIS_PA_CTRL2, SZ_4K, MT_DEVICE },
/* IDE drives */
{ (u32)ANUBIS_IDEPRI, S3C2410_CS3, SZ_1M, MT_DEVICE },
{ (u32)ANUBIS_IDEPRIAUX, S3C2410_CS3+(1<<26), SZ_1M, MT_DEVICE },
{ (u32)ANUBIS_IDESEC, S3C2410_CS4, SZ_1M, MT_DEVICE },
{ (u32)ANUBIS_IDESECAUX, S3C2410_CS4+(1<<26), SZ_1M, MT_DEVICE },
};
#define UCON S3C2410_UCON_DEFAULT | S3C2410_UCON_UCLK
#define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB
#define UFCON S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE
static struct s3c24xx_uart_clksrc anubis_serial_clocks[] = {
[0] = {
.name = "uclk",
.divisor = 1,
.min_baud = 0,
.max_baud = 0,
},
[1] = {
.name = "pclk",
.divisor = 1,
.min_baud = 0,
.max_baud = 0.
}
};
static struct s3c2410_uartcfg anubis_uartcfgs[] = {
[0] = {
.hwport = 0,
.flags = 0,
.ucon = UCON,
.ulcon = ULCON,
.ufcon = UFCON,
.clocks = anubis_serial_clocks,
.clocks_size = ARRAY_SIZE(anubis_serial_clocks)
},
[1] = {
.hwport = 2,
.flags = 0,
.ucon = UCON,
.ulcon = ULCON,
.ufcon = UFCON,
.clocks = anubis_serial_clocks,
.clocks_size = ARRAY_SIZE(anubis_serial_clocks)
},
};
/* NAND Flash on Anubis board */
static int external_map[] = { 2 };
static int chip0_map[] = { 0 };
static int chip1_map[] = { 1 };
struct mtd_partition anubis_default_nand_part[] = {
[0] = {
.name = "Boot Agent",
.size = SZ_16K,
.offset = 0
},
[1] = {
.name = "/boot",
.size = SZ_4M - SZ_16K,
.offset = SZ_16K,
},
[2] = {
.name = "user1",
.offset = SZ_4M,
.size = SZ_32M - SZ_4M,
},
[3] = {
.name = "user2",
.offset = SZ_32M,
.size = MTDPART_SIZ_FULL,
}
};
/* the Anubis has 3 selectable slots for nand-flash, the two
* on-board chip areas, as well as the external slot.
*
* Note, there is no current hot-plug support for the External
* socket.
*/
static struct s3c2410_nand_set anubis_nand_sets[] = {
[1] = {
.name = "External",
.nr_chips = 1,
.nr_map = external_map,
.nr_partitions = ARRAY_SIZE(anubis_default_nand_part),
.partitions = anubis_default_nand_part
},
[0] = {
.name = "chip0",
.nr_chips = 1,
.nr_map = chip0_map,
.nr_partitions = ARRAY_SIZE(anubis_default_nand_part),
.partitions = anubis_default_nand_part
},
[2] = {
.name = "chip1",
.nr_chips = 1,
.nr_map = chip1_map,
.nr_partitions = ARRAY_SIZE(anubis_default_nand_part),
.partitions = anubis_default_nand_part
},
};
static void anubis_nand_select(struct s3c2410_nand_set *set, int slot)
{
unsigned int tmp;
slot = set->nr_map[slot] & 3;
pr_debug("anubis_nand: selecting slot %d (set %p,%p)\n",
slot, set, set->nr_map);
tmp = __raw_readb(ANUBIS_VA_CTRL1);
tmp &= ~ANUBIS_CTRL1_NANDSEL;
tmp |= slot;
pr_debug("anubis_nand: ctrl1 now %02x\n", tmp);
__raw_writeb(tmp, ANUBIS_VA_CTRL1);
}
static struct s3c2410_platform_nand anubis_nand_info = {
.tacls = 25,
.twrph0 = 80,
.twrph1 = 80,
.nr_sets = ARRAY_SIZE(anubis_nand_sets),
.sets = anubis_nand_sets,
.select_chip = anubis_nand_select,
};
/* Standard Anubis devices */
static struct platform_device *anubis_devices[] __initdata = {
&s3c_device_usb,
&s3c_device_wdt,
&s3c_device_adc,
&s3c_device_i2c,
&s3c_device_rtc,
&s3c_device_nand,
};
static struct clk *anubis_clocks[] = {
&s3c24xx_dclk0,
&s3c24xx_dclk1,
&s3c24xx_clkout0,
&s3c24xx_clkout1,
&s3c24xx_uclk,
};
static struct s3c24xx_board anubis_board __initdata = {
.devices = anubis_devices,
.devices_count = ARRAY_SIZE(anubis_devices),
.clocks = anubis_clocks,
.clocks_count = ARRAY_SIZE(anubis_clocks)
};
void __init anubis_map_io(void)
{
/* initialise the clocks */
s3c24xx_dclk0.parent = NULL;
s3c24xx_dclk0.rate = 12*1000*1000;
s3c24xx_dclk1.parent = NULL;
s3c24xx_dclk1.rate = 24*1000*1000;
s3c24xx_clkout0.parent = &s3c24xx_dclk0;
s3c24xx_clkout1.parent = &s3c24xx_dclk1;
s3c24xx_uclk.parent = &s3c24xx_clkout1;
s3c_device_nand.dev.platform_data = &anubis_nand_info;
s3c24xx_init_io(anubis_iodesc, ARRAY_SIZE(anubis_iodesc));
s3c24xx_init_clocks(0);
s3c24xx_init_uarts(anubis_uartcfgs, ARRAY_SIZE(anubis_uartcfgs));
s3c24xx_set_board(&anubis_board);
/* ensure that the GPIO is setup */
s3c2410_gpio_setpin(S3C2410_GPA0, 1);
}
MACHINE_START(ANUBIS, "Simtec-Anubis")
/* Maintainer: Ben Dooks <ben@simtec.co.uk> */
.phys_ram = S3C2410_SDRAM_PA,
.phys_io = S3C2410_PA_UART,
.io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
.boot_params = S3C2410_SDRAM_PA + 0x100,
.map_io = anubis_map_io,
.init_irq = s3c24xx_init_irq,
.timer = &s3c24xx_timer,
MACHINE_END

View File

@@ -48,7 +48,7 @@ static __init int pm_simtec_init(void)
/* check which machine we are running on */
if (!machine_is_bast() && !machine_is_vr1000())
if (!machine_is_bast() && !machine_is_vr1000() && !machine_is_anubis())
return 0;
printk(KERN_INFO "Simtec Board Power Manangement" COPYRIGHT "\n");

View File

@@ -164,7 +164,7 @@ static void s3c2410_timer_setup (void)
/* configure the system for whichever machine is in use */
if (machine_is_bast() || machine_is_vr1000()) {
if (machine_is_bast() || machine_is_vr1000() || machine_is_anubis()) {
/* timer is at 12MHz, scaler is 1 */
timer_usec_ticks = timer_mask_usec_ticks(1, 12000000);
tcnt = 12000000 / HZ;

View File

@@ -91,6 +91,13 @@ config OMAP_32K_TIMER_HZ
Kernel internal timer frequency should be a divisor of 32768,
such as 64 or 128.
config OMAP_DM_TIMER
bool "Use dual-mode timer"
default n
depends on ARCH_OMAP16XX
help
Select this option if you want to use OMAP Dual-Mode timers.
choice
prompt "Low-level debug console UART"
depends on ARCH_OMAP
@@ -107,6 +114,15 @@ config OMAP_LL_DEBUG_UART3
endchoice
config OMAP_SERIAL_WAKE
bool "Enable wake-up events for serial ports"
depends OMAP_MUX
default y
help
Select this option if you want to have your system wake up
to data on the serial RX line. This allows you to wake the
system from serial console.
endmenu
endif

View File

@@ -3,7 +3,7 @@
#
# Common support
obj-y := common.o dma.o clock.o mux.o gpio.o mcbsp.o usb.o
obj-y := common.o sram.o sram-fn.o clock.o dma.o mux.o gpio.o mcbsp.o usb.o
obj-m :=
obj-n :=
obj- :=
@@ -15,3 +15,5 @@ obj-$(CONFIG_ARCH_OMAP16XX) += ocpi.o
obj-$(CONFIG_PM) += pm.o sleep.o
obj-$(CONFIG_CPU_FREQ) += cpu-omap.o
obj-$(CONFIG_OMAP_DM_TIMER) += dmtimer.o

View File

@@ -21,6 +21,7 @@
#include <asm/arch/usb.h>
#include "clock.h"
#include "sram.h"
static LIST_HEAD(clocks);
static DECLARE_MUTEX(clocks_sem);
@@ -141,7 +142,7 @@ static struct clk arm_ck = {
static struct clk armper_ck = {
.name = "armper_ck",
.parent = &ck_dpll1,
.flags = CLOCK_IN_OMAP730 | CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
.flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
RATE_CKCTL,
.enable_reg = ARM_IDLECT2,
.enable_bit = EN_PERCK,
@@ -385,7 +386,8 @@ static struct clk uart2_ck = {
.name = "uart2_ck",
/* Direct from ULPD, no parent */
.rate = 12000000,
.flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | ENABLE_REG_32BIT,
.flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | ENABLE_REG_32BIT |
ALWAYS_ENABLED,
.enable_reg = MOD_CONF_CTRL_0,
.enable_bit = 30, /* Chooses between 12MHz and 48MHz */
.set_rate = &set_uart_rate,
@@ -443,6 +445,15 @@ static struct clk usb_hhc_ck16xx = {
.enable_bit = 8 /* UHOST_EN */,
};
static struct clk usb_dc_ck = {
.name = "usb_dc_ck",
/* Direct from ULPD, no parent */
.rate = 48000000,
.flags = CLOCK_IN_OMAP16XX | RATE_FIXED,
.enable_reg = SOFT_REQ_REG,
.enable_bit = 4,
};
static struct clk mclk_1510 = {
.name = "mclk",
/* Direct from ULPD, no parent. May be enabled by ext hardware. */
@@ -552,6 +563,7 @@ static struct clk * onchip_clks[] = {
&uart3_16xx,
&usb_clko,
&usb_hhc_ck1510, &usb_hhc_ck16xx,
&usb_dc_ck,
&mclk_1510, &mclk_16xx,
&bclk_1510, &bclk_16xx,
&mmc1_ck,
@@ -946,14 +958,13 @@ static int select_table_rate(struct clk * clk, unsigned long rate)
if (!ptr->rate)
return -EINVAL;
if (!ptr->rate)
return -EINVAL;
/*
* In most cases we should not need to reprogram DPLL.
* Reprogramming the DPLL is tricky, it must be done from SRAM.
*/
omap_sram_reprogram_clock(ptr->dpllctl_val, ptr->ckctl_val);
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);
ck_dpll1.rate = ptr->pll_rate;
propagate_rate(&ck_dpll1);
return 0;
}
@@ -1224,9 +1235,11 @@ int __init clk_init(void)
#endif
/* Cache rates for clocks connected to ck_ref (not dpll1) */
propagate_rate(&ck_ref);
printk(KERN_INFO "Clocking rate (xtal/DPLL1/MPU): %ld.%01ld/%ld/%ld MHz\n",
printk(KERN_INFO "Clocking rate (xtal/DPLL1/MPU): "
"%ld.%01ld/%ld.%01ld/%ld.%01ld MHz\n",
ck_ref.rate / 1000000, (ck_ref.rate / 100000) % 10,
ck_dpll1.rate, arm_ck.rate);
ck_dpll1.rate / 1000000, (ck_dpll1.rate / 100000) % 10,
arm_ck.rate / 1000000, (arm_ck.rate / 100000) % 10);
#ifdef CONFIG_MACH_OMAP_PERSEUS2
/* Select slicer output as OMAP input clock */
@@ -1271,7 +1284,9 @@ static int __init omap_late_clk_reset(void)
struct clk *p;
__u32 regval32;
omap_writew(0, SOFT_REQ_REG);
/* USB_REQ_EN will be disabled later if necessary (usb_dc_ck) */
regval32 = omap_readw(SOFT_REQ_REG) & (1 << 4);
omap_writew(regval32, SOFT_REQ_REG);
omap_writew(0, SOFT_REQ_REG2);
list_for_each_entry(p, &clocks, node) {

View File

@@ -26,6 +26,7 @@
#include <asm/hardware/clock.h>
#include <asm/io.h>
#include <asm/mach-types.h>
#include <asm/setup.h>
#include <asm/arch/board.h>
#include <asm/arch/mux.h>
@@ -35,11 +36,11 @@
#define NO_LENGTH_CHECK 0xffffffff
extern int omap_bootloader_tag_len;
extern u8 omap_bootloader_tag[];
unsigned char omap_bootloader_tag[512];
int omap_bootloader_tag_len;
struct omap_board_config_kernel *omap_board_config;
int omap_board_config_size = 0;
int omap_board_config_size;
static const void *get_config(u16 tag, size_t len, int skip, size_t *len_out)
{

View File

@@ -425,7 +425,7 @@ static int dma_handle_ch(int ch)
dma_chan[ch + 6].saved_csr = csr >> 7;
csr &= 0x7f;
}
if (!csr)
if ((csr & 0x3f) == 0)
return 0;
if (unlikely(dma_chan[ch].dev_id == -1)) {
printk(KERN_WARNING "Spurious interrupt from DMA channel %d (CSR %04x)\n",
@@ -890,11 +890,11 @@ void omap_enable_lcd_dma(void)
w |= 1 << 8;
omap_writew(w, OMAP1610_DMA_LCD_CTRL);
lcd_dma.active = 1;
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)
@@ -965,8 +965,8 @@ void omap_clear_dma(int lch)
*/
dma_addr_t omap_get_dma_src_pos(int lch)
{
return (dma_addr_t) (OMAP_DMA_CSSA_L(lch) |
(OMAP_DMA_CSSA_U(lch) << 16));
return (dma_addr_t) (omap_readw(OMAP_DMA_CSSA_L(lch)) |
(omap_readw(OMAP_DMA_CSSA_U(lch)) << 16));
}
/*
@@ -979,8 +979,18 @@ dma_addr_t omap_get_dma_src_pos(int lch)
*/
dma_addr_t omap_get_dma_dst_pos(int lch)
{
return (dma_addr_t) (OMAP_DMA_CDSA_L(lch) |
(OMAP_DMA_CDSA_U(lch) << 16));
return (dma_addr_t) (omap_readw(OMAP_DMA_CDSA_L(lch)) |
(omap_readw(OMAP_DMA_CDSA_U(lch)) << 16));
}
/*
* Returns current source transfer counting for the given DMA channel.
* Can be used to monitor the progress of a transfer inside a block.
* It must be called with disabled interrupts.
*/
int omap_get_dma_src_addr_counter(int lch)
{
return (dma_addr_t) omap_readw(OMAP_DMA_CSAC(lch));
}
int omap_dma_running(void)
@@ -1076,6 +1086,7 @@ arch_initcall(omap_init_dma);
EXPORT_SYMBOL(omap_get_dma_src_pos);
EXPORT_SYMBOL(omap_get_dma_dst_pos);
EXPORT_SYMBOL(omap_get_dma_src_addr_counter);
EXPORT_SYMBOL(omap_clear_dma);
EXPORT_SYMBOL(omap_set_dma_priority);
EXPORT_SYMBOL(omap_request_dma);

View File

@@ -0,0 +1,260 @@
/*
* linux/arch/arm/plat-omap/dmtimer.c
*
* OMAP Dual-Mode Timers
*
* Copyright (C) 2005 Nokia Corporation
* Author: Lauri Leukkunen <lauri.leukkunen@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 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
* 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/init.h>
#include <asm/arch/hardware.h>
#include <asm/arch/dmtimer.h>
#include <asm/io.h>
#include <asm/arch/irqs.h>
#include <linux/spinlock.h>
#include <linux/list.h>
#define OMAP_TIMER_COUNT 8
#define OMAP_TIMER_ID_REG 0x00
#define OMAP_TIMER_OCP_CFG_REG 0x10
#define OMAP_TIMER_SYS_STAT_REG 0x14
#define OMAP_TIMER_STAT_REG 0x18
#define OMAP_TIMER_INT_EN_REG 0x1c
#define OMAP_TIMER_WAKEUP_EN_REG 0x20
#define OMAP_TIMER_CTRL_REG 0x24
#define OMAP_TIMER_COUNTER_REG 0x28
#define OMAP_TIMER_LOAD_REG 0x2c
#define OMAP_TIMER_TRIGGER_REG 0x30
#define OMAP_TIMER_WRITE_PEND_REG 0x34
#define OMAP_TIMER_MATCH_REG 0x38
#define OMAP_TIMER_CAPTURE_REG 0x3c
#define OMAP_TIMER_IF_CTRL_REG 0x40
static struct dmtimer_info_struct {
struct list_head unused_timers;
struct list_head reserved_timers;
} dm_timer_info;
static struct omap_dm_timer dm_timers[] = {
{ .base=0xfffb1400, .irq=INT_1610_GPTIMER1 },
{ .base=0xfffb1c00, .irq=INT_1610_GPTIMER2 },
{ .base=0xfffb2400, .irq=INT_1610_GPTIMER3 },
{ .base=0xfffb2c00, .irq=INT_1610_GPTIMER4 },
{ .base=0xfffb3400, .irq=INT_1610_GPTIMER5 },
{ .base=0xfffb3c00, .irq=INT_1610_GPTIMER6 },
{ .base=0xfffb4400, .irq=INT_1610_GPTIMER7 },
{ .base=0xfffb4c00, .irq=INT_1610_GPTIMER8 },
{ .base=0x0 },
};
static spinlock_t dm_timer_lock;
inline void omap_dm_timer_write_reg(struct omap_dm_timer *timer, int reg, u32 value)
{
omap_writel(value, timer->base + reg);
while (omap_dm_timer_read_reg(timer, OMAP_TIMER_WRITE_PEND_REG))
;
}
u32 omap_dm_timer_read_reg(struct omap_dm_timer *timer, int reg)
{
return omap_readl(timer->base + reg);
}
int omap_dm_timers_active(void)
{
struct omap_dm_timer *timer;
for (timer = &dm_timers[0]; timer->base; ++timer)
if (omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG) &
OMAP_TIMER_CTRL_ST)
return 1;
return 0;
}
void omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
{
int n = (timer - dm_timers) << 1;
u32 l;
l = omap_readl(MOD_CONF_CTRL_1) & ~(0x03 << n);
l |= source << n;
omap_writel(l, MOD_CONF_CTRL_1);
}
static void omap_dm_timer_reset(struct omap_dm_timer *timer)
{
/* Reset and set posted mode */
omap_dm_timer_write_reg(timer, OMAP_TIMER_IF_CTRL_REG, 0x06);
omap_dm_timer_write_reg(timer, OMAP_TIMER_OCP_CFG_REG, 0x02);
omap_dm_timer_set_source(timer, OMAP_TIMER_SRC_ARMXOR);
}
struct omap_dm_timer * omap_dm_timer_request(void)
{
struct omap_dm_timer *timer = NULL;
unsigned long flags;
spin_lock_irqsave(&dm_timer_lock, flags);
if (!list_empty(&dm_timer_info.unused_timers)) {
timer = (struct omap_dm_timer *)
dm_timer_info.unused_timers.next;
list_move_tail((struct list_head *)timer,
&dm_timer_info.reserved_timers);
}
spin_unlock_irqrestore(&dm_timer_lock, flags);
return timer;
}
void omap_dm_timer_free(struct omap_dm_timer *timer)
{
unsigned long flags;
omap_dm_timer_reset(timer);
spin_lock_irqsave(&dm_timer_lock, flags);
list_move_tail((struct list_head *)timer, &dm_timer_info.unused_timers);
spin_unlock_irqrestore(&dm_timer_lock, flags);
}
void omap_dm_timer_set_int_enable(struct omap_dm_timer *timer,
unsigned int value)
{
omap_dm_timer_write_reg(timer, OMAP_TIMER_INT_EN_REG, value);
}
unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer)
{
return omap_dm_timer_read_reg(timer, OMAP_TIMER_STAT_REG);
}
void omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value)
{
omap_dm_timer_write_reg(timer, OMAP_TIMER_STAT_REG, value);
}
void omap_dm_timer_enable_autoreload(struct omap_dm_timer *timer)
{
u32 l;
l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
l |= OMAP_TIMER_CTRL_AR;
omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
}
void omap_dm_timer_trigger(struct omap_dm_timer *timer)
{
omap_dm_timer_write_reg(timer, OMAP_TIMER_TRIGGER_REG, 1);
}
void omap_dm_timer_set_trigger(struct omap_dm_timer *timer, unsigned int value)
{
u32 l;
l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
l |= value & 0x3;
omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
}
void omap_dm_timer_start(struct omap_dm_timer *timer)
{
u32 l;
l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
l |= OMAP_TIMER_CTRL_ST;
omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
}
void omap_dm_timer_stop(struct omap_dm_timer *timer)
{
u32 l;
l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
l &= ~0x1;
omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
}
unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer)
{
return omap_dm_timer_read_reg(timer, OMAP_TIMER_COUNTER_REG);
}
void omap_dm_timer_reset_counter(struct omap_dm_timer *timer)
{
omap_dm_timer_write_reg(timer, OMAP_TIMER_COUNTER_REG, 0);
}
void omap_dm_timer_set_load(struct omap_dm_timer *timer, unsigned int load)
{
omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG, load);
}
void omap_dm_timer_set_match(struct omap_dm_timer *timer, unsigned int match)
{
omap_dm_timer_write_reg(timer, OMAP_TIMER_MATCH_REG, match);
}
void omap_dm_timer_enable_compare(struct omap_dm_timer *timer)
{
u32 l;
l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
l |= OMAP_TIMER_CTRL_CE;
omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
}
static inline void __dm_timer_init(void)
{
struct omap_dm_timer *timer;
spin_lock_init(&dm_timer_lock);
INIT_LIST_HEAD(&dm_timer_info.unused_timers);
INIT_LIST_HEAD(&dm_timer_info.reserved_timers);
timer = &dm_timers[0];
while (timer->base) {
list_add_tail((struct list_head *)timer, &dm_timer_info.unused_timers);
omap_dm_timer_reset(timer);
timer++;
}
}
static int __init omap_dm_timer_init(void)
{
if (cpu_is_omap16xx())
__dm_timer_init();
return 0;
}
arch_initcall(omap_dm_timer_init);

View File

@@ -3,7 +3,7 @@
*
* Support functions for OMAP GPIO
*
* Copyright (C) 2003 Nokia Corporation
* Copyright (C) 2003-2005 Nokia Corporation
* Written by Juha Yrj<72>l<EFBFBD> <juha.yrjola@nokia.com>
*
* This program is free software; you can redistribute it and/or modify
@@ -17,8 +17,11 @@
#include <linux/sched.h>
#include <linux/interrupt.h>
#include <linux/ptrace.h>
#include <linux/sysdev.h>
#include <linux/err.h>
#include <asm/hardware.h>
#include <asm/hardware/clock.h>
#include <asm/irq.h>
#include <asm/arch/irqs.h>
#include <asm/arch/gpio.h>
@@ -29,7 +32,7 @@
/*
* OMAP1510 GPIO registers
*/
#define OMAP1510_GPIO_BASE 0xfffce000
#define OMAP1510_GPIO_BASE (void __iomem *)0xfffce000
#define OMAP1510_GPIO_DATA_INPUT 0x00
#define OMAP1510_GPIO_DATA_OUTPUT 0x04
#define OMAP1510_GPIO_DIR_CONTROL 0x08
@@ -43,34 +46,37 @@
/*
* OMAP1610 specific GPIO registers
*/
#define OMAP1610_GPIO1_BASE 0xfffbe400
#define OMAP1610_GPIO2_BASE 0xfffbec00
#define OMAP1610_GPIO3_BASE 0xfffbb400
#define OMAP1610_GPIO4_BASE 0xfffbbc00
#define OMAP1610_GPIO1_BASE (void __iomem *)0xfffbe400
#define OMAP1610_GPIO2_BASE (void __iomem *)0xfffbec00
#define OMAP1610_GPIO3_BASE (void __iomem *)0xfffbb400
#define OMAP1610_GPIO4_BASE (void __iomem *)0xfffbbc00
#define OMAP1610_GPIO_REVISION 0x0000
#define OMAP1610_GPIO_SYSCONFIG 0x0010
#define OMAP1610_GPIO_SYSSTATUS 0x0014
#define OMAP1610_GPIO_IRQSTATUS1 0x0018
#define OMAP1610_GPIO_IRQENABLE1 0x001c
#define OMAP1610_GPIO_WAKEUPENABLE 0x0028
#define OMAP1610_GPIO_DATAIN 0x002c
#define OMAP1610_GPIO_DATAOUT 0x0030
#define OMAP1610_GPIO_DIRECTION 0x0034
#define OMAP1610_GPIO_EDGE_CTRL1 0x0038
#define OMAP1610_GPIO_EDGE_CTRL2 0x003c
#define OMAP1610_GPIO_CLEAR_IRQENABLE1 0x009c
#define OMAP1610_GPIO_CLEAR_WAKEUPENA 0x00a8
#define OMAP1610_GPIO_CLEAR_DATAOUT 0x00b0
#define OMAP1610_GPIO_SET_IRQENABLE1 0x00dc
#define OMAP1610_GPIO_SET_WAKEUPENA 0x00e8
#define OMAP1610_GPIO_SET_DATAOUT 0x00f0
/*
* OMAP730 specific GPIO registers
*/
#define OMAP730_GPIO1_BASE 0xfffbc000
#define OMAP730_GPIO2_BASE 0xfffbc800
#define OMAP730_GPIO3_BASE 0xfffbd000
#define OMAP730_GPIO4_BASE 0xfffbd800
#define OMAP730_GPIO5_BASE 0xfffbe000
#define OMAP730_GPIO6_BASE 0xfffbe800
#define OMAP730_GPIO1_BASE (void __iomem *)0xfffbc000
#define OMAP730_GPIO2_BASE (void __iomem *)0xfffbc800
#define OMAP730_GPIO3_BASE (void __iomem *)0xfffbd000
#define OMAP730_GPIO4_BASE (void __iomem *)0xfffbd800
#define OMAP730_GPIO5_BASE (void __iomem *)0xfffbe000
#define OMAP730_GPIO6_BASE (void __iomem *)0xfffbe800
#define OMAP730_GPIO_DATA_INPUT 0x00
#define OMAP730_GPIO_DATA_OUTPUT 0x04
#define OMAP730_GPIO_DIR_CONTROL 0x08
@@ -78,14 +84,43 @@
#define OMAP730_GPIO_INT_MASK 0x10
#define OMAP730_GPIO_INT_STATUS 0x14
/*
* omap24xx specific GPIO registers
*/
#define OMAP24XX_GPIO1_BASE (void __iomem *)0x48018000
#define OMAP24XX_GPIO2_BASE (void __iomem *)0x4801a000
#define OMAP24XX_GPIO3_BASE (void __iomem *)0x4801c000
#define OMAP24XX_GPIO4_BASE (void __iomem *)0x4801e000
#define OMAP24XX_GPIO_REVISION 0x0000
#define OMAP24XX_GPIO_SYSCONFIG 0x0010
#define OMAP24XX_GPIO_SYSSTATUS 0x0014
#define OMAP24XX_GPIO_IRQSTATUS1 0x0018
#define OMAP24XX_GPIO_IRQENABLE1 0x001c
#define OMAP24XX_GPIO_CTRL 0x0030
#define OMAP24XX_GPIO_OE 0x0034
#define OMAP24XX_GPIO_DATAIN 0x0038
#define OMAP24XX_GPIO_DATAOUT 0x003c
#define OMAP24XX_GPIO_LEVELDETECT0 0x0040
#define OMAP24XX_GPIO_LEVELDETECT1 0x0044
#define OMAP24XX_GPIO_RISINGDETECT 0x0048
#define OMAP24XX_GPIO_FALLINGDETECT 0x004c
#define OMAP24XX_GPIO_CLEARIRQENABLE1 0x0060
#define OMAP24XX_GPIO_SETIRQENABLE1 0x0064
#define OMAP24XX_GPIO_CLEARWKUENA 0x0080
#define OMAP24XX_GPIO_SETWKUENA 0x0084
#define OMAP24XX_GPIO_CLEARDATAOUT 0x0090
#define OMAP24XX_GPIO_SETDATAOUT 0x0094
#define OMAP_MPUIO_MASK (~OMAP_MAX_GPIO_LINES & 0xff)
struct gpio_bank {
u32 base;
void __iomem *base;
u16 irq;
u16 virtual_irq_start;
u8 method;
int method;
u32 reserved_map;
u32 suspend_wakeup;
u32 saved_wakeup;
spinlock_t lock;
};
@@ -93,8 +128,9 @@ struct gpio_bank {
#define METHOD_GPIO_1510 1
#define METHOD_GPIO_1610 2
#define METHOD_GPIO_730 3
#define METHOD_GPIO_24XX 4
#if defined(CONFIG_ARCH_OMAP16XX)
#ifdef 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 },
@@ -123,6 +159,15 @@ static struct gpio_bank gpio_bank_730[7] = {
};
#endif
#ifdef CONFIG_ARCH_OMAP24XX
static struct gpio_bank gpio_bank_24xx[4] = {
{ OMAP24XX_GPIO1_BASE, INT_24XX_GPIO_BANK1, IH_GPIO_BASE, METHOD_GPIO_24XX },
{ OMAP24XX_GPIO2_BASE, INT_24XX_GPIO_BANK2, IH_GPIO_BASE + 32, METHOD_GPIO_24XX },
{ OMAP24XX_GPIO3_BASE, INT_24XX_GPIO_BANK3, IH_GPIO_BASE + 64, METHOD_GPIO_24XX },
{ OMAP24XX_GPIO4_BASE, INT_24XX_GPIO_BANK4, IH_GPIO_BASE + 96, METHOD_GPIO_24XX },
};
#endif
static struct gpio_bank *gpio_bank;
static int gpio_bank_count;
@@ -149,14 +194,23 @@ static inline struct gpio_bank *get_gpio_bank(int gpio)
return &gpio_bank[1 + (gpio >> 5)];
}
#endif
#ifdef CONFIG_ARCH_OMAP24XX
if (cpu_is_omap24xx())
return &gpio_bank[gpio >> 5];
#endif
}
static inline int get_gpio_index(int gpio)
{
#ifdef CONFIG_ARCH_OMAP730
if (cpu_is_omap730())
return gpio & 0x1f;
else
return gpio & 0x0f;
#endif
#ifdef CONFIG_ARCH_OMAP24XX
if (cpu_is_omap24xx())
return gpio & 0x1f;
#endif
return gpio & 0x0f;
}
static inline int gpio_valid(int gpio)
@@ -179,6 +233,10 @@ static inline int gpio_valid(int gpio)
#ifdef CONFIG_ARCH_OMAP730
if (cpu_is_omap730() && gpio < 192)
return 0;
#endif
#ifdef CONFIG_ARCH_OMAP24XX
if (cpu_is_omap24xx() && gpio < 128)
return 0;
#endif
return -1;
}
@@ -195,7 +253,7 @@ static int check_gpio(int gpio)
static void _set_gpio_direction(struct gpio_bank *bank, int gpio, int is_input)
{
u32 reg = bank->base;
void __iomem *reg = bank->base;
u32 l;
switch (bank->method) {
@@ -211,6 +269,9 @@ static void _set_gpio_direction(struct gpio_bank *bank, int gpio, int is_input)
case METHOD_GPIO_730:
reg += OMAP730_GPIO_DIR_CONTROL;
break;
case METHOD_GPIO_24XX:
reg += OMAP24XX_GPIO_OE;
break;
}
l = __raw_readl(reg);
if (is_input)
@@ -234,7 +295,7 @@ void omap_set_gpio_direction(int gpio, int is_input)
static void _set_gpio_dataout(struct gpio_bank *bank, int gpio, int enable)
{
u32 reg = bank->base;
void __iomem *reg = bank->base;
u32 l = 0;
switch (bank->method) {
@@ -269,6 +330,13 @@ static void _set_gpio_dataout(struct gpio_bank *bank, int gpio, int enable)
else
l &= ~(1 << gpio);
break;
case METHOD_GPIO_24XX:
if (enable)
reg += OMAP24XX_GPIO_SETDATAOUT;
else
reg += OMAP24XX_GPIO_CLEARDATAOUT;
l = 1 << gpio;
break;
default:
BUG();
return;
@@ -291,7 +359,7 @@ void omap_set_gpio_dataout(int gpio, int enable)
int omap_get_gpio_datain(int gpio)
{
struct gpio_bank *bank;
u32 reg;
void __iomem *reg;
if (check_gpio(gpio) < 0)
return -1;
@@ -310,109 +378,132 @@ int omap_get_gpio_datain(int gpio)
case METHOD_GPIO_730:
reg += OMAP730_GPIO_DATA_INPUT;
break;
case METHOD_GPIO_24XX:
reg += OMAP24XX_GPIO_DATAIN;
break;
default:
BUG();
return -1;
}
return (__raw_readl(reg) & (1 << get_gpio_index(gpio))) != 0;
return (__raw_readl(reg)
& (1 << get_gpio_index(gpio))) != 0;
}
static void _set_gpio_edge_ctrl(struct gpio_bank *bank, int gpio, int edge)
#define MOD_REG_BIT(reg, bit_mask, set) \
do { \
int l = __raw_readl(base + reg); \
if (set) l |= bit_mask; \
else l &= ~bit_mask; \
__raw_writel(l, base + reg); \
} while(0)
static inline void set_24xx_gpio_triggering(void __iomem *base, int gpio, int trigger)
{
u32 reg = bank->base;
u32 l;
u32 gpio_bit = 1 << gpio;
MOD_REG_BIT(OMAP24XX_GPIO_LEVELDETECT0, gpio_bit,
trigger & IRQT_LOW);
MOD_REG_BIT(OMAP24XX_GPIO_LEVELDETECT1, gpio_bit,
trigger & IRQT_HIGH);
MOD_REG_BIT(OMAP24XX_GPIO_RISINGDETECT, gpio_bit,
trigger & IRQT_RISING);
MOD_REG_BIT(OMAP24XX_GPIO_FALLINGDETECT, gpio_bit,
trigger & IRQT_FALLING);
/* FIXME: Possibly do 'set_irq_handler(j, do_level_IRQ)' if only level
* triggering requested. */
}
static int _set_gpio_triggering(struct gpio_bank *bank, int gpio, int trigger)
{
void __iomem *reg = bank->base;
u32 l = 0;
switch (bank->method) {
case METHOD_MPUIO:
reg += OMAP_MPUIO_GPIO_INT_EDGE;
l = __raw_readl(reg);
if (edge == OMAP_GPIO_RISING_EDGE)
if (trigger == IRQT_RISING)
l |= 1 << gpio;
else
else if (trigger == IRQT_FALLING)
l &= ~(1 << gpio);
__raw_writel(l, reg);
else
goto bad;
break;
case METHOD_GPIO_1510:
reg += OMAP1510_GPIO_INT_CONTROL;
l = __raw_readl(reg);
if (edge == OMAP_GPIO_RISING_EDGE)
if (trigger == IRQT_RISING)
l |= 1 << gpio;
else
else if (trigger == IRQT_FALLING)
l &= ~(1 << gpio);
__raw_writel(l, reg);
else
goto bad;
break;
case METHOD_GPIO_1610:
edge &= 0x03;
if (gpio & 0x08)
reg += OMAP1610_GPIO_EDGE_CTRL2;
else
reg += OMAP1610_GPIO_EDGE_CTRL1;
gpio &= 0x07;
/* We allow only edge triggering, i.e. two lowest bits */
if (trigger & ~IRQT_BOTHEDGE)
BUG();
/* NOTE: knows __IRQT_{FAL,RIS}EDGE match OMAP hardware */
trigger &= 0x03;
l = __raw_readl(reg);
l &= ~(3 << (gpio << 1));
l |= edge << (gpio << 1);
__raw_writel(l, reg);
l |= trigger << (gpio << 1);
break;
case METHOD_GPIO_730:
reg += OMAP730_GPIO_INT_CONTROL;
l = __raw_readl(reg);
if (edge == OMAP_GPIO_RISING_EDGE)
if (trigger == IRQT_RISING)
l |= 1 << gpio;
else
else if (trigger == IRQT_FALLING)
l &= ~(1 << gpio);
__raw_writel(l, reg);
else
goto bad;
break;
case METHOD_GPIO_24XX:
set_24xx_gpio_triggering(reg, gpio, trigger);
break;
default:
BUG();
return;
goto bad;
}
__raw_writel(l, reg);
return 0;
bad:
return -EINVAL;
}
void omap_set_gpio_edge_ctrl(int gpio, int edge)
static int gpio_irq_type(unsigned irq, unsigned type)
{
struct gpio_bank *bank;
unsigned gpio;
int retval;
if (irq > IH_MPUIO_BASE)
gpio = OMAP_MPUIO(irq - IH_MPUIO_BASE);
else
gpio = irq - IH_GPIO_BASE;
if (check_gpio(gpio) < 0)
return;
return -EINVAL;
if (type & (__IRQT_LOWLVL|__IRQT_HIGHLVL|IRQT_PROBE))
return -EINVAL;
bank = get_gpio_bank(gpio);
spin_lock(&bank->lock);
_set_gpio_edge_ctrl(bank, get_gpio_index(gpio), edge);
retval = _set_gpio_triggering(bank, get_gpio_index(gpio), type);
spin_unlock(&bank->lock);
}
static int _get_gpio_edge_ctrl(struct gpio_bank *bank, int gpio)
{
u32 reg = bank->base, l;
switch (bank->method) {
case METHOD_MPUIO:
l = __raw_readl(reg + OMAP_MPUIO_GPIO_INT_EDGE);
return (l & (1 << gpio)) ?
OMAP_GPIO_RISING_EDGE : OMAP_GPIO_FALLING_EDGE;
case METHOD_GPIO_1510:
l = __raw_readl(reg + OMAP1510_GPIO_INT_CONTROL);
return (l & (1 << gpio)) ?
OMAP_GPIO_RISING_EDGE : OMAP_GPIO_FALLING_EDGE;
case METHOD_GPIO_1610:
if (gpio & 0x08)
reg += OMAP1610_GPIO_EDGE_CTRL2;
else
reg += OMAP1610_GPIO_EDGE_CTRL1;
return (__raw_readl(reg) >> ((gpio & 0x07) << 1)) & 0x03;
case METHOD_GPIO_730:
l = __raw_readl(reg + OMAP730_GPIO_INT_CONTROL);
return (l & (1 << gpio)) ?
OMAP_GPIO_RISING_EDGE : OMAP_GPIO_FALLING_EDGE;
default:
BUG();
return -1;
}
return retval;
}
static void _clear_gpio_irqbank(struct gpio_bank *bank, int gpio_mask)
{
u32 reg = bank->base;
void __iomem *reg = bank->base;
switch (bank->method) {
case METHOD_MPUIO:
@@ -428,6 +519,9 @@ static void _clear_gpio_irqbank(struct gpio_bank *bank, int gpio_mask)
case METHOD_GPIO_730:
reg += OMAP730_GPIO_INT_STATUS;
break;
case METHOD_GPIO_24XX:
reg += OMAP24XX_GPIO_IRQSTATUS1;
break;
default:
BUG();
return;
@@ -442,7 +536,7 @@ static inline void _clear_gpio_irqstatus(struct gpio_bank *bank, int gpio)
static void _enable_gpio_irqbank(struct gpio_bank *bank, int gpio_mask, int enable)
{
u32 reg = bank->base;
void __iomem *reg = bank->base;
u32 l;
switch (bank->method) {
@@ -477,6 +571,13 @@ static void _enable_gpio_irqbank(struct gpio_bank *bank, int gpio_mask, int enab
else
l |= gpio_mask;
break;
case METHOD_GPIO_24XX:
if (enable)
reg += OMAP24XX_GPIO_SETIRQENABLE1;
else
reg += OMAP24XX_GPIO_CLEARIRQENABLE1;
l = gpio_mask;
break;
default:
BUG();
return;
@@ -489,6 +590,50 @@ static inline void _set_gpio_irqenable(struct gpio_bank *bank, int gpio, int ena
_enable_gpio_irqbank(bank, 1 << get_gpio_index(gpio), enable);
}
/*
* Note that ENAWAKEUP needs to be enabled in GPIO_SYSCONFIG register.
* 1510 does not seem to have a wake-up register. If JTAG is connected
* to the target, system will wake up always on GPIO events. While
* system is running all registered GPIO interrupts need to have wake-up
* enabled. When system is suspended, only selected GPIO interrupts need
* to have wake-up enabled.
*/
static int _set_gpio_wakeup(struct gpio_bank *bank, int gpio, int enable)
{
switch (bank->method) {
case METHOD_GPIO_1610:
case METHOD_GPIO_24XX:
spin_lock(&bank->lock);
if (enable)
bank->suspend_wakeup |= (1 << gpio);
else
bank->suspend_wakeup &= ~(1 << gpio);
spin_unlock(&bank->lock);
return 0;
default:
printk(KERN_ERR "Can't enable GPIO wakeup for method %i\n",
bank->method);
return -EINVAL;
}
}
/* Use disable_irq_wake() and enable_irq_wake() functions from drivers */
static int gpio_wake_enable(unsigned int irq, unsigned int enable)
{
unsigned int gpio = irq - IH_GPIO_BASE;
struct gpio_bank *bank;
int retval;
if (check_gpio(gpio) < 0)
return -ENODEV;
bank = get_gpio_bank(gpio);
spin_lock(&bank->lock);
retval = _set_gpio_wakeup(bank, get_gpio_index(gpio), enable);
spin_unlock(&bank->lock);
return retval;
}
int omap_request_gpio(int gpio)
{
struct gpio_bank *bank;
@@ -505,14 +650,32 @@ int omap_request_gpio(int gpio)
return -1;
}
bank->reserved_map |= (1 << get_gpio_index(gpio));
/* Set trigger to none. You need to enable the trigger after request_irq */
_set_gpio_triggering(bank, get_gpio_index(gpio), IRQT_NOEDGE);
#ifdef CONFIG_ARCH_OMAP1510
if (bank->method == METHOD_GPIO_1510) {
u32 reg;
void __iomem *reg;
/* Claim the pin for the ARM */
/* Claim the pin for MPU */
reg = bank->base + OMAP1510_GPIO_PIN_CONTROL;
__raw_writel(__raw_readl(reg) | (1 << get_gpio_index(gpio)), reg);
}
#endif
#ifdef CONFIG_ARCH_OMAP16XX
if (bank->method == METHOD_GPIO_1610) {
/* Enable wake-up during idle for dynamic tick */
void __iomem *reg = bank->base + OMAP1610_GPIO_SET_WAKEUPENA;
__raw_writel(1 << get_gpio_index(gpio), reg);
}
#endif
#ifdef CONFIG_ARCH_OMAP24XX
if (bank->method == METHOD_GPIO_24XX) {
/* Enable wake-up during idle for dynamic tick */
void __iomem *reg = bank->base + OMAP24XX_GPIO_SETWKUENA;
__raw_writel(1 << get_gpio_index(gpio), reg);
}
#endif
spin_unlock(&bank->lock);
@@ -533,6 +696,20 @@ void omap_free_gpio(int gpio)
spin_unlock(&bank->lock);
return;
}
#ifdef CONFIG_ARCH_OMAP16XX
if (bank->method == METHOD_GPIO_1610) {
/* Disable wake-up during idle for dynamic tick */
void __iomem *reg = bank->base + OMAP1610_GPIO_CLEAR_WAKEUPENA;
__raw_writel(1 << get_gpio_index(gpio), reg);
}
#endif
#ifdef CONFIG_ARCH_OMAP24XX
if (bank->method == METHOD_GPIO_24XX) {
/* Disable wake-up during idle for dynamic tick */
void __iomem *reg = bank->base + OMAP24XX_GPIO_CLEARWKUENA;
__raw_writel(1 << get_gpio_index(gpio), reg);
}
#endif
bank->reserved_map &= ~(1 << get_gpio_index(gpio));
_set_gpio_direction(bank, get_gpio_index(gpio), 1);
_set_gpio_irqenable(bank, gpio, 0);
@@ -552,7 +729,7 @@ void omap_free_gpio(int gpio)
static void gpio_irq_handler(unsigned int irq, struct irqdesc *desc,
struct pt_regs *regs)
{
u32 isr_reg = 0;
void __iomem *isr_reg = NULL;
u32 isr;
unsigned int gpio_irq;
struct gpio_bank *bank;
@@ -574,24 +751,30 @@ static void gpio_irq_handler(unsigned int irq, struct irqdesc *desc,
if (bank->method == METHOD_GPIO_730)
isr_reg = bank->base + OMAP730_GPIO_INT_STATUS;
#endif
#ifdef CONFIG_ARCH_OMAP24XX
if (bank->method == METHOD_GPIO_24XX)
isr_reg = bank->base + OMAP24XX_GPIO_IRQSTATUS1;
#endif
isr = __raw_readl(isr_reg);
_enable_gpio_irqbank(bank, isr, 0);
_clear_gpio_irqbank(bank, isr);
_enable_gpio_irqbank(bank, isr, 1);
desc->chip->unmask(irq);
while(1) {
isr = __raw_readl(isr_reg);
_enable_gpio_irqbank(bank, isr, 0);
_clear_gpio_irqbank(bank, isr);
_enable_gpio_irqbank(bank, isr, 1);
desc->chip->unmask(irq);
if (unlikely(!isr))
return;
if (!isr)
break;
gpio_irq = bank->virtual_irq_start;
for (; isr != 0; isr >>= 1, gpio_irq++) {
struct irqdesc *d;
if (!(isr & 1))
continue;
d = irq_desc + gpio_irq;
desc_handle_irq(gpio_irq, d, regs);
}
gpio_irq = bank->virtual_irq_start;
for (; isr != 0; isr >>= 1, gpio_irq++) {
struct irqdesc *d;
if (!(isr & 1))
continue;
d = irq_desc + gpio_irq;
desc_handle_irq(gpio_irq, d, regs);
}
}
}
static void gpio_ack_irq(unsigned int irq)
@@ -613,14 +796,10 @@ static void gpio_mask_irq(unsigned int irq)
static void gpio_unmask_irq(unsigned int irq)
{
unsigned int gpio = irq - IH_GPIO_BASE;
unsigned int gpio_idx = get_gpio_index(gpio);
struct gpio_bank *bank = get_gpio_bank(gpio);
if (_get_gpio_edge_ctrl(bank, get_gpio_index(gpio)) == OMAP_GPIO_NO_EDGE) {
printk(KERN_ERR "OMAP GPIO %d: trying to enable GPIO IRQ while no edge is set\n",
gpio);
_set_gpio_edge_ctrl(bank, get_gpio_index(gpio), OMAP_GPIO_RISING_EDGE);
}
_set_gpio_irqenable(bank, gpio, 1);
_set_gpio_irqenable(bank, gpio_idx, 1);
}
static void mpuio_ack_irq(unsigned int irq)
@@ -645,9 +824,11 @@ static void mpuio_unmask_irq(unsigned int irq)
}
static struct irqchip gpio_irq_chip = {
.ack = gpio_ack_irq,
.mask = gpio_mask_irq,
.unmask = gpio_unmask_irq,
.ack = gpio_ack_irq,
.mask = gpio_mask_irq,
.unmask = gpio_unmask_irq,
.set_type = gpio_irq_type,
.set_wake = gpio_wake_enable,
};
static struct irqchip mpuio_irq_chip = {
@@ -657,6 +838,7 @@ static struct irqchip mpuio_irq_chip = {
};
static int initialized = 0;
static struct clk * gpio_ck = NULL;
static int __init _omap_gpio_init(void)
{
@@ -665,6 +847,14 @@ static int __init _omap_gpio_init(void)
initialized = 1;
if (cpu_is_omap1510()) {
gpio_ck = clk_get(NULL, "arm_gpio_ck");
if (IS_ERR(gpio_ck))
printk("Could not get arm_gpio_ck\n");
else
clk_use(gpio_ck);
}
#ifdef CONFIG_ARCH_OMAP1510
if (cpu_is_omap1510()) {
printk(KERN_INFO "OMAP1510 GPIO hardware\n");
@@ -674,7 +864,7 @@ static int __init _omap_gpio_init(void)
#endif
#if defined(CONFIG_ARCH_OMAP16XX)
if (cpu_is_omap16xx()) {
int rev;
u32 rev;
gpio_bank_count = 5;
gpio_bank = gpio_bank_1610;
@@ -689,6 +879,17 @@ static int __init _omap_gpio_init(void)
gpio_bank_count = 7;
gpio_bank = gpio_bank_730;
}
#endif
#ifdef CONFIG_ARCH_OMAP24XX
if (cpu_is_omap24xx()) {
int rev;
gpio_bank_count = 4;
gpio_bank = gpio_bank_24xx;
rev = omap_readl(gpio_bank[0].base + OMAP24XX_GPIO_REVISION);
printk(KERN_INFO "OMAP24xx GPIO hardware version %d.%d\n",
(rev >> 4) & 0x0f, rev & 0x0f);
}
#endif
for (i = 0; i < gpio_bank_count; i++) {
int j, gpio_count = 16;
@@ -710,6 +911,7 @@ static int __init _omap_gpio_init(void)
if (bank->method == METHOD_GPIO_1610) {
__raw_writew(0x0000, bank->base + OMAP1610_GPIO_IRQENABLE1);
__raw_writew(0xffff, bank->base + OMAP1610_GPIO_IRQSTATUS1);
__raw_writew(0x0014, bank->base + OMAP1610_GPIO_SYSCONFIG);
}
#endif
#ifdef CONFIG_ARCH_OMAP730
@@ -719,6 +921,14 @@ static int __init _omap_gpio_init(void)
gpio_count = 32; /* 730 has 32-bit GPIOs */
}
#endif
#ifdef CONFIG_ARCH_OMAP24XX
if (bank->method == METHOD_GPIO_24XX) {
__raw_writel(0x00000000, bank->base + OMAP24XX_GPIO_IRQENABLE1);
__raw_writel(0xffffffff, bank->base + OMAP24XX_GPIO_IRQSTATUS1);
gpio_count = 32;
}
#endif
for (j = bank->virtual_irq_start;
j < bank->virtual_irq_start + gpio_count; j++) {
@@ -735,12 +945,97 @@ static int __init _omap_gpio_init(void)
/* Enable system clock for GPIO module.
* The CAM_CLK_CTRL *is* really the right place. */
if (cpu_is_omap1610() || cpu_is_omap1710())
if (cpu_is_omap16xx())
omap_writel(omap_readl(ULPD_CAM_CLK_CTRL) | 0x04, ULPD_CAM_CLK_CTRL);
return 0;
}
#if defined (CONFIG_ARCH_OMAP16XX) || defined (CONFIG_ARCH_OMAP24XX)
static int omap_gpio_suspend(struct sys_device *dev, pm_message_t mesg)
{
int i;
if (!cpu_is_omap24xx() && !cpu_is_omap16xx())
return 0;
for (i = 0; i < gpio_bank_count; i++) {
struct gpio_bank *bank = &gpio_bank[i];
void __iomem *wake_status;
void __iomem *wake_clear;
void __iomem *wake_set;
switch (bank->method) {
case METHOD_GPIO_1610:
wake_status = bank->base + OMAP1610_GPIO_WAKEUPENABLE;
wake_clear = bank->base + OMAP1610_GPIO_CLEAR_WAKEUPENA;
wake_set = bank->base + OMAP1610_GPIO_SET_WAKEUPENA;
break;
case METHOD_GPIO_24XX:
wake_status = bank->base + OMAP24XX_GPIO_SETWKUENA;
wake_clear = bank->base + OMAP24XX_GPIO_CLEARWKUENA;
wake_set = bank->base + OMAP24XX_GPIO_SETWKUENA;
break;
default:
continue;
}
spin_lock(&bank->lock);
bank->saved_wakeup = __raw_readl(wake_status);
__raw_writel(0xffffffff, wake_clear);
__raw_writel(bank->suspend_wakeup, wake_set);
spin_unlock(&bank->lock);
}
return 0;
}
static int omap_gpio_resume(struct sys_device *dev)
{
int i;
if (!cpu_is_omap24xx() && !cpu_is_omap16xx())
return 0;
for (i = 0; i < gpio_bank_count; i++) {
struct gpio_bank *bank = &gpio_bank[i];
void __iomem *wake_clear;
void __iomem *wake_set;
switch (bank->method) {
case METHOD_GPIO_1610:
wake_clear = bank->base + OMAP1610_GPIO_CLEAR_WAKEUPENA;
wake_set = bank->base + OMAP1610_GPIO_SET_WAKEUPENA;
break;
case METHOD_GPIO_24XX:
wake_clear = bank->base + OMAP1610_GPIO_CLEAR_WAKEUPENA;
wake_set = bank->base + OMAP1610_GPIO_SET_WAKEUPENA;
break;
default:
continue;
}
spin_lock(&bank->lock);
__raw_writel(0xffffffff, wake_clear);
__raw_writel(bank->saved_wakeup, wake_set);
spin_unlock(&bank->lock);
}
return 0;
}
static struct sysdev_class omap_gpio_sysclass = {
set_kset_name("gpio"),
.suspend = omap_gpio_suspend,
.resume = omap_gpio_resume,
};
static struct sys_device omap_gpio_device = {
.id = 0,
.cls = &omap_gpio_sysclass,
};
#endif
/*
* This may get called early from board specific init
*/
@@ -752,11 +1047,30 @@ int omap_gpio_init(void)
return 0;
}
static int __init omap_gpio_sysinit(void)
{
int ret = 0;
if (!initialized)
ret = _omap_gpio_init();
#if defined(CONFIG_ARCH_OMAP16XX) || defined(CONFIG_ARCH_OMAP24XX)
if (cpu_is_omap16xx() || cpu_is_omap24xx()) {
if (ret == 0) {
ret = sysdev_class_register(&omap_gpio_sysclass);
if (ret == 0)
ret = sysdev_register(&omap_gpio_device);
}
}
#endif
return ret;
}
EXPORT_SYMBOL(omap_request_gpio);
EXPORT_SYMBOL(omap_free_gpio);
EXPORT_SYMBOL(omap_set_gpio_direction);
EXPORT_SYMBOL(omap_set_gpio_dataout);
EXPORT_SYMBOL(omap_get_gpio_datain);
EXPORT_SYMBOL(omap_set_gpio_edge_ctrl);
arch_initcall(omap_gpio_init);
arch_initcall(omap_gpio_sysinit);

View File

@@ -27,6 +27,7 @@
#include <asm/arch/dma.h>
#include <asm/arch/mux.h>
#include <asm/arch/irqs.h>
#include <asm/arch/dsp_common.h>
#include <asm/arch/mcbsp.h>
#include <asm/hardware/clock.h>
@@ -187,9 +188,6 @@ 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)
{
if (cpu_is_omap1510() || cpu_is_omap16xx()) {
@@ -198,6 +196,11 @@ static void omap_mcbsp_dsp_request(void)
/* enable 12MHz clock to mcbsp 1 & 3 */
clk_use(mcbsp_dspxor_ck);
/*
* DSP external peripheral reset
* FIXME: This should be moved to dsp code
*/
__raw_writew(__raw_readw(DSP_RSTCT2) | 1 | 1 << 1,
DSP_RSTCT2);
}

View File

@@ -48,6 +48,9 @@ omap_cfg_reg(const reg_cfg_t reg_cfg)
pull_orig = 0, pull = 0;
unsigned int mask, warn = 0;
if (cpu_is_omap7xx())
return 0;
if (reg_cfg > ARRAY_SIZE(reg_cfg_table)) {
printk(KERN_ERR "MUX: reg_cfg %d\n", reg_cfg);
return -EINVAL;

View File

@@ -25,6 +25,7 @@
#include <linux/config.h>
#include <linux/module.h>
#include <linux/version.h>
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/kernel.h>

View File

@@ -39,24 +39,32 @@
#include <linux/sched.h>
#include <linux/proc_fs.h>
#include <linux/pm.h>
#include <linux/interrupt.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/mach/time.h>
#include <asm/mach-types.h>
#include <asm/mach/irq.h>
#include <asm/arch/omap16xx.h>
#include <asm/mach-types.h>
#include <asm/arch/irqs.h>
#include <asm/arch/tc.h>
#include <asm/arch/pm.h>
#include <asm/arch/mux.h>
#include <asm/arch/tc.h>
#include <asm/arch/tps65010.h>
#include <asm/arch/dsp_common.h>
#include "clock.h"
#include "sram.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];
static void (*omap_sram_idle)(void) = NULL;
static void (*omap_sram_suspend)(unsigned long r0, unsigned long r1) = NULL;
/*
* Let's power down on idle, but only if we are really
* idle, because once we start down the path of
@@ -65,7 +73,6 @@ static unsigned int mpui1610_sleep_save[MPUI1610_SLEEP_SAVE_SIZE];
*/
void omap_pm_idle(void)
{
int (*func_ptr)(void) = 0;
unsigned int mask32 = 0;
/*
@@ -83,6 +90,13 @@ void omap_pm_idle(void)
}
mask32 = omap_readl(ARM_SYSST);
/*
* Prevent the ULPD from entering low power state by setting
* POWER_CTRL_REG:4 = 0
*/
omap_writew(omap_readw(ULPD_POWER_CTRL) &
~ULPD_DEEP_SLEEP_TRANSITION_EN, ULPD_POWER_CTRL);
/*
* Since an interrupt may set up a timer, we don't want to
* reprogram the hardware timer with interrupts enabled.
@@ -92,18 +106,9 @@ void omap_pm_idle(void)
if ((mask32 & DSP_IDLE) == 0) {
__asm__ volatile ("mcr p15, 0, r0, c7, c0, 4");
} else {
} else
omap_sram_idle();
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();
}
local_fiq_enable();
local_irq_enable();
}
@@ -115,58 +120,55 @@ void omap_pm_idle(void)
*/
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);
u32 level1_wake = OMAP_IRQ_BIT(INT_IH2_IRQ);
u32 level2_wake = OMAP_IRQ_BIT(INT_UART2) | OMAP_IRQ_BIT(INT_KEYBOARD);
/*
* Turn off all interrupts except L1-2nd level cascade,
* and the L2 wakeup interrupts: keypad and UART2.
* Turn off all interrupts except GPIO bank 1, L1-2nd level cascade,
* and the L2 wakeup interrupts: keypad and UART2. Note that the
* drivers must still separately call omap_set_gpio_wakeup() to
* wake up to a GPIO interrupt.
*/
if (cpu_is_omap1510() || cpu_is_omap16xx())
level1_wake |= OMAP_IRQ_BIT(INT_GPIO_BANK1);
else if (cpu_is_omap730())
level1_wake |= OMAP_IRQ_BIT(INT_730_GPIO_BANK1);
omap_writel(~IRQ_LEVEL2, OMAP_IH1_MIR);
omap_writel(~level1_wake, OMAP_IH1_MIR);
if (cpu_is_omap1510()) {
omap_writel(~(IRQ_UART2 | IRQ_KEYBOARD), OMAP_IH2_MIR);
}
if (cpu_is_omap1510())
omap_writel(~level2_wake, OMAP_IH2_MIR);
/* INT_1610_WAKE_UP_REQ is needed for GPIO wakeup... */
if (cpu_is_omap16xx()) {
omap_writel(~(IRQ_UART2 | IRQ_KEYBOARD), OMAP_IH2_0_MIR);
omap_writel(~0x0, OMAP_IH2_1_MIR);
omap_writel(~level2_wake, OMAP_IH2_0_MIR);
omap_writel(~OMAP_IRQ_BIT(INT_1610_WAKE_UP_REQ), OMAP_IH2_1_MIR);
omap_writel(~0x0, OMAP_IH2_2_MIR);
omap_writel(~0x0, OMAP_IH2_3_MIR);
}
/* New IRQ agreement */
/* New IRQ agreement, recalculate in cascade order */
omap_writel(1, OMAP_IH2_CONTROL);
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);
printk("PM: OMAP%x is trying to enter deep sleep...\n", system_rev);
omap_serial_wake_trigger(1);
if (machine_is_omap_osk()) {
/* Stop LED1 (D9) blink */
tps65010_set_led(LED1, OFF);
}
omap_writew(0xffff, ULPD_SOFT_DISABLE_REQ_REG);
/*
* Step 1: turn off interrupts
* Step 1: turn off interrupts (FIXME: NOTE: already disabled)
*/
local_irq_disable();
@@ -207,6 +209,8 @@ void omap_pm_suspend(void)
ARM_SAVE(ARM_CKCTL);
ARM_SAVE(ARM_IDLECT1);
ARM_SAVE(ARM_IDLECT2);
if (!(cpu_is_omap1510()))
ARM_SAVE(ARM_IDLECT3);
ARM_SAVE(ARM_EWUPCT);
ARM_SAVE(ARM_RSTCT1);
ARM_SAVE(ARM_RSTCT2);
@@ -214,42 +218,12 @@ void omap_pm_suspend(void)
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 3 removed - we now allow deep sleep by default) */
/*
* 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
@@ -258,24 +232,9 @@ void omap_pm_suspend(void)
omap_pm_wakeup_setup();
/*
* Step 6a: ARM and Traffic controller shutdown
*
* Step 6 starts here with clock and watchdog disable
* Step 6: ARM and Traffic controller shutdown
*/
/* 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);
@@ -295,47 +254,24 @@ void omap_pm_suspend(void)
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);
omap_sram_suspend(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
*/
if (!(cpu_is_omap1510()))
ARM_RESTORE(ARM_IDLECT3);
ARM_RESTORE(ARM_CKCTL);
ARM_RESTORE(ARM_EWUPCT);
ARM_RESTORE(ARM_RSTCT1);
@@ -366,6 +302,8 @@ void omap_pm_suspend(void)
MPUI1610_RESTORE(OMAP_IH2_3_MIR);
}
omap_writew(0, ULPD_SOFT_DISABLE_REQ_REG);
/*
* Reenable interrupts
*/
@@ -373,6 +311,8 @@ void omap_pm_suspend(void)
local_irq_enable();
local_fiq_enable();
omap_serial_wake_trigger(0);
printk("PM: OMAP%x is re-starting from deep sleep...\n", system_rev);
if (machine_is_omap_osk()) {
@@ -401,6 +341,8 @@ static int omap_pm_read_proc(
ARM_SAVE(ARM_CKCTL);
ARM_SAVE(ARM_IDLECT1);
ARM_SAVE(ARM_IDLECT2);
if (!(cpu_is_omap1510()))
ARM_SAVE(ARM_IDLECT3);
ARM_SAVE(ARM_EWUPCT);
ARM_SAVE(ARM_RSTCT1);
ARM_SAVE(ARM_RSTCT2);
@@ -436,6 +378,7 @@ static int omap_pm_read_proc(
"ARM_CKCTL_REG: 0x%-8x \n"
"ARM_IDLECT1_REG: 0x%-8x \n"
"ARM_IDLECT2_REG: 0x%-8x \n"
"ARM_IDLECT3_REG: 0x%-8x \n"
"ARM_EWUPCT_REG: 0x%-8x \n"
"ARM_RSTCT1_REG: 0x%-8x \n"
"ARM_RSTCT2_REG: 0x%-8x \n"
@@ -449,6 +392,7 @@ static int omap_pm_read_proc(
ARM_SHOW(ARM_CKCTL),
ARM_SHOW(ARM_IDLECT1),
ARM_SHOW(ARM_IDLECT2),
ARM_SHOW(ARM_IDLECT3),
ARM_SHOW(ARM_EWUPCT),
ARM_SHOW(ARM_RSTCT1),
ARM_SHOW(ARM_RSTCT2),
@@ -507,7 +451,7 @@ static void omap_pm_init_proc(void)
entry = create_proc_read_entry("driver/omap_pm",
S_IWUSR | S_IRUGO, NULL,
omap_pm_read_proc, 0);
omap_pm_read_proc, NULL);
}
#endif /* DEBUG && CONFIG_PROC_FS */
@@ -580,7 +524,21 @@ static int omap_pm_finish(suspend_state_t state)
}
struct pm_ops omap_pm_ops ={
static irqreturn_t omap_wakeup_interrupt(int irq, void * dev,
struct pt_regs * regs)
{
return IRQ_HANDLED;
}
static struct irqaction omap_wakeup_irq = {
.name = "peripheral wakeup",
.flags = SA_INTERRUPT,
.handler = omap_wakeup_interrupt
};
static struct pm_ops omap_pm_ops ={
.pm_disk_mode = 0,
.prepare = omap_pm_prepare,
.enter = omap_pm_enter,
@@ -590,42 +548,61 @@ struct pm_ops omap_pm_ops ={
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);
omap_sram_idle = omap_sram_push(omap1510_idle_loop_suspend,
omap1510_idle_loop_suspend_sz);
omap_sram_suspend = omap_sram_push(omap1510_cpu_suspend,
omap1510_cpu_suspend_sz);
} else if (cpu_is_omap16xx()) {
omap_sram_idle = omap_sram_push(omap1610_idle_loop_suspend,
omap1610_idle_loop_suspend_sz);
omap_sram_suspend = omap_sram_push(omap1610_cpu_suspend,
omap1610_cpu_suspend_sz);
}
if (omap_sram_idle == NULL || omap_sram_suspend == NULL) {
printk(KERN_ERR "PM not initialized: Missing SRAM support\n");
return -ENODEV;
}
pm_idle = omap_pm_idle;
setup_irq(INT_1610_WAKE_UP_REQ, &omap_wakeup_irq);
#if 0
/* --- BEGIN BOARD-DEPENDENT CODE --- */
/* Sleepx mask direction */
omap_writew((omap_readw(0xfffb5008) & ~2), 0xfffb5008);
/* Unmask sleepx signal */
omap_writew((omap_readw(0xfffb5004) & ~2), 0xfffb5004);
/* --- END BOARD-DEPENDENT CODE --- */
#endif
/* Program new power ramp-up time
* (0 for most boards since we don't lower voltage when in deep sleep)
*/
omap_writew(ULPD_SETUP_ANALOG_CELL_3_VAL, ULPD_SETUP_ANALOG_CELL_3);
/* Setup ULPD POWER_CTRL_REG - enter deep sleep whenever possible */
omap_writew(ULPD_POWER_CTRL_REG_VAL, ULPD_POWER_CTRL);
/* Configure IDLECT3 */
if (cpu_is_omap16xx())
omap_writel(OMAP1610_IDLECT3_VAL, OMAP1610_IDLECT3);
pm_set_ops(&omap_pm_ops);
#if defined(DEBUG) && defined(CONFIG_PROC_FS)
omap_pm_init_proc();
#endif
/* configure LOW_PWR pin */
omap_cfg_reg(T20_1610_LOW_PWR);
return 0;
}
__initcall(omap_pm_init);

View File

@@ -66,7 +66,7 @@ ENTRY(omap1510_idle_loop_suspend)
@ 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
orr r5, r5, #OMAP1510_IDLE_CLOCK_DOMAINS & 0xff00
strh r5, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
@ request ARM idle
@@ -76,7 +76,7 @@ ENTRY(omap1510_idle_loop_suspend)
strh r3, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
mov r5, #IDLE_WAIT_CYCLES & 0xff
orr r5, r5, #IDLE_WAIT_CYCLES & 0xff00
orr r5, r5, #IDLE_WAIT_CYCLES & 0xff00
l_1510: subs r5, r5, #1
bne l_1510
/*
@@ -96,7 +96,7 @@ l_1510: subs r5, r5, #1
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
ldmfd sp!, {r0 - r12, pc} @ restore regs and return
ENTRY(omap1510_idle_loop_suspend_sz)
.word . - omap1510_idle_loop_suspend
@@ -115,8 +115,8 @@ ENTRY(omap1610_idle_loop_suspend)
@ 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
mov r5, #OMAP1610_IDLECT2_SLEEP_VAL & 0xff
orr r5, r5, #OMAP1610_IDLECT2_SLEEP_VAL & 0xff00
strh r5, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
@ request ARM idle
@@ -126,7 +126,7 @@ ENTRY(omap1610_idle_loop_suspend)
strh r3, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
mov r5, #IDLE_WAIT_CYCLES & 0xff
orr r5, r5, #IDLE_WAIT_CYCLES & 0xff00
orr r5, r5, #IDLE_WAIT_CYCLES & 0xff00
l_1610: subs r5, r5, #1
bne l_1610
/*
@@ -146,7 +146,7 @@ l_1610: subs r5, r5, #1
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
ldmfd sp!, {r0 - r12, pc} @ restore regs and return
ENTRY(omap1610_idle_loop_suspend_sz)
.word . - omap1610_idle_loop_suspend
@@ -208,7 +208,7 @@ ENTRY(omap1510_cpu_suspend)
@ turn off clock domains
mov r5, #OMAP1510_IDLE_CLOCK_DOMAINS & 0xff
orr r5,r5, #OMAP1510_IDLE_CLOCK_DOMAINS & 0xff00
orr r5, r5, #OMAP1510_IDLE_CLOCK_DOMAINS & 0xff00
strh r5, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
@ request ARM idle
@@ -217,7 +217,7 @@ ENTRY(omap1510_cpu_suspend)
strh r3, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
mov r5, #IDLE_WAIT_CYCLES & 0xff
orr r5, r5, #IDLE_WAIT_CYCLES & 0xff00
orr r5, r5, #IDLE_WAIT_CYCLES & 0xff00
l_1510_2:
subs r5, r5, #1
bne l_1510_2
@@ -237,7 +237,7 @@ l_1510_2:
strh r0, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
@ restore regs and return
ldmfd sp!, {r0 - r12, pc}
ldmfd sp!, {r0 - r12, pc}
ENTRY(omap1510_cpu_suspend_sz)
.word . - omap1510_cpu_suspend
@@ -249,21 +249,26 @@ ENTRY(omap1610_cpu_suspend)
@ save registers on stack
stmfd sp!, {r0 - r12, lr}
@ Drain write cache
mov r4, #0
mcr p15, 0, r0, c7, c10, 4
nop
@ 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
mov r6, #TCMIF_ASM_BASE & 0xff000000
orr r6, r6, #TCMIF_ASM_BASE & 0x00ff0000
orr r6, r6, #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]
ldr r7, [r6, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff]
orr r9, r7, #SELF_REFRESH_MODE & 0xff000000
orr r9, r9, #SELF_REFRESH_MODE & 0x000000ff
str r9, [r6, #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]
ldr r8, [r6, #EMIFS_CONFIG_ASM_OFFSET & 0xff]
orr r9, r8, #IDLE_EMIFS_REQUEST & 0xff
str r9, [r6, #EMIFS_CONFIG_ASM_OFFSET & 0xff]
@ load base address of ARM_IDLECT1 and ARM_IDLECT2
mov r4, #CLKGEN_REG_ASM_BASE & 0xff000000
@@ -271,26 +276,22 @@ ENTRY(omap1610_cpu_suspend)
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
@ do not disable PERCK (0x04)
mov r5, #OMAP1610_IDLECT2_SLEEP_VAL & 0xff
orr r5, r5, #OMAP1610_IDLECT2_SLEEP_VAL & 0xff00
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
mov r3, #OMAP1610_IDLECT1_SLEEP_VAL & 0xff
orr r3, r3, #OMAP1610_IDLECT1_SLEEP_VAL & 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
@ disable instruction cache
mrc p15, 0, r9, c1, c0, 0
bic r2, r9, #0x1000
mcr p15, 0, r2, c1, c0, 0
nop
/*
* Let's wait for the next wake up event to wake us up. r0 can't be
* used here because r0 holds ARM_IDLECT1
@@ -301,13 +302,21 @@ l_1610_2:
* 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.
* stack.
*/
@ re-enable Icache
mcr p15, 0, r9, c1, c0, 0
@ reset the ARM_IDLECT1 and ARM_IDLECT2.
strh r1, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
strh r0, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
@ Restore EMIFF controls
str r7, [r6, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff]
str r8, [r6, #EMIFS_CONFIG_ASM_OFFSET & 0xff]
@ restore regs and return
ldmfd sp!, {r0 - r12, pc}
ldmfd sp!, {r0 - r12, pc}
ENTRY(omap1610_cpu_suspend_sz)
.word . - omap1610_cpu_suspend

View File

@@ -0,0 +1,58 @@
/*
* linux/arch/arm/plat-omap/sram.S
*
* Functions that need to be run in internal SRAM
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/config.h>
#include <linux/linkage.h>
#include <asm/assembler.h>
#include <asm/arch/io.h>
#include <asm/arch/hardware.h>
.text
/*
* Reprograms ULPD and CKCTL.
*/
ENTRY(sram_reprogram_clock)
stmfd sp!, {r0 - r12, lr} @ save registers on stack
mov r2, #IO_ADDRESS(DPLL_CTL) & 0xff000000
orr r2, r2, #IO_ADDRESS(DPLL_CTL) & 0x00ff0000
orr r2, r2, #IO_ADDRESS(DPLL_CTL) & 0x0000ff00
mov r3, #IO_ADDRESS(ARM_CKCTL) & 0xff000000
orr r3, r3, #IO_ADDRESS(ARM_CKCTL) & 0x00ff0000
orr r3, r3, #IO_ADDRESS(ARM_CKCTL) & 0x0000ff00
tst r0, #1 << 4 @ want lock mode?
beq newck @ nope
bic r0, r0, #1 << 4 @ else clear lock bit
strh r0, [r2] @ set dpll into bypass mode
orr r0, r0, #1 << 4 @ set lock bit again
newck:
strh r1, [r3] @ write new ckctl value
strh r0, [r2] @ write new dpll value
mov r4, #0x0700 @ let the clocks settle
orr r4, r4, #0x00ff
delay: sub r4, r4, #1
cmp r4, #0
bne delay
lock: ldrh r4, [r2], #0 @ read back dpll value
tst r0, #1 << 4 @ want lock mode?
beq out @ nope
tst r4, #1 << 0 @ dpll rate locked?
beq lock @ try again
out:
ldmfd sp!, {r0 - r12, pc} @ restore regs and return
ENTRY(sram_reprogram_clock_sz)
.word . - sram_reprogram_clock

116
arch/arm/plat-omap/sram.c Normal file
View File

@@ -0,0 +1,116 @@
/*
* linux/arch/arm/plat-omap/sram.c
*
* OMAP SRAM detection and management
*
* Copyright (C) 2005 Nokia Corporation
* Written 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 version 2 as
* published by the Free Software Foundation.
*/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <asm/mach/map.h>
#include <asm/io.h>
#include <asm/cacheflush.h>
#include "sram.h"
#define OMAP1_SRAM_BASE 0xd0000000
#define OMAP1_SRAM_START 0x20000000
#define SRAM_BOOTLOADER_SZ 0x80
static unsigned long omap_sram_base;
static unsigned long omap_sram_size;
static unsigned long omap_sram_ceil;
/*
* The amount of SRAM depends on the core type:
* 730 = 200K, 1510 = 512K, 5912 = 256K, 1610 = 16K, 1710 = 16K
* Note that we cannot try to test for SRAM here because writes
* to secure SRAM will hang the system. Also the SRAM is not
* yet mapped at this point.
*/
void __init omap_detect_sram(void)
{
omap_sram_base = OMAP1_SRAM_BASE;
if (cpu_is_omap730())
omap_sram_size = 0x32000;
else if (cpu_is_omap1510())
omap_sram_size = 0x80000;
else if (cpu_is_omap1610() || cpu_is_omap1621() || cpu_is_omap1710())
omap_sram_size = 0x4000;
else if (cpu_is_omap1611())
omap_sram_size = 0x3e800;
else {
printk(KERN_ERR "Could not detect SRAM size\n");
omap_sram_size = 0x4000;
}
printk(KERN_INFO "SRAM size: 0x%lx\n", omap_sram_size);
omap_sram_ceil = omap_sram_base + omap_sram_size;
}
static struct map_desc omap_sram_io_desc[] __initdata = {
{ OMAP1_SRAM_BASE, OMAP1_SRAM_START, 0, MT_DEVICE }
};
/*
* In order to use last 2kB of SRAM on 1611b, we must round the size
* up to multiple of PAGE_SIZE. We cannot use ioremap for SRAM, as
* clock init needs SRAM early.
*/
void __init omap_map_sram(void)
{
if (omap_sram_size == 0)
return;
omap_sram_io_desc[0].length = (omap_sram_size + PAGE_SIZE-1)/PAGE_SIZE;
omap_sram_io_desc[0].length *= PAGE_SIZE;
iotable_init(omap_sram_io_desc, ARRAY_SIZE(omap_sram_io_desc));
/*
* Looks like we need to preserve some bootloader code at the
* beginning of SRAM for jumping to flash for reboot to work...
*/
memset((void *)omap_sram_base + SRAM_BOOTLOADER_SZ, 0,
omap_sram_size - SRAM_BOOTLOADER_SZ);
}
static void (*_omap_sram_reprogram_clock)(u32 dpllctl, u32 ckctl) = NULL;
void omap_sram_reprogram_clock(u32 dpllctl, u32 ckctl)
{
if (_omap_sram_reprogram_clock == NULL)
panic("Cannot use SRAM");
return _omap_sram_reprogram_clock(dpllctl, ckctl);
}
void * omap_sram_push(void * start, unsigned long size)
{
if (size > (omap_sram_ceil - (omap_sram_base + SRAM_BOOTLOADER_SZ))) {
printk(KERN_ERR "Not enough space in SRAM\n");
return NULL;
}
omap_sram_ceil -= size;
omap_sram_ceil &= ~0x3;
memcpy((void *)omap_sram_ceil, start, size);
return (void *)omap_sram_ceil;
}
void __init omap_sram_init(void)
{
omap_detect_sram();
omap_map_sram();
_omap_sram_reprogram_clock = omap_sram_push(sram_reprogram_clock,
sram_reprogram_clock_sz);
}

21
arch/arm/plat-omap/sram.h Normal file
View File

@@ -0,0 +1,21 @@
/*
* linux/arch/arm/plat-omap/sram.h
*
* Interface for functions that need to be run in internal SRAM
*
* 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_SRAM_H
#define __ARCH_ARM_OMAP_SRAM_H
extern void * omap_sram_push(void * start, unsigned long size);
extern void omap_sram_reprogram_clock(u32 dpllctl, u32 ckctl);
/* Do not use these */
extern void sram_reprogram_clock(u32 ckctl, u32 dpllctl);
extern unsigned long sram_reprogram_clock_sz;
#endif

View File

@@ -41,6 +41,7 @@
/* These routines should handle the standard chip-specific modes
* for usb0/1/2 ports, covering basic mux and transceiver setup.
* Call omap_usb_init() once, from INIT_MACHINE().
*
* Some board-*.c files will need to set up additional mux options,
* like for suspend handling, vbus sensing, GPIOs, and the D+ pullup.