add support for target 3c24xx (more known as Openmoko GTA02 "Freerunner") and merge it with the openmoko-target and the work Michael Buesch <mb> did

SVN-Revision: 13609
This commit is contained in:
Mirko Vogt 2008-12-12 00:02:36 +00:00
parent 4571721ec2
commit b9dfb81f2a
268 changed files with 151304 additions and 133872 deletions

View file

@ -1,6 +0,0 @@
::sysinit:/etc/init.d/rcS S boot
::shutdown:/etc/init.d/rcS K stop
tts/0::askfirst:/bin/ash --login
ttyS0::askfirst:/bin/ash --login
ttyS2::respawn:/sbin/getty -L ttyS2 115200 vt100

View file

@ -1,3 +0,0 @@
src snapshots http://vlink.guthrie.homedns.org/vlink3
dest root /
dest ram /tmp

File diff suppressed because it is too large Load diff

View file

@ -1,37 +0,0 @@
#
# Copyright (C) 2008 OpenWrt.org
#
# This is free software, licensed under the GNU General Public License v2.
# See /LICENSE for more information.
#
JFFS2_BLOCKSIZE := 128k
include $(TOPDIR)/rules.mk
include $(INCLUDE_DIR)/image.mk
define Image/mkfs/jffs2/sub
$(STAGING_DIR_HOST)/bin/mkfs.jffs2 --pad --little-endian --pagesize=0x800 --no-cleanmarkers -e $(patsubst %k,%KiB,$(1)) -o $(KDIR)/root.jffs2-$(1) -d $(TARGET_DIR)
$(call add_jffs2_mark,$(KDIR)/root.jffs2-$(1))
$(call Image/Build,jffs2-$(1))
endef
define Build/Clean
endef
define Build/Compile
endef
define Image/Prepare
cp $(LINUX_DIR)/arch/arm/boot/uImage $(KDIR)/uImage
endef
define Image/BuildKernel
cp $(KDIR)/uImage $(BIN_DIR)/openwrt-$(BOARD)-uImage
endef
define Image/Build
cp $(KDIR)/root.jffs2-128k $(BIN_DIR)/openwrt-$(BOARD)-rootfs
endef
$(eval $(call BuildImage))

File diff suppressed because it is too large Load diff

View file

@ -1,5 +1,5 @@
#
# Copyright (C) 2008 OpenWrt.org
# Copyright (C) 2006 OpenWrt.org
#
# This is free software, licensed under the GNU General Public License v2.
# See /LICENSE for more information.
@ -7,18 +7,19 @@
include $(TOPDIR)/rules.mk
ARCH:=arm
BOARD:=openmoko
BOARDNAME:=Openmoko
FEATURES:=usb
BOARD:=s3c24xx
BOARDNAME:=s3c24xx
FEATURES:=jffs2
LINUX_VERSION:=2.6.24.7
LINUX_VERSION:=2.6.26
include $(INCLUDE_DIR)/target.mk
KERNELNAME:="uImage"
DEVICE_TYPE=phone
define Target/Description
Build fimware images for the Openmoko Smartphone.
OpenMoko gta02
endef
include $(INCLUDE_DIR)/target.mk
DEFAULT_PACKAGES += xglamo enlightenment
$(eval $(call BuildTarget))

View file

@ -0,0 +1,14 @@
# Copyright (C) 2006 OpenWrt.org
config interface loopback
option ifname lo
option proto static
option ipaddr 127.0.0.1
option netmask 255.0.0.0
config interface lan
option ifname usb0
option type bridge
option proto static
option ipaddr 192.168.1.1
option netmask 255.255.255.0

View file

@ -0,0 +1,5 @@
::sysinit:/etc/init.d/rcS S boot
::shutdown:/etc/init.d/rcS K stop
s3c2410_serial0::askfirst:/bin/ash --login
s3c2410_serial2::askfirst:/bin/ash --login
tty1::askfirst:/bin/ash --login

View file

@ -0,0 +1,78 @@
#!/bin/sh
# Copyright (C) 2006 OpenWrt.org
export PATH=/bin:/sbin:/usr/bin:/usr/sbin
. /etc/diag.sh
rm -rf /dev/console
mknod /dev/console c 204 64
exec </dev/console > /dev/console 2>&0
failsafe_ip() {
ifconfig $ifname 192.168.1.1 netmask 255.255.255.0 broadcast 192.168.1.255 up
}
failsafe() {
[ -n "$ifname" ] && grep "$ifname" /proc/net/dev >/dev/null && {
failsafe_ip
netmsg 192.168.1.255 "Entering Failsafe!"
telnetd -l /bin/login <> /dev/null 2>&1
}
lock /tmp/.failsafe
ash --login
}
mount none /proc -t proc
mount none /sys -t sysfs
size=$(awk '/MemTotal:/ {l=5242880;mt=($2*1024);print((s=mt/2)<l)?mt-l:s}' /proc/meminfo)
mount none /tmp -t tmpfs -o size=$size,nosuid,nodev,mode=1777
if grep devfs /proc/filesystems > /dev/null; then
mount none /dev -t devfs
M0=/dev/pty/m0
M1=/dev/pty/m1
HOTPLUG=/sbin/hotplug-call
else
mount -t tmpfs tmpfs /dev -o size=512K
# mknod /dev/console c 5 1
mkdir /dev/shm
/sbin/hotplug2 --coldplug --set-rules-file /etc/hotplug2-init.rules
/sbin/hotplug2 --no-coldplug --persistent --set-rules-file /etc/hotplug2-init.rules &
M0=/dev/ptmx
M1=/dev/ptmx
HOTPLUG=
fi
mkdir -p /dev/pts /dev/shm
mount none /dev/pts -t devpts
# the shell really doesn't like having stdin/out closed
# that's why we use /dev/pty/m0 and m1 as replacement
# for /dev/console if there's no serial console available
dd if=/dev/console of=/dev/null bs=1 count=0 >/dev/null 2>/dev/null && {
M0=/dev/console
M1=/dev/console
}
exec <$M0 >$M1 2>&0
echo "- preinit -"
trap 'FAILSAFE=true' USR1
[ -e /etc/preinit.arch ] && . /etc/preinit.arch
set_state preinit
echo "$HOTPLUG" > /proc/sys/kernel/hotplug
eval ${FAILSAFE:+failsafe}
lock -w /tmp/.failsafe
#mount_root
[ -f /sysupgrade.tgz ] && {
echo "- config restore -"
cd /
mv sysupgrade.tgz /tmp
tar xzf /tmp/sysupgrade.tgz
rm -f /tmp/sysupgrade.tgz
sync
}
echo "- init -"
killall hotplug2
exec /sbin/init

View file

@ -0,0 +1,684 @@
CONFIG_AEABI=y
CONFIG_ALIGNMENT_TRAP=y
CONFIG_APM_EMULATION=y
CONFIG_APM_POWER=y
# CONFIG_ARCH_AAEC2000 is not set
# CONFIG_ARCH_AT91 is not set
# CONFIG_ARCH_BAST is not set
# CONFIG_ARCH_CLPS711X is not set
# CONFIG_ARCH_CLPS7500 is not set
# CONFIG_ARCH_CO285 is not set
# CONFIG_ARCH_DAVINCI is not set
# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
# CONFIG_ARCH_EBSA110 is not set
# CONFIG_ARCH_EP93XX is not set
# CONFIG_ARCH_FOOTBRIDGE is not set
# CONFIG_ARCH_H1940 is not set
# CONFIG_ARCH_H720X is not set
# CONFIG_ARCH_HAS_ILOG2_U32 is not set
# CONFIG_ARCH_HAS_ILOG2_U64 is not set
# CONFIG_ARCH_IMX is not set
# CONFIG_ARCH_INTEGRATOR is not set
# CONFIG_ARCH_IOP13XX is not set
# CONFIG_ARCH_IOP32X is not set
# CONFIG_ARCH_IOP33X is not set
# CONFIG_ARCH_IXP2000 is not set
# CONFIG_ARCH_IXP23XX is not set
# CONFIG_ARCH_IXP4XX is not set
# CONFIG_ARCH_KS8695 is not set
# CONFIG_ARCH_L7200 is not set
# CONFIG_ARCH_LH7A40X is not set
# CONFIG_ARCH_MSM7X00A is not set
# CONFIG_ARCH_MXC is not set
# CONFIG_ARCH_NETX is not set
# CONFIG_ARCH_NS9XXX is not set
# CONFIG_ARCH_OMAP is not set
# CONFIG_ARCH_ORION5X is not set
# CONFIG_ARCH_PNX4008 is not set
# CONFIG_ARCH_PXA is not set
# CONFIG_ARCH_REALVIEW is not set
# CONFIG_ARCH_RPC is not set
CONFIG_ARCH_S3C2410=y
CONFIG_ARCH_S3C2440=y
# CONFIG_ARCH_SA1100 is not set
# CONFIG_ARCH_SHARK is not set
# CONFIG_ARCH_SMDK2410 is not set
CONFIG_ARCH_SUPPORTS_AOUT=y
# CONFIG_ARCH_SUPPORTS_MSI is not set
CONFIG_ARCH_SUSPEND_POSSIBLE=y
# CONFIG_ARCH_VERSATILE is not set
CONFIG_ARM=y
CONFIG_ARM_THUMB=y
# CONFIG_ARPD is not set
CONFIG_ATAGS_PROC=y
# CONFIG_ATM is not set
CONFIG_BACKLIGHT_CLASS_DEVICE=y
# CONFIG_BACKLIGHT_CORGI is not set
CONFIG_BACKLIGHT_GTA01=y
CONFIG_BACKLIGHT_LCD_SUPPORT=y
CONFIG_BASE_SMALL=0
CONFIG_BATTERY_BQ27000_HDQ=y
# CONFIG_BATTERY_DS2760 is not set
# CONFIG_BINFMT_AOUT is not set
CONFIG_BITREVERSE=y
# CONFIG_BLK_DEV_INITRD is not set
# CONFIG_BLK_DEV_LOOP is not set
# CONFIG_BLK_DEV_NBD is not set
CONFIG_BLK_DEV_SD=y
CONFIG_BLK_DEV_SR=y
# CONFIG_BLK_DEV_SR_VENDOR is not set
# CONFIG_BONDING is not set
CONFIG_BOUNCE=y
# CONFIG_BRIDGE_EBT_NFLOG is not set
CONFIG_BRIDGE_NETFILTER=y
# CONFIG_BSD_DISKLABEL is not set
# CONFIG_BSD_PROCESS_ACCT is not set
CONFIG_BT=y
CONFIG_BT_BNEP=y
# CONFIG_BT_HCIBCM203X is not set
# CONFIG_BT_HCIBFUSB is not set
# CONFIG_BT_HCIBPA10X is not set
# CONFIG_BT_HCIUART is not set
CONFIG_BT_HCIUSB=y
# CONFIG_BT_HCIVHCI is not set
CONFIG_BT_HIDP=y
CONFIG_BT_L2CAP=y
CONFIG_BT_RFCOMM=y
CONFIG_BT_SCO=y
CONFIG_CAN_PM_TRACE=y
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_CHR_DEV_SG=y
CONFIG_CLASSIC_RCU=y
CONFIG_CMDLINE="unused -- bootloader passes ATAG list"
CONFIG_COMPAT_BRK=y
# CONFIG_CONFIGFS_FS is not set
CONFIG_CPU_32=y
CONFIG_CPU_32v4T=y
CONFIG_CPU_ABRT_EV4T=y
CONFIG_CPU_ARM920T=y
CONFIG_CPU_CACHE_V4WT=y
CONFIG_CPU_CACHE_VIVT=y
CONFIG_CPU_COPY_V4WB=y
CONFIG_CPU_CP15=y
CONFIG_CPU_CP15_MMU=y
# CONFIG_CPU_DCACHE_DISABLE is not set
# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
# CONFIG_CPU_ICACHE_DISABLE is not set
CONFIG_CPU_LLSERIAL_S3C2410=y
CONFIG_CPU_LLSERIAL_S3C2440=y
CONFIG_CPU_PABRT_NOIFAR=y
CONFIG_CPU_S3C2410=y
CONFIG_CPU_S3C2410_DMA=y
CONFIG_CPU_S3C2440=y
CONFIG_CPU_S3C2442=y
CONFIG_CPU_S3C244X=y
CONFIG_CPU_TLB_V4WBI=y
# CONFIG_CRC16 is not set
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC_ITU_T is not set
CONFIG_CRYPTO_AES=y
CONFIG_CRYPTO_ALGAPI=y
# CONFIG_CRYPTO_ANUBIS is not set
CONFIG_CRYPTO_ARC4=y
CONFIG_CRYPTO_BLKCIPHER=y
CONFIG_CRYPTO_BLOWFISH=y
# CONFIG_CRYPTO_CAMELLIA is not set
# CONFIG_CRYPTO_CAST5 is not set
CONFIG_CRYPTO_CAST6=y
CONFIG_CRYPTO_CBC=y
CONFIG_CRYPTO_CRC32C=y
CONFIG_CRYPTO_DES=y
CONFIG_CRYPTO_ECB=y
CONFIG_CRYPTO_HASH=y
CONFIG_CRYPTO_HMAC=y
# CONFIG_CRYPTO_KHAZAD is not set
CONFIG_CRYPTO_MANAGER=y
# CONFIG_CRYPTO_MD4 is not set
CONFIG_CRYPTO_MD5=y
# CONFIG_CRYPTO_MICHAEL_MIC is not set
# CONFIG_CRYPTO_NULL is not set
CONFIG_CRYPTO_SERPENT=y
CONFIG_CRYPTO_SHA1=y
CONFIG_CRYPTO_SHA256=y
CONFIG_CRYPTO_SHA512=y
CONFIG_CRYPTO_TEA=y
# CONFIG_CRYPTO_TEST is not set
# CONFIG_CRYPTO_TGR192 is not set
CONFIG_CRYPTO_TWOFISH=y
CONFIG_CRYPTO_TWOFISH_COMMON=y
# CONFIG_CRYPTO_WP512 is not set
# CONFIG_CS89x0 is not set
CONFIG_DAB=y
CONFIG_DEBUG_BUGVERBOSE=y
CONFIG_DEBUG_S3C_UART=2
# CONFIG_DEBUG_USER is not set
CONFIG_DEFAULT_TCP_CONG="cubic"
CONFIG_DISPLAY_JBT6K74=y
CONFIG_DISPLAY_SUPPORT=y
# CONFIG_DM9000 is not set
CONFIG_DNOTIFY=y
CONFIG_DUMMY_CONSOLE=y
# CONFIG_EEPROM_93CX6 is not set
CONFIG_ELF_CORE=y
# CONFIG_EMBEDDED is not set
# CONFIG_ENABLE_WARN_DEPRECATED is not set
CONFIG_EXT2_FS=y
CONFIG_EXT3_FS=y
CONFIG_FAT_FS=y
CONFIG_FB=y
# CONFIG_FB_BACKLIGHT is not set
CONFIG_FB_CFB_COPYAREA=y
CONFIG_FB_CFB_FILLRECT=y
CONFIG_FB_CFB_IMAGEBLIT=y
# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
# CONFIG_FB_DDC is not set
# CONFIG_FB_FOREIGN_ENDIAN is not set
# CONFIG_FB_MACMODES is not set
# CONFIG_FB_MODE_HELPERS is not set
# CONFIG_FB_S1D13XXX is not set
CONFIG_FB_S3C2410=y
# CONFIG_FB_S3C2410_DEBUG is not set
# CONFIG_FB_SVGALIB is not set
# CONFIG_FB_SYS_COPYAREA is not set
# CONFIG_FB_SYS_FILLRECT is not set
# CONFIG_FB_SYS_FOPS is not set
# CONFIG_FB_SYS_IMAGEBLIT is not set
# CONFIG_FB_TILEBLITTING is not set
# CONFIG_FB_VIRTUAL is not set
CONFIG_FIQ=y
# CONFIG_FIRMWARE_EDID is not set
CONFIG_FONTS=y
# CONFIG_FONT_10x18 is not set
CONFIG_FONT_6x11=y
# CONFIG_FONT_7x14 is not set
# CONFIG_FONT_8x16 is not set
# CONFIG_FONT_8x8 is not set
# CONFIG_FONT_ACORN_8x8 is not set
# CONFIG_FONT_MINI_4x6 is not set
# CONFIG_FONT_PEARL_8x8 is not set
# CONFIG_FONT_SUN12x22 is not set
# CONFIG_FONT_SUN8x16 is not set
# CONFIG_FPE_FASTFPE is not set
CONFIG_FPE_NWFPE=y
# CONFIG_FPE_NWFPE_XP is not set
CONFIG_FRAMEBUFFER_CONSOLE=y
# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
CONFIG_FRAME_POINTER=y
CONFIG_FUSE_FS=y
CONFIG_FW_LOADER=m
# CONFIG_GENERIC_CLOCKEVENTS is not set
# CONFIG_GENERIC_FIND_FIRST_BIT is not set
# CONFIG_GENERIC_FIND_NEXT_BIT is not set
CONFIG_GENERIC_GPIO=y
# CONFIG_GENERIC_TIME is not set
CONFIG_GTA02_HDQ=y
# CONFIG_HAMRADIO is not set
CONFIG_HARDIRQS_SW_RESEND=y
CONFIG_HAS_DMA=y
CONFIG_HAS_IOMEM=y
# CONFIG_HAVE_DMA_ATTRS is not set
CONFIG_HAVE_IDE=y
CONFIG_HAVE_KPROBES=y
CONFIG_HAVE_KRETPROBES=y
CONFIG_HAVE_OPROFILE=y
# CONFIG_HFSPLUS_FS is not set
# CONFIG_HFS_FS is not set
CONFIG_HID=y
CONFIG_HID_SUPPORT=y
CONFIG_HWMON=y
# CONFIG_HWMON_DEBUG_CHIP is not set
CONFIG_HW_CONSOLE=y
# CONFIG_HW_RANDOM is not set
CONFIG_HZ=200
CONFIG_I2C=y
CONFIG_I2C_BOARDINFO=y
CONFIG_I2C_CHARDEV=y
CONFIG_I2C_S3C2410=y
# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
# CONFIG_IBM_NEW_EMAC_RGMII is not set
# CONFIG_IBM_NEW_EMAC_TAH is not set
# CONFIG_IBM_NEW_EMAC_ZMII is not set
# CONFIG_IDE is not set
# CONFIG_IEEE80211 is not set
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
CONFIG_INOTIFY=y
CONFIG_INOTIFY_USER=y
CONFIG_INPUT=y
CONFIG_INPUT_EVBUG=m
CONFIG_INPUT_EVDEV=y
# CONFIG_INPUT_GPIO_BUTTONS is not set
CONFIG_INPUT_KEYBOARD=y
CONFIG_INPUT_LIS302DL=y
CONFIG_INPUT_MISC=y
CONFIG_INPUT_MOUSE=y
CONFIG_INPUT_MOUSEDEV=y
# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
CONFIG_INPUT_MOUSEDEV_SCREEN_X=480
CONFIG_INPUT_MOUSEDEV_SCREEN_Y=640
CONFIG_INPUT_TOUCHSCREEN=y
CONFIG_INPUT_UINPUT=m
# CONFIG_INPUT_YEALINK is not set
CONFIG_IOSCHED_AS=m
CONFIG_IOSCHED_CFQ=m
# CONFIG_IP6_NF_QUEUE is not set
# CONFIG_IP6_NF_RAW is not set
CONFIG_IPV6_NDISC_NODETYPE=y
# CONFIG_IPV6_ROUTER_PREF is not set
CONFIG_IPV6_TUNNEL=m
# CONFIG_IP_NF_ARPTABLES is not set
CONFIG_IP_NF_FILTER=m
CONFIG_IP_NF_IPTABLES=m
CONFIG_IP_NF_MANGLE=m
# CONFIG_IP_NF_MATCH_RECENT is not set
# CONFIG_IP_NF_QUEUE is not set
# CONFIG_IP_NF_RAW is not set
CONFIG_IP_NF_TARGET_REJECT=m
CONFIG_IP_PNP=y
# CONFIG_IP_PNP_BOOTP is not set
# CONFIG_IP_PNP_DHCP is not set
# CONFIG_IP_PNP_RARP is not set
# CONFIG_IP_ROUTE_MULTIPATH is not set
# CONFIG_IP_ROUTE_VERBOSE is not set
# CONFIG_ISDN is not set
# CONFIG_ISO9660_FS is not set
# CONFIG_IWLWIFI_LEDS is not set
CONFIG_JBD=y
# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
CONFIG_KALLSYMS=y
CONFIG_KEXEC=y
# CONFIG_KEYBOARD_ATKBD is not set
CONFIG_KEYBOARD_GPIO=m
# CONFIG_KEYBOARD_LKKBD is not set
CONFIG_KEYBOARD_NEO1973=y
# CONFIG_KEYBOARD_NEWTON is not set
CONFIG_KEYBOARD_QT2410=y
CONFIG_KEYBOARD_STOWAWAY=m
# CONFIG_KEYBOARD_SUNKBD is not set
# CONFIG_KEYBOARD_XTKBD is not set
CONFIG_KMOD=y
# CONFIG_KPROBES is not set
CONFIG_LCD_CLASS_DEVICE=y
CONFIG_LCD_LTV350QV=y
# CONFIG_LEDS_ALIX is not set
CONFIG_LEDS_GPIO=y
CONFIG_LEDS_NEO1973_GTA02=y
CONFIG_LEDS_NEO1973_VIBRATOR=y
CONFIG_LEDS_S3C24XX=m
# CONFIG_LEDS_TRIGGER_DEFAULT_ON is not set
# CONFIG_LEDS_TRIGGER_HEARTBEAT is not set
CONFIG_LIBCRC32C=y
# CONFIG_LLC2 is not set
CONFIG_LOCALVERSION="-mokodev"
CONFIG_LOCK_KERNEL=y
# CONFIG_LOGO is not set
CONFIG_LOG_BUF_SHIFT=17
# CONFIG_MACH_AML_M5900 is not set
# CONFIG_MACH_ANUBIS is not set
# CONFIG_MACH_N30 is not set
CONFIG_MACH_NEO1973=y
CONFIG_MACH_NEO1973_GTA01=y
CONFIG_MACH_NEO1973_GTA02=y
# CONFIG_MACH_NEXCODER_2440 is not set
# CONFIG_MACH_OSIRIS is not set
# CONFIG_MACH_OTOM is not set
CONFIG_MACH_QT2410=y
# CONFIG_MACH_RX3715 is not set
CONFIG_MACH_SMDK=y
# CONFIG_MACH_SMDK2412 is not set
# CONFIG_MACH_SMDK2413 is not set
# CONFIG_MACH_SMDK2443 is not set
# CONFIG_MACH_TCT_HAMMER is not set
# CONFIG_MACH_VR1000 is not set
# CONFIG_MACH_VSTMS is not set
# CONFIG_MAC_PARTITION is not set
CONFIG_MARKERS=y
CONFIG_MFD_GLAMO=y
CONFIG_MFD_GLAMO_FB=y
CONFIG_MFD_GLAMO_MCI=y
CONFIG_MFD_GLAMO_SPI_FB=y
CONFIG_MFD_GLAMO_SPI_GPIO=y
# CONFIG_MINIX_FS is not set
# CONFIG_MINI_FO is not set
CONFIG_MMC=y
CONFIG_MMC_BLOCK=y
# CONFIG_MMC_BLOCK_BOUNCE is not set
# CONFIG_MMC_DEBUG is not set
CONFIG_MMC_S3C=y
# CONFIG_MMC_SPI is not set
CONFIG_MMC_UNSAFE_RESUME=y
CONFIG_MODULE_FORCE_UNLOAD=y
# CONFIG_MOUSE_GPIO is not set
# CONFIG_MOUSE_PS2 is not set
# CONFIG_MOUSE_SERIAL is not set
# CONFIG_MOUSE_VSXXXAA is not set
CONFIG_MSDOS_FS=y
CONFIG_MTD=y
CONFIG_MTD_ABSENT=y
# CONFIG_MTD_AFS_PARTS is not set
# CONFIG_MTD_ALAUDA is not set
# CONFIG_MTD_ARM_INTEGRATOR is not set
CONFIG_MTD_BLKDEVS=y
CONFIG_MTD_BLOCK=y
# CONFIG_MTD_BLOCK2MTD is not set
CONFIG_MTD_CFI=y
# CONFIG_MTD_CFI_ADV_OPTIONS is not set
# CONFIG_MTD_CFI_AMDSTD 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_STAA is not set
CONFIG_MTD_CFI_UTIL=y
CONFIG_MTD_CHAR=y
CONFIG_MTD_CMDLINE_PARTS=y
# CONFIG_MTD_COMPLEX_MAPPINGS is not set
CONFIG_MTD_CONCAT=y
# CONFIG_MTD_DEBUG is not set
# CONFIG_MTD_DOC2000 is not set
# CONFIG_MTD_DOC2001 is not set
# CONFIG_MTD_DOC2001PLUS is not set
CONFIG_MTD_GEN_PROBE=y
# CONFIG_MTD_JEDECPROBE is not set
CONFIG_MTD_MAP_BANK_WIDTH_1=y
# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
CONFIG_MTD_MAP_BANK_WIDTH_2=y
# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
CONFIG_MTD_MAP_BANK_WIDTH_4=y
# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
# CONFIG_MTD_MTDRAM is not set
CONFIG_MTD_NAND=y
# CONFIG_MTD_NAND_DISKONCHIP is not set
# CONFIG_MTD_NAND_ECC_SMC is not set
CONFIG_MTD_NAND_IDS=y
# CONFIG_MTD_NAND_MUSEUM_IDS is not set
# CONFIG_MTD_NAND_NANDSIM is not set
# CONFIG_MTD_NAND_PLATFORM is not set
CONFIG_MTD_NAND_S3C2410=y
# CONFIG_MTD_NAND_S3C2410_CLKSTOP is not set
# CONFIG_MTD_NAND_S3C2410_DEBUG is not set
CONFIG_MTD_NAND_S3C2410_HWECC=y
CONFIG_MTD_NAND_VERIFY_WRITE=y
# CONFIG_MTD_ONENAND is not set
CONFIG_MTD_PARTITIONS=y
# CONFIG_MTD_PHRAM is not set
CONFIG_MTD_PHYSMAP=y
CONFIG_MTD_PHYSMAP_BANKWIDTH=2
CONFIG_MTD_PHYSMAP_LEN=0
CONFIG_MTD_PHYSMAP_START=0x0
# CONFIG_MTD_PLATRAM is not set
# CONFIG_MTD_RAM is not set
# CONFIG_MTD_REDBOOT_PARTS is not set
CONFIG_MTD_ROM=y
# CONFIG_MTD_SLRAM is not set
CONFIG_NAMESPACES=y
# CONFIG_NEO1973_GTA02_2440 is not set
# CONFIG_NETDEVICES_MULTIQUEUE is not set
# CONFIG_NETDEV_1000 is not set
CONFIG_NETFILTER_NETLINK=m
CONFIG_NETFILTER_NETLINK_LOG=m
CONFIG_NETFILTER_NETLINK_QUEUE=m
CONFIG_NETFILTER_XTABLES=m
# CONFIG_NETFILTER_XT_MATCH_COMMENT is not set
# CONFIG_NETFILTER_XT_MATCH_IPRANGE is not set
CONFIG_NETFILTER_XT_MATCH_LIMIT=m
CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
# CONFIG_NETFILTER_XT_MATCH_OWNER is not set
CONFIG_NETFILTER_XT_MATCH_QUOTA=m
# CONFIG_NETFILTER_XT_MATCH_RATEEST is not set
CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
# CONFIG_NETFILTER_XT_MATCH_TIME is not set
# CONFIG_NETFILTER_XT_MATCH_U32 is not set
# CONFIG_NETFILTER_XT_TARGET_RATEEST is not set
CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
# CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP is not set
# CONFIG_NETWORK_FILESYSTEMS is not set
# CONFIG_NET_CLS_ACT is not set
# CONFIG_NET_CLS_FLOW is not set
# CONFIG_NET_CLS_IND is not set
# CONFIG_NET_EMATCH is not set
# CONFIG_NET_IPGRE_BROADCAST is not set
CONFIG_NET_KEY_MIGRATE=y
# CONFIG_NET_PKTGEN is not set
# CONFIG_NF_CONNTRACK is not set
CONFIG_NLS=y
# CONFIG_NLS_CODEPAGE_1250 is not set
CONFIG_NLS_CODEPAGE_437=y
CONFIG_NLS_CODEPAGE_936=m
CONFIG_NLS_CODEPAGE_950=m
CONFIG_NLS_ISO8859_1=y
# CONFIG_NLS_ISO8859_15 is not set
# CONFIG_NLS_KOI8_R is not set
CONFIG_NO_IDLE_HZ=y
CONFIG_NO_IOPORT=y
CONFIG_NR_TTY_DEVICES=4
# CONFIG_NVRAM is not set
CONFIG_OABI_COMPAT=y
# CONFIG_OCF_OCF is not set
# CONFIG_OUTER_CACHE is not set
CONFIG_PAGEFLAGS_EXTENDED=y
# CONFIG_PCI_SYSCALL is not set
CONFIG_PDA_POWER=y
CONFIG_PLAT_S3C=y
CONFIG_PLAT_S3C24XX=y
CONFIG_PM=y
CONFIG_PM_DEBUG=y
CONFIG_PM_SLEEP=y
CONFIG_PM_VERBOSE=y
CONFIG_PNP=y
# CONFIG_PNPACPI is not set
CONFIG_PNP_DEBUG=y
CONFIG_POWER_SUPPLY=y
CONFIG_POWER_SUPPLY_DEBUG=y
# CONFIG_PPP is not set
CONFIG_PREEMPT=y
CONFIG_PROC_PAGE_MONITOR=y
# CONFIG_RFKILL is not set
CONFIG_RTC_CLASS=y
CONFIG_RTC_DEBUG=y
# CONFIG_RTC_DRV_CMOS is not set
# CONFIG_RTC_DRV_DS1307 is not set
# CONFIG_RTC_DRV_DS1374 is not set
# CONFIG_RTC_DRV_DS1553 is not set
# CONFIG_RTC_DRV_DS1672 is not set
# CONFIG_RTC_DRV_DS1742 is not set
# CONFIG_RTC_DRV_ISL1208 is not set
# CONFIG_RTC_DRV_M41T80 is not set
# CONFIG_RTC_DRV_M48T59 is not set
# CONFIG_RTC_DRV_M48T86 is not set
# CONFIG_RTC_DRV_PCF8563 is not set
# CONFIG_RTC_DRV_PCF8583 is not set
# CONFIG_RTC_DRV_RS5C372 is not set
CONFIG_RTC_DRV_S3C=m
# CONFIG_RTC_DRV_STK17TA8 is not set
# CONFIG_RTC_DRV_TEST is not set
# CONFIG_RTC_DRV_V3020 is not set
# CONFIG_RTC_DRV_X1205 is not set
CONFIG_RTC_HCTOSYS=y
CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
CONFIG_RTC_INTF_DEV=y
# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
CONFIG_RTC_INTF_PROC=y
CONFIG_RTC_INTF_SYSFS=y
CONFIG_RTC_LIB=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
CONFIG_S3C2410_CLOCK=y
CONFIG_S3C2410_DMA=y
# CONFIG_S3C2410_DMA_DEBUG is not set
CONFIG_S3C2410_GPIO=y
CONFIG_S3C2410_PM=y
# CONFIG_S3C2410_PM_CHECK is not set
# CONFIG_S3C2410_PM_DEBUG is not set
CONFIG_S3C2410_PWM=y
CONFIG_S3C2410_WATCHDOG=m
CONFIG_S3C2440_C_FIQ=y
CONFIG_S3C2440_DMA=y
# CONFIG_S3C_BOOT_ERROR_RESET is not set
# CONFIG_S3C_BOOT_WATCHDOG is not set
CONFIG_S3C_LOWLEVEL_UART_PORT=2
CONFIG_SCSI=y
CONFIG_SCSI_SCAN_ASYNC=y
CONFIG_SCSI_WAIT_SCAN=m
CONFIG_SDIO=y
CONFIG_SDIO_AR6000_WLAN=y
CONFIG_SDIO_S3C24XX=y
CONFIG_SDIO_S3C24XX_DMA=y
# CONFIG_SDIO_UART is not set
# CONFIG_SENSORS_PC87360 is not set
CONFIG_SENSORS_PCF50606=y
CONFIG_SENSORS_PCF50633=y
# CONFIG_SERIAL_8250 is not set
CONFIG_SERIAL_S3C2410=y
CONFIG_SERIAL_S3C2410_CONSOLE=y
CONFIG_SERIO=y
# CONFIG_SERIO_RAW is not set
# CONFIG_SERIO_SERPORT is not set
CONFIG_SLAB=y
CONFIG_SLABINFO=y
# CONFIG_SLUB is not set
# CONFIG_SMC91X is not set
CONFIG_SMDK2440_CPU2440=y
CONFIG_SMDK2440_CPU2442=y
CONFIG_SND=y
CONFIG_SND_HWDEP=y
CONFIG_SND_MIXER_OSS=y
CONFIG_SND_PCM=y
CONFIG_SND_PCM_OSS=y
CONFIG_SND_S3C24XX_SOC=y
CONFIG_SND_S3C24XX_SOC_I2S=y
# CONFIG_SND_S3C24XX_SOC_LN2440SBC_ALC650 is not set
CONFIG_SND_S3C24XX_SOC_NEO1973_GTA02_WM8753=y
CONFIG_SND_S3C24XX_SOC_NEO1973_WM8753=y
CONFIG_SND_SEQUENCER=y
# CONFIG_SND_SEQUENCER_OSS is not set
# CONFIG_SND_SEQ_DUMMY is not set
CONFIG_SND_SOC=y
CONFIG_SND_SOC_WM8753=y
CONFIG_SND_TIMER=y
# CONFIG_SND_USB_AUDIO is not set
# CONFIG_SND_VERBOSE_PROCFS is not set
# CONFIG_SND_VIRMIDI is not set
# CONFIG_SOFT_WATCHDOG is not set
CONFIG_SOUND=y
# CONFIG_SPARSEMEM_STATIC is not set
# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
CONFIG_SPI=y
CONFIG_SPI_BITBANG=y
# CONFIG_SPI_GPIO is not set
CONFIG_SPI_MASTER=y
# CONFIG_SPI_S3C24XX is not set
CONFIG_SPI_S3C24XX_GPIO=y
# CONFIG_SPI_SPIDEV is not set
CONFIG_SPLIT_PTLOCK_CPUS=4096
CONFIG_SSB_POSSIBLE=y
CONFIG_SUSPEND=y
CONFIG_SUSPEND_FREEZER=y
# CONFIG_SWAP is not set
CONFIG_SYSFS_DEPRECATED=y
CONFIG_SYSFS_DEPRECATED_V2=y
CONFIG_SYSVIPC_SYSCTL=y
CONFIG_SYS_SUPPORTS_APM_EMULATION=y
# CONFIG_TCP_CONG_ADVANCED is not set
CONFIG_TCP_CONG_CUBIC=y
CONFIG_TCP_MD5SIG=y
# CONFIG_TICK_ONESHOT is not set
# CONFIG_TMPFS is not set
# CONFIG_TOUCHSCREEN_ADS7846 is not set
# CONFIG_TOUCHSCREEN_ELO is not set
# CONFIG_TOUCHSCREEN_FUJITSU is not set
# CONFIG_TOUCHSCREEN_GUNZE is not set
# CONFIG_TOUCHSCREEN_MK712 is not set
# CONFIG_TOUCHSCREEN_MTOUCH is not set
# CONFIG_TOUCHSCREEN_PENMOUNT is not set
CONFIG_TOUCHSCREEN_S3C2410=y
# CONFIG_TOUCHSCREEN_S3C2410_DEBUG is not set
# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set
# CONFIG_TOUCHSCREEN_TOUCHWIN is not set
# CONFIG_TOUCHSCREEN_UCB1400 is not set
# CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set
CONFIG_TUN=y
# CONFIG_UDF_FS is not set
CONFIG_UID16=y
CONFIG_UIO=y
# CONFIG_UIO_SMX is not set
CONFIG_USB=y
CONFIG_USB_ACM=y
CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
# CONFIG_USB_ARCH_HAS_EHCI is not set
CONFIG_USB_DEVICE_CLASS=y
CONFIG_USB_EPSON2888=y
CONFIG_USB_ETH=y
CONFIG_USB_ETH_RNDIS=y
# CONFIG_USB_FILE_STORAGE is not set
CONFIG_USB_GADGET=y
# CONFIG_USB_GADGETFS is not set
# CONFIG_USB_GADGET_AMD5536UDC is not set
# CONFIG_USB_GADGET_AT91 is not set
# CONFIG_USB_GADGET_ATMEL_USBA is not set
# CONFIG_USB_GADGET_DEBUG_FILES is not set
# CONFIG_USB_GADGET_DUALSPEED is not set
# CONFIG_USB_GADGET_DUMMY_HCD is not set
# CONFIG_USB_GADGET_FSL_USB2 is not set
# CONFIG_USB_GADGET_GOKU is not set
# CONFIG_USB_GADGET_LH7A40X is not set
# CONFIG_USB_GADGET_M66592 is not set
# CONFIG_USB_GADGET_NET2280 is not set
# CONFIG_USB_GADGET_OMAP is not set
# CONFIG_USB_GADGET_PXA27X is not set
# CONFIG_USB_GADGET_PXA2XX is not set
CONFIG_USB_GADGET_S3C2410=y
CONFIG_USB_GADGET_SELECTED=y
# CONFIG_USB_G_PRINTER is not set
# CONFIG_USB_G_SERIAL is not set
CONFIG_USB_HID=y
# CONFIG_USB_ISIGHTFW is not set
CONFIG_USB_KC2190=y
CONFIG_USB_LIBUSUAL=y
# CONFIG_USB_MIDI_GADGET is not set
CONFIG_USB_MON=y
# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
CONFIG_USB_OHCI_HCD=y
# CONFIG_USB_PRINTER is not set
CONFIG_USB_RTL8150=m
CONFIG_USB_S3C2410=y
# CONFIG_USB_S3C2410_DEBUG is not set
CONFIG_USB_SERIAL=y
# CONFIG_USB_SERIAL_CH341 is not set
CONFIG_USB_SERIAL_CONSOLE=y
# CONFIG_USB_SERIAL_IUU is not set
# CONFIG_USB_SERIAL_MOTOROLA is not set
CONFIG_USB_SERIAL_OPTION=y
# CONFIG_USB_SERIAL_OTI6858 is not set
# CONFIG_USB_SERIAL_SPCP8X5 is not set
CONFIG_USB_STORAGE=y
# CONFIG_USB_STORAGE_ALAUDA is not set
CONFIG_USB_STORAGE_CYPRESS_ATACB=y
CONFIG_USB_STORAGE_ISD200=y
CONFIG_USB_STORAGE_ONETOUCH=y
CONFIG_USB_SUSPEND=y
CONFIG_USB_USBNET=y
# CONFIG_USB_ZERO is not set
# CONFIG_USER_NS is not set
CONFIG_VECTORS_BASE=0xffff0000
CONFIG_VFAT_FS=y
# CONFIG_VGASTATE is not set
# CONFIG_VGA_CONSOLE is not set
# CONFIG_VIDEO_DEV is not set
# CONFIG_VIDEO_MEDIA is not set
CONFIG_VIDEO_OUTPUT_CONTROL=y
# CONFIG_VLAN_8021Q is not set
CONFIG_VM_EVENT_COUNTERS=y
CONFIG_VT=y
CONFIG_VT_CONSOLE=y
CONFIG_VT_HW_CONSOLE_BINDING=y
# CONFIG_W1 is not set
# CONFIG_WLAN_80211 is not set
CONFIG_XFRM_MIGRATE=y
# CONFIG_XFRM_USER is not set
# CONFIG_XFS_FS is not set
# CONFIG_XIP_KERNEL is not set
CONFIG_ZBOOT_ROM_BSS=0x0
CONFIG_ZBOOT_ROM_TEXT=0x0

View file

@ -0,0 +1,35 @@
#
# Copyright (C) 2006 OpenWrt.org
#
# This is free software, licensed under the GNU General Public License v2.
# See /LICENSE for more information.
#
include $(TOPDIR)/rules.mk
include $(INCLUDE_DIR)/image.mk
#JFFS2_BLOCKSIZE=16k
#JFFS2OPTS += -n --faketime -x lzo
JFFS2OPTS += --little-endian --eraseblock=0x20000 --pagesize=0x800 --no-cleanmarkers --pad -n
MAKE += -j5
#:mkfs.jffs2 -x lzo --root=/data/moko/build/tmp/rootfs --faketime --output=/data/moko/build/tmp/deploy/glibc/images/fic-gta01/OpenMoko-openmoko-devel-image-glibc-P1-August-Snapshot-20070829-fic-gta01.rootfs.jffs2 --little-endian --eraseblock=0x4000 --pad -n
define Image/BuildKernel
$(TARGET_CROSS)objcopy -O binary -R .note -R .comment -S $(KDIR)/linux-2.6.26/arch/arm/boot/compressed/vmlinux linux.bin
mkimage -A arm -O linux -T kernel -C none -a 30008000 -e 30008000 -n "Openmoko Kernel Image Freerunner (Neo1973(GTA02))" -d linux.bin uImage
cp uImage $(BIN_DIR)/openwrt-$(BOARD)-$(KERNEL)-uImage
endef
define Image/Build/squashfs
$(call prepare_generic_squashfs,$(BIN_DIR)/openwrt-$(BOARD)-$(KERNEL)-root.$(1))
endef
define Image/Build
$(CP) $(KDIR)/root.$(1) $(BIN_DIR)/openwrt-$(BOARD)-$(KERNEL)-root.$(1)
$(call Image/Build/$(1),$(1))
endef
$(eval $(call BuildImage))

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,29 @@
From 0fa9c1c2fe923ca4f36573ca6e6b97e555d0802d Mon Sep 17 00:00:00 2001
From: mokopatches <mokopatches@openmoko.org>
Date: Wed, 16 Jul 2008 14:44:10 +0100
Subject: [PATCH] explicitly-link-notes-section.patch
Since 2.6.23 kbuild produces a 3GB arch/arm/boot/Image because it includes a
.note.gnu.build-id section at address 0 which is followed by 3GB of 0x00.
The --build-id option is set in the toplevel Makefile.
This patch explicitly puts the notes section after the TEXT section.
---
arch/arm/kernel/vmlinux.lds.S | 2 ++
1 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S
index 4898bdc..b835564 100644
--- a/arch/arm/kernel/vmlinux.lds.S
+++ b/arch/arm/kernel/vmlinux.lds.S
@@ -106,6 +106,8 @@ SECTIONS
*(.got) /* Global offset table */
}
+ NOTES
+
RODATA
_etext = .; /* End of text and rodata section */
--
1.5.6.3

View file

@ -0,0 +1,60 @@
From 1ef4af1f96284576aa9b7f4490c791350c99fffd Mon Sep 17 00:00:00 2001
From: mokopatches <mokopatches@openmoko.org>
Date: Wed, 16 Jul 2008 14:44:10 +0100
Subject: [PATCH] gta01-no_nand_partitions.patch
[PATCH] support mtd NAND commandline partitions for S3C2410
This patch adds support for the mtd NAND core standard method of passing
partition table information from the bootloader into the kernel by using
the kernel commandline.
The board specific code can still manually override and provide a fixed
partition table, so this patch will behave backwards compatible.
Signed-off-by: Harald Welte <laforge@openmoko.org>
Acked-byt: Ben Dooks <ben-linux@fluff.org>
---
drivers/mtd/nand/s3c2410.c | 18 ++++++++++++++++--
1 files changed, 16 insertions(+), 2 deletions(-)
diff --git a/drivers/mtd/nand/s3c2410.c b/drivers/mtd/nand/s3c2410.c
index b34a460..101b6b5 100644
--- a/drivers/mtd/nand/s3c2410.c
+++ b/drivers/mtd/nand/s3c2410.c
@@ -566,17 +566,31 @@ static int s3c2410_nand_remove(struct platform_device *pdev)
}
#ifdef CONFIG_MTD_PARTITIONS
+const char *part_probes[] = { "cmdlinepart", NULL };
static int s3c2410_nand_add_partition(struct s3c2410_nand_info *info,
struct s3c2410_nand_mtd *mtd,
struct s3c2410_nand_set *set)
{
+ struct mtd_partition *part_info;
+ int nr_part = 0;
+
if (set == NULL)
return add_mtd_device(&mtd->mtd);
- if (set->nr_partitions > 0 && set->partitions != NULL) {
- return add_mtd_partitions(&mtd->mtd, set->partitions, set->nr_partitions);
+ if (set->nr_partitions == 0) {
+ mtd->mtd.name = set->name;
+ nr_part = parse_mtd_partitions(&mtd->mtd, part_probes,
+ &part_info, 0);
+ } else {
+ if (set->nr_partitions > 0 && set->partitions != NULL) {
+ nr_part = set->nr_partitions;
+ part_info = set->partitions;
+ }
}
+ if (nr_part > 0 && part_info)
+ return add_mtd_partitions(&mtd->mtd, part_info, nr_part);
+
return add_mtd_device(&mtd->mtd);
}
#else
--
1.5.6.3

View file

@ -0,0 +1,106 @@
From eb5cadc7ff0e6c3aedfec3323146d7bb6bdfe0f0 Mon Sep 17 00:00:00 2001
From: mokopatches <mokopatches@openmoko.org>
Date: Wed, 16 Jul 2008 14:44:10 +0100
Subject: [PATCH] fix-i2c-s3c2410-resume-race.patch
fix-i2c-s3c2410-resume-race.patch
There is a nasty race between i2c-s3c2410 resume and resume of I2C
driver and the client drivers -- the watchdog device actually gets to
use the dead I2C bus before it is reinitialized by the I2C driver
resume! This patch makes sure any customers get turned away until
the shopkeeper has woken up.
Signed-off-by: Andy Green <andy@openmoko.com>
---
drivers/i2c/busses/i2c-s3c2410.c | 33 +++++++++++++++++++++++++++++++++
1 files changed, 33 insertions(+), 0 deletions(-)
diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c
index 9e8c875..02459d7 100644
--- a/drivers/i2c/busses/i2c-s3c2410.c
+++ b/drivers/i2c/busses/i2c-s3c2410.c
@@ -71,6 +71,8 @@ struct s3c24xx_i2c {
struct resource *irq;
struct resource *ioarea;
struct i2c_adapter adap;
+
+ int suspended;
};
/* default platform data to use if not supplied in the platform_device
@@ -156,6 +158,14 @@ static inline void s3c24xx_i2c_disable_irq(struct s3c24xx_i2c *i2c)
unsigned long tmp;
tmp = readl(i2c->regs + S3C2410_IICCON);
+
+/* S3c2442 datasheet
+ *
+ * If the IICCON[5]=0, IICCON[4] does not operate correctly.
+ * So, It is recommended that you should set IICCON[5]=1,
+ * although you does not use the IIC interrupt.
+ */
+
writel(tmp & ~S3C2410_IICCON_IRQEN, i2c->regs + S3C2410_IICCON);
}
@@ -501,6 +511,14 @@ static int s3c24xx_i2c_doxfer(struct s3c24xx_i2c *i2c, struct i2c_msg *msgs, int
unsigned long timeout;
int ret;
+ if (i2c->suspended) {
+ dev_err(i2c->dev,
+ "Hey I am still asleep (suspended: %d), retry later\n",
+ i2c->suspended);
+ ret = -EAGAIN;
+ goto out;
+ }
+
ret = s3c24xx_i2c_set_master(i2c);
if (ret != 0) {
dev_err(i2c->dev, "cannot get bus (error %d)\n", ret);
@@ -885,6 +903,17 @@ static int s3c24xx_i2c_remove(struct platform_device *pdev)
}
#ifdef CONFIG_PM
+
+static int s3c24xx_i2c_suspend(struct platform_device *dev, pm_message_t state)
+{
+ struct s3c24xx_i2c *i2c = platform_get_drvdata(dev);
+
+ if (i2c != NULL)
+ i2c->suspended++;
+
+ return 0;
+}
+
static int s3c24xx_i2c_resume(struct platform_device *dev)
{
struct s3c24xx_i2c *i2c = platform_get_drvdata(dev);
@@ -892,6 +921,8 @@ static int s3c24xx_i2c_resume(struct platform_device *dev)
if (i2c != NULL)
s3c24xx_i2c_init(i2c);
+ i2c->suspended--;
+
return 0;
}
@@ -904,6 +935,7 @@ static int s3c24xx_i2c_resume(struct platform_device *dev)
static struct platform_driver s3c2410_i2c_driver = {
.probe = s3c24xx_i2c_probe,
.remove = s3c24xx_i2c_remove,
+ .suspend = s3c24xx_i2c_suspend,
.resume = s3c24xx_i2c_resume,
.driver = {
.owner = THIS_MODULE,
@@ -914,6 +946,7 @@ static struct platform_driver s3c2410_i2c_driver = {
static struct platform_driver s3c2440_i2c_driver = {
.probe = s3c24xx_i2c_probe,
.remove = s3c24xx_i2c_remove,
+ .suspend = s3c24xx_i2c_suspend,
.resume = s3c24xx_i2c_resume,
.driver = {
.owner = THIS_MODULE,
--
1.5.6.3

View file

@ -0,0 +1,45 @@
From 62bc0d984e5c2778e09094ba2e4d885903c6c35b Mon Sep 17 00:00:00 2001
From: mokopatches <mokopatches@openmoko.org>
Date: Wed, 16 Jul 2008 14:44:10 +0100
Subject: [PATCH] resume-timers-wq.patch
The initialization of clocks uses mutexes, but we execute the resume in
an interrupt context. We therefore have to hand this task to a non-interrupt.
Adapted from a patch by Andy Green.
---
arch/arm/plat-s3c24xx/time.c | 18 +++++++++++++++++-
1 files changed, 17 insertions(+), 1 deletions(-)
diff --git a/arch/arm/plat-s3c24xx/time.c b/arch/arm/plat-s3c24xx/time.c
index 766473b..f8d307b 100644
--- a/arch/arm/plat-s3c24xx/time.c
+++ b/arch/arm/plat-s3c24xx/time.c
@@ -253,8 +253,24 @@ static void __init s3c2410_timer_init (void)
setup_irq(IRQ_TIMER4, &s3c2410_timer_irq);
}
+static void s3c2410_timer_resume_work(struct work_struct *work)
+{
+ s3c2410_timer_setup();
+}
+
+static void s3c2410_timer_resume(void)
+{
+ static DECLARE_WORK(work, s3c2410_timer_resume_work);
+ int res;
+
+ res = schedule_work(&work);
+ if (!res)
+ printk(KERN_ERR
+ "s3c2410_timer_resume_work already queued ???\n");
+}
+
struct sys_timer s3c24xx_timer = {
.init = s3c2410_timer_init,
.offset = s3c2410_gettimeoffset,
- .resume = s3c2410_timer_setup
+ .resume = s3c2410_timer_resume,
};
--
1.5.6.3

View file

@ -0,0 +1,56 @@
From ee782e877d8c50f3ed775aee8934565699a5fc99 Mon Sep 17 00:00:00 2001
From: mokopatches <mokopatches@openmoko.org>
Date: Wed, 16 Jul 2008 14:44:10 +0100
Subject: [PATCH] s3c2410-bbt.patch
[PATCH] Add Kconfig option to enable NAND bad-block-table support for s3c2410
This patch adds a new CONFIG_MTD_NAND_S3C2410_BBT which, if enabled,
asks the mtd NAND core to use a bad-block table.
Signed-off-by: Harald Welte <laforge@openmoko.org>
---
drivers/mtd/nand/s3c2410.c | 6 +++++-
include/asm-arm/plat-s3c/nand.h | 3 +++
2 files changed, 8 insertions(+), 1 deletions(-)
diff --git a/drivers/mtd/nand/s3c2410.c b/drivers/mtd/nand/s3c2410.c
index 101b6b5..cd2e1da 100644
--- a/drivers/mtd/nand/s3c2410.c
+++ b/drivers/mtd/nand/s3c2410.c
@@ -619,9 +619,13 @@ static void s3c2410_nand_init_chip(struct s3c2410_nand_info *info,
chip->select_chip = s3c2410_nand_select_chip;
chip->chip_delay = 50;
chip->priv = nmtd;
- chip->options = 0;
chip->controller = &info->controller;
+ if (set->flags & S3C2410_NAND_BBT)
+ chip->options = NAND_USE_FLASH_BBT;
+ else
+ chip->options = 0;
+
switch (info->cpu_type) {
case TYPE_S3C2410:
chip->IO_ADDR_W = regs + S3C2410_NFDATA;
diff --git a/include/asm-arm/plat-s3c/nand.h b/include/asm-arm/plat-s3c/nand.h
index ad6bbe9..54f479e 100644
--- a/include/asm-arm/plat-s3c/nand.h
+++ b/include/asm-arm/plat-s3c/nand.h
@@ -21,11 +21,14 @@
* partitions = mtd partition list
*/
+#define S3C2410_NAND_BBT 0x0001
+
struct s3c2410_nand_set {
unsigned int disable_ecc : 1;
int nr_chips;
int nr_partitions;
+ unsigned int flags;
char *name;
int *nr_map;
struct mtd_partition *partitions;
--
1.5.6.3

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,831 @@
From 821c65f3420494eadf5260e48b54b9f59e6e865c Mon Sep 17 00:00:00 2001
From: mokopatches <mokopatches@openmoko.org>
Date: Wed, 16 Jul 2008 14:44:42 +0100
Subject: [PATCH] gta01-core.patch
This patch adds support for the FIC Neo1973 GTA01 machine type to the ARM port
of the Linux kernel.
Signed-off-by: Harald Welte <laforge@openmoko.org>
---
MAINTAINERS | 8 +
arch/arm/mach-s3c2410/Kconfig | 8 +
arch/arm/mach-s3c2410/Makefile | 10 +
arch/arm/mach-s3c2410/mach-gta01.c | 658 ++++++++++++++++++++++++++++++++++
arch/arm/plat-s3c24xx/Kconfig | 5 +
include/asm-arm/arch-s3c2410/gta01.h | 70 ++++
6 files changed, 759 insertions(+), 0 deletions(-)
create mode 100644 arch/arm/mach-s3c2410/mach-gta01.c
create mode 100644 include/asm-arm/arch-s3c2410/gta01.h
diff --git a/MAINTAINERS b/MAINTAINERS
index 56a2f67..9c1a796 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1664,6 +1664,14 @@ P: Akinobu Mita
M: akinobu.mita@gmail.com
S: Supported
+FIC/OPENMOKO NEO1973 GSM PHONE
+P: Harald Welte
+M: laforge@openmoko.org
+L: openmoko-kernel@lists.openmoko.org
+W: http://wiki.openmoko.org/wiki/Kernel
+W: http://wiki.openmoko.org/wiki/Neo1973
+S: Maintained
+
FRAMEBUFFER LAYER
P: Antonino Daplas
M: adaplas@gmail.com
diff --git a/arch/arm/mach-s3c2410/Kconfig b/arch/arm/mach-s3c2410/Kconfig
index cd3dc08..7e3a1a2 100644
--- a/arch/arm/mach-s3c2410/Kconfig
+++ b/arch/arm/mach-s3c2410/Kconfig
@@ -117,5 +117,13 @@ config MACH_QT2410
help
Say Y here if you are using the Armzone QT2410
+config MACH_NEO1973_GTA01
+ bool "FIC Neo1973 GSM Phone (GTA01 Hardware)"
+ select CPU_S3C2410
+ select MACH_NEO1973
+ select SENSORS_PCF50606
+ help
+ Say Y here if you are using the FIC Neo1973 GSM Phone
+
endmenu
diff --git a/arch/arm/mach-s3c2410/Makefile b/arch/arm/mach-s3c2410/Makefile
index cabc13c..b73562f 100644
--- a/arch/arm/mach-s3c2410/Makefile
+++ b/arch/arm/mach-s3c2410/Makefile
@@ -30,3 +30,13 @@ obj-$(CONFIG_BAST_PC104_IRQ) += bast-irq.o
obj-$(CONFIG_MACH_TCT_HAMMER) += mach-tct_hammer.o
obj-$(CONFIG_MACH_VR1000) += mach-vr1000.o usb-simtec.o
obj-$(CONFIG_MACH_QT2410) += mach-qt2410.o
+
+# Common bits of machine support
+
+obj-$(CONFIG_SIMTEC_NOR) += nor-simtec.o
+
+# machine additions
+
+obj-$(CONFIG_MACH_BAST_IDE) += bast-ide.o
+obj-$(CONFIG_MACH_NEO1973_GTA01)+= mach-gta01.o
+
diff --git a/arch/arm/mach-s3c2410/mach-gta01.c b/arch/arm/mach-s3c2410/mach-gta01.c
new file mode 100644
index 0000000..e690ed7
--- /dev/null
+++ b/arch/arm/mach-s3c2410/mach-gta01.c
@@ -0,0 +1,658 @@
+/*
+ * linux/arch/arm/mach-s3c2410/mach-gta01.c
+ *
+ * S3C2410 Machine Support for the FIC Neo1973 GTA01
+ *
+ * Copyright (C) 2006-2007 by OpenMoko, Inc.
+ * Author: Harald Welte <laforge@openmoko.org>
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+
+#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/workqueue.h>
+#include <linux/platform_device.h>
+#include <linux/serial_core.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/spi_bitbang.h>
+#include <linux/mmc/mmc.h>
+#include <linux/mmc/host.h>
+
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/nand_ecc.h>
+#include <linux/mtd/partitions.h>
+
+#include <linux/mmc/host.h>
+
+#include <linux/pcf50606.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/mach-types.h>
+
+#include <asm/arch/regs-gpio.h>
+#include <asm/arch/fb.h>
+#include <asm/arch/spi.h>
+#include <asm/arch/spi-gpio.h>
+#include <asm/arch/usb-control.h>
+
+#include <asm/arch/gta01.h>
+
+#include <asm/plat-s3c/regs-serial.h>
+#include <asm/plat-s3c/nand.h>
+#include <asm/plat-s3c24xx/devs.h>
+#include <asm/plat-s3c24xx/cpu.h>
+#include <asm/plat-s3c24xx/pm.h>
+#include <asm/plat-s3c24xx/udc.h>
+
+static struct map_desc gta01_iodesc[] __initdata = {
+ {
+ .virtual = 0xe0000000,
+ .pfn = __phys_to_pfn(S3C2410_CS3+0x01000000),
+ .length = SZ_1M,
+ .type = MT_DEVICE
+ },
+};
+
+#define UCON S3C2410_UCON_DEFAULT
+#define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB
+#define UFCON S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE
+
+static struct s3c2410_uartcfg gta01_uartcfgs[] = {
+ [0] = {
+ .hwport = 0,
+ .flags = 0,
+ .ucon = UCON,
+ .ulcon = ULCON,
+ .ufcon = UFCON,
+ },
+ [1] = {
+ .hwport = 1,
+ .flags = 0,
+ .ucon = UCON,
+ .ulcon = ULCON,
+ .ufcon = UFCON,
+ },
+};
+
+/* PMU driver info */
+
+static int pmu_callback(struct device *dev, unsigned int feature,
+ enum pmu_event event)
+{
+ switch (feature) {
+ case PCF50606_FEAT_ACD:
+ switch (event) {
+ case PMU_EVT_INSERT:
+ pcf50606_charge_fast(pcf50606_global, 1);
+ break;
+ case PMU_EVT_REMOVE:
+ pcf50606_charge_fast(pcf50606_global, 0);
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static struct pcf50606_platform_data gta01_pcf_pdata = {
+ .used_features = PCF50606_FEAT_EXTON |
+ PCF50606_FEAT_MBC |
+ PCF50606_FEAT_BBC |
+ PCF50606_FEAT_RTC |
+ PCF50606_FEAT_WDT |
+ PCF50606_FEAT_CHGCUR |
+ PCF50606_FEAT_BATVOLT |
+ PCF50606_FEAT_BATTEMP,
+ .onkey_seconds_required = 3,
+ .cb = &pmu_callback,
+ .r_fix_batt = 10000,
+ .r_fix_batt_par = 10000,
+ .r_sense_milli = 220,
+ .rails = {
+ [PCF50606_REGULATOR_D1REG] = {
+ .name = "bt_3v15",
+ .voltage = {
+ .init = 3150,
+ .max = 3150,
+ },
+ },
+ [PCF50606_REGULATOR_D2REG] = {
+ .name = "gl_2v5",
+ .voltage = {
+ .init = 2500,
+ .max = 2500,
+ },
+ },
+ [PCF50606_REGULATOR_D3REG] = {
+ .name = "stby_1v8",
+ .flags = PMU_VRAIL_F_SUSPEND_ON,
+ .voltage = {
+ .init = 1800,
+ .max = 2100,
+ },
+ },
+ [PCF50606_REGULATOR_DCD] = {
+ .name = "gl_1v5",
+ .voltage = {
+ .init = 1500,
+ .max = 1500,
+ },
+ },
+ [PCF50606_REGULATOR_DCDE] = {
+ .name = "io_3v3",
+ .flags = PMU_VRAIL_F_SUSPEND_ON,
+ .voltage = {
+ .init = 3300,
+ .max = 3330,
+ },
+ },
+ [PCF50606_REGULATOR_DCUD] = {
+ .name = "core_1v8",
+ .flags = PMU_VRAIL_F_SUSPEND_ON,
+ .voltage = {
+ .init = 2100,
+ .max = 2100,
+ },
+ },
+ [PCF50606_REGULATOR_IOREG] = {
+ .name = "codec_3v3",
+ .voltage = {
+ .init = 3300,
+ .max = 3300,
+ },
+ },
+ [PCF50606_REGULATOR_LPREG] = {
+ .name = "lcm_3v3",
+ .voltage = {
+ .init = 3300,
+ .max = 3300,
+ },
+ }
+ },
+};
+
+static void cfg_pmu_vrail(struct pmu_voltage_rail *vrail, char *name,
+ unsigned int flags, unsigned int init,
+ unsigned int max)
+{
+ vrail->name = name;
+ vrail->flags = flags;
+ vrail->voltage.init = init;
+ vrail->voltage.max = max;
+}
+
+static void mangle_pmu_pdata_by_system_rev(void)
+{
+ switch (system_rev) {
+ case GTA01Bv4_SYSTEM_REV:
+ gta01_pcf_pdata.used_features |= PCF50606_FEAT_ACD;
+ break;
+ case GTA01Bv3_SYSTEM_REV:
+ case GTA01Bv2_SYSTEM_REV:
+ gta01_pcf_pdata.rails[PCF50606_REGULATOR_D3REG]
+ .name = "user1";
+ gta01_pcf_pdata.rails[PCF50606_REGULATOR_D3REG]
+ .flags &= ~PMU_VRAIL_F_SUSPEND_ON;
+ gta01_pcf_pdata.rails[PCF50606_REGULATOR_D3REG]
+ .flags = PMU_VRAIL_F_UNUSED;
+ break;
+ case GTA01v4_SYSTEM_REV:
+ cfg_pmu_vrail(&gta01_pcf_pdata.rails[PCF50606_REGULATOR_DCUD],
+ "core_1v8", PMU_VRAIL_F_SUSPEND_ON, 1800, 1800);
+ cfg_pmu_vrail(&gta01_pcf_pdata.rails[PCF50606_REGULATOR_D1REG],
+ "vrf_3v", 0, 3000, 3000);
+ cfg_pmu_vrail(&gta01_pcf_pdata.rails[PCF50606_REGULATOR_D3REG],
+ "vtcxo_2v8", 0, 2800, 2800);
+ cfg_pmu_vrail(&gta01_pcf_pdata.rails[PCF50606_REGULATOR_DCD],
+ "gl_3v5", 0, 3500, 3500);
+ break;
+ case GTA01v3_SYSTEM_REV:
+ cfg_pmu_vrail(&gta01_pcf_pdata.rails[PCF50606_REGULATOR_D1REG],
+ "vrf_3v", 0, 3000, 3000);
+ cfg_pmu_vrail(&gta01_pcf_pdata.rails[PCF50606_REGULATOR_D2REG],
+ "sd_3v3", 0, 3300, 3300);
+ cfg_pmu_vrail(&gta01_pcf_pdata.rails[PCF50606_REGULATOR_D3REG],
+ "codec_3v3", 0, 3300, 3300);
+ cfg_pmu_vrail(&gta01_pcf_pdata.rails[PCF50606_REGULATOR_DCD],
+ "gpsio_3v3", 0, 3300, 3300);
+ cfg_pmu_vrail(&gta01_pcf_pdata.rails[PCF50606_REGULATOR_DCUD],
+ "core_1v8", PMU_VRAIL_F_SUSPEND_ON, 1800, 1800);
+ cfg_pmu_vrail(&gta01_pcf_pdata.rails[PCF50606_REGULATOR_IOREG],
+ "vtcxo_2v8", 0, 2800, 2800);
+ break;
+ }
+}
+
+static struct resource gta01_pmu_resources[] = {
+ [0] = {
+ .flags = IORESOURCE_IRQ,
+ .start = GTA01_IRQ_PCF50606,
+ .end = GTA01_IRQ_PCF50606,
+ },
+};
+
+struct platform_device gta01_pmu_dev = {
+ .name = "pcf50606",
+ .num_resources = ARRAY_SIZE(gta01_pmu_resources),
+ .resource = gta01_pmu_resources,
+ .dev = {
+ .platform_data = &gta01_pcf_pdata,
+ },
+};
+
+/* LCD driver info */
+
+/* Configuration for 480x640 toppoly TD028TTEC1.
+ * Do not mark this as __initdata or it will break! */
+static struct s3c2410fb_display gta01_displays[] = {
+ {
+ .type = S3C2410_LCDCON1_TFT,
+ .width = 43,
+ .height = 58,
+ .xres = 480,
+ .yres = 640,
+ .bpp = 16,
+
+ .pixclock = 40000, /* HCLK/4 */
+ .left_margin = 104,
+ .right_margin = 8,
+ .hsync_len = 8,
+ .upper_margin = 2,
+ .lower_margin = 16,
+ .vsync_len = 2,
+ .lcdcon5 = S3C2410_LCDCON5_FRM565 |
+ S3C2410_LCDCON5_INVVCLK |
+ S3C2410_LCDCON5_INVVLINE |
+ S3C2410_LCDCON5_INVVFRAME |
+ S3C2410_LCDCON5_PWREN |
+ S3C2410_LCDCON5_HWSWP,
+ },
+ {
+ .type = S3C2410_LCDCON1_TFT,
+ .width = 43,
+ .height = 58,
+ .xres = 480,
+ .yres = 640,
+ .bpp = 32,
+
+ .pixclock = 40000, /* HCLK/4 */
+ .left_margin = 104,
+ .right_margin = 8,
+ .hsync_len = 8,
+ .upper_margin = 2,
+ .lower_margin = 16,
+ .vsync_len = 2,
+ .lcdcon5 = S3C2410_LCDCON5_FRM565 |
+ S3C2410_LCDCON5_INVVCLK |
+ S3C2410_LCDCON5_INVVLINE |
+ S3C2410_LCDCON5_INVVFRAME |
+ S3C2410_LCDCON5_PWREN |
+ S3C2410_LCDCON5_HWSWP,
+ },
+ {
+ .type = S3C2410_LCDCON1_TFT,
+ .width = 43,
+ .height = 58,
+ .xres = 240,
+ .yres = 320,
+ .bpp = 16,
+
+ .pixclock = 40000, /* HCLK/4 */
+ .left_margin = 104,
+ .right_margin = 8,
+ .hsync_len = 8,
+ .upper_margin = 2,
+ .lower_margin = 16,
+ .vsync_len = 2,
+ .lcdcon5 = S3C2410_LCDCON5_FRM565 |
+ S3C2410_LCDCON5_INVVCLK |
+ S3C2410_LCDCON5_INVVLINE |
+ S3C2410_LCDCON5_INVVFRAME |
+ S3C2410_LCDCON5_PWREN |
+ S3C2410_LCDCON5_HWSWP,
+ },
+};
+
+static struct s3c2410fb_mach_info gta01_lcd_cfg __initdata = {
+ .displays = gta01_displays,
+ .num_displays = ARRAY_SIZE(gta01_displays),
+ .default_display = 0,
+
+ .lpcsel = ((0xCE6) & ~7) | 1<<4,
+};
+
+static struct platform_device *gta01_devices[] __initdata = {
+ &s3c_device_usb,
+ &s3c_device_lcd,
+ &s3c_device_wdt,
+ &s3c_device_i2c,
+ &s3c_device_iis,
+ &s3c_device_sdi,
+ &s3c_device_usbgadget,
+ &s3c_device_nand,
+};
+
+static struct s3c2410_nand_set gta01_nand_sets[] = {
+ [0] = {
+ .name = "neo1973-nand",
+ .nr_chips = 1,
+ .flags = S3C2410_NAND_BBT,
+ },
+};
+
+static struct s3c2410_platform_nand gta01_nand_info = {
+ .tacls = 20,
+ .twrph0 = 60,
+ .twrph1 = 20,
+ .nr_sets = ARRAY_SIZE(gta01_nand_sets),
+ .sets = gta01_nand_sets,
+};
+
+static void gta01_udc_command(enum s3c2410_udc_cmd_e cmd)
+{
+ printk(KERN_DEBUG "%s(%d)\n", __func__, cmd);
+
+ switch (cmd) {
+ case S3C2410_UDC_P_ENABLE:
+ s3c2410_gpio_setpin(GTA01_GPIO_USB_PULLUP, 1);
+ break;
+ case S3C2410_UDC_P_DISABLE:
+ s3c2410_gpio_setpin(GTA01_GPIO_USB_PULLUP, 0);
+ break;
+ default:
+ break;
+ }
+}
+
+/* use a work queue, since I2C API inherently schedules
+ * and we get called in hardirq context from UDC driver */
+
+struct vbus_draw {
+ struct work_struct work;
+ int ma;
+};
+static struct vbus_draw gta01_udc_vbus_drawer;
+
+static void __gta01_udc_vbus_draw(struct work_struct *work)
+{
+ /* this is a fix to work around boot-time ordering problems if the
+ * s3c2410_udc is initialized before the pcf50606 driver has defined
+ * pcf50606_global */
+ if (!pcf50606_global)
+ return;
+
+ if (gta01_udc_vbus_drawer.ma >= 500) {
+ /* enable fast charge */
+ printk(KERN_DEBUG "udc: enabling fast charge\n");
+ pcf50606_charge_fast(pcf50606_global, 1);
+ } else {
+ /* disable fast charge */
+ printk(KERN_DEBUG "udc: disabling fast charge\n");
+ pcf50606_charge_fast(pcf50606_global, 0);
+ }
+}
+
+static void gta01_udc_vbus_draw(unsigned int ma)
+{
+ gta01_udc_vbus_drawer.ma = ma;
+ schedule_work(&gta01_udc_vbus_drawer.work);
+}
+
+static struct s3c2410_udc_mach_info gta01_udc_cfg = {
+ .vbus_draw = gta01_udc_vbus_draw,
+};
+
+/* SPI */
+
+static struct spi_board_info gta01_spi_board_info[] = {
+ {
+ .modalias = "jbt6k74",
+ /* platform_data */
+ /* controller_data */
+ /* irq */
+ .max_speed_hz = 10 * 1000 * 1000,
+ .bus_num = 1,
+ /* chip_select */
+ },
+};
+
+static void spi_gpio_cs(struct s3c2410_spigpio_info *spi, int cs)
+{
+ switch (cs) {
+ case BITBANG_CS_ACTIVE:
+ s3c2410_gpio_setpin(S3C2410_GPG3, 0);
+ break;
+ case BITBANG_CS_INACTIVE:
+ s3c2410_gpio_setpin(S3C2410_GPG3, 1);
+ break;
+ }
+}
+
+static struct s3c2410_spigpio_info spi_gpio_cfg = {
+ .pin_clk = S3C2410_GPG7,
+ .pin_mosi = S3C2410_GPG6,
+ .pin_miso = S3C2410_GPG5,
+ .board_size = ARRAY_SIZE(gta01_spi_board_info),
+ .board_info = gta01_spi_board_info,
+ .chip_select = &spi_gpio_cs,
+};
+
+static struct resource s3c_spi_lcm_resource[] = {
+ [0] = {
+ .start = S3C2410_GPG3,
+ .end = S3C2410_GPG3,
+ },
+ [1] = {
+ .start = S3C2410_GPG5,
+ .end = S3C2410_GPG5,
+ },
+ [2] = {
+ .start = S3C2410_GPG6,
+ .end = S3C2410_GPG6,
+ },
+ [3] = {
+ .start = S3C2410_GPG7,
+ .end = S3C2410_GPG7,
+ },
+};
+
+struct platform_device s3c_device_spi_lcm = {
+ .name = "s3c24xx-spi-gpio",
+ .id = 1,
+ .num_resources = ARRAY_SIZE(s3c_spi_lcm_resource),
+ .resource = s3c_spi_lcm_resource,
+ .dev = {
+ .platform_data = &spi_gpio_cfg,
+ },
+};
+
+static struct gta01bl_machinfo backlight_machinfo = {
+ .default_intensity = 1,
+ .max_intensity = 1,
+ .limit_mask = 1,
+};
+
+static struct resource gta01_bl_resources[] = {
+ [0] = {
+ .start = GTA01_GPIO_BACKLIGHT,
+ .end = GTA01_GPIO_BACKLIGHT,
+ },
+};
+
+struct platform_device gta01_bl_dev = {
+ .name = "gta01-bl",
+ .num_resources = ARRAY_SIZE(gta01_bl_resources),
+ .resource = gta01_bl_resources,
+ .dev = {
+ .platform_data = &backlight_machinfo,
+ },
+};
+
+static struct resource gta01_led_resources[] = {
+ [0] = {
+ .start = GTA01_GPIO_VIBRATOR_ON,
+ .end = GTA01_GPIO_VIBRATOR_ON,
+ },
+};
+
+struct platform_device gta01_led_dev = {
+ .name = "neo1973-vibrator",
+ .num_resources = ARRAY_SIZE(gta01_led_resources),
+ .resource = gta01_led_resources,
+};
+
+static struct resource gta01_button_resources[] = {
+ [0] = {
+ .start = GTA01_GPIO_AUX_KEY,
+ .end = GTA01_GPIO_AUX_KEY,
+ },
+ [1] = {
+ .start = GTA01_GPIO_HOLD_KEY,
+ .end = GTA01_GPIO_HOLD_KEY,
+ },
+ [2] = {
+ .start = GTA01_GPIO_JACK_INSERT,
+ .end = GTA01_GPIO_JACK_INSERT,
+ },
+};
+
+struct platform_device gta01_button_dev = {
+ .name = "neo1973-button",
+ .num_resources = ARRAY_SIZE(gta01_button_resources),
+ .resource = gta01_button_resources,
+};
+
+static struct platform_device gta01_pm_gsm_dev = {
+ .name = "neo1973-pm-gsm",
+};
+
+/* USB */
+static struct s3c2410_hcd_info gta01_usb_info = {
+ .port[0] = {
+ .flags = S3C_HCDFLG_USED,
+ },
+ .port[1] = {
+ .flags = 0,
+ },
+};
+
+static void __init gta01_map_io(void)
+{
+ s3c24xx_init_io(gta01_iodesc, ARRAY_SIZE(gta01_iodesc));
+ s3c24xx_init_clocks(12*1000*1000);
+ s3c24xx_init_uarts(gta01_uartcfgs, ARRAY_SIZE(gta01_uartcfgs));
+}
+
+static irqreturn_t gta01_modem_irq(int irq, void *param)
+{
+ printk(KERN_DEBUG "modem wakeup interrupt\n");
+ return IRQ_HANDLED;
+}
+
+static void __init gta01_machine_init(void)
+{
+ int rc;
+
+ if (system_rev == GTA01v4_SYSTEM_REV ||
+ system_rev == GTA01Bv2_SYSTEM_REV ||
+ system_rev == GTA01Bv3_SYSTEM_REV ||
+ system_rev == GTA01Bv4_SYSTEM_REV) {
+ gta01_udc_cfg.udc_command = gta01_udc_command;
+ }
+
+ s3c_device_usb.dev.platform_data = &gta01_usb_info;
+ s3c_device_nand.dev.platform_data = &gta01_nand_info;
+
+ s3c24xx_fb_set_platdata(&gta01_lcd_cfg);
+
+ INIT_WORK(&gta01_udc_vbus_drawer.work, __gta01_udc_vbus_draw);
+ s3c24xx_udc_set_platdata(&gta01_udc_cfg);
+
+ /* Set LCD_RESET / XRES to high */
+ s3c2410_gpio_cfgpin(S3C2410_GPC6, S3C2410_GPIO_OUTPUT);
+ s3c2410_gpio_setpin(S3C2410_GPC6, 1);
+
+ /* SPI chip select is gpio output */
+ s3c2410_gpio_cfgpin(S3C2410_GPG3, S3C2410_GPIO_OUTPUT);
+ s3c2410_gpio_setpin(S3C2410_GPG3, 1);
+ platform_device_register(&s3c_device_spi_lcm);
+
+ platform_device_register(&gta01_bl_dev);
+ platform_device_register(&gta01_button_dev);
+ platform_device_register(&gta01_pm_gsm_dev);
+
+ switch (system_rev) {
+ case GTA01v3_SYSTEM_REV:
+ case GTA01v4_SYSTEM_REV:
+ /* just use the default (GTA01_IRQ_PCF50606) */
+ break;
+ case GTA01Bv2_SYSTEM_REV:
+ case GTA01Bv3_SYSTEM_REV:
+ /* just use the default (GTA01_IRQ_PCF50606) */
+ gta01_led_resources[0].start =
+ gta01_led_resources[0].end = GTA01Bv2_GPIO_VIBRATOR_ON;
+ break;
+ case GTA01Bv4_SYSTEM_REV:
+ gta01_pmu_resources[0].start =
+ gta01_pmu_resources[0].end = GTA01Bv4_IRQ_PCF50606;
+ gta01_led_resources[0].start =
+ gta01_led_resources[0].end = GTA01Bv4_GPIO_VIBRATOR_ON;
+ break;
+ }
+ mangle_pmu_pdata_by_system_rev();
+ platform_device_register(&gta01_pmu_dev);
+ platform_device_register(&gta01_led_dev);
+
+ platform_add_devices(gta01_devices, ARRAY_SIZE(gta01_devices));
+
+ s3c2410_pm_init();
+
+ set_irq_type(GTA01_IRQ_MODEM, IRQT_RISING);
+ rc = request_irq(GTA01_IRQ_MODEM, gta01_modem_irq, IRQF_DISABLED,
+ "modem", NULL);
+ if (!rc)
+ printk(KERN_ERR "GTA01: can't request GSM modem wakeup IRQ\n");
+ enable_irq_wake(GTA01_IRQ_MODEM);
+}
+
+MACHINE_START(NEO1973_GTA01, "GTA01")
+ .phys_io = S3C2410_PA_UART,
+ .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
+ .boot_params = S3C2410_SDRAM_PA + 0x100,
+ .map_io = gta01_map_io,
+ .init_irq = s3c24xx_init_irq,
+ .init_machine = gta01_machine_init,
+ .timer = &s3c24xx_timer,
+MACHINE_END
diff --git a/arch/arm/plat-s3c24xx/Kconfig b/arch/arm/plat-s3c24xx/Kconfig
index b66fb3c..7ee4b82 100644
--- a/arch/arm/plat-s3c24xx/Kconfig
+++ b/arch/arm/plat-s3c24xx/Kconfig
@@ -46,4 +46,9 @@ config MACH_SMDK
help
Common machine code for SMDK2410 and SMDK2440
+config MACH_NEO1973
+ bool
+ help
+ Common machine code for Neo1973 hardware
+
endif
diff --git a/include/asm-arm/arch-s3c2410/gta01.h b/include/asm-arm/arch-s3c2410/gta01.h
new file mode 100644
index 0000000..1cc2099
--- /dev/null
+++ b/include/asm-arm/arch-s3c2410/gta01.h
@@ -0,0 +1,70 @@
+#ifndef _GTA01_H
+#define _GTA01_H
+
+#include <asm/arch/regs-gpio.h>
+#include <asm/arch/irqs.h>
+
+/* Different hardware revisions, passed in ATAG_REVISION by u-boot */
+#define GTA01v3_SYSTEM_REV 0x00000130
+#define GTA01v4_SYSTEM_REV 0x00000140
+#define GTA01Bv2_SYSTEM_REV 0x00000220
+#define GTA01Bv3_SYSTEM_REV 0x00000230
+#define GTA01Bv4_SYSTEM_REV 0x00000240
+
+/* Backlight */
+struct gta01bl_machinfo {
+ unsigned int default_intensity;
+ unsigned int max_intensity;
+ unsigned int limit_mask;
+};
+
+/* Definitions common to all revisions */
+#define GTA01_GPIO_BACKLIGHT S3C2410_GPB0
+#define GTA01_GPIO_GPS_PWRON S3C2410_GPB1
+#define GTA01_GPIO_MODEM_RST S3C2410_GPB6
+#define GTA01_GPIO_MODEM_ON S3C2410_GPB7
+#define GTA01_GPIO_LCD_RESET S3C2410_GPC6
+#define GTA01_GPIO_PMU_IRQ S3C2410_GPG8
+#define GTA01_GPIO_JACK_INSERT S3C2410_GPF4
+#define GTA01_GPIO_nSD_DETECT S3C2410_GPF5
+#define GTA01_GPIO_AUX_KEY S3C2410_GPF6
+#define GTA01_GPIO_HOLD_KEY S3C2410_GPF7
+#define GTA01_GPIO_VIBRATOR_ON S3C2410_GPG11
+
+#define GTA01_IRQ_MODEM IRQ_EINT1
+#define GTA01_IRQ_JACK_INSERT IRQ_EINT4
+#define GTA01_IRQ_nSD_DETECT IRQ_EINT5
+#define GTA01_IRQ_AUX_KEY IRQ_EINT6
+#define GTA01_IRQ_PCF50606 IRQ_EINT16
+
+/* GTA01v3 */
+#define GTA01v3_GPIO_nGSM_EN S3C2410_GPG9
+
+/* GTA01v4 */
+#define GTA01_GPIO_MODEM_DNLOAD S3C2410_GPG0
+
+/* GTA01Bv2 */
+#define GTA01Bv2_GPIO_nGSM_EN S3C2410_GPF2
+#define GTA01Bv2_GPIO_VIBRATOR_ON S3C2410_GPB10
+
+/* GTA01Bv3 */
+#define GTA01_GPIO_GPS_EN_3V3 S3C2410_GPG9
+
+#define GTA01_GPIO_SDMMC_ON S3C2410_GPB2
+#define GTA01_GPIO_BT_EN S3C2410_GPB5
+#define GTA01_GPIO_AB_DETECT S3C2410_GPB8
+#define GTA01_GPIO_USB_PULLUP S3C2410_GPB9
+#define GTA01_GPIO_USB_ATTACH S3C2410_GPB10
+
+#define GTA01_GPIO_GPS_EN_2V8 S3C2410_GPG9
+#define GTA01_GPIO_GPS_EN_3V S3C2410_GPG10
+#define GTA01_GPIO_GPS_RESET S3C2410_GPC0
+
+/* GTA01Bv4 */
+#define GTA01Bv4_GPIO_nNAND_WP S3C2410_GPA16
+#define GTA01Bv4_GPIO_VIBRATOR_ON S3C2410_GPB3
+#define GTA01Bv4_GPIO_PMU_IRQ S3C2410_GPG1
+
+#define GTA01Bv4_IRQ_PCF50606 IRQ_EINT9
+
+#endif /* _GTA01_H */
--
1.5.6.3

View file

@ -0,0 +1,748 @@
From 5b0814282e6878f7f2f07b98cc8b0128e7ea423d Mon Sep 17 00:00:00 2001
From: mokopatches <mokopatches@openmoko.org>
Date: Wed, 16 Jul 2008 14:44:48 +0100
Subject: [PATCH] gta01-jbt6k74.patch
This driver adds support for the SPI-based control interface of the LCM (LCD
Panel) found on the FIC GTA01 hardware.
The specific panel in this hardware is a TPO TD028TTEC1, but the driver should
be able to drive any other diplay based on the JBT6K74-AS controller ASIC.
Signed-off-by: Harald Welte <laforge@openmoko.org>
---
arch/arm/mach-s3c2410/Kconfig | 1 +
drivers/video/display/Kconfig | 11 +
drivers/video/display/Makefile | 1 +
drivers/video/display/jbt6k74.c | 678 +++++++++++++++++++++++++++++++++++++++
4 files changed, 691 insertions(+), 0 deletions(-)
create mode 100644 drivers/video/display/jbt6k74.c
diff --git a/arch/arm/mach-s3c2410/Kconfig b/arch/arm/mach-s3c2410/Kconfig
index 7e3a1a2..58519e6 100644
--- a/arch/arm/mach-s3c2410/Kconfig
+++ b/arch/arm/mach-s3c2410/Kconfig
@@ -114,6 +114,7 @@ config MACH_VR1000
config MACH_QT2410
bool "QT2410"
select CPU_S3C2410
+ select DISPLAY_JBT6K74
help
Say Y here if you are using the Armzone QT2410
diff --git a/drivers/video/display/Kconfig b/drivers/video/display/Kconfig
index f99af93..f0da483 100644
--- a/drivers/video/display/Kconfig
+++ b/drivers/video/display/Kconfig
@@ -21,4 +21,15 @@ config DISPLAY_SUPPORT
comment "Display hardware drivers"
depends on DISPLAY_SUPPORT
+config DISPLAY_JBT6K74
+ tristate "TPO JBT6K74-AS TFT display ASIC control interface"
+ depends on SPI_MASTER && SYSFS
+ help
+ SPI driver for the control interface of TFT panels containing
+ the TPO JBT6K74-AS controller ASIC, such as the TPO TD028TTEC1
+ TFT diplay module used in the FIC/OpenMoko Neo1973 GSM phones.
+
+ The control interface is required for display operation, as it
+ controls power management, display timing and gamma calibration.
+
endmenu
diff --git a/drivers/video/display/Makefile b/drivers/video/display/Makefile
index c0ea832..011b69d 100644
--- a/drivers/video/display/Makefile
+++ b/drivers/video/display/Makefile
@@ -3,4 +3,5 @@
display-objs := display-sysfs.o
obj-$(CONFIG_DISPLAY_SUPPORT) += display.o
+obj-$(CONFIG_DISPLAY_JBT6K74) += jbt6k74.o
diff --git a/drivers/video/display/jbt6k74.c b/drivers/video/display/jbt6k74.c
new file mode 100644
index 0000000..d021d7e
--- /dev/null
+++ b/drivers/video/display/jbt6k74.c
@@ -0,0 +1,678 @@
+/* Linux kernel driver for the tpo JBT6K74-AS LCM ASIC
+ *
+ * Copyright (C) 2006-2007 by OpenMoko, Inc.
+ * Author: Harald Welte <laforge@openmoko.org>,
+ * Stefan Schmidt <stefan@openmoko.org>
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+
+#include <linux/spi/spi.h>
+
+enum jbt_register {
+ JBT_REG_SLEEP_IN = 0x10,
+ JBT_REG_SLEEP_OUT = 0x11,
+
+ JBT_REG_DISPLAY_OFF = 0x28,
+ JBT_REG_DISPLAY_ON = 0x29,
+
+ JBT_REG_RGB_FORMAT = 0x3a,
+ JBT_REG_QUAD_RATE = 0x3b,
+
+ JBT_REG_POWER_ON_OFF = 0xb0,
+ JBT_REG_BOOSTER_OP = 0xb1,
+ JBT_REG_BOOSTER_MODE = 0xb2,
+ JBT_REG_BOOSTER_FREQ = 0xb3,
+ JBT_REG_OPAMP_SYSCLK = 0xb4,
+ JBT_REG_VSC_VOLTAGE = 0xb5,
+ JBT_REG_VCOM_VOLTAGE = 0xb6,
+ JBT_REG_EXT_DISPL = 0xb7,
+ JBT_REG_OUTPUT_CONTROL = 0xb8,
+ JBT_REG_DCCLK_DCEV = 0xb9,
+ JBT_REG_DISPLAY_MODE1 = 0xba,
+ JBT_REG_DISPLAY_MODE2 = 0xbb,
+ JBT_REG_DISPLAY_MODE = 0xbc,
+ JBT_REG_ASW_SLEW = 0xbd,
+ JBT_REG_DUMMY_DISPLAY = 0xbe,
+ JBT_REG_DRIVE_SYSTEM = 0xbf,
+
+ JBT_REG_SLEEP_OUT_FR_A = 0xc0,
+ JBT_REG_SLEEP_OUT_FR_B = 0xc1,
+ JBT_REG_SLEEP_OUT_FR_C = 0xc2,
+ JBT_REG_SLEEP_IN_LCCNT_D = 0xc3,
+ JBT_REG_SLEEP_IN_LCCNT_E = 0xc4,
+ JBT_REG_SLEEP_IN_LCCNT_F = 0xc5,
+ JBT_REG_SLEEP_IN_LCCNT_G = 0xc6,
+
+ JBT_REG_GAMMA1_FINE_1 = 0xc7,
+ JBT_REG_GAMMA1_FINE_2 = 0xc8,
+ JBT_REG_GAMMA1_INCLINATION = 0xc9,
+ JBT_REG_GAMMA1_BLUE_OFFSET = 0xca,
+
+ /* VGA */
+ JBT_REG_BLANK_CONTROL = 0xcf,
+ JBT_REG_BLANK_TH_TV = 0xd0,
+ JBT_REG_CKV_ON_OFF = 0xd1,
+ JBT_REG_CKV_1_2 = 0xd2,
+ JBT_REG_OEV_TIMING = 0xd3,
+ JBT_REG_ASW_TIMING_1 = 0xd4,
+ JBT_REG_ASW_TIMING_2 = 0xd5,
+
+ /* QVGA */
+ JBT_REG_BLANK_CONTROL_QVGA = 0xd6,
+ JBT_REG_BLANK_TH_TV_QVGA = 0xd7,
+ JBT_REG_CKV_ON_OFF_QVGA = 0xd8,
+ JBT_REG_CKV_1_2_QVGA = 0xd9,
+ JBT_REG_OEV_TIMING_QVGA = 0xde,
+ JBT_REG_ASW_TIMING_1_QVGA = 0xdf,
+ JBT_REG_ASW_TIMING_2_QVGA = 0xe0,
+
+
+ JBT_REG_HCLOCK_VGA = 0xec,
+ JBT_REG_HCLOCK_QVGA = 0xed,
+
+};
+
+enum jbt_state {
+ JBT_STATE_DEEP_STANDBY,
+ JBT_STATE_SLEEP,
+ JBT_STATE_NORMAL,
+ JBT_STATE_QVGA_NORMAL,
+};
+
+static const char *jbt_state_names[] = {
+ [JBT_STATE_DEEP_STANDBY] = "deep-standby",
+ [JBT_STATE_SLEEP] = "sleep",
+ [JBT_STATE_NORMAL] = "normal",
+ [JBT_STATE_QVGA_NORMAL] = "qvga-normal",
+};
+
+struct jbt_info {
+ enum jbt_state state, last_state;
+ struct spi_device *spi_dev;
+ struct mutex lock; /* protects tx_buf and reg_cache */
+ u16 tx_buf[8];
+ u16 reg_cache[0xEE];
+};
+
+#define JBT_COMMAND 0x000
+#define JBT_DATA 0x100
+
+static int jbt_reg_write_nodata(struct jbt_info *jbt, u8 reg)
+{
+ int rc;
+
+ mutex_lock(&jbt->lock);
+
+ jbt->tx_buf[0] = JBT_COMMAND | reg;
+ rc = spi_write(jbt->spi_dev, (u8 *)jbt->tx_buf,
+ 1*sizeof(u16));
+ if (rc == 0)
+ jbt->reg_cache[reg] = 0;
+
+ mutex_unlock(&jbt->lock);
+
+ return rc;
+}
+
+
+static int jbt_reg_write(struct jbt_info *jbt, u8 reg, u8 data)
+{
+ int rc;
+
+ mutex_lock(&jbt->lock);
+
+ jbt->tx_buf[0] = JBT_COMMAND | reg;
+ jbt->tx_buf[1] = JBT_DATA | data;
+ rc = spi_write(jbt->spi_dev, (u8 *)jbt->tx_buf,
+ 2*sizeof(u16));
+ if (rc == 0)
+ jbt->reg_cache[reg] = data;
+
+ mutex_unlock(&jbt->lock);
+
+ return rc;
+}
+
+static int jbt_reg_write16(struct jbt_info *jbt, u8 reg, u16 data)
+{
+ int rc;
+
+ mutex_lock(&jbt->lock);
+
+ jbt->tx_buf[0] = JBT_COMMAND | reg;
+ jbt->tx_buf[1] = JBT_DATA | (data >> 8);
+ jbt->tx_buf[2] = JBT_DATA | (data & 0xff);
+
+ rc = spi_write(jbt->spi_dev, (u8 *)jbt->tx_buf,
+ 3*sizeof(u16));
+ if (rc == 0)
+ jbt->reg_cache[reg] = data;
+
+ mutex_unlock(&jbt->lock);
+
+ return rc;
+}
+
+static int jbt_init_regs(struct jbt_info *jbt, int qvga)
+{
+ int rc;
+
+ dev_dbg(&jbt->spi_dev->dev, "entering %cVGA mode\n", qvga ? 'Q' : ' ');
+
+ rc = jbt_reg_write(jbt, JBT_REG_DISPLAY_MODE1, 0x01);
+ rc |= jbt_reg_write(jbt, JBT_REG_DISPLAY_MODE2, 0x00);
+ rc |= jbt_reg_write(jbt, JBT_REG_RGB_FORMAT, 0x60);
+ rc |= jbt_reg_write(jbt, JBT_REG_DRIVE_SYSTEM, 0x10);
+ rc |= jbt_reg_write(jbt, JBT_REG_BOOSTER_OP, 0x56);
+ rc |= jbt_reg_write(jbt, JBT_REG_BOOSTER_MODE, 0x33);
+ rc |= jbt_reg_write(jbt, JBT_REG_BOOSTER_FREQ, 0x11);
+ rc |= jbt_reg_write(jbt, JBT_REG_OPAMP_SYSCLK, 0x02);
+ rc |= jbt_reg_write(jbt, JBT_REG_VSC_VOLTAGE, 0x2b);
+ rc |= jbt_reg_write(jbt, JBT_REG_VCOM_VOLTAGE, 0x40);
+ rc |= jbt_reg_write(jbt, JBT_REG_EXT_DISPL, 0x03);
+ rc |= jbt_reg_write(jbt, JBT_REG_DCCLK_DCEV, 0x04);
+ /*
+ * default of 0x02 in JBT_REG_ASW_SLEW responsible for 72Hz requirement
+ * to avoid red / blue flicker
+ */
+ rc |= jbt_reg_write(jbt, JBT_REG_ASW_SLEW, 0x04);
+ rc |= jbt_reg_write(jbt, JBT_REG_DUMMY_DISPLAY, 0x00);
+
+ rc |= jbt_reg_write(jbt, JBT_REG_SLEEP_OUT_FR_A, 0x11);
+ rc |= jbt_reg_write(jbt, JBT_REG_SLEEP_OUT_FR_B, 0x11);
+ rc |= jbt_reg_write(jbt, JBT_REG_SLEEP_OUT_FR_C, 0x11);
+ rc |= jbt_reg_write16(jbt, JBT_REG_SLEEP_IN_LCCNT_D, 0x2040);
+ rc |= jbt_reg_write16(jbt, JBT_REG_SLEEP_IN_LCCNT_E, 0x60c0);
+ rc |= jbt_reg_write16(jbt, JBT_REG_SLEEP_IN_LCCNT_F, 0x1020);
+ rc |= jbt_reg_write16(jbt, JBT_REG_SLEEP_IN_LCCNT_G, 0x60c0);
+
+ rc |= jbt_reg_write16(jbt, JBT_REG_GAMMA1_FINE_1, 0x5533);
+ rc |= jbt_reg_write(jbt, JBT_REG_GAMMA1_FINE_2, 0x00);
+ rc |= jbt_reg_write(jbt, JBT_REG_GAMMA1_INCLINATION, 0x00);
+ rc |= jbt_reg_write(jbt, JBT_REG_GAMMA1_BLUE_OFFSET, 0x00);
+
+ if (!qvga) {
+ rc |= jbt_reg_write16(jbt, JBT_REG_HCLOCK_VGA, 0x1f0);
+ rc |= jbt_reg_write(jbt, JBT_REG_BLANK_CONTROL, 0x02);
+ rc |= jbt_reg_write16(jbt, JBT_REG_BLANK_TH_TV, 0x0804);
+
+ rc |= jbt_reg_write(jbt, JBT_REG_CKV_ON_OFF, 0x01);
+ rc |= jbt_reg_write16(jbt, JBT_REG_CKV_1_2, 0x0000);
+
+ rc |= jbt_reg_write16(jbt, JBT_REG_OEV_TIMING, 0x0d0e);
+ rc |= jbt_reg_write16(jbt, JBT_REG_ASW_TIMING_1, 0x11a4);
+ rc |= jbt_reg_write(jbt, JBT_REG_ASW_TIMING_2, 0x0e);
+ } else {
+ rc |= jbt_reg_write16(jbt, JBT_REG_HCLOCK_QVGA, 0x00ff);
+ rc |= jbt_reg_write(jbt, JBT_REG_BLANK_CONTROL_QVGA, 0x02);
+ rc |= jbt_reg_write16(jbt, JBT_REG_BLANK_TH_TV_QVGA, 0x0804);
+
+ rc |= jbt_reg_write(jbt, JBT_REG_CKV_ON_OFF_QVGA, 0x01);
+ rc |= jbt_reg_write16(jbt, JBT_REG_CKV_1_2_QVGA, 0x0008);
+
+ rc |= jbt_reg_write16(jbt, JBT_REG_OEV_TIMING_QVGA, 0x050a);
+ rc |= jbt_reg_write16(jbt, JBT_REG_ASW_TIMING_1_QVGA, 0x0a19);
+ rc |= jbt_reg_write(jbt, JBT_REG_ASW_TIMING_2_QVGA, 0x0a);
+ }
+
+ return rc ? -EIO : 0;
+}
+
+static int standby_to_sleep(struct jbt_info *jbt)
+{
+ int rc;
+
+ /* three times command zero */
+ rc = jbt_reg_write_nodata(jbt, 0x00);
+ mdelay(1);
+ rc |= jbt_reg_write_nodata(jbt, 0x00);
+ mdelay(1);
+ rc |= jbt_reg_write_nodata(jbt, 0x00);
+ mdelay(1);
+
+ /* deep standby out */
+ rc |= jbt_reg_write(jbt, JBT_REG_POWER_ON_OFF, 0x17);
+
+ return rc ? -EIO : 0;
+}
+
+static int sleep_to_normal(struct jbt_info *jbt)
+{
+ int rc;
+
+ /* RGB I/F on, RAM wirte off, QVGA through, SIGCON enable */
+ rc = jbt_reg_write(jbt, JBT_REG_DISPLAY_MODE, 0x80);
+
+ /* Quad mode off */
+ rc |= jbt_reg_write(jbt, JBT_REG_QUAD_RATE, 0x00);
+
+ /* AVDD on, XVDD on */
+ rc |= jbt_reg_write(jbt, JBT_REG_POWER_ON_OFF, 0x16);
+
+ /* Output control */
+ rc |= jbt_reg_write16(jbt, JBT_REG_OUTPUT_CONTROL, 0xfff9);
+
+ /* Sleep mode off */
+ rc |= jbt_reg_write_nodata(jbt, JBT_REG_SLEEP_OUT);
+
+ /* initialize register set */
+ rc |= jbt_init_regs(jbt, 0);
+
+ return rc ? -EIO : 0;
+}
+
+static int sleep_to_qvga_normal(struct jbt_info *jbt)
+{
+ int rc;
+
+ /* RGB I/F on, RAM wirte off, QVGA through, SIGCON enable */
+ rc = jbt_reg_write(jbt, JBT_REG_DISPLAY_MODE, 0x81);
+
+ /* Quad mode on */
+ rc |= jbt_reg_write(jbt, JBT_REG_QUAD_RATE, 0x22);
+
+ /* AVDD on, XVDD on */
+ rc |= jbt_reg_write(jbt, JBT_REG_POWER_ON_OFF, 0x16);
+
+ /* Output control */
+ rc |= jbt_reg_write16(jbt, JBT_REG_OUTPUT_CONTROL, 0xfff9);
+
+ /* Sleep mode off */
+ rc |= jbt_reg_write_nodata(jbt, JBT_REG_SLEEP_OUT);
+
+ /* initialize register set for qvga*/
+ rc |= jbt_init_regs(jbt, 1);
+
+ return rc ? -EIO : 0;
+}
+
+static int normal_to_sleep(struct jbt_info *jbt)
+{
+ int rc;
+
+ rc = jbt_reg_write_nodata(jbt, JBT_REG_DISPLAY_OFF);
+ rc |= jbt_reg_write16(jbt, JBT_REG_OUTPUT_CONTROL, 0x8002);
+ rc |= jbt_reg_write_nodata(jbt, JBT_REG_SLEEP_IN);
+
+ return rc ? -EIO : 0;
+}
+
+static int sleep_to_standby(struct jbt_info *jbt)
+{
+ return jbt_reg_write(jbt, JBT_REG_POWER_ON_OFF, 0x00);
+}
+
+/* frontend function */
+int jbt6k74_enter_state(struct jbt_info *jbt, enum jbt_state new_state)
+{
+ int rc = -EINVAL;
+
+ dev_dbg(&jbt->spi_dev->dev, "entering (old_state=%u, "
+ "new_state=%u)\n", jbt->state, new_state);
+
+ switch (jbt->state) {
+ case JBT_STATE_DEEP_STANDBY:
+ switch (new_state) {
+ case JBT_STATE_DEEP_STANDBY:
+ rc = 0;
+ break;
+ case JBT_STATE_SLEEP:
+ rc = standby_to_sleep(jbt);
+ break;
+ case JBT_STATE_NORMAL:
+ /* first transition into sleep */
+ rc = standby_to_sleep(jbt);
+ /* then transition into normal */
+ rc |= sleep_to_normal(jbt);
+ break;
+ case JBT_STATE_QVGA_NORMAL:
+ /* first transition into sleep */
+ rc = standby_to_sleep(jbt);
+ /* then transition into normal */
+ rc |= sleep_to_qvga_normal(jbt);
+ break;
+ }
+ break;
+ case JBT_STATE_SLEEP:
+ switch (new_state) {
+ case JBT_STATE_SLEEP:
+ rc = 0;
+ break;
+ case JBT_STATE_DEEP_STANDBY:
+ rc = sleep_to_standby(jbt);
+ break;
+ case JBT_STATE_NORMAL:
+ rc = sleep_to_normal(jbt);
+ break;
+ case JBT_STATE_QVGA_NORMAL:
+ rc = sleep_to_qvga_normal(jbt);
+ break;
+ }
+ break;
+ case JBT_STATE_NORMAL:
+ switch (new_state) {
+ case JBT_STATE_NORMAL:
+ rc = 0;
+ break;
+ case JBT_STATE_DEEP_STANDBY:
+ /* first transition into sleep */
+ rc = normal_to_sleep(jbt);
+ /* then transition into deep standby */
+ rc |= sleep_to_standby(jbt);
+ break;
+ case JBT_STATE_SLEEP:
+ rc = normal_to_sleep(jbt);
+ break;
+ case JBT_STATE_QVGA_NORMAL:
+ /* first transition into sleep */
+ rc = normal_to_sleep(jbt);
+ /* second transition into deep standby */
+ rc |= sleep_to_standby(jbt);
+ /* third transition into sleep */
+ rc |= standby_to_sleep(jbt);
+ /* fourth transition into normal */
+ rc |= sleep_to_qvga_normal(jbt);
+ break;
+ }
+ break;
+ case JBT_STATE_QVGA_NORMAL:
+ switch (new_state) {
+ case JBT_STATE_QVGA_NORMAL:
+ rc = 0;
+ break;
+ case JBT_STATE_DEEP_STANDBY:
+ /* first transition into sleep */
+ rc = normal_to_sleep(jbt);
+ /* then transition into deep standby */
+ rc |= sleep_to_standby(jbt);
+ break;
+ case JBT_STATE_SLEEP:
+ rc = normal_to_sleep(jbt);
+ break;
+ case JBT_STATE_NORMAL:
+ /* first transition into sleep */
+ rc = normal_to_sleep(jbt);
+ /* second transition into deep standby */
+ rc |= sleep_to_standby(jbt);
+ /* third transition into sleep */
+ rc |= standby_to_sleep(jbt);
+ /* fourth transition into normal */
+ rc |= sleep_to_normal(jbt);
+ break;
+ }
+ break;
+ }
+ if (rc == 0)
+ jbt->state = new_state;
+
+ return rc;
+}
+EXPORT_SYMBOL_GPL(jbt6k74_enter_state);
+
+int jbt6k74_display_onoff(struct jbt_info *jbt, int on)
+{
+ if (on)
+ return jbt_reg_write_nodata(jbt, JBT_REG_DISPLAY_ON);
+ else
+ return jbt_reg_write_nodata(jbt, JBT_REG_DISPLAY_OFF);
+}
+EXPORT_SYMBOL_GPL(jbt6k74_display_onoff);
+
+static ssize_t state_read(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct jbt_info *jbt = dev_get_drvdata(dev);
+
+ if (jbt->state >= ARRAY_SIZE(jbt_state_names))
+ return -EIO;
+
+ return sprintf(buf, "%s\n", jbt_state_names[jbt->state]);
+}
+
+static ssize_t state_write(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct jbt_info *jbt = dev_get_drvdata(dev);
+ int i, rc;
+
+ for (i = 0; i < ARRAY_SIZE(jbt_state_names); i++) {
+ if (!strncmp(buf, jbt_state_names[i],
+ strlen(jbt_state_names[i]))) {
+ rc = jbt6k74_enter_state(jbt, i);
+ if (rc)
+ return rc;
+ switch (i) {
+ case JBT_STATE_NORMAL:
+ case JBT_STATE_QVGA_NORMAL:
+ /* Enable display again after deep-standby */
+ rc = jbt6k74_display_onoff(jbt, 1);
+ if (rc)
+ return rc;
+ break;
+ default:
+ break;
+ }
+ return count;
+ }
+ }
+
+ return -EINVAL;
+}
+
+static DEVICE_ATTR(state, 0644, state_read, state_write);
+
+static int reg_by_string(const char *name)
+{
+ if (!strcmp(name, "gamma_fine1"))
+ return JBT_REG_GAMMA1_FINE_1;
+ else if (!strcmp(name, "gamma_fine2"))
+ return JBT_REG_GAMMA1_FINE_2;
+ else if (!strcmp(name, "gamma_inclination"))
+ return JBT_REG_GAMMA1_INCLINATION;
+ else
+ return JBT_REG_GAMMA1_BLUE_OFFSET;
+}
+
+static ssize_t gamma_read(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct jbt_info *jbt = dev_get_drvdata(dev);
+ int reg = reg_by_string(attr->attr.name);
+ u16 val;
+
+ mutex_lock(&jbt->lock);
+ val = jbt->reg_cache[reg];
+ mutex_unlock(&jbt->lock);
+
+ return sprintf(buf, "0x%04x\n", val);
+}
+
+static ssize_t gamma_write(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct jbt_info *jbt = dev_get_drvdata(dev);
+ int reg = reg_by_string(attr->attr.name);
+ unsigned long val = simple_strtoul(buf, NULL, 10);
+
+ jbt_reg_write(jbt, reg, val & 0xff);
+
+ return count;
+}
+
+static DEVICE_ATTR(gamma_fine1, 0644, gamma_read, gamma_write);
+static DEVICE_ATTR(gamma_fine2, 0644, gamma_read, gamma_write);
+static DEVICE_ATTR(gamma_inclination, 0644, gamma_read, gamma_write);
+static DEVICE_ATTR(gamma_blue_offset, 0644, gamma_read, gamma_write);
+
+static struct attribute *jbt_sysfs_entries[] = {
+ &dev_attr_state.attr,
+ &dev_attr_gamma_fine1.attr,
+ &dev_attr_gamma_fine2.attr,
+ &dev_attr_gamma_inclination.attr,
+ &dev_attr_gamma_blue_offset.attr,
+ NULL,
+};
+
+static struct attribute_group jbt_attr_group = {
+ .name = NULL,
+ .attrs = jbt_sysfs_entries,
+};
+
+/* linux device model infrastructure */
+
+static int __devinit jbt_probe(struct spi_device *spi)
+{
+ int rc;
+ struct jbt_info *jbt;
+
+ /* the controller doesn't have a MISO pin; we can't do detection */
+
+ spi->mode = SPI_CPOL | SPI_CPHA;
+ spi->bits_per_word = 9;
+
+ rc = spi_setup(spi);
+ if (rc < 0) {
+ dev_err(&spi->dev,
+ "error during spi_setup of jbt6k74 driver\n");
+ return rc;
+ }
+
+ jbt = kzalloc(sizeof(*jbt), GFP_KERNEL);
+ if (!jbt)
+ return -ENOMEM;
+
+ jbt->spi_dev = spi;
+ jbt->state = JBT_STATE_DEEP_STANDBY;
+ mutex_init(&jbt->lock);
+
+ dev_set_drvdata(&spi->dev, jbt);
+
+ rc = jbt6k74_enter_state(jbt, JBT_STATE_NORMAL);
+ if (rc < 0) {
+ dev_err(&spi->dev, "cannot enter NORMAL state\n");
+ goto err_free_drvdata;
+ }
+
+ rc = jbt6k74_display_onoff(jbt, 1);
+ if (rc < 0) {
+ dev_err(&spi->dev, "cannot switch display on\n");
+ goto err_standby;
+ }
+
+ rc = sysfs_create_group(&spi->dev.kobj, &jbt_attr_group);
+ if (rc < 0) {
+ dev_err(&spi->dev, "cannot create sysfs group\n");
+ goto err_off;
+ }
+
+ return 0;
+
+err_off:
+ jbt6k74_display_onoff(jbt, 0);
+err_standby:
+ jbt6k74_enter_state(jbt, JBT_STATE_DEEP_STANDBY);
+err_free_drvdata:
+ dev_set_drvdata(&spi->dev, NULL);
+ kfree(jbt);
+
+ return rc;
+}
+
+static int __devexit jbt_remove(struct spi_device *spi)
+{
+ struct jbt_info *jbt = dev_get_drvdata(&spi->dev);
+
+ /* We don't want to switch off the display in case the user
+ * accidentially onloads the module (whose use count normally is 0) */
+
+ sysfs_remove_group(&spi->dev.kobj, &jbt_attr_group);
+ dev_set_drvdata(&spi->dev, NULL);
+ kfree(jbt);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int jbt_suspend(struct spi_device *spi, pm_message_t state)
+{
+ struct jbt_info *jbt = dev_get_drvdata(&spi->dev);
+
+ /* Save mode for resume */
+ jbt->last_state = jbt->state;
+ jbt6k74_enter_state(jbt, JBT_STATE_DEEP_STANDBY);
+
+ return 0;
+}
+
+static int jbt_resume(struct spi_device *spi)
+{
+ struct jbt_info *jbt = dev_get_drvdata(&spi->dev);
+
+ jbt6k74_enter_state(jbt, jbt->last_state);
+
+ switch (jbt->last_state) {
+ case JBT_STATE_NORMAL:
+ case JBT_STATE_QVGA_NORMAL:
+ jbt6k74_display_onoff(jbt, 1);
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+#else
+#define jbt_suspend NULL
+#define jbt_resume NULL
+#endif
+
+static struct spi_driver jbt6k74_driver = {
+ .driver = {
+ .name = "jbt6k74",
+ .owner = THIS_MODULE,
+ },
+
+ .probe = jbt_probe,
+ .remove = __devexit_p(jbt_remove),
+ .suspend = jbt_suspend,
+ .resume = jbt_resume,
+};
+
+static int __init jbt_init(void)
+{
+ return spi_register_driver(&jbt6k74_driver);
+}
+
+static void __exit jbt_exit(void)
+{
+ spi_unregister_driver(&jbt6k74_driver);
+}
+
+MODULE_DESCRIPTION("SPI driver for tpo JBT6K74-AS LCM control interface");
+MODULE_AUTHOR("Harald Welte <laforge@openmoko.org>");
+MODULE_LICENSE("GPL");
+
+module_init(jbt_init);
+module_exit(jbt_exit);
--
1.5.6.3

View file

@ -0,0 +1,298 @@
From db36b757a45cf8d9088727d975d93917021b1171 Mon Sep 17 00:00:00 2001
From: mokopatches <mokopatches@openmoko.org>
Date: Wed, 16 Jul 2008 14:44:48 +0100
Subject: [PATCH] gta01-inputdevice.patch
This provides support for the GTA01 keyboard
Signed-off-by: Harald Welte <laforge@openmoko.org>
---
drivers/input/keyboard/Kconfig | 12 ++
drivers/input/keyboard/Makefile | 1 +
drivers/input/keyboard/neo1973kbd.c | 242 +++++++++++++++++++++++++++++++++++
3 files changed, 255 insertions(+), 0 deletions(-)
create mode 100644 drivers/input/keyboard/neo1973kbd.c
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
index efd70a9..b8ecca9 100644
--- a/drivers/input/keyboard/Kconfig
+++ b/drivers/input/keyboard/Kconfig
@@ -323,4 +323,16 @@ config KEYBOARD_SH_KEYSC
To compile this driver as a module, choose M here: the
module will be called sh_keysc.
+config KEYBOARD_NEO1973
+ tristate "FIC Neo1973 buttons"
+ depends on MACH_NEO1973
+ default y
+ help
+ Say Y here to enable the buttons on the FIC Neo1973
+ GSM phone.
+
+ To compile this driver as a module, choose M here: the
+ module will be called neo1973kbd.
+
+
endif
diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile
index 0edc8f2..b3aa339 100644
--- a/drivers/input/keyboard/Makefile
+++ b/drivers/input/keyboard/Makefile
@@ -14,6 +14,7 @@ obj-$(CONFIG_KEYBOARD_LOCOMO) += locomokbd.o
obj-$(CONFIG_KEYBOARD_NEWTON) += newtonkbd.o
obj-$(CONFIG_KEYBOARD_STOWAWAY) += stowaway.o
obj-$(CONFIG_KEYBOARD_CORGI) += corgikbd.o
+obj-$(CONFIG_KEYBOARD_NEO1973) += neo1973kbd.o
obj-$(CONFIG_KEYBOARD_SPITZ) += spitzkbd.o
obj-$(CONFIG_KEYBOARD_TOSA) += tosakbd.o
obj-$(CONFIG_KEYBOARD_HIL) += hil_kbd.o
diff --git a/drivers/input/keyboard/neo1973kbd.c b/drivers/input/keyboard/neo1973kbd.c
new file mode 100644
index 0000000..917d5ae
--- /dev/null
+++ b/drivers/input/keyboard/neo1973kbd.c
@@ -0,0 +1,242 @@
+/*
+ * Keyboard driver for FIC Neo1973 GSM phone
+ *
+ * (C) 2006-2007 by OpenMoko, Inc.
+ * Author: Harald Welte <laforge@openmoko.org>
+ * All rights reserved.
+ *
+ * inspired by corkgbd.c by Richard Purdie
+ *
+ * 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/delay.h>
+#include <linux/platform_device.h>
+#include <linux/init.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/jiffies.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+
+#include <asm/hardware.h>
+#include <asm/arch/gta01.h>
+#include <asm/mach-types.h>
+
+struct neo1973kbd {
+ struct input_dev *input;
+ unsigned int suspended;
+ unsigned long suspend_jiffies;
+};
+
+static irqreturn_t neo1973kbd_aux_irq(int irq, void *dev_id)
+{
+ struct neo1973kbd *neo1973kbd_data = dev_id;
+
+ /* FIXME: use GPIO from platform_dev resources */
+ if (s3c2410_gpio_getpin(GTA01_GPIO_AUX_KEY))
+ input_report_key(neo1973kbd_data->input, KEY_PHONE, 0);
+ else
+ input_report_key(neo1973kbd_data->input, KEY_PHONE, 1);
+
+ input_sync(neo1973kbd_data->input);
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t neo1973kbd_hold_irq(int irq, void *dev_id)
+{
+ struct neo1973kbd *neo1973kbd_data = dev_id;
+
+ /* FIXME: use GPIO from platform_dev resources */
+ if (s3c2410_gpio_getpin(GTA01_GPIO_HOLD_KEY))
+ input_report_key(neo1973kbd_data->input, KEY_PAUSE, 1);
+ else
+ input_report_key(neo1973kbd_data->input, KEY_PAUSE, 0);
+
+ input_sync(neo1973kbd_data->input);
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t neo1973kbd_headphone_irq(int irq, void *dev_id)
+{
+ struct neo1973kbd *neo1973kbd_data = dev_id;
+
+ /* FIXME: use GPIO from platform_dev resources */
+ if (s3c2410_gpio_getpin(GTA01_GPIO_JACK_INSERT))
+ input_report_switch(neo1973kbd_data->input,
+ SW_HEADPHONE_INSERT, 1);
+ else
+ input_report_switch(neo1973kbd_data->input,
+ SW_HEADPHONE_INSERT, 0);
+
+ input_sync(neo1973kbd_data->input);
+
+ return IRQ_HANDLED;
+}
+
+#ifdef CONFIG_PM
+static int neo1973kbd_suspend(struct platform_device *dev, pm_message_t state)
+{
+ struct neo1973kbd *neo1973kbd = platform_get_drvdata(dev);
+
+ neo1973kbd->suspended = 1;
+
+ return 0;
+}
+
+static int neo1973kbd_resume(struct platform_device *dev)
+{
+ struct neo1973kbd *neo1973kbd = platform_get_drvdata(dev);
+
+ neo1973kbd->suspended = 0;
+
+ return 0;
+}
+#else
+#define neo1973kbd_suspend NULL
+#define neo1973kbd_resume NULL
+#endif
+
+static int neo1973kbd_probe(struct platform_device *pdev)
+{
+ struct neo1973kbd *neo1973kbd;
+ struct input_dev *input_dev;
+ int rc, irq_aux, irq_hold, irq_jack;
+
+ neo1973kbd = kzalloc(sizeof(struct neo1973kbd), GFP_KERNEL);
+ input_dev = input_allocate_device();
+ if (!neo1973kbd || !input_dev) {
+ kfree(neo1973kbd);
+ input_free_device(input_dev);
+ return -ENOMEM;
+ }
+
+ if (pdev->resource[0].flags != 0)
+ return -EINVAL;
+
+ irq_aux = s3c2410_gpio_getirq(pdev->resource[0].start);
+ if (irq_aux < 0)
+ return -EINVAL;
+
+ irq_hold = s3c2410_gpio_getirq(pdev->resource[1].start);
+ if (irq_hold < 0)
+ return -EINVAL;
+
+ irq_jack = s3c2410_gpio_getirq(pdev->resource[2].start);
+ if (irq_jack < 0)
+ return -EINVAL;
+
+ platform_set_drvdata(pdev, neo1973kbd);
+
+ neo1973kbd->input = input_dev;
+
+ input_dev->name = "Neo1973 Buttons";
+ input_dev->phys = "neo1973kbd/input0";
+ input_dev->id.bustype = BUS_HOST;
+ input_dev->id.vendor = 0x0001;
+ input_dev->id.product = 0x0001;
+ input_dev->id.version = 0x0100;
+ input_dev->cdev.dev = &pdev->dev;
+ input_dev->private = neo1973kbd;
+
+ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_SW);
+ set_bit(SW_HEADPHONE_INSERT, input_dev->swbit);
+ set_bit(KEY_PHONE, input_dev->keybit);
+ set_bit(KEY_PAUSE, input_dev->keybit);
+
+ rc = input_register_device(neo1973kbd->input);
+ if (rc)
+ goto out_register;
+
+ if (request_irq(irq_aux, neo1973kbd_aux_irq, IRQF_DISABLED |
+ IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
+ "Neo1973 AUX button", neo1973kbd)) {
+ dev_err(&pdev->dev, "Can't get IRQ %u\n", irq_aux);
+ goto out_aux;
+ }
+
+ /*
+ * GTA01 revisions before Bv4 can't be resumed by the PMU, so we use
+ * resume by AUX.
+ */
+ if (machine_is_neo1973_gta01())
+ enable_irq_wake(irq_aux);
+
+ if (request_irq(irq_hold, neo1973kbd_hold_irq, IRQF_DISABLED |
+ IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
+ "Neo1973 HOLD button", neo1973kbd)) {
+ dev_err(&pdev->dev, "Can't get IRQ %u\n", irq_hold);
+ goto out_hold;
+ }
+
+ if (request_irq(irq_jack, neo1973kbd_headphone_irq, IRQF_DISABLED |
+ IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
+ "Neo1973 Headphone Jack", neo1973kbd)) {
+ dev_err(&pdev->dev, "Can't get IRQ %u\n", irq_jack);
+ goto out_jack;
+ }
+ enable_irq_wake(irq_jack);
+
+ return 0;
+
+out_jack:
+ free_irq(irq_hold, neo1973kbd);
+out_hold:
+ free_irq(irq_aux, neo1973kbd);
+out_aux:
+ input_unregister_device(neo1973kbd->input);
+out_register:
+ input_free_device(neo1973kbd->input);
+ platform_set_drvdata(pdev, NULL);
+ kfree(neo1973kbd);
+
+ return -ENODEV;
+}
+
+static int neo1973kbd_remove(struct platform_device *pdev)
+{
+ struct neo1973kbd *neo1973kbd = platform_get_drvdata(pdev);
+
+ free_irq(s3c2410_gpio_getirq(pdev->resource[2].start), neo1973kbd);
+ free_irq(s3c2410_gpio_getirq(pdev->resource[1].start), neo1973kbd);
+ free_irq(s3c2410_gpio_getirq(pdev->resource[0].start), neo1973kbd);
+
+ input_unregister_device(neo1973kbd->input);
+ input_free_device(neo1973kbd->input);
+ platform_set_drvdata(pdev, NULL);
+ kfree(neo1973kbd);
+
+ return 0;
+}
+
+static struct platform_driver neo1973kbd_driver = {
+ .probe = neo1973kbd_probe,
+ .remove = neo1973kbd_remove,
+ .suspend = neo1973kbd_suspend,
+ .resume = neo1973kbd_resume,
+ .driver = {
+ .name = "neo1973-button",
+ },
+};
+
+static int __devinit neo1973kbd_init(void)
+{
+ return platform_driver_register(&neo1973kbd_driver);
+}
+
+static void __exit neo1973kbd_exit(void)
+{
+ platform_driver_unregister(&neo1973kbd_driver);
+}
+
+module_init(neo1973kbd_init);
+module_exit(neo1973kbd_exit);
+
+MODULE_AUTHOR("Harald Welte <laforge@openmoko.org>");
+MODULE_DESCRIPTION("FIC Neo1973 buttons input driver");
+MODULE_LICENSE("GPL");
--
1.5.6.3

View file

@ -0,0 +1,976 @@
From 0739383d85822b93831803abb207794c16eedd79 Mon Sep 17 00:00:00 2001
From: mokopatches <mokopatches@openmoko.org>
Date: Wed, 16 Jul 2008 14:44:48 +0100
Subject: [PATCH] gta01-power_control.patch
[PATCH] Neo1973 GPS / GSM / Bluetooth power control via sysfs
Signed-off-by: Harald Welte <laforge@openmoko.org>
---
arch/arm/plat-s3c24xx/Makefile | 1 +
arch/arm/plat-s3c24xx/neo1973_pm_bt.c | 152 +++++++++
arch/arm/plat-s3c24xx/neo1973_pm_gps.c | 560 ++++++++++++++++++++++++++++++++
arch/arm/plat-s3c24xx/neo1973_pm_gsm.c | 217 ++++++++++++
4 files changed, 930 insertions(+), 0 deletions(-)
create mode 100644 arch/arm/plat-s3c24xx/neo1973_pm_bt.c
create mode 100644 arch/arm/plat-s3c24xx/neo1973_pm_gps.c
create mode 100644 arch/arm/plat-s3c24xx/neo1973_pm_gsm.c
diff --git a/arch/arm/plat-s3c24xx/Makefile b/arch/arm/plat-s3c24xx/Makefile
index 131d202..6f43aca 100644
--- a/arch/arm/plat-s3c24xx/Makefile
+++ b/arch/arm/plat-s3c24xx/Makefile
@@ -29,3 +29,4 @@ obj-$(CONFIG_PM) += pm.o
obj-$(CONFIG_PM) += sleep.o
obj-$(CONFIG_S3C2410_DMA) += dma.o
obj-$(CONFIG_MACH_SMDK) += common-smdk.o
+obj-$(CONFIG_MACH_NEO1973) += neo1973_pm_gsm.o neo1973_pm_gps.o neo1973_pm_bt.o
diff --git a/arch/arm/plat-s3c24xx/neo1973_pm_bt.c b/arch/arm/plat-s3c24xx/neo1973_pm_bt.c
new file mode 100644
index 0000000..b1af441
--- /dev/null
+++ b/arch/arm/plat-s3c24xx/neo1973_pm_bt.c
@@ -0,0 +1,152 @@
+/*
+ * Bluetooth PM code for the FIC Neo1973 GSM Phone
+ *
+ * (C) 2007 by OpenMoko Inc.
+ * Author: Harald Welte <laforge@openmoko.org>
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+
+#include <linux/pcf50606.h>
+
+#include <asm/hardware.h>
+#include <asm/arch/gta01.h>
+
+#define DRVMSG "FIC Neo1973 Bluetooth Power Management"
+
+static ssize_t bt_read(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ if (!strcmp(attr->attr.name, "power_on")) {
+ if (pcf50606_onoff_get(pcf50606_global,
+ PCF50606_REGULATOR_D1REG) &&
+ pcf50606_voltage_get(pcf50606_global,
+ PCF50606_REGULATOR_D1REG) == 3100)
+ goto out_1;
+ } else if (!strcmp(attr->attr.name, "reset")) {
+ if (s3c2410_gpio_getpin(GTA01_GPIO_BT_EN) == 0)
+ goto out_1;
+ }
+
+ return strlcpy(buf, "0\n", 3);
+out_1:
+ return strlcpy(buf, "1\n", 3);
+}
+
+static ssize_t bt_write(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned long on = simple_strtoul(buf, NULL, 10);
+
+ if (!strcmp(attr->attr.name, "power_on")) {
+ /* if we are powering up, assert reset, then power, then
+ * release reset */
+ if (on) {
+ s3c2410_gpio_setpin(GTA01_GPIO_BT_EN, 0);
+ pcf50606_voltage_set(pcf50606_global,
+ PCF50606_REGULATOR_D1REG,
+ 3100);
+ }
+ pcf50606_onoff_set(pcf50606_global,
+ PCF50606_REGULATOR_D1REG, on);
+ s3c2410_gpio_setpin(GTA01_GPIO_BT_EN, on);
+ } else if (!strcmp(attr->attr.name, "reset")) {
+ /* reset is low-active, so we need to invert */
+ s3c2410_gpio_setpin(GTA01_GPIO_BT_EN, on ? 0 : 1);
+ }
+
+ return count;
+}
+
+static DEVICE_ATTR(power_on, 0644, bt_read, bt_write);
+static DEVICE_ATTR(reset, 0644, bt_read, bt_write);
+
+#ifdef CONFIG_PM
+static int gta01_bt_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ dev_dbg(&pdev->dev, DRVMSG ": suspending\n");
+ /* FIXME: The PMU should save the PMU status, and the GPIO code should
+ * preserve the GPIO level, so there shouldn't be anything left to do
+ * for us, should there? */
+
+ return 0;
+}
+
+static int gta01_bt_resume(struct platform_device *pdev)
+{
+ dev_dbg(&pdev->dev, DRVMSG ": resuming\n");
+
+ return 0;
+}
+#else
+#define gta01_bt_suspend NULL
+#define gta01_bt_resume NULL
+#endif
+
+static struct attribute *gta01_bt_sysfs_entries[] = {
+ &dev_attr_power_on.attr,
+ &dev_attr_reset.attr,
+ NULL
+};
+
+static struct attribute_group gta01_bt_attr_group = {
+ .name = NULL,
+ .attrs = gta01_bt_sysfs_entries,
+};
+
+static int __init gta01_bt_probe(struct platform_device *pdev)
+{
+ dev_info(&pdev->dev, DRVMSG ": starting\n");
+
+ /* we make sure that the voltage is off */
+ pcf50606_onoff_set(pcf50606_global,
+ PCF50606_REGULATOR_D1REG, 0);
+ /* we pull reset to low to make sure that the chip doesn't
+ * drain power through the reset line */
+ s3c2410_gpio_setpin(GTA01_GPIO_BT_EN, 0);
+
+ return sysfs_create_group(&pdev->dev.kobj, &gta01_bt_attr_group);
+}
+
+static int gta01_bt_remove(struct platform_device *pdev)
+{
+ sysfs_remove_group(&pdev->dev.kobj, &gta01_bt_attr_group);
+
+ return 0;
+}
+
+static struct platform_driver gta01_bt_driver = {
+ .probe = gta01_bt_probe,
+ .remove = gta01_bt_remove,
+ .suspend = gta01_bt_suspend,
+ .resume = gta01_bt_resume,
+ .driver = {
+ .name = "neo1973-pm-bt",
+ },
+};
+
+static int __devinit gta01_bt_init(void)
+{
+ return platform_driver_register(&gta01_bt_driver);
+}
+
+static void gta01_bt_exit(void)
+{
+ platform_driver_unregister(&gta01_bt_driver);
+}
+
+module_init(gta01_bt_init);
+module_exit(gta01_bt_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Harald Welte <laforge@openmoko.org>");
+MODULE_DESCRIPTION(DRVMSG);
diff --git a/arch/arm/plat-s3c24xx/neo1973_pm_gps.c b/arch/arm/plat-s3c24xx/neo1973_pm_gps.c
new file mode 100644
index 0000000..f8cf719
--- /dev/null
+++ b/arch/arm/plat-s3c24xx/neo1973_pm_gps.c
@@ -0,0 +1,560 @@
+/*
+ * GPS Power Management code for the FIC Neo1973 GSM Phone
+ *
+ * (C) 2007 by OpenMoko Inc.
+ * Author: Harald Welte <laforge@openmoko.org>
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+
+#include <linux/pcf50606.h>
+
+#include <asm/hardware.h>
+#include <asm/arch/gta01.h>
+
+/* This is the 2.8V supply for the RTC crystal, the mail clock crystal and
+ * the input to VDD_RF */
+static void gps_power_2v8_set(int on)
+{
+ switch (system_rev) {
+ case GTA01v3_SYSTEM_REV:
+ case GTA01v4_SYSTEM_REV:
+ if (on)
+ pcf50606_voltage_set(pcf50606_global,
+ PCF50606_REGULATOR_IOREG, 2800);
+ pcf50606_onoff_set(pcf50606_global,
+ PCF50606_REGULATOR_IOREG, on);
+ break;
+ case GTA01Bv2_SYSTEM_REV:
+ s3c2410_gpio_setpin(GTA01_GPIO_GPS_EN_2V8, on);
+ break;
+ case GTA01Bv3_SYSTEM_REV:
+ case GTA01Bv4_SYSTEM_REV:
+ break;
+ }
+}
+
+static int gps_power_2v8_get(void)
+{
+ int ret = 0;
+
+ switch (system_rev) {
+ case GTA01v3_SYSTEM_REV:
+ case GTA01v4_SYSTEM_REV:
+ if (pcf50606_onoff_get(pcf50606_global,
+ PCF50606_REGULATOR_IOREG) &&
+ pcf50606_voltage_get(pcf50606_global,
+ PCF50606_REGULATOR_IOREG) == 2800)
+ ret = 1;
+ break;
+ case GTA01Bv2_SYSTEM_REV:
+ if (s3c2410_gpio_getpin(GTA01_GPIO_GPS_EN_2V8))
+ ret = 1;
+ break;
+ case GTA01Bv3_SYSTEM_REV:
+ case GTA01Bv4_SYSTEM_REV:
+ break;
+ }
+
+ return ret;
+}
+
+/* This is the 3V supply (AVDD) for the external RF frontend (LNA bias) */
+static void gps_power_3v_set(int on)
+{
+ switch (system_rev) {
+ case GTA01v3_SYSTEM_REV:
+ case GTA01v4_SYSTEM_REV:
+ if (on)
+ pcf50606_voltage_set(pcf50606_global,
+ PCF50606_REGULATOR_D1REG, 3000);
+ pcf50606_onoff_set(pcf50606_global,
+ PCF50606_REGULATOR_D1REG, on);
+ break;
+ case GTA01Bv2_SYSTEM_REV:
+ case GTA01Bv3_SYSTEM_REV:
+ case GTA01Bv4_SYSTEM_REV:
+ s3c2410_gpio_setpin(GTA01_GPIO_GPS_EN_3V, on);
+ break;
+ }
+}
+
+static int gps_power_3v_get(void)
+{
+ int ret = 0;
+
+ switch (system_rev) {
+ case GTA01v3_SYSTEM_REV:
+ case GTA01v4_SYSTEM_REV:
+ if (pcf50606_onoff_get(pcf50606_global,
+ PCF50606_REGULATOR_D1REG) &&
+ pcf50606_voltage_get(pcf50606_global,
+ PCF50606_REGULATOR_D1REG) == 3000)
+ ret = 1;
+ break;
+ case GTA01Bv2_SYSTEM_REV:
+ case GTA01Bv3_SYSTEM_REV:
+ case GTA01Bv4_SYSTEM_REV:
+ if (s3c2410_gpio_getpin(GTA01_GPIO_GPS_EN_3V))
+ ret = 1;
+ break;
+ }
+
+ return ret;
+}
+
+/* This is the 3.3V supply for VDD_IO and VDD_LPREG input */
+static void gps_power_3v3_set(int on)
+{
+ switch (system_rev) {
+ case GTA01v3_SYSTEM_REV:
+ case GTA01v4_SYSTEM_REV:
+ case GTA01Bv2_SYSTEM_REV:
+ if (on)
+ pcf50606_voltage_set(pcf50606_global,
+ PCF50606_REGULATOR_DCD, 3300);
+ pcf50606_onoff_set(pcf50606_global,
+ PCF50606_REGULATOR_DCD, on);
+ break;
+ case GTA01Bv3_SYSTEM_REV:
+ case GTA01Bv4_SYSTEM_REV:
+ s3c2410_gpio_setpin(GTA01_GPIO_GPS_EN_3V3, on);
+ break;
+ }
+}
+
+static int gps_power_3v3_get(void)
+{
+ int ret = 0;
+
+ switch (system_rev) {
+ case GTA01v3_SYSTEM_REV:
+ case GTA01v4_SYSTEM_REV:
+ case GTA01Bv2_SYSTEM_REV:
+ if (pcf50606_onoff_get(pcf50606_global,
+ PCF50606_REGULATOR_DCD) &&
+ pcf50606_voltage_get(pcf50606_global,
+ PCF50606_REGULATOR_DCD) == 3300)
+ ret = 1;
+ break;
+ case GTA01Bv3_SYSTEM_REV:
+ case GTA01Bv4_SYSTEM_REV:
+ if (s3c2410_gpio_getpin(GTA01_GPIO_GPS_EN_3V3))
+ ret = 1;
+ break;
+ }
+
+ return ret;
+}
+
+/* This is the 2.5V supply for VDD_PLLREG and VDD_COREREG input */
+static void gps_power_2v5_set(int on)
+{
+ switch (system_rev) {
+ case GTA01v3_SYSTEM_REV:
+ /* This is CORE_1V8 and cannot be disabled */
+ break;
+ case GTA01v4_SYSTEM_REV:
+ case GTA01Bv2_SYSTEM_REV:
+ case GTA01Bv3_SYSTEM_REV:
+ case GTA01Bv4_SYSTEM_REV:
+ if (on)
+ pcf50606_voltage_set(pcf50606_global,
+ PCF50606_REGULATOR_D2REG, 2500);
+ pcf50606_onoff_set(pcf50606_global,
+ PCF50606_REGULATOR_D2REG, on);
+ break;
+ }
+}
+
+static int gps_power_2v5_get(void)
+{
+ int ret = 0;
+
+ switch (system_rev) {
+ case GTA01v3_SYSTEM_REV:
+ /* This is CORE_1V8 and cannot be disabled */
+ ret = 1;
+ break;
+ case GTA01v4_SYSTEM_REV:
+ case GTA01Bv2_SYSTEM_REV:
+ case GTA01Bv3_SYSTEM_REV:
+ case GTA01Bv4_SYSTEM_REV:
+ if (pcf50606_onoff_get(pcf50606_global,
+ PCF50606_REGULATOR_D2REG) &&
+ pcf50606_voltage_get(pcf50606_global,
+ PCF50606_REGULATOR_D2REG) == 2500)
+ ret = 1;
+ break;
+ }
+
+ return ret;
+}
+
+/* This is the 1.5V supply for VDD_CORE */
+static void gps_power_1v5_set(int on)
+{
+ switch (system_rev) {
+ case GTA01v3_SYSTEM_REV:
+ case GTA01v4_SYSTEM_REV:
+ case GTA01Bv2_SYSTEM_REV:
+ /* This is switched via 2v5 */
+ break;
+ case GTA01Bv3_SYSTEM_REV:
+ case GTA01Bv4_SYSTEM_REV:
+ if (on)
+ pcf50606_voltage_set(pcf50606_global,
+ PCF50606_REGULATOR_DCD, 1500);
+ pcf50606_onoff_set(pcf50606_global,
+ PCF50606_REGULATOR_DCD, on);
+ break;
+ }
+}
+
+static int gps_power_1v5_get(void)
+{
+ int ret = 0;
+
+ switch (system_rev) {
+ case GTA01v3_SYSTEM_REV:
+ case GTA01v4_SYSTEM_REV:
+ case GTA01Bv2_SYSTEM_REV:
+ /* This is switched via 2v5 */
+ ret = 1;
+ break;
+ case GTA01Bv3_SYSTEM_REV:
+ case GTA01Bv4_SYSTEM_REV:
+ if (pcf50606_onoff_get(pcf50606_global,
+ PCF50606_REGULATOR_DCD) &&
+ pcf50606_voltage_get(pcf50606_global,
+ PCF50606_REGULATOR_DCD) == 1500)
+ ret = 1;
+ break;
+ }
+
+ return ret;
+}
+
+/* This is the POWERON pin */
+static void gps_pwron_set(int on)
+{
+ s3c2410_gpio_setpin(GTA01_GPIO_GPS_PWRON, on);
+}
+
+static int gps_pwron_get(void)
+{
+ if (s3c2410_gpio_getpin(GTA01_GPIO_GPS_PWRON))
+ return 1;
+ else
+ return 0;
+}
+
+/* This is the nRESET pin */
+static void gps_rst_set(int on)
+{
+ switch (system_rev) {
+ case GTA01v3_SYSTEM_REV:
+ pcf50606_gpo0_set(pcf50606_global, on);
+ break;
+ case GTA01v4_SYSTEM_REV:
+ case GTA01Bv2_SYSTEM_REV:
+ case GTA01Bv3_SYSTEM_REV:
+ case GTA01Bv4_SYSTEM_REV:
+ s3c2410_gpio_setpin(GTA01_GPIO_GPS_RESET, on);
+ break;
+ }
+}
+
+static int gps_rst_get(void)
+{
+ switch (system_rev) {
+ case GTA01v3_SYSTEM_REV:
+ if (pcf50606_gpo0_get(pcf50606_global))
+ return 1;
+ break;
+ case GTA01v4_SYSTEM_REV:
+ case GTA01Bv2_SYSTEM_REV:
+ case GTA01Bv3_SYSTEM_REV:
+ case GTA01Bv4_SYSTEM_REV:
+ if (s3c2410_gpio_getpin(GTA01_GPIO_GPS_RESET))
+ return 1;
+ break;
+ }
+
+ return 0;
+}
+
+static ssize_t power_gps_read(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int ret = 0;
+
+ if (!strcmp(attr->attr.name, "power_tcxo_2v8")) {
+ ret = gps_power_2v8_get();
+ } else if (!strcmp(attr->attr.name, "power_avdd_3v")) {
+ ret = gps_power_3v_get();
+ } else if (!strcmp(attr->attr.name, "pwron")) {
+ ret = gps_pwron_get();
+ } else if (!strcmp(attr->attr.name, "reset")) {
+ ret = gps_rst_get();
+ } else if (!strcmp(attr->attr.name, "power_lp_io_3v3")) {
+ ret = gps_power_3v3_get();
+ } else if (!strcmp(attr->attr.name, "power_pll_core_2v5")) {
+ ret = gps_power_2v5_get();
+ } else if (!strcmp(attr->attr.name, "power_core_1v5") ||
+ !strcmp(attr->attr.name, "power_vdd_core_1v5")) {
+ ret = gps_power_1v5_get();
+ }
+
+ if (ret)
+ return strlcpy(buf, "1\n", 3);
+ else
+ return strlcpy(buf, "0\n", 3);
+}
+
+static ssize_t power_gps_write(struct device *dev,
+ struct device_attribute *attr, const char *buf,
+ size_t count)
+{
+ unsigned long on = simple_strtoul(buf, NULL, 10);
+
+ if (!strcmp(attr->attr.name, "power_tcxo_2v8")) {
+ gps_power_2v8_set(on);
+ } else if (!strcmp(attr->attr.name, "power_avdd_3v")) {
+ gps_power_3v_set(on);
+ } else if (!strcmp(attr->attr.name, "pwron")) {
+ gps_pwron_set(on);
+ } else if (!strcmp(attr->attr.name, "reset")) {
+ gps_rst_set(on);
+ } else if (!strcmp(attr->attr.name, "power_lp_io_3v3")) {
+ gps_power_3v3_set(on);
+ } else if (!strcmp(attr->attr.name, "power_pll_core_2v5")) {
+ gps_power_2v5_set(on);
+ } else if (!strcmp(attr->attr.name, "power_core_1v5") ||
+ !strcmp(attr->attr.name, "power_vdd_core_1v5")) {
+ gps_power_1v5_set(on);
+ }
+
+ return count;
+}
+
+static void gps_power_sequence_up(void)
+{
+ /* According to PMB2520 Data Sheet, Rev. 2006-06-05,
+ * Chapter 4.2.2 */
+
+ /* nRESET must be asserted low */
+ gps_rst_set(0);
+
+ /* POWERON must be de-asserted (low) */
+ gps_pwron_set(0);
+
+ /* Apply VDD_IO and VDD_LPREG_IN */
+ gps_power_3v3_set(1);
+
+ /* VDD_COREREG_IN, VDD_PLLREG_IN */
+ gps_power_1v5_set(1);
+ gps_power_2v5_set(1);
+
+ /* and VDD_RF may be applied */
+ gps_power_2v8_set(1);
+
+ /* We need to enable AVDD, since in GTA01Bv3 it is
+ * shared with RFREG_IN */
+ gps_power_3v_set(1);
+
+ msleep(3); /* Is 3ms enough? */
+
+ /* De-asert nRESET */
+ gps_rst_set(1);
+
+ /* Switch power on */
+ gps_pwron_set(1);
+
+}
+
+static void gps_power_sequence_down(void)
+{
+ /* According to PMB2520 Data Sheet, Rev. 2006-06-05,
+ * Chapter 4.2.3.1 */
+ gps_pwron_set(0);
+
+ /* Don't disable AVDD before PWRON is cleared, since
+ * in GTA01Bv3, AVDD and RFREG_IN are shared */
+ gps_power_3v_set(0);
+
+ /* Remove VDD_COREREG_IN, VDD_PLLREG_IN and VDD_REFREG_IN */
+ gps_power_1v5_set(0);
+ gps_power_2v5_set(0);
+ gps_power_2v8_set(0);
+
+ /* Remove VDD_LPREG_IN and VDD_IO */
+ gps_power_3v3_set(0);
+}
+
+
+static ssize_t power_sequence_read(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ return strlcpy(buf, "power_up power_down\n", PAGE_SIZE);
+}
+
+static ssize_t power_sequence_write(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ dev_dbg(dev, "wrote: '%s'\n", buf);
+
+ if (!strncmp(buf, "power_up", 8))
+ gps_power_sequence_up();
+ else if (!strncmp(buf, "power_down", 10))
+ gps_power_sequence_down();
+ else
+ return -EINVAL;
+
+ return count;
+}
+
+static DEVICE_ATTR(power_tcxo_2v8, 0644, power_gps_read, power_gps_write);
+static DEVICE_ATTR(power_avdd_3v, 0644, power_gps_read, power_gps_write);
+static DEVICE_ATTR(pwron, 0644, power_gps_read, power_gps_write);
+static DEVICE_ATTR(reset, 0644, power_gps_read, power_gps_write);
+static DEVICE_ATTR(power_lp_io_3v3, 0644, power_gps_read, power_gps_write);
+static DEVICE_ATTR(power_pll_core_2v5, 0644, power_gps_read, power_gps_write);
+static DEVICE_ATTR(power_core_1v5, 0644, power_gps_read, power_gps_write);
+static DEVICE_ATTR(power_vdd_core_1v5, 0644, power_gps_read, power_gps_write);
+static DEVICE_ATTR(power_sequence, 0644, power_sequence_read,
+ power_sequence_write);
+
+#ifdef CONFIG_PM
+static int gta01_pm_gps_suspend(struct platform_device *pdev,
+ pm_message_t state)
+{
+ /* FIXME */
+ gps_power_sequence_down();
+
+ return 0;
+}
+
+static int gta01_pm_gps_resume(struct platform_device *pdev)
+{
+ /* FIXME */
+ gps_power_sequence_up();
+
+ return 0;
+}
+#else
+#define gta01_pm_gps_suspend NULL
+#define gta01_pm_gps_resume NULL
+#endif
+
+static struct attribute *gta01_gps_sysfs_entries[] = {
+ &dev_attr_power_avdd_3v.attr,
+ &dev_attr_pwron.attr,
+ &dev_attr_reset.attr,
+ &dev_attr_power_lp_io_3v3.attr,
+ &dev_attr_power_pll_core_2v5.attr,
+ &dev_attr_power_sequence.attr,
+ NULL, /* power_core_1v5 */
+ NULL, /* power_vdd_core_1v5 */
+ NULL /* terminating entry */
+};
+
+static struct attribute_group gta01_gps_attr_group = {
+ .name = NULL,
+ .attrs = gta01_gps_sysfs_entries,
+};
+
+static int __init gta01_pm_gps_probe(struct platform_device *pdev)
+{
+ s3c2410_gpio_cfgpin(GTA01_GPIO_GPS_PWRON, S3C2410_GPIO_OUTPUT);
+
+ switch (system_rev) {
+ case GTA01v3_SYSTEM_REV:
+ break;
+ case GTA01v4_SYSTEM_REV:
+ s3c2410_gpio_cfgpin(GTA01_GPIO_GPS_RESET, S3C2410_GPIO_OUTPUT);
+ break;
+ case GTA01Bv3_SYSTEM_REV:
+ case GTA01Bv4_SYSTEM_REV:
+ s3c2410_gpio_cfgpin(GTA01_GPIO_GPS_EN_3V3, S3C2410_GPIO_OUTPUT);
+ /* fallthrough */
+ case GTA01Bv2_SYSTEM_REV:
+ s3c2410_gpio_cfgpin(GTA01_GPIO_GPS_EN_2V8, S3C2410_GPIO_OUTPUT);
+ s3c2410_gpio_cfgpin(GTA01_GPIO_GPS_EN_3V, S3C2410_GPIO_OUTPUT);
+ s3c2410_gpio_cfgpin(GTA01_GPIO_GPS_RESET, S3C2410_GPIO_OUTPUT);
+ break;
+ default:
+ dev_warn(&pdev->dev, "Unknown GTA01 Revision 0x%x, "
+ "AGPS PM features not available!!!\n",
+ system_rev);
+ return -1;
+ break;
+ }
+
+ gps_power_sequence_down();
+
+ switch (system_rev) {
+ case GTA01v3_SYSTEM_REV:
+ case GTA01v4_SYSTEM_REV:
+ case GTA01Bv2_SYSTEM_REV:
+ gta01_gps_sysfs_entries[ARRAY_SIZE(gta01_gps_sysfs_entries)-3] =
+ &dev_attr_power_tcxo_2v8.attr;
+ break;
+ case GTA01Bv3_SYSTEM_REV:
+ case GTA01Bv4_SYSTEM_REV:
+ gta01_gps_sysfs_entries[ARRAY_SIZE(gta01_gps_sysfs_entries)-3] =
+ &dev_attr_power_core_1v5.attr;
+ gta01_gps_sysfs_entries[ARRAY_SIZE(gta01_gps_sysfs_entries)-2] =
+ &dev_attr_power_vdd_core_1v5.attr;
+ break;
+ }
+
+ return sysfs_create_group(&pdev->dev.kobj, &gta01_gps_attr_group);
+}
+
+static int gta01_pm_gps_remove(struct platform_device *pdev)
+{
+ gps_power_sequence_down();
+ sysfs_remove_group(&pdev->dev.kobj, &gta01_gps_attr_group);
+
+ return 0;
+}
+
+static struct platform_driver gta01_pm_gps_driver = {
+ .probe = gta01_pm_gps_probe,
+ .remove = gta01_pm_gps_remove,
+ .suspend = gta01_pm_gps_suspend,
+ .resume = gta01_pm_gps_resume,
+ .driver = {
+ .name = "neo1973-pm-gps",
+ },
+};
+
+static int __devinit gta01_pm_gps_init(void)
+{
+ return platform_driver_register(&gta01_pm_gps_driver);
+}
+
+static void gta01_pm_gps_exit(void)
+{
+ platform_driver_unregister(&gta01_pm_gps_driver);
+}
+
+module_init(gta01_pm_gps_init);
+module_exit(gta01_pm_gps_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Harald Welte <laforge@openmoko.org>");
+MODULE_DESCRIPTION("FIC Neo1973 GPS Power Management");
diff --git a/arch/arm/plat-s3c24xx/neo1973_pm_gsm.c b/arch/arm/plat-s3c24xx/neo1973_pm_gsm.c
new file mode 100644
index 0000000..a1615f8
--- /dev/null
+++ b/arch/arm/plat-s3c24xx/neo1973_pm_gsm.c
@@ -0,0 +1,217 @@
+/*
+ * GSM Management code for the FIC Neo1973 GSM Phone
+ *
+ * (C) 2007 by OpenMoko Inc.
+ * Author: Harald Welte <laforge@openmoko.org>
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/console.h>
+#include <linux/errno.h>
+
+#include <asm/hardware.h>
+#include <asm/arch/gta01.h>
+
+struct gta01pm_priv {
+ int gpio_ngsm_en;
+ struct console *con;
+};
+
+static struct gta01pm_priv gta01_gsm;
+
+static struct console *find_s3c24xx_console(void)
+{
+ struct console *con;
+
+ acquire_console_sem();
+
+ for (con = console_drivers; con; con = con->next) {
+ if (!strcmp(con->name, "ttySAC"))
+ break;
+ }
+
+ release_console_sem();
+
+ return con;
+}
+
+static ssize_t gsm_read(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ if (!strcmp(attr->attr.name, "power_on")) {
+ if (s3c2410_gpio_getpin(GTA01_GPIO_MODEM_ON))
+ goto out_1;
+ } else if (!strcmp(attr->attr.name, "reset")) {
+ if (s3c2410_gpio_getpin(GTA01_GPIO_MODEM_RST))
+ goto out_1;
+ } else if (!strcmp(attr->attr.name, "download")) {
+ if (s3c2410_gpio_getpin(GTA01_GPIO_MODEM_DNLOAD))
+ goto out_1;
+ }
+
+ return strlcpy(buf, "0\n", 3);
+out_1:
+ return strlcpy(buf, "1\n", 3);
+}
+
+static ssize_t gsm_write(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned long on = simple_strtoul(buf, NULL, 10);
+
+ if (!strcmp(attr->attr.name, "power_on")) {
+ if (on) {
+ dev_info(dev, "powering up GSM, thus disconnecting "
+ "serial console\n");
+
+ if (gta01_gsm.con)
+ console_stop(gta01_gsm.con);
+
+ if (gta01_gsm.gpio_ngsm_en)
+ s3c2410_gpio_setpin(gta01_gsm.gpio_ngsm_en, 0);
+
+ s3c2410_gpio_setpin(GTA01_GPIO_MODEM_ON, 1);
+ } else {
+ s3c2410_gpio_setpin(GTA01_GPIO_MODEM_ON, 0);
+
+ if (gta01_gsm.gpio_ngsm_en)
+ s3c2410_gpio_setpin(gta01_gsm.gpio_ngsm_en, 1);
+
+ if (gta01_gsm.con)
+ console_start(gta01_gsm.con);
+
+ dev_info(dev, "powered down GSM, thus enabling "
+ "serial console\n");
+ }
+ } else if (!strcmp(attr->attr.name, "reset")) {
+ s3c2410_gpio_setpin(GTA01_GPIO_MODEM_RST, on);
+ } else if (!strcmp(attr->attr.name, "download")) {
+ s3c2410_gpio_setpin(GTA01_GPIO_MODEM_DNLOAD, on);
+ }
+
+ return count;
+}
+
+static DEVICE_ATTR(power_on, 0644, gsm_read, gsm_write);
+static DEVICE_ATTR(reset, 0644, gsm_read, gsm_write);
+static DEVICE_ATTR(download, 0644, gsm_read, gsm_write);
+
+#ifdef CONFIG_PM
+static int gta01_gsm_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ /* GPIO state is saved/restored by S3C2410 core GPIO driver, so we
+ * don't need to do anything here */
+
+ return 0;
+}
+
+static int gta01_gsm_resume(struct platform_device *pdev)
+{
+ /* GPIO state is saved/restored by S3C2410 core GPIO driver, so we
+ * don't need to do anything here */
+
+ /* Make sure that the kernel console on the serial port is still
+ * disabled. FIXME: resume ordering race with serial driver! */
+ if (s3c2410_gpio_getpin(GTA01_GPIO_MODEM_ON) && gta01_gsm.con)
+ console_stop(gta01_gsm.con);
+
+ return 0;
+}
+#else
+#define gta01_gsm_suspend NULL
+#define gta01_gsm_resume NULL
+#endif
+
+static struct attribute *gta01_gsm_sysfs_entries[] = {
+ &dev_attr_power_on.attr,
+ &dev_attr_reset.attr,
+ NULL,
+ NULL
+};
+
+static struct attribute_group gta01_gsm_attr_group = {
+ .name = NULL,
+ .attrs = gta01_gsm_sysfs_entries,
+};
+
+static int __init gta01_gsm_probe(struct platform_device *pdev)
+{
+ switch (system_rev) {
+ case GTA01v3_SYSTEM_REV:
+ gta01_gsm.gpio_ngsm_en = GTA01v3_GPIO_nGSM_EN;
+ break;
+ case GTA01v4_SYSTEM_REV:
+ gta01_gsm.gpio_ngsm_en = 0;
+ break;
+ case GTA01Bv2_SYSTEM_REV:
+ case GTA01Bv3_SYSTEM_REV:
+ case GTA01Bv4_SYSTEM_REV:
+ gta01_gsm.gpio_ngsm_en = GTA01Bv2_GPIO_nGSM_EN;
+ s3c2410_gpio_setpin(GTA01v3_GPIO_nGSM_EN, 0);
+ break;
+ default:
+ dev_warn(&pdev->dev, "Unknown GTA01 Revision 0x%x, "
+ "some PM features not available!!!\n",
+ system_rev);
+ break;
+ }
+
+ switch (system_rev) {
+ case GTA01v4_SYSTEM_REV:
+ case GTA01Bv2_SYSTEM_REV:
+ gta01_gsm_sysfs_entries[ARRAY_SIZE(gta01_gsm_sysfs_entries)-2] =
+ &dev_attr_download.attr;
+ break;
+ default:
+ break;
+ }
+
+ gta01_gsm.con = find_s3c24xx_console();
+ if (!gta01_gsm.con)
+ dev_warn(&pdev->dev, "cannot find S3C24xx console driver\n");
+
+ return sysfs_create_group(&pdev->dev.kobj, &gta01_gsm_attr_group);
+}
+
+static int gta01_gsm_remove(struct platform_device *pdev)
+{
+ sysfs_remove_group(&pdev->dev.kobj, &gta01_gsm_attr_group);
+
+ return 0;
+}
+
+static struct platform_driver gta01_gsm_driver = {
+ .probe = gta01_gsm_probe,
+ .remove = gta01_gsm_remove,
+ .suspend = gta01_gsm_suspend,
+ .resume = gta01_gsm_resume,
+ .driver = {
+ .name = "neo1973-pm-gsm",
+ },
+};
+
+static int __devinit gta01_gsm_init(void)
+{
+ return platform_driver_register(&gta01_gsm_driver);
+}
+
+static void gta01_gsm_exit(void)
+{
+ platform_driver_unregister(&gta01_gsm_driver);
+}
+
+module_init(gta01_gsm_init);
+module_exit(gta01_gsm_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Harald Welte <laforge@openmoko.org>");
+MODULE_DESCRIPTION("FIC Neo1973 GSM Power Management");
--
1.5.6.3

View file

@ -0,0 +1,323 @@
From 2b1ccb68bdc0e1454be0e769896862bf0c7f95f9 Mon Sep 17 00:00:00 2001
From: mokopatches <mokopatches@openmoko.org>
Date: Wed, 16 Jul 2008 14:44:49 +0100
Subject: [PATCH] s3c2410-pwm.patch
This patch adds a PWM api abstraction for the S3C2410 SoC
Signed-off-by: Javi Roman <javiroman@kernel-labs.org>
Signed-off-by: Harald Welte <laforge@openmoko.org>
---
arch/arm/mach-s3c2410/Kconfig | 7 +
arch/arm/mach-s3c2410/Makefile | 1 +
arch/arm/mach-s3c2410/pwm.c | 214 ++++++++++++++++++++++++++++++++++++
include/asm-arm/arch-s3c2410/pwm.h | 40 +++++++
4 files changed, 262 insertions(+), 0 deletions(-)
create mode 100644 arch/arm/mach-s3c2410/pwm.c
create mode 100644 include/asm-arm/arch-s3c2410/pwm.h
diff --git a/arch/arm/mach-s3c2410/Kconfig b/arch/arm/mach-s3c2410/Kconfig
index 58519e6..3e9ec50 100644
--- a/arch/arm/mach-s3c2410/Kconfig
+++ b/arch/arm/mach-s3c2410/Kconfig
@@ -9,6 +9,7 @@ config CPU_S3C2410
depends on ARCH_S3C2410
select S3C2410_CLOCK
select S3C2410_GPIO
+ select S3C2410_PWM
select CPU_LLSERIAL_S3C2410
select S3C2410_PM if PM
help
@@ -38,6 +39,12 @@ config S3C2410_CLOCK
Clock code for the S3C2410, and similar processors
+config S3C2410_PWM
+ bool
+ help
+ PWM timer code for the S3C2410, and similar processors
+
+
menu "S3C2410 Machines"
config ARCH_SMDK2410
diff --git a/arch/arm/mach-s3c2410/Makefile b/arch/arm/mach-s3c2410/Makefile
index b73562f..2a12a6a 100644
--- a/arch/arm/mach-s3c2410/Makefile
+++ b/arch/arm/mach-s3c2410/Makefile
@@ -16,6 +16,7 @@ obj-$(CONFIG_CPU_S3C2410_DMA) += dma.o
obj-$(CONFIG_S3C2410_PM) += pm.o sleep.o
obj-$(CONFIG_S3C2410_GPIO) += gpio.o
obj-$(CONFIG_S3C2410_CLOCK) += clock.o
+obj-$(CONFIG_S3C2410_PWM) += pwm.o
# Machine support
diff --git a/arch/arm/mach-s3c2410/pwm.c b/arch/arm/mach-s3c2410/pwm.c
new file mode 100644
index 0000000..8a07359
--- /dev/null
+++ b/arch/arm/mach-s3c2410/pwm.c
@@ -0,0 +1,214 @@
+/*
+ * arch/arm/mach-s3c2410/3c2410-pwm.c
+ *
+ * Copyright (c) by Javi Roman <javiroman@kernel-labs.org>
+ * for the OpenMoko Project.
+ *
+ * S3C2410A SoC PWM support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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/kernel.h>
+#include <linux/init.h>
+#include <linux/clk.h>
+#include <asm/hardware.h>
+#include <asm/plat-s3c/regs-timer.h>
+#include <asm/arch/pwm.h>
+
+int s3c2410_pwm_disable(struct s3c2410_pwm *pwm)
+{
+ unsigned long tcon;
+
+ /* stop timer */
+ tcon = __raw_readl(S3C2410_TCON);
+ tcon &= 0xffffff00;
+ __raw_writel(tcon, S3C2410_TCON);
+
+ clk_disable(pwm->pclk);
+ clk_put(pwm->pclk);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(s3c2410_pwm_disable);
+
+int s3c2410_pwm_init(struct s3c2410_pwm *pwm)
+{
+ pwm->pclk = clk_get(NULL, "timers");
+ if (IS_ERR(pwm->pclk))
+ return PTR_ERR(pwm->pclk);
+
+ clk_enable(pwm->pclk);
+ pwm->pclk_rate = clk_get_rate(pwm->pclk);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(s3c2410_pwm_init);
+
+int s3c2410_pwm_enable(struct s3c2410_pwm *pwm)
+{
+ unsigned long tcfg0, tcfg1, tcnt, tcmp;
+
+ /* control registers bits */
+ tcfg1 = __raw_readl(S3C2410_TCFG1);
+ tcfg0 = __raw_readl(S3C2410_TCFG0);
+
+ /* divider & scaler slection */
+ switch (pwm->timerid) {
+ case PWM0:
+ tcfg1 &= ~S3C2410_TCFG1_MUX0_MASK;
+ tcfg0 &= ~S3C2410_TCFG_PRESCALER0_MASK;
+ break;
+ case PWM1:
+ tcfg1 &= ~S3C2410_TCFG1_MUX1_MASK;
+ tcfg0 &= ~S3C2410_TCFG_PRESCALER0_MASK;
+ break;
+ case PWM2:
+ tcfg1 &= ~S3C2410_TCFG1_MUX2_MASK;
+ tcfg0 &= ~S3C2410_TCFG_PRESCALER1_MASK;
+ break;
+ case PWM3:
+ tcfg1 &= ~S3C2410_TCFG1_MUX3_MASK;
+ tcfg0 &= ~S3C2410_TCFG_PRESCALER1_MASK;
+ break;
+ case PWM4:
+ /* timer four is not capable of doing PWM */
+ break;
+ default:
+ clk_disable(pwm->pclk);
+ clk_put(pwm->pclk);
+ return -1;
+ }
+
+ /* divider & scaler values */
+ tcfg1 |= pwm->divider;
+ __raw_writel(tcfg1, S3C2410_TCFG1);
+
+ switch (pwm->timerid) {
+ case PWM0:
+ case PWM1:
+ tcfg0 |= pwm->prescaler;
+ __raw_writel(tcfg0, S3C2410_TCFG0);
+ break;
+ default:
+ if ((tcfg0 | pwm->prescaler) != tcfg0) {
+ printk(KERN_WARNING "not changing prescaler of PWM %u,"
+ " since it's shared with timer4 (clock tick)\n",
+ pwm->timerid);
+ }
+ break;
+ }
+
+ /* timer count and compare buffer initial values */
+ tcnt = pwm->counter;
+ tcmp = pwm->comparer;
+
+ __raw_writel(tcnt, S3C2410_TCNTB(pwm->timerid));
+ __raw_writel(tcmp, S3C2410_TCMPB(pwm->timerid));
+
+ /* ensure timer is stopped */
+ s3c2410_pwm_stop(pwm);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(s3c2410_pwm_enable);
+
+int s3c2410_pwm_start(struct s3c2410_pwm *pwm)
+{
+ unsigned long tcon;
+
+ tcon = __raw_readl(S3C2410_TCON);
+
+ switch (pwm->timerid) {
+ case PWM0:
+ tcon |= S3C2410_TCON_T0START;
+ tcon &= ~S3C2410_TCON_T0MANUALUPD;
+ break;
+ case PWM1:
+ tcon |= S3C2410_TCON_T1START;
+ tcon &= ~S3C2410_TCON_T1MANUALUPD;
+ break;
+ case PWM2:
+ tcon |= S3C2410_TCON_T2START;
+ tcon &= ~S3C2410_TCON_T2MANUALUPD;
+ break;
+ case PWM3:
+ tcon |= S3C2410_TCON_T3START;
+ tcon &= ~S3C2410_TCON_T3MANUALUPD;
+ break;
+ case PWM4:
+ /* timer four is not capable of doing PWM */
+ default:
+ return -ENODEV;
+ }
+
+ __raw_writel(tcon, S3C2410_TCON);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(s3c2410_pwm_start);
+
+int s3c2410_pwm_stop(struct s3c2410_pwm *pwm)
+{
+ unsigned long tcon;
+
+ tcon = __raw_readl(S3C2410_TCON);
+
+ switch (pwm->timerid) {
+ case PWM0:
+ tcon &= ~0x00000000;
+ tcon |= S3C2410_TCON_T0RELOAD;
+ tcon |= S3C2410_TCON_T0MANUALUPD;
+ break;
+ case PWM1:
+ tcon &= ~0x00000080;
+ tcon |= S3C2410_TCON_T1RELOAD;
+ tcon |= S3C2410_TCON_T1MANUALUPD;
+ break;
+ case PWM2:
+ tcon &= ~0x00000800;
+ tcon |= S3C2410_TCON_T2RELOAD;
+ tcon |= S3C2410_TCON_T2MANUALUPD;
+ break;
+ case PWM3:
+ tcon &= ~0x00008000;
+ tcon |= S3C2410_TCON_T3RELOAD;
+ tcon |= S3C2410_TCON_T3MANUALUPD;
+ break;
+ case PWM4:
+ /* timer four is not capable of doing PWM */
+ default:
+ return -ENODEV;
+ }
+
+ __raw_writel(tcon, S3C2410_TCON);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(s3c2410_pwm_stop);
+
+int s3c2410_pwm_duty_cycle(int reg_value, struct s3c2410_pwm *pwm)
+{
+ __raw_writel(reg_value, S3C2410_TCMPB(pwm->timerid));
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(s3c2410_pwm_duty_cycle);
+
+int s3c2410_pwm_dumpregs(void)
+{
+ printk(KERN_INFO "TCON: %08lx, TCFG0: %08lx, TCFG1: %08lx\n",
+ (unsigned long) __raw_readl(S3C2410_TCON),
+ (unsigned long) __raw_readl(S3C2410_TCFG0),
+ (unsigned long) __raw_readl(S3C2410_TCFG1));
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(s3c2410_pwm_dumpregs);
diff --git a/include/asm-arm/arch-s3c2410/pwm.h b/include/asm-arm/arch-s3c2410/pwm.h
new file mode 100644
index 0000000..a797ec3
--- /dev/null
+++ b/include/asm-arm/arch-s3c2410/pwm.h
@@ -0,0 +1,40 @@
+#ifndef __S3C2410_PWM_H
+#define __S3C2410_PWM_H
+
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+
+#include <asm-arm/io.h>
+#include <asm/arch/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/plat-s3c/regs-timer.h>
+#include <asm/arch/gta01.h>
+
+enum pwm_timer {
+ PWM0,
+ PWM1,
+ PWM2,
+ PWM3,
+ PWM4
+};
+
+struct s3c2410_pwm {
+ enum pwm_timer timerid;
+ struct clk *pclk;
+ unsigned long pclk_rate;
+ unsigned long prescaler;
+ unsigned long divider;
+ unsigned long counter;
+ unsigned long comparer;
+};
+
+int s3c2410_pwm_init(struct s3c2410_pwm *s3c2410_pwm);
+int s3c2410_pwm_enable(struct s3c2410_pwm *s3c2410_pwm);
+int s3c2410_pwm_disable(struct s3c2410_pwm *s3c2410_pwm);
+int s3c2410_pwm_start(struct s3c2410_pwm *s3c2410_pwm);
+int s3c2410_pwm_stop(struct s3c2410_pwm *s3c2410_pwm);
+int s3c2410_pwm_duty_cycle(int reg_value, struct s3c2410_pwm *s3c2410_pwm);
+int s3c2410_pwm_dumpregs(void);
+
+#endif /* __S3C2410_PWM_H */
--
1.5.6.3

View file

@ -0,0 +1,244 @@
From 51990833d84bdff24a384119a9ba0cf815edd683 Mon Sep 17 00:00:00 2001
From: mokopatches <mokopatches@openmoko.org>
Date: Wed, 16 Jul 2008 14:44:49 +0100
Subject: [PATCH] gta01-vibrator.patch
This patch adds driver support for the vibator device of the FIC/OpenMoko
Neo1973 GSM phone. The driver uses the existing LED class driver framework,
since there's a lot of similarity between the LED and the vibrator function.
Signed-off-by: Harald Welte <laforge@openmoko.org>
---
drivers/leds/Kconfig | 8 ++-
drivers/leds/Makefile | 1 +
drivers/leds/leds-neo1973-vibrator.c | 181 ++++++++++++++++++++++++++++++++++
3 files changed, 189 insertions(+), 1 deletions(-)
create mode 100644 drivers/leds/leds-neo1973-vibrator.c
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index 86a369b..8c7d949 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -47,7 +47,7 @@ config LEDS_SPITZ
config LEDS_S3C24XX
tristate "LED Support for Samsung S3C24XX GPIO LEDs"
- depends on LEDS_CLASS && ARCH_S3C2410
+ depends on LEDS_CLASS && ARCH_S3C2410 && S3C2410_PWM
help
This option enables support for LEDs connected to GPIO lines
on Samsung S3C24XX series CPUs, such as the S3C2410 and S3C2440.
@@ -147,6 +147,12 @@ config LEDS_CLEVO_MAIL
To compile this driver as a module, choose M here: the
module will be called leds-clevo-mail.
+config LEDS_NEO1973_VIBRATOR
+ tristate "Vibrator Support for the FIC Neo1973 GSM phone"
+ depends on LEDS_CLASS && MACH_NEO1973
+ help
+ This option enables support for the vibrator on the FIC Neo1973.
+
comment "LED Triggers"
config LEDS_TRIGGERS
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
index 973d626..148fe51 100644
--- a/drivers/leds/Makefile
+++ b/drivers/leds/Makefile
@@ -21,6 +21,7 @@ obj-$(CONFIG_LEDS_CM_X270) += leds-cm-x270.o
obj-$(CONFIG_LEDS_CLEVO_MAIL) += leds-clevo-mail.o
obj-$(CONFIG_LEDS_HP6XX) += leds-hp6xx.o
obj-$(CONFIG_LEDS_FSG) += leds-fsg.o
+obj-$(CONFIG_LEDS_NEO1973_VIBRATOR) += leds-neo1973-vibrator.o
# LED Triggers
obj-$(CONFIG_LEDS_TRIGGER_TIMER) += ledtrig-timer.o
diff --git a/drivers/leds/leds-neo1973-vibrator.c b/drivers/leds/leds-neo1973-vibrator.c
new file mode 100644
index 0000000..0336e36
--- /dev/null
+++ b/drivers/leds/leds-neo1973-vibrator.c
@@ -0,0 +1,181 @@
+/*
+ * LED driver for the vibrator of the FIC Neo1973 GSM Phone
+ *
+ * (C) 2006-2007 by OpenMoko, Inc.
+ * Author: Harald Welte <laforge@openmoko.org>
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Javi Roman <javiroman@kernel-labs.org>:
+ * Implement PWM support for GTA01Bv4 and later
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/leds.h>
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/arch/pwm.h>
+#include <asm/arch/gta01.h>
+#include <asm/plat-s3c/regs-timer.h>
+
+#define COUNTER 64
+
+struct neo1973_vib_priv {
+ struct led_classdev cdev;
+ unsigned int gpio;
+ struct mutex mutex;
+ unsigned int has_pwm;
+ struct s3c2410_pwm pwm;
+};
+
+static void neo1973_vib_vib_set(struct led_classdev *led_cdev,
+ enum led_brightness value)
+{
+ struct neo1973_vib_priv *vp =
+ container_of(led_cdev, struct neo1973_vib_priv, cdev);
+
+ /*
+ * value == 255 -> 99% duty cycle (full power)
+ * value == 128 -> 50% duty cycle (medium power)
+ * value == 0 -> 0% duty cycle (zero power)
+ */
+ mutex_lock(&vp->mutex);
+ if (vp->has_pwm)
+ s3c2410_pwm_duty_cycle(value/4, &vp->pwm);
+ else {
+ if (value)
+ s3c2410_gpio_setpin(vp->gpio, 1);
+ else
+ s3c2410_gpio_setpin(vp->gpio, 0);
+ }
+
+ mutex_unlock(&vp->mutex);
+}
+
+static struct neo1973_vib_priv neo1973_vib_led = {
+ .cdev = {
+ .name = "neo1973:vibrator",
+ .brightness_set = neo1973_vib_vib_set,
+ },
+};
+
+static int neo1973_vib_init_hw(struct neo1973_vib_priv *vp)
+{
+ int rc;
+
+ rc = s3c2410_pwm_init(&vp->pwm);
+ if (rc)
+ return rc;
+
+ vp->pwm.timerid = PWM3;
+ /* use same prescaler as arch/arm/plat-s3c24xx/time.c */
+ vp->pwm.prescaler = (6 - 1) / 2;
+ vp->pwm.divider = S3C2410_TCFG1_MUX3_DIV2;
+ vp->pwm.counter = COUNTER;
+ vp->pwm.comparer = COUNTER;
+
+ rc = s3c2410_pwm_enable(&vp->pwm);
+ if (rc)
+ return rc;
+
+ s3c2410_pwm_start(&vp->pwm);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int neo1973_vib_suspend(struct platform_device *dev, pm_message_t state)
+{
+ led_classdev_suspend(&neo1973_vib_led.cdev);
+ return 0;
+}
+
+static int neo1973_vib_resume(struct platform_device *dev)
+{
+ struct neo1973_vib_priv *vp = platform_get_drvdata(dev);
+
+ if (vp->has_pwm)
+ neo1973_vib_init_hw(vp);
+
+ led_classdev_resume(&neo1973_vib_led.cdev);
+
+ return 0;
+}
+#endif /* CONFIG_PM */
+
+static int __init neo1973_vib_probe(struct platform_device *pdev)
+{
+ struct resource *r;
+ int rc;
+
+ if (!machine_is_neo1973_gta01())
+ return -EIO;
+
+ r = platform_get_resource(pdev, 0, 0);
+ if (!r || !r->start)
+ return -EIO;
+
+ neo1973_vib_led.gpio = r->start;
+ platform_set_drvdata(pdev, &neo1973_vib_led);
+
+ /* TOUT3 */
+ if (neo1973_vib_led.gpio == S3C2410_GPB3) {
+ rc = neo1973_vib_init_hw(&neo1973_vib_led);
+ if (rc)
+ return rc;
+
+ s3c2410_pwm_duty_cycle(0, &neo1973_vib_led.pwm);
+ s3c2410_gpio_cfgpin(neo1973_vib_led.gpio, S3C2410_GPB3_TOUT3);
+ neo1973_vib_led.has_pwm = 1;
+ }
+
+ mutex_init(&neo1973_vib_led.mutex);
+
+ return led_classdev_register(&pdev->dev, &neo1973_vib_led.cdev);
+}
+
+static int neo1973_vib_remove(struct platform_device *pdev)
+{
+ if (neo1973_vib_led.has_pwm)
+ s3c2410_pwm_disable(&neo1973_vib_led.pwm);
+
+ led_classdev_unregister(&neo1973_vib_led.cdev);
+
+ mutex_destroy(&neo1973_vib_led.mutex);
+
+ return 0;
+}
+
+static struct platform_driver neo1973_vib_driver = {
+ .probe = neo1973_vib_probe,
+ .remove = neo1973_vib_remove,
+#ifdef CONFIG_PM
+ .suspend = neo1973_vib_suspend,
+ .resume = neo1973_vib_resume,
+#endif
+ .driver = {
+ .name = "neo1973-vibrator",
+ },
+};
+
+static int __init neo1973_vib_init(void)
+{
+ return platform_driver_register(&neo1973_vib_driver);
+}
+
+static void __exit neo1973_vib_exit(void)
+{
+ platform_driver_unregister(&neo1973_vib_driver);
+}
+
+module_init(neo1973_vib_init);
+module_exit(neo1973_vib_exit);
+
+MODULE_AUTHOR("Harald Welte <laforge@openmoko.org>");
+MODULE_DESCRIPTION("FIC Neo1973 vibrator driver");
+MODULE_LICENSE("GPL");
--
1.5.6.3

View file

@ -0,0 +1,308 @@
From deee418974cd5cc3b1aa9b1329d91b50f8bb7baf Mon Sep 17 00:00:00 2001
From: mokopatches <mokopatches@openmoko.org>
Date: Wed, 16 Jul 2008 14:44:49 +0100
Subject: [PATCH] gta01-backlight.patch
This is a backlight driver for the FIC/OpenMoko Neo1973 GTA01 GSM Phone
Signed-off-by: Harald Welte <laforge@openmoko.org>
---
drivers/video/backlight/Kconfig | 7 +
drivers/video/backlight/Makefile | 1 +
drivers/video/backlight/gta01_bl.c | 255 ++++++++++++++++++++++++++++++++++++
3 files changed, 263 insertions(+), 0 deletions(-)
create mode 100644 drivers/video/backlight/gta01_bl.c
diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig
index dcd8073..475db76 100644
--- a/drivers/video/backlight/Kconfig
+++ b/drivers/video/backlight/Kconfig
@@ -89,6 +89,13 @@ config BACKLIGHT_OMAP1
the PWL module of OMAP1 processors. Say Y if your board
uses this hardware.
+config BACKLIGHT_GTA01
+ tristate "FIC Neo1973 GTA01 Backlight Driver"
+ depends on BACKLIGHT_CLASS_DEVICE && MACH_NEO1973_GTA01
+ default y
+ help
+ If you have a FIC Neo1973 GTA01, say y to enable the backlight driver.
+
config BACKLIGHT_HP680
tristate "HP Jornada 680 Backlight Driver"
depends on BACKLIGHT_CLASS_DEVICE && SH_HP6XX
diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile
index 33f6c7c..aee9f46 100644
--- a/drivers/video/backlight/Makefile
+++ b/drivers/video/backlight/Makefile
@@ -5,6 +5,7 @@ obj-$(CONFIG_LCD_LTV350QV) += ltv350qv.o
obj-$(CONFIG_BACKLIGHT_CLASS_DEVICE) += backlight.o
obj-$(CONFIG_BACKLIGHT_CORGI) += corgi_bl.o
+obj-$(CONFIG_BACKLIGHT_GTA01) += gta01_bl.o
obj-$(CONFIG_BACKLIGHT_HP680) += hp680_bl.o
obj-$(CONFIG_BACKLIGHT_LOCOMO) += locomolcd.o
obj-$(CONFIG_BACKLIGHT_OMAP1) += omap1_bl.o
diff --git a/drivers/video/backlight/gta01_bl.c b/drivers/video/backlight/gta01_bl.c
new file mode 100644
index 0000000..c2bf0c9
--- /dev/null
+++ b/drivers/video/backlight/gta01_bl.c
@@ -0,0 +1,255 @@
+/*
+ * Backlight Driver for FIC GTA01 (Neo1973) GSM Phone
+ *
+ * Copyright (C) 2006-2007 by OpenMoko, Inc.
+ * Author: Harald Welte <laforge@openmoko.org>
+ * All rights reserved.
+ *
+ * based on corgi_cl.c, Copyright (c) 2004-2006 Richard Purdie
+ *
+ * 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, version 2.
+ *
+ * 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
+ *
+ * Javi Roman <javiroman@kernel-labs.org>:
+ * implement PWM, instead of simple on/off switching
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/mutex.h>
+#include <linux/fb.h>
+#include <linux/backlight.h>
+#include <linux/clk.h>
+
+#include <asm/arch/hardware.h>
+#include <asm/arch/gta01.h>
+#include <asm/arch/pwm.h>
+
+#include <asm/plat-s3c/regs-timer.h>
+
+static struct backlight_properties gta01bl_prop;
+static struct backlight_device *gta01_backlight_device;
+static struct gta01bl_machinfo *bl_machinfo;
+
+static unsigned long gta01bl_flags;
+
+struct gta01bl_data {
+ int intensity;
+ struct mutex mutex;
+ struct clk *clk;
+ struct s3c2410_pwm pwm;
+};
+
+static struct gta01bl_data gta01bl;
+
+#define GTA01BL_SUSPENDED 0x01
+#define GTA01BL_BATTLOW 0x02
+
+/* On the GTA01 / Neo1973, we use a 50 or 66MHz PCLK, which gives
+ * us a 6.25..8.25MHz DIV8 clock, which is further divided by a
+ * prescaler of 4, resulting in a 1.56..2.06MHz tick. This results in a
+ * minimum frequency of 24..31Hz. At 400Hz, we need to set the count
+ * to something like 3906..5156, providing us a way sufficient resolution
+ * for display brightness adjustment. */
+#define GTA01BL_COUNTER 5156
+
+static int gta01bl_send_intensity(struct backlight_device *bd)
+{
+ int intensity = bd->props.brightness;
+
+ if (bd->props.power != FB_BLANK_UNBLANK)
+ intensity = 0;
+ if (bd->props.fb_blank != FB_BLANK_UNBLANK)
+ intensity = 0;
+ if (gta01bl_flags & GTA01BL_SUSPENDED)
+ intensity = 0;
+ if (gta01bl_flags & GTA01BL_BATTLOW)
+ intensity &= bl_machinfo->limit_mask;
+
+ mutex_lock(&gta01bl.mutex);
+#ifdef GTA01_BACKLIGHT_ONOFF_ONLY
+ if (intensity)
+ s3c2410_gpio_setpin(GTA01_GPIO_BACKLIGHT, 1);
+ else
+ s3c2410_gpio_setpin(GTA01_GPIO_BACKLIGHT, 0);
+#else
+ if (intensity == bd->props.max_brightness) {
+ s3c2410_gpio_setpin(GTA01_GPIO_BACKLIGHT, 1);
+ s3c2410_gpio_cfgpin(GTA01_GPIO_BACKLIGHT, S3C2410_GPIO_OUTPUT);
+ } else {
+ s3c2410_pwm_duty_cycle(intensity & 0xffff, &gta01bl.pwm);
+ s3c2410_gpio_cfgpin(GTA01_GPIO_BACKLIGHT, S3C2410_GPB0_TOUT0);
+ }
+#endif
+ mutex_unlock(&gta01bl.mutex);
+
+ gta01bl.intensity = intensity;
+ return 0;
+}
+
+static int gta01bl_init_hw(void)
+{
+ int rc;
+
+ rc = s3c2410_pwm_init(&gta01bl.pwm);
+ if (rc)
+ return rc;
+
+ gta01bl.pwm.timerid = PWM0;
+ gta01bl.pwm.prescaler = (4 - 1);
+ gta01bl.pwm.divider = S3C2410_TCFG1_MUX0_DIV8;
+ gta01bl.pwm.counter = GTA01BL_COUNTER;
+ gta01bl.pwm.comparer = gta01bl.pwm.counter;
+
+ rc = s3c2410_pwm_enable(&gta01bl.pwm);
+ if (rc)
+ return rc;
+
+ s3c2410_pwm_start(&gta01bl.pwm);
+
+ gta01bl_prop.max_brightness = gta01bl.pwm.counter;
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int gta01bl_suspend(struct platform_device *dev, pm_message_t state)
+{
+ gta01bl_flags |= GTA01BL_SUSPENDED;
+ gta01bl_send_intensity(gta01_backlight_device);
+ return 0;
+}
+
+static int gta01bl_resume(struct platform_device *dev)
+{
+ mutex_lock(&gta01bl.mutex);
+ gta01bl_init_hw();
+ mutex_unlock(&gta01bl.mutex);
+
+ gta01bl_flags &= ~GTA01BL_SUSPENDED;
+ gta01bl_send_intensity(gta01_backlight_device);
+ return 0;
+}
+#else
+#define gta01bl_suspend NULL
+#define gta01bl_resume NULL
+#endif
+
+static int gta01bl_get_intensity(struct backlight_device *bd)
+{
+ return gta01bl.intensity;
+}
+
+static int gta01bl_set_intensity(struct backlight_device *bd)
+{
+ gta01bl_send_intensity(gta01_backlight_device);
+ return 0;
+}
+
+/*
+ * Called when the battery is low to limit the backlight intensity.
+ * If limit==0 clear any limit, otherwise limit the intensity
+ */
+void gta01bl_limit_intensity(int limit)
+{
+ if (limit)
+ gta01bl_flags |= GTA01BL_BATTLOW;
+ else
+ gta01bl_flags &= ~GTA01BL_BATTLOW;
+ gta01bl_send_intensity(gta01_backlight_device);
+}
+EXPORT_SYMBOL_GPL(gta01bl_limit_intensity);
+
+
+static struct backlight_ops gta01bl_ops = {
+ .get_brightness = gta01bl_get_intensity,
+ .update_status = gta01bl_set_intensity,
+};
+
+static int __init gta01bl_probe(struct platform_device *pdev)
+{
+ struct gta01bl_machinfo *machinfo = pdev->dev.platform_data;
+ int rc;
+
+#ifdef GTA01_BACKLIGHT_ONOFF_ONLY
+ s3c2410_gpio_cfgpin(GTA01_GPIO_BACKLIGHT, S3C2410_GPIO_OUTPUT);
+ gta01bl_prop.max_brightness = 1;
+#else
+ rc = gta01bl_init_hw();
+ if (rc < 0)
+ return rc;
+#endif
+ mutex_init(&gta01bl.mutex);
+
+ if (!machinfo->limit_mask)
+ machinfo->limit_mask = -1;
+
+ gta01_backlight_device = backlight_device_register("gta01-bl",
+ &pdev->dev, NULL,
+ &gta01bl_ops);
+ if (IS_ERR(gta01_backlight_device))
+ return PTR_ERR(gta01_backlight_device);
+
+ gta01bl_prop.power = FB_BLANK_UNBLANK;
+ gta01bl_prop.brightness = gta01bl_prop.max_brightness;
+ memcpy(&gta01_backlight_device->props,
+ &gta01bl_prop, sizeof(gta01bl_prop));
+ gta01bl_send_intensity(gta01_backlight_device);
+
+ return 0;
+}
+
+static int gta01bl_remove(struct platform_device *dev)
+{
+#ifndef GTA01_BACKLIGHT_ONOFF_ONLY
+ s3c2410_pwm_disable(&gta01bl.pwm);
+#endif
+ backlight_device_unregister(gta01_backlight_device);
+ mutex_destroy(&gta01bl.mutex);
+
+ s3c2410_gpio_cfgpin(GTA01_GPIO_BACKLIGHT, S3C2410_GPIO_OUTPUT);
+ s3c2410_gpio_setpin(GTA01_GPIO_BACKLIGHT, 1);
+
+ return 0;
+}
+
+static struct platform_driver gta01bl_driver = {
+ .probe = gta01bl_probe,
+ .remove = gta01bl_remove,
+ .suspend = gta01bl_suspend,
+ .resume = gta01bl_resume,
+ .driver = {
+ .name = "gta01-bl",
+ },
+};
+
+static int __init gta01bl_init(void)
+{
+ return platform_driver_register(&gta01bl_driver);
+}
+
+static void __exit gta01bl_exit(void)
+{
+ platform_driver_unregister(&gta01bl_driver);
+}
+
+module_init(gta01bl_init);
+module_exit(gta01bl_exit);
+
+MODULE_DESCRIPTION("FIC GTA01 (Neo1973) Backlight Driver");
+MODULE_AUTHOR("Harald Welte <laforge@openmoko.org>");
+MODULE_LICENSE("GPL");
--
1.5.6.3

View file

@ -0,0 +1,636 @@
From fc5d5366335469828d78898e2e74f8f80aa1d076 Mon Sep 17 00:00:00 2001
From: mokopatches <mokopatches@openmoko.org>
Date: Wed, 16 Jul 2008 14:44:49 +0100
Subject: [PATCH] s3c2410_touchscreen.patch
---
arch/arm/mach-s3c2410/mach-h1940.c | 8 +
arch/arm/plat-s3c24xx/devs.c | 18 ++
arch/arm/plat-s3c24xx/s3c244x.c | 1 +
drivers/input/touchscreen/Kconfig | 18 ++
drivers/input/touchscreen/Makefile | 1 +
drivers/input/touchscreen/s3c2410_ts.c | 437 ++++++++++++++++++++++++++++++++
include/asm-arm/arch-s3c2410/ts.h | 28 ++
include/asm-arm/plat-s3c24xx/devs.h | 1 +
8 files changed, 512 insertions(+), 0 deletions(-)
create mode 100644 drivers/input/touchscreen/s3c2410_ts.c
create mode 100644 include/asm-arm/arch-s3c2410/ts.h
diff --git a/arch/arm/mach-s3c2410/mach-h1940.c b/arch/arm/mach-s3c2410/mach-h1940.c
index 7c1145e..93cd8c8 100644
--- a/arch/arm/mach-s3c2410/mach-h1940.c
+++ b/arch/arm/mach-s3c2410/mach-h1940.c
@@ -38,6 +38,7 @@
#include <asm/arch/h1940.h>
#include <asm/arch/h1940-latch.h>
#include <asm/arch/fb.h>
+#include <asm/arch/tc.h>
#include <asm/plat-s3c24xx/udc.h>
#include <asm/plat-s3c24xx/clock.h>
@@ -129,6 +130,11 @@ static struct s3c2410_udc_mach_info h1940_udc_cfg __initdata = {
.vbus_pin_inverted = 1,
};
+static struct s3c2410_ts_mach_info h1940_ts_cfg __initdata = {
+ .delay = 10000,
+ .presc = 49,
+ .oversampling_shift = 2,
+};
/**
* Set lcd on or off
@@ -186,6 +192,7 @@ static struct platform_device *h1940_devices[] __initdata = {
&s3c_device_i2c,
&s3c_device_iis,
&s3c_device_usbgadget,
+ &s3c_device_ts,
&s3c_device_leds,
&s3c_device_bluetooth,
};
@@ -214,6 +221,7 @@ static void __init h1940_init(void)
u32 tmp;
s3c24xx_fb_set_platdata(&h1940_fb_info);
+ set_s3c2410ts_info(&h1940_ts_cfg);
s3c24xx_udc_set_platdata(&h1940_udc_cfg);
/* Turn off suspend on both USB ports, and switch the
diff --git a/arch/arm/plat-s3c24xx/devs.c b/arch/arm/plat-s3c24xx/devs.c
index e546e93..c1fbe2d 100644
--- a/arch/arm/plat-s3c24xx/devs.c
+++ b/arch/arm/plat-s3c24xx/devs.c
@@ -24,6 +24,7 @@
#include <asm/mach/map.h>
#include <asm/mach/irq.h>
#include <asm/arch/fb.h>
+#include <asm/arch/ts.h>
#include <asm/hardware.h>
#include <asm/io.h>
#include <asm/irq.h>
@@ -207,6 +208,23 @@ struct platform_device s3c_device_nand = {
EXPORT_SYMBOL(s3c_device_nand);
+/* Touchscreen */
+struct platform_device s3c_device_ts = {
+ .name = "s3c2410-ts",
+ .id = -1,
+};
+
+EXPORT_SYMBOL(s3c_device_ts);
+
+static struct s3c2410_ts_mach_info s3c2410ts_info;
+
+void set_s3c2410ts_info(struct s3c2410_ts_mach_info *hard_s3c2410ts_info)
+{
+ memcpy(&s3c2410ts_info,hard_s3c2410ts_info,sizeof(struct s3c2410_ts_mach_info));
+ s3c_device_ts.dev.platform_data = &s3c2410ts_info;
+}
+EXPORT_SYMBOL(set_s3c2410ts_info);
+
/* USB Device (Gadget)*/
static struct resource s3c_usbgadget_resource[] = {
diff --git a/arch/arm/plat-s3c24xx/s3c244x.c b/arch/arm/plat-s3c24xx/s3c244x.c
index 2f01af5..7a1a12d 100644
--- a/arch/arm/plat-s3c24xx/s3c244x.c
+++ b/arch/arm/plat-s3c24xx/s3c244x.c
@@ -68,6 +68,7 @@ void __init s3c244x_map_io(struct map_desc *mach_desc, int size)
s3c_device_sdi.name = "s3c2440-sdi";
s3c_device_i2c.name = "s3c2440-i2c";
s3c_device_nand.name = "s3c2440-nand";
+ s3c_device_ts.name = "s3c2440-ts";
s3c_device_usbgadget.name = "s3c2440-usbgadget";
}
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index 565ec71..52de2b0 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -67,6 +67,24 @@ config TOUCHSCREEN_FUJITSU
To compile this driver as a module, choose M here: the
module will be called fujitsu-ts.
+config TOUCHSCREEN_S3C2410
+ tristate "Samsung S3C2410 touchscreen input driver"
+ depends on ARCH_S3C2410 && INPUT && INPUT_TOUCHSCREEN
+ select SERIO
+ help
+ Say Y here if you have the s3c2410 touchscreen.
+
+ If unsure, say N.
+
+ To compile this driver as a module, choose M here: the
+ module will be called s3c2410_ts.
+
+config TOUCHSCREEN_S3C2410_DEBUG
+ boolean "Samsung S3C2410 touchscreen debug messages"
+ depends on TOUCHSCREEN_S3C2410
+ help
+ Select this if you want debug messages
+
config TOUCHSCREEN_GUNZE
tristate "Gunze AHL-51S touchscreen"
select SERIO
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
index 3c096d7..7c3bd1c 100644
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -26,3 +26,4 @@ wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9705) += wm9705.o
wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9712) += wm9712.o
wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9713) += wm9713.o
obj-$(CONFIG_TOUCHSCREEN_WM97XX_MAINSTONE) += mainstone-wm97xx.o
+obj-$(CONFIG_TOUCHSCREEN_S3C2410) += s3c2410_ts.o
diff --git a/drivers/input/touchscreen/s3c2410_ts.c b/drivers/input/touchscreen/s3c2410_ts.c
new file mode 100644
index 0000000..68071c2
--- /dev/null
+++ b/drivers/input/touchscreen/s3c2410_ts.c
@@ -0,0 +1,437 @@
+/*
+ * 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
+ *
+ * Copyright (c) 2004 Arnaud Patard <arnaud.patard@rtp-net.org>
+ * iPAQ H1940 touchscreen support
+ *
+ * ChangeLog
+ *
+ * 2004-09-05: Herbert Pötzl <herbert@13thfloor.at>
+ * - added clock (de-)allocation code
+ *
+ * 2005-03-06: Arnaud Patard <arnaud.patard@rtp-net.org>
+ * - h1940_ -> s3c2410 (this driver is now also used on the n30
+ * machines :P)
+ * - Debug messages are now enabled with the config option
+ * TOUCHSCREEN_S3C2410_DEBUG
+ * - Changed the way the value are read
+ * - Input subsystem should now work
+ * - Use ioremap and readl/writel
+ *
+ * 2005-03-23: Arnaud Patard <arnaud.patard@rtp-net.org>
+ * - Make use of some undocumented features of the touchscreen
+ * controller
+ *
+ * 2007-05-23: Harald Welte <laforge@openmoko.org>
+ * - Add proper support for S32440
+ */
+
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/input.h>
+#include <linux/init.h>
+#include <linux/serio.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+
+#include <asm/arch/regs-gpio.h>
+#include <asm/arch/ts.h>
+
+#include <asm/plat-s3c/regs-adc.h>
+
+/* For ts.dev.id.version */
+#define S3C2410TSVERSION 0x0101
+
+#define TSC_SLEEP (S3C2410_ADCTSC_PULL_UP_DISABLE | S3C2410_ADCTSC_XY_PST(0))
+
+#define WAIT4INT(x) (((x)<<8) | \
+ S3C2410_ADCTSC_YM_SEN | S3C2410_ADCTSC_YP_SEN | S3C2410_ADCTSC_XP_SEN | \
+ S3C2410_ADCTSC_XY_PST(3))
+
+#define AUTOPST (S3C2410_ADCTSC_YM_SEN | S3C2410_ADCTSC_YP_SEN | S3C2410_ADCTSC_XP_SEN | \
+ S3C2410_ADCTSC_AUTO_PST | S3C2410_ADCTSC_XY_PST(0))
+
+#define DEBUG_LVL KERN_DEBUG
+
+MODULE_AUTHOR("Arnaud Patard <arnaud.patard@rtp-net.org>");
+MODULE_DESCRIPTION("s3c2410 touchscreen driver");
+MODULE_LICENSE("GPL");
+
+/*
+ * Definitions & global arrays.
+ */
+
+
+static char *s3c2410ts_name = "s3c2410 TouchScreen";
+
+/*
+ * Per-touchscreen data.
+ */
+
+struct s3c2410ts {
+ struct input_dev *dev;
+ long xp;
+ long yp;
+ int count;
+ int shift;
+};
+
+static struct s3c2410ts ts;
+static void __iomem *base_addr;
+
+static inline void s3c2410_ts_connect(void)
+{
+ s3c2410_gpio_cfgpin(S3C2410_GPG12, S3C2410_GPG12_XMON);
+ s3c2410_gpio_cfgpin(S3C2410_GPG13, S3C2410_GPG13_nXPON);
+ s3c2410_gpio_cfgpin(S3C2410_GPG14, S3C2410_GPG14_YMON);
+ s3c2410_gpio_cfgpin(S3C2410_GPG15, S3C2410_GPG15_nYPON);
+}
+
+static void touch_timer_fire(unsigned long data)
+{
+ unsigned long data0;
+ unsigned long data1;
+ int updown;
+
+ data0 = readl(base_addr+S3C2410_ADCDAT0);
+ data1 = readl(base_addr+S3C2410_ADCDAT1);
+
+ updown = (!(data0 & S3C2410_ADCDAT0_UPDOWN)) && (!(data1 & S3C2410_ADCDAT0_UPDOWN));
+
+ if (updown) {
+ if (ts.count != 0) {
+ ts.xp >>= ts.shift;
+ ts.yp >>= ts.shift;
+
+#ifdef CONFIG_TOUCHSCREEN_S3C2410_DEBUG
+ {
+ struct timeval tv;
+ do_gettimeofday(&tv);
+ printk(DEBUG_LVL "T: %06d, X: %03ld, Y: %03ld\n", (int)tv.tv_usec, ts.xp, ts.yp);
+ }
+#endif
+
+ input_report_abs(ts.dev, ABS_X, ts.xp);
+ input_report_abs(ts.dev, ABS_Y, ts.yp);
+
+ input_report_key(ts.dev, BTN_TOUCH, 1);
+ input_report_abs(ts.dev, ABS_PRESSURE, 1);
+ input_sync(ts.dev);
+ }
+
+ ts.xp = 0;
+ ts.yp = 0;
+ ts.count = 0;
+
+ writel(S3C2410_ADCTSC_PULL_UP_DISABLE | AUTOPST, base_addr+S3C2410_ADCTSC);
+ writel(readl(base_addr+S3C2410_ADCCON) | S3C2410_ADCCON_ENABLE_START, base_addr+S3C2410_ADCCON);
+ } else {
+ ts.count = 0;
+
+ input_report_key(ts.dev, BTN_TOUCH, 0);
+ input_report_abs(ts.dev, ABS_PRESSURE, 0);
+ input_sync(ts.dev);
+
+ writel(WAIT4INT(0), base_addr+S3C2410_ADCTSC);
+ }
+}
+
+static struct timer_list touch_timer =
+ TIMER_INITIALIZER(touch_timer_fire, 0, 0);
+
+static irqreturn_t stylus_updown(int irq, void *dev_id)
+{
+ unsigned long data0;
+ unsigned long data1;
+ int updown;
+
+ data0 = readl(base_addr+S3C2410_ADCDAT0);
+ data1 = readl(base_addr+S3C2410_ADCDAT1);
+
+ updown = (!(data0 & S3C2410_ADCDAT0_UPDOWN)) && (!(data1 & S3C2410_ADCDAT0_UPDOWN));
+
+ /* TODO we should never get an interrupt with updown set while
+ * the timer is running, but maybe we ought to verify that the
+ * timer isn't running anyways. */
+
+ if (updown)
+ touch_timer_fire(0);
+
+ return IRQ_HANDLED;
+}
+
+
+static irqreturn_t stylus_action(int irq, void *dev_id)
+{
+ unsigned long data0;
+ unsigned long data1;
+
+ data0 = readl(base_addr+S3C2410_ADCDAT0);
+ data1 = readl(base_addr+S3C2410_ADCDAT1);
+
+ ts.xp += data0 & S3C2410_ADCDAT0_XPDATA_MASK;
+ ts.yp += data1 & S3C2410_ADCDAT1_YPDATA_MASK;
+ ts.count++;
+
+ if (ts.count < (1<<ts.shift)) {
+ writel(S3C2410_ADCTSC_PULL_UP_DISABLE | AUTOPST, base_addr+S3C2410_ADCTSC);
+ writel(readl(base_addr+S3C2410_ADCCON) | S3C2410_ADCCON_ENABLE_START, base_addr+S3C2410_ADCCON);
+ } else {
+ mod_timer(&touch_timer, jiffies+1);
+ writel(WAIT4INT(1), base_addr+S3C2410_ADCTSC);
+ }
+
+ return IRQ_HANDLED;
+}
+
+static struct clk *adc_clock;
+
+/*
+ * The functions for inserting/removing us as a module.
+ */
+
+static int __init s3c2410ts_probe(struct platform_device *pdev)
+{
+ int rc;
+ struct s3c2410_ts_mach_info *info;
+ struct input_dev *input_dev;
+
+ info = ( struct s3c2410_ts_mach_info *)pdev->dev.platform_data;
+
+ if (!info)
+ {
+ printk(KERN_ERR "Hm... too bad : no platform data for ts\n");
+ return -EINVAL;
+ }
+
+#ifdef CONFIG_TOUCHSCREEN_S3C2410_DEBUG
+ printk(DEBUG_LVL "Entering s3c2410ts_init\n");
+#endif
+
+ adc_clock = clk_get(NULL, "adc");
+ if (!adc_clock) {
+ printk(KERN_ERR "failed to get adc clock source\n");
+ return -ENOENT;
+ }
+ clk_enable(adc_clock);
+
+#ifdef CONFIG_TOUCHSCREEN_S3C2410_DEBUG
+ printk(DEBUG_LVL "got and enabled clock\n");
+#endif
+
+ base_addr = ioremap(S3C2410_PA_ADC,0x20);
+ if (base_addr == NULL) {
+ printk(KERN_ERR "Failed to remap register block\n");
+ return -ENOMEM;
+ }
+
+
+ /* If we acutally are a S3C2410: Configure GPIOs */
+ if (!strcmp(pdev->name, "s3c2410-ts"))
+ s3c2410_ts_connect();
+
+ if ((info->presc&0xff) > 0)
+ writel(S3C2410_ADCCON_PRSCEN | S3C2410_ADCCON_PRSCVL(info->presc&0xFF),\
+ base_addr+S3C2410_ADCCON);
+ else
+ writel(0,base_addr+S3C2410_ADCCON);
+
+
+ /* Initialise registers */
+ if ((info->delay&0xffff) > 0)
+ writel(info->delay & 0xffff, base_addr+S3C2410_ADCDLY);
+
+ writel(WAIT4INT(0), base_addr+S3C2410_ADCTSC);
+
+ /* Initialise input stuff */
+ memset(&ts, 0, sizeof(struct s3c2410ts));
+ input_dev = input_allocate_device();
+
+ if (!input_dev) {
+ printk(KERN_ERR "Unable to allocate the input device !!\n");
+ return -ENOMEM;
+ }
+
+ ts.dev = input_dev;
+ ts.dev->evbit[0] = BIT_MASK(EV_SYN) | BIT_MASK(EV_KEY) |
+ BIT_MASK(EV_ABS);
+ ts.dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
+ input_set_abs_params(ts.dev, ABS_X, 0, 0x3FF, 0, 0);
+ input_set_abs_params(ts.dev, ABS_Y, 0, 0x3FF, 0, 0);
+ input_set_abs_params(ts.dev, ABS_PRESSURE, 0, 1, 0, 0);
+
+ ts.dev->private = &ts;
+ ts.dev->name = s3c2410ts_name;
+ ts.dev->id.bustype = BUS_RS232;
+ ts.dev->id.vendor = 0xDEAD;
+ ts.dev->id.product = 0xBEEF;
+ ts.dev->id.version = S3C2410TSVERSION;
+
+ ts.shift = info->oversampling_shift;
+
+ /* Get irqs */
+ if (request_irq(IRQ_ADC, stylus_action, IRQF_SAMPLE_RANDOM,
+ "s3c2410_action", ts.dev)) {
+ printk(KERN_ERR "s3c2410_ts.c: Could not allocate ts IRQ_ADC !\n");
+ iounmap(base_addr);
+ return -EIO;
+ }
+ if (request_irq(IRQ_TC, stylus_updown, IRQF_SAMPLE_RANDOM,
+ "s3c2410_action", ts.dev)) {
+ printk(KERN_ERR "s3c2410_ts.c: Could not allocate ts IRQ_TC !\n");
+ free_irq(IRQ_ADC, ts.dev);
+ iounmap(base_addr);
+ return -EIO;
+ }
+
+ printk(KERN_INFO "%s successfully loaded\n", s3c2410ts_name);
+
+ /* All went ok, so register to the input system */
+ rc = input_register_device(ts.dev);
+ if (rc) {
+ free_irq(IRQ_TC, ts.dev);
+ free_irq(IRQ_ADC, ts.dev);
+ clk_disable(adc_clock);
+ iounmap(base_addr);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int s3c2410ts_remove(struct platform_device *pdev)
+{
+ disable_irq(IRQ_ADC);
+ disable_irq(IRQ_TC);
+ free_irq(IRQ_TC,ts.dev);
+ free_irq(IRQ_ADC,ts.dev);
+
+ if (adc_clock) {
+ clk_disable(adc_clock);
+ clk_put(adc_clock);
+ adc_clock = NULL;
+ }
+
+ input_unregister_device(ts.dev);
+ iounmap(base_addr);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int s3c2410ts_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ writel(TSC_SLEEP, base_addr+S3C2410_ADCTSC);
+ writel(readl(base_addr+S3C2410_ADCCON) | S3C2410_ADCCON_STDBM,
+ base_addr+S3C2410_ADCCON);
+
+ disable_irq(IRQ_ADC);
+ disable_irq(IRQ_TC);
+
+ clk_disable(adc_clock);
+
+ return 0;
+}
+
+static int s3c2410ts_resume(struct platform_device *pdev)
+{
+ struct s3c2410_ts_mach_info *info =
+ ( struct s3c2410_ts_mach_info *)pdev->dev.platform_data;
+
+ clk_enable(adc_clock);
+ msleep(1);
+
+ enable_irq(IRQ_ADC);
+ enable_irq(IRQ_TC);
+
+ if ((info->presc&0xff) > 0)
+ writel(S3C2410_ADCCON_PRSCEN | S3C2410_ADCCON_PRSCVL(info->presc&0xFF),\
+ base_addr+S3C2410_ADCCON);
+ else
+ writel(0,base_addr+S3C2410_ADCCON);
+
+ /* Initialise registers */
+ if ((info->delay&0xffff) > 0)
+ writel(info->delay & 0xffff, base_addr+S3C2410_ADCDLY);
+
+ writel(WAIT4INT(0), base_addr+S3C2410_ADCTSC);
+
+ return 0;
+}
+
+#else
+#define s3c2410ts_suspend NULL
+#define s3c2410ts_resume NULL
+#endif
+
+static struct platform_driver s3c2410ts_driver = {
+ .driver = {
+ .name = "s3c2410-ts",
+ .owner = THIS_MODULE,
+ },
+ .probe = s3c2410ts_probe,
+ .remove = s3c2410ts_remove,
+ .suspend = s3c2410ts_suspend,
+ .resume = s3c2410ts_resume,
+
+};
+
+static struct platform_driver s3c2440ts_driver = {
+ .driver = {
+ .name = "s3c2440-ts",
+ .owner = THIS_MODULE,
+ },
+ .probe = s3c2410ts_probe,
+ .remove = s3c2410ts_remove,
+ .suspend = s3c2410ts_suspend,
+ .resume = s3c2410ts_resume,
+
+};
+
+static int __init s3c2410ts_init(void)
+{
+ int rc;
+
+ rc = platform_driver_register(&s3c2410ts_driver);
+ if (rc < 0)
+ return rc;
+
+ rc = platform_driver_register(&s3c2440ts_driver);
+ if (rc < 0)
+ platform_driver_unregister(&s3c2410ts_driver);
+
+ return rc;
+}
+
+static void __exit s3c2410ts_exit(void)
+{
+ platform_driver_unregister(&s3c2440ts_driver);
+ platform_driver_unregister(&s3c2410ts_driver);
+}
+
+module_init(s3c2410ts_init);
+module_exit(s3c2410ts_exit);
+
+/*
+ Local variables:
+ compile-command: "make ARCH=arm CROSS_COMPILE=/usr/local/arm/3.3.2/bin/arm-linux- -k -C ../../.."
+ c-basic-offset: 8
+ End:
+*/
diff --git a/include/asm-arm/arch-s3c2410/ts.h b/include/asm-arm/arch-s3c2410/ts.h
new file mode 100644
index 0000000..593632a
--- /dev/null
+++ b/include/asm-arm/arch-s3c2410/ts.h
@@ -0,0 +1,28 @@
+/* linux/include/asm/arch-s3c2410/ts.h
+ *
+ * Copyright (c) 2005 Arnaud Patard <arnaud.patard@rtp-net.org>
+ *
+ *
+ * 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:
+ * 24-Mar-2005 RTP Created file
+ * 03-Aug-2005 RTP Renamed to ts.h
+ */
+
+#ifndef __ASM_ARM_TS_H
+#define __ASM_ARM_TS_H
+
+struct s3c2410_ts_mach_info {
+ int delay;
+ int presc;
+ int oversampling_shift;
+};
+
+void set_s3c2410ts_info(struct s3c2410_ts_mach_info *hard_s3c2410ts_info);
+
+#endif /* __ASM_ARM_TS_H */
+
diff --git a/include/asm-arm/plat-s3c24xx/devs.h b/include/asm-arm/plat-s3c24xx/devs.h
index f9d6f03..43de9cc 100644
--- a/include/asm-arm/plat-s3c24xx/devs.h
+++ b/include/asm-arm/plat-s3c24xx/devs.h
@@ -42,6 +42,7 @@ extern struct platform_device s3c_device_timer2;
extern struct platform_device s3c_device_timer3;
extern struct platform_device s3c_device_usbgadget;
+extern struct platform_device s3c_device_ts;
/* s3c2440 specific devices */
--
1.5.6.3

View file

@ -0,0 +1,53 @@
From 4c5bb8608de01a165a32432a4091613bb12303fc Mon Sep 17 00:00:00 2001
From: mokopatches <mokopatches@openmoko.org>
Date: Wed, 16 Jul 2008 14:44:49 +0100
Subject: [PATCH] s3c2410_ts-gta01.patch
---
arch/arm/mach-s3c2410/mach-gta01.c | 9 +++++++++
1 files changed, 9 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-s3c2410/mach-gta01.c b/arch/arm/mach-s3c2410/mach-gta01.c
index e690ed7..3462c7f 100644
--- a/arch/arm/mach-s3c2410/mach-gta01.c
+++ b/arch/arm/mach-s3c2410/mach-gta01.c
@@ -33,6 +33,7 @@
#include <linux/workqueue.h>
#include <linux/platform_device.h>
#include <linux/serial_core.h>
+#include <asm/arch/ts.h>
#include <linux/spi/spi.h>
#include <linux/spi/spi_bitbang.h>
#include <linux/mmc/mmc.h>
@@ -362,6 +363,7 @@ static struct platform_device *gta01_devices[] __initdata = {
&s3c_device_sdi,
&s3c_device_usbgadget,
&s3c_device_nand,
+ &s3c_device_ts,
};
static struct s3c2410_nand_set gta01_nand_sets[] = {
@@ -434,6 +436,12 @@ static struct s3c2410_udc_mach_info gta01_udc_cfg = {
.vbus_draw = gta01_udc_vbus_draw,
};
+static struct s3c2410_ts_mach_info gta01_ts_cfg = {
+ .delay = 10000,
+ .presc = 65,
+ .oversampling_shift = 5,
+};
+
/* SPI */
static struct spi_board_info gta01_spi_board_info[] = {
@@ -599,6 +607,7 @@ static void __init gta01_machine_init(void)
INIT_WORK(&gta01_udc_vbus_drawer.work, __gta01_udc_vbus_draw);
s3c24xx_udc_set_platdata(&gta01_udc_cfg);
+ set_s3c2410ts_info(&gta01_ts_cfg);
/* Set LCD_RESET / XRES to high */
s3c2410_gpio_cfgpin(S3C2410_GPC6, S3C2410_GPIO_OUTPUT);
--
1.5.6.3

View file

@ -0,0 +1,33 @@
From 839b25d6bcef4b1609aaa53d018cdbc59ea4efa7 Mon Sep 17 00:00:00 2001
From: mokopatches <mokopatches@openmoko.org>
Date: Wed, 16 Jul 2008 14:44:50 +0100
Subject: [PATCH] i2c-permit_invalid_addrs.patch
We need this stupid workaround since our amplifier chip uses a 'reserved' I2C
address
Signed-off-by: Harald Welte <laforge@openmoko.org>
---
drivers/i2c/i2c-core.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index d0175f4..bb0c5e5 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -1026,11 +1026,11 @@ static int i2c_probe_address(struct i2c_adapter *adapter, int addr, int kind,
int err;
/* Make sure the address is valid */
- if (addr < 0x03 || addr > 0x77) {
+ /*if (addr < 0x03 || addr > 0x77) {
dev_warn(&adapter->dev, "Invalid probe address 0x%02x\n",
addr);
return -EINVAL;
- }
+ }*/
/* Skip if already in use */
if (i2c_check_addr(adapter, addr))
--
1.5.6.3

View file

@ -0,0 +1,34 @@
From c03d30af20838833c54f9e9684f38b7048e369d3 Mon Sep 17 00:00:00 2001
From: mokopatches <mokopatches@openmoko.org>
Date: Wed, 16 Jul 2008 14:44:50 +0100
Subject: [PATCH] g_ether-highpower.patch
---
drivers/usb/gadget/ether.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c
index 8d61ea6..066a3e7 100644
--- a/drivers/usb/gadget/ether.c
+++ b/drivers/usb/gadget/ether.c
@@ -464,7 +464,7 @@ eth_config = {
.bConfigurationValue = DEV_CONFIG_VALUE,
.iConfiguration = STRING_CDC,
.bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
- .bMaxPower = 50,
+ .bMaxPower = 250,
};
#ifdef CONFIG_USB_ETH_RNDIS
@@ -478,7 +478,7 @@ rndis_config = {
.bConfigurationValue = DEV_RNDIS_CONFIG_VALUE,
.iConfiguration = STRING_RNDIS,
.bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
- .bMaxPower = 50,
+ .bMaxPower = 250,
};
#endif
--
1.5.6.3

View file

@ -0,0 +1,44 @@
From 5ca57da3402b856986ac1e1ce316937207f6cbad Mon Sep 17 00:00:00 2001
From: mokopatches <mokopatches@openmoko.org>
Date: Wed, 16 Jul 2008 14:44:50 +0100
Subject: [PATCH] g_ether-vendor_product.patch
Use FIC's own USB Vendor ID rather than NetChip's
Yes, we could solve this by some modprobe.conf parameters, but I'd like to
rather not rely on this.
---
drivers/usb/gadget/ether.c | 11 ++++-------
1 files changed, 4 insertions(+), 7 deletions(-)
diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c
index 066a3e7..a474b0d 100644
--- a/drivers/usb/gadget/ether.c
+++ b/drivers/usb/gadget/ether.c
@@ -134,11 +134,8 @@ struct eth_dev {
* Instead: allocate your own, using normal USB-IF procedures.
*/
-/* Thanks to NetChip Technologies for donating this product ID.
- * It's for devices with only CDC Ethernet configurations.
- */
-#define CDC_VENDOR_NUM 0x0525 /* NetChip */
-#define CDC_PRODUCT_NUM 0xa4a1 /* Linux-USB Ethernet Gadget */
+#define CDC_VENDOR_NUM 0x1457 /* First International Computer */
+#define CDC_PRODUCT_NUM 0x5117 /* Linux-USB Ethernet Gadget */
/* For hardware that can't talk CDC, we use the same vendor ID that
* ARM Linux has used for ethernet-over-usb, both with sa1100 and
@@ -159,8 +156,8 @@ struct eth_dev {
* used with CDC Ethernet, Linux 2.4 hosts will need updates to choose
* the non-RNDIS configuration.
*/
-#define RNDIS_VENDOR_NUM 0x0525 /* NetChip */
-#define RNDIS_PRODUCT_NUM 0xa4a2 /* Ethernet/RNDIS Gadget */
+#define RNDIS_VENDOR_NUM 0x1457 /* NetChip */
+#define RNDIS_PRODUCT_NUM 0x5122 /* Ethernet/RNDIS Gadget */
/* Some systems will want different product identifers published in the
--
1.5.6.3

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,97 @@
From d63b12e946e83c7db8c9f94ae9d5d9d420a6f907 Mon Sep 17 00:00:00 2001
From: mokopatches <mokopatches@openmoko.org>
Date: Wed, 16 Jul 2008 14:44:50 +0100
Subject: [PATCH] s3c_mci-gta01.patch
---
arch/arm/mach-s3c2410/mach-gta01.c | 56 ++++++++++++++++++++++++++++++++++++
1 files changed, 56 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-s3c2410/mach-gta01.c b/arch/arm/mach-s3c2410/mach-gta01.c
index 3462c7f..87bb189 100644
--- a/arch/arm/mach-s3c2410/mach-gta01.c
+++ b/arch/arm/mach-s3c2410/mach-gta01.c
@@ -59,6 +59,7 @@
#include <asm/arch/regs-gpio.h>
#include <asm/arch/fb.h>
+#include <asm/arch/mci.h>
#include <asm/arch/spi.h>
#include <asm/arch/spi-gpio.h>
#include <asm/arch/usb-control.h>
@@ -382,6 +383,59 @@ static struct s3c2410_platform_nand gta01_nand_info = {
.sets = gta01_nand_sets,
};
+static void gta01_mmc_set_power(unsigned char power_mode, unsigned short vdd)
+{
+ int bit;
+ int mv = 1700; /* 1.7V for MMC_VDD_165_195 */
+
+ printk(KERN_DEBUG "mmc_set_power(power_mode=%u, vdd=%u\n",
+ power_mode, vdd);
+
+ switch (system_rev) {
+ case GTA01v3_SYSTEM_REV:
+ switch (power_mode) {
+ case MMC_POWER_OFF:
+ pcf50606_onoff_set(pcf50606_global,
+ PCF50606_REGULATOR_D2REG, 0);
+ break;
+ case MMC_POWER_ON:
+ /* translate MMC_VDD_* VDD bit to mv */
+ for (bit = 8; bit != 24; bit++)
+ if (vdd == (1 << bit))
+ mv += 100 * (bit - 4);
+ pcf50606_voltage_set(pcf50606_global,
+ PCF50606_REGULATOR_D2REG, mv);
+ pcf50606_onoff_set(pcf50606_global,
+ PCF50606_REGULATOR_D2REG, 1);
+ break;
+ }
+ break;
+ case GTA01v4_SYSTEM_REV:
+ case GTA01Bv2_SYSTEM_REV:
+ case GTA01Bv3_SYSTEM_REV:
+ case GTA01Bv4_SYSTEM_REV:
+ switch (power_mode) {
+ case MMC_POWER_OFF:
+ s3c2410_gpio_setpin(GTA01_GPIO_SDMMC_ON, 1);
+ break;
+ case MMC_POWER_ON:
+ s3c2410_gpio_setpin(GTA01_GPIO_SDMMC_ON, 0);
+ break;
+ }
+ break;
+ }
+}
+
+static struct s3c24xx_mci_pdata gta01_mmc_cfg = {
+ .gpio_detect = GTA01_GPIO_nSD_DETECT,
+ .set_power = &gta01_mmc_set_power,
+ .ocr_avail = MMC_VDD_165_195|MMC_VDD_20_21|
+ MMC_VDD_21_22|MMC_VDD_22_23|MMC_VDD_23_24|
+ MMC_VDD_24_25|MMC_VDD_25_26|MMC_VDD_26_27|
+ MMC_VDD_27_28|MMC_VDD_28_29|MMC_VDD_29_30|
+ MMC_VDD_30_31|MMC_VDD_31_32|MMC_VDD_32_33,
+};
+
static void gta01_udc_command(enum s3c2410_udc_cmd_e cmd)
{
printk(KERN_DEBUG "%s(%d)\n", __func__, cmd);
@@ -598,10 +652,12 @@ static void __init gta01_machine_init(void)
system_rev == GTA01Bv3_SYSTEM_REV ||
system_rev == GTA01Bv4_SYSTEM_REV) {
gta01_udc_cfg.udc_command = gta01_udc_command;
+ gta01_mmc_cfg.ocr_avail = MMC_VDD_32_33;
}
s3c_device_usb.dev.platform_data = &gta01_usb_info;
s3c_device_nand.dev.platform_data = &gta01_nand_info;
+ s3c_device_sdi.dev.platform_data = &gta01_mmc_cfg;
s3c24xx_fb_set_platdata(&gta01_lcd_cfg);
--
1.5.6.3

View file

@ -0,0 +1,58 @@
From 68108d95040732cebf06296affaaeaaf76029c3d Mon Sep 17 00:00:00 2001
From: mokopatches <mokopatches@openmoko.org>
Date: Wed, 16 Jul 2008 14:44:50 +0100
Subject: [PATCH] s3c24xx-nand-largepage.patch
MTD: S3C24XX large page NAND support
This adds support for using large page NAND devices
with the S3C24XX NAND controller. This also adds the
file Documentation/arm/Samsung-S3C24XX/NAND.txt to
describe the differences.
Signed-off-by: Ben Dooks <ben-linux@fluff.org>
---
drivers/mtd/nand/s3c2410.c | 28 ++++++++++++++++++++++++++++
1 files changed, 28 insertions(+), 0 deletions(-)
diff --git a/drivers/mtd/nand/s3c2410.c b/drivers/mtd/nand/s3c2410.c
index cd2e1da..6e7a5b9 100644
--- a/drivers/mtd/nand/s3c2410.c
+++ b/drivers/mtd/nand/s3c2410.c
@@ -726,6 +726,34 @@ static void s3c2410_nand_update_chip(struct s3c2410_nand_info *info,
}
}
+/* s3c2410_nand_update_chip
+ *
+ * post-probe chip update, to change any items, such as the
+ * layout for large page nand
+ */
+
+static void s3c2410_nand_update_chip(struct s3c2410_nand_info *info,
+ struct s3c2410_nand_mtd *nmtd)
+{
+ struct nand_chip *chip = &nmtd->chip;
+
+ printk("%s: chip %p: %d\n", __func__, chip, chip->page_shift);
+
+ if (hardware_ecc) {
+ /* change the behaviour depending on wether we are using
+ * the large or small page nand device */
+
+ if (chip->page_shift > 10) {
+ chip->ecc.size = 256;
+ chip->ecc.bytes = 3;
+ } else {
+ chip->ecc.size = 512;
+ chip->ecc.bytes = 3;
+ chip->ecc.layout = &nand_hw_eccoob;
+ }
+ }
+}
+
/* s3c2410_nand_probe
*
* called by device layer when it finds a device matching
--
1.5.6.3

View file

@ -0,0 +1,61 @@
From 5207363cc9d50f99a2ad490eff5efa913b1c10ba Mon Sep 17 00:00:00 2001
From: mokopatches <mokopatches@openmoko.org>
Date: Wed, 16 Jul 2008 14:44:50 +0100
Subject: [PATCH] s3c2410_udc-2440_dual_packet-workaround.patch
This is a patch that seems to make the USB hangs on the S3C2440 go away. At
least a good amount of ping torture didn't make them come back so far.
The issue is that, if there are several back-to-back packets,
sometimes no interrupt is generated for one of them. This
seems to be caused by the mysterious dual packet mode, which
the USB hardware enters automatically if the endpoint size is
half that of the FIFO. (On the 2440, this is the normal
situation for bulk data endpoints.)
There is also a timing factor in this. I think what happens is
that the USB hardware automatically sends an acknowledgement
if there is only one packet in the FIFO (the FIFO has space
for two). If another packet arrives before the host has
retrieved and acknowledged the previous one, no interrupt is
generated for that second one.
However, there may be an indication. There is one undocumented
bit (none of the 244x manuals document it), OUT_CRS1_REG[1],
that seems to be set suspiciously often when this condition
occurs. There is also CLR_DATA_TOGGLE, OUT_CRS1_REG[7], which
may have a function related to this. (The Samsung manual is
rather terse on that, as usual.)
This needs to be examined further. For now, the patch seems to do the
trick.
Note that this is not a clean solution by any means, because we
might potentially get stuck in that interrupt for quite a while.
---
drivers/usb/gadget/s3c2410_udc.c | 3 +++
1 files changed, 3 insertions(+), 0 deletions(-)
diff --git a/drivers/usb/gadget/s3c2410_udc.c b/drivers/usb/gadget/s3c2410_udc.c
index 6b1ef48..c1a4379 100644
--- a/drivers/usb/gadget/s3c2410_udc.c
+++ b/drivers/usb/gadget/s3c2410_udc.c
@@ -845,6 +845,7 @@ static void s3c2410_udc_handle_ep(struct s3c2410_ep *ep)
u32 ep_csr1;
u32 idx;
+handle_ep_again:
if (likely (!list_empty(&ep->queue)))
req = list_entry(ep->queue.next,
struct s3c2410_request, queue);
@@ -884,6 +885,8 @@ static void s3c2410_udc_handle_ep(struct s3c2410_ep *ep)
if ((ep_csr1 & S3C2410_UDC_OCSR1_PKTRDY) && req) {
s3c2410_udc_read_fifo(ep,req);
+ if (s3c2410_udc_fifo_count_out())
+ goto handle_ep_again;
}
}
}
--
1.5.6.3

View file

@ -0,0 +1,56 @@
From ca652d910f40692ce558d525b61911b66202d908 Mon Sep 17 00:00:00 2001
From: mokopatches <mokopatches@openmoko.org>
Date: Wed, 16 Jul 2008 14:44:50 +0100
Subject: [PATCH] s3c2442b-cpuid.patch
Add the Samsung S3C2442B CPU idcode to the samsung s3c24xx platform code
and fix a Kconfig typo related tot the 2442.
---
arch/arm/mach-s3c2442/Kconfig | 2 +-
arch/arm/plat-s3c24xx/cpu.c | 10 ++++++++++
2 files changed, 11 insertions(+), 1 deletions(-)
diff --git a/arch/arm/mach-s3c2442/Kconfig b/arch/arm/mach-s3c2442/Kconfig
index 26d131a..6cc68a1 100644
--- a/arch/arm/mach-s3c2442/Kconfig
+++ b/arch/arm/mach-s3c2442/Kconfig
@@ -6,7 +6,7 @@
config CPU_S3C2442
bool
- depends on ARCH_S3C2410
+ depends on ARCH_S3C2440
select S3C2410_CLOCK
select S3C2410_GPIO
select S3C2410_PM if PM
diff --git a/arch/arm/plat-s3c24xx/cpu.c b/arch/arm/plat-s3c24xx/cpu.c
index f5699ca..05fb61d 100644
--- a/arch/arm/plat-s3c24xx/cpu.c
+++ b/arch/arm/plat-s3c24xx/cpu.c
@@ -72,6 +72,7 @@ static const char name_s3c2410[] = "S3C2410";
static const char name_s3c2412[] = "S3C2412";
static const char name_s3c2440[] = "S3C2440";
static const char name_s3c2442[] = "S3C2442";
+static const char name_s3c2442b[] = "S3C2442B";
static const char name_s3c2443[] = "S3C2443";
static const char name_s3c2410a[] = "S3C2410A";
static const char name_s3c2440a[] = "S3C2440A";
@@ -123,6 +124,15 @@ static struct cpu_table cpu_ids[] __initdata = {
.name = name_s3c2442
},
{
+ .idcode = 0x32440aab,
+ .idmask = 0xffffffff,
+ .map_io = s3c244x_map_io,
+ .init_clocks = s3c244x_init_clocks,
+ .init_uarts = s3c244x_init_uarts,
+ .init = s3c2442_init,
+ .name = name_s3c2442b
+ },
+ {
.idcode = 0x32412001,
.idmask = 0xffffffff,
.map_io = s3c2412_map_io,
--
1.5.6.3

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,45 @@
From c96b850a977e3b7018c5ef1b145a3c11cb160265 Mon Sep 17 00:00:00 2001
From: mokopatches <mokopatches@openmoko.org>
Date: Wed, 16 Jul 2008 14:44:50 +0100
Subject: [PATCH] pcf50633-suspend-hacks.patch
---
drivers/i2c/chips/pcf50633.c | 22 ++++++++++++++++++++--
1 files changed, 20 insertions(+), 2 deletions(-)
diff --git a/drivers/i2c/chips/pcf50633.c b/drivers/i2c/chips/pcf50633.c
index 5488084..0cf5e53 100644
--- a/drivers/i2c/chips/pcf50633.c
+++ b/drivers/i2c/chips/pcf50633.c
@@ -567,8 +567,26 @@ static void pcf50633_work(struct work_struct *work)
*/
ret = i2c_smbus_read_i2c_block_data(&pcf->client, PCF50633_REG_INT1, 5,
pcfirq);
- if (ret != 5)
- DEBUGP("Oh crap PMU IRQ register read failed %d\n", ret);
+ if (ret != 5) {
+ DEBUGP("Oh crap PMU IRQ register read failed -- "
+ "retrying later %d\n", ret);
+ /*
+ * this situation can happen during resume, just defer
+ * handling the interrupt until enough I2C is up we can
+ * actually talk to the PMU. We can't just ignore this
+ * because we are on a falling edge interrupt and our
+ * PMU interrupt source does not clear until we read these
+ * interrupt source registers.
+ */
+ if (!schedule_work(&pcf->work) && !pcf->working)
+ dev_dbg(&pcf->client.dev, "work item may be lost\n");
+
+ /* we don't put the device here, hold it for next time */
+ mutex_unlock(&pcf->working_lock);
+ /* don't spew, delaying whatever else is happening */
+ msleep(1);
+ return;
+ }
if (!pcf->coldplug_done) {
DEBUGP("PMU Coldplug init\n");
--
1.5.6.3

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,586 @@
From 70a0c17968f5151ce4f468785860e04bbc7a9d3c Mon Sep 17 00:00:00 2001
From: mokopatches <mokopatches@openmoko.org>
Date: Wed, 16 Jul 2008 14:46:56 +0100
Subject: [PATCH] gta02-power_control.patch
---
arch/arm/plat-s3c24xx/neo1973_pm_bt.c | 84 +++++++++---
arch/arm/plat-s3c24xx/neo1973_pm_gps.c | 217 ++++++++++++++++++++++++--------
arch/arm/plat-s3c24xx/neo1973_pm_gsm.c | 97 ++++++++++++--
3 files changed, 309 insertions(+), 89 deletions(-)
diff --git a/arch/arm/plat-s3c24xx/neo1973_pm_bt.c b/arch/arm/plat-s3c24xx/neo1973_pm_bt.c
index b1af441..d685ef7 100644
--- a/arch/arm/plat-s3c24xx/neo1973_pm_bt.c
+++ b/arch/arm/plat-s3c24xx/neo1973_pm_bt.c
@@ -19,7 +19,9 @@
#include <linux/pcf50606.h>
#include <asm/hardware.h>
+#include <asm/mach-types.h>
#include <asm/arch/gta01.h>
+#include <asm/arch/gta02.h>
#define DRVMSG "FIC Neo1973 Bluetooth Power Management"
@@ -27,14 +29,30 @@ static ssize_t bt_read(struct device *dev, struct device_attribute *attr,
char *buf)
{
if (!strcmp(attr->attr.name, "power_on")) {
- if (pcf50606_onoff_get(pcf50606_global,
- PCF50606_REGULATOR_D1REG) &&
- pcf50606_voltage_get(pcf50606_global,
- PCF50606_REGULATOR_D1REG) == 3100)
- goto out_1;
+ switch (machine_arch_type) {
+ case MACH_TYPE_NEO1973_GTA01:
+ if (pcf50606_onoff_get(pcf50606_global,
+ PCF50606_REGULATOR_D1REG) &&
+ pcf50606_voltage_get(pcf50606_global,
+ PCF50606_REGULATOR_D1REG) == 3100)
+ goto out_1;
+ break;
+ case MACH_TYPE_NEO1973_GTA02:
+ if (s3c2410_gpio_getpin(GTA02_GPIO_BT_EN))
+ goto out_1;
+ break;
+ }
} else if (!strcmp(attr->attr.name, "reset")) {
- if (s3c2410_gpio_getpin(GTA01_GPIO_BT_EN) == 0)
- goto out_1;
+ switch (machine_arch_type) {
+ case MACH_TYPE_NEO1973_GTA01:
+ if (s3c2410_gpio_getpin(GTA01_GPIO_BT_EN) == 0)
+ goto out_1;
+ break;
+ case MACH_TYPE_NEO1973_GTA02:
+ if (s3c2410_gpio_getpin(GTA02_GPIO_BT_EN) == 0)
+ goto out_1;
+ break;
+ }
}
return strlcpy(buf, "0\n", 3);
@@ -48,20 +66,37 @@ static ssize_t bt_write(struct device *dev, struct device_attribute *attr,
unsigned long on = simple_strtoul(buf, NULL, 10);
if (!strcmp(attr->attr.name, "power_on")) {
- /* if we are powering up, assert reset, then power, then
- * release reset */
- if (on) {
- s3c2410_gpio_setpin(GTA01_GPIO_BT_EN, 0);
- pcf50606_voltage_set(pcf50606_global,
- PCF50606_REGULATOR_D1REG,
- 3100);
+ switch (machine_arch_type) {
+ case MACH_TYPE_NEO1973_GTA01:
+ /* if we are powering up, assert reset, then power,
+ * then release reset */
+ if (on) {
+ s3c2410_gpio_setpin(GTA01_GPIO_BT_EN, 0);
+ pcf50606_voltage_set(pcf50606_global,
+ PCF50606_REGULATOR_D1REG,
+ 3100);
+ }
+ pcf50606_onoff_set(pcf50606_global,
+ PCF50606_REGULATOR_D1REG, on);
+ s3c2410_gpio_setpin(GTA01_GPIO_BT_EN, on);
+ break;
+ case MACH_TYPE_NEO1973_GTA02:
+ if (on)
+ s3c2410_gpio_setpin(GTA02_GPIO_BT_EN, 0);
+ else
+ s3c2410_gpio_setpin(GTA02_GPIO_BT_EN, 1);
+ break;
}
- pcf50606_onoff_set(pcf50606_global,
- PCF50606_REGULATOR_D1REG, on);
- s3c2410_gpio_setpin(GTA01_GPIO_BT_EN, on);
} else if (!strcmp(attr->attr.name, "reset")) {
/* reset is low-active, so we need to invert */
- s3c2410_gpio_setpin(GTA01_GPIO_BT_EN, on ? 0 : 1);
+ switch (machine_arch_type) {
+ case MACH_TYPE_NEO1973_GTA01:
+ s3c2410_gpio_setpin(GTA01_GPIO_BT_EN, on ? 0 : 1);
+ break;
+ case MACH_TYPE_NEO1973_GTA02:
+ s3c2410_gpio_setpin(GTA02_GPIO_BT_EN, on ? 0 : 1);
+ break;
+ }
}
return count;
@@ -107,9 +142,16 @@ static int __init gta01_bt_probe(struct platform_device *pdev)
{
dev_info(&pdev->dev, DRVMSG ": starting\n");
- /* we make sure that the voltage is off */
- pcf50606_onoff_set(pcf50606_global,
- PCF50606_REGULATOR_D1REG, 0);
+ switch (machine_arch_type) {
+ case MACH_TYPE_NEO1973_GTA01:
+ /* we make sure that the voltage is off */
+ pcf50606_onoff_set(pcf50606_global,
+ PCF50606_REGULATOR_D1REG, 0);
+ break;
+ case MACH_TYPE_NEO1973_GTA02:
+ /* FIXME: implementation */
+ break;
+ }
/* we pull reset to low to make sure that the chip doesn't
* drain power through the reset line */
s3c2410_gpio_setpin(GTA01_GPIO_BT_EN, 0);
diff --git a/arch/arm/plat-s3c24xx/neo1973_pm_gps.c b/arch/arm/plat-s3c24xx/neo1973_pm_gps.c
index f8cf719..6bd8054 100644
--- a/arch/arm/plat-s3c24xx/neo1973_pm_gps.c
+++ b/arch/arm/plat-s3c24xx/neo1973_pm_gps.c
@@ -17,10 +17,18 @@
#include <linux/delay.h>
#include <linux/platform_device.h>
-#include <linux/pcf50606.h>
-
#include <asm/hardware.h>
+
+#include <asm/mach-types.h>
+#ifdef CONFIG_MACH_NEO1973_GTA01
#include <asm/arch/gta01.h>
+#include <linux/pcf50606.h>
+#endif
+
+#ifdef CONFIG_MACH_NEO1973_GTA02
+#include <asm/arch/gta02.h>
+#include <linux/pcf50633.h>
+#endif
/* This is the 2.8V supply for the RTC crystal, the mail clock crystal and
* the input to VDD_RF */
@@ -248,15 +256,42 @@ static int gps_power_1v5_get(void)
/* This is the POWERON pin */
static void gps_pwron_set(int on)
{
- s3c2410_gpio_setpin(GTA01_GPIO_GPS_PWRON, on);
+#ifdef CONFIG_MACH_NEO1973_GTA01
+ if (machine_is_neo1973_gta01())
+ s3c2410_gpio_setpin(GTA01_GPIO_GPS_PWRON, on);
+#endif /* CONFIG_MACH_NEO1973_GTA01 */
+
+#ifdef CONFIG_MACH_NEO1973_GTA02
+ if (machine_is_neo1973_gta02()) {
+ if (on)
+ pcf50633_voltage_set(pcf50633_global,
+ PCF50633_REGULATOR_LDO5, 3000);
+ pcf50633_onoff_set(pcf50633_global,
+ PCF50633_REGULATOR_LDO5, on);
+ }
+#endif /* CONFIG_MACH_NEO1973_GTA02 */
}
static int gps_pwron_get(void)
{
- if (s3c2410_gpio_getpin(GTA01_GPIO_GPS_PWRON))
- return 1;
- else
- return 0;
+#ifdef CONFIG_MACH_NEO1973_GTA01
+ if (machine_is_neo1973_gta01()) {
+ if (s3c2410_gpio_getpin(GTA01_GPIO_GPS_PWRON))
+ return 1;
+ else
+ return 0;
+ }
+#endif /* CONFIG_MACH_NEO1973_GTA01 */
+
+#ifdef CONFIG_MACH_NEO1973_GTA02
+ if (machine_is_neo1973_gta02()) {
+ if (pcf50633_onoff_get(pcf50633_global, PCF50633_REGULATOR_LDO5))
+ return 1;
+ else
+ return 0;
+ }
+#endif /* CONFIG_MACH_NEO1973_GTA02 */
+ return -1;
}
/* This is the nRESET pin */
@@ -441,17 +476,40 @@ static DEVICE_ATTR(power_sequence, 0644, power_sequence_read,
static int gta01_pm_gps_suspend(struct platform_device *pdev,
pm_message_t state)
{
- /* FIXME */
- gps_power_sequence_down();
+#ifdef CONFIG_MACH_NEO1973_GTA01
+ if (machine_is_neo1973_gta01()) {
+ /* FIXME */
+ gps_power_sequence_down();
+ }
+#endif /* CONFIG_MACH_NEO1973_GTA01 */
+
+#ifdef CONFIG_MACH_NEO1973_GTA02
+ if (machine_is_neo1973_gta02()) {
+ /* FIXME */
+ pcf50633_onoff_set(pcf50633_global,
+ PCF50633_REGULATOR_LDO5, 0);
+ }
+#endif /* CONFIG_MACH_NEO1973_GTA02 */
return 0;
}
static int gta01_pm_gps_resume(struct platform_device *pdev)
{
- /* FIXME */
- gps_power_sequence_up();
-
+#ifdef CONFIG_MACH_NEO1973_GTA01
+ if (machine_is_neo1973_gta01()) {
+ /* FIXME */
+ gps_power_sequence_up();
+ }
+#endif /* CONFIG_MACH_NEO1973_GTA01 */
+
+#ifdef CONFIG_MACH_NEO1973_GTA02
+ if (machine_is_neo1973_gta02()) {
+ /* FIXME */
+ pcf50633_onoff_set(pcf50633_global,
+ PCF50633_REGULATOR_LDO5, 1);
+#endif /* CONFIG_MACH_NEO1973_GTA02 */
+ }
return 0;
}
#else
@@ -476,59 +534,110 @@ static struct attribute_group gta01_gps_attr_group = {
.attrs = gta01_gps_sysfs_entries,
};
+static struct attribute *gta02_gps_sysfs_entries[] = {
+ &dev_attr_pwron.attr,
+ NULL
+};
+
+static struct attribute_group gta02_gps_attr_group = {
+ .name = NULL,
+ .attrs = gta02_gps_sysfs_entries,
+};
+
static int __init gta01_pm_gps_probe(struct platform_device *pdev)
{
- s3c2410_gpio_cfgpin(GTA01_GPIO_GPS_PWRON, S3C2410_GPIO_OUTPUT);
+#ifdef CONFIG_MACH_NEO1973_GTA01
+ if (machine_is_neo1973_gta01()) {
+ s3c2410_gpio_cfgpin(GTA01_GPIO_GPS_PWRON, S3C2410_GPIO_OUTPUT);
- switch (system_rev) {
- case GTA01v3_SYSTEM_REV:
- break;
- case GTA01v4_SYSTEM_REV:
- s3c2410_gpio_cfgpin(GTA01_GPIO_GPS_RESET, S3C2410_GPIO_OUTPUT);
- break;
- case GTA01Bv3_SYSTEM_REV:
- case GTA01Bv4_SYSTEM_REV:
- s3c2410_gpio_cfgpin(GTA01_GPIO_GPS_EN_3V3, S3C2410_GPIO_OUTPUT);
- /* fallthrough */
- case GTA01Bv2_SYSTEM_REV:
- s3c2410_gpio_cfgpin(GTA01_GPIO_GPS_EN_2V8, S3C2410_GPIO_OUTPUT);
- s3c2410_gpio_cfgpin(GTA01_GPIO_GPS_EN_3V, S3C2410_GPIO_OUTPUT);
- s3c2410_gpio_cfgpin(GTA01_GPIO_GPS_RESET, S3C2410_GPIO_OUTPUT);
- break;
- default:
- dev_warn(&pdev->dev, "Unknown GTA01 Revision 0x%x, "
- "AGPS PM features not available!!!\n",
- system_rev);
- return -1;
- break;
- }
+ switch (system_rev) {
+ case GTA01v3_SYSTEM_REV:
+ break;
+ case GTA01v4_SYSTEM_REV:
+ s3c2410_gpio_cfgpin(GTA01_GPIO_GPS_RESET, S3C2410_GPIO_OUTPUT);
+ break;
+ case GTA01Bv3_SYSTEM_REV:
+ case GTA01Bv4_SYSTEM_REV:
+ s3c2410_gpio_cfgpin(GTA01_GPIO_GPS_EN_3V3, S3C2410_GPIO_OUTPUT);
+ /* fallthrough */
+ case GTA01Bv2_SYSTEM_REV:
+ s3c2410_gpio_cfgpin(GTA01_GPIO_GPS_EN_2V8, S3C2410_GPIO_OUTPUT);
+ s3c2410_gpio_cfgpin(GTA01_GPIO_GPS_EN_3V, S3C2410_GPIO_OUTPUT);
+ s3c2410_gpio_cfgpin(GTA01_GPIO_GPS_RESET, S3C2410_GPIO_OUTPUT);
+ break;
+ default:
+ dev_warn(&pdev->dev, "Unknown GTA01 Revision 0x%x, "
+ "AGPS PM features not available!!!\n",
+ system_rev);
+ return -1;
+ break;
+ }
- gps_power_sequence_down();
+ gps_power_sequence_down();
- switch (system_rev) {
- case GTA01v3_SYSTEM_REV:
- case GTA01v4_SYSTEM_REV:
- case GTA01Bv2_SYSTEM_REV:
- gta01_gps_sysfs_entries[ARRAY_SIZE(gta01_gps_sysfs_entries)-3] =
- &dev_attr_power_tcxo_2v8.attr;
- break;
- case GTA01Bv3_SYSTEM_REV:
- case GTA01Bv4_SYSTEM_REV:
- gta01_gps_sysfs_entries[ARRAY_SIZE(gta01_gps_sysfs_entries)-3] =
- &dev_attr_power_core_1v5.attr;
- gta01_gps_sysfs_entries[ARRAY_SIZE(gta01_gps_sysfs_entries)-2] =
- &dev_attr_power_vdd_core_1v5.attr;
- break;
- }
+ switch (system_rev) {
+ case GTA01v3_SYSTEM_REV:
+ case GTA01v4_SYSTEM_REV:
+ case GTA01Bv2_SYSTEM_REV:
+ gta01_gps_sysfs_entries[ARRAY_SIZE(gta01_gps_sysfs_entries)-3] =
+ &dev_attr_power_tcxo_2v8.attr;
+ break;
+ case GTA01Bv3_SYSTEM_REV:
+ case GTA01Bv4_SYSTEM_REV:
+ gta01_gps_sysfs_entries[ARRAY_SIZE(gta01_gps_sysfs_entries)-3] =
+ &dev_attr_power_core_1v5.attr;
+ gta01_gps_sysfs_entries[ARRAY_SIZE(gta01_gps_sysfs_entries)-2] =
+ &dev_attr_power_vdd_core_1v5.attr;
+ break;
+ }
- return sysfs_create_group(&pdev->dev.kobj, &gta01_gps_attr_group);
+ return sysfs_create_group(&pdev->dev.kobj, &gta01_gps_attr_group);
+ }
+#endif /* CONFIG_MACH_NEO1973_GTA01 */
+
+#ifdef CONFIG_MACH_NEO1973_GTA02
+ if (machine_is_neo1973_gta02()) {
+ switch (system_rev) {
+ case GTA02v2_SYSTEM_REV:
+ case GTA02v3_SYSTEM_REV:
+ case GTA02v4_SYSTEM_REV:
+ case GTA02v5_SYSTEM_REV:
+ case GTA02v6_SYSTEM_REV:
+ pcf50633_voltage_set(pcf50633_global,
+ PCF50633_REGULATOR_LDO5, 3000);
+ pcf50633_onoff_set(pcf50633_global,
+ PCF50633_REGULATOR_LDO5, 0);
+ dev_info(&pdev->dev, "FIC Neo1973 GPS Power Managerment:"
+ "starting\n");
+ break;
+ default:
+ dev_warn(&pdev->dev, "Unknown GTA02 Revision 0x%x, "
+ "AGPS PM features not available!!!\n",
+ system_rev);
+ return -1;
+ break;
+ }
+ return sysfs_create_group(&pdev->dev.kobj, &gta02_gps_attr_group);
+ }
+#endif /* CONFIG_MACH_NEO1973_GTA02 */
+ return -1;
}
static int gta01_pm_gps_remove(struct platform_device *pdev)
{
- gps_power_sequence_down();
- sysfs_remove_group(&pdev->dev.kobj, &gta01_gps_attr_group);
+#ifdef CONFIG_MACH_NEO1973_GTA01
+ if (machine_is_neo1973_gta01()) {
+ gps_power_sequence_down();
+ sysfs_remove_group(&pdev->dev.kobj, &gta01_gps_attr_group);
+ }
+#endif /* CONFIG_MACH_NEO1973_GTA01 */
+#ifdef CONFIG_MACH_NEO1973_GTA02
+ if (machine_is_neo1973_gta02()) {
+ pcf50633_onoff_set(pcf50633_global, PCF50633_REGULATOR_LDO5, 0);
+ sysfs_remove_group(&pdev->dev.kobj, &gta02_gps_attr_group);
+ }
+#endif /* CONFIG_MACH_NEO1973_GTA02 */
return 0;
}
diff --git a/arch/arm/plat-s3c24xx/neo1973_pm_gsm.c b/arch/arm/plat-s3c24xx/neo1973_pm_gsm.c
index a1615f8..13cb45b 100644
--- a/arch/arm/plat-s3c24xx/neo1973_pm_gsm.c
+++ b/arch/arm/plat-s3c24xx/neo1973_pm_gsm.c
@@ -19,8 +19,15 @@
#include <linux/errno.h>
#include <asm/hardware.h>
+#include <asm/mach-types.h>
#include <asm/arch/gta01.h>
+#ifdef CONFIG_MACH_NEO1973_GTA02
+#include <asm/arch/gta02.h>
+#include <linux/pcf50633.h>
+#include <asm/arch/regs-gpioj.h>
+#endif
+
struct gta01pm_priv {
int gpio_ngsm_en;
struct console *con;
@@ -54,8 +61,16 @@ static ssize_t gsm_read(struct device *dev, struct device_attribute *attr,
if (s3c2410_gpio_getpin(GTA01_GPIO_MODEM_RST))
goto out_1;
} else if (!strcmp(attr->attr.name, "download")) {
- if (s3c2410_gpio_getpin(GTA01_GPIO_MODEM_DNLOAD))
- goto out_1;
+#ifdef CONFIG_MACH_NEO1973_GTA01
+ if (machine_is_neo1973_gta01())
+ if (s3c2410_gpio_getpin(GTA01_GPIO_MODEM_DNLOAD))
+ goto out_1;
+#endif
+#ifdef CONFIG_MACH_NEO1973_GTA02
+ if (machine_is_neo1973_gta02())
+ if (s3c2410_gpio_getpin(GTA02_GPIO_nDL_GSM))
+ goto out_1;
+#endif
}
return strlcpy(buf, "0\n", 3);
@@ -70,32 +85,67 @@ static ssize_t gsm_write(struct device *dev, struct device_attribute *attr,
if (!strcmp(attr->attr.name, "power_on")) {
if (on) {
- dev_info(dev, "powering up GSM, thus disconnecting "
- "serial console\n");
+ if (gta01_gsm.con) {
+ dev_info(dev, "powering up GSM, thus "
+ "disconnecting serial console\n");
- if (gta01_gsm.con)
console_stop(gta01_gsm.con);
+ }
if (gta01_gsm.gpio_ngsm_en)
s3c2410_gpio_setpin(gta01_gsm.gpio_ngsm_en, 0);
+ switch (system_rev) {
+#ifdef CONFIG_MACH_NEO1973_GTA02
+ case GTA02v2_SYSTEM_REV:
+ case GTA02v3_SYSTEM_REV:
+ case GTA02v4_SYSTEM_REV:
+ case GTA02v5_SYSTEM_REV:
+ case GTA02v6_SYSTEM_REV:
+ pcf50633_gpio_set(pcf50633_global,
+ PCF50633_GPIO2, 1);
+ break;
+#endif
+ }
+
s3c2410_gpio_setpin(GTA01_GPIO_MODEM_ON, 1);
} else {
s3c2410_gpio_setpin(GTA01_GPIO_MODEM_ON, 0);
+ switch (system_rev) {
+#ifdef CONFIG_MACH_NEO1973_GTA02
+ case GTA02v2_SYSTEM_REV:
+ case GTA02v3_SYSTEM_REV:
+ case GTA02v4_SYSTEM_REV:
+ case GTA02v5_SYSTEM_REV:
+ case GTA02v6_SYSTEM_REV:
+ pcf50633_gpio_set(pcf50633_global,
+ PCF50633_GPIO2, 0);
+ break;
+#endif
+ }
+
if (gta01_gsm.gpio_ngsm_en)
s3c2410_gpio_setpin(gta01_gsm.gpio_ngsm_en, 1);
- if (gta01_gsm.con)
+ if (gta01_gsm.con) {
console_start(gta01_gsm.con);
- dev_info(dev, "powered down GSM, thus enabling "
- "serial console\n");
+ dev_info(dev, "powered down GSM, thus enabling "
+ "serial console\n");
+ }
}
} else if (!strcmp(attr->attr.name, "reset")) {
s3c2410_gpio_setpin(GTA01_GPIO_MODEM_RST, on);
} else if (!strcmp(attr->attr.name, "download")) {
- s3c2410_gpio_setpin(GTA01_GPIO_MODEM_DNLOAD, on);
+#ifdef CONFIG_MACH_NEO1973_GTA01
+ if (machine_is_neo1973_gta01())
+ s3c2410_gpio_setpin(GTA01_GPIO_MODEM_DNLOAD, on);
+#endif
+#ifdef CONFIG_MACH_NEO1973_GTA02
+ if (machine_is_neo1973_gta02())
+ s3c2410_gpio_setpin(GTA02_GPIO_nDL_GSM, on);
+#endif
}
return count;
@@ -111,6 +161,9 @@ static int gta01_gsm_suspend(struct platform_device *pdev, pm_message_t state)
/* GPIO state is saved/restored by S3C2410 core GPIO driver, so we
* don't need to do anything here */
+ /* disable DL GSM to prevent jack_insert becoming flaoting */
+ if (machine_is_neo1973_gta02())
+ s3c2410_gpio_setpin(GTA02_GPIO_nDL_GSM, 1);
return 0;
}
@@ -124,6 +177,8 @@ static int gta01_gsm_resume(struct platform_device *pdev)
if (s3c2410_gpio_getpin(GTA01_GPIO_MODEM_ON) && gta01_gsm.con)
console_stop(gta01_gsm.con);
+ if (machine_is_neo1973_gta02())
+ s3c2410_gpio_setpin(GTA02_GPIO_nDL_GSM, 0);
return 0;
}
#else
@@ -134,7 +189,7 @@ static int gta01_gsm_resume(struct platform_device *pdev)
static struct attribute *gta01_gsm_sysfs_entries[] = {
&dev_attr_power_on.attr,
&dev_attr_reset.attr,
- NULL,
+ &dev_attr_download.attr,
NULL
};
@@ -158,8 +213,18 @@ static int __init gta01_gsm_probe(struct platform_device *pdev)
gta01_gsm.gpio_ngsm_en = GTA01Bv2_GPIO_nGSM_EN;
s3c2410_gpio_setpin(GTA01v3_GPIO_nGSM_EN, 0);
break;
+#ifdef CONFIG_MACH_NEO1973_GTA02
+ case GTA02v1_SYSTEM_REV:
+ case GTA02v2_SYSTEM_REV:
+ case GTA02v3_SYSTEM_REV:
+ case GTA02v4_SYSTEM_REV:
+ case GTA02v5_SYSTEM_REV:
+ case GTA02v6_SYSTEM_REV:
+ gta01_gsm.gpio_ngsm_en = 0;
+ break;
+#endif
default:
- dev_warn(&pdev->dev, "Unknown GTA01 Revision 0x%x, "
+ dev_warn(&pdev->dev, "Unknown Neo1973 Revision 0x%x, "
"some PM features not available!!!\n",
system_rev);
break;
@@ -175,9 +240,13 @@ static int __init gta01_gsm_probe(struct platform_device *pdev)
break;
}
- gta01_gsm.con = find_s3c24xx_console();
- if (!gta01_gsm.con)
- dev_warn(&pdev->dev, "cannot find S3C24xx console driver\n");
+ if (machine_is_neo1973_gta01()) {
+ gta01_gsm.con = find_s3c24xx_console();
+ if (!gta01_gsm.con)
+ dev_warn(&pdev->dev,
+ "cannot find S3C24xx console driver\n");
+ } else
+ gta01_gsm.con = NULL;
return sysfs_create_group(&pdev->dev.kobj, &gta01_gsm_attr_group);
}
--
1.5.6.3

View file

@ -0,0 +1,778 @@
From c03e9f46b9f15afc3e8980ae28666ff30907b173 Mon Sep 17 00:00:00 2001
From: mokopatches <mokopatches@openmoko.org>
Date: Wed, 16 Jul 2008 14:46:56 +0100
Subject: [PATCH] gta02-sound.patch
---
include/sound/soc-dapm.h | 7 +
sound/soc/s3c24xx/Kconfig | 9 +
sound/soc/s3c24xx/Makefile | 3 +
sound/soc/s3c24xx/neo1973_gta02_wm8753.c | 667 ++++++++++++++++++++++++++++++
sound/soc/soc-dapm.c | 24 ++
5 files changed, 710 insertions(+), 0 deletions(-)
create mode 100644 sound/soc/s3c24xx/neo1973_gta02_wm8753.c
diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h
index a105b01..e867447 100644
--- a/include/sound/soc-dapm.h
+++ b/include/sound/soc-dapm.h
@@ -225,6 +225,13 @@ int snd_soc_dapm_set_endpoint(struct snd_soc_codec *codec,
char *pin, int status);
int snd_soc_dapm_sync_endpoints(struct snd_soc_codec *codec);
+/* dapm audio endpoint control */
+int snd_soc_dapm_set_endpoint(struct snd_soc_codec *codec,
+ char *pin, int status);
+int snd_soc_dapm_get_endpoint(struct snd_soc_codec *codec,
+ char *pin);
+int snd_soc_dapm_sync_endpoints(struct snd_soc_codec *codec);
+
/* dapm widget types */
enum snd_soc_dapm_type {
snd_soc_dapm_input = 0, /* input pin */
diff --git a/sound/soc/s3c24xx/Kconfig b/sound/soc/s3c24xx/Kconfig
index 1f6dbfc..3155c43 100644
--- a/sound/soc/s3c24xx/Kconfig
+++ b/sound/soc/s3c24xx/Kconfig
@@ -28,6 +28,15 @@ config SND_S3C24XX_SOC_NEO1973_WM8753
Say Y if you want to add support for SoC audio on smdk2440
with the WM8753.
+config SND_S3C24XX_SOC_NEO1973_GTA02_WM8753
+ tristate "SoC I2S Audio support for NEO1973 GTA02 - WM8753"
+ depends on SND_S3C24XX_SOC && MACH_NEO1973_GTA02
+ select SND_S3C24XX_SOC_I2S
+ select SND_SOC_WM8753
+ help
+ Say Y if you want to add support for SoC audio on neo1973 gta02
+ with the WM8753 codec
+
config SND_S3C24XX_SOC_SMDK2443_WM9710
tristate "SoC AC97 Audio support for SMDK2443 - WM9710"
depends on SND_S3C24XX_SOC && MACH_SMDK2443
diff --git a/sound/soc/s3c24xx/Makefile b/sound/soc/s3c24xx/Makefile
index 0aa5fb0..f154cb1 100644
--- a/sound/soc/s3c24xx/Makefile
+++ b/sound/soc/s3c24xx/Makefile
@@ -13,7 +13,10 @@ obj-$(CONFIG_SND_S3C2412_SOC_I2S) += snd-soc-s3c2412-i2s.o
snd-soc-neo1973-wm8753-objs := neo1973_wm8753.o
snd-soc-smdk2443-wm9710-objs := smdk2443_wm9710.o
snd-soc-ln2440sbc-alc650-objs := ln2440sbc_alc650.o
+snd-soc-neo1973-gta02-wm8753-objs := neo1973_gta02_wm8753.o
obj-$(CONFIG_SND_S3C24XX_SOC_NEO1973_WM8753) += snd-soc-neo1973-wm8753.o
obj-$(CONFIG_SND_S3C24XX_SOC_SMDK2443_WM9710) += snd-soc-smdk2443-wm9710.o
obj-$(CONFIG_SND_S3C24XX_SOC_LN2440SBC_ALC650) += snd-soc-ln2440sbc-alc650.o
+obj-$(CONFIG_SND_S3C24XX_SOC_NEO1973_GTA02_WM8753) += snd-soc-neo1973-gta02-wm8753.o
+
diff --git a/sound/soc/s3c24xx/neo1973_gta02_wm8753.c b/sound/soc/s3c24xx/neo1973_gta02_wm8753.c
new file mode 100644
index 0000000..f32cba3
--- /dev/null
+++ b/sound/soc/s3c24xx/neo1973_gta02_wm8753.c
@@ -0,0 +1,667 @@
+/*
+ * neo1973_gta02_wm8753.c -- SoC audio for Neo1973
+ *
+ * Copyright 2007 OpenMoko Inc
+ * Author: Graeme Gregory <graeme@openmoko.org>
+ * Copyright 2007 Wolfson Microelectronics PLC.
+ * Author: Graeme Gregory <linux@wolfsonmicro.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.
+ *
+ * Revision history
+ * 06th Nov 2007 Changed from GTA01 to GTA02
+ * 20th Jan 2007 Initial version.
+ * 05th Feb 2007 Rename all to Neo1973
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/timer.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/i2c.h>
+#include <sound/driver.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+
+#include <asm/mach-types.h>
+#include <asm/hardware/scoop.h>
+#include <asm/plat-s3c24xx/regs-iis.h>
+#include <asm/arch/regs-clock.h>
+#include <asm/arch/regs-gpio.h>
+#include <asm/hardware.h>
+#include <asm/arch/audio.h>
+#include <asm/io.h>
+#include <asm/arch/spi-gpio.h>
+#include <asm/arch/regs-gpioj.h>
+#include <asm/arch/gta02.h>
+#include "../codecs/wm8753.h"
+#include "s3c24xx-pcm.h"
+#include "s3c24xx-i2s.h"
+
+/* define the scenarios */
+#define NEO_AUDIO_OFF 0
+#define NEO_GSM_CALL_AUDIO_HANDSET 1
+#define NEO_GSM_CALL_AUDIO_HEADSET 2
+#define NEO_GSM_CALL_AUDIO_BLUETOOTH 3
+#define NEO_STEREO_TO_SPEAKERS 4
+#define NEO_STEREO_TO_HEADPHONES 5
+#define NEO_CAPTURE_HANDSET 6
+#define NEO_CAPTURE_HEADSET 7
+#define NEO_CAPTURE_BLUETOOTH 8
+#define NEO_STEREO_TO_HANDSET_SPK 9
+
+static struct snd_soc_machine neo1973_gta02;
+
+static int neo1973_gta02_hifi_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_codec_dai *codec_dai = rtd->dai->codec_dai;
+ struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai;
+ unsigned int pll_out = 0, bclk = 0;
+ int ret = 0;
+ unsigned long iis_clkrate;
+
+ iis_clkrate = s3c24xx_i2s_get_clockrate();
+
+ switch (params_rate(params)) {
+ case 8000:
+ case 16000:
+ pll_out = 12288000;
+ break;
+ case 48000:
+ bclk = WM8753_BCLK_DIV_4;
+ pll_out = 12288000;
+ break;
+ case 96000:
+ bclk = WM8753_BCLK_DIV_2;
+ pll_out = 12288000;
+ break;
+ case 11025:
+ bclk = WM8753_BCLK_DIV_16;
+ pll_out = 11289600;
+ break;
+ case 22050:
+ bclk = WM8753_BCLK_DIV_8;
+ pll_out = 11289600;
+ break;
+ case 44100:
+ bclk = WM8753_BCLK_DIV_4;
+ pll_out = 11289600;
+ break;
+ case 88200:
+ bclk = WM8753_BCLK_DIV_2;
+ pll_out = 11289600;
+ break;
+ }
+
+ /* set codec DAI configuration */
+ ret = codec_dai->dai_ops.set_fmt(codec_dai,
+ SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_CBM_CFM);
+ if (ret < 0)
+ return ret;
+
+ /* set cpu DAI configuration */
+ ret = cpu_dai->dai_ops.set_fmt(cpu_dai,
+ SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_CBM_CFM);
+ if (ret < 0)
+ return ret;
+
+ /* set the codec system clock for DAC and ADC */
+ ret = codec_dai->dai_ops.set_sysclk(codec_dai, WM8753_MCLK, pll_out,
+ SND_SOC_CLOCK_IN);
+ if (ret < 0)
+ return ret;
+
+ /* set MCLK division for sample rate */
+ ret = cpu_dai->dai_ops.set_clkdiv(cpu_dai, S3C24XX_DIV_MCLK,
+ S3C2410_IISMOD_32FS );
+ if (ret < 0)
+ return ret;
+
+ /* set codec BCLK division for sample rate */
+ ret = codec_dai->dai_ops.set_clkdiv(codec_dai,
+ WM8753_BCLKDIV, bclk);
+ if (ret < 0)
+ return ret;
+
+ /* set prescaler division for sample rate */
+ ret = cpu_dai->dai_ops.set_clkdiv(cpu_dai, S3C24XX_DIV_PRESCALER,
+ S3C24XX_PRESCALE(4,4));
+ if (ret < 0)
+ return ret;
+
+ /* codec PLL input is PCLK/4 */
+ ret = codec_dai->dai_ops.set_pll(codec_dai, WM8753_PLL1,
+ iis_clkrate / 4, pll_out);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+static int neo1973_gta02_hifi_hw_free(struct snd_pcm_substream *substream)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_codec_dai *codec_dai = rtd->dai->codec_dai;
+
+ /* disable the PLL */
+ return codec_dai->dai_ops.set_pll(codec_dai, WM8753_PLL1, 0, 0);
+}
+
+/*
+ * Neo1973 WM8753 HiFi DAI opserations.
+ */
+static struct snd_soc_ops neo1973_gta02_hifi_ops = {
+ .hw_params = neo1973_gta02_hifi_hw_params,
+ .hw_free = neo1973_gta02_hifi_hw_free,
+};
+
+static int neo1973_gta02_voice_hw_params(
+ struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_codec_dai *codec_dai = rtd->dai->codec_dai;
+ unsigned int pcmdiv = 0;
+ int ret = 0;
+ unsigned long iis_clkrate;
+
+ iis_clkrate = s3c24xx_i2s_get_clockrate();
+
+ if (params_rate(params) != 8000)
+ return -EINVAL;
+ if (params_channels(params) != 1)
+ return -EINVAL;
+
+ pcmdiv = WM8753_PCM_DIV_6; /* 2.048 MHz */
+
+ /* todo: gg check mode (DSP_B) against CSR datasheet */
+ /* set codec DAI configuration */
+ ret = codec_dai->dai_ops.set_fmt(codec_dai, SND_SOC_DAIFMT_DSP_B |
+ SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
+ if (ret < 0)
+ return ret;
+
+ /* set the codec system clock for DAC and ADC */
+ ret = codec_dai->dai_ops.set_sysclk(codec_dai, WM8753_PCMCLK,
+ 12288000, SND_SOC_CLOCK_IN);
+ if (ret < 0)
+ return ret;
+
+ /* set codec PCM division for sample rate */
+ ret = codec_dai->dai_ops.set_clkdiv(codec_dai, WM8753_PCMDIV,
+ pcmdiv);
+ if (ret < 0)
+ return ret;
+
+ /* configue and enable PLL for 12.288MHz output */
+ ret = codec_dai->dai_ops.set_pll(codec_dai, WM8753_PLL2,
+ iis_clkrate / 4, 12288000);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+static int neo1973_gta02_voice_hw_free(struct snd_pcm_substream *substream)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_codec_dai *codec_dai = rtd->dai->codec_dai;
+
+ /* disable the PLL */
+ return codec_dai->dai_ops.set_pll(codec_dai, WM8753_PLL2, 0, 0);
+}
+
+static struct snd_soc_ops neo1973_gta02_voice_ops = {
+ .hw_params = neo1973_gta02_voice_hw_params,
+ .hw_free = neo1973_gta02_voice_hw_free,
+};
+
+#define LM4853_AMP 1
+#define LM4853_SPK 2
+
+static u8 lm4853_state=0;
+
+static int lm4853_set_state(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ int val = ucontrol->value.integer.value[0];
+
+ if(val) {
+ lm4853_state |= LM4853_AMP;
+ s3c2410_gpio_setpin(GTA02_GPIO_AMP_SHUT,0);
+ } else {
+ lm4853_state &= ~LM4853_AMP;
+ s3c2410_gpio_setpin(GTA02_GPIO_AMP_SHUT,1);
+ }
+
+ return 0;
+}
+
+static int lm4853_get_state(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ ucontrol->value.integer.value[0] = lm4853_state & LM4853_AMP;
+
+ return 0;
+}
+
+static int lm4853_set_spk(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ int val = ucontrol->value.integer.value[0];
+
+ if(val) {
+ lm4853_state |= LM4853_SPK;
+ s3c2410_gpio_setpin(GTA02_GPIO_HP_IN,0);
+ } else {
+ lm4853_state &= ~LM4853_SPK;
+ s3c2410_gpio_setpin(GTA02_GPIO_HP_IN,1);
+ }
+
+ return 0;
+}
+
+static int lm4853_get_spk(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ ucontrol->value.integer.value[0] = (lm4853_state & LM4853_SPK) >> 1;
+
+ return 0;
+}
+
+static int neo1973_gta02_set_stereo_out(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ int val = ucontrol->value.integer.value[0];
+
+ snd_soc_dapm_set_endpoint(codec, "Stereo Out", val);
+
+ snd_soc_dapm_sync_endpoints(codec);
+
+ return 0;
+}
+
+static int neo1973_gta02_get_stereo_out(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+
+ ucontrol->value.integer.value[0] =
+ snd_soc_dapm_get_endpoint(codec, "Stereo Out");
+
+ return 0;
+}
+
+
+static int neo1973_gta02_set_gsm_out(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ int val = ucontrol->value.integer.value[0];
+
+ snd_soc_dapm_set_endpoint(codec, "GSM Line Out", val);
+
+ snd_soc_dapm_sync_endpoints(codec);
+
+ return 0;
+}
+
+static int neo1973_gta02_get_gsm_out(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+
+ ucontrol->value.integer.value[0] =
+ snd_soc_dapm_get_endpoint(codec, "GSM Line Out");
+
+ return 0;
+}
+
+static int neo1973_gta02_set_gsm_in(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ int val = ucontrol->value.integer.value[0];
+
+ snd_soc_dapm_set_endpoint(codec, "GSM Line In", val);
+
+ snd_soc_dapm_sync_endpoints(codec);
+
+ return 0;
+}
+
+static int neo1973_gta02_get_gsm_in(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+
+ ucontrol->value.integer.value[0] =
+ snd_soc_dapm_get_endpoint(codec, "GSM Line In");
+
+ return 0;
+}
+
+static int neo1973_gta02_set_headset_mic(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ int val = ucontrol->value.integer.value[0];
+
+ snd_soc_dapm_set_endpoint(codec, "Headset Mic", val);
+
+ snd_soc_dapm_sync_endpoints(codec);
+
+ return 0;
+}
+
+static int neo1973_gta02_get_headset_mic(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+
+ ucontrol->value.integer.value[0] =
+ snd_soc_dapm_get_endpoint(codec, "Headset Mic");
+
+ return 0;
+}
+
+static int neo1973_gta02_set_handset_mic(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ int val = ucontrol->value.integer.value[0];
+
+ snd_soc_dapm_set_endpoint(codec, "Handset Mic", val);
+
+ snd_soc_dapm_sync_endpoints(codec);
+
+ return 0;
+}
+
+static int neo1973_gta02_get_handset_mic(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+
+ ucontrol->value.integer.value[0] =
+ snd_soc_dapm_get_endpoint(codec, "Handset Mic");
+
+ return 0;
+}
+
+static int neo1973_gta02_set_handset_spk(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ int val = ucontrol->value.integer.value[0];
+
+ snd_soc_dapm_set_endpoint(codec, "Handset Spk", val);
+
+ snd_soc_dapm_sync_endpoints(codec);
+
+ return 0;
+}
+
+static int neo1973_gta02_get_handset_spk(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+
+ ucontrol->value.integer.value[0] =
+ snd_soc_dapm_get_endpoint(codec, "Handset Spk");
+
+ return 0;
+}
+
+static const struct snd_soc_dapm_widget wm8753_dapm_widgets[] = {
+ SND_SOC_DAPM_LINE("Stereo Out", NULL),
+ SND_SOC_DAPM_LINE("GSM Line Out", NULL),
+ SND_SOC_DAPM_LINE("GSM Line In", NULL),
+ SND_SOC_DAPM_MIC("Headset Mic", NULL),
+ SND_SOC_DAPM_MIC("Handset Mic", NULL),
+ SND_SOC_DAPM_SPK("Handset Spk", NULL),
+};
+
+
+/* example machine audio_mapnections */
+static const char* audio_map[][3] = {
+
+ /* Connections to the lm4853 amp */
+ {"Stereo Out", NULL, "LOUT1"},
+ {"Stereo Out", NULL, "ROUT1"},
+
+ /* Connections to the GSM Module */
+ {"GSM Line Out", NULL, "MONO1"},
+ {"GSM Line Out", NULL, "MONO2"},
+ {"RXP", NULL, "GSM Line In"},
+ {"RXN", NULL, "GSM Line In"},
+
+ /* Connections to Headset */
+ {"MIC1", NULL, "Mic Bias"},
+ {"Mic Bias", NULL, "Headset Mic"},
+
+ /* Call Mic */
+ {"MIC2", NULL, "Mic Bias"},
+ {"MIC2N", NULL, "Mic Bias"},
+ {"Mic Bias", NULL, "Handset Mic"},
+
+ /* Call Speaker */
+ {"Handset Spk", NULL, "LOUT2"},
+ {"Handset Spk", NULL, "ROUT2"},
+
+ /* Connect the ALC pins */
+ {"ACIN", NULL, "ACOP"},
+
+ {NULL, NULL, NULL},
+};
+
+static const struct snd_kcontrol_new wm8753_neo1973_gta02_controls[] = {
+ SOC_SINGLE_EXT("DAPM Stereo Out Switch", 0, 0, 1, 0,
+ neo1973_gta02_get_stereo_out,
+ neo1973_gta02_set_stereo_out),
+ SOC_SINGLE_EXT("DAPM GSM Line Out Switch", 1, 0, 1, 0,
+ neo1973_gta02_get_gsm_out,
+ neo1973_gta02_set_gsm_out),
+ SOC_SINGLE_EXT("DAPM GSM Line In Switch", 2, 0, 1, 0,
+ neo1973_gta02_get_gsm_in,
+ neo1973_gta02_set_gsm_in),
+ SOC_SINGLE_EXT("DAPM Headset Mic Switch", 3, 0, 1, 0,
+ neo1973_gta02_get_headset_mic,
+ neo1973_gta02_set_headset_mic),
+ SOC_SINGLE_EXT("DAPM Handset Mic Switch", 4, 0, 1, 0,
+ neo1973_gta02_get_handset_mic,
+ neo1973_gta02_set_handset_mic),
+ SOC_SINGLE_EXT("DAPM Handset Spk Switch", 5, 0, 1, 0,
+ neo1973_gta02_get_handset_spk,
+ neo1973_gta02_set_handset_spk),
+ SOC_SINGLE_EXT("Amp State Switch", 6, 0, 1, 0,
+ lm4853_get_state,
+ lm4853_set_state),
+ SOC_SINGLE_EXT("Amp Spk Switch", 7, 0, 1, 0,
+ lm4853_get_spk,
+ lm4853_set_spk),
+};
+
+/*
+ * This is an example machine initialisation for a wm8753 connected to a
+ * neo1973 GTA02.
+ */
+static int neo1973_gta02_wm8753_init(struct snd_soc_codec *codec)
+{
+ int i, err;
+
+ /* set up NC codec pins */
+ snd_soc_dapm_set_endpoint(codec, "OUT3", 0);
+ snd_soc_dapm_set_endpoint(codec, "OUT4", 0);
+ snd_soc_dapm_set_endpoint(codec, "LINE1", 0);
+ snd_soc_dapm_set_endpoint(codec, "LINE2", 0);
+
+ /* Add neo1973 gta02 specific widgets */
+ for (i = 0; i < ARRAY_SIZE(wm8753_dapm_widgets); i++)
+ snd_soc_dapm_new_control(codec, &wm8753_dapm_widgets[i]);
+
+ /* add neo1973 gta02 specific controls */
+ for (i = 0; i < ARRAY_SIZE(wm8753_neo1973_gta02_controls); i++) {
+ err = snd_ctl_add(codec->card,
+ snd_soc_cnew(&wm8753_neo1973_gta02_controls[i],
+ codec, NULL));
+ if (err < 0)
+ return err;
+ }
+
+ /* set up neo1973 gta02 specific audio path audio_mapnects */
+ for (i = 0; audio_map[i][0] != NULL; i++) {
+ snd_soc_dapm_connect_input(codec, audio_map[i][0],
+ audio_map[i][1], audio_map[i][2]);
+ }
+
+ /* set endpoints to default off mode */
+ snd_soc_dapm_set_endpoint(codec, "Stereo Out", 0);
+ snd_soc_dapm_set_endpoint(codec, "GSM Line Out",0);
+ snd_soc_dapm_set_endpoint(codec, "GSM Line In", 0);
+ snd_soc_dapm_set_endpoint(codec, "Headset Mic", 0);
+ snd_soc_dapm_set_endpoint(codec, "Handset Mic", 0);
+ snd_soc_dapm_set_endpoint(codec, "Handset Spk", 0);
+
+ snd_soc_dapm_sync_endpoints(codec);
+ return 0;
+}
+
+/*
+ * BT Codec DAI
+ */
+static struct snd_soc_cpu_dai bt_dai =
+{ .name = "Bluetooth",
+ .id = 0,
+ .type = SND_SOC_DAI_PCM,
+ .playback = {
+ .channels_min = 1,
+ .channels_max = 1,
+ .rates = SNDRV_PCM_RATE_8000,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,},
+ .capture = {
+ .channels_min = 1,
+ .channels_max = 1,
+ .rates = SNDRV_PCM_RATE_8000,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,},
+};
+
+static struct snd_soc_dai_link neo1973_gta02_dai[] = {
+{ /* Hifi Playback - for similatious use with voice below */
+ .name = "WM8753",
+ .stream_name = "WM8753 HiFi",
+ .cpu_dai = &s3c24xx_i2s_dai,
+ .codec_dai = &wm8753_dai[WM8753_DAI_HIFI],
+ .init = neo1973_gta02_wm8753_init,
+ .ops = &neo1973_gta02_hifi_ops,
+},
+{ /* Voice via BT */
+ .name = "Bluetooth",
+ .stream_name = "Voice",
+ .cpu_dai = &bt_dai,
+ .codec_dai = &wm8753_dai[WM8753_DAI_VOICE],
+ .ops = &neo1973_gta02_voice_ops,
+},
+};
+
+#ifdef CONFIG_PM
+int neo1973_gta02_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ s3c2410_gpio_setpin(GTA02_GPIO_AMP_SHUT, 1);
+
+ return 0;
+}
+
+int neo1973_gta02_resume(struct platform_device *pdev)
+{
+ if(lm4853_state & LM4853_AMP)
+ s3c2410_gpio_setpin(GTA02_GPIO_AMP_SHUT, 0);
+
+ return 0;
+}
+#else
+#define neo1973_gta02_suspend NULL
+#define neo1973_gta02_resume NULL
+#endif
+
+static struct snd_soc_machine neo1973_gta02 = {
+ .name = "neo1973-gta02",
+ .suspend_pre = neo1973_gta02_suspend,
+ .resume_post = neo1973_gta02_resume,
+ .dai_link = neo1973_gta02_dai,
+ .num_links = ARRAY_SIZE(neo1973_gta02_dai),
+};
+
+static struct wm8753_setup_data neo1973_gta02_wm8753_setup = {
+ .i2c_address = 0x1a,
+};
+
+static struct snd_soc_device neo1973_gta02_snd_devdata = {
+ .machine = &neo1973_gta02,
+ .platform = &s3c24xx_soc_platform,
+ .codec_dev = &soc_codec_dev_wm8753,
+ .codec_data = &neo1973_gta02_wm8753_setup,
+};
+
+static struct platform_device *neo1973_gta02_snd_device;
+
+static int __init neo1973_gta02_init(void)
+{
+ int ret;
+
+ if (!machine_is_neo1973_gta02()) {
+ printk(KERN_INFO
+ "Only GTA02 hardware supported by ASoc driver\n");
+ return -ENODEV;
+ }
+
+ neo1973_gta02_snd_device = platform_device_alloc("soc-audio", -1);
+ if (!neo1973_gta02_snd_device)
+ return -ENOMEM;
+
+ platform_set_drvdata(neo1973_gta02_snd_device,
+ &neo1973_gta02_snd_devdata);
+ neo1973_gta02_snd_devdata.dev = &neo1973_gta02_snd_device->dev;
+ ret = platform_device_add(neo1973_gta02_snd_device);
+
+ if (ret)
+ platform_device_put(neo1973_gta02_snd_device);
+
+ /* Initialise GPIOs used by amp */
+ s3c2410_gpio_cfgpin(GTA02_GPIO_HP_IN, S3C2410_GPIO_OUTPUT);
+ s3c2410_gpio_cfgpin(GTA02_GPIO_AMP_SHUT, S3C2410_GPIO_OUTPUT);
+
+ /* Amp off by default */
+ s3c2410_gpio_setpin(GTA02_GPIO_AMP_SHUT, 1);
+
+ /* Speaker off by default */
+ s3c2410_gpio_setpin(GTA02_GPIO_HP_IN, 1);
+
+ return ret;
+}
+
+static void __exit neo1973_gta02_exit(void)
+{
+ platform_device_unregister(neo1973_gta02_snd_device);
+}
+
+module_init(neo1973_gta02_init);
+module_exit(neo1973_gta02_exit);
+
+/* Module information */
+MODULE_AUTHOR("Graeme Gregory, graeme@openmoko.org");
+MODULE_DESCRIPTION("ALSA SoC WM8753 Neo1973 GTA02");
+MODULE_LICENSE("GPL");
+
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index af3326c..95df1ff 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -1343,6 +1343,30 @@ int snd_soc_dapm_set_endpoint(struct snd_soc_codec *codec,
EXPORT_SYMBOL_GPL(snd_soc_dapm_set_endpoint);
/**
+ * snd_soc_dapm_get_endpoint - get audio endpoint status
+ * @codec: audio codec
+ * @endpoint: audio signal endpoint (or start point)
+ *
+ * Get audio endpoint status - connected or disconnected.
+ *
+ * Returns status
+ */
+int snd_soc_dapm_get_endpoint(struct snd_soc_codec *codec,
+ char *endpoint)
+{
+ struct snd_soc_dapm_widget *w;
+
+ list_for_each_entry(w, &codec->dapm_widgets, list) {
+ if (!strcmp(w->name, endpoint)) {
+ return w->connected;
+ }
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(snd_soc_dapm_get_endpoint);
+
+/**
* snd_soc_dapm_free - free dapm resources
* @socdev: SoC device
*
--
1.5.6.3

View file

@ -0,0 +1,781 @@
From 65c5d85b4cf89969d2e2e981c018bf0ef1c03a2a Mon Sep 17 00:00:00 2001
From: mokopatches <mokopatches@openmoko.org>
Date: Wed, 16 Jul 2008 14:46:56 +0100
Subject: [PATCH] lis302dl.patch
This is a Linux driver for the STmicro LIS302DL 3-axis accelerometer.
Signed-off-by: Harald Welte <laforge@openmoko.org>
---
arch/arm/mach-s3c2440/mach-gta02.c | 46 +++-
drivers/input/misc/Kconfig | 9 +
drivers/input/misc/Makefile | 2 +
drivers/input/misc/lis302dl.c | 633 ++++++++++++++++++++++++++++++++++++
include/linux/lis302dl.h | 11 +
5 files changed, 700 insertions(+), 1 deletions(-)
create mode 100644 drivers/input/misc/lis302dl.c
create mode 100644 include/linux/lis302dl.h
diff --git a/arch/arm/mach-s3c2440/mach-gta02.c b/arch/arm/mach-s3c2440/mach-gta02.c
index f72a5ae..d11da10 100644
--- a/arch/arm/mach-s3c2440/mach-gta02.c
+++ b/arch/arm/mach-s3c2440/mach-gta02.c
@@ -46,6 +46,7 @@
#include <linux/mtd/physmap.h>
#include <linux/pcf50633.h>
+#include <linux/lis302dl.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
@@ -463,7 +464,7 @@ static struct s3c2410_ts_mach_info gta02_ts_cfg = {
.oversampling_shift = 5,
};
-/* SPI */
+/* SPI: LCM control interface attached to Glamo3362 */
static struct spi_board_info gta02_spi_board_info[] = {
{
@@ -504,6 +505,48 @@ static struct platform_device gta01_led_dev = {
.resource = gta01_led_resources,
};
+/* SPI: Accelerometers attached to SPI of s3c244x */
+
+static void gta02_spi_acc_set_cs(struct s3c2410_spi_info *spi, int cs, int pol)
+{
+ s3c2410_gpio_setpin(cs, pol);
+}
+
+static const struct lis302dl_platform_data lis302_pdata[] = {
+ {
+ .name = "lis302-1 (top)"
+ }, {
+ .name = "lis302-2 (bottom)"
+ },
+};
+
+static struct spi_board_info gta02_spi_acc_bdinfo[] = {
+ {
+ .modalias = "lis302dl",
+ .platform_data = &lis302_pdata[0],
+ .irq = GTA02_IRQ_GSENSOR_1,
+ .max_speed_hz = 400 * 1000,
+ .bus_num = 1,
+ .chip_select = S3C2410_GPD12,
+ .mode = SPI_MODE_3,
+ },
+ {
+ .modalias = "lis302dl",
+ .platform_data = &lis302_pdata[1],
+ .irq = GTA02_IRQ_GSENSOR_2,
+ .max_speed_hz = 400 * 1000,
+ .bus_num = 1,
+ .chip_select = S3C2410_GPD13,
+ .mode = SPI_MODE_3,
+ },
+};
+
+static struct s3c2410_spi_info gta02_spi_acc_cfg = {
+ .set_cs = gta02_spi_acc_set_cs,
+ .board_size = ARRAY_SIZE(gta02_spi_acc_bdinfo),
+ .board_info = gta02_spi_acc_bdinfo,
+};
+
static struct resource gta02_led_resources[] = {
{
.name = "gta02-power:orange",
@@ -746,6 +789,7 @@ static void __init gta02_machine_init(void)
s3c_device_usb.dev.platform_data = &gta02_usb_info;
s3c_device_nand.dev.platform_data = &gta02_nand_info;
s3c_device_sdi.dev.platform_data = &gta02_mmc_cfg;
+ s3c_device_spi1.dev.platform_data = &gta02_spi_acc_cfg;
/* Only GTA02v1 has a SD_DETECT GPIO. Since the slot is not
* hot-pluggable, this is not required anyway */
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
index 432699d..ac8bcf4 100644
--- a/drivers/input/misc/Kconfig
+++ b/drivers/input/misc/Kconfig
@@ -197,4 +197,13 @@ config HP_SDC_RTC
Say Y here if you want to support the built-in real time clock
of the HP SDC controller.
+config INPUT_LIS302DL
+ tristate "STmicro LIS302DL 3-axis accelerometer"
+ depends on SPI_MASTER
+ help
+ SPI driver for the STmicro LIS302DL 3-axis accelerometer.
+
+ The userspece interface is a 3-axis (X/Y/Z) relative movement
+ Linux input device, reporting REL_[XYZ] events.
+
endif
diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile
index ebd39f2..0d223ba 100644
--- a/drivers/input/misc/Makefile
+++ b/drivers/input/misc/Makefile
@@ -20,3 +20,4 @@
obj-$(CONFIG_INPUT_UINPUT) += uinput.o
obj-$(CONFIG_INPUT_APANEL) += apanel.o
obj-$(CONFIG_INPUT_GPIO_BUTTONS) += gpio_buttons.o
+obj-$(CONFIG_INPUT_LIS302DL) += lis302dl.o
diff --git a/drivers/input/misc/lis302dl.c b/drivers/input/misc/lis302dl.c
new file mode 100644
index 0000000..45c41c8
--- /dev/null
+++ b/drivers/input/misc/lis302dl.c
@@ -0,0 +1,633 @@
+/* Linux kernel driver for the ST LIS302D 3-axis accelerometer
+ *
+ * Copyright (C) 2007 by OpenMoko, Inc.
+ * Author: Harald Welte <laforge@openmoko.org>
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * TODO
+ * * statistics for overflow events
+ * * configuration interface (sysfs) for
+ * * enable/disable x/y/z axis data ready
+ * * enable/disable resume from freee fall / click
+ * * free fall / click parameters
+ * * high pass filter parameters
+ */
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/input.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/sysfs.h>
+
+#include <linux/lis302dl.h>
+
+#include <linux/spi/spi.h>
+
+#define LIS302DL_WHO_AM_I_MAGIC 0x3b
+
+enum lis302dl_reg {
+ LIS302DL_REG_WHO_AM_I = 0x0f,
+ LIS302DL_REG_CTRL1 = 0x20,
+ LIS302DL_REG_CTRL2 = 0x21,
+ LIS302DL_REG_CTRL3 = 0x22,
+ LIS302DL_REG_HP_FILTER_RESET = 0x23,
+ LIS302DL_REG_STATUS = 0x27,
+ LIS302DL_REG_OUT_X = 0x29,
+ LIS302DL_REG_OUT_Y = 0x2b,
+ LIS302DL_REG_OUT_Z = 0x2d,
+ LIS302DL_REG_FF_WU_CFG_1 = 0x30,
+ LIS302DL_REG_FF_WU_SRC_1 = 0x31,
+ LIS302DL_REG_FF_WU_THS_1 = 0x32,
+ LIS302DL_REG_FF_WU_DURATION_1 = 0x33,
+ LIS302DL_REG_FF_WU_CFG_2 = 0x34,
+ LIS302DL_REG_FF_WU_SRC_2 = 0x35,
+ LIS302DL_REG_FF_WU_THS_2 = 0x36,
+ LIS302DL_REG_FF_WU_DURATION_2 = 0x37,
+ LIS302DL_REG_CLICK_CFG = 0x38,
+ LIS302DL_REG_CLICK_SRC = 0x39,
+ LIS302DL_REG_CLICK_THSY_X = 0x3b,
+ LIS302DL_REG_CLICK_THSZ = 0x3c,
+ LIS302DL_REG_CLICK_TIME_LIMIT = 0x3d,
+ LIS302DL_REG_CLICK_LATENCY = 0x3e,
+ LIS302DL_REG_CLICK_WINDOW = 0x3f,
+};
+
+enum lis302dl_reg_ctrl1 {
+ LIS302DL_CTRL1_Xen = 0x01,
+ LIS302DL_CTRL1_Yen = 0x02,
+ LIS302DL_CTRL1_Zen = 0x04,
+ LIS302DL_CTRL1_STM = 0x08,
+ LIS302DL_CTRL1_STP = 0x10,
+ LIS302DL_CTRL1_FS = 0x20,
+ LIS302DL_CTRL1_PD = 0x40,
+ LIS302DL_CTRL1_DR = 0x80,
+};
+
+enum lis302dl_reg_ctrl3 {
+ LIS302DL_CTRL3_PP_OD = 0x40,
+};
+
+enum lis302dl_reg_status {
+ LIS302DL_STATUS_XDA = 0x01,
+ LIS302DL_STATUS_YDA = 0x02,
+ LIS302DL_STATUS_ZDA = 0x04,
+ LIS302DL_STATUS_XYZDA = 0x08,
+ LIS302DL_STATUS_XOR = 0x10,
+ LIS302DL_STATUS_YOR = 0x20,
+ LIS302DL_STATUS_ZOR = 0x40,
+ LIS302DL_STATUS_XYZOR = 0x80,
+};
+
+enum lis302dl_reg_ffwusrc1 {
+ LIS302DL_FFWUSRC1_XL = 0x01,
+ LIS302DL_FFWUSRC1_XH = 0x02,
+ LIS302DL_FFWUSRC1_YL = 0x04,
+ LIS302DL_FFWUSRC1_YH = 0x08,
+ LIS302DL_FFWUSRC1_ZL = 0x10,
+ LIS302DL_FFWUSRC1_ZH = 0x20,
+ LIS302DL_FFWUSRC1_IA = 0x40,
+};
+
+enum lis302dl_reg_cloik_src {
+ LIS302DL_CLICKSRC_SINGLE_X = 0x01,
+ LIS302DL_CLICKSRC_DOUBLE_X = 0x02,
+ LIS302DL_CLICKSRC_SINGLE_Y = 0x04,
+ LIS302DL_CLICKSRC_DOUBLE_Y = 0x08,
+ LIS302DL_CLICKSRC_SINGLE_Z = 0x10,
+ LIS302DL_CLICKSRC_DOUBLE_Z = 0x20,
+ LIS302DL_CLICKSRC_IA = 0x40,
+};
+
+struct lis302dl_info {
+ struct spi_device *spi_dev;
+ struct input_dev *input_dev;
+ struct mutex lock;
+ struct work_struct work;
+ unsigned int flags;
+ unsigned int working;
+ u_int8_t regs[0x40];
+};
+
+#define LIS302DL_F_WUP_FF 0x0001 /* wake up from free fall */
+#define LIS302DL_F_WUP_CLICK 0x0002
+#define LIS302DL_F_POWER 0x0010
+#define LIS302DL_F_FS 0x0020 /* ADC full scale */
+
+/* lowlevel register access functions */
+
+#define READ_BIT 0x01
+#define MS_BIT 0x02
+#define ADDR_SHIFT 2
+
+static inline u_int8_t __reg_read(struct lis302dl_info *lis, u_int8_t reg)
+{
+ int rc;
+ u_int8_t cmd;
+
+ cmd = (reg << ADDR_SHIFT) | READ_BIT;
+
+ rc = spi_w8r8(lis->spi_dev, cmd);
+
+ return rc;
+}
+
+static u_int8_t reg_read(struct lis302dl_info *lis, u_int8_t reg)
+{
+ u_int8_t ret;
+
+ mutex_lock(&lis->lock);
+ ret = __reg_read(lis, reg);
+ mutex_unlock(&lis->lock);
+
+ return ret;
+}
+
+static inline int __reg_write(struct lis302dl_info *lis, u_int8_t reg, u_int8_t val)
+{
+ u_int8_t buf[2];
+
+ buf[0] = (reg << ADDR_SHIFT);
+ buf[1] = val;
+
+ return spi_write(lis->spi_dev, buf, sizeof(buf));
+}
+
+static int reg_write(struct lis302dl_info *lis, u_int8_t reg, u_int8_t val)
+{
+ int ret;
+
+ mutex_lock(&lis->lock);
+ ret = __reg_write(lis, reg, val);
+ mutex_unlock(&lis->lock);
+
+ return ret;
+}
+
+static int reg_set_bit_mask(struct lis302dl_info *lis,
+ u_int8_t reg, u_int8_t mask, u_int8_t val)
+{
+ int ret;
+ u_int8_t tmp;
+
+ val &= mask;
+
+ mutex_lock(&lis->lock);
+
+ tmp = __reg_read(lis, reg);
+ tmp &= ~mask;
+ tmp |= val;
+ ret = __reg_write(lis, reg, tmp);
+
+ mutex_unlock(&lis->lock);
+
+ return ret;
+}
+
+/* interrupt handling related */
+
+enum lis302dl_intmode {
+ LIS302DL_INTMODE_GND = 0x00,
+ LIS302DL_INTMODE_FF_WU_1 = 0x01,
+ LIX302DL_INTMODE_FF_WU_2 = 0x02,
+ LIX302DL_INTMODE_FF_WU_12 = 0x03,
+ LIX302DL_INTMODE_DATA_READY = 0x04,
+ LIX302DL_INTMODE_CLICK = 0x07,
+};
+
+static void lis302dl_int_mode(struct spi_device *spi, int int_pin,
+ enum lis302dl_intmode mode)
+{
+ struct lis302dl_info *lis = dev_get_drvdata(&spi->dev);
+
+ if (int_pin == 1)
+ reg_set_bit_mask(lis, LIS302DL_REG_CTRL3, 0x07, mode);
+ else if (int_pin == 2)
+ reg_set_bit_mask(lis, LIS302DL_REG_CTRL3, 0x38, mode << 3);
+}
+
+static void _report_btn_single(struct input_dev *inp, int btn)
+{
+ input_report_key(inp, btn, 1);
+ input_sync(inp);
+ input_report_key(inp, btn, 0);
+}
+
+static void _report_btn_double(struct input_dev *inp, int btn)
+{
+ input_report_key(inp, btn, 1);
+ input_sync(inp);
+ input_report_key(inp, btn, 0);
+ input_sync(inp);
+ input_report_key(inp, btn, 1);
+ input_sync(inp);
+ input_report_key(inp, btn, 0);
+}
+
+static void lis302dl_work(struct work_struct *work)
+{
+ struct lis302dl_info *lis =
+ container_of(work, struct lis302dl_info, work);
+
+ u_int8_t status, ff_wu_src_1, click_src;
+ u_int8_t val;
+
+ lis->working = 1;
+
+ status = reg_read(lis, LIS302DL_REG_STATUS);
+ ff_wu_src_1 = reg_read(lis, LIS302DL_REG_FF_WU_SRC_1);
+ click_src = reg_read(lis, LIS302DL_REG_CLICK_SRC);
+
+ if (status & LIS302DL_STATUS_XDA) {
+ val = reg_read(lis, LIS302DL_REG_OUT_X);
+ if (lis->flags & LIS302DL_F_FS)
+ val = val << 2;
+ input_report_rel(lis->input_dev, REL_X, val);
+ }
+
+ if (status & LIS302DL_STATUS_YDA) {
+ val = reg_read(lis, LIS302DL_REG_OUT_Y);
+ if (lis->flags & LIS302DL_F_FS)
+ val = val << 2;
+ input_report_rel(lis->input_dev, REL_Y, val);
+ }
+
+ if (status & LIS302DL_STATUS_ZDA) {
+ val = reg_read(lis, LIS302DL_REG_OUT_Z);
+ if (lis->flags & LIS302DL_F_FS)
+ val = val << 2;
+ input_report_rel(lis->input_dev, REL_Z, val);
+ }
+
+ if (status & 0xf0)
+ dev_dbg(&lis->spi_dev->dev, "overrun!\n");
+
+ /* FIXME: implement overrun statistics */
+
+ if (ff_wu_src_1 & LIS302DL_FFWUSRC1_IA) {
+ /* FIXME: free fall interrupt handling */
+ }
+
+ if (click_src & LIS302DL_CLICKSRC_IA) {
+ if (click_src & LIS302DL_CLICKSRC_SINGLE_X)
+ _report_btn_single(lis->input_dev, BTN_X);
+ if (click_src & LIS302DL_CLICKSRC_DOUBLE_X)
+ _report_btn_double(lis->input_dev, BTN_X);
+
+ if (click_src & LIS302DL_CLICKSRC_SINGLE_Y)
+ _report_btn_single(lis->input_dev, BTN_Y);
+ if (click_src & LIS302DL_CLICKSRC_DOUBLE_Y)
+ _report_btn_double(lis->input_dev, BTN_Y);
+
+ if (click_src & LIS302DL_CLICKSRC_SINGLE_Z)
+ _report_btn_single(lis->input_dev, BTN_Z);
+ if (click_src & LIS302DL_CLICKSRC_DOUBLE_Z)
+ _report_btn_double(lis->input_dev, BTN_Z);
+ }
+
+ lis->working = 0;
+ input_sync(lis->input_dev);
+ put_device(&lis->spi_dev->dev);
+
+ enable_irq(lis->spi_dev->irq);
+}
+
+static void lis302dl_schedule_work(struct lis302dl_info *lis)
+{
+ int status;
+
+ get_device(&lis->spi_dev->dev);
+ status = schedule_work(&lis->work);
+ if (!status && !lis->working)
+ dev_dbg(&lis->spi_dev->dev, "work item may be lost\n");
+}
+
+static irqreturn_t lis302dl_interrupt(int irq, void *_lis)
+{
+ struct lis302dl_info *lis = _lis;
+
+ lis302dl_schedule_work(lis);
+
+ /* Disable any further interrupts until we have processed
+ * the current one */
+ disable_irq(lis->spi_dev->irq);
+
+ return IRQ_HANDLED;
+}
+
+/* sysfs */
+
+static ssize_t show_rate(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct lis302dl_info *lis = dev_get_drvdata(dev);
+ u_int8_t ctrl1 = reg_read(lis, LIS302DL_REG_CTRL1);
+
+ return sprintf(buf, "%d\n", ctrl1 & LIS302DL_CTRL1_DR ? 400 : 100);
+}
+
+static ssize_t set_rate(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct lis302dl_info *lis = dev_get_drvdata(dev);
+
+ if (!strcmp(buf, "400\n"))
+ reg_set_bit_mask(lis, LIS302DL_REG_CTRL1, LIS302DL_CTRL1_DR,
+ LIS302DL_CTRL1_DR);
+ else
+ reg_set_bit_mask(lis, LIS302DL_REG_CTRL1, LIS302DL_CTRL1_DR, 0);
+
+ return count;
+}
+
+static DEVICE_ATTR(sample_rate, S_IRUGO | S_IWUSR, show_rate, set_rate);
+
+static ssize_t show_scale(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct lis302dl_info *lis = dev_get_drvdata(dev);
+ u_int8_t ctrl1 = reg_read(lis, LIS302DL_REG_CTRL1);
+
+ return sprintf(buf, "%s\n", ctrl1 & LIS302DL_CTRL1_FS ? "9.2" : "2.3");
+}
+
+static ssize_t set_scale(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct lis302dl_info *lis = dev_get_drvdata(dev);
+
+ if (!strcmp(buf, "9.2\n"))
+ reg_set_bit_mask(lis, LIS302DL_REG_CTRL1, LIS302DL_CTRL1_FS,
+ LIS302DL_CTRL1_FS);
+ else
+ reg_set_bit_mask(lis, LIS302DL_REG_CTRL1, LIS302DL_CTRL1_FS, 0);
+
+ return count;
+}
+
+static DEVICE_ATTR(full_scale, S_IRUGO | S_IWUSR, show_scale, set_scale);
+
+static struct attribute *lis302dl_sysfs_entries[] = {
+ &dev_attr_sample_rate.attr,
+ &dev_attr_full_scale.attr,
+};
+
+static struct attribute_group lis302dl_attr_group = {
+ .name = NULL,
+ .attrs = lis302dl_sysfs_entries,
+};
+
+/* input device handling and driver core interaction */
+
+static int lis302dl_input_open(struct input_dev *inp)
+{
+ struct lis302dl_info *lis = inp->private;
+ u_int8_t ctrl1 = LIS302DL_CTRL1_PD | LIS302DL_CTRL1_Xen |
+ LIS302DL_CTRL1_Yen | LIS302DL_CTRL1_Zen;
+
+ /* make sure we're powered up and generate data ready */
+ reg_set_bit_mask(lis, LIS302DL_REG_CTRL1, ctrl1, ctrl1);
+
+ return 0;
+}
+
+static void lis302dl_input_close(struct input_dev *inp)
+{
+ struct lis302dl_info *lis = inp->private;
+ u_int8_t ctrl1 = LIS302DL_CTRL1_Xen | LIS302DL_CTRL1_Yen |
+ LIS302DL_CTRL1_Zen;
+
+ /* since the input core already serializes access and makes sure we
+ * only see close() for the close of the lastre user, we can safely
+ * disable the data ready events */
+ reg_set_bit_mask(lis, LIS302DL_REG_CTRL1, ctrl1, 0x00);
+
+ /* however, don't power down the whole device if still needed */
+ if (!(lis->flags & LIS302DL_F_WUP_FF ||
+ lis->flags & LIS302DL_F_WUP_CLICK)) {
+ reg_set_bit_mask(lis, LIS302DL_REG_CTRL1, LIS302DL_CTRL1_PD,
+ 0x00);
+ }
+}
+
+static int __devinit lis302dl_probe(struct spi_device *spi)
+{
+ int rc;
+ struct lis302dl_info *lis;
+ u_int8_t wai;
+
+ lis = kzalloc(sizeof(*lis), GFP_KERNEL);
+ if (!lis)
+ return -ENOMEM;
+
+ mutex_init(&lis->lock);
+ INIT_WORK(&lis->work, lis302dl_work);
+ lis->spi_dev = spi;
+
+ spi_set_drvdata(spi, lis);
+
+ rc = spi_setup(spi);
+ if (rc < 0) {
+ printk(KERN_ERR "error durign spi_setup of lis302dl driver\n");
+ dev_set_drvdata(&spi->dev, NULL);
+ kfree(lis);
+ return rc;
+ }
+
+ wai = reg_read(lis, LIS302DL_REG_WHO_AM_I);
+ if (wai != LIS302DL_WHO_AM_I_MAGIC) {
+ printk(KERN_ERR "unknown who_am_i signature 0x%02x\n", wai);
+ dev_set_drvdata(&spi->dev, NULL);
+ kfree(lis);
+ return -ENODEV;
+ }
+
+ /* switch interrupt to open collector */
+ reg_write(lis, LIS302DL_CTRL3_PP_OD, 0x7c);
+
+ rc = request_irq(lis->spi_dev->irq, lis302dl_interrupt, IRQF_DISABLED,
+ "lis302dl", NULL);
+ if (rc < 0) {
+ dev_err(&spi->dev, "error requesting IRQ %d\n",
+ lis->spi_dev->irq);
+ /* FIXME */
+ return rc;
+ }
+
+ rc = sysfs_create_group(&spi->dev.kobj, &lis302dl_attr_group);
+ if (rc) {
+ dev_err(&spi->dev, "error creating sysfs group\n");
+ /* FIXME */
+ return rc;
+ }
+
+ /* initialize input layer details */
+ lis->input_dev = input_allocate_device();
+ if (!lis->input_dev) {
+ dev_err(&spi->dev, "Unable to allocate input device\n");
+ /* FIXME */
+ }
+
+ set_bit(EV_REL, lis->input_dev->evbit);
+ set_bit(EV_KEY, lis->input_dev->evbit);
+ set_bit(BTN_X, lis->input_dev->keybit);
+ set_bit(BTN_Y, lis->input_dev->keybit);
+ set_bit(BTN_Z, lis->input_dev->keybit);
+
+ lis->input_dev->private = lis;
+ lis->input_dev->name = "lis302dl"; /* FIXME: platform data */
+ lis->input_dev->id.bustype = BUS_I2C; /* FIXME: SPI Bus */
+ lis->input_dev->open = lis302dl_input_open;
+ lis->input_dev->close = lis302dl_input_close;
+
+ input_register_device(lis->input_dev);
+
+ return 0;
+}
+
+static int __devexit lis302dl_remove(struct spi_device *spi)
+{
+ struct lis302dl_info *lis = dev_get_drvdata(&spi->dev);
+
+ /* power down the device */
+ reg_write(lis, LIS302DL_REG_CTRL1, 0x00);
+ sysfs_remove_group(&spi->dev.kobj, &lis302dl_attr_group);
+ input_unregister_device(lis->input_dev);
+ dev_set_drvdata(&spi->dev, NULL);
+ kfree(lis);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int lis302dl_suspend(struct spi_device *spi, pm_message_t state)
+{
+ struct lis302dl_info *lis = dev_get_drvdata(&spi->dev);
+
+ /* save registers */
+ lis->regs[LIS302DL_REG_CTRL1] = reg_read(lis, LIS302DL_REG_CTRL1);
+ lis->regs[LIS302DL_REG_CTRL2] = reg_read(lis, LIS302DL_REG_CTRL2);
+ lis->regs[LIS302DL_REG_CTRL3] = reg_read(lis, LIS302DL_REG_CTRL3);
+ lis->regs[LIS302DL_REG_FF_WU_CFG_1] =
+ reg_read(lis, LIS302DL_REG_FF_WU_CFG_1);
+ lis->regs[LIS302DL_REG_FF_WU_THS_1] =
+ reg_read(lis, LIS302DL_REG_FF_WU_THS_1);
+ lis->regs[LIS302DL_REG_FF_WU_DURATION_1] =
+ reg_read(lis, LIS302DL_REG_FF_WU_DURATION_1);
+ lis->regs[LIS302DL_REG_FF_WU_CFG_2] =
+ reg_read(lis, LIS302DL_REG_FF_WU_CFG_2);
+ lis->regs[LIS302DL_REG_FF_WU_THS_2] =
+ reg_read(lis, LIS302DL_REG_FF_WU_THS_2);
+ lis->regs[LIS302DL_REG_FF_WU_DURATION_2] =
+ reg_read(lis, LIS302DL_REG_FF_WU_DURATION_2);
+ lis->regs[LIS302DL_REG_CLICK_CFG] =
+ reg_read(lis, LIS302DL_REG_CLICK_CFG);
+ lis->regs[LIS302DL_REG_CLICK_THSY_X] =
+ reg_read(lis, LIS302DL_REG_CLICK_THSY_X);
+ lis->regs[LIS302DL_REG_CLICK_THSZ] =
+ reg_read(lis, LIS302DL_REG_CLICK_THSZ);
+ lis->regs[LIS302DL_REG_CLICK_TIME_LIMIT] =
+ reg_read(lis, LIS302DL_REG_CLICK_TIME_LIMIT);
+ lis->regs[LIS302DL_REG_CLICK_LATENCY] =
+ reg_read(lis, LIS302DL_REG_CLICK_LATENCY);
+ lis->regs[LIS302DL_REG_CLICK_WINDOW] =
+ reg_read(lis, LIS302DL_REG_CLICK_WINDOW);
+
+ /* determine if we want to wake up from the accel. */
+ if (!(lis->flags & LIS302DL_F_WUP_FF ||
+ lis->flags & LIS302DL_F_WUP_CLICK)) {
+ /* power down */
+ u_int8_t tmp;
+ tmp = reg_read(lis, LIS302DL_REG_CTRL1);
+ tmp &= ~LIS302DL_CTRL1_PD;
+ reg_write(lis, LIS302DL_REG_CTRL1, tmp);
+ }
+
+ return 0;
+}
+
+static int lis302dl_resume(struct spi_device *spi)
+{
+ struct lis302dl_info *lis = dev_get_drvdata(&spi->dev);
+
+ /* restore registers after resume */
+ reg_write(lis, LIS302DL_REG_CTRL1, lis->regs[LIS302DL_REG_CTRL1]);
+ reg_write(lis, LIS302DL_REG_CTRL2, lis->regs[LIS302DL_REG_CTRL2]);
+ reg_write(lis, LIS302DL_REG_CTRL3, lis->regs[LIS302DL_REG_CTRL3]);
+ reg_write(lis, LIS302DL_REG_FF_WU_CFG_1,
+ lis->regs[LIS302DL_REG_FF_WU_CFG_1]);
+ reg_write(lis, LIS302DL_REG_FF_WU_THS_1,
+ lis->regs[LIS302DL_REG_FF_WU_THS_1]);
+ reg_write(lis, LIS302DL_REG_FF_WU_DURATION_1,
+ lis->regs[LIS302DL_REG_FF_WU_DURATION_1]);
+ reg_write(lis, LIS302DL_REG_FF_WU_CFG_2,
+ lis->regs[LIS302DL_REG_FF_WU_CFG_2]);
+ reg_write(lis, LIS302DL_REG_FF_WU_THS_2,
+ lis->regs[LIS302DL_REG_FF_WU_THS_2]);
+ reg_write(lis, LIS302DL_REG_FF_WU_DURATION_2,
+ lis->regs[LIS302DL_REG_FF_WU_DURATION_2]);
+ reg_write(lis, LIS302DL_REG_CLICK_CFG,
+ lis->regs[LIS302DL_REG_CLICK_CFG]);
+ reg_write(lis, LIS302DL_REG_CLICK_THSY_X,
+ lis->regs[LIS302DL_REG_CLICK_THSY_X]);
+ reg_write(lis, LIS302DL_REG_CLICK_THSZ,
+ lis->regs[LIS302DL_REG_CLICK_THSZ]);
+ reg_write(lis, LIS302DL_REG_CLICK_TIME_LIMIT,
+ lis->regs[LIS302DL_REG_CLICK_TIME_LIMIT]);
+ reg_write(lis, LIS302DL_REG_CLICK_LATENCY,
+ lis->regs[LIS302DL_REG_CLICK_LATENCY]);
+ reg_write(lis, LIS302DL_REG_CLICK_WINDOW,
+ lis->regs[LIS302DL_REG_CLICK_WINDOW]);
+
+ return 0;
+}
+#else
+#define lis302dl_suspend NULL
+#define lis302dl_resume NULL
+#endif
+
+static struct spi_driver lis302dl_driver = {
+ .driver = {
+ .name = "lis302dl",
+ .owner = THIS_MODULE,
+ },
+
+ .probe = lis302dl_probe,
+ .remove = __devexit_p(lis302dl_remove),
+ .suspend = lis302dl_suspend,
+ .resume = lis302dl_resume,
+};
+
+static int __init lis302dl_init(void)
+{
+ return spi_register_driver(&lis302dl_driver);
+}
+
+static void __exit lis302dl_exit(void)
+{
+ spi_unregister_driver(&lis302dl_driver);
+}
+
+MODULE_AUTHOR("Harald Welte <laforge@openmoko.org>");
+MODULE_LICENSE("GPL");
+
+module_init(lis302dl_init);
+module_exit(lis302dl_exit);
diff --git a/include/linux/lis302dl.h b/include/linux/lis302dl.h
new file mode 100644
index 0000000..d0f31be
--- /dev/null
+++ b/include/linux/lis302dl.h
@@ -0,0 +1,11 @@
+#ifndef _LINUX_LIS302DL_H
+#define _LINUX_LIS302DL_H
+
+#include <linux/types.h>
+
+struct lis302dl_platform_data {
+ char *name;
+};
+
+#endif /* _LINUX_LIS302DL_H */
+
--
1.5.6.3

View file

@ -0,0 +1,276 @@
From fc22d87d11df9053f1a1b41b7b450c3af07b5059 Mon Sep 17 00:00:00 2001
From: mokopatches <mokopatches@openmoko.org>
Date: Wed, 16 Jul 2008 14:46:56 +0100
Subject: [PATCH] gta02-leds.patch
---
drivers/leds/Kconfig | 6 +
drivers/leds/Makefile | 1 +
drivers/leds/leds-neo1973-gta02.c | 226 +++++++++++++++++++++++++++++++++++++
3 files changed, 233 insertions(+), 0 deletions(-)
create mode 100644 drivers/leds/leds-neo1973-gta02.c
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index 8c7d949..b6b1211 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -153,6 +153,12 @@ config LEDS_NEO1973_VIBRATOR
help
This option enables support for the vibrator on the FIC Neo1973.
+config LEDS_NEO1973_GTA02
+ tristate "LED Support for the FIC Neo1973 (GTA02)"
+ depends on LEDS_CLASS && MACH_NEO1973_GTA02
+ help
+ This option enables support for the LEDs on the FIC Neo1973.
+
comment "LED Triggers"
config LEDS_TRIGGERS
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
index 148fe51..3a9df6a 100644
--- a/drivers/leds/Makefile
+++ b/drivers/leds/Makefile
@@ -22,6 +22,7 @@ obj-$(CONFIG_LEDS_CLEVO_MAIL) += leds-clevo-mail.o
obj-$(CONFIG_LEDS_HP6XX) += leds-hp6xx.o
obj-$(CONFIG_LEDS_FSG) += leds-fsg.o
obj-$(CONFIG_LEDS_NEO1973_VIBRATOR) += leds-neo1973-vibrator.o
+obj-$(CONFIG_LEDS_NEO1973_GTA02) += leds-neo1973-gta02.o
# LED Triggers
obj-$(CONFIG_LEDS_TRIGGER_TIMER) += ledtrig-timer.o
diff --git a/drivers/leds/leds-neo1973-gta02.c b/drivers/leds/leds-neo1973-gta02.c
new file mode 100644
index 0000000..bf1d540
--- /dev/null
+++ b/drivers/leds/leds-neo1973-gta02.c
@@ -0,0 +1,226 @@
+/*
+ * LED driver for the FIC Neo1973 GTA02 GSM phone
+ *
+ * (C) 2006-2007 by OpenMoko, Inc.
+ * Author: Harald Welte <laforge@openmoko.org>
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/leds.h>
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/arch/pwm.h>
+#include <asm/arch/gta02.h>
+#include <asm/plat-s3c/regs-timer.h>
+
+#define MAX_LEDS 3
+#define COUNTER 256
+
+struct gta02_led_priv
+{
+ struct mutex mutex;
+ struct led_classdev cdev;
+ struct s3c2410_pwm pwm;
+ unsigned int gpio;
+ unsigned int has_pwm;
+};
+
+struct gta02_led_bundle
+{
+ int num_leds;
+ struct gta02_led_priv led[MAX_LEDS];
+};
+
+static inline struct gta02_led_priv *to_priv(struct led_classdev *led_cdev)
+{
+ return container_of(led_cdev, struct gta02_led_priv, cdev);
+}
+
+static inline struct gta02_led_bundle *to_bundle(struct led_classdev *led_cdev)
+{
+ return dev_get_drvdata(led_cdev->dev);
+}
+
+static void gta02led_set(struct led_classdev *led_cdev,
+ enum led_brightness value)
+{
+ struct gta02_led_priv *lp = to_priv(led_cdev);
+
+ /*
+ * value == 255 -> 99% duty cycle (full power)
+ * value == 128 -> 50% duty cycle (medium power)
+ * value == 0 -> 0% duty cycle (zero power)
+ */
+ mutex_lock(&lp->mutex);
+ if (lp->has_pwm) {
+ s3c2410_pwm_duty_cycle(value, &lp->pwm);
+ } else {
+ if (value)
+ s3c2410_gpio_setpin(lp->gpio, 1);
+ else
+ s3c2410_gpio_setpin(lp->gpio, 0);
+ }
+ mutex_unlock(&lp->mutex);
+}
+
+#ifdef CONFIG_PM
+static int gta02led_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ struct gta02_led_bundle *bundle = platform_get_drvdata(pdev);
+ int i;
+
+ for (i = 0; i < bundle->num_leds; i++)
+ led_classdev_suspend(&bundle->led[i].cdev);
+
+ return 0;
+}
+
+static int gta02led_resume(struct platform_device *pdev)
+{
+ struct gta02_led_bundle *bundle = platform_get_drvdata(pdev);
+ int i;
+
+ for (i = 0; i < bundle->num_leds; i++)
+ led_classdev_resume(&bundle->led[i].cdev);
+
+ return 0;
+}
+#endif
+
+static int __init gta02led_probe(struct platform_device *pdev)
+{
+ int i, rc;
+ struct gta02_led_bundle *bundle;
+
+ if (!machine_is_neo1973_gta02())
+ return -EIO;
+
+ bundle = kzalloc(sizeof(struct gta02_led_bundle), GFP_KERNEL);
+ if (!bundle)
+ return -ENOMEM;
+ platform_set_drvdata(pdev, bundle);
+
+ for (i = 0; i < pdev->num_resources; i++) {
+ struct gta02_led_priv *lp;
+ struct resource *r;
+
+ if (i >= MAX_LEDS)
+ break;
+
+ r = platform_get_resource(pdev, 0, i);
+ if (!r || !r->start || !r->name)
+ continue;
+
+ lp = &bundle->led[i];
+
+ lp->gpio = r->start;
+ lp->cdev.name = r->name;
+ lp->cdev.brightness_set = gta02led_set;
+
+ switch (lp->gpio) {
+ case S3C2410_GPB0:
+ lp->has_pwm = 1;
+ lp->pwm.timerid = PWM0;
+ s3c2410_gpio_cfgpin(lp->gpio, S3C2410_GPB0_TOUT0);
+ break;
+ case S3C2410_GPB1:
+ lp->has_pwm = 1;
+ lp->pwm.timerid = PWM1;
+ s3c2410_gpio_cfgpin(lp->gpio, S3C2410_GPB1_TOUT1);
+ break;
+ case S3C2410_GPB2:
+ lp->has_pwm = 1;
+ lp->pwm.timerid = PWM2;
+ s3c2410_gpio_cfgpin(lp->gpio, S3C2410_GPB2_TOUT2);
+ break;
+ case S3C2410_GPB3:
+ lp->has_pwm = 1;
+ lp->pwm.timerid = PWM3;
+ s3c2410_gpio_cfgpin(lp->gpio, S3C2410_GPB3_TOUT3);
+ break;
+ default:
+ break;
+ }
+
+ lp->pwm.prescaler = 0;
+ lp->pwm.divider = S3C2410_TCFG1_MUX3_DIV8;
+ lp->pwm.counter = COUNTER;
+ lp->pwm.comparer = COUNTER;
+ s3c2410_pwm_enable(&lp->pwm);
+ s3c2410_pwm_start(&lp->pwm);
+
+ switch (lp->gpio) {
+ case S3C2410_GPB0:
+ case S3C2410_GPB1:
+ case S3C2410_GPB2:
+ lp->has_pwm = 0;
+ s3c2410_gpio_cfgpin(lp->gpio, S3C2410_GPIO_OUTPUT);
+ s3c2410_gpio_setpin(lp->gpio, 0);
+ break;
+ default:
+ break;
+ }
+
+ mutex_init(&lp->mutex);
+ rc = led_classdev_register(&pdev->dev, &lp->cdev);
+ }
+
+ return 0;
+}
+
+static int gta02led_remove(struct platform_device *pdev)
+{
+ struct gta02_led_bundle *bundle = platform_get_drvdata(pdev);
+ int i;
+
+ for (i = 0; i < bundle->num_leds; i++) {
+ struct gta02_led_priv *lp = &bundle->led[i];
+ if (lp->has_pwm)
+ s3c2410_pwm_disable(&lp->pwm);
+
+ led_classdev_unregister(&lp->cdev);
+ mutex_destroy(&lp->mutex);
+ }
+
+ platform_set_drvdata(pdev, NULL);
+ kfree(bundle);
+
+ return 0;
+}
+
+static struct platform_driver gta02led_driver = {
+ .probe = gta02led_probe,
+ .remove = gta02led_remove,
+#ifdef CONFIG_PM
+ .suspend = gta02led_suspend,
+ .resume = gta02led_resume,
+#endif
+ .driver = {
+ .name = "gta02-led",
+ },
+};
+
+static int __init gta02led_init(void)
+{
+ return platform_driver_register(&gta02led_driver);
+}
+
+static void __exit gta02led_exit(void)
+{
+ platform_driver_unregister(&gta02led_driver);
+}
+
+module_init(gta02led_init);
+module_exit(gta02led_exit);
+
+MODULE_AUTHOR("Harald Welte <laforge@openmoko.org>");
+MODULE_DESCRIPTION("FIC Neo1973 GTA02 LED driver");
+MODULE_LICENSE("GPL");
--
1.5.6.3

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,200 @@
From 4ced79a6699eb5828c71b5438826fb44e3b41997 Mon Sep 17 00:00:00 2001
From: mokopatches <mokopatches@openmoko.org>
Date: Wed, 16 Jul 2008 14:46:56 +0100
Subject: [PATCH] pcf506xx.patch
Moved shared PMU code from pcf50606.h and pcf50633.h (which prevented inclusion
of both at the same time) to pcf506xx.h
- include/linux/pcf50606.h (struct pmu_voltage_rail, enum pmu_event, pmu_cb):
moved to pcf506xx.h
- include/linux/pcf50633.h (struct pmu_voltage_rail, enum pmu_event, pmu_cb):
moved to pcf506xx.h
Signed off-by: Werner Almesberger <werner@openmoko.org>
---
drivers/i2c/chips/pcf50606.c | 28 +++++++++++++++++++++++++++-
include/linux/pcf50606.h | 23 +++--------------------
include/linux/pcf50633.h | 27 +++------------------------
include/linux/pcf506xx.h | 31 +++++++++++++++++++++++++++++++
4 files changed, 64 insertions(+), 45 deletions(-)
create mode 100644 include/linux/pcf506xx.h
diff --git a/drivers/i2c/chips/pcf50606.c b/drivers/i2c/chips/pcf50606.c
index 6626c68..b530583 100644
--- a/drivers/i2c/chips/pcf50606.c
+++ b/drivers/i2c/chips/pcf50606.c
@@ -102,6 +102,7 @@ struct pcf50606_data {
int allow_close;
int onkey_seconds;
int irq;
+ int coldplug_done;
#ifdef CONFIG_PM
struct {
u_int8_t dcdc1, dcdc2;
@@ -573,6 +574,30 @@ static void pcf50606_work(struct work_struct *work)
if (ret != 3)
DEBUGPC("Oh crap PMU IRQ register read failed %d\n", ret);
+ if (!pcf->coldplug_done) {
+ DEBUGPC("PMU Coldplug init\n");
+
+ /* we used SECOND to kick ourselves started -- turn it off */
+ pcfirq[0] &= ~PCF50606_INT1_SECOND;
+ reg_set_bit_mask(pcf, PCF50606_REG_INT1M, PCF50606_INT1_SECOND,
+ PCF50606_INT1_SECOND);
+
+ /* coldplug the USB if present */
+ if (__reg_read(pcf, PCF50606_REG_OOCS) & PCF50606_OOCS_EXTON) {
+ /* Charger inserted */
+ DEBUGPC("COLD CHGINS ");
+ input_report_key(pcf->input_dev, KEY_BATTERY, 1);
+ apm_queue_event(APM_POWER_STATUS_CHANGE);
+ pcf->flags |= PCF50606_F_CHG_PRESENT;
+ if (pcf->pdata->cb)
+ pcf->pdata->cb(&pcf->client.dev,
+ PCF50606_FEAT_MBC, PMU_EVT_INSERT);
+ }
+
+ pcf->coldplug_done = 1;
+ }
+
+
dev_dbg(&pcf->client.dev, "INT1=0x%02x INT2=0x%02x INT3=0x%02x:",
pcfirq[0], pcfirq[1], pcfirq[2]);
@@ -1642,7 +1667,8 @@ static int pcf50606_detect(struct i2c_adapter *adapter, int address, int kind)
pm_power_off = &pcf50606_go_standby;
/* configure interrupt mask */
- reg_write(data, PCF50606_REG_INT1M, PCF50606_INT1_SECOND);
+ /* we don't mask SECOND here, because we want one to do coldplug with */
+ reg_write(data, PCF50606_REG_INT1M, 0x00);
reg_write(data, PCF50606_REG_INT2M, 0x00);
reg_write(data, PCF50606_REG_INT3M, PCF50606_INT3_TSCPRES);
diff --git a/include/linux/pcf50606.h b/include/linux/pcf50606.h
index bc98e47..167328f 100644
--- a/include/linux/pcf50606.h
+++ b/include/linux/pcf50606.h
@@ -1,6 +1,9 @@
#ifndef _LINUX_PCF50606_H
#define _LINUX_PCF50606_H
+#include <linux/pcf506xx.h>
+
+
/* public in-kernel pcf50606 api */
enum pcf50606_regulator_id {
PCF50606_REGULATOR_DCD,
@@ -48,26 +51,6 @@ pcf50606_onoff_set(struct pcf50606_data *pcf,
extern void
pcf50606_charge_fast(struct pcf50606_data *pcf, int on);
-#define PMU_VRAIL_F_SUSPEND_ON 0x00000001 /* Remains on during suspend */
-#define PMU_VRAIL_F_UNUSED 0x00000002 /* This rail is not used */
-struct pmu_voltage_rail {
- char *name;
- unsigned int flags;
- struct {
- unsigned int init;
- unsigned int max;
- } voltage;
-};
-
-enum pmu_event {
- PMU_EVT_NONE,
- PMU_EVT_INSERT,
- PMU_EVT_REMOVE,
- __NUM_PMU_EVTS
-};
-
-typedef int pmu_cb(struct device *dev, unsigned int feature,
- enum pmu_event event);
#define PCF50606_FEAT_EXTON 0x00000001 /* not yet supported */
#define PCF50606_FEAT_MBC 0x00000002
diff --git a/include/linux/pcf50633.h b/include/linux/pcf50633.h
index 5f32004..bf50fe4 100644
--- a/include/linux/pcf50633.h
+++ b/include/linux/pcf50633.h
@@ -1,6 +1,9 @@
#ifndef _LINUX_PCF50633_H
#define _LINUX_PCF50633_H
+#include <linux/pcf506xx.h>
+
+
/* public in-kernel pcf50633 api */
enum pcf50633_regulator_id {
PCF50633_REGULATOR_AUTO,
@@ -57,30 +60,6 @@ pcf50633_usb_curlim_set(struct pcf50633_data *pcf, int ma);
extern void
pcf50633_charge_enable(struct pcf50633_data *pcf, int on);
-/* FIXME: sharded with pcf50606 */
-#define PMU_VRAIL_F_SUSPEND_ON 0x00000001 /* Remains on during suspend */
-#define PMU_VRAIL_F_UNUSED 0x00000002 /* This rail is not used */
-struct pmu_voltage_rail {
- char *name;
- unsigned int flags;
- struct {
- unsigned int init;
- unsigned int max;
- } voltage;
-};
-
-enum pmu_event {
- PMU_EVT_NONE,
- PMU_EVT_INSERT,
- PMU_EVT_REMOVE,
- PMU_EVT_USB_INSERT,
- PMU_EVT_USB_REMOVE,
- __NUM_PMU_EVTS
-};
-
-typedef int pmu_cb(struct device *dev, unsigned int feature,
- enum pmu_event event);
-
#define PCF50633_FEAT_EXTON 0x00000001 /* not yet supported */
#define PCF50633_FEAT_MBC 0x00000002
#define PCF50633_FEAT_BBC 0x00000004 /* not yet supported */
diff --git a/include/linux/pcf506xx.h b/include/linux/pcf506xx.h
new file mode 100644
index 0000000..33be73e
--- /dev/null
+++ b/include/linux/pcf506xx.h
@@ -0,0 +1,31 @@
+#ifndef _LINUX_PCF506XX_H
+#define _LINUX_PCF506XX_H
+
+
+#define PMU_VRAIL_F_SUSPEND_ON 0x00000001 /* Remains on during suspend */
+#define PMU_VRAIL_F_UNUSED 0x00000002 /* This rail is not used */
+struct pmu_voltage_rail {
+ char *name;
+ unsigned int flags;
+ struct {
+ unsigned int init;
+ unsigned int max;
+ } voltage;
+};
+
+enum pmu_event {
+ PMU_EVT_NONE,
+ PMU_EVT_INSERT,
+ PMU_EVT_REMOVE,
+#ifdef CONFIG_SENSORS_PCF50633
+ PMU_EVT_USB_INSERT,
+ PMU_EVT_USB_REMOVE,
+#endif
+ __NUM_PMU_EVTS
+};
+
+typedef int pmu_cb(struct device *dev, unsigned int feature,
+ enum pmu_event event);
+
+
+#endif /* !_LINUX_PCF506XX_H */
--
1.5.6.3

View file

@ -0,0 +1,209 @@
From d4d6e6229c94cfe2bd8f29b4ebc0d60b8ad29455 Mon Sep 17 00:00:00 2001
From: mokopatches <mokopatches@openmoko.org>
Date: Wed, 16 Jul 2008 14:46:57 +0100
Subject: [PATCH] gta02-bt-fixes.patch
Modify GTA02 power manager for bluetooth.
1. Default power value isn't correct. Now we set pcf50633 LDO4 to 3.2 voltage.
2. Separate GTA01 and GTA02 source code.
3. Add pcf50633 API for enable register.
---
arch/arm/mach-s3c2440/mach-gta02.c | 4 +-
arch/arm/plat-s3c24xx/neo1973_pm_bt.c | 71 ++++++++++++++++++++++++++++----
include/linux/pcf50633.h | 1 +
3 files changed, 65 insertions(+), 11 deletions(-)
diff --git a/arch/arm/mach-s3c2440/mach-gta02.c b/arch/arm/mach-s3c2440/mach-gta02.c
index 3fbb131..46acede 100644
--- a/arch/arm/mach-s3c2440/mach-gta02.c
+++ b/arch/arm/mach-s3c2440/mach-gta02.c
@@ -213,10 +213,10 @@ static struct pcf50633_platform_data gta02_pcf_pdata = {
},
},
[PCF50633_REGULATOR_LDO4] = {
- .name = "gl_2v5",
+ .name = "bt_3v2",
.voltage = {
.init = 2500,
- .max = 2500,
+ .max = 3300,
},
},
[PCF50633_REGULATOR_LDO5] = {
diff --git a/arch/arm/plat-s3c24xx/neo1973_pm_bt.c b/arch/arm/plat-s3c24xx/neo1973_pm_bt.c
index d685ef7..8f5be88 100644
--- a/arch/arm/plat-s3c24xx/neo1973_pm_bt.c
+++ b/arch/arm/plat-s3c24xx/neo1973_pm_bt.c
@@ -16,12 +16,19 @@
#include <linux/kernel.h>
#include <linux/platform_device.h>
-#include <linux/pcf50606.h>
-
#include <asm/hardware.h>
#include <asm/mach-types.h>
+
+#ifdef CONFIG_MACH_NEO1973_GTA01
#include <asm/arch/gta01.h>
+#include <linux/pcf50606.h>
+#endif
+
+#ifdef CONFIG_MACH_NEO1973_GTA02
#include <asm/arch/gta02.h>
+#include <linux/pcf50633.h>
+#endif
+
#define DRVMSG "FIC Neo1973 Bluetooth Power Management"
@@ -30,6 +37,8 @@ static ssize_t bt_read(struct device *dev, struct device_attribute *attr,
{
if (!strcmp(attr->attr.name, "power_on")) {
switch (machine_arch_type) {
+
+#ifdef CONFIG_MACH_NEO1973_GTA01
case MACH_TYPE_NEO1973_GTA01:
if (pcf50606_onoff_get(pcf50606_global,
PCF50606_REGULATOR_D1REG) &&
@@ -37,21 +46,33 @@ static ssize_t bt_read(struct device *dev, struct device_attribute *attr,
PCF50606_REGULATOR_D1REG) == 3100)
goto out_1;
break;
+#endif /* CONFIG_MACH_NEO1973_GTA01 */
+
+#ifdef CONFIG_MACH_NEO1973_GTA02
case MACH_TYPE_NEO1973_GTA02:
if (s3c2410_gpio_getpin(GTA02_GPIO_BT_EN))
goto out_1;
break;
+#endif /* CONFIG_MACH_NEO1973_GTA02 */
+
}
} else if (!strcmp(attr->attr.name, "reset")) {
switch (machine_arch_type) {
+
+#ifdef CONFIG_MACH_NEO1973_GTA01
case MACH_TYPE_NEO1973_GTA01:
if (s3c2410_gpio_getpin(GTA01_GPIO_BT_EN) == 0)
goto out_1;
break;
+#endif /* CONFIG_MACH_NEO1973_GTA01 */
+
+#ifdef CONFIG_MACH_NEO1973_GTA02
case MACH_TYPE_NEO1973_GTA02:
if (s3c2410_gpio_getpin(GTA02_GPIO_BT_EN) == 0)
goto out_1;
break;
+#endif /* CONFIG_MACH_NEO1973_GTA02 */
+
}
}
@@ -64,9 +85,12 @@ static ssize_t bt_write(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
unsigned long on = simple_strtoul(buf, NULL, 10);
+ unsigned int vol;
if (!strcmp(attr->attr.name, "power_on")) {
switch (machine_arch_type) {
+
+#ifdef CONFIG_MACH_NEO1973_GTA01
case MACH_TYPE_NEO1973_GTA01:
/* if we are powering up, assert reset, then power,
* then release reset */
@@ -80,22 +104,39 @@ static ssize_t bt_write(struct device *dev, struct device_attribute *attr,
PCF50606_REGULATOR_D1REG, on);
s3c2410_gpio_setpin(GTA01_GPIO_BT_EN, on);
break;
+#endif /* CONFIG_MACH_NEO1973_GTA01 */
+
+#ifdef CONFIG_MACH_NEO1973_GTA02
case MACH_TYPE_NEO1973_GTA02:
+ s3c2410_gpio_setpin(GTA02_GPIO_BT_EN, on ? 0 : 1);
if (on)
- s3c2410_gpio_setpin(GTA02_GPIO_BT_EN, 0);
- else
- s3c2410_gpio_setpin(GTA02_GPIO_BT_EN, 1);
+ pcf50633_voltage_set(pcf50633_global,
+ PCF50633_REGULATOR_LDO4, 3200);
+ pcf50633_onoff_set(pcf50633_global,
+ PCF50633_REGULATOR_LDO4, on);
+ vol = pcf50633_voltage_get(pcf50633_global,
+ PCF50633_REGULATOR_LDO4);
+ dev_info(dev, "GTA02 Set PCF50633 LDO4 = %d\n", vol);
break;
+#endif /* CONFIG_MACH_NEO1973_GTA02 */
+
}
} else if (!strcmp(attr->attr.name, "reset")) {
/* reset is low-active, so we need to invert */
switch (machine_arch_type) {
+
+#ifdef CONFIG_MACH_NEO1973_GTA01
case MACH_TYPE_NEO1973_GTA01:
s3c2410_gpio_setpin(GTA01_GPIO_BT_EN, on ? 0 : 1);
break;
+#endif /* CONFIG_MACH_NEO1973_GTA01 */
+
+#ifdef CONFIG_MACH_NEO1973_GTA02
case MACH_TYPE_NEO1973_GTA02:
s3c2410_gpio_setpin(GTA02_GPIO_BT_EN, on ? 0 : 1);
break;
+#endif /* CONFIG_MACH_NEO1973_GTA02 */
+
}
}
@@ -143,18 +184,30 @@ static int __init gta01_bt_probe(struct platform_device *pdev)
dev_info(&pdev->dev, DRVMSG ": starting\n");
switch (machine_arch_type) {
+
+#ifdef CONFIG_MACH_NEO1973_GTA01
case MACH_TYPE_NEO1973_GTA01:
/* we make sure that the voltage is off */
pcf50606_onoff_set(pcf50606_global,
PCF50606_REGULATOR_D1REG, 0);
+ /* we pull reset to low to make sure that the chip doesn't
+ * drain power through the reset line */
+ s3c2410_gpio_setpin(GTA01_GPIO_BT_EN, 0);
break;
+#endif /* CONFIG_MACH_NEO1973_GTA01 */
+
+#ifdef CONFIG_MACH_NEO1973_GTA02
case MACH_TYPE_NEO1973_GTA02:
- /* FIXME: implementation */
+ /* we make sure that the voltage is off */
+ pcf50633_onoff_set(pcf50633_global,
+ PCF50633_REGULATOR_LDO4, 0);
+ /* we pull reset to low to make sure that the chip doesn't
+ * drain power through the reset line */
+ s3c2410_gpio_setpin(GTA02_GPIO_BT_EN, 0);
break;
+#endif /* CONFIG_MACH_NEO1973_GTA02 */
+
}
- /* we pull reset to low to make sure that the chip doesn't
- * drain power through the reset line */
- s3c2410_gpio_setpin(GTA01_GPIO_BT_EN, 0);
return sysfs_create_group(&pdev->dev.kobj, &gta01_bt_attr_group);
}
diff --git a/include/linux/pcf50633.h b/include/linux/pcf50633.h
index bf50fe4..b6a67ee 100644
--- a/include/linux/pcf50633.h
+++ b/include/linux/pcf50633.h
@@ -46,6 +46,7 @@ pcf50633_voltage_set(struct pcf50633_data *pcf,
extern unsigned int
pcf50633_voltage_get(struct pcf50633_data *pcf,
enum pcf50633_regulator_id reg);
+
extern int
pcf50633_onoff_get(struct pcf50633_data *pcf,
enum pcf50633_regulator_id reg);
--
1.5.6.3

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,60 @@
From 18dc67c2500cc825b8f726e90aa1ce4b765f28da Mon Sep 17 00:00:00 2001
From: mokopatches <mokopatches@openmoko.org>
Date: Wed, 16 Jul 2008 14:46:57 +0100
Subject: [PATCH] config-nr-tty-devices.patch
---
drivers/char/Kconfig | 12 ++++++++++++
include/linux/vt.h | 11 +++++++++++
2 files changed, 23 insertions(+), 0 deletions(-)
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index 2d854bb..04afc16 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -58,6 +58,18 @@ config VT_CONSOLE
If unsure, say Y.
+config NR_TTY_DEVICES
+ int "Maximum tty device number"
+ depends on VT
+ default 63
+ ---help---
+ This is the highest numbered device created in /dev. You will actually have
+ NR_TTY_DEVICES+1 devices in /dev. The default is 63, which will result in
+ 64 /dev entries. The lowest number you can set is 11, anything below that,
+ and it will default to 11. 63 is also the upper limit so we don't overrun
+ the serial consoles.
+
+
config HW_CONSOLE
bool
depends on VT && !S390 && !UML
diff --git a/include/linux/vt.h b/include/linux/vt.h
index 02c1c02..2ba4d21 100644
--- a/include/linux/vt.h
+++ b/include/linux/vt.h
@@ -18,8 +18,19 @@ extern int unregister_vt_notifier(struct notifier_block *nb);
* resizing).
*/
#define MIN_NR_CONSOLES 1 /* must be at least 1 */
+#if (CONFIG_NR_TTY_DEVICES < 4)
+/* Lower Limit */
+#define MAX_NR_CONSOLES 4 /* serial lines start at 64 */
+#define MAX_NR_USER_CONSOLES 4 /* must be root to allocate above this */
+#elif (CONFIG_NR_TTY_DEVICES > 63)
+/* Upper Limit */
#define MAX_NR_CONSOLES 63 /* serial lines start at 64 */
#define MAX_NR_USER_CONSOLES 63 /* must be root to allocate above this */
+#else
+/* They chose a sensible number */
+#define MAX_NR_CONSOLES CONFIG_NR_TTY_DEVICES
+#define MAX_NR_USER_CONSOLES CONFIG_NR_TTY_DEVICES
+#endif
/* Note: the ioctl VT_GETSTATE does not work for
consoles 16 and higher (since it returns a short) */
--
1.5.6.3

View file

@ -0,0 +1,28 @@
From 4d5727829b4589a1e2c209ea562a057e758ec556 Mon Sep 17 00:00:00 2001
From: mokopatches <mokopatches@openmoko.org>
Date: Wed, 16 Jul 2008 14:46:57 +0100
Subject: [PATCH] pm-debug_less_verbose.patch
---
drivers/base/power/main.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c
index 45cc3d9..524f1a2 100644
--- a/drivers/base/power/main.c
+++ b/drivers/base/power/main.c
@@ -64,9 +64,9 @@ int device_pm_add(struct device *dev)
{
int error;
- pr_debug("PM: Adding info for %s:%s\n",
+ /* pr_debug("PM: Adding info for %s:%s\n",
dev->bus ? dev->bus->name : "No Bus",
- kobject_name(&dev->kobj));
+ kobject_name(&dev->kobj)); */
mutex_lock(&dpm_list_mtx);
if ((dev->parent && dev->parent->power.sleeping) || all_sleeping) {
if (dev->parent->power.sleeping)
--
1.5.6.3

View file

@ -0,0 +1,40 @@
From 1611aca52fd831b0a90a854ef71f07ed341bd987 Mon Sep 17 00:00:00 2001
From: mokopatches <mokopatches@openmoko.org>
Date: Fri, 25 Jul 2008 22:21:03 +0100
Subject: [PATCH] s3c2410_serial-nodebug.patch
---
drivers/serial/s3c2410.c | 8 --------
1 files changed, 0 insertions(+), 8 deletions(-)
diff --git a/drivers/serial/s3c2410.c b/drivers/serial/s3c2410.c
index 2b6a013..7117110 100644
--- a/drivers/serial/s3c2410.c
+++ b/drivers/serial/s3c2410.c
@@ -708,10 +708,6 @@ static unsigned int s3c24xx_serial_getclk(struct uart_port *port,
int calc_deviation;
for (sptr = res; sptr < resptr; sptr++) {
- printk(KERN_DEBUG
- "found clk %p (%s) quot %d, calc %d\n",
- sptr->clksrc, sptr->clksrc->name,
- sptr->quot, sptr->calc);
calc_deviation = baud - sptr->calc;
if (calc_deviation < 0)
@@ -723,12 +719,8 @@ static unsigned int s3c24xx_serial_getclk(struct uart_port *port,
}
}
- printk(KERN_DEBUG "best %p (deviation %d)\n", best, deviation);
}
- printk(KERN_DEBUG "selected clock %p (%s) quot %d, calc %d\n",
- best->clksrc, best->clksrc->name, best->quot, best->calc);
-
/* store results to pass back */
*clksrc = best->clksrc;
--
1.5.6.3

View file

@ -0,0 +1,37 @@
From 95bdfec0f2515b7f1cd8dd959e49e950a814868b Mon Sep 17 00:00:00 2001
From: mokopatches <mokopatches@openmoko.org>
Date: Fri, 25 Jul 2008 22:21:22 +0100
Subject: [PATCH] input-nots-mousedev.patch
This patch disables the reporting of touchscreen-like devices via
/dev/input/mice. In the Neo1973 (much like other handheld devices),
we need this to distinguish between the touchscreen (which uses tslib)
and optional additional usb/bluetooth mice that might be attached.
Signed-off-by: Harald Welte <laforge@openmoko.org>
---
drivers/input/mousedev.c | 2 ++
1 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/drivers/input/mousedev.c b/drivers/input/mousedev.c
index b989748..685917e 100644
--- a/drivers/input/mousedev.c
+++ b/drivers/input/mousedev.c
@@ -1009,6 +1009,7 @@ static const struct input_device_id mousedev_ids[] = {
.evbit = { BIT_MASK(EV_KEY) | BIT_MASK(EV_REL) },
.relbit = { BIT_MASK(REL_WHEEL) },
}, /* A separate scrollwheel */
+#if 0
{
.flags = INPUT_DEVICE_ID_MATCH_EVBIT |
INPUT_DEVICE_ID_MATCH_KEYBIT |
@@ -1018,6 +1019,7 @@ static const struct input_device_id mousedev_ids[] = {
.absbit = { BIT_MASK(ABS_X) | BIT_MASK(ABS_Y) },
}, /* A tablet like device, at least touch detection,
two absolute axes */
+#endif
{
.flags = INPUT_DEVICE_ID_MATCH_EVBIT |
INPUT_DEVICE_ID_MATCH_KEYBIT |
--
1.5.6.3

View file

@ -0,0 +1,28 @@
From bc0d09dd89a8837b9a4eeb63585caded6b290cf9 Mon Sep 17 00:00:00 2001
From: mokopatches <mokopatches@openmoko.org>
Date: Fri, 25 Jul 2008 22:21:22 +0100
Subject: [PATCH] s3c2440-nand-disable-hwecc.patch
Disable the hardware ECC checking on S3C2440 based platforms (HXD8, SMDK2440,
GTA02) for the time being, since our u-boot doesn't yet support it for 2k page
size NAND
---
drivers/mtd/nand/s3c2410.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/mtd/nand/s3c2410.c b/drivers/mtd/nand/s3c2410.c
index 6e7a5b9..8e1e482 100644
--- a/drivers/mtd/nand/s3c2410.c
+++ b/drivers/mtd/nand/s3c2410.c
@@ -665,7 +665,7 @@ static void s3c2410_nand_init_chip(struct s3c2410_nand_info *info,
nmtd->mtd.owner = THIS_MODULE;
nmtd->set = set;
- if (hardware_ecc) {
+ if (info->cpu_type == TYPE_S3C2410 && hardware_ecc) {
chip->ecc.calculate = s3c2410_nand_calculate_ecc;
chip->ecc.correct = s3c2410_nand_correct_data;
chip->ecc.mode = NAND_ECC_HW;
--
1.5.6.3

View file

@ -0,0 +1,74 @@
From 0ed3724f733b7049d5efea9c44f5e6f0c6beae06 Mon Sep 17 00:00:00 2001
From: mokopatches <mokopatches@openmoko.org>
Date: Fri, 25 Jul 2008 22:21:22 +0100
Subject: [PATCH] qt2410-cs8900.patch
---
drivers/net/Kconfig | 4 ++--
drivers/net/cs89x0.c | 14 +++++++++++++-
2 files changed, 15 insertions(+), 3 deletions(-)
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index f4182cf..8caa04a 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -1248,7 +1248,7 @@ source "drivers/net/ibm_newemac/Kconfig"
config NET_PCI
bool "EISA, VLB, PCI and on board controllers"
- depends on ISA || EISA || PCI
+ depends on ISA || EISA || PCI || MACH_QT2410
help
This is another class of network cards which attach directly to the
bus. If you have one of those, say Y and read the Ethernet-HOWTO,
@@ -1410,7 +1410,7 @@ config FORCEDETH_NAPI
config CS89x0
tristate "CS89x0 support"
- depends on NET_PCI && (ISA || MACH_IXDP2351 || ARCH_IXDP2X01 || ARCH_PNX010X)
+ depends on NET_PCI && (ISA || MACH_IXDP2351 || ARCH_IXDP2X01 || ARCH_PNX010X || MACH_QT2410)
---help---
Support for CS89x0 chipset based Ethernet cards. If you have a
network (Ethernet) card of this type, say Y and read the
diff --git a/drivers/net/cs89x0.c b/drivers/net/cs89x0.c
index fba87ab..d94a790 100644
--- a/drivers/net/cs89x0.c
+++ b/drivers/net/cs89x0.c
@@ -194,6 +194,10 @@ static unsigned int cs8900_irq_map[] = {IRQ_IXDP2X01_CS8900, 0, 0, 0};
#define CIRRUS_DEFAULT_IRQ VH_INTC_INT_NUM_CASCADED_INTERRUPT_1 /* Event inputs bank 1 - ID 35/bit 3 */
static unsigned int netcard_portlist[] __used __initdata = {CIRRUS_DEFAULT_BASE, 0};
static unsigned int cs8900_irq_map[] = {CIRRUS_DEFAULT_IRQ, 0, 0, 0};
+#elif defined(CONFIG_MACH_QT2410)
+#include <asm/arch/irqs.h>
+static unsigned int netcard_portlist [] __initdata = { 0xe0000300, 0 };
+static unsigned int cs8900_irq_map[] = { IRQ_EINT9, 0, 0, 0 };
#else
static unsigned int netcard_portlist[] __used __initdata =
{ 0x300, 0x320, 0x340, 0x360, 0x200, 0x220, 0x240, 0x260, 0x280, 0x2a0, 0x2c0, 0x2e0, 0};
@@ -829,6 +833,14 @@ cs89x0_probe1(struct net_device *dev, int ioaddr, int modular)
printk(" IRQ %d", dev->irq);
+ dev->dev_addr[0] = 0x00;
+ dev->dev_addr[1] = 0x00;
+ dev->dev_addr[2] = 0xc0;
+ dev->dev_addr[3] = 0xff;
+ dev->dev_addr[4] = 0xee;
+ dev->dev_addr[5] = 0x08;
+ set_mac_address(dev, dev->dev_addr);
+
#if ALLOW_DMA
if (lp->use_dma) {
get_dma_channel(dev);
@@ -1304,7 +1316,7 @@ net_open(struct net_device *dev)
else
#endif
{
-#if !defined(CONFIG_MACH_IXDP2351) && !defined(CONFIG_ARCH_IXDP2X01) && !defined(CONFIG_ARCH_PNX010X)
+#if !defined(CONFIG_MACH_IXDP2351) && !defined(CONFIG_ARCH_IXDP2X01) && !defined(CONFIG_ARCH_PNX010X) && !defined(CONFIG_MACH_QT2410)
if (((1 << dev->irq) & lp->irq_map) == 0) {
printk(KERN_ERR "%s: IRQ %d is not in our map of allowable IRQs, which is %x\n",
dev->name, dev->irq, lp->irq_map);
--
1.5.6.3

View file

@ -0,0 +1,311 @@
From a63a227ece28df06d4c8f04eec51c7649ef28aea Mon Sep 17 00:00:00 2001
From: mokopatches <mokopatches@openmoko.org>
Date: Fri, 25 Jul 2008 22:21:22 +0100
Subject: [PATCH] s3c2410-qt2410-buttons.patch
---
arch/arm/mach-s3c2410/mach-qt2410.c | 18 +++
drivers/input/keyboard/Kconfig | 5 +
drivers/input/keyboard/Makefile | 1 +
drivers/input/keyboard/qt2410kbd.c | 233 +++++++++++++++++++++++++++++++++++
4 files changed, 257 insertions(+), 0 deletions(-)
create mode 100644 drivers/input/keyboard/qt2410kbd.c
diff --git a/arch/arm/mach-s3c2410/mach-qt2410.c b/arch/arm/mach-s3c2410/mach-qt2410.c
index 6f7b56d..daf94cd 100644
--- a/arch/arm/mach-s3c2410/mach-qt2410.c
+++ b/arch/arm/mach-s3c2410/mach-qt2410.c
@@ -321,6 +321,24 @@ static int __init qt2410_tft_setup(char *str)
__setup("tft=", qt2410_tft_setup);
+static struct resource qt2410_button_resources[] = {
+ [0] = {
+ .start = S3C2410_GPF0,
+ .end = S3C2410_GPF0,
+ },
+ [1] = {
+ .start = S3C2410_GPF2,
+ .end = S3C2410_GPF2,
+ },
+};
+
+struct platform_device qt2410_button_dev = {
+ .name ="qt2410-button",
+ .num_resources = ARRAY_SIZE(qt2410_button_resources),
+ .resource = qt2410_button_resources,
+};
+
+
static void __init qt2410_map_io(void)
{
s3c24xx_init_io(qt2410_iodesc, ARRAY_SIZE(qt2410_iodesc));
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
index b8ecca9..bc7aac3 100644
--- a/drivers/input/keyboard/Kconfig
+++ b/drivers/input/keyboard/Kconfig
@@ -334,5 +334,10 @@ config KEYBOARD_NEO1973
To compile this driver as a module, choose M here: the
module will be called neo1973kbd.
+config KEYBOARD_QT2410
+ tristate "QT2410 buttons"
+ depends on MACH_QT2410
+ default y
+
endif
diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile
index b3aa339..63a8972 100644
--- a/drivers/input/keyboard/Makefile
+++ b/drivers/input/keyboard/Makefile
@@ -15,6 +15,7 @@ obj-$(CONFIG_KEYBOARD_NEWTON) += newtonkbd.o
obj-$(CONFIG_KEYBOARD_STOWAWAY) += stowaway.o
obj-$(CONFIG_KEYBOARD_CORGI) += corgikbd.o
obj-$(CONFIG_KEYBOARD_NEO1973) += neo1973kbd.o
+obj-$(CONFIG_KEYBOARD_QT2410) += qt2410kbd.o
obj-$(CONFIG_KEYBOARD_SPITZ) += spitzkbd.o
obj-$(CONFIG_KEYBOARD_TOSA) += tosakbd.o
obj-$(CONFIG_KEYBOARD_HIL) += hil_kbd.o
diff --git a/drivers/input/keyboard/qt2410kbd.c b/drivers/input/keyboard/qt2410kbd.c
new file mode 100644
index 0000000..4d497a3
--- /dev/null
+++ b/drivers/input/keyboard/qt2410kbd.c
@@ -0,0 +1,233 @@
+/*
+ * Keyboard driver for Armzone QT2410
+ *
+ * (C) 2006 by OpenMoko, Inc.
+ * Author: Harald Welte <laforge@openmoko.org>
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/init.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/jiffies.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+
+#include <asm/hardware.h>
+#include <asm/arch/gta01.h>
+
+struct gta01kbd {
+ struct input_dev *input;
+ unsigned int suspended;
+ unsigned long suspend_jiffies;
+};
+
+static irqreturn_t gta01kbd_interrupt(int irq, void *dev_id)
+{
+ struct gta01kbd *gta01kbd_data = dev_id;
+
+ /* FIXME: use GPIO from platform_dev resources */
+ if (s3c2410_gpio_getpin(S3C2410_GPF0))
+ input_report_key(gta01kbd_data->input, KEY_PHONE, 1);
+ else
+ input_report_key(gta01kbd_data->input, KEY_PHONE, 0);
+
+ input_sync(gta01kbd_data->input);
+
+ return IRQ_HANDLED;
+}
+
+
+#ifdef CONFIG_PM
+static int gta01kbd_suspend(struct platform_device *dev, pm_message_t state)
+{
+ struct gta01kbd *gta01kbd = platform_get_drvdata(dev);
+
+ gta01kbd->suspended = 1;
+
+ return 0;
+}
+
+static int gta01kbd_resume(struct platform_device *dev)
+{
+ struct gta01kbd *gta01kbd = platform_get_drvdata(dev);
+
+ gta01kbd->suspended = 0;
+
+ return 0;
+}
+#else
+#define gta01kbd_suspend NULL
+#define gta01kbd_resume NULL
+#endif
+
+static int gta01kbd_probe(struct platform_device *pdev)
+{
+ struct gta01kbd *gta01kbd;
+ struct input_dev *input_dev;
+ int irq_911;
+ int rc = 0;
+
+ gta01kbd = kzalloc(sizeof(struct gta01kbd), GFP_KERNEL);
+ if (!gta01kbd) {
+ rc = -ENOMEM;
+ goto bail;
+ }
+ input_dev = input_allocate_device();
+ if (!gta01kbd || !input_dev) {
+ rc = -ENOMEM;
+ goto bail_free;
+ }
+
+ if (pdev->resource[0].flags != 0) {\
+ rc = -EINVAL;
+ goto bail_free_dev;
+ }
+
+ irq_911 = s3c2410_gpio_getirq(pdev->resource[0].start);
+ if (irq_911 < 0) {
+ rc = -EINVAL;
+ goto bail_free_dev;
+ }
+
+ platform_set_drvdata(pdev, gta01kbd);
+
+ gta01kbd->input = input_dev;
+
+#if 0
+ spin_lock_init(&gta01kbd->lock);
+ /* Init Keyboard rescan timer */
+ init_timer(&corgikbd->timer);
+ corgikbd->timer.function = corgikbd_timer_callback;
+ corgikbd->timer.data = (unsigned long) corgikbd;
+
+ /* Init Hinge Timer */
+ init_timer(&corgikbd->htimer);
+ corgikbd->htimer.function = corgikbd_hinge_timer;
+ corgikbd->htimer.data = (unsigned long) corgikbd;
+
+ corgikbd->suspend_jiffies=jiffies;
+
+ memcpy(corgikbd->keycode, corgikbd_keycode, sizeof(corgikbd->keycode));
+#endif
+
+ input_dev->name = "QT2410 Buttons";
+ input_dev->phys = "qt2410kbd/input0";
+ input_dev->id.bustype = BUS_HOST;
+ input_dev->id.vendor = 0x0001;
+ input_dev->id.product = 0x0001;
+ input_dev->id.version = 0x0100;
+ input_dev->cdev.dev = &pdev->dev;
+ input_dev->private = gta01kbd;
+
+ input_dev->evbit[0] = BIT(EV_KEY);
+#if 0
+ input_dev->keycode = gta01kbd->keycode;
+ input_dev->keycodesize = sizeof(unsigned char);
+ input_dev->keycodemax = ARRAY_SIZE(corgikbd_keycode);
+
+ for (i = 0; i < ARRAY_SIZE(corgikbd_keycode); i++)
+ set_bit(corgikbd->keycode[i], input_dev->keybit);
+ clear_bit(0, input_dev->keybit);
+ set_bit(SW_LID, input_dev->swbit);
+ set_bit(SW_TABLET_MODE, input_dev->swbit);
+ set_bit(SW_HEADPHONE_INSERT, input_dev->swbit);
+#endif
+
+ rc = input_register_device(gta01kbd->input);
+ if (rc)
+ goto bail_free_dev;
+
+ s3c2410_gpio_cfgpin(S3C2410_GPF0, S3C2410_GPF0_EINT0);
+ if (request_irq(irq_911, gta01kbd_interrupt,
+ IRQF_DISABLED | IRQF_TRIGGER_RISING |
+ IRQF_TRIGGER_FALLING, "qt2410kbd_eint0", gta01kbd))
+ printk(KERN_WARNING "gta01kbd: Can't get IRQ\n");
+ enable_irq_wake(irq_911);
+
+ /* FIXME: headphone insert */
+
+#if 0
+ mod_timer(&corgikbd->htimer, jiffies + msecs_to_jiffies(HINGE_SCAN_INTERVAL));
+
+ /* Setup sense interrupts - RisingEdge Detect, sense lines as inputs */
+ for (i = 0; i < CORGI_KEY_SENSE_NUM; i++) {
+ pxa_gpio_mode(CORGI_GPIO_KEY_SENSE(i) | GPIO_IN);
+ if (request_irq(CORGI_IRQ_GPIO_KEY_SENSE(i), corgikbd_interrupt,
+ SA_INTERRUPT | SA_TRIGGER_RISING,
+ "corgikbd", corgikbd))
+ printk(KERN_WARNING "corgikbd: Can't get IRQ: %d!\n", i);
+ }
+
+ /* Set Strobe lines as outputs - set high */
+ for (i = 0; i < CORGI_KEY_STROBE_NUM; i++)
+ pxa_gpio_mode(CORGI_GPIO_KEY_STROBE(i) | GPIO_OUT | GPIO_DFLT_HIGH);
+
+ /* Setup the headphone jack as an input */
+ pxa_gpio_mode(CORGI_GPIO_AK_INT | GPIO_IN);
+#endif
+
+ return 0;
+
+bail_free_dev:
+ input_free_device(input_dev);
+bail_free:
+ kfree(gta01kbd);
+bail:
+ return rc;
+}
+
+static int gta01kbd_remove(struct platform_device *pdev)
+{
+ struct gta01kbd *gta01kbd = platform_get_drvdata(pdev);
+
+ free_irq(s3c2410_gpio_getirq(pdev->resource[0].start), gta01kbd);
+#if 0
+ int i;
+
+ for (i = 0; i < CORGI_KEY_SENSE_NUM; i++)
+ free_irq(CORGI_IRQ_GPIO_KEY_SENSE(i), corgikbd);
+
+ del_timer_sync(&corgikbd->htimer);
+ del_timer_sync(&corgikbd->timer);
+#endif
+ input_unregister_device(gta01kbd->input);
+
+ kfree(gta01kbd);
+
+ return 0;
+}
+
+static struct platform_driver gta01kbd_driver = {
+ .probe = gta01kbd_probe,
+ .remove = gta01kbd_remove,
+ .suspend = gta01kbd_suspend,
+ .resume = gta01kbd_resume,
+ .driver = {
+ .name = "qt2410-button",
+ },
+};
+
+static int __devinit gta01kbd_init(void)
+{
+ return platform_driver_register(&gta01kbd_driver);
+}
+
+static void __exit gta01kbd_exit(void)
+{
+ platform_driver_unregister(&gta01kbd_driver);
+}
+
+module_init(gta01kbd_init);
+module_exit(gta01kbd_exit);
+
+MODULE_AUTHOR("Harald Welte <laforge@openmoko.org>");
+MODULE_DESCRIPTION("Armzone QT2410 Buttons Driver");
+MODULE_LICENSE("GPL");
--
1.5.6.3

View file

@ -0,0 +1,27 @@
From 10042752e49358e1ef5ccfbb4e1c27875f3f43c5 Mon Sep 17 00:00:00 2001
From: mokopatches <mokopatches@openmoko.org>
Date: Fri, 25 Jul 2008 22:21:22 +0100
Subject: [PATCH] fail-unless-uimage.patch
Fail the build noisily if "mkimage" can't be found, e.g., if we forgot to add
the u-boot directory to PATH.
---
scripts/mkuboot.sh | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/scripts/mkuboot.sh b/scripts/mkuboot.sh
index 2e3d3cd..446739c 100755
--- a/scripts/mkuboot.sh
+++ b/scripts/mkuboot.sh
@@ -11,7 +11,7 @@ if [ -z "${MKIMAGE}" ]; then
if [ -z "${MKIMAGE}" ]; then
# Doesn't exist
echo '"mkimage" command not found - U-Boot images will not be built' >&2
- exit 0;
+ exit 1;
fi
fi
--
1.5.6.3

View file

@ -0,0 +1,587 @@
From 6a2c7de90f47b7eb74f3cb2d181f950ece22b3fb Mon Sep 17 00:00:00 2001
From: mokopatches <mokopatches@openmoko.org>
Date: Fri, 25 Jul 2008 22:21:22 +0100
Subject: [PATCH] introduce-fiq-basis.patch
Adds a C-based FIQ ISR which is very convenient (and unusual --
normally you have to do FIQ ISR in assembler only).
Based on my article:
http://warmcat.com/_wp/2007/09/17/at91rm9200-fiq-faq-and-simple-example-code-patch/
Implemented as a platform device and driver.
Suspend / resume is tested and works.
Signed-off-by: Andy Green <andy@warmcat.com>
---
arch/arm/mach-s3c2440/Kconfig | 7 +
arch/arm/mach-s3c2440/Makefile | 1 +
arch/arm/mach-s3c2440/fiq_c_isr.c | 250 ++++++++++++++++++++++++++
arch/arm/mach-s3c2440/fiq_c_isr.h | 64 +++++++
arch/arm/mach-s3c2440/mach-gta02.c | 22 +++
arch/arm/plat-s3c24xx/irq.c | 32 +++-
include/asm-arm/arch-s3c2410/fiq_ipc_gta02.h | 28 +++
include/asm-arm/plat-s3c24xx/irq.h | 20 ++
8 files changed, 422 insertions(+), 2 deletions(-)
create mode 100644 arch/arm/mach-s3c2440/fiq_c_isr.c
create mode 100644 arch/arm/mach-s3c2440/fiq_c_isr.h
create mode 100644 include/asm-arm/arch-s3c2410/fiq_ipc_gta02.h
diff --git a/arch/arm/mach-s3c2440/Kconfig b/arch/arm/mach-s3c2440/Kconfig
index 6b317d1..3015aaf 100644
--- a/arch/arm/mach-s3c2440/Kconfig
+++ b/arch/arm/mach-s3c2440/Kconfig
@@ -22,6 +22,13 @@ config S3C2440_DMA
help
Support for S3C2440 specific DMA code5A
+config S3C2440_C_FIQ
+ bool "FIQ ISR support in C"
+ depends on ARCH_S3C2410
+ select FIQ
+ help
+ Support for S3C2440 FIQ support in C -- see
+ ./arch/arm/macs3c2440/fiq_c_isr.c
menu "S3C2440 Machines"
diff --git a/arch/arm/mach-s3c2440/Makefile b/arch/arm/mach-s3c2440/Makefile
index 1a4defd..4932232 100644
--- a/arch/arm/mach-s3c2440/Makefile
+++ b/arch/arm/mach-s3c2440/Makefile
@@ -13,6 +13,7 @@ obj-$(CONFIG_CPU_S3C2440) += s3c2440.o dsc.o
obj-$(CONFIG_CPU_S3C2440) += irq.o
obj-$(CONFIG_CPU_S3C2440) += clock.o
obj-$(CONFIG_S3C2440_DMA) += dma.o
+obj-$(CONFIG_S3C2440_C_FIQ) += fiq_c_isr.o
# Machine support
diff --git a/arch/arm/mach-s3c2440/fiq_c_isr.c b/arch/arm/mach-s3c2440/fiq_c_isr.c
new file mode 100644
index 0000000..12f4527
--- /dev/null
+++ b/arch/arm/mach-s3c2440/fiq_c_isr.c
@@ -0,0 +1,250 @@
+/*
+ * Copyright 2007 Andy Green <andy@warmcat.com>
+ * S3C modfifications
+ * Copyright 2008 Andy Green <andy@openmoko.com>
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <asm/hardware.h>
+#include <asm/fiq.h>
+#include "fiq_c_isr.h"
+#include <linux/sysfs.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+
+#include <asm/io.h>
+
+#include <asm/plat-s3c24xx/cpu.h>
+#include <asm/plat-s3c24xx/irq.h>
+
+/*
+ * Major Caveats for using FIQ
+ * ---------------------------
+ *
+ * 1) it CANNOT touch any vmalloc()'d memory, only memory
+ * that was kmalloc()'d. Static allocations in the monolithic kernel
+ * are kmalloc()'d so they are okay. You can touch memory-mapped IO, but
+ * the pointer for it has to have been stored in kmalloc'd memory. The
+ * reason for this is simple: every now and then Linux turns off interrupts
+ * and reorders the paging tables. If a FIQ happens during this time, the
+ * virtual memory space can be partly or entirely disordered or missing.
+ *
+ * 2) Because vmalloc() is used when a module is inserted, THIS FIQ
+ * ISR HAS TO BE IN THE MONOLITHIC KERNEL, not a module. But the way
+ * it is set up, you can all to enable and disable it from your module
+ * and intercommunicate with it through struct fiq_ipc
+ * fiq_ipc which you can define in
+ * asm/archfiq_ipc_type.h. The reason is the same as above, a
+ * FIQ could happen while even the ISR is not present in virtual memory
+ * space due to pagetables being changed at the time.
+ *
+ * 3) You can't call any Linux API code except simple macros
+ * - understand that FIQ can come in at any time, no matter what
+ * state of undress the kernel may privately be in, thinking it
+ * locked the door by turning off interrupts... FIQ is an
+ * unstoppable monster force (which is its value)
+ * - they are not vmalloc()'d memory safe
+ * - they might do crazy stuff like sleep: FIQ pisses fire and
+ * is not interested in 'sleep' that the weak seem to need
+ * - calling APIs from FIQ can re-enter un-renterable things
+ * - summary: you cannot interoperate with linux APIs directly in the FIQ ISR
+ *
+ * If you follow these rules, it is fantastic, an extremely powerful, solid,
+ * genuine hard realtime feature.
+ *
+ */
+
+/* more than enough to cover our jump instruction to the isr */
+#define SIZEOF_FIQ_JUMP 8
+/* more than enough to cover s3c2440_fiq_isr() in 4K blocks */
+#define SIZEOF_FIQ_ISR 0x2000
+/* increase the size of the stack that is active during FIQ as needed */
+static u8 u8aFiqStack[4096];
+
+/* only one FIQ ISR possible, okay to do these here */
+u32 _fiq_ack_mask; /* used by isr exit define */
+unsigned long _fiq_count_fiqs; /* used by isr exit define */
+static int _fiq_irq; /* private ; irq index we were started with, or 0 */
+
+/* this function must live in the monolithic kernel somewhere! A module is
+ * NOT good enough!
+ */
+extern void __attribute__ ((naked)) s3c2440_fiq_isr(void);
+
+/* this is copied into the hard FIQ vector during init */
+
+static void __attribute__ ((naked)) s3c2440_FIQ_Branch(void)
+{
+ asm __volatile__ (
+ "mov pc, r8 ; "
+ );
+}
+
+/* sysfs */
+
+static ssize_t show_count(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ return sprintf(buf, "%ld\n", _fiq_count_fiqs);
+}
+
+static DEVICE_ATTR(count, 0444, show_count, NULL);
+
+static struct attribute *s3c2440_fiq_sysfs_entries[] = {
+ &dev_attr_count.attr,
+ NULL
+};
+
+static struct attribute_group s3c2440_fiq_attr_group = {
+ .name = "fiq",
+ .attrs = s3c2440_fiq_sysfs_entries,
+};
+
+/*
+ * call this from your kernel module to set up the FIQ ISR to service FIQs,
+ * You need to have configured your FIQ input pin before anything will happen
+ *
+ * call it with, eg, IRQ_TIMER3 from asm-arm/arch-s3c2410/irqs.h
+ *
+ * you still need to clear the source interrupt in S3C2410_INTMSK to get
+ * anything good happening
+ */
+static void fiq_init_irq_source(int irq_index_fiq)
+{
+ if (!irq_index_fiq) /* no interrupt */
+ return;
+
+ printk(KERN_INFO"Enabling FIQ using int idx %d\n",
+ irq_index_fiq - S3C2410_CPUIRQ_OFFSET);
+ local_fiq_disable();
+
+ _fiq_irq = irq_index_fiq;
+ _fiq_ack_mask = 1 << (irq_index_fiq - S3C2410_CPUIRQ_OFFSET);
+
+ /* let our selected interrupt be a magic FIQ interrupt */
+ __raw_writel(_fiq_ack_mask, S3C2410_INTMOD);
+
+ /* it's ready to go as soon as we unmask the source in S3C2410_INTMSK */
+ local_fiq_enable();
+}
+
+
+/* call this from your kernel module to disable generation of FIQ actions */
+static void fiq_disable_irq_source(void)
+{
+ /* nothing makes FIQ any more */
+ __raw_writel(0, S3C2410_INTMOD);
+ local_fiq_disable();
+ _fiq_irq = 0; /* no active source interrupt now either */
+}
+
+/* this starts FIQ timer events... they continue until the FIQ ISR sees that
+ * its work is done and it turns off the timer. After setting up the fiq_ipc
+ * struct with new work, you call this to start FIQ timer actions up again.
+ * Only the FIQ ISR decides when it is done and controls turning off the
+ * timer events.
+ */
+void fiq_kick(void)
+{
+ unsigned long flags;
+
+ /* we have to take care about FIQ because this modification is
+ * non-atomic, FIQ could come in after the read and before the
+ * writeback and its changes to the register would be lost
+ * (platform INTMSK mod code is taken care of already)
+ */
+ local_save_flags(flags);
+ local_fiq_disable();
+ __raw_writel(__raw_readl(S3C2410_INTMSK) &
+ ~(1 << (_fiq_irq - S3C2410_CPUIRQ_OFFSET)),
+ S3C2410_INTMSK);
+ local_irq_restore(flags);
+}
+EXPORT_SYMBOL_GPL(fiq_kick);
+
+
+
+static int __init sc32440_fiq_probe(struct platform_device *pdev)
+{
+ struct resource *r = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+
+ if (!r)
+ return -EIO;
+ /* configure for the interrupt we are meant to use */
+ fiq_init_irq_source(r->start);
+
+ return sysfs_create_group(&pdev->dev.kobj, &s3c2440_fiq_attr_group);
+}
+
+static int sc32440_fiq_remove(struct platform_device *pdev)
+{
+ fiq_disable_irq_source();
+ sysfs_remove_group(&pdev->dev.kobj, &s3c2440_fiq_attr_group);
+ return 0;
+}
+
+static void fiq_set_vector_and_regs(void)
+{
+ struct pt_regs regs;
+
+ /* prep the special FIQ mode regs */
+ memset(&regs, 0, sizeof(regs));
+ regs.ARM_r8 = (unsigned long)s3c2440_fiq_isr;
+ regs.ARM_sp = (unsigned long)u8aFiqStack + sizeof(u8aFiqStack) - 4;
+ /* set up the special FIQ-mode-only registers from our regs */
+ set_fiq_regs(&regs);
+ /* copy our jump to the real ISR into the hard vector address */
+ set_fiq_handler(s3c2440_FIQ_Branch, SIZEOF_FIQ_JUMP);
+}
+
+#ifdef CONFIG_PM
+static int sc32440_fiq_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ /* nothing makes FIQ any more */
+ __raw_writel(0, S3C2410_INTMOD);
+ local_fiq_disable();
+
+ return 0;
+}
+
+static int sc32440_fiq_resume(struct platform_device *pdev)
+{
+ fiq_set_vector_and_regs();
+ fiq_init_irq_source(_fiq_irq);
+ return 0;
+}
+#else
+#define sc32440_fiq_suspend NULL
+#define sc32440_fiq_resume NULL
+#endif
+
+static struct platform_driver sc32440_fiq_driver = {
+ .driver = {
+ .name = "sc32440_fiq",
+ .owner = THIS_MODULE,
+ },
+
+ .probe = sc32440_fiq_probe,
+ .remove = __devexit_p(sc32440_fiq_remove),
+ .suspend = sc32440_fiq_suspend,
+ .resume = sc32440_fiq_resume,
+};
+
+static int __init sc32440_fiq_init(void)
+{
+ fiq_set_vector_and_regs();
+
+ return platform_driver_register(&sc32440_fiq_driver);
+}
+
+static void __exit sc32440_fiq_exit(void)
+{
+ fiq_disable_irq_source();
+}
+
+MODULE_AUTHOR("Andy Green <andy@openmoko.com>");
+MODULE_LICENSE("GPL");
+
+module_init(sc32440_fiq_init);
+module_exit(sc32440_fiq_exit);
diff --git a/arch/arm/mach-s3c2440/fiq_c_isr.h b/arch/arm/mach-s3c2440/fiq_c_isr.h
new file mode 100644
index 0000000..f08740e
--- /dev/null
+++ b/arch/arm/mach-s3c2440/fiq_c_isr.h
@@ -0,0 +1,64 @@
+#ifndef _LINUX_FIQ_C_ISR_H
+#define _LINUX_FIQ_C_ISR_H
+
+#include <asm/arch-s3c2410/regs-irq.h>
+
+extern unsigned long _fiq_count_fiqs;
+extern u32 _fiq_ack_mask;
+
+/* This CANNOT be implemented in a module -- it has to be used in code
+ * included in the monolithic kernel
+ */
+
+#define FIQ_HANDLER_START() \
+void __attribute__ ((naked)) s3c2440_fiq_isr(void) \
+{\
+ /*\
+ * you can declare local vars here, take care to set the frame size\
+ * below accordingly if there are more than a few dozen bytes of them\
+ */\
+
+/* stick your locals here :-)
+ * Do NOT initialize them here! define them and initialize them after
+ * FIQ_HANDLER_ENTRY() is done.
+ */
+
+#define FIQ_HANDLER_ENTRY(LOCALS, FRAME) \
+ const int _FIQ_FRAME_SIZE = FRAME; \
+ /* entry takes care to store registers we will be treading on here */\
+ asm __volatile__ (\
+ "mov ip, sp ;"\
+ /* stash FIQ and r0-r8 normal regs */\
+ "stmdb sp!, {r0-r12, lr};"\
+ /* allow SP to get some space */\
+ "sub sp, sp, %1 ;"\
+ /* !! THIS SETS THE FRAME, adjust to > sizeof locals */\
+ "sub fp, sp, %0 ;"\
+ :\
+ : "rI" (LOCALS), "rI" (FRAME)\
+ :"r9"\
+ );
+
+/* stick your ISR code here and then end with... */
+
+#define FIQ_HANDLER_END() \
+ _fiq_count_fiqs++;\
+ __raw_writel(_fiq_ack_mask, S3C2410_SRCPND);\
+\
+ /* exit back to normal mode restoring everything */\
+ asm __volatile__ (\
+ /* pop our allocation */\
+ "add sp, sp, %0 ;"\
+ /* return FIQ regs back to pristine state\
+ * and get normal regs back\
+ */\
+ "ldmia sp!, {r0-r12, lr};"\
+\
+ /* return */\
+ "subs pc, lr, #4;"\
+ : \
+ : "rI" (_FIQ_FRAME_SIZE) \
+ );\
+}
+
+#endif /* _LINUX_FIQ_C_ISR_H */
diff --git a/arch/arm/mach-s3c2440/mach-gta02.c b/arch/arm/mach-s3c2440/mach-gta02.c
index 46acede..0bdd0e0 100644
--- a/arch/arm/mach-s3c2440/mach-gta02.c
+++ b/arch/arm/mach-s3c2440/mach-gta02.c
@@ -78,9 +78,31 @@
#include <linux/glamofb.h>
+#include <asm/arch/fiq_ipc_gta02.h>
+#include "fiq_c_isr.h"
+
/* arbitrates which sensor IRQ owns the shared SPI bus */
static spinlock_t motion_irq_lock;
+/* define FIQ IPC struct */
+/*
+ * contains stuff FIQ ISR modifies and normal kernel code can see and use
+ * this is defined in <asm/arch/fiq_ipc_gta02.h>, you should customize
+ * the definition in there and include the same definition in your kernel
+ * module that wants to interoperate with your FIQ code.
+ */
+struct fiq_ipc fiq_ipc;
+EXPORT_SYMBOL(fiq_ipc);
+
+/* define FIQ ISR */
+
+FIQ_HANDLER_START()
+/* define your locals here -- no initializers though */
+FIQ_HANDLER_ENTRY(256, 512)
+/* Your ISR here :-) */
+FIQ_HANDLER_END()
+
+
static struct map_desc gta02_iodesc[] __initdata = {
{
.virtual = 0xe0000000,
diff --git a/arch/arm/plat-s3c24xx/irq.c b/arch/arm/plat-s3c24xx/irq.c
index ae2c5d7..9887db1 100644
--- a/arch/arm/plat-s3c24xx/irq.c
+++ b/arch/arm/plat-s3c24xx/irq.c
@@ -133,12 +133,20 @@ static void
s3c_irq_mask(unsigned int irqno)
{
unsigned long mask;
-
+#ifdef CONFIG_S3C2440_C_FIQ
+ unsigned long flags;
+#endif
irqno -= IRQ_EINT0;
-
+#ifdef CONFIG_S3C2440_C_FIQ
+ local_save_flags(flags);
+ local_fiq_disable();
+#endif
mask = __raw_readl(S3C2410_INTMSK);
mask |= 1UL << irqno;
__raw_writel(mask, S3C2410_INTMSK);
+#ifdef CONFIG_S3C2440_C_FIQ
+ local_irq_restore(flags);
+#endif
}
static inline void
@@ -155,9 +163,19 @@ s3c_irq_maskack(unsigned int irqno)
{
unsigned long bitval = 1UL << (irqno - IRQ_EINT0);
unsigned long mask;
+#ifdef CONFIG_S3C2440_C_FIQ
+ unsigned long flags;
+#endif
+#ifdef CONFIG_S3C2440_C_FIQ
+ local_save_flags(flags);
+ local_fiq_disable();
+#endif
mask = __raw_readl(S3C2410_INTMSK);
__raw_writel(mask|bitval, S3C2410_INTMSK);
+#ifdef CONFIG_S3C2440_C_FIQ
+ local_irq_restore(flags);
+#endif
__raw_writel(bitval, S3C2410_SRCPND);
__raw_writel(bitval, S3C2410_INTPND);
@@ -168,15 +186,25 @@ static void
s3c_irq_unmask(unsigned int irqno)
{
unsigned long mask;
+#ifdef CONFIG_S3C2440_C_FIQ
+ unsigned long flags;
+#endif
if (irqno != IRQ_TIMER4 && irqno != IRQ_EINT8t23)
irqdbf2("s3c_irq_unmask %d\n", irqno);
irqno -= IRQ_EINT0;
+#ifdef CONFIG_S3C2440_C_FIQ
+ local_save_flags(flags);
+ local_fiq_disable();
+#endif
mask = __raw_readl(S3C2410_INTMSK);
mask &= ~(1UL << irqno);
__raw_writel(mask, S3C2410_INTMSK);
+#ifdef CONFIG_S3C2440_C_FIQ
+ local_irq_restore(flags);
+#endif
}
struct irq_chip s3c_irq_level_chip = {
diff --git a/include/asm-arm/arch-s3c2410/fiq_ipc_gta02.h b/include/asm-arm/arch-s3c2410/fiq_ipc_gta02.h
new file mode 100644
index 0000000..341f2bb
--- /dev/null
+++ b/include/asm-arm/arch-s3c2410/fiq_ipc_gta02.h
@@ -0,0 +1,28 @@
+#ifndef _LINUX_FIQ_IPC_H
+#define _LINUX_FIQ_IPC_H
+
+/*
+ * this defines the struct which is used to communicate between the FIQ
+ * world and the normal linux kernel world. One of these structs is
+ * statically defined for you in the monolithic kernel so the FIQ ISR code
+ * can safely touch it any any time.
+ *
+ * You also want to include this file in your kernel module that wants to
+ * communicate with your FIQ code. Add any kinds of vars that are used by
+ * the FIQ ISR and the module in here.
+ *
+ * To get you started there is just an int that is incremented every FIQ
+ * you can remove this when you are ready to customize, but it is useful
+ * for testing
+ */
+
+struct fiq_ipc {
+ u8 u8a[0]; /* placeholder */
+};
+
+/* actual definition lives in arch/arm/mach-s3c2440/fiq_c_isr.c */
+extern struct fiq_ipc fiq_ipc;
+
+extern void fiq_kick(void); /* provoke a FIQ "immediately" */
+
+#endif /* _LINUX_FIQ_IPC_H */
diff --git a/include/asm-arm/plat-s3c24xx/irq.h b/include/asm-arm/plat-s3c24xx/irq.h
index 45746a9..bf15e1c 100644
--- a/include/asm-arm/plat-s3c24xx/irq.h
+++ b/include/asm-arm/plat-s3c24xx/irq.h
@@ -25,8 +25,15 @@ s3c_irqsub_mask(unsigned int irqno, unsigned int parentbit,
{
unsigned long mask;
unsigned long submask;
+#ifdef CONFIG_S3C2440_C_FIQ
+ unsigned long flags;
+#endif
submask = __raw_readl(S3C2410_INTSUBMSK);
+#ifdef CONFIG_S3C2440_C_FIQ
+ local_save_flags(flags);
+ local_fiq_disable();
+#endif
mask = __raw_readl(S3C2410_INTMSK);
submask |= (1UL << (irqno - IRQ_S3CUART_RX0));
@@ -39,6 +46,9 @@ s3c_irqsub_mask(unsigned int irqno, unsigned int parentbit,
/* write back masks */
__raw_writel(submask, S3C2410_INTSUBMSK);
+#ifdef CONFIG_S3C2440_C_FIQ
+ local_irq_restore(flags);
+#endif
}
@@ -47,8 +57,15 @@ s3c_irqsub_unmask(unsigned int irqno, unsigned int parentbit)
{
unsigned long mask;
unsigned long submask;
+#ifdef CONFIG_S3C2440_C_FIQ
+ unsigned long flags;
+#endif
submask = __raw_readl(S3C2410_INTSUBMSK);
+#ifdef CONFIG_S3C2440_C_FIQ
+ local_save_flags(flags);
+ local_fiq_disable();
+#endif
mask = __raw_readl(S3C2410_INTMSK);
submask &= ~(1UL << (irqno - IRQ_S3CUART_RX0));
@@ -57,6 +74,9 @@ s3c_irqsub_unmask(unsigned int irqno, unsigned int parentbit)
/* write back masks */
__raw_writel(submask, S3C2410_INTSUBMSK);
__raw_writel(mask, S3C2410_INTMSK);
+#ifdef CONFIG_S3C2440_C_FIQ
+ local_irq_restore(flags);
+#endif
}
--
1.5.6.3

View file

@ -0,0 +1,220 @@
From 26fa0c816d5e1b593128477c7e200fafe3caae18 Mon Sep 17 00:00:00 2001
From: mokopatches <mokopatches@openmoko.org>
Date: Fri, 25 Jul 2008 22:21:22 +0100
Subject: [PATCH] introduce-fiq-use-timer3-as-source.patch
This makes the FIQ stuff specific to one of the timers on the
s3c244x and adds the platform stuff for fiq in the gta02 init
Currently one sysfs node is exposed, a count of FIQ events
cat /sys/devices/platform/sc32440_fiq.0/fiq/count
From: Andy Green <andy@openmoko.com>
Signed-off-by: Andy Green <andy@openmoko.com>
---
arch/arm/mach-s3c2440/fiq_c_isr.c | 56 +++++++++++++++++++++----
arch/arm/mach-s3c2440/fiq_c_isr.h | 2 +
arch/arm/mach-s3c2440/mach-gta02.c | 17 ++++++++
include/asm-arm/arch-s3c2410/fiq_ipc_gta02.h | 2 +-
4 files changed, 67 insertions(+), 10 deletions(-)
diff --git a/arch/arm/mach-s3c2440/fiq_c_isr.c b/arch/arm/mach-s3c2440/fiq_c_isr.c
index 12f4527..a71a234 100644
--- a/arch/arm/mach-s3c2440/fiq_c_isr.c
+++ b/arch/arm/mach-s3c2440/fiq_c_isr.c
@@ -18,6 +18,9 @@
#include <asm/plat-s3c24xx/cpu.h>
#include <asm/plat-s3c24xx/irq.h>
+#include <asm/arch/pwm.h>
+#include <asm/plat-s3c/regs-timer.h>
+
/*
* Major Caveats for using FIQ
* ---------------------------
@@ -66,6 +69,10 @@ static u8 u8aFiqStack[4096];
u32 _fiq_ack_mask; /* used by isr exit define */
unsigned long _fiq_count_fiqs; /* used by isr exit define */
static int _fiq_irq; /* private ; irq index we were started with, or 0 */
+struct s3c2410_pwm pwm_timer_fiq;
+int _fiq_timer_index;
+u16 _fiq_timer_divisor;
+
/* this function must live in the monolithic kernel somewhere! A module is
* NOT good enough!
@@ -110,23 +117,45 @@ static struct attribute_group s3c2440_fiq_attr_group = {
* you still need to clear the source interrupt in S3C2410_INTMSK to get
* anything good happening
*/
-static void fiq_init_irq_source(int irq_index_fiq)
+static int fiq_init_irq_source(int irq_index_fiq)
{
+ int rc = 0;
+
if (!irq_index_fiq) /* no interrupt */
- return;
+ goto bail;
- printk(KERN_INFO"Enabling FIQ using int idx %d\n",
- irq_index_fiq - S3C2410_CPUIRQ_OFFSET);
local_fiq_disable();
_fiq_irq = irq_index_fiq;
_fiq_ack_mask = 1 << (irq_index_fiq - S3C2410_CPUIRQ_OFFSET);
+ timer_index = (irq_index_fiq - IRQ_TIMER0);
+
+ /* set up the timer to operate as a pwm device */
+
+ rc = s3c2410_pwm_init(&pwm_timer_fiq);
+ if (rc)
+ goto bail;
+
+ pwm_timer_fiq.timerid = PWM0 + timer_index;
+ pwm_timer_fiq.prescaler = (6 - 1) / 2;
+ pwm_timer_fiq.divider = S3C2410_TCFG1_MUX3_DIV2;
+ /* default rate == ~32us */
+ pwm_timer_fiq.counter = pwm_timer_fiq.comparer =
+ timer_divisor = 64;
+
+ rc = s3c2410_pwm_enable(&pwm_timer_fiq);
+ if (rc)
+ goto bail;
+
+ s3c2410_pwm_start(&pwm_timer_fiq);
/* let our selected interrupt be a magic FIQ interrupt */
__raw_writel(_fiq_ack_mask, S3C2410_INTMOD);
/* it's ready to go as soon as we unmask the source in S3C2410_INTMSK */
local_fiq_enable();
+bail:
+ return rc;
}
@@ -139,15 +168,13 @@ static void fiq_disable_irq_source(void)
_fiq_irq = 0; /* no active source interrupt now either */
}
-/* this starts FIQ timer events... they continue until the FIQ ISR sees that
- * its work is done and it turns off the timer. After setting up the fiq_ipc
- * struct with new work, you call this to start FIQ timer actions up again.
- * Only the FIQ ISR decides when it is done and controls turning off the
- * timer events.
+/*
+ * fiq_kick() forces a FIQ event to happen shortly after leaving the routine
*/
void fiq_kick(void)
{
unsigned long flags;
+ u32 tcon;
/* we have to take care about FIQ because this modification is
* non-atomic, FIQ could come in after the read and before the
@@ -156,15 +183,24 @@ void fiq_kick(void)
*/
local_save_flags(flags);
local_fiq_disable();
+ /* allow FIQs to resume */
__raw_writel(__raw_readl(S3C2410_INTMSK) &
~(1 << (_fiq_irq - S3C2410_CPUIRQ_OFFSET)),
S3C2410_INTMSK);
+ tcon = __raw_readl(S3C2410_TCON) & ~S3C2410_TCON_T3START;
+ /* fake the timer to a count of 1 */
+ __raw_writel(1, S3C2410_TCNTB(timer_index));
+ __raw_writel(tcon | S3C2410_TCON_T3MANUALUPD, S3C2410_TCON);
+ __raw_writel(tcon | S3C2410_TCON_T3MANUALUPD | S3C2410_TCON_T3START,
+ S3C2410_TCON);
+ __raw_writel(tcon | S3C2410_TCON_T3START, S3C2410_TCON);
local_irq_restore(flags);
}
EXPORT_SYMBOL_GPL(fiq_kick);
+
static int __init sc32440_fiq_probe(struct platform_device *pdev)
{
struct resource *r = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
@@ -172,6 +208,8 @@ static int __init sc32440_fiq_probe(struct platform_device *pdev)
if (!r)
return -EIO;
/* configure for the interrupt we are meant to use */
+ printk(KERN_INFO"Enabling FIQ using irq %d\n", r->start);
+
fiq_init_irq_source(r->start);
return sysfs_create_group(&pdev->dev.kobj, &s3c2440_fiq_attr_group);
diff --git a/arch/arm/mach-s3c2440/fiq_c_isr.h b/arch/arm/mach-s3c2440/fiq_c_isr.h
index f08740e..0c45eb7 100644
--- a/arch/arm/mach-s3c2440/fiq_c_isr.h
+++ b/arch/arm/mach-s3c2440/fiq_c_isr.h
@@ -5,6 +5,8 @@
extern unsigned long _fiq_count_fiqs;
extern u32 _fiq_ack_mask;
+extern int _fiq_timer_index;
+extern u16 _fiq_timer_divisor;
/* This CANNOT be implemented in a module -- it has to be used in code
* included in the monolithic kernel
diff --git a/arch/arm/mach-s3c2440/mach-gta02.c b/arch/arm/mach-s3c2440/mach-gta02.c
index 0bdd0e0..cb839b2 100644
--- a/arch/arm/mach-s3c2440/mach-gta02.c
+++ b/arch/arm/mach-s3c2440/mach-gta02.c
@@ -57,6 +57,7 @@
#include <asm/irq.h>
#include <asm/mach-types.h>
+#include <asm/arch-s3c2410/regs-irq.h>
#include <asm/arch/regs-gpio.h>
#include <asm/arch/regs-gpioj.h>
#include <asm/arch/fb.h>
@@ -336,6 +337,21 @@ struct platform_device gta02_pmu_dev = {
},
};
+/* FIQ */
+
+static struct resource sc32440_fiq_resources[] = {
+ [0] = {
+ .flags = IORESOURCE_IRQ,
+ .start = IRQ_TIMER3,
+ .end = IRQ_TIMER3,
+ },
+};
+
+struct platform_device sc32440_fiq_device = {
+ .name = "sc32440_fiq",
+ .num_resources = 1,
+ .resource = sc32440_fiq_resources,
+};
/* NOR Flash */
@@ -403,6 +419,7 @@ static struct platform_device *gta02_devices[] __initdata = {
&s3c_device_nand,
&s3c_device_ts,
&gta02_nor_flash,
+ &sc32440_fiq_device,
};
static struct s3c2410_nand_set gta02_nand_sets[] = {
diff --git a/include/asm-arm/arch-s3c2410/fiq_ipc_gta02.h b/include/asm-arm/arch-s3c2410/fiq_ipc_gta02.h
index 341f2bb..6cbd8e4 100644
--- a/include/asm-arm/arch-s3c2410/fiq_ipc_gta02.h
+++ b/include/asm-arm/arch-s3c2410/fiq_ipc_gta02.h
@@ -22,7 +22,7 @@ struct fiq_ipc {
/* actual definition lives in arch/arm/mach-s3c2440/fiq_c_isr.c */
extern struct fiq_ipc fiq_ipc;
-
+extern unsigned long _fiq_count_fiqs;
extern void fiq_kick(void); /* provoke a FIQ "immediately" */
#endif /* _LINUX_FIQ_IPC_H */
--
1.5.6.3

View file

@ -0,0 +1,243 @@
From b740b1200958baf4b5675017531c773bad5b64d0 Mon Sep 17 00:00:00 2001
From: mokopatches <mokopatches@openmoko.org>
Date: Fri, 25 Jul 2008 22:21:23 +0100
Subject: [PATCH] introduce-fiq-migrate-vibrator-gta02-only.patch
On GTA02 we use FIQ to manage the vibrator IO now. That
is necessary because we stole timer3 from doing hw pwm
for vibrator. This keeps the same UI in /sys but does
"bitbang pwm" on the same vibrator GPIO
From: Andy Green <andy@openmoko.com>
Signed-off-by: Andy Green <andy@openmoko.com>
---
arch/arm/mach-s3c2440/fiq_c_isr.c | 13 +++++---
arch/arm/mach-s3c2440/mach-gta02.c | 38 ++++++++++++++++++++++++++
drivers/leds/Kconfig | 1 +
drivers/leds/leds-neo1973-vibrator.c | 24 +++++++++++++++-
include/asm-arm/arch-s3c2410/fiq_ipc_gta02.h | 9 +++++-
5 files changed, 77 insertions(+), 8 deletions(-)
diff --git a/arch/arm/mach-s3c2440/fiq_c_isr.c b/arch/arm/mach-s3c2440/fiq_c_isr.c
index a71a234..38692fc 100644
--- a/arch/arm/mach-s3c2440/fiq_c_isr.c
+++ b/arch/arm/mach-s3c2440/fiq_c_isr.c
@@ -79,6 +79,7 @@ u16 _fiq_timer_divisor;
*/
extern void __attribute__ ((naked)) s3c2440_fiq_isr(void);
+
/* this is copied into the hard FIQ vector during init */
static void __attribute__ ((naked)) s3c2440_FIQ_Branch(void)
@@ -128,7 +129,7 @@ static int fiq_init_irq_source(int irq_index_fiq)
_fiq_irq = irq_index_fiq;
_fiq_ack_mask = 1 << (irq_index_fiq - S3C2410_CPUIRQ_OFFSET);
- timer_index = (irq_index_fiq - IRQ_TIMER0);
+ _fiq_timer_index = (irq_index_fiq - IRQ_TIMER0);
/* set up the timer to operate as a pwm device */
@@ -136,12 +137,11 @@ static int fiq_init_irq_source(int irq_index_fiq)
if (rc)
goto bail;
- pwm_timer_fiq.timerid = PWM0 + timer_index;
+ pwm_timer_fiq.timerid = PWM0 + _fiq_timer_index;
pwm_timer_fiq.prescaler = (6 - 1) / 2;
pwm_timer_fiq.divider = S3C2410_TCFG1_MUX3_DIV2;
/* default rate == ~32us */
- pwm_timer_fiq.counter = pwm_timer_fiq.comparer =
- timer_divisor = 64;
+ pwm_timer_fiq.counter = pwm_timer_fiq.comparer = 3000;
rc = s3c2410_pwm_enable(&pwm_timer_fiq);
if (rc)
@@ -149,6 +149,8 @@ static int fiq_init_irq_source(int irq_index_fiq)
s3c2410_pwm_start(&pwm_timer_fiq);
+ _fiq_timer_divisor = 0xffff; /* so kick will work initially */
+
/* let our selected interrupt be a magic FIQ interrupt */
__raw_writel(_fiq_ack_mask, S3C2410_INTMOD);
@@ -189,7 +191,7 @@ void fiq_kick(void)
S3C2410_INTMSK);
tcon = __raw_readl(S3C2410_TCON) & ~S3C2410_TCON_T3START;
/* fake the timer to a count of 1 */
- __raw_writel(1, S3C2410_TCNTB(timer_index));
+ __raw_writel(1, S3C2410_TCNTB(_fiq_timer_index));
__raw_writel(tcon | S3C2410_TCON_T3MANUALUPD, S3C2410_TCON);
__raw_writel(tcon | S3C2410_TCON_T3MANUALUPD | S3C2410_TCON_T3START,
S3C2410_TCON);
@@ -207,6 +209,7 @@ static int __init sc32440_fiq_probe(struct platform_device *pdev)
if (!r)
return -EIO;
+
/* configure for the interrupt we are meant to use */
printk(KERN_INFO"Enabling FIQ using irq %d\n", r->start);
diff --git a/arch/arm/mach-s3c2440/mach-gta02.c b/arch/arm/mach-s3c2440/mach-gta02.c
index cb839b2..8c7bbe7 100644
--- a/arch/arm/mach-s3c2440/mach-gta02.c
+++ b/arch/arm/mach-s3c2440/mach-gta02.c
@@ -95,12 +95,50 @@ static spinlock_t motion_irq_lock;
struct fiq_ipc fiq_ipc;
EXPORT_SYMBOL(fiq_ipc);
+#define DIVISOR_FROM_US(x) ((x) << 1)
+
+#define FIQ_DIVISOR_VIBRATOR DIVISOR_FROM_US(100)
+
/* define FIQ ISR */
FIQ_HANDLER_START()
/* define your locals here -- no initializers though */
+ u16 divisor;
FIQ_HANDLER_ENTRY(256, 512)
/* Your ISR here :-) */
+ divisor = 0xffff;
+
+ /* Vibrator servicing */
+
+ if (fiq_ipc.vib_pwm_latched || fiq_ipc.vib_pwm) { /* not idle */
+ if (((u8)_fiq_count_fiqs) == fiq_ipc.vib_pwm_latched)
+ s3c2410_gpio_setpin(fiq_ipc.vib_gpio_pin, 0);
+ if (((u8)_fiq_count_fiqs) == 0) {
+ fiq_ipc.vib_pwm_latched = fiq_ipc.vib_pwm;
+ if (fiq_ipc.vib_pwm_latched)
+ s3c2410_gpio_setpin(fiq_ipc.vib_gpio_pin, 1);
+ }
+ divisor = FIQ_DIVISOR_VIBRATOR;
+ }
+
+ /* TODO: HDQ servicing */
+
+
+
+ /* disable further timer interrupts if nobody has any work
+ * or adjust rate according to who still has work
+ *
+ * CAUTION: it means forground code must disable FIQ around
+ * its own non-atomic S3C2410_INTMSK changes... not common
+ * thankfully and taken care of by the fiq-basis patch
+ */
+ if (divisor == 0xffff) /* mask the fiq irq source */
+ __raw_writel(__raw_readl(S3C2410_INTMSK) | _fiq_ack_mask,
+ S3C2410_INTMSK);
+ else /* still working, maybe at a different rate */
+ __raw_writel(divisor, S3C2410_TCNTB(_fiq_timer_index));
+ _fiq_timer_divisor = divisor;
+
FIQ_HANDLER_END()
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index b6b1211..5a0aa9c 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -150,6 +150,7 @@ config LEDS_CLEVO_MAIL
config LEDS_NEO1973_VIBRATOR
tristate "Vibrator Support for the FIC Neo1973 GSM phone"
depends on LEDS_CLASS && MACH_NEO1973
+ select S3C2440_C_FIQ
help
This option enables support for the vibrator on the FIC Neo1973.
diff --git a/drivers/leds/leds-neo1973-vibrator.c b/drivers/leds/leds-neo1973-vibrator.c
index c943a6a..36ed216 100644
--- a/drivers/leds/leds-neo1973-vibrator.c
+++ b/drivers/leds/leds-neo1973-vibrator.c
@@ -23,6 +23,8 @@
#include <asm/arch/gta01.h>
#include <asm/plat-s3c/regs-timer.h>
+#include <asm/arch-s3c2410/fiq_ipc_gta02.h>
+
#define COUNTER 64
struct neo1973_vib_priv {
@@ -39,6 +41,11 @@ static void neo1973_vib_vib_set(struct led_classdev *led_cdev,
struct neo1973_vib_priv *vp =
container_of(led_cdev, struct neo1973_vib_priv, cdev);
+ if (machine_is_neo1973_gta02()) { /* use FIQ to control GPIO */
+ fiq_ipc.vib_pwm = value; /* set it for FIQ */
+ fiq_kick(); /* start up FIQs if not already going */
+ return;
+ }
/*
* value == 255 -> 99% duty cycle (full power)
* value == 128 -> 50% duty cycle (medium power)
@@ -46,7 +53,7 @@ static void neo1973_vib_vib_set(struct led_classdev *led_cdev,
*/
mutex_lock(&vp->mutex);
if (vp->has_pwm)
- s3c2410_pwm_duty_cycle(value/4, &vp->pwm);
+ s3c2410_pwm_duty_cycle(value / 4, &vp->pwm);
else {
if (value)
s3c2410_gpio_setpin(vp->gpio, 1);
@@ -123,6 +130,15 @@ static int __init neo1973_vib_probe(struct platform_device *pdev)
neo1973_vib_led.gpio = r->start;
platform_set_drvdata(pdev, &neo1973_vib_led);
+ if (machine_is_neo1973_gta02()) { /* use FIQ to control GPIO */
+ s3c2410_gpio_setpin(neo1973_vib_led.gpio, 0); /* off */
+ s3c2410_gpio_cfgpin(neo1973_vib_led.gpio, S3C2410_GPIO_OUTPUT);
+ /* safe, kmalloc'd copy needed for FIQ ISR */
+ fiq_ipc.vib_gpio_pin = neo1973_vib_led.gpio;
+ fiq_ipc.vib_pwm = 0; /* off */
+ goto configured;
+ }
+
/* TOUT3 */
if (neo1973_vib_led.gpio == S3C2410_GPB3) {
rc = neo1973_vib_init_hw(&neo1973_vib_led);
@@ -133,7 +149,7 @@ static int __init neo1973_vib_probe(struct platform_device *pdev)
s3c2410_gpio_cfgpin(neo1973_vib_led.gpio, S3C2410_GPB3_TOUT3);
neo1973_vib_led.has_pwm = 1;
}
-
+configured:
mutex_init(&neo1973_vib_led.mutex);
return led_classdev_register(&pdev->dev, &neo1973_vib_led.cdev);
@@ -141,6 +157,10 @@ static int __init neo1973_vib_probe(struct platform_device *pdev)
static int neo1973_vib_remove(struct platform_device *pdev)
{
+ if (machine_is_neo1973_gta02()) /* use FIQ to control GPIO */
+ fiq_ipc.vib_pwm = 0; /* off */
+ /* would only need kick if already off so no kick needed */
+
if (neo1973_vib_led.has_pwm)
s3c2410_pwm_disable(&neo1973_vib_led.pwm);
diff --git a/include/asm-arm/arch-s3c2410/fiq_ipc_gta02.h b/include/asm-arm/arch-s3c2410/fiq_ipc_gta02.h
index 6cbd8e4..507d235 100644
--- a/include/asm-arm/arch-s3c2410/fiq_ipc_gta02.h
+++ b/include/asm-arm/arch-s3c2410/fiq_ipc_gta02.h
@@ -16,8 +16,15 @@
* for testing
*/
+#include <asm/arch/pwm.h>
+#include <asm/plat-s3c/regs-timer.h>
+
+
struct fiq_ipc {
- u8 u8a[0]; /* placeholder */
+ /* vibrator */
+ unsigned long vib_gpio_pin; /* which pin to meddle with */
+ u8 vib_pwm; /* 0 = OFF -- will ensure GPIO deasserted and stop FIQ */
+ u8 vib_pwm_latched;
};
/* actual definition lives in arch/arm/mach-s3c2440/fiq_c_isr.c */
--
1.5.6.3

View file

@ -0,0 +1,606 @@
From d183fa083737f2b042ecf92166951c30fd83fe61 Mon Sep 17 00:00:00 2001
From: mokopatches <mokopatches@openmoko.org>
Date: Fri, 25 Jul 2008 22:21:23 +0100
Subject: [PATCH] fiq-hdq.patch
---
arch/arm/mach-s3c2440/mach-gta02.c | 204 +++++++++++++++++++++-
drivers/power/Kconfig | 8 +
drivers/power/Makefile | 2 +
drivers/power/gta02_hdq.c | 250 ++++++++++++++++++++++++++
include/asm-arm/arch-s3c2410/fiq_ipc_gta02.h | 23 +++
include/asm-arm/arch-s3c2410/gta02.h | 1 +
include/linux/gta02_hdq.h | 8 +
7 files changed, 495 insertions(+), 1 deletions(-)
create mode 100644 drivers/power/gta02_hdq.c
create mode 100644 include/linux/gta02_hdq.h
diff --git a/arch/arm/mach-s3c2440/mach-gta02.c b/arch/arm/mach-s3c2440/mach-gta02.c
index 8c7bbe7..cea76e7 100644
--- a/arch/arm/mach-s3c2440/mach-gta02.c
+++ b/arch/arm/mach-s3c2440/mach-gta02.c
@@ -99,6 +99,19 @@ EXPORT_SYMBOL(fiq_ipc);
#define FIQ_DIVISOR_VIBRATOR DIVISOR_FROM_US(100)
+#ifdef CONFIG_GTA02_HDQ
+/* HDQ specific */
+#define HDQ_SAMPLE_PERIOD_US 20
+/* private HDQ FSM state -- all other info interesting for caller in fiq_ipc */
+static enum hdq_bitbang_states hdq_state;
+static u8 hdq_ctr;
+static u8 hdq_ctr2;
+static u8 hdq_bit;
+static u8 hdq_shifter;
+static u8 hdq_tx_data_done;
+
+#define FIQ_DIVISOR_HDQ DIVISOR_FROM_US(HDQ_SAMPLE_PERIOD_US)
+#endif
/* define FIQ ISR */
FIQ_HANDLER_START()
@@ -121,9 +134,171 @@ FIQ_HANDLER_ENTRY(256, 512)
divisor = FIQ_DIVISOR_VIBRATOR;
}
- /* TODO: HDQ servicing */
+#ifdef CONFIG_GTA02_HDQ
+ /* HDQ servicing */
+
+ switch (hdq_state) {
+ case HDQB_IDLE:
+ if (fiq_ipc.hdq_request_ctr == fiq_ipc.hdq_transaction_ctr)
+ break;
+ hdq_ctr = 210 / HDQ_SAMPLE_PERIOD_US;
+ s3c2410_gpio_setpin(fiq_ipc.hdq_gpio_pin, 0);
+ s3c2410_gpio_cfgpin(fiq_ipc.hdq_gpio_pin, S3C2410_GPIO_OUTPUT);
+ hdq_tx_data_done = 0;
+ hdq_state = HDQB_TX_BREAK;
+ break;
+
+ case HDQB_TX_BREAK: /* issue low for > 190us */
+ if (--hdq_ctr == 0) {
+ hdq_ctr = 60 / HDQ_SAMPLE_PERIOD_US;
+ hdq_state = HDQB_TX_BREAK_RECOVERY;
+ s3c2410_gpio_setpin(fiq_ipc.hdq_gpio_pin, 1);
+ }
+ break;
+
+ case HDQB_TX_BREAK_RECOVERY: /* issue low for > 40us */
+ if (--hdq_ctr)
+ break;
+ hdq_shifter = fiq_ipc.hdq_ads;
+ hdq_bit = 8; /* 8 bits of ads / rw */
+ hdq_tx_data_done = 0; /* doing ads */
+ /* fallthru on last one */
+ case HDQB_ADS_CALC:
+ if (hdq_shifter & 1)
+ hdq_ctr = 50 / HDQ_SAMPLE_PERIOD_US;
+ else
+ hdq_ctr = 120 / HDQ_SAMPLE_PERIOD_US;
+ /* carefully precompute the other phase length */
+ hdq_ctr2 = (210 - (hdq_ctr * HDQ_SAMPLE_PERIOD_US)) /
+ HDQ_SAMPLE_PERIOD_US;
+ hdq_state = HDQB_ADS_LOW;
+ hdq_shifter >>= 1;
+ hdq_bit--;
+ s3c2410_gpio_setpin(fiq_ipc.hdq_gpio_pin, 0);
+ break;
+
+ case HDQB_ADS_LOW:
+ if (--hdq_ctr)
+ break;
+ s3c2410_gpio_setpin(fiq_ipc.hdq_gpio_pin, 1);
+ hdq_state = HDQB_ADS_HIGH;
+ break;
+
+ case HDQB_ADS_HIGH:
+ if (--hdq_ctr2 > 1) /* account for HDQB_ADS_CALC */
+ break;
+ if (hdq_bit) { /* more bits to do */
+ hdq_state = HDQB_ADS_CALC;
+ break;
+ }
+ /* no more bits, wait it out until hdq_ctr2 exhausted */
+ if (hdq_ctr2)
+ break;
+ /* ok no more bits and very last state */
+ hdq_ctr = 60 / HDQ_SAMPLE_PERIOD_US;
+ /* FIXME 0 = read */
+ if (fiq_ipc.hdq_ads & 0x80) { /* write the byte out */
+ /* set delay before payload */
+ hdq_ctr = 300 / HDQ_SAMPLE_PERIOD_US;
+ /* already high, no need to write */
+ hdq_state = HDQB_WAIT_TX;
+ break;
+ }
+ /* read the next byte */
+ hdq_bit = 8; /* 8 bits of data */
+ hdq_ctr = 3000 / HDQ_SAMPLE_PERIOD_US;
+ hdq_state = HDQB_WAIT_RX;
+ s3c2410_gpio_cfgpin(fiq_ipc.hdq_gpio_pin, S3C2410_GPIO_INPUT);
+ break;
+
+ case HDQB_WAIT_TX: /* issue low for > 40us */
+ if (--hdq_ctr)
+ break;
+ if (!hdq_tx_data_done) { /* was that the data sent? */
+ hdq_tx_data_done++;
+ hdq_shifter = fiq_ipc.hdq_tx_data;
+ hdq_bit = 8; /* 8 bits of data */
+ hdq_state = HDQB_ADS_CALC; /* start sending */
+ break;
+ }
+ fiq_ipc.hdq_error = 0;
+ fiq_ipc.hdq_transaction_ctr++;
+ hdq_state = HDQB_IDLE; /* all tx is done */
+ /* idle in input mode, it's pulled up by 10K */
+ s3c2410_gpio_cfgpin(fiq_ipc.hdq_gpio_pin, S3C2410_GPIO_INPUT);
+ break;
+
+ case HDQB_WAIT_RX: /* wait for battery to talk to us */
+ if (s3c2410_gpio_getpin(fiq_ipc.hdq_gpio_pin) == 0) {
+ /* it talks to us! */
+ hdq_ctr2 = 1;
+ hdq_bit = 8; /* 8 bits of data */
+ /* timeout */
+ hdq_ctr = 300 / HDQ_SAMPLE_PERIOD_US;
+ hdq_state = HDQB_DATA_RX_LOW;
+ break;
+ }
+ if (--hdq_ctr == 0) { /* timed out, error */
+ fiq_ipc.hdq_error = 1;
+ fiq_ipc.hdq_transaction_ctr++;
+ hdq_state = HDQB_IDLE; /* abort */
+ }
+ break;
+
+ /*
+ * HDQ basically works by measuring the low time of the bit cell
+ * 32-50us --> '1', 80 - 145us --> '0'
+ */
+
+ case HDQB_DATA_RX_LOW:
+ if (s3c2410_gpio_getpin(fiq_ipc.hdq_gpio_pin)) {
+ fiq_ipc.hdq_rx_data >>= 1;
+ if (hdq_ctr2 <= (65 / HDQ_SAMPLE_PERIOD_US))
+ fiq_ipc.hdq_rx_data |= 0x80;
+
+ if (--hdq_bit == 0) {
+ fiq_ipc.hdq_error = 0;
+ fiq_ipc.hdq_transaction_ctr++; /* done */
+ hdq_state = HDQB_IDLE;
+ } else
+ hdq_state = HDQB_DATA_RX_HIGH;
+ /* timeout */
+ hdq_ctr = 1000 / HDQ_SAMPLE_PERIOD_US;
+ hdq_ctr2 = 1;
+ break;
+ }
+ hdq_ctr2++;
+ if (--hdq_ctr)
+ break;
+ /* timed out, error */
+ fiq_ipc.hdq_error = 2;
+ fiq_ipc.hdq_transaction_ctr++;
+ hdq_state = HDQB_IDLE; /* abort */
+ break;
+ case HDQB_DATA_RX_HIGH:
+ if (!s3c2410_gpio_getpin(fiq_ipc.hdq_gpio_pin)) {
+ /* it talks to us! */
+ hdq_ctr2 = 1;
+ /* timeout */
+ hdq_ctr = 400 / HDQ_SAMPLE_PERIOD_US;
+ hdq_state = HDQB_DATA_RX_LOW;
+ break;
+ }
+ if (--hdq_ctr)
+ break;
+ /* timed out, error */
+ fiq_ipc.hdq_error = 3;
+ fiq_ipc.hdq_transaction_ctr++;
+ /* we're in input mode already */
+ hdq_state = HDQB_IDLE; /* abort */
+ break;
+ }
+ if (hdq_state != HDQB_IDLE) /* ie, not idle */
+ if (divisor > FIQ_DIVISOR_HDQ)
+ divisor = FIQ_DIVISOR_HDQ; /* keep us going */
+#endif
/* disable further timer interrupts if nobody has any work
* or adjust rate according to who still has work
@@ -391,6 +566,23 @@ struct platform_device sc32440_fiq_device = {
.resource = sc32440_fiq_resources,
};
+#ifdef CONFIG_GTA02_HDQ
+/* HDQ */
+
+static struct resource gta02_hdq_resources[] = {
+ [0] = {
+ .start = GTA02v5_GPIO_HDQ,
+ .end = GTA02v5_GPIO_HDQ,
+ },
+};
+
+struct platform_device gta02_hdq_device = {
+ .name = "gta02-hdq",
+ .num_resources = 1,
+ .resource = gta02_hdq_resources,
+};
+#endif
+
/* NOR Flash */
#define GTA02_FLASH_BASE 0x18000000 /* GCS3 */
@@ -1074,6 +1266,16 @@ static void __init gta02_machine_init(void)
platform_add_devices(gta02_devices, ARRAY_SIZE(gta02_devices));
+#ifdef CONFIG_GTA02_HDQ
+ switch (system_rev) {
+ case GTA02v5_SYSTEM_REV:
+ case GTA02v6_SYSTEM_REV:
+ platform_device_register(&gta02_hdq_device);
+ break;
+ default:
+ break;
+ }
+#endif
s3c2410_pm_init();
/* Set LCD_RESET / XRES to high */
diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
index 58c806e..0a4515d 100644
--- a/drivers/power/Kconfig
+++ b/drivers/power/Kconfig
@@ -50,3 +50,11 @@ config BATTERY_OLPC
Say Y to enable support for the battery on the OLPC laptop.
endif # POWER_SUPPLY
+
+config GTA02_HDQ
+ tristate "Neo Freerunner HDQ"
+ depends on MACH_NEO1973_GTA02 && FIQ && S3C2440_C_FIQ
+ help
+ Say Y to enable support for communicating with an HDQ battery
+ on the Neo Freerunner. You probably want to select
+ at least BATTERY_BQ27000_HDQ as well
diff --git a/drivers/power/Makefile b/drivers/power/Makefile
index 6413ded..88f227f 100644
--- a/drivers/power/Makefile
+++ b/drivers/power/Makefile
@@ -20,3 +20,5 @@ obj-$(CONFIG_APM_POWER) += apm_power.o
obj-$(CONFIG_BATTERY_DS2760) += ds2760_battery.o
obj-$(CONFIG_BATTERY_PMU) += pmu_battery.o
obj-$(CONFIG_BATTERY_OLPC) += olpc_battery.o
+
+obj-$(CONFIG_GTA02_HDQ) += gta02_hdq.o
diff --git a/drivers/power/gta02_hdq.c b/drivers/power/gta02_hdq.c
new file mode 100644
index 0000000..12c742e
--- /dev/null
+++ b/drivers/power/gta02_hdq.c
@@ -0,0 +1,250 @@
+/*
+ * HDQ driver for the FIC Neo1973 GTA02 GSM phone
+ *
+ * (C) 2006-2007 by OpenMoko, Inc.
+ * Author: Andy Green <andy@openmoko.com>
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/arch/gta02.h>
+#include <asm/arch/fiq_ipc_gta02.h>
+
+
+
+#define HDQ_READ 0
+#define HDQ_WRITE 0x80
+
+
+int gta02hdq_initialized(void)
+{
+ return fiq_ipc.hdq_probed;
+}
+EXPORT_SYMBOL_GPL(gta02hdq_initialized);
+
+int gta02hdq_read(int address)
+{
+ int count_sleeps = 5;
+ int ret = -ETIME;
+
+ mutex_lock(&fiq_ipc.hdq_lock);
+
+ fiq_ipc.hdq_ads = address | HDQ_READ;
+ fiq_ipc.hdq_request_ctr++;
+ fiq_kick();
+ /*
+ * FIQ takes care of it while we block our calling process
+ * But we're not spinning -- other processes run normally while
+ * we wait for the result
+ */
+ while (count_sleeps--) {
+ msleep(10); /* valid transaction always completes in < 10ms */
+
+ if (fiq_ipc.hdq_request_ctr != fiq_ipc.hdq_transaction_ctr)
+ continue;
+
+ if (fiq_ipc.hdq_error)
+ goto done; /* didn't see a response in good time */
+
+ ret = fiq_ipc.hdq_rx_data;
+ goto done;
+ }
+ ret = -EINVAL;
+
+done:
+ mutex_unlock(&fiq_ipc.hdq_lock);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(gta02hdq_read);
+
+int gta02hdq_write(int address, u8 data)
+{
+ int count_sleeps = 5;
+ int ret = -ETIME;
+
+ mutex_lock(&fiq_ipc.hdq_lock);
+
+ fiq_ipc.hdq_ads = address | HDQ_WRITE;
+ fiq_ipc.hdq_tx_data = data;
+ fiq_ipc.hdq_request_ctr++;
+ fiq_kick();
+ /*
+ * FIQ takes care of it while we block our calling process
+ * But we're not spinning -- other processes run normally while
+ * we wait for the result
+ */
+ while (count_sleeps--) {
+ msleep(10); /* valid transaction always completes in < 10ms */
+
+ if (fiq_ipc.hdq_request_ctr != fiq_ipc.hdq_transaction_ctr)
+ continue; /* something bad with FIQ */
+
+ if (fiq_ipc.hdq_error)
+ goto done; /* didn't see a response in good time */
+ }
+ ret = -EINVAL;
+
+done:
+ mutex_unlock(&fiq_ipc.hdq_lock);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(gta02hdq_write);
+
+/* sysfs */
+
+static ssize_t hdq_sysfs_dump(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ int n;
+ int v;
+ u8 u8a[128]; /* whole address space for HDQ */
+ char *end = buf;
+
+ /* the dump does not take care about 16 bit regs, because at this
+ * bus level we don't know about the chip details
+ */
+ for (n = 0; n < sizeof(u8a); n++) {
+ v = gta02hdq_read(n);
+ if (v < 0)
+ goto bail;
+ u8a[n] = v;
+ }
+
+ for (n = 0; n < sizeof(u8a); n += 16) {
+ hex_dump_to_buffer(u8a + n, sizeof(u8a), 16, 1, end, 4096, 0);
+ end += strlen(end);
+ *end++ = '\n';
+ *end = '\0';
+ }
+ return (end - buf);
+
+bail:
+ return sprintf(buf, "ERROR %d\n", v);
+}
+
+/* you write by <address> <data>, eg, "34 128" */
+
+#define atoi(str) simple_strtoul(((str != NULL) ? str : ""), NULL, 0)
+
+static ssize_t hdq_sysfs_write(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ const char *end = buf + count;
+ int address = atoi(buf);
+
+ while ((buf != end) && (*buf != ' '))
+ buf++;
+ if (buf >= end)
+ return 0;
+ while ((buf < end) && (*buf == ' '))
+ buf++;
+ if (buf >= end)
+ return 0;
+
+ gta02hdq_write(address, atoi(buf));
+
+ return count;
+}
+
+static DEVICE_ATTR(dump, 0400, hdq_sysfs_dump, NULL);
+static DEVICE_ATTR(write, 0600, NULL, hdq_sysfs_write);
+
+static struct attribute *gta02hdq_sysfs_entries[] = {
+ &dev_attr_dump.attr,
+ &dev_attr_write.attr,
+ NULL
+};
+
+static struct attribute_group gta02hdq_attr_group = {
+ .name = "hdq",
+ .attrs = gta02hdq_sysfs_entries,
+};
+
+
+#ifdef CONFIG_PM
+static int gta02hdq_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ /* after 18s of this, the battery monitor will also go to sleep */
+ s3c2410_gpio_setpin(fiq_ipc.hdq_gpio_pin, 0);
+ s3c2410_gpio_cfgpin(fiq_ipc.hdq_gpio_pin, S3C2410_GPIO_OUTPUT);
+ return 0;
+}
+
+static int gta02hdq_resume(struct platform_device *pdev)
+{
+ s3c2410_gpio_setpin(fiq_ipc.hdq_gpio_pin, 1);
+ s3c2410_gpio_cfgpin(fiq_ipc.hdq_gpio_pin, S3C2410_GPIO_OUTPUT);
+ return 0;
+}
+#endif
+
+static int __init gta02hdq_probe(struct platform_device *pdev)
+{
+ struct resource *r = platform_get_resource(pdev, 0, 0);
+
+ if (!machine_is_neo1973_gta02())
+ return -EIO;
+
+ if (!r)
+ return -EINVAL;
+
+ platform_set_drvdata(pdev, NULL);
+
+ mutex_init(&fiq_ipc.hdq_lock);
+
+ /* set our HDQ comms pin from the platform data */
+ fiq_ipc.hdq_gpio_pin = r->start;
+
+ s3c2410_gpio_setpin(fiq_ipc.hdq_gpio_pin, 1);
+ s3c2410_gpio_cfgpin(fiq_ipc.hdq_gpio_pin, S3C2410_GPIO_OUTPUT);
+
+ fiq_ipc.hdq_probed = 1; /* we are ready to do stuff now */
+
+ return sysfs_create_group(&pdev->dev.kobj, &gta02hdq_attr_group);
+}
+
+static int gta02hdq_remove(struct platform_device *pdev)
+{
+ sysfs_remove_group(&pdev->dev.kobj, &gta02hdq_attr_group);
+ return 0;
+}
+
+static struct platform_driver gta02hdq_driver = {
+ .probe = gta02hdq_probe,
+ .remove = gta02hdq_remove,
+#ifdef CONFIG_PM
+ .suspend = gta02hdq_suspend,
+ .resume = gta02hdq_resume,
+#endif
+ .driver = {
+ .name = "gta02-hdq",
+ },
+};
+
+static int __init gta02hdq_init(void)
+{
+ return platform_driver_register(&gta02hdq_driver);
+}
+
+static void __exit gta02hdq_exit(void)
+{
+ platform_driver_unregister(&gta02hdq_driver);
+}
+
+module_init(gta02hdq_init);
+module_exit(gta02hdq_exit);
+
+MODULE_AUTHOR("Andy Green <andy@openmoko.com>");
+MODULE_DESCRIPTION("GTA02 HDQ driver");
+MODULE_LICENSE("GPL");
diff --git a/include/asm-arm/arch-s3c2410/fiq_ipc_gta02.h b/include/asm-arm/arch-s3c2410/fiq_ipc_gta02.h
index 507d235..c5eb3df 100644
--- a/include/asm-arm/arch-s3c2410/fiq_ipc_gta02.h
+++ b/include/asm-arm/arch-s3c2410/fiq_ipc_gta02.h
@@ -19,12 +19,35 @@
#include <asm/arch/pwm.h>
#include <asm/plat-s3c/regs-timer.h>
+enum hdq_bitbang_states {
+ HDQB_IDLE = 0,
+ HDQB_TX_BREAK,
+ HDQB_TX_BREAK_RECOVERY,
+ HDQB_ADS_CALC,
+ HDQB_ADS_LOW,
+ HDQB_ADS_HIGH,
+ HDQB_WAIT_RX,
+ HDQB_DATA_RX_LOW,
+ HDQB_DATA_RX_HIGH,
+ HDQB_WAIT_TX,
+};
struct fiq_ipc {
/* vibrator */
unsigned long vib_gpio_pin; /* which pin to meddle with */
u8 vib_pwm; /* 0 = OFF -- will ensure GPIO deasserted and stop FIQ */
u8 vib_pwm_latched;
+
+ /* hdq */
+ u8 hdq_probed; /* nonzero after HDQ driver probed */
+ struct mutex hdq_lock; /* if you want to use hdq, you have to take lock */
+ unsigned long hdq_gpio_pin; /* GTA02 = GPD14 which pin to meddle with */
+ u8 hdq_ads; /* b7..b6 = register address, b0 = r/w */
+ u8 hdq_tx_data; /* data to tx for write action */
+ u8 hdq_rx_data; /* data received in read action */
+ u8 hdq_request_ctr; /* incremented by "user" to request a transfer */
+ u8 hdq_transaction_ctr; /* incremented after each transfer */
+ u8 hdq_error; /* 0 = no error */
};
/* actual definition lives in arch/arm/mach-s3c2440/fiq_c_isr.c */
diff --git a/include/asm-arm/arch-s3c2410/gta02.h b/include/asm-arm/arch-s3c2410/gta02.h
index fa49d93..f686a7a 100644
--- a/include/asm-arm/arch-s3c2410/gta02.h
+++ b/include/asm-arm/arch-s3c2410/gta02.h
@@ -37,6 +37,7 @@
#define GTA02v3_GPIO_nG1_CS S3C2410_GPD12 /* v3 + v4 only */
#define GTA02v3_GPIO_nG2_CS S3C2410_GPD13 /* v3 + v4 only */
+#define GTA02v5_GPIO_HDQ S3C2410_GPD14 /* v5 + */
#define GTA02_GPIO_nG1_INT S3C2410_GPF0
#define GTA02_GPIO_IO1 S3C2410_GPF1
diff --git a/include/linux/gta02_hdq.h b/include/linux/gta02_hdq.h
new file mode 100644
index 0000000..2f43a62
--- /dev/null
+++ b/include/linux/gta02_hdq.h
@@ -0,0 +1,8 @@
+#ifndef __GTA02HDQ_H__
+#define __GTA02HDQ_H__
+
+int gta02hdq_read(int address);
+int gta02hdq_write(int address, u8 data);
+int gta02hdq_initialized(void);
+
+#endif
--
1.5.6.3

View file

@ -0,0 +1,510 @@
From 2bab304b10f077cb88d5b5f5bd7e50c16aac2132 Mon Sep 17 00:00:00 2001
From: mokopatches <mokopatches@openmoko.org>
Date: Fri, 25 Jul 2008 22:21:23 +0100
Subject: [PATCH] bq27000-battery-driver.patch
---
arch/arm/mach-s3c2440/Kconfig | 2 +
arch/arm/mach-s3c2440/mach-gta02.c | 21 ++
drivers/power/Kconfig | 7 +-
drivers/power/Makefile | 1 +
drivers/power/bq27000_battery.c | 375 ++++++++++++++++++++++++++++++++++++
include/linux/bq27000_battery.h | 12 ++
6 files changed, 417 insertions(+), 1 deletions(-)
create mode 100644 drivers/power/bq27000_battery.c
create mode 100644 include/linux/bq27000_battery.h
diff --git a/arch/arm/mach-s3c2440/Kconfig b/arch/arm/mach-s3c2440/Kconfig
index 3015aaf..b417f8e 100644
--- a/arch/arm/mach-s3c2440/Kconfig
+++ b/arch/arm/mach-s3c2440/Kconfig
@@ -79,6 +79,8 @@ config MACH_NEO1973_GTA02
bool "FIC Neo1973 GSM Phone (GTA02 Hardware)"
select CPU_S3C2442
select SENSORS_PCF50633
+ select POWER_SUPPLY
+ select GTA02_HDQ
help
Say Y here if you are using the FIC Neo1973 GSM Phone
diff --git a/arch/arm/mach-s3c2440/mach-gta02.c b/arch/arm/mach-s3c2440/mach-gta02.c
index cea76e7..3816ea5 100644
--- a/arch/arm/mach-s3c2440/mach-gta02.c
+++ b/arch/arm/mach-s3c2440/mach-gta02.c
@@ -81,6 +81,8 @@
#include <asm/arch/fiq_ipc_gta02.h>
#include "fiq_c_isr.h"
+#include <linux/gta02_hdq.h>
+#include <linux/bq27000_battery.h>
/* arbitrates which sensor IRQ owns the shared SPI bus */
static spinlock_t motion_irq_lock;
@@ -583,6 +585,24 @@ struct platform_device gta02_hdq_device = {
};
#endif
+/* BQ27000 Battery */
+
+struct bq27000_platform_data bq27000_pdata = {
+ .name = "bat",
+ .rsense_mohms = 20,
+ .hdq_read = gta02hdq_read,
+ .hdq_write = gta02hdq_write,
+ .hdq_initialized = gta02hdq_initialized,
+};
+
+struct platform_device bq27000_battery_device = {
+ .name = "bq27000-battery",
+ .dev = {
+ .platform_data = &bq27000_pdata,
+ },
+};
+
+
/* NOR Flash */
#define GTA02_FLASH_BASE 0x18000000 /* GCS3 */
@@ -1271,6 +1291,7 @@ static void __init gta02_machine_init(void)
case GTA02v5_SYSTEM_REV:
case GTA02v6_SYSTEM_REV:
platform_device_register(&gta02_hdq_device);
+ platform_device_register(&bq27000_battery_device);
break;
default:
break;
diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
index 0a4515d..feb8b0a 100644
--- a/drivers/power/Kconfig
+++ b/drivers/power/Kconfig
@@ -49,7 +49,10 @@ config BATTERY_OLPC
help
Say Y to enable support for the battery on the OLPC laptop.
-endif # POWER_SUPPLY
+config BATTERY_BQ27000_HDQ
+ tristate "BQ27000 HDQ battery monitor driver"
+ help
+ Say Y to enable support for the battery on the Neo Freerunner
config GTA02_HDQ
tristate "Neo Freerunner HDQ"
@@ -58,3 +61,5 @@ config GTA02_HDQ
Say Y to enable support for communicating with an HDQ battery
on the Neo Freerunner. You probably want to select
at least BATTERY_BQ27000_HDQ as well
+
+endif # POWER_SUPPLY
diff --git a/drivers/power/Makefile b/drivers/power/Makefile
index 88f227f..d7e87ad 100644
--- a/drivers/power/Makefile
+++ b/drivers/power/Makefile
@@ -20,5 +20,6 @@ obj-$(CONFIG_APM_POWER) += apm_power.o
obj-$(CONFIG_BATTERY_DS2760) += ds2760_battery.o
obj-$(CONFIG_BATTERY_PMU) += pmu_battery.o
obj-$(CONFIG_BATTERY_OLPC) += olpc_battery.o
+obj-$(CONFIG_BATTERY_BQ27000_HDQ) += bq27000_battery.o
obj-$(CONFIG_GTA02_HDQ) += gta02_hdq.o
diff --git a/drivers/power/bq27000_battery.c b/drivers/power/bq27000_battery.c
new file mode 100644
index 0000000..d19186a
--- /dev/null
+++ b/drivers/power/bq27000_battery.c
@@ -0,0 +1,375 @@
+/*
+ * Driver for batteries with bq27000 chips inside via HDQ
+ *
+ * Copyright 2008 Openmoko, Inc
+ * Andy Green <andy@openmoko.com>
+ *
+ * based on ds2760 driver, original copyright notice for that --->
+ *
+ * Copyright © 2007 Anton Vorontsov
+ * 2004-2007 Matt Reimer
+ * 2004 Szabolcs Gyurko
+ *
+ * Use consistent with the GNU GPL is permitted,
+ * provided that this copyright notice is
+ * preserved in its entirety in all copies and derived works.
+ *
+ * Author: Anton Vorontsov <cbou@mail.ru>
+ * February 2007
+ *
+ * Matt Reimer <mreimer@vpop.net>
+ * April 2004, 2005, 2007
+ *
+ * Szabolcs Gyurko <szabolcs.gyurko@tlt.hu>
+ * September 2004
+ */
+
+#include <linux/module.h>
+#include <linux/param.h>
+#include <linux/jiffies.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/platform_device.h>
+#include <linux/power_supply.h>
+#include <linux/bq27000_battery.h>
+
+enum bq27000_regs {
+ /* RAM regs */
+ /* read-write after this */
+ BQ27000_CTRL = 0, /* Device Control Register */
+ BQ27000_MODE, /* Device Mode Register */
+ BQ27000_AR_L, /* At-Rate H L */
+ BQ27000_AR_H,
+ /* read-only after this */
+ BQ27000_ARTTE_L, /* At-Rate Time To Empty H L */
+ BQ27000_ARTTE_H,
+ BQ27000_TEMP_L, /* Reported Temperature H L */
+ BQ27000_TEMP_H,
+ BQ27000_VOLT_L, /* Reported Voltage H L */
+ BQ27000_VOLT_H,
+ BQ27000_FLAGS, /* Status Flags */
+ BQ27000_RSOC, /* Relative State of Charge */
+ BQ27000_NAC_L, /* Nominal Available Capacity H L */
+ BQ27000_NAC_H,
+ BQ27000_CACD_L, /* Discharge Compensated H L */
+ BQ27000_CACD_H,
+ BQ27000_CACT_L, /* Temperature Compensated H L */
+ BQ27000_CACT_H,
+ BQ27000_LMD_L, /* Last measured discharge H L */
+ BQ27000_LMD_H,
+ BQ27000_AI_L, /* Average Current H L */
+ BQ27000_AI_H,
+ BQ27000_TTE_L, /* Time to Empty H L */
+ BQ27000_TTE_H,
+ BQ27000_TTF_L, /* Time to Full H L */
+ BQ27000_TTF_H,
+ BQ27000_SI_L, /* Standby Current H L */
+ BQ27000_SI_H,
+ BQ27000_STTE_L, /* Standby Time To Empty H L */
+ BQ27000_STTE_H,
+ BQ27000_MLI_L, /* Max Load Current H L */
+ BQ27000_MLI_H,
+ BQ27000_MLTTE_L, /* Max Load Time To Empty H L */
+ BQ27000_MLTTE_H,
+ BQ27000_SAE_L, /* Available Energy H L */
+ BQ27000_SAE_H,
+ BQ27000_AP_L, /* Available Power H L */
+ BQ27000_AP_H,
+ BQ27000_TTECP_L, /* Time to Empty at Constant Power H L */
+ BQ27000_TTECP_H,
+ BQ27000_CYCL_L, /* Cycle count since learning cycle H L */
+ BQ27000_CYCL_H,
+ BQ27000_CYCT_L, /* Cycle Count Total H L */
+ BQ27000_CYCT_H,
+ BQ27000_CSOC, /* Compensated State Of Charge */
+ /* EEPROM regs */
+ /* read-write after this */
+ BQ27000_EE_EE_EN = 0x6e, /* EEPROM Program Enable */
+ BQ27000_EE_ILMD = 0x76, /* Initial Last Measured Discharge High Byte */
+ BQ27000_EE_SEDVF, /* Scaled EDVF Threshold */
+ BQ27000_EE_SEDV1, /* Scaled EDV1 Threshold */
+ BQ27000_EE_ISLC, /* Initial Standby Load Current */
+ BQ27000_EE_DMFSD, /* Digital Magnitude Filter and Self Discharge */
+ BQ27000_EE_TAPER, /* Aging Estimate Enable, Charge Termination Taper */
+ BQ27000_EE_PKCFG, /* Pack Configuration Values */
+ BQ27000_EE_IMLC, /* Initial Max Load Current or ID #3 */
+ BQ27000_EE_DCOMP, /* Discharge rate compensation constants or ID #2 */
+ BQ27000_EE_TCOMP, /* Temperature Compensation constants or ID #1 */
+};
+
+enum bq27000_status_flags {
+ BQ27000_STATUS_CHGS = 0x80, /* 1 = being charged */
+ BQ27000_STATUS_NOACT = 0x40, /* 1 = no activity */
+ BQ27000_STATUS_IMIN = 0x20, /* 1 = Lion taper current mode */
+ BQ27000_STATUS_CI = 0x10, /* 1 = capacity likely innacurate */
+ BQ27000_STATUS_CALIP = 0x08, /* 1 = calibration in progress */
+ BQ27000_STATUS_VDQ = 0x04, /* 1 = capacity should be accurate */
+ BQ27000_STATUS_EDV1 = 0x02, /* 1 = end of discharge.. <6% left */
+ BQ27000_STATUS_EDVF = 0x01, /* 1 = no, it's really empty now */
+};
+
+#define NANOVOLTS_UNIT 3750
+
+struct bq27000_device_info {
+ struct device *dev;
+ struct power_supply bat;
+
+ int rsense_mohms; /* from platform */
+
+ int (*hdq_initialized)(void); /* from platform */
+ int (*hdq_read)(int); /* from platform */
+ int (*hdq_write)(int, u8); /* from platform */
+};
+
+/*
+ * reading 16 bit values over HDQ has a special hazard where the
+ * hdq device firmware can update the 16-bit register during the time we
+ * read the two halves. TI document SLUS556D recommends the algorithm here
+ * to avoid trouble
+ */
+
+static int hdq_read16(struct bq27000_device_info *di, int address)
+{
+ int acc;
+ int high;
+ int retries = 3;
+
+ while (retries--) {
+
+ high = (di->hdq_read)(address + 1); /* high part */
+
+ if (high < 0)
+ return high;
+ acc = (di->hdq_read)(address);
+ if (acc < 0)
+ return acc;
+
+ /* confirm high didn't change between reading it and low */
+ if (high == (di->hdq_read)(address + 1))
+ return (high << 8) | acc;
+ }
+
+ return -ETIME;
+}
+
+#define to_bq27000_device_info(x) container_of((x), \
+ struct bq27000_device_info, \
+ bat);
+
+static void bq27000_battery_external_power_changed(struct power_supply *psy)
+{
+ struct bq27000_device_info *di = to_bq27000_device_info(psy);
+
+ dev_dbg(di->dev, "%s\n", __FUNCTION__);
+}
+
+static int bq27000_battery_get_property(struct power_supply *psy,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
+{
+ int v, n;
+ struct bq27000_device_info *di = to_bq27000_device_info(psy);
+
+ if (!(di->hdq_initialized)())
+ return -EINVAL;
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_STATUS:
+ val->intval = POWER_SUPPLY_STATUS_UNKNOWN;
+ v = hdq_read16(di, BQ27000_AI_L);
+ if (v < 0)
+ return v;
+ if (v < 2) { /* no real activity on the battery */
+ if (!hdq_read16(di, BQ27000_TTF_L))
+ val->intval = POWER_SUPPLY_STATUS_FULL;
+ else
+ val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
+ break;
+ }
+ /* power is actually going in or out... */
+ v = (di->hdq_read)(BQ27000_FLAGS);
+ if (v < 0)
+ return v;
+ if (v & BQ27000_STATUS_CHGS)
+ val->intval = POWER_SUPPLY_STATUS_CHARGING;
+ else
+ val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
+ break;
+ case POWER_SUPPLY_PROP_VOLTAGE_NOW:
+ v = hdq_read16(di, BQ27000_VOLT_L);
+ if (v < 0)
+ return v;
+ val->intval = v * 1000; /* mV -> uV */
+ break;
+ case POWER_SUPPLY_PROP_CURRENT_NOW:
+ v = (di->hdq_read)(BQ27000_FLAGS);
+ if (v < 0)
+ return v;
+ if (v & BQ27000_STATUS_CHGS)
+ n = -NANOVOLTS_UNIT;
+ else
+ n = NANOVOLTS_UNIT;
+ v = hdq_read16(di, BQ27000_AI_L);
+ if (v < 0)
+ return v;
+ val->intval = (v * n) / di->rsense_mohms;
+ break;
+ case POWER_SUPPLY_PROP_CHARGE_FULL:
+ v = hdq_read16(di, BQ27000_LMD_L);
+ if (v < 0)
+ return v;
+ val->intval = (v * 3570) / di->rsense_mohms;
+ break;
+ case POWER_SUPPLY_PROP_TEMP:
+ v = hdq_read16(di, BQ27000_TEMP_L);
+ if (v < 0)
+ return v;
+ /* K (in 0.25K units) is 273.15 up from C (in 0.1C)*/
+ /* 10926 = 27315 * 4 / 10 */
+ val->intval = (((long)v * 10l) - 10926) / 4;
+ break;
+ case POWER_SUPPLY_PROP_TECHNOLOGY:
+ val->intval = POWER_SUPPLY_TECHNOLOGY_LION;
+ break;
+ case POWER_SUPPLY_PROP_CAPACITY:
+ val->intval = (di->hdq_read)(BQ27000_RSOC);
+ if (val->intval < 0)
+ return val->intval;
+ break;
+ case POWER_SUPPLY_PROP_PRESENT:
+ v = (di->hdq_read)(BQ27000_RSOC);
+ val->intval = !(v < 0);
+ break;
+ case POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW:
+ v = hdq_read16(di, BQ27000_TTE_L);
+ if (v < 0)
+ return v;
+ val->intval = 60 * v;
+ break;
+ case POWER_SUPPLY_PROP_TIME_TO_FULL_NOW:
+ v = hdq_read16(di, BQ27000_TTF_L);
+ if (v < 0)
+ return v;
+ val->intval = 60 * v;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static enum power_supply_property bq27000_battery_props[] = {
+ POWER_SUPPLY_PROP_STATUS,
+ POWER_SUPPLY_PROP_VOLTAGE_NOW,
+ POWER_SUPPLY_PROP_CURRENT_NOW,
+ POWER_SUPPLY_PROP_CHARGE_FULL,
+ POWER_SUPPLY_PROP_TEMP,
+ POWER_SUPPLY_PROP_TECHNOLOGY,
+ POWER_SUPPLY_PROP_PRESENT,
+ POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW,
+ POWER_SUPPLY_PROP_TIME_TO_FULL_NOW,
+ POWER_SUPPLY_PROP_MODEL_NAME,
+ POWER_SUPPLY_PROP_CAPACITY
+};
+
+static int bq27000_battery_probe(struct platform_device *pdev)
+{
+ int retval = 0;
+ struct bq27000_device_info *di;
+ struct bq27000_platform_data *pdata;
+
+ dev_info(&pdev->dev, "BQ27000 Battery Driver (C) 2008 Openmoko, Inc\n");
+
+ di = kzalloc(sizeof(*di), GFP_KERNEL);
+ if (!di) {
+ retval = -ENOMEM;
+ goto di_alloc_failed;
+ }
+
+ platform_set_drvdata(pdev, di);
+
+ pdata = pdev->dev.platform_data;
+ di->dev = &pdev->dev;
+ /* di->w1_dev = pdev->dev.parent; */
+ di->bat.name = pdata->name;
+ di->bat.type = POWER_SUPPLY_TYPE_BATTERY;
+ di->bat.properties = bq27000_battery_props;
+ di->bat.num_properties = ARRAY_SIZE(bq27000_battery_props);
+ di->bat.get_property = bq27000_battery_get_property;
+ di->bat.external_power_changed =
+ bq27000_battery_external_power_changed;
+ di->hdq_read = pdata->hdq_read;
+ di->hdq_write = pdata->hdq_write;
+ di->rsense_mohms = pdata->rsense_mohms;
+ di->hdq_initialized = pdata->hdq_initialized;
+
+ retval = power_supply_register(&pdev->dev, &di->bat);
+ if (retval) {
+ dev_err(di->dev, "failed to register battery\n");
+ goto batt_failed;
+ }
+
+ return 0;
+
+batt_failed:
+ kfree(di);
+di_alloc_failed:
+ return retval;
+}
+
+static int bq27000_battery_remove(struct platform_device *pdev)
+{
+ struct bq27000_device_info *di = platform_get_drvdata(pdev);
+
+ power_supply_unregister(&di->bat);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+
+static int bq27000_battery_suspend(struct platform_device *pdev,
+ pm_message_t state)
+{
+ return 0;
+}
+
+static int bq27000_battery_resume(struct platform_device *pdev)
+{
+ return 0;
+}
+
+#else
+
+#define bq27000_battery_suspend NULL
+#define bq27000_battery_resume NULL
+
+#endif /* CONFIG_PM */
+
+static struct platform_driver bq27000_battery_driver = {
+ .driver = {
+ .name = "bq27000-battery",
+ },
+ .probe = bq27000_battery_probe,
+ .remove = bq27000_battery_remove,
+ .suspend = bq27000_battery_suspend,
+ .resume = bq27000_battery_resume,
+};
+
+static int __init bq27000_battery_init(void)
+{
+ return platform_driver_register(&bq27000_battery_driver);
+}
+
+static void __exit bq27000_battery_exit(void)
+{
+ platform_driver_unregister(&bq27000_battery_driver);
+}
+
+module_init(bq27000_battery_init);
+module_exit(bq27000_battery_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Andy Green <andy@openmoko.com>");
+MODULE_DESCRIPTION("bq27000 battery driver");
diff --git a/include/linux/bq27000_battery.h b/include/linux/bq27000_battery.h
new file mode 100644
index 0000000..36b4f20
--- /dev/null
+++ b/include/linux/bq27000_battery.h
@@ -0,0 +1,12 @@
+#ifndef __BQ27000_BATTERY_H__
+#define __BQ27000_BATTERY_H__
+
+struct bq27000_platform_data {
+ const char *name;
+ int rsense_mohms;
+ int (*hdq_read)(int);
+ int (*hdq_write)(int, u8);
+ int (*hdq_initialized)(void);
+};
+
+#endif
--
1.5.6.3

View file

@ -0,0 +1,95 @@
From 6294c84872b0d26111bdd1b9e5fec41c8a087443 Mon Sep 17 00:00:00 2001
From: mokopatches <mokopatches@openmoko.org>
Date: Fri, 25 Jul 2008 22:21:23 +0100
Subject: [PATCH] fix-EVIOCGRAB-semantics.patch
---
drivers/input/evdev.c | 32 +++++++++++++++-----------------
1 files changed, 15 insertions(+), 17 deletions(-)
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c
index b32984b..499ffe1 100644
--- a/drivers/input/evdev.c
+++ b/drivers/input/evdev.c
@@ -28,7 +28,7 @@ struct evdev {
char name[16];
struct input_handle handle;
wait_queue_head_t wait;
- struct evdev_client *grab;
+ int *grab;
struct list_head client_list;
spinlock_t client_lock; /* protects client_list */
struct mutex mutex;
@@ -39,6 +39,7 @@ struct evdev_client {
struct input_event buffer[EVDEV_BUFFER_SIZE];
int head;
int tail;
+ int grab;
spinlock_t buffer_lock; /* protects access to buffer, head and tail */
struct fasync_struct *fasync;
struct evdev *evdev;
@@ -79,12 +80,8 @@ static void evdev_event(struct input_handle *handle,
rcu_read_lock();
- client = rcu_dereference(evdev->grab);
- if (client)
+ list_for_each_entry_rcu(client, &evdev->client_list, node)
evdev_pass_event(client, &event);
- else
- list_for_each_entry_rcu(client, &evdev->client_list, node)
- evdev_pass_event(client, &event);
rcu_read_unlock();
@@ -136,14 +133,15 @@ static int evdev_grab(struct evdev *evdev, struct evdev_client *client)
{
int error;
- if (evdev->grab)
+ if (client->grab)
return -EBUSY;
- error = input_grab_device(&evdev->handle);
- if (error)
- return error;
-
- rcu_assign_pointer(evdev->grab, client);
+ if (!evdev->grab++) {
+ error = input_grab_device(&evdev->handle);
+ if (error)
+ return error;
+ }
+ client->grab = 1;
synchronize_rcu();
return 0;
@@ -151,12 +149,12 @@ static int evdev_grab(struct evdev *evdev, struct evdev_client *client)
static int evdev_ungrab(struct evdev *evdev, struct evdev_client *client)
{
- if (evdev->grab != client)
+ if (!client->grab)
return -EINVAL;
- rcu_assign_pointer(evdev->grab, NULL);
- synchronize_rcu();
- input_release_device(&evdev->handle);
+ if (!--evdev->grab && evdev->exist)
+ input_release_device(&evdev->handle);
+ client->grab = 0;
return 0;
}
@@ -231,7 +229,7 @@ static int evdev_release(struct inode *inode, struct file *file)
struct evdev *evdev = client->evdev;
mutex_lock(&evdev->mutex);
- if (evdev->grab == client)
+ if (client->grab)
evdev_ungrab(evdev, client);
mutex_unlock(&evdev->mutex);
--
1.5.6.3

View file

@ -0,0 +1,89 @@
From 7cb1e9a0797dd5d372f943f0ed971a5b432d16aa Mon Sep 17 00:00:00 2001
From: mokopatches <mokopatches@openmoko.org>
Date: Fri, 25 Jul 2008 22:21:23 +0100
Subject: [PATCH] s3c2410-usb-switch.patch
---
drivers/usb/host/ohci-s3c2410.c | 43 +++++++++++++++++++++++++++++++++++++++
1 files changed, 43 insertions(+), 0 deletions(-)
diff --git a/drivers/usb/host/ohci-s3c2410.c b/drivers/usb/host/ohci-s3c2410.c
index 3c7a740..5877fc9 100644
--- a/drivers/usb/host/ohci-s3c2410.c
+++ b/drivers/usb/host/ohci-s3c2410.c
@@ -24,6 +24,7 @@
#include <asm/hardware.h>
#include <asm/arch/usb-control.h>
+#include <asm/arch/regs-gpio.h>
#define valid_port(idx) ((idx) == 1 || (idx) == 2)
@@ -308,6 +309,40 @@ static void s3c2410_hcd_oc(struct s3c2410_hcd_info *info, int port_oc)
local_irq_restore(flags);
}
+/* switching of USB pads */
+static ssize_t show_usb_mode(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ if (__raw_readl(S3C24XX_MISCCR) & S3C2410_MISCCR_USBHOST)
+ return sprintf(buf, "host\n");
+
+ return sprintf(buf, "device\n");
+}
+
+static ssize_t set_usb_mode(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ if (!strncmp(buf, "host", 4)) {
+ printk("s3c2410: changing usb to host\n");
+ s3c2410_modify_misccr(S3C2410_MISCCR_USBHOST,
+ S3C2410_MISCCR_USBHOST);
+ /* FIXME:
+ * - call machine-specific disable-pullup function i
+ * - enable +Vbus (if hardware supports it)
+ */
+ s3c2410_gpio_setpin(S3C2410_GPB9, 0);
+ } else if (!strncmp(buf, "device", 6)) {
+ printk("s3c2410: changing usb to device\n");
+ s3c2410_modify_misccr(S3C2410_MISCCR_USBHOST, 0);
+ s3c2410_gpio_setpin(S3C2410_GPB9, 1);
+ } else
+ printk("s3c2410: unknown mode\n");
+ return -EINVAL;
+ return count;
+}
+
+static DEVICE_ATTR(usb_mode, S_IRUGO | S_IWUSR, show_usb_mode, set_usb_mode);
+
/* may be called without controller electrically present */
/* may be called with controller, bus, and devices active */
@@ -325,6 +360,7 @@ static void s3c2410_hcd_oc(struct s3c2410_hcd_info *info, int port_oc)
static void
usb_hcd_s3c2410_remove (struct usb_hcd *hcd, struct platform_device *dev)
{
+ device_remove_file(&dev->dev, &dev_attr_usb_mode);
usb_remove_hcd(hcd);
s3c2410_stop_hc(dev);
iounmap(hcd->regs);
@@ -392,8 +428,15 @@ static int usb_hcd_s3c2410_probe (const struct hc_driver *driver,
if (retval != 0)
goto err_ioremap;
+ retval = device_create_file(&dev->dev, &dev_attr_usb_mode);
+ if (retval != 0)
+ goto err_hcd;
+
return 0;
+ err_hcd:
+ usb_remove_hcd(hcd);
+
err_ioremap:
s3c2410_stop_hc(dev);
iounmap(hcd->regs);
--
1.5.6.3

View file

@ -0,0 +1,46 @@
From 60018d983c0e7e8cc2f3b1669338b05c5b5356f8 Mon Sep 17 00:00:00 2001
From: mokopatches <mokopatches@openmoko.org>
Date: Fri, 25 Jul 2008 22:21:24 +0100
Subject: [PATCH] pnp_fixes.patch
---
drivers/pnp/Kconfig | 2 +-
drivers/pnp/resource.c | 2 ++
2 files changed, 3 insertions(+), 1 deletions(-)
diff --git a/drivers/pnp/Kconfig b/drivers/pnp/Kconfig
index 821933f..f9313cf 100644
--- a/drivers/pnp/Kconfig
+++ b/drivers/pnp/Kconfig
@@ -5,7 +5,7 @@
menuconfig PNP
bool "Plug and Play support"
depends on HAS_IOMEM
- depends on ISA || ACPI
+ depends on ISA || ACPI || SDIO
---help---
Plug and Play (PnP) is a standard for peripherals which allows those
peripherals to be configured by software, e.g. assign IRQ's or other
diff --git a/drivers/pnp/resource.c b/drivers/pnp/resource.c
index 390b500..3aabbf6 100644
--- a/drivers/pnp/resource.c
+++ b/drivers/pnp/resource.c
@@ -468,6 +468,7 @@ int pnp_check_dma(struct pnp_dev *dev, struct resource *res)
}
}
+#if 0
/* check if the resource is already in use, skip if the
* device is active because it itself may be in use */
if (!dev->active) {
@@ -475,6 +476,7 @@ int pnp_check_dma(struct pnp_dev *dev, struct resource *res)
return 0;
free_dma(*dma);
}
+#endif
/* check for conflicts with other pnp devices */
pnp_for_each_dev(tdev) {
--
1.5.6.3

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,30 @@
From 1b629ded094c800293cf694e85d0c5b66cc9fcfd Mon Sep 17 00:00:00 2001
From: mokopatches <mokopatches@openmoko.org>
Date: Fri, 25 Jul 2008 22:21:25 +0100
Subject: [PATCH] fix-hwecc-2410.patch
S3C24xx ECC mis-calculates the bit to flip:
http://lists.infradead.org/pipermail/linux-mtd/2007-October/019586.html
If the error couldn't be corrected, we returned "no problem" :-(
http://lists.infradead.org/pipermail/linux-mtd/2007-October/019615.html
Signed-off-by: Werner Almesberger <werner@openmoko.org>
---
drivers/mtd/nand/s3c2410.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/mtd/nand/s3c2410.c b/drivers/mtd/nand/s3c2410.c
index 8e1e482..4f747b1 100644
--- a/drivers/mtd/nand/s3c2410.c
+++ b/drivers/mtd/nand/s3c2410.c
@@ -406,7 +406,7 @@ static int s3c2410_nand_correct_data(struct mtd_info *mtd, u_char *dat,
if ((diff0 & ~(1<<fls(diff0))) == 0)
return 1;
- return -1;
+ return -EBADMSG;
}
/* ECC functions
--
1.5.6.3

View file

@ -0,0 +1,83 @@
From 835002d2e751c0d35b744ceec5bef726b9778b7b Mon Sep 17 00:00:00 2001
From: mokopatches <mokopatches@openmoko.org>
Date: Fri, 25 Jul 2008 22:21:25 +0100
Subject: [PATCH] fix-pcf50606-LOWBAT-kill-init.patch
---
drivers/i2c/chips/pcf50606.c | 53 ++++++++++++++++++++++++++++++++++++-----
1 files changed, 46 insertions(+), 7 deletions(-)
diff --git a/drivers/i2c/chips/pcf50606.c b/drivers/i2c/chips/pcf50606.c
index b530583..a1c92d3 100644
--- a/drivers/i2c/chips/pcf50606.c
+++ b/drivers/i2c/chips/pcf50606.c
@@ -654,8 +654,20 @@ static void pcf50606_work(struct work_struct *work)
if (pcf->onkey_seconds >=
pcf->pdata->onkey_seconds_required) {
/* Ask init to do 'ctrlaltdel' */
- DEBUGPC("SIGINT(init) ");
- kill_proc(1, SIGINT, 1);
+ /*
+ * currently Linux reacts badly to issuing a
+ * signal to PID #1 before init is started.
+ * What happens is that the next kernel thread
+ * to start, which is the JFFS2 Garbage
+ * collector in our case, gets the signal
+ * instead and proceeds to fail to fork --
+ * which is very bad. Therefore we confirm
+ * PID #1 exists before issuing the signal
+ */
+ if (find_task_by_pid(1)) {
+ kill_proc(1, SIGINT, 1);
+ DEBUGPC("SIGINT(init) ");
+ }
/* FIXME: what to do if userspace doesn't
* shut down? Do we want to force it? */
}
@@ -749,11 +761,38 @@ static void pcf50606_work(struct work_struct *work)
}
/* FIXME: TSCPRES */
if (pcfirq[2] & PCF50606_INT3_LOWBAT) {
- /* Really low battery voltage, we have 8 seconds left */
- DEBUGPC("LOWBAT ");
- apm_queue_event(APM_LOW_BATTERY);
- DEBUGPC("SIGPWR(init) ");
- kill_proc(1, SIGPWR, 1);
+ if (__reg_read(pcf, PCF50606_REG_OOCS) & PCF50606_OOCS_EXTON) {
+ /*
+ * hey no need to freak out, we have some kind of
+ * valid charger power
+ */
+ DEBUGPC("(NO)BAT ");
+ } else {
+ /* Really low battery voltage, we have 8 seconds left */
+ DEBUGPC("LOWBAT ");
+ /*
+ * currently Linux reacts badly to issuing a signal to
+ * PID #1 before init is started. What happens is that
+ * the next kernel thread to start, which is the JFFS2
+ * Garbage collector in our case, gets the signal
+ * instead and proceeds to fail to fork -- which is
+ * very bad. Therefore we confirm PID #1 exists
+ * before issuing SPIGPWR
+ */
+ if (find_task_by_pid(1)) {
+ apm_queue_event(APM_LOW_BATTERY);
+ DEBUGPC("SIGPWR(init) ");
+ kill_proc(1, SIGPWR, 1);
+ } else
+ /*
+ * well, our situation is like this: we do not
+ * have any external power, we have a low
+ * battery and since PID #1 doesn't exist yet,
+ * we are early in the boot, likely before
+ * rootfs mount. We should just call it a day
+ */
+ apm_queue_event(APM_CRITICAL_SUSPEND);
+ }
/* Tell PMU we are taking care of this */
reg_set_bit_mask(pcf, PCF50606_REG_OOCC1,
PCF50606_OOCC1_TOTRST,
--
1.5.6.3

View file

@ -0,0 +1,86 @@
From 6d3172ba9f1b4a650c8fdb3b6e11dc71852fe6d1 Mon Sep 17 00:00:00 2001
From: mokopatches <mokopatches@openmoko.org>
Date: Fri, 25 Jul 2008 22:21:25 +0100
Subject: [PATCH] fix-pcf50633-LOWBAT-kill-init.patch
---
drivers/i2c/chips/pcf50633.c | 56 ++++++++++++++++++++++++++++++++++++-----
1 files changed, 49 insertions(+), 7 deletions(-)
diff --git a/drivers/i2c/chips/pcf50633.c b/drivers/i2c/chips/pcf50633.c
index 0cf5e53..fc1262e 100644
--- a/drivers/i2c/chips/pcf50633.c
+++ b/drivers/i2c/chips/pcf50633.c
@@ -690,8 +690,20 @@ static void pcf50633_work(struct work_struct *work)
if (pcf->onkey_seconds >=
pcf->pdata->onkey_seconds_sig_init) {
/* Ask init to do 'ctrlaltdel' */
- DEBUGPC("SIGINT(init) ");
- kill_proc(1, SIGINT, 1);
+ /*
+ * currently Linux reacts badly to issuing a
+ * signal to PID #1 before init is started.
+ * What happens is that the next kernel thread
+ * to start, which is the JFFS2 Garbage
+ * collector in our case, gets the signal
+ * instead and proceeds to fail to fork --
+ * which is very bad. Therefore we confirm
+ * PID #1 exists before issuing the signal
+ */
+ if (find_task_by_pid(1)) {
+ DEBUGPC("SIGINT(init) ");
+ kill_proc(1, SIGINT, 1);
+ }
/* FIXME: what if userspace doesn't shut down? */
}
if (pcf->onkey_seconds >=
@@ -790,11 +802,41 @@ static void pcf50633_work(struct work_struct *work)
}
if (pcfirq[3] & (PCF50633_INT4_LOWBAT|PCF50633_INT4_LOWSYS)) {
- /* Really low battery voltage, we have 8 seconds left */
- DEBUGPC("LOWBAT ");
- apm_queue_event(APM_LOW_BATTERY);
- DEBUGPC("SIGPWR(init) ");
- kill_proc(1, SIGPWR, 1);
+ if ((__reg_read(pcf, PCF50633_REG_MBCS1) &
+ (PCF50633_MBCS1_USBPRES | PCF50633_MBCS1_USBOK)) ==
+ (PCF50633_MBCS1_USBPRES | PCF50633_MBCS1_USBOK)) {
+ /*
+ * hey no need to freak out, we have some kind of
+ * valid charger power
+ */
+ DEBUGPC("(NO)BAT ");
+ } else {
+ /* Really low battery voltage, we have 8 seconds left */
+ DEBUGPC("LOWBAT ");
+ /*
+ * currently Linux reacts badly to issuing a signal to
+ * PID #1 before init is started. What happens is that
+ * the next kernel thread to start, which is the JFFS2
+ * Garbage collector in our case, gets the signal
+ * instead and proceeds to fail to fork -- which is
+ * very bad. Therefore we confirm PID #1 exists
+ * before issuing SPIGPWR
+ */
+ if (find_task_by_pid(1)) {
+ apm_queue_event(APM_LOW_BATTERY);
+ DEBUGPC("SIGPWR(init) ");
+ kill_proc(1, SIGPWR, 1);
+ } else
+ /*
+ * well, our situation is like this: we do not
+ * have any external power, we have a low
+ * battery and since PID #1 doesn't exist yet,
+ * we are early in the boot, likely before
+ * rootfs mount. We should just call it a day
+ */
+ apm_queue_event(APM_CRITICAL_SUSPEND);
+ }
+
/* Tell PMU we are taking care of this */
reg_set_bit_mask(pcf, PCF50633_REG_OOCSHDWN,
PCF50633_OOCSHDWN_TOTRST,
--
1.5.6.3

View file

@ -0,0 +1,44 @@
From 2e7d18a213b94e4aeded7f35b7cd0d02b9b661cd Mon Sep 17 00:00:00 2001
From: mokopatches <mokopatches@openmoko.org>
Date: Fri, 25 Jul 2008 23:04:37 +0100
Subject: [PATCH] gta01-dehang-printk.patch
This is a temporary work-around Mike Westerhof for this bug:
http://bugzilla.openmoko.org/cgi-bin/bugzilla/show_bug.cgi?id=788
See also
http://lists.openmoko.org/pipermail/openmoko-kernel/2008-February/000804.html
(It's the 2nd option.)
We may settle on a different solution in the future, depending on
feedback from upstream.
---
drivers/serial/s3c2410.c | 9 +++++++++
1 files changed, 9 insertions(+), 0 deletions(-)
diff --git a/drivers/serial/s3c2410.c b/drivers/serial/s3c2410.c
index 7117110..bd87c79 100644
--- a/drivers/serial/s3c2410.c
+++ b/drivers/serial/s3c2410.c
@@ -1720,9 +1720,18 @@ static void
s3c24xx_serial_console_putchar(struct uart_port *port, int ch)
{
unsigned int ufcon = rd_regl(cons_uart, S3C2410_UFCON);
+ unsigned int umcon = rd_regl(cons_uart, S3C2410_UMCON);
+
+ /* If auto HW flow control enabled, temporarily turn it off */
+ if (umcon & S3C2410_UMCOM_AFC)
+ wr_regl(port, S3C2410_UMCON, (umcon & !S3C2410_UMCOM_AFC));
+
while (!s3c24xx_serial_console_txrdy(port, ufcon))
barrier();
wr_regb(cons_uart, S3C2410_UTXH, ch);
+
+ if (umcon & S3C2410_UMCOM_AFC)
+ wr_regl(port, S3C2410_UMCON, umcon);
}
static void
--
1.5.6.3

View file

@ -0,0 +1,98 @@
From a158085e182617f31960599ab1f468668c3161d4 Mon Sep 17 00:00:00 2001
From: mokopatches <mokopatches@openmoko.org>
Date: Fri, 25 Jul 2008 23:05:18 +0100
Subject: [PATCH] suspend-prelim1.patch
---
drivers/i2c/chips/pcf50633.c | 5 +++++
drivers/i2c/i2c-core.c | 13 ++++++++++++-
drivers/mfd/glamo/glamo-core.c | 2 ++
3 files changed, 19 insertions(+), 1 deletions(-)
diff --git a/drivers/i2c/chips/pcf50633.c b/drivers/i2c/chips/pcf50633.c
index fc1262e..e23c540 100644
--- a/drivers/i2c/chips/pcf50633.c
+++ b/drivers/i2c/chips/pcf50633.c
@@ -1901,6 +1901,9 @@ static int pcf50633_suspend(struct device *dev, pm_message_t state)
}
}
+ /* turn off the backlight */
+ __reg_write(pcf, PCF50633_REG_LEDENA, 0x00);
+
pcf->standby_regs.int1m = __reg_read(pcf, PCF50633_REG_INT1M);
pcf->standby_regs.int2m = __reg_read(pcf, PCF50633_REG_INT2M);
pcf->standby_regs.int3m = __reg_read(pcf, PCF50633_REG_INT3M);
@@ -1925,6 +1928,8 @@ static int pcf50633_resume(struct device *dev)
mutex_lock(&pcf->lock);
+ __reg_write(pcf, PCF50633_REG_LEDENA, 0x01);
+
/* Resume all saved registers that don't "survive" standby state */
__reg_write(pcf, PCF50633_REG_INT1M, pcf->standby_regs.int1m);
__reg_write(pcf, PCF50633_REG_INT2M, pcf->standby_regs.int2m);
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index bb0c5e5..c300975 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -1,4 +1,3 @@
-/* i2c-core.c - a device driver for the iic-bus interface */
/* ------------------------------------------------------------------------- */
/* Copyright (C) 1995-99 Simon G. Vogl
@@ -160,10 +159,16 @@ static int i2c_device_suspend(struct device * dev, pm_message_t mesg)
if (!dev->driver)
return 0;
+#if 0
driver = to_i2c_driver(dev->driver);
if (!driver->suspend)
return 0;
return driver->suspend(to_i2c_client(dev), mesg);
+#else
+ if (!dev->driver->suspend)
+ return 0;
+ return dev->driver->suspend(dev, mesg);
+#endif
}
static int i2c_device_resume(struct device * dev)
@@ -172,10 +177,16 @@ static int i2c_device_resume(struct device * dev)
if (!dev->driver)
return 0;
+#if 0
driver = to_i2c_driver(dev->driver);
if (!driver->resume)
return 0;
return driver->resume(to_i2c_client(dev));
+#else
+ if (!dev->driver->resume)
+ return 0;
+ return dev->driver->resume(dev);
+#endif
}
static void i2c_client_release(struct device *dev)
diff --git a/drivers/mfd/glamo/glamo-core.c b/drivers/mfd/glamo/glamo-core.c
index 8497de2..ffa4945 100644
--- a/drivers/mfd/glamo/glamo-core.c
+++ b/drivers/mfd/glamo/glamo-core.c
@@ -1125,11 +1125,13 @@ static int glamo_remove(struct platform_device *pdev)
#ifdef CONFIG_PM
static int glamo_suspend(struct platform_device *pdev, pm_message_t state)
{
+ glamo_power(glamo_handle, GLAMO_POWER_SUSPEND);
return 0;
}
static int glamo_resume(struct platform_device *pdev)
{
+ glamo_power(glamo_handle, GLAMO_POWER_ON);
return 0;
}
#else
--
1.5.6.3

View file

@ -0,0 +1,29 @@
From 4df411aa6f42be6fe5881d7b2fb88aae9d9a56a8 Mon Sep 17 00:00:00 2001
From: mokopatches <mokopatches@openmoko.org>
Date: Fri, 25 Jul 2008 23:05:21 +0100
Subject: [PATCH] gta02-sound-bandaid.patch
http://bugzilla.openmoko.org/cgi-bin/bugzilla/show_bug.cgi?id=1172
This patch seems to alleviate the symptoms but doesn't cure them.
Keep it to keep development going, until we have a proper solution.
---
sound/soc/codecs/wm8753.c | 3 +++
1 files changed, 3 insertions(+), 0 deletions(-)
diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c
index fb41826..72baf3d 100644
--- a/sound/soc/codecs/wm8753.c
+++ b/sound/soc/codecs/wm8753.c
@@ -1589,6 +1589,9 @@ static int wm8753_init(struct snd_soc_device *socdev)
schedule_delayed_work(&codec->delayed_work,
msecs_to_jiffies(caps_charge));
+ /* Fix reg WM8753_ADCTL2 */
+ wm8753_write(codec, WM8753_ADCTL2, 0x0000);
+
/* set the update bits */
reg = wm8753_read_reg_cache(codec, WM8753_LDAC);
wm8753_write(codec, WM8753_LDAC, reg | 0x0100);
--
1.5.6.3

View file

@ -0,0 +1,81 @@
From 08f211e0775ee1e29993fd072968e17a51c5ec14 Mon Sep 17 00:00:00 2001
From: mokopatches <mokopatches@openmoko.org>
Date: Fri, 25 Jul 2008 23:05:22 +0100
Subject: [PATCH] glamo-cmdqueue-bandaid.patch
[ Stop kernel from hanging every once in a while during Glamo
initialization. ]
debug-glamo-fb-cmdqueue-wait-timeout.patch
From: warmcat <andy@warmcat.com>
---
drivers/mfd/glamo/glamo-fb.c | 30 +++++++++++++++++++++++++++---
1 files changed, 27 insertions(+), 3 deletions(-)
diff --git a/drivers/mfd/glamo/glamo-fb.c b/drivers/mfd/glamo/glamo-fb.c
index 394a0ad..f0d7600 100644
--- a/drivers/mfd/glamo/glamo-fb.c
+++ b/drivers/mfd/glamo/glamo-fb.c
@@ -553,12 +553,20 @@ static inline int glamofb_cmdq_empty(struct glamofb_handle *gfb)
void glamofb_cmd_mode(struct glamofb_handle *gfb, int on)
{
+ int timeout = 2000;
+
dev_dbg(gfb->dev, "glamofb_cmd_mode(gfb=%p, on=%d)\n", gfb, on);
if (on) {
dev_dbg(gfb->dev, "%s: waiting for cmdq empty: ",
__FUNCTION__);
- while (!glamofb_cmdq_empty(gfb))
+ while ((!glamofb_cmdq_empty(gfb)) && (timeout--))
yield();
+ if (timeout < 0) {
+ printk(KERN_ERR"*************"
+ "glamofb cmd_queue never got empty"
+ "*************\n");
+ return;
+ }
dev_dbg(gfb->dev, "empty!\n");
/* display the entire frame then switch to command */
@@ -568,8 +576,16 @@ void glamofb_cmd_mode(struct glamofb_handle *gfb, int on)
/* wait until LCD is idle */
dev_dbg(gfb->dev, "waiting for LCD idle: ");
- while (!reg_read(gfb, GLAMO_REG_LCD_STATUS2) & (1 << 12))
+ timeout = 2000;
+ while ((!reg_read(gfb, GLAMO_REG_LCD_STATUS2) & (1 << 12)) &&
+ (timeout--))
yield();
+ if (timeout < 0) {
+ printk(KERN_ERR"*************"
+ "glamofb lcd never idle"
+ "*************\n");
+ return;
+ }
dev_dbg(gfb->dev, "idle!\n");
msleep(90);
@@ -589,10 +605,18 @@ EXPORT_SYMBOL_GPL(glamofb_cmd_mode);
int glamofb_cmd_write(struct glamofb_handle *gfb, u_int16_t val)
{
+ int timeout = 2000;
+
dev_dbg(gfb->dev, "%s: waiting for cmdq empty\n",
__FUNCTION__);
- while (!glamofb_cmdq_empty(gfb))
+ while ((!glamofb_cmdq_empty(gfb)) && (timeout--))
yield();
+ if (timeout < 0) {
+ printk(KERN_ERR"*************"
+ "glamofb cmd_queue never got empty"
+ "*************\n");
+ return 1;
+ }
dev_dbg(gfb->dev, "idle, writing 0x%04x\n", val);
reg_write(gfb, GLAMO_REG_LCD_COMMAND1, val);
--
1.5.6.3

View file

@ -0,0 +1,26 @@
From 38801452b334d3591eddadbfa4a31529b8957513 Mon Sep 17 00:00:00 2001
From: Andy Green <andy@openmoko.com>
Date: Fri, 25 Jul 2008 23:05:24 +0100
Subject: [PATCH] fix-wm8753-DBG.patch
Signed-off-by: Andy Green <andy@openmoko.com>
---
sound/soc/s3c24xx/neo1973_wm8753.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/sound/soc/s3c24xx/neo1973_wm8753.c b/sound/soc/s3c24xx/neo1973_wm8753.c
index 4ab6f63..2bc813f 100644
--- a/sound/soc/s3c24xx/neo1973_wm8753.c
+++ b/sound/soc/s3c24xx/neo1973_wm8753.c
@@ -671,7 +671,7 @@ static int __init neo1973_init(void)
{
int ret;
- DBG("Entered %s\n", __func__);
+ printk(KERN_DEBUG "Entered %s\n", __func__);
if (!machine_is_neo1973_gta01()) {
printk(KERN_INFO
--
1.5.6.3

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,53 @@
From bd559c9f37baa73f7220b8158909ce6d7264d4d3 Mon Sep 17 00:00:00 2001
From: warmcat <andy@warmcat.com>
Date: Fri, 25 Jul 2008 23:05:59 +0100
Subject: [PATCH] local-build-scripts.patch
Add a couple of handy scripts to crossmake and send over dfu
From: warmcat <andy@warmcat.com>
---
build | 14 ++++++++++++++
dfu-kern | 9 +++++++++
2 files changed, 23 insertions(+), 0 deletions(-)
create mode 100755 build
create mode 100755 dfu-kern
diff --git a/build b/build
new file mode 100755
index 0000000..7e61ea2
--- /dev/null
+++ b/build
@@ -0,0 +1,14 @@
+#!/bin/sh
+
+set -x
+
+export CROSS_COMPILE=../../cross/bin/arm-angstrom-linux-gnueabi-
+make ARCH=arm silentoldconfig
+if make -j5 ARCH=arm; then
+ ${CROSS_COMPILE}objcopy -O binary -R .note -R .comment -S arch/arm/boot/compressed/vmlinux linux.bin
+ mkimage -A arm -O linux -T kernel -C none -a 30008000 -e 30008000 -n "OpenMoko Kernel Image Neo1973(GTA02)" -d linux.bin uImage.bin
+ exit 0
+else
+ exit 1
+fi
+
diff --git a/dfu-kern b/dfu-kern
new file mode 100755
index 0000000..990abdd
--- /dev/null
+++ b/dfu-kern
@@ -0,0 +1,9 @@
+#!/bin/bash
+../../dfu-util/src/dfu-util -a 3 -d 0x1457:0x5119 -D uImage.bin
+if [ $? -eq 1 ] ; then
+../../dfu-util/src/dfu-util -a 3 -d 0x1457:0x5120 -D uImage.bin
+../../dfu-util/src/dfu-util -a 3 -d 0x1457:0x5119 -D uImage.bin
+
+fi
+
+
--
1.5.6.3

View file

@ -0,0 +1,31 @@
From 11b5692836d6e70af1da2acf4c61f45838b6be83 Mon Sep 17 00:00:00 2001
From: warmcat <andy@warmcat.com>
Date: Fri, 25 Jul 2008 23:05:59 +0100
Subject: [PATCH] local-build-new-dfu-vid.patch
Update to new DFU VID for A5
Signed-off-by: Andy Green <andy@openmoko.com>
---
dfu-kern | 6 +++---
1 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/dfu-kern b/dfu-kern
index 990abdd..b7ed2c3 100755
--- a/dfu-kern
+++ b/dfu-kern
@@ -1,8 +1,8 @@
#!/bin/bash
-../../dfu-util/src/dfu-util -a 3 -d 0x1457:0x5119 -D uImage.bin
+../../dfu-util/src/dfu-util -a 3 -d 0x1d50:0x5119 -D uImage.bin
if [ $? -eq 1 ] ; then
-../../dfu-util/src/dfu-util -a 3 -d 0x1457:0x5120 -D uImage.bin
-../../dfu-util/src/dfu-util -a 3 -d 0x1457:0x5119 -D uImage.bin
+../../dfu-util/src/dfu-util -a 3 -d 0x1d50:0x5120 -D uImage.bin
+../../dfu-util/src/dfu-util -a 3 -d 0x1d50:0x5119 -D uImage.bin
fi
--
1.5.6.3

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,72 @@
From 46b7ab304f0f5fcdfa1ab6d2034438928ab68f97 Mon Sep 17 00:00:00 2001
From: warmcat <andy@warmcat.com>
Date: Fri, 25 Jul 2008 23:05:59 +0100
Subject: [PATCH] local-config-add-vfat-nls-to-kern.patch
SD Card / VFAT in monolithic kernel
Signed-off-by: Andy Green <andy@openmoko.com>
---
defconfig-2.6.24 | 18 +++++++++---------
1 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/defconfig-2.6.24 b/defconfig-2.6.24
index 48644ac..b0ef327 100644
--- a/defconfig-2.6.24
+++ b/defconfig-2.6.24
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.24-rc6
-# Tue Jan 8 11:16:56 2008
+# Linux kernel version: 2.6.24-rc7
+# Sun Jan 13 21:40:55 2008
#
CONFIG_ARM=y
CONFIG_SYS_SUPPORTS_APM_EMULATION=y
@@ -1034,7 +1034,7 @@ CONFIG_SPI_MASTER=y
#
CONFIG_SPI_BITBANG=y
CONFIG_SPI_S3C24XX=y
-CONFIG_SPI_S3C24XX_GPIO=y
+# CONFIG_SPI_S3C24XX_GPIO is not set
#
# SPI Protocol Masters
@@ -1587,9 +1587,9 @@ CONFIG_JOLIET=y
#
# DOS/FAT/NT Filesystems
#
-CONFIG_FAT_FS=m
-CONFIG_MSDOS_FS=m
-CONFIG_VFAT_FS=m
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
CONFIG_FAT_DEFAULT_CODEPAGE=437
CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
# CONFIG_NTFS_FS is not set
@@ -1649,9 +1649,9 @@ CONFIG_CRAMFS=y
#
# CONFIG_PARTITION_ADVANCED is not set
CONFIG_MSDOS_PARTITION=y
-CONFIG_NLS=m
+CONFIG_NLS=y
CONFIG_NLS_DEFAULT="iso8859-1"
-CONFIG_NLS_CODEPAGE_437=m
+CONFIG_NLS_CODEPAGE_437=y
# CONFIG_NLS_CODEPAGE_737 is not set
# CONFIG_NLS_CODEPAGE_775 is not set
CONFIG_NLS_CODEPAGE_850=m
@@ -1675,7 +1675,7 @@ CONFIG_NLS_CODEPAGE_950=m
# CONFIG_NLS_CODEPAGE_1250 is not set
# CONFIG_NLS_CODEPAGE_1251 is not set
# CONFIG_NLS_ASCII is not set
-CONFIG_NLS_ISO8859_1=m
+CONFIG_NLS_ISO8859_1=y
# CONFIG_NLS_ISO8859_2 is not set
# CONFIG_NLS_ISO8859_3 is not set
# CONFIG_NLS_ISO8859_4 is not set
--
1.5.6.3

View file

@ -0,0 +1,44 @@
From 5e63b0173c4f096c43f9320c1ea910710b11eaad Mon Sep 17 00:00:00 2001
From: warmcat <andy@openmoko.com>
Date: Fri, 25 Jul 2008 23:05:59 +0100
Subject: [PATCH] local-config-add-bluetooth-monolithic.patch
Add Bluetooth in monolithic kernel
---
defconfig-2.6.24 | 10 ++--------
1 files changed, 2 insertions(+), 8 deletions(-)
diff --git a/defconfig-2.6.24 b/defconfig-2.6.24
index b0ef327..5b3e5e9 100644
--- a/defconfig-2.6.24
+++ b/defconfig-2.6.24
@@ -1275,16 +1275,10 @@ CONFIG_HID=y
#
# USB Input Devices
#
-CONFIG_USB_HID=m
+CONFIG_USB_HID=y
# CONFIG_USB_HIDINPUT_POWERBOOK is not set
# CONFIG_HID_FF is not set
# CONFIG_USB_HIDDEV is not set
-
-#
-# USB HID Boot Protocol drivers
-#
-# CONFIG_USB_KBD is not set
-# CONFIG_USB_MOUSE is not set
CONFIG_USB_SUPPORT=y
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
@@ -1306,7 +1300,7 @@ CONFIG_USB_PERSIST=y
# USB Host Controller Drivers
#
# CONFIG_USB_ISP116X_HCD is not set
-CONFIG_USB_OHCI_HCD=m
+CONFIG_USB_OHCI_HCD=y
# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
CONFIG_USB_OHCI_LITTLE_ENDIAN=y
--
1.5.6.3

View file

@ -0,0 +1,155 @@
From c21c82ef59cc77008ab05448ff001ae4a72396ba Mon Sep 17 00:00:00 2001
From: warmcat <andy@warmcat.com>
Date: Fri, 25 Jul 2008 23:05:59 +0100
Subject: [PATCH] local-config-wlan-config-changes.patch
---
defconfig-2.6.24 | 47 ++++++++++++++++++++++++++++++++---------------
1 files changed, 32 insertions(+), 15 deletions(-)
diff --git a/defconfig-2.6.24 b/defconfig-2.6.24
index 5b3e5e9..140fbfa 100644
--- a/defconfig-2.6.24
+++ b/defconfig-2.6.24
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.24-rc7
-# Sun Jan 13 21:40:55 2008
+# Linux kernel version: 2.6.24-rc8
+# Tue Jan 22 11:47:25 2008
#
CONFIG_ARM=y
CONFIG_SYS_SUPPORTS_APM_EMULATION=y
@@ -322,7 +322,7 @@ CONFIG_NET=y
#
# Networking options
#
-CONFIG_PACKET=m
+CONFIG_PACKET=y
CONFIG_PACKET_MMAP=y
CONFIG_UNIX=y
CONFIG_XFRM=y
@@ -595,20 +595,20 @@ CONFIG_NET_SCH_FIFO=y
# CONFIG_NET_PKTGEN is not set
# CONFIG_HAMRADIO is not set
# CONFIG_IRDA is not set
-CONFIG_BT=m
-CONFIG_BT_L2CAP=m
-CONFIG_BT_SCO=m
-CONFIG_BT_RFCOMM=m
+CONFIG_BT=y
+CONFIG_BT_L2CAP=y
+CONFIG_BT_SCO=y
+CONFIG_BT_RFCOMM=y
CONFIG_BT_RFCOMM_TTY=y
-CONFIG_BT_BNEP=m
+CONFIG_BT_BNEP=y
CONFIG_BT_BNEP_MC_FILTER=y
CONFIG_BT_BNEP_PROTO_FILTER=y
-CONFIG_BT_HIDP=m
+CONFIG_BT_HIDP=y
#
# Bluetooth device drivers
#
-CONFIG_BT_HCIUSB=m
+CONFIG_BT_HCIUSB=y
CONFIG_BT_HCIUSB_SCO=y
# CONFIG_BT_HCIBTSDIO is not set
# CONFIG_BT_HCIUART is not set
@@ -623,7 +623,7 @@ CONFIG_FIB_RULES=y
# Wireless
#
# CONFIG_CFG80211 is not set
-# CONFIG_WIRELESS_EXT is not set
+CONFIG_WIRELESS_EXT=y
# CONFIG_MAC80211 is not set
# CONFIG_IEEE80211 is not set
# CONFIG_RFKILL is not set
@@ -737,6 +737,13 @@ CONFIG_MTD_NAND_S3C2410_HWECC=y
#
# CONFIG_MTD_UBI is not set
# CONFIG_PARPORT is not set
+CONFIG_PNP=y
+CONFIG_PNP_DEBUG=y
+
+#
+# Protocols
+#
+# CONFIG_PNPACPI is not set
CONFIG_BLK_DEV=y
# CONFIG_BLK_DEV_COW_COMMON is not set
CONFIG_BLK_DEV_LOOP=m
@@ -814,9 +821,10 @@ CONFIG_NETDEVICES=y
# CONFIG_EQUALIZER is not set
CONFIG_TUN=m
# CONFIG_VETH is not set
+# CONFIG_NET_SB1000 is not set
# CONFIG_PHYLIB is not set
CONFIG_NET_ETHERNET=y
-CONFIG_MII=m
+CONFIG_MII=y
# CONFIG_AX88796 is not set
# CONFIG_SMC91X is not set
# CONFIG_DM9000 is not set
@@ -843,7 +851,7 @@ CONFIG_USB_CATC=m
CONFIG_USB_KAWETH=m
CONFIG_USB_PEGASUS=m
CONFIG_USB_RTL8150=m
-CONFIG_USB_USBNET=m
+CONFIG_USB_USBNET=y
CONFIG_USB_NET_AX8817X=m
CONFIG_USB_NET_CDCETHER=m
CONFIG_USB_NET_DM9601=m
@@ -1436,6 +1444,7 @@ CONFIG_USB_IOWARRIOR=m
CONFIG_USB_GADGET=y
# CONFIG_USB_GADGET_DEBUG is not set
# CONFIG_USB_GADGET_DEBUG_FILES is not set
+# CONFIG_USB_GADGET_DEBUG_FS is not set
CONFIG_USB_GADGET_SELECTED=y
# CONFIG_USB_GADGET_AMD5536UDC is not set
# CONFIG_USB_GADGET_ATMEL_USBA is not set
@@ -1459,6 +1468,14 @@ CONFIG_USB_ETH_RNDIS=y
# CONFIG_USB_FILE_STORAGE is not set
# CONFIG_USB_G_SERIAL is not set
# CONFIG_USB_MIDI_GADGET is not set
+
+#
+# SDIO support
+#
+CONFIG_SDIO=y
+CONFIG_SDIO_S3C24XX=y
+CONFIG_SDIO_S3C24XX_DMA=y
+CONFIG_SDIO_AR6000_WLAN=y
CONFIG_MMC=y
# CONFIG_MMC_DEBUG is not set
# CONFIG_MMC_UNSAFE_RESUME is not set
@@ -1475,7 +1492,6 @@ CONFIG_MMC_BLOCK=y
#
# CONFIG_MMC_SPI is not set
# CONFIG_MMC_S3C is not set
-CONFIG_MMC_GLAMO=y
CONFIG_NEW_LEDS=y
CONFIG_LEDS_CLASS=y
@@ -1554,6 +1570,7 @@ CONFIG_EXT3_FS=y
# CONFIG_EXT3_FS_XATTR is not set
# CONFIG_EXT4DEV_FS is not set
CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
# CONFIG_FS_POSIX_ACL is not set
@@ -1696,7 +1713,7 @@ CONFIG_ENABLE_WARN_DEPRECATED=y
CONFIG_ENABLE_MUST_CHECK=y
CONFIG_MAGIC_SYSRQ=y
# CONFIG_UNUSED_SYMBOLS is not set
-# CONFIG_DEBUG_FS is not set
+CONFIG_DEBUG_FS=y
# CONFIG_HEADERS_CHECK is not set
CONFIG_DEBUG_KERNEL=y
CONFIG_DEBUG_SHIRQ=y
--
1.5.6.3

View file

@ -0,0 +1,36 @@
From cdefa3c7722774152538c4ac5ea9290c441d6a4b Mon Sep 17 00:00:00 2001
From: warmcat <andy@openmoko.com>
Date: Fri, 25 Jul 2008 23:05:59 +0100
Subject: [PATCH] local-config-defconfig-motion-sensor-gpio.patch
---
defconfig-2.6.24 | 6 +++---
1 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/defconfig-2.6.24 b/defconfig-2.6.24
index 140fbfa..8b428b1 100644
--- a/defconfig-2.6.24
+++ b/defconfig-2.6.24
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
# Linux kernel version: 2.6.24-rc8
-# Tue Jan 22 11:47:25 2008
+# Wed Jan 23 10:00:57 2008
#
CONFIG_ARM=y
CONFIG_SYS_SUPPORTS_APM_EMULATION=y
@@ -1041,8 +1041,8 @@ CONFIG_SPI_MASTER=y
# SPI Master Controller Drivers
#
CONFIG_SPI_BITBANG=y
-CONFIG_SPI_S3C24XX=y
-# CONFIG_SPI_S3C24XX_GPIO is not set
+# CONFIG_SPI_S3C24XX is not set
+CONFIG_SPI_S3C24XX_GPIO=y
#
# SPI Protocol Masters
--
1.5.6.3

View file

@ -0,0 +1,34 @@
From cdb9d4e048f43bb19bd50713b88b1594ae60abf7 Mon Sep 17 00:00:00 2001
From: warmcat <andy@warmcat.com>
Date: Fri, 25 Jul 2008 23:06:00 +0100
Subject: [PATCH] local-config-pmu.patch
---
defconfig-2.6.24 | 4 +++-
1 files changed, 3 insertions(+), 1 deletions(-)
diff --git a/defconfig-2.6.24 b/defconfig-2.6.24
index 8b428b1..270c4f9 100644
--- a/defconfig-2.6.24
+++ b/defconfig-2.6.24
@@ -308,7 +308,7 @@ CONFIG_BINFMT_ELF=y
CONFIG_PM=y
CONFIG_PM_LEGACY=y
CONFIG_PM_DEBUG=y
-# CONFIG_PM_VERBOSE is not set
+CONFIG_PM_VERBOSE=y
CONFIG_PM_SLEEP=y
CONFIG_SUSPEND_UP_POSSIBLE=y
CONFIG_SUSPEND=y
@@ -1056,6 +1056,8 @@ CONFIG_POWER_SUPPLY_DEBUG=y
CONFIG_PDA_POWER=y
CONFIG_APM_POWER=y
# CONFIG_BATTERY_DS2760 is not set
+CONFIG_BATTERY_BQ27000_HDQ=y
+CONFIG_GTA02_HDQ=y
CONFIG_HWMON=y
# CONFIG_HWMON_VID is not set
# CONFIG_SENSORS_AD7418 is not set
--
1.5.6.3

View file

@ -0,0 +1,25 @@
From e2cf46fcd393bcba106d610fae6d0a56e646328b Mon Sep 17 00:00:00 2001
From: warmcat <andy@warmcat.com>
Date: Fri, 25 Jul 2008 23:06:00 +0100
Subject: [PATCH] local-config-ext2.patch
---
defconfig-2.6.24 | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/defconfig-2.6.24 b/defconfig-2.6.24
index 270c4f9..833e15e 100644
--- a/defconfig-2.6.24
+++ b/defconfig-2.6.24
@@ -1565,7 +1565,7 @@ CONFIG_RTC_DRV_S3C=m
#
# File systems
#
-CONFIG_EXT2_FS=m
+CONFIG_EXT2_FS=y
# CONFIG_EXT2_FS_XATTR is not set
# CONFIG_EXT2_FS_XIP is not set
CONFIG_EXT3_FS=y
--
1.5.6.3

View file

@ -0,0 +1,52 @@
diff --git a/drivers/i2c/chips/pcf50606.c b/drivers/i2c/chips/pcf50606.c
index a1c92d3..aaec6e8 100644
--- a/drivers/i2c/chips/pcf50606.c
+++ b/drivers/i2c/chips/pcf50606.c
@@ -72,12 +72,19 @@ static unsigned short normal_i2c[] = { 0x08, I2C_CLIENT_END };
I2C_CLIENT_INSMOD_1(pcf50606);
-#define PCF50606_F_CHG_FAST 0x00000001 /* Charger Fast allowed */
-#define PCF50606_F_CHG_PRESENT 0x00000002 /* Charger present */
-#define PCF50606_F_CHG_FOK 0x00000004 /* Fast OK for battery */
-#define PCF50606_F_CHG_ERR 0x00000008 /* Charger Error */
-#define PCF50606_F_CHG_PROT 0x00000010 /* Charger Protection */
-#define PCF50606_F_CHG_READY 0x00000020 /* Charging completed */
+#define PCF50606_B_CHG_FAST 0 /* Charger Fast allowed */
+#define PCF50606_B_CHG_PRESENT 1 /* Charger present */
+#define PCF50606_B_CHG_FOK 2 /* Fast OK for battery */
+#define PCF50606_B_CHG_ERR 3 /* Charger Error */
+#define PCF50606_B_CHG_PROT 4 /* Charger Protection */
+#define PCF50606_B_CHG_READY 5 /* Charging completed */
+
+#define PCF50606_F_CHG_FAST (1<<PCF50606_B_CHG_FAST) /* Charger Fast allowed */
+#define PCF50606_F_CHG_PRESENT (1<<PCF50606_B_CHG_PRESENT) /* Charger present */
+#define PCF50606_F_CHG_FOK (1<<PCF50606_B_CHG_FOK) /* Fast OK for battery */
+#define PCF50606_F_CHG_ERR (1<<PCF50606_B_CHG_ERR) /* Charger Error */
+#define PCF50606_F_CHG_PROT (1<<PCF50606_B_CHG_PROT) /* Charger Protection */
+#define PCF50606_F_CHG_READY (1<<PCF50606_B_CHG_READY) /* Charging completed */
#define PCF50606_F_CHG_MASK 0x000000fc
#define PCF50606_F_PWR_PRESSED 0x00000100
@@ -1087,12 +1094,12 @@ static ssize_t set_chgmode(struct device *dev, struct device_attribute *attr,
static DEVICE_ATTR(chgmode, S_IRUGO | S_IWUSR, show_chgmode, set_chgmode);
static const char *chgstate_names[] = {
- [PCF50606_F_CHG_FAST] = "fast_enabled",
- [PCF50606_F_CHG_PRESENT] = "present",
- [PCF50606_F_CHG_FOK] = "fast_ok",
- [PCF50606_F_CHG_ERR] = "error",
- [PCF50606_F_CHG_PROT] = "protection",
- [PCF50606_F_CHG_READY] = "ready",
+ [PCF50606_B_CHG_FAST] = "fast_enabled",
+ [PCF50606_B_CHG_PRESENT] = "present",
+ [PCF50606_B_CHG_FOK] = "fast_ok",
+ [PCF50606_B_CHG_ERR] = "error",
+ [PCF50606_B_CHG_PROT] = "protection",
+ [PCF50606_B_CHG_READY] = "ready",
};
static ssize_t show_chgstate(struct device *dev, struct device_attribute *attr,
--
1.5.6.3

View file

@ -0,0 +1,43 @@
From 25a9f8ef682fcc215a345202defb3884c2be080f Mon Sep 17 00:00:00 2001
From: warmcat <andy@openmoko.com>
Date: Fri, 25 Jul 2008 23:06:00 +0100
Subject: [PATCH] bugfix-deglitch-gpio-output-enable.patch
---
arch/arm/mach-s3c2440/mach-gta02.c | 10 ++++++++--
1 files changed, 8 insertions(+), 2 deletions(-)
diff --git a/arch/arm/mach-s3c2440/mach-gta02.c b/arch/arm/mach-s3c2440/mach-gta02.c
index 3816ea5..e32294b 100644
--- a/arch/arm/mach-s3c2440/mach-gta02.c
+++ b/arch/arm/mach-s3c2440/mach-gta02.c
@@ -1258,9 +1258,9 @@ static void __init gta02_machine_init(void)
s3c2410_gpio_setpin(GTA02_CHIP_PWD, 0);
break;
default:
- s3c2410_gpio_cfgpin(GTA02_GPIO_nWLAN_RESET, S3C2410_GPIO_OUTPUT);
/* Chip is in reset state */
s3c2410_gpio_setpin(GTA02_GPIO_nWLAN_RESET, 0);
+ s3c2410_gpio_cfgpin(GTA02_GPIO_nWLAN_RESET, S3C2410_GPIO_OUTPUT);
mdelay(100);
/* Power is up */
s3c2410_gpio_setpin(GTA02_CHIP_PWD, 0);
@@ -1300,8 +1300,14 @@ static void __init gta02_machine_init(void)
s3c2410_pm_init();
/* Set LCD_RESET / XRES to high */
- s3c2410_gpio_cfgpin(GTA01_GPIO_LCD_RESET, S3C2410_GPIO_OUTPUT);
s3c2410_gpio_setpin(GTA01_GPIO_LCD_RESET, 1);
+ s3c2410_gpio_cfgpin(GTA01_GPIO_LCD_RESET, S3C2410_GPIO_OUTPUT);
+
+ s3c2410_gpio_setpin(S3C2410_GPD12, 1);
+ s3c2410_gpio_cfgpin(S3C2410_GPD12, S3C2410_GPIO_OUTPUT);
+
+ s3c2410_gpio_setpin(S3C2410_GPD13, 1);
+ s3c2410_gpio_cfgpin(S3C2410_GPD13, S3C2410_GPIO_OUTPUT);
/* Make sure the modem can wake us up */
set_irq_type(GTA02_IRQ_MODEM, IRQT_RISING);
--
1.5.6.3

View file

@ -0,0 +1,31 @@
From 60e00c0c6a69c302d73093ccaf09697f94d6e7c2 Mon Sep 17 00:00:00 2001
From: warmcat <andy@openmoko.com>
Date: Fri, 25 Jul 2008 23:06:00 +0100
Subject: [PATCH] clean-snip-gpio-reinit.patch
These are initialized already
Signed-off-by: Andy Green <andy@openmoko.com>
---
arch/arm/mach-s3c2440/mach-gta02.c | 6 ------
1 files changed, 0 insertions(+), 6 deletions(-)
diff --git a/arch/arm/mach-s3c2440/mach-gta02.c b/arch/arm/mach-s3c2440/mach-gta02.c
index e32294b..f2b1b66 100644
--- a/arch/arm/mach-s3c2440/mach-gta02.c
+++ b/arch/arm/mach-s3c2440/mach-gta02.c
@@ -1303,12 +1303,6 @@ static void __init gta02_machine_init(void)
s3c2410_gpio_setpin(GTA01_GPIO_LCD_RESET, 1);
s3c2410_gpio_cfgpin(GTA01_GPIO_LCD_RESET, S3C2410_GPIO_OUTPUT);
- s3c2410_gpio_setpin(S3C2410_GPD12, 1);
- s3c2410_gpio_cfgpin(S3C2410_GPD12, S3C2410_GPIO_OUTPUT);
-
- s3c2410_gpio_setpin(S3C2410_GPD13, 1);
- s3c2410_gpio_cfgpin(S3C2410_GPD13, S3C2410_GPIO_OUTPUT);
-
/* Make sure the modem can wake us up */
set_irq_type(GTA02_IRQ_MODEM, IRQT_RISING);
rc = request_irq(GTA02_IRQ_MODEM, gta02_modem_irq, IRQF_DISABLED,
--
1.5.6.3

View file

@ -0,0 +1,87 @@
From 46f0b99a7b0e52e8dee4cdfe2e3599814f0388ed Mon Sep 17 00:00:00 2001
From: Andy Green <andy@openmoko.com>
Date: Fri, 25 Jul 2008 23:06:00 +0100
Subject: [PATCH] introduce-fiq-hdq.patch
This adds a platform driver and device which performs HDQ
battery protocol using a single GPIO pin which is set
through platform data.
HDQ has some hard latency requirements which can't
be met if interrupts are enabled, so normally using
a GPIO for this will require blocking out all other
interrupts and processes for several milliseconds
per register being read or written.
This HDQ protocol engine is a FSM implemented inside the
the FIQ ISR and regulated by timer interrupts happening
at 20us intervals. The path through the FSM on any
"clock" is very short and should be over with in ~
1us. Because FIQ has guaranteed latencies of <1us,
it means we can service the HDQ protocol without
blocking interrupts or any other process other than
the caller that is waiting for the result. It's pretty
cool performance from 1 GPIO ;-)
Due to it being hard to do locking from the FIQ ISR
the code simply sleeps 10ms or whatever the scheduler
gives it and checks if the transfer took place yet.
This platform driver doesn't have any knowledge about
the device it is talking to, it just knows it is a
HDQ device. It exports three functions for read, write
and confirming HDQ is initialized. It also exports two
/sys nodes that are usable by humans, one dumps the whole
127 register HDQ register space
# cat /sys/devices/platform/gta02-hdq.0/hdq/dump
00 44 55 00 00 00 ba 04 a2 0d 50 00 00 00 00 00
00 00 9a 1a 00 00 ff ff ff ff 29 00 00 00 80 2b
00 00 00 00 00 00 ff ff 00 00 00 00 00 32 af 06
a0 d8 37 4e 00 00 00 00 00 00 00 34 2e 03 b4 e7
00 00 06 00 41 00 4c 02 00 00 00 00 00 00 00 00
83 02 00 00 94 09 59 b9 a5 0d 7f 21 00 00 7a ff
df ff 62 ff a7 04 2e 05 00 00 00 01 00 07 00 00
2a 78 36 67 7b b5 1b a9 af 19 38 89 63 57 42 7c
#
and the other allows to set one register
# echo 2 170 > /sys/devices/platform/gta02-hdq.0/hdq/write
writes 0xAA into register 2.
Signed-off-by: Andy Green <andy@openmoko.com>
---
defconfig-2.6.24 | 1 +
drivers/power/Kconfig | 8 ++++++++
2 files changed, 9 insertions(+), 0 deletions(-)
diff --git a/defconfig-2.6.24 b/defconfig-2.6.24
index 833e15e..6d750a5 100644
--- a/defconfig-2.6.24
+++ b/defconfig-2.6.24
@@ -1825,3 +1825,4 @@ CONFIG_TEXTSEARCH_FSM=m
CONFIG_PLIST=y
CONFIG_HAS_IOMEM=y
CONFIG_HAS_DMA=y
+CONFIG_GTA02_HDQ=y
diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
index feb8b0a..5ace872 100644
--- a/drivers/power/Kconfig
+++ b/drivers/power/Kconfig
@@ -63,3 +63,11 @@ config GTA02_HDQ
at least BATTERY_BQ27000_HDQ as well
endif # POWER_SUPPLY
+
+config GTA02_HDQ
+ tristate "Neo Freerunner HDQ"
+ depends on MACH_NEO1973_GTA02 && FIQ && S3C2440_C_FIQ
+ help
+ Say Y to enable support for communicating with an HDQ battery
+ on the Neo Freerunner. You probably want to select
+ at least BATTERY_BQ27000_HDQ as well
--
1.5.6.3

View file

@ -0,0 +1,73 @@
From ee70eb69aca0855f8deea2d6792bca29f5f64c8d Mon Sep 17 00:00:00 2001
From: Andy Green <andy@openmoko.com>
Date: Fri, 25 Jul 2008 23:06:00 +0100
Subject: [PATCH] introduce-bq27000-battery-driver.patch
This is a driver for the bq27000 found in the Highcell A5
battery, and the platform device stuff for it for GTA02. It
is a Power Supply Class battery device.
The driver doesn't contain an HDQ engine but accepts pointers
from the platform data to the HDQ action routines; our
platform data plugs it into the FIQ HDQ engine stuff.
The Power Supply class exposes the battery down /sys so you
can find out battery status by doing the equivalent of this
bash command
for i in capacity charge_full current_now present status technology temp time_to_empty_now time_to_full_now type voltage_now ; do echo -n "$i " ; cat /sys/devices/platform/bq27000-battery.0/power_supply/bat/$i ; done
Here is the kind of result you get from a battery discharging
capacity 0
charge_full 1215585
current_now 183375
present 1
status Discharging
technology Li-ion
temp 276
time_to_empty_now 0
time_to_full_now 3932100
type Battery
voltage_now 2761000
Note that temp is in 1/10 degrees C, other values are in uV,
uA, uW. The time_to_* reported are bogus, but that is what
the battery actually reports.
We can make more mappings to entries in power_supply class
but this is enough to get started with.
Signed-off-by: Andy Green <andy@openmoko.com>
---
defconfig-2.6.24 | 1 +
drivers/power/Kconfig | 7 -------
2 files changed, 1 insertions(+), 7 deletions(-)
diff --git a/defconfig-2.6.24 b/defconfig-2.6.24
index 6d750a5..9467f4b 100644
--- a/defconfig-2.6.24
+++ b/defconfig-2.6.24
@@ -1826,3 +1826,4 @@ CONFIG_PLIST=y
CONFIG_HAS_IOMEM=y
CONFIG_HAS_DMA=y
CONFIG_GTA02_HDQ=y
+CONFIG_BATTERY_BQ27000_HDQ=y
diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
index 5ace872..8c50ecb 100644
--- a/drivers/power/Kconfig
+++ b/drivers/power/Kconfig
@@ -64,10 +64,3 @@ config GTA02_HDQ
endif # POWER_SUPPLY
-config GTA02_HDQ
- tristate "Neo Freerunner HDQ"
- depends on MACH_NEO1973_GTA02 && FIQ && S3C2440_C_FIQ
- help
- Say Y to enable support for communicating with an HDQ battery
- on the Neo Freerunner. You probably want to select
- at least BATTERY_BQ27000_HDQ as well
--
1.5.6.3

View file

@ -0,0 +1,452 @@
From c6eeaaf1c19526e7ceb535663c3b8143c19b8cc7 Mon Sep 17 00:00:00 2001
From: Andy Green <andy@openmoko.com>
Date: Fri, 25 Jul 2008 23:06:00 +0100
Subject: [PATCH] debug-suspend-dump-gpio-states-add-GPA.patch
Add support for GPA[] GPIO bus since we have some NCs
but they seem to output-only IO cells so no matter
Signed-off-by: Andy Green <andy@openmoko.com>
---
arch/arm/plat-s3c24xx/gpio.c | 421 ++++++++++++++++++++++++++++++++++++++++++
1 files changed, 421 insertions(+), 0 deletions(-)
diff --git a/arch/arm/plat-s3c24xx/gpio.c b/arch/arm/plat-s3c24xx/gpio.c
index ee99dcc..4e94801 100644
--- a/arch/arm/plat-s3c24xx/gpio.c
+++ b/arch/arm/plat-s3c24xx/gpio.c
@@ -32,6 +32,7 @@
#include <asm/io.h>
#include <asm/arch/regs-gpio.h>
+#include <asm/arch/regs-gpioj.h>
void s3c2410_gpio_cfgpin(unsigned int pin, unsigned int function)
{
@@ -215,3 +216,423 @@ int s3c2410_gpio_irq2pin(unsigned int irq)
}
EXPORT_SYMBOL(s3c2410_gpio_irq2pin);
+
+static void pretty_dump(u32 cfg, u32 state, u32 pull,
+ const char ** function_names_2,
+ const char ** function_names_3,
+ const char * prefix,
+ int count)
+{
+ int n;
+ const char *tag_type = NULL,
+ *tag_state = NULL,
+ *tag_pulldown = NULL,
+ * level0 = "0",
+ * level1 = "1";
+
+ for (n = 0; n < count; n++) {
+ switch ((cfg >> (2 * n)) & 3) {
+ case 0:
+ tag_type = "input ";
+ break;
+ case 1:
+ tag_type = "OUTPUT ";
+ break;
+ case 2:
+ if (function_names_2) {
+ if (function_names_2[n])
+ tag_type = function_names_2[n];
+ else
+ tag_type = "*** ILLEGAL CFG (2) *** ";
+ } else
+ tag_type = "(function) ";
+ break;
+ default:
+ if (function_names_3) {
+ if (function_names_3[n])
+ tag_type = function_names_3[n];
+ else
+ tag_type = "*** ILLEGAL CFG (3) *** ";
+ } else
+ tag_type = "(function) ";
+ break;
+ }
+ if ((state >> n) & 1)
+ tag_state = level1;
+ else
+ tag_state = level0;
+
+ if (((pull >> n) & 1))
+ tag_pulldown = "";
+ else
+ tag_pulldown = "(pulldown)";
+
+ printk(KERN_INFO"%s%02d: %s %s %s\n", prefix, n, tag_type,
+ tag_state, tag_pulldown);
+ }
+ printk(KERN_INFO"\n");
+}
+
+static void pretty_dump_a(u32 cfg, u32 state,
+ const char ** function_names,
+ const char * prefix,
+ int count)
+{
+ int n;
+ const char *tag_type = NULL,
+ *tag_state = NULL,
+ * level0 = "0",
+ * level1 = "1";
+
+ for (n = 0; n < count; n++) {
+ switch ((cfg >> n) & 1) {
+ case 0:
+ tag_type = "OUTPUT ";
+ break;
+ default:
+ if (function_names) {
+ if (function_names[n])
+ tag_type = function_names[n];
+ else
+ tag_type = "*** ILLEGAL CFG *** ";
+ } else
+ tag_type = "(function) ";
+ break;
+ }
+ if ((state >> n) & 1)
+ tag_state = level1;
+ else
+ tag_state = level0;
+
+ printk(KERN_INFO"%s%02d: %s %s\n", prefix, n, tag_type,
+ tag_state);
+ }
+ printk(KERN_INFO"\n");
+}
+
+static const char * funcs_a[] = {
+ "ADDR0 ",
+ "ADDR16 ",
+ "ADDR17 ",
+ "ADDR18 ",
+ "ADDR19 ",
+ "ADDR20 ",
+ "ADDR21 ",
+ "ADDR22 ",
+ "ADDR23 ",
+ "ADDR24 ",
+ "ADDR25 ",
+ "ADDR26 ",
+ "nGCS[1] ",
+ "nGCS[2] ",
+ "nGCS[3] ",
+ "nGCS[4] ",
+ "nGCS[5] ",
+ "CLE ",
+ "ALE ",
+ "nFWE ",
+ "nFRE ",
+ "nRSTOUT ",
+ "nFCE ",
+ NULL,
+ NULL
+};
+
+
+static const char * funcs_b2[] = {
+ "TOUT0 ",
+ "TOUT1 ",
+ "TOUT2 ",
+ "TOUT3 ",
+ "TCLK[0] ",
+ "nXBACK ",
+ "nXBREQ ",
+ "nXDACK1 ",
+ "nXDREQ1 ",
+ "nXDACK0 ",
+ "nXDREQ0 ",
+};
+static const char * funcs_b3[] = {
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+};
+
+static const char * funcs_c2[] = {
+ "LEND ",
+ "VCLK ",
+ "VLINE ",
+ "VFRAME ",
+ "VM ",
+ "LCD_LPCOE ",
+ "LCD_LPCREV ",
+ "LCD_LPCREVB",
+ "VD[0] ",
+ "VD[1] ",
+ "VD[2] ",
+ "VD[3] ",
+ "VD[4] ",
+ "VD[5] ",
+ "VD[6] ",
+ "VD[7] ",
+};
+static const char * funcs_c3[] = {
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "I2SSDI ",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+};
+
+static const char * funcs_d2[] = {
+ "VD[8] ",
+ "VD[9] ",
+ "VD[10] ",
+ "VD[11] ",
+ "VD[12] ",
+ "VD[13] ",
+ "VD[14] ",
+ "VD[15] ",
+ "VD[16] ",
+ "VD[17] ",
+ "VD[18] ",
+ "VD[19] ",
+ "VD[20] ",
+ "VD[21] ",
+ "VD[22] ",
+ "VD[23] ",
+};
+static const char * funcs_d3[] = {
+ "nSPICS1 ",
+ "SPICLK1 ",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "SPIMISO1 ",
+ "SPIMOSI1 ",
+ "SPICLK1 ",
+ NULL,
+ NULL,
+ NULL,
+ "nSS1 ",
+ "nSS0 ",
+};
+
+static const char * funcs_e2[] = {
+ "I2SLRCK ",
+ "I2SSCLK ",
+ "CDCLK ",
+ "I2SDI ",
+ "I2SDO ",
+ "SDCLK ",
+ "SDCMD ",
+ "SDDAT0 ",
+ "SDDAT1 ",
+ "SDDAT2 ",
+ "SDDAT3 ",
+ "SPIMISO0 ",
+ "SPIMOSI0 ",
+ "SPICLK0 ",
+ "IICSCL ",
+ "IICSDA ",
+};
+static const char * funcs_e3[] = {
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+};
+
+static const char * funcs_f2[] = {
+ "EINT[0] ",
+ "EINT[1] ",
+ "EINT[2] ",
+ "EINT[3] ",
+ "EINT[4] ",
+ "EINT[5] ",
+ "EINT[6] ",
+ "EINT[7] ",
+};
+static const char * funcs_f3[] = {
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+};
+
+
+static const char * funcs_g2[] = {
+ "EINT[8] ",
+ "EINT[9] ",
+ "EINT[10] ",
+ "EINT[11] ",
+ "EINT[12] ",
+ "EINT[13] ",
+ "EINT[14] ",
+ "EINT[15] ",
+ "EINT[16] ",
+ "EINT[17] ",
+ "EINT[18] ",
+ "EINT[19] ",
+ "EINT[20] ",
+ "EINT[21] ",
+ "EINT[22] ",
+ "EINT[23] ",
+};
+static const char * funcs_g3[] = {
+ NULL,
+ NULL,
+ "nSS0 ",
+ "nSS1 ",
+ "LCD_PWRDN ",
+ "SPIMISO1 ",
+ "SPIMOSI1 ",
+ "SPICLK1 ",
+ NULL,
+ "nRTS1 ",
+ "nCTS1 ",
+ "TCLK[1] ",
+ "nSPICS0 ",
+ NULL,
+ NULL,
+ NULL,
+};
+
+static const char * funcs_h2[] = {
+ "nCTS0 ",
+ "nRTS0 ",
+ "TXD[0] ",
+ "RXD[0] ",
+ "TXD[1] ",
+ "RXD[1] ",
+ "TXD[2] ",
+ "RXD[2] ",
+ "UEXTCLK ",
+ "CLKOUT0 ",
+ "CLKOUT1 ",
+};
+static const char * funcs_h3[] = {
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "nRTS1 ",
+ "nCTS1 ",
+ NULL,
+ "nSPICS0 ",
+ NULL,
+};
+
+static const char * funcs_j2[] = {
+ "CAMDATA[0] ",
+ "CAMDATA[1] ",
+ "CAMDATA[2] ",
+ "CAMDATA[3] ",
+ "CAMDATA[4] ",
+ "CAMDATA[5] ",
+ "CAMDATA[6] ",
+ "CAMDATA[7] ",
+ "CAMPCLK ",
+ "CAMVSYNC ",
+ "CAMHREF ",
+ "CAMCLKOUT ",
+ "CAMRESET ",
+};
+static const char * funcs_j3[] = {
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+};
+
+/* used to dump GPIO states at suspend */
+void s3c24xx_dump_gpio_states(void)
+{
+ pretty_dump_a(__raw_readl(S3C2410_GPACON),
+ __raw_readl(S3C2410_GPADAT),
+ funcs_a, "GPA", 25);
+ pretty_dump(__raw_readl(S3C2410_GPBCON),
+ __raw_readl(S3C2410_GPBDAT),
+ __raw_readl(S3C2410_GPBUP),
+ funcs_b2, funcs_b3, "GPB", 11);
+ pretty_dump(__raw_readl(S3C2410_GPCCON),
+ __raw_readl(S3C2410_GPCDAT),
+ __raw_readl(S3C2410_GPCUP),
+ funcs_c2, funcs_c3, "GPC", 16);
+ pretty_dump(__raw_readl(S3C2410_GPDCON),
+ __raw_readl(S3C2410_GPDDAT),
+ __raw_readl(S3C2410_GPDUP),
+ funcs_d2, funcs_d3, "GPD", 16);
+ pretty_dump(__raw_readl(S3C2410_GPECON),
+ __raw_readl(S3C2410_GPEDAT),
+ __raw_readl(S3C2410_GPEUP),
+ funcs_e2, funcs_e3, "GPE", 16);
+ pretty_dump(__raw_readl(S3C2410_GPFCON),
+ __raw_readl(S3C2410_GPFDAT),
+ __raw_readl(S3C2410_GPFUP),
+ funcs_f2, funcs_f3, "GPF", 8);
+ pretty_dump(__raw_readl(S3C2410_GPGCON),
+ __raw_readl(S3C2410_GPGDAT),
+ __raw_readl(S3C2410_GPGUP),
+ funcs_g2, funcs_g3, "GPG", 16);
+ pretty_dump(__raw_readl(S3C2410_GPHCON),
+ __raw_readl(S3C2410_GPHDAT),
+ __raw_readl(S3C2410_GPHUP),
+ funcs_h2, funcs_h3, "GPH", 11);
+ pretty_dump(__raw_readl(S3C2440_GPJCON),
+ __raw_readl(S3C2440_GPJDAT),
+ __raw_readl(S3C2440_GPJUP),
+ funcs_j2, funcs_j3, "GPJ", 13);
+
+}
+EXPORT_SYMBOL(s3c24xx_dump_gpio_states);
+
--
1.5.6.3

View file

@ -0,0 +1,128 @@
From 1da7d81ddc35e3527d10abbc411bc09c81340d70 Mon Sep 17 00:00:00 2001
From: warmcat <andy@warmcat.com>
Date: Fri, 25 Jul 2008 23:06:00 +0100
Subject: [PATCH] fix-s3c2410_timer_setup-resume-BUG.patch
---
arch/arm/plat-s3c24xx/time.c | 33 +++++++++++++++++++++++++++++++++
drivers/i2c/chips/pcf50633.c | 9 +++++++--
2 files changed, 40 insertions(+), 2 deletions(-)
diff --git a/arch/arm/plat-s3c24xx/time.c b/arch/arm/plat-s3c24xx/time.c
index f8d307b..59e5382 100644
--- a/arch/arm/plat-s3c24xx/time.c
+++ b/arch/arm/plat-s3c24xx/time.c
@@ -42,6 +42,7 @@
static unsigned long timer_startval;
static unsigned long timer_usec_ticks;
+static struct work_struct resume_work;
#define TIMER_USEC_SHIFT 16
@@ -199,9 +200,12 @@ static void s3c2410_timer_setup (void)
pclk = clk_get_rate(clk);
+ printk("pclk = %d\n", pclk);
+
/* configure clock tick */
timer_usec_ticks = timer_mask_usec_ticks(6, pclk);
+ printk("timer_usec_ticks = %d\n", timer_usec_ticks);
tcfg1 &= ~S3C2410_TCFG1_MUX4_MASK;
tcfg1 |= S3C2410_TCFG1_MUX4_DIV2;
@@ -210,6 +214,11 @@ static void s3c2410_timer_setup (void)
tcfg0 |= ((6 - 1) / 2) << S3C2410_TCFG_PRESCALER1_SHIFT;
tcnt = (pclk / 6) / HZ;
+
+ /* start the timer running */
+ tcon |= S3C2410_TCON_T4START | S3C2410_TCON_T4RELOAD;
+ tcon &= ~S3C2410_TCON_T4MANUALUPD;
+ __raw_writel(tcon, S3C2410_TCON);
}
/* timers reload after counting zero, so reduce the count by 1 */
@@ -245,10 +254,34 @@ static void s3c2410_timer_setup (void)
tcon |= S3C2410_TCON_T4START;
tcon &= ~S3C2410_TCON_T4MANUALUPD;
__raw_writel(tcon, S3C2410_TCON);
+
+ __raw_writel(__raw_readl(S3C2410_INTMSK) & (~(1UL << 14)),
+ S3C2410_INTMSK);
+
+}
+
+static void timer_resume_work(struct work_struct *work)
+{
+ s3c2410_timer_setup();
+}
+
+/* ooh a nasty situation arises if we try to call s3c2410_timer_setup() from
+ * the resume handler. It is called in atomic context but the clock APIs
+ * try to lock a mutex which may sleep. We are in a bit of an unusual
+ * situation because we don't have a tick source right now, but it should be
+ * okay to try to schedule a work item... hopefully
+ */
+
+static void s3c2410_timer_resume_atomic(void)
+{
+ int ret = schedule_work(&resume_work);
+ if (!ret)
+ printk(KERN_INFO"Failed to schedule_work tick ctr (%d)\n", ret);
}
static void __init s3c2410_timer_init (void)
{
+ INIT_WORK(&resume_work, timer_resume_work);
s3c2410_timer_setup();
setup_irq(IRQ_TIMER4, &s3c2410_timer_irq);
}
diff --git a/drivers/i2c/chips/pcf50633.c b/drivers/i2c/chips/pcf50633.c
index e23c540..91b9ac3 100644
--- a/drivers/i2c/chips/pcf50633.c
+++ b/drivers/i2c/chips/pcf50633.c
@@ -1926,9 +1926,11 @@ static int pcf50633_resume(struct device *dev)
struct pcf50633_data *pcf = i2c_get_clientdata(client);
int i;
- mutex_lock(&pcf->lock);
+ printk(KERN_INFO"a\n");
+ /* mutex_lock(&pcf->lock); */ /* resume in atomic context */
__reg_write(pcf, PCF50633_REG_LEDENA, 0x01);
+ printk(KERN_INFO"b\n");
/* Resume all saved registers that don't "survive" standby state */
__reg_write(pcf, PCF50633_REG_INT1M, pcf->standby_regs.int1m);
@@ -1936,6 +1938,7 @@ static int pcf50633_resume(struct device *dev)
__reg_write(pcf, PCF50633_REG_INT3M, pcf->standby_regs.int3m);
__reg_write(pcf, PCF50633_REG_INT4M, pcf->standby_regs.int4m);
__reg_write(pcf, PCF50633_REG_INT5M, pcf->standby_regs.int5m);
+ printk(KERN_INFO"c\n");
__reg_write(pcf, PCF50633_REG_OOCTIM2, pcf->standby_regs.ooctim2);
__reg_write(pcf, PCF50633_REG_AUTOOUT, pcf->standby_regs.autoout);
@@ -1949,14 +1952,16 @@ static int pcf50633_resume(struct device *dev)
__reg_write(pcf, PCF50633_REG_LEDOUT, pcf->standby_regs.ledout);
__reg_write(pcf, PCF50633_REG_LEDENA, pcf->standby_regs.ledena);
__reg_write(pcf, PCF50633_REG_LEDDIM, pcf->standby_regs.leddim);
+ printk(KERN_INFO"d\n");
/* FIXME: one big read? */
for (i = 0; i < 7; i++) {
u_int8_t reg_out = PCF50633_REG_LDO1OUT + 2*i;
__reg_write(pcf, reg_out, pcf->standby_regs.ldo[i].out);
__reg_write(pcf, reg_out+1, pcf->standby_regs.ldo[i].ena);
}
+ printk(KERN_INFO"e\n");
- mutex_unlock(&pcf->lock);
+ /* mutex_unlock(&pcf->lock); */ /* resume in atomic context */
pcf50633_irq(pcf->irq, pcf);
--
1.5.6.3

View file

@ -0,0 +1,97 @@
From eb890d62a201337536f18f8d2ea44df744155552 Mon Sep 17 00:00:00 2001
From: warmcat <andy@warmcat.com>
Date: Fri, 25 Jul 2008 23:06:01 +0100
Subject: [PATCH] config-add-alsa.patch
---
defconfig-2.6.24 | 34 +++++++++++++++++-----------------
1 files changed, 17 insertions(+), 17 deletions(-)
diff --git a/defconfig-2.6.24 b/defconfig-2.6.24
index 9467f4b..e57081a 100644
--- a/defconfig-2.6.24
+++ b/defconfig-2.6.24
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.24-rc8
-# Wed Jan 23 10:00:57 2008
+# Linux kernel version: 2.6.24
+# Fri Feb 22 22:38:48 2008
#
CONFIG_ARM=y
CONFIG_SYS_SUPPORTS_APM_EMULATION=y
@@ -22,6 +22,7 @@ CONFIG_RWSEM_GENERIC_SPINLOCK=y
CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_ZONE_DMA=y
+CONFIG_FIQ=y
CONFIG_VECTORS_BASE=0xffff0000
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
@@ -44,7 +45,7 @@ CONFIG_SYSVIPC_SYSCTL=y
# CONFIG_PID_NS is not set
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
-CONFIG_LOG_BUF_SHIFT=14
+CONFIG_LOG_BUF_SHIFT=16
# CONFIG_CGROUPS is not set
CONFIG_FAIR_GROUP_SCHED=y
CONFIG_FAIR_USER_SCHED=y
@@ -195,6 +196,7 @@ CONFIG_MACH_NEO1973_GTA01=y
# CONFIG_MACH_VSTMS is not set
CONFIG_CPU_S3C2440=y
CONFIG_S3C2440_DMA=y
+CONFIG_S3C2440_C_FIQ=y
#
# S3C2440 Machines
@@ -1221,15 +1223,15 @@ CONFIG_SOUND=y
#
# Advanced Linux Sound Architecture
#
-CONFIG_SND=m
-CONFIG_SND_TIMER=m
-CONFIG_SND_PCM=m
-CONFIG_SND_HWDEP=m
-CONFIG_SND_RAWMIDI=m
+CONFIG_SND=y
+CONFIG_SND_TIMER=y
+CONFIG_SND_PCM=y
+CONFIG_SND_HWDEP=y
+CONFIG_SND_RAWMIDI=y
# CONFIG_SND_SEQUENCER is not set
CONFIG_SND_OSSEMUL=y
-CONFIG_SND_MIXER_OSS=m
-CONFIG_SND_PCM_OSS=m
+CONFIG_SND_MIXER_OSS=y
+CONFIG_SND_PCM_OSS=y
CONFIG_SND_PCM_OSS_PLUGINS=y
# CONFIG_SND_DYNAMIC_MINORS is not set
CONFIG_SND_SUPPORT_OLD_API=y
@@ -1262,11 +1264,11 @@ CONFIG_SND_USB_AUDIO=m
#
# System on Chip audio support
#
-CONFIG_SND_SOC=m
-CONFIG_SND_S3C24XX_SOC=m
-CONFIG_SND_S3C24XX_SOC_I2S=m
-CONFIG_SND_S3C24XX_SOC_NEO1973_WM8753=m
-CONFIG_SND_S3C24XX_SOC_NEO1973_GTA02_WM8753=m
+CONFIG_SND_SOC=y
+CONFIG_SND_S3C24XX_SOC=y
+CONFIG_SND_S3C24XX_SOC_I2S=y
+CONFIG_SND_S3C24XX_SOC_NEO1973_WM8753=y
+CONFIG_SND_S3C24XX_SOC_NEO1973_GTA02_WM8753=y
#
# SoC Audio support for SuperH
@@ -1825,5 +1827,3 @@ CONFIG_TEXTSEARCH_FSM=m
CONFIG_PLIST=y
CONFIG_HAS_IOMEM=y
CONFIG_HAS_DMA=y
-CONFIG_GTA02_HDQ=y
-CONFIG_BATTERY_BQ27000_HDQ=y
--
1.5.6.3

View file

@ -0,0 +1,73 @@
From adeb466de3bb306dc68468c64be3ebc61960d788 Mon Sep 17 00:00:00 2001
From: Andy Green <andy@openmoko.com>
Date: Fri, 25 Jul 2008 23:06:01 +0100
Subject: [PATCH] fix-glamo-mci-defeat-ops-during-suspend.patch
We need to be able to use the config option CONFIG_MMC_UNSAFE_RESUME that allows the rootfs
to live on SD. But when we use this, it tries to send a reset command to the SD card during
suspend -- and unfortunately many things like Power have suspended by then.
This patch again rejects IO on the MMC device during suspend of the MMC device, and it
gives the result the rootfs on SD card works okay.
Signed-off-by: Andy Green <andy@openmoko.com>
---
drivers/mfd/glamo/glamo-mci.c | 14 ++++++++++++++
drivers/mfd/glamo/glamo-mci.h | 2 ++
2 files changed, 16 insertions(+), 0 deletions(-)
diff --git a/drivers/mfd/glamo/glamo-mci.c b/drivers/mfd/glamo/glamo-mci.c
index f559e5e..bbbbe4d 100644
--- a/drivers/mfd/glamo/glamo-mci.c
+++ b/drivers/mfd/glamo/glamo-mci.c
@@ -406,6 +406,14 @@ static void glamo_mci_send_request(struct mmc_host *mmc)
u16 status;
int n;
+ if (host->suspending) {
+ cmd->error = -EIO;
+ if (cmd->data)
+ cmd->data->error = -EIO;
+ mmc_request_done(mmc, mrq);
+ return;
+ }
+
host->ccnt++;
/*
* somehow 2.6.24 MCI manages to issue MMC_WRITE_BLOCK *without* the
@@ -792,6 +800,9 @@ static int glamo_mci_remove(struct platform_device *pdev)
static int glamo_mci_suspend(struct platform_device *dev, pm_message_t state)
{
struct mmc_host *mmc = platform_get_drvdata(dev);
+ struct glamo_mci_host *host = mmc_priv(mmc);
+
+ host->suspending++;
return mmc_suspend_host(mmc, state);
}
@@ -799,6 +810,9 @@ static int glamo_mci_suspend(struct platform_device *dev, pm_message_t state)
static int glamo_mci_resume(struct platform_device *dev)
{
struct mmc_host *mmc = platform_get_drvdata(dev);
+ struct glamo_mci_host *host = mmc_priv(mmc);
+
+ host->suspending--;
return mmc_resume_host(mmc);
}
diff --git a/drivers/mfd/glamo/glamo-mci.h b/drivers/mfd/glamo/glamo-mci.h
index 40c3e24..55852e7 100644
--- a/drivers/mfd/glamo/glamo-mci.h
+++ b/drivers/mfd/glamo/glamo-mci.h
@@ -34,6 +34,8 @@ struct glamo_mci_host {
int dma;
int data_max_size;
+ int suspending;
+
int power_mode_current;
unsigned int vdd_current;
--
1.5.6.3

View file

@ -0,0 +1,286 @@
From 3d71204efba10914e339b411471877b81cf1e5d9 Mon Sep 17 00:00:00 2001
From: warmcat <andy@warmcat.com>
Date: Fri, 25 Jul 2008 23:06:01 +0100
Subject: [PATCH] fix-lcm-reinit-post-resume.patch
---
arch/arm/mach-s3c2440/mach-gta02.c | 12 +++++++++
drivers/mfd/glamo/glamo-core.c | 15 ++++++++++-
drivers/mfd/glamo/glamo-spi-gpio.c | 38 ++++++++++++++++++++++++++--
drivers/video/display/jbt6k74.c | 47 ++++++++++++++++++++++++++++++++----
include/linux/glamofb.h | 1 +
include/linux/jbt6k74.h | 8 ++++++
6 files changed, 111 insertions(+), 10 deletions(-)
create mode 100644 include/linux/jbt6k74.h
diff --git a/arch/arm/mach-s3c2440/mach-gta02.c b/arch/arm/mach-s3c2440/mach-gta02.c
index f2b1b66..750fd97 100644
--- a/arch/arm/mach-s3c2440/mach-gta02.c
+++ b/arch/arm/mach-s3c2440/mach-gta02.c
@@ -76,6 +76,7 @@
#include <asm/plat-s3c24xx/cpu.h>
#include <asm/plat-s3c24xx/pm.h>
#include <asm/plat-s3c24xx/udc.h>
+#include <linux/jbt6k74.h>
#include <linux/glamofb.h>
@@ -756,10 +757,21 @@ static struct s3c2410_ts_mach_info gta02_ts_cfg = {
/* SPI: LCM control interface attached to Glamo3362 */
+void gta02_jbt6k74_reset(int devidx, int level)
+{
+ glamo_lcm_reset(level);
+}
+
+
+const struct jbt6k74_platform_data jbt6k74_pdata = {
+ .reset = gta02_jbt6k74_reset,
+};
+
static struct spi_board_info gta02_spi_board_info[] = {
{
.modalias = "jbt6k74",
/* platform_data */
+ .platform_data = &jbt6k74_pdata,
/* controller_data */
/* irq */
.max_speed_hz = 10 * 1000 * 1000,
diff --git a/drivers/mfd/glamo/glamo-core.c b/drivers/mfd/glamo/glamo-core.c
index ffa4945..2076e61 100644
--- a/drivers/mfd/glamo/glamo-core.c
+++ b/drivers/mfd/glamo/glamo-core.c
@@ -513,6 +513,17 @@ void glamo_engine_reset(struct glamo_core *glamo, enum glamo_engine engine)
}
EXPORT_SYMBOL_GPL(glamo_engine_reset);
+void glamo_lcm_reset(int level)
+{
+ if (!glamo_handle)
+ return;
+
+ glamo_gpio_setpin(glamo_handle, GLAMO_GPIO4, level);
+ glamo_gpio_cfgpin(glamo_handle, GLAMO_GPIO4_OUTPUT);
+
+}
+EXPORT_SYMBOL_GPL(glamo_lcm_reset);
+
enum glamo_pll {
GLAMO_PLL1,
GLAMO_PLL2,
@@ -1142,8 +1153,8 @@ static int glamo_resume(struct platform_device *pdev)
static struct platform_driver glamo_driver = {
.probe = glamo_probe,
.remove = glamo_remove,
- .suspend = glamo_suspend,
- .resume = glamo_resume,
+ .suspend_late = glamo_suspend,
+ .resume_early = glamo_resume,
.driver = {
.name = "glamo3362",
.owner = THIS_MODULE,
diff --git a/drivers/mfd/glamo/glamo-spi-gpio.c b/drivers/mfd/glamo/glamo-spi-gpio.c
index 73926bd..eda7322 100644
--- a/drivers/mfd/glamo/glamo-spi-gpio.c
+++ b/drivers/mfd/glamo/glamo-spi-gpio.c
@@ -224,14 +224,46 @@ static int glamo_spigpio_remove(struct platform_device *pdev)
return 0;
}
-#define glamo_spigpio_suspend NULL
+/*#define glamo_spigpio_suspend NULL
#define glamo_spigpio_resume NULL
+*/
+
+
+#ifdef CONFIG_PM
+static int glamo_spigpio_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ return 0;
+}
+
+static int glamo_spigpio_resume(struct platform_device *pdev)
+{
+ struct glamo_spigpio *sp = platform_get_drvdata(pdev);
+
+ if (!sp)
+ return 0;
+
+ /* set state of spi pins */
+ glamo_gpio_setpin(sp->glamo, sp->info->pin_clk, 0);
+ glamo_gpio_setpin(sp->glamo, sp->info->pin_mosi, 0);
+ glamo_gpio_setpin(sp->glamo, sp->info->pin_cs, 1);
+
+ glamo_gpio_cfgpin(sp->glamo, sp->info->pin_clk);
+ glamo_gpio_cfgpin(sp->glamo, sp->info->pin_mosi);
+ glamo_gpio_cfgpin(sp->glamo, sp->info->pin_cs);
+ if (sp->info->pin_miso)
+ glamo_gpio_cfgpin(sp->glamo, sp->info->pin_miso);
+
+ return 0;
+}
+#endif
static struct platform_driver glamo_spi_drv = {
.probe = glamo_spigpio_probe,
.remove = glamo_spigpio_remove,
- .suspend = glamo_spigpio_suspend,
- .resume = glamo_spigpio_resume,
+#ifdef CONFIG_PM
+ .suspend_late = glamo_spigpio_suspend,
+ .resume_early = glamo_spigpio_resume,
+#endif
.driver = {
.name = "glamo-spi-gpio",
.owner = THIS_MODULE,
diff --git a/drivers/video/display/jbt6k74.c b/drivers/video/display/jbt6k74.c
index d021d7e..d7e9442 100644
--- a/drivers/video/display/jbt6k74.c
+++ b/drivers/video/display/jbt6k74.c
@@ -27,6 +27,8 @@
#include <linux/device.h>
#include <linux/platform_device.h>
#include <linux/delay.h>
+#include <linux/workqueue.h>
+#include <linux/jbt6k74.h>
#include <linux/spi/spi.h>
@@ -114,11 +116,15 @@ struct jbt_info {
struct mutex lock; /* protects tx_buf and reg_cache */
u16 tx_buf[8];
u16 reg_cache[0xEE];
+ struct work_struct work;
};
#define JBT_COMMAND 0x000
#define JBT_DATA 0x100
+static void jbt_resume_work(struct work_struct *work);
+
+
static int jbt_reg_write_nodata(struct jbt_info *jbt, u8 reg)
{
int rc;
@@ -130,6 +136,9 @@ static int jbt_reg_write_nodata(struct jbt_info *jbt, u8 reg)
1*sizeof(u16));
if (rc == 0)
jbt->reg_cache[reg] = 0;
+ else
+ printk(KERN_ERR"jbt_reg_write_nodata spi_write ret %d\n",
+ rc);
mutex_unlock(&jbt->lock);
@@ -149,6 +158,8 @@ static int jbt_reg_write(struct jbt_info *jbt, u8 reg, u8 data)
2*sizeof(u16));
if (rc == 0)
jbt->reg_cache[reg] = data;
+ else
+ printk(KERN_ERR"jbt_reg_write spi_write ret %d\n", rc);
mutex_unlock(&jbt->lock);
@@ -169,6 +180,8 @@ static int jbt_reg_write16(struct jbt_info *jbt, u8 reg, u16 data)
3*sizeof(u16));
if (rc == 0)
jbt->reg_cache[reg] = data;
+ else
+ printk(KERN_ERR"jbt_reg_write16 spi_write ret %d\n", rc);
mutex_unlock(&jbt->lock);
@@ -563,6 +576,8 @@ static int __devinit jbt_probe(struct spi_device *spi)
if (!jbt)
return -ENOMEM;
+ INIT_WORK(&jbt->work, jbt_resume_work);
+
jbt->spi_dev = spi;
jbt->state = JBT_STATE_DEEP_STANDBY;
mutex_init(&jbt->lock);
@@ -618,28 +633,50 @@ static int __devexit jbt_remove(struct spi_device *spi)
static int jbt_suspend(struct spi_device *spi, pm_message_t state)
{
struct jbt_info *jbt = dev_get_drvdata(&spi->dev);
+ struct jbt6k74_platform_data *jbt6k74_pdata = spi->dev.platform_data;
/* Save mode for resume */
jbt->last_state = jbt->state;
jbt6k74_enter_state(jbt, JBT_STATE_DEEP_STANDBY);
+ (jbt6k74_pdata->reset)(0, 0);
+
return 0;
}
-static int jbt_resume(struct spi_device *spi)
+static void jbt_resume_work(struct work_struct *work)
{
- struct jbt_info *jbt = dev_get_drvdata(&spi->dev);
+ struct jbt_info *jbt = container_of(work, struct jbt_info, work);
+
+ printk(KERN_INFO"jbt_resume_work waiting...\n");
+ msleep(2000);
+ printk(KERN_INFO"jbt_resume_work GO...\n");
- jbt6k74_enter_state(jbt, jbt->last_state);
+ jbt6k74_enter_state(jbt, JBT_STATE_DEEP_STANDBY);
+ msleep(100);
switch (jbt->last_state) {
- case JBT_STATE_NORMAL:
case JBT_STATE_QVGA_NORMAL:
- jbt6k74_display_onoff(jbt, 1);
+ jbt6k74_enter_state(jbt, JBT_STATE_QVGA_NORMAL);
break;
default:
+ jbt6k74_enter_state(jbt, JBT_STATE_NORMAL);
break;
}
+ jbt6k74_display_onoff(jbt, 1);
+
+ printk(KERN_INFO"jbt_resume_work done...\n");
+}
+
+static int jbt_resume(struct spi_device *spi)
+{
+ struct jbt_info *jbt = dev_get_drvdata(&spi->dev);
+ struct jbt6k74_platform_data *jbt6k74_pdata = spi->dev.platform_data;
+
+ (jbt6k74_pdata->reset)(0, 1);
+
+ if (!schedule_work(&jbt->work))
+ dev_err(&spi->dev, "Unable to schedule LCM wakeup work\n");
return 0;
}
diff --git a/include/linux/glamofb.h b/include/linux/glamofb.h
index 24742a2..75eefef 100644
--- a/include/linux/glamofb.h
+++ b/include/linux/glamofb.h
@@ -35,5 +35,6 @@ struct glamofb_platform_data {
void glamofb_cmd_mode(struct glamofb_handle *gfb, int on);
int glamofb_cmd_write(struct glamofb_handle *gfb, u_int16_t val);
+void glamo_lcm_reset(int level);
#endif
diff --git a/include/linux/jbt6k74.h b/include/linux/jbt6k74.h
new file mode 100644
index 0000000..3fbe178
--- /dev/null
+++ b/include/linux/jbt6k74.h
@@ -0,0 +1,8 @@
+#ifndef __JBT6K74_H__
+#define __JBT6K74_H__
+
+struct jbt6k74_platform_data {
+ void (* reset)(int devindex, int level);
+};
+
+#endif
--
1.5.6.3

View file

@ -0,0 +1,141 @@
From f26eee35ae154c2be8a6e23f3e6a45f01f50f7a7 Mon Sep 17 00:00:00 2001
From: warmcat <andy@warmcat.com>
Date: Fri, 25 Jul 2008 23:06:01 +0100
Subject: [PATCH] fix-glamo-mci-fake-reset-opcode-in-suspend.patch
---
arch/arm/mach-s3c2440/mach-gta02.c | 4 ++--
drivers/mfd/glamo/glamo-core.c | 16 +++++++++-------
drivers/mfd/glamo/glamo-mci.c | 29 +++++++++++++++++++++--------
3 files changed, 32 insertions(+), 17 deletions(-)
diff --git a/arch/arm/mach-s3c2440/mach-gta02.c b/arch/arm/mach-s3c2440/mach-gta02.c
index 750fd97..f18c8fd 100644
--- a/arch/arm/mach-s3c2440/mach-gta02.c
+++ b/arch/arm/mach-s3c2440/mach-gta02.c
@@ -1281,6 +1281,8 @@ static void __init gta02_machine_init(void)
s3c2410_gpio_setpin(GTA02_GPIO_nWLAN_RESET, 1);
break;
}
+ mangle_glamo_res_by_system_rev();
+ platform_device_register(&gta02_glamo_dev);
platform_device_register(&s3c_device_spi_acc);
platform_device_register(&gta01_button_dev);
@@ -1291,8 +1293,6 @@ static void __init gta02_machine_init(void)
platform_device_register(&gta01_led_dev);
platform_device_register(&gta02_led_dev);
- mangle_glamo_res_by_system_rev();
- platform_device_register(&gta02_glamo_dev);
platform_device_register(&gta02_sdio_dev);
diff --git a/drivers/mfd/glamo/glamo-core.c b/drivers/mfd/glamo/glamo-core.c
index 2076e61..4d8e47f 100644
--- a/drivers/mfd/glamo/glamo-core.c
+++ b/drivers/mfd/glamo/glamo-core.c
@@ -822,6 +822,8 @@ static void glamo_power(struct glamo_core *glamo,
{
spin_lock(&glamo->lock);
+ dev_dbg(&glamo->pdev->dev, "***** glamo_power -> %d\n", new_state);
+
switch (new_state) {
case GLAMO_POWER_ON:
/* power up PLL1 and PLL2 */
@@ -1026,13 +1028,6 @@ static int __init glamo_probe(struct platform_device *pdev)
glamo_mci_def_pdata.glamo_irq_is_wired =
glamo->pdata->glamo_irq_is_wired;
- glamo_mmc_dev.dev.parent = &pdev->dev;
- /* we need it later to give to the engine enable and disable */
- glamo_mci_def_pdata.pglamo = glamo;
- mangle_mem_resources(glamo_mmc_dev.resource,
- glamo_mmc_dev.num_resources, glamo->mem);
- platform_device_register(&glamo_mmc_dev);
-
glamo_2d_dev.dev.parent = &pdev->dev;
mangle_mem_resources(glamo_2d_dev.resource,
glamo_2d_dev.num_resources, glamo->mem);
@@ -1065,6 +1060,13 @@ static int __init glamo_probe(struct platform_device *pdev)
glamo_spigpio_dev.dev.platform_data = glamo->pdata->spigpio_info;
platform_device_register(&glamo_spigpio_dev);
+ glamo_mmc_dev.dev.parent = &pdev->dev;
+ /* we need it later to give to the engine enable and disable */
+ glamo_mci_def_pdata.pglamo = glamo;
+ mangle_mem_resources(glamo_mmc_dev.resource,
+ glamo_mmc_dev.num_resources, glamo->mem);
+ platform_device_register(&glamo_mmc_dev);
+
/* only request the generic, hostbus and memory controller MMIO */
glamo->mem = request_mem_region(glamo->mem->start,
GLAMO_REGOFS_VIDCAP, "glamo-core");
diff --git a/drivers/mfd/glamo/glamo-mci.c b/drivers/mfd/glamo/glamo-mci.c
index bbbbe4d..d8847c5 100644
--- a/drivers/mfd/glamo/glamo-mci.c
+++ b/drivers/mfd/glamo/glamo-mci.c
@@ -405,11 +405,11 @@ static void glamo_mci_send_request(struct mmc_host *mmc)
u16 * reg_resp = (u16 *)(host->base + GLAMO_REG_MMC_CMD_RSP1);
u16 status;
int n;
+ int timeout = 100000000;
if (host->suspending) {
- cmd->error = -EIO;
- if (cmd->data)
- cmd->data->error = -EIO;
+ dev_err(&host->pdev->dev, "faking cmd %d "
+ "during suspend\n", cmd->opcode);
mmc_request_done(mmc, mrq);
return;
}
@@ -502,10 +502,23 @@ static void glamo_mci_send_request(struct mmc_host *mmc)
* our own INT# line"
*/
if (!glamo_mci_def_pdata.pglamo->irq_works) {
- /* we have faith we will get an "interrupt"... */
- while (!(readw_dly(glamo_mci_def_pdata.pglamo->base +
- GLAMO_REG_IRQ_STATUS) & GLAMO_IRQ_MMC))
+ /*
+ * we have faith we will get an "interrupt"...
+ * but something insane like suspend problems can mean
+ * we spin here forever, so we timeout after a LONG time
+ */
+ while ((!(readw_dly(glamo_mci_def_pdata.pglamo->base +
+ GLAMO_REG_IRQ_STATUS) & GLAMO_IRQ_MMC)) &&
+ (timeout--))
;
+
+ if (timeout < 0) {
+ if (cmd->data->error)
+ cmd->data->error = -ETIMEDOUT;
+ dev_err(&host->pdev->dev, "Payload timeout\n");
+ return;
+ }
+
/* yay we are an interrupt controller! -- call the ISR */
glamo_mci_irq(IRQ_GLAMO(GLAMO_IRQIDX_MMC),
irq_desc + IRQ_GLAMO(GLAMO_IRQIDX_MMC));
@@ -529,6 +542,7 @@ static void glamo_mci_request(struct mmc_host *mmc, struct mmc_request *mrq)
static void glamo_mci_reset(struct glamo_mci_host *host)
{
+ dev_dbg(&host->pdev->dev, "******* glamo_mci_reset\n");
/* reset MMC controller */
writew_dly(GLAMO_CLOCK_MMC_RESET | GLAMO_CLOCK_MMC_DG_TCLK |
GLAMO_CLOCK_MMC_EN_TCLK | GLAMO_CLOCK_MMC_DG_M9CLK |
@@ -803,8 +817,7 @@ static int glamo_mci_suspend(struct platform_device *dev, pm_message_t state)
struct glamo_mci_host *host = mmc_priv(mmc);
host->suspending++;
-
- return mmc_suspend_host(mmc, state);
+ return mmc_suspend_host(mmc, state);
}
static int glamo_mci_resume(struct platform_device *dev)
--
1.5.6.3

View file

@ -0,0 +1,51 @@
From 39f011b7788caa6800c5779eeb51f1877de9cfc4 Mon Sep 17 00:00:00 2001
From: Willie <willie_chen@openmoko.com>
Date: Fri, 25 Jul 2008 23:06:01 +0100
Subject: [PATCH] use gpio control leds
---
drivers/leds/leds-neo1973-gta02.c | 9 ++++-----
1 files changed, 4 insertions(+), 5 deletions(-)
diff --git a/drivers/leds/leds-neo1973-gta02.c b/drivers/leds/leds-neo1973-gta02.c
index bf1d540..e442e48 100644
--- a/drivers/leds/leds-neo1973-gta02.c
+++ b/drivers/leds/leds-neo1973-gta02.c
@@ -127,22 +127,22 @@ static int __init gta02led_probe(struct platform_device *pdev)
switch (lp->gpio) {
case S3C2410_GPB0:
- lp->has_pwm = 1;
+ lp->has_pwm = 0;
lp->pwm.timerid = PWM0;
s3c2410_gpio_cfgpin(lp->gpio, S3C2410_GPB0_TOUT0);
break;
case S3C2410_GPB1:
- lp->has_pwm = 1;
+ lp->has_pwm = 0;
lp->pwm.timerid = PWM1;
s3c2410_gpio_cfgpin(lp->gpio, S3C2410_GPB1_TOUT1);
break;
case S3C2410_GPB2:
- lp->has_pwm = 1;
+ lp->has_pwm = 0;
lp->pwm.timerid = PWM2;
s3c2410_gpio_cfgpin(lp->gpio, S3C2410_GPB2_TOUT2);
break;
case S3C2410_GPB3:
- lp->has_pwm = 1;
+ lp->has_pwm = 0;
lp->pwm.timerid = PWM3;
s3c2410_gpio_cfgpin(lp->gpio, S3C2410_GPB3_TOUT3);
break;
@@ -167,7 +167,6 @@ static int __init gta02led_probe(struct platform_device *pdev)
break;
default:
break;
- }
mutex_init(&lp->mutex);
rc = led_classdev_register(&pdev->dev, &lp->cdev);
--
1.5.6.3

View file

@ -0,0 +1,58 @@
From 3488a253e7a20d491d180313340f39cf6fd043a9 Mon Sep 17 00:00:00 2001
From: warmcat <andy@warmcat.com>
Date: Fri, 25 Jul 2008 23:06:01 +0100
Subject: [PATCH] fix-gpio-led-patch-still-pwm-t3.patch
Starting up all the PWMs seems to be needed for PWM3 operation
and FIQ / HDQ / VIB operation. But after starting, turn the
LEDs to GPIO-only.
Applies on top of Willie's patch
Signed-off-by: Andy Green <andy@openmoko.com>
---
drivers/leds/leds-neo1973-gta02.c | 9 +++++----
1 files changed, 5 insertions(+), 4 deletions(-)
diff --git a/drivers/leds/leds-neo1973-gta02.c b/drivers/leds/leds-neo1973-gta02.c
index e442e48..bf1d540 100644
--- a/drivers/leds/leds-neo1973-gta02.c
+++ b/drivers/leds/leds-neo1973-gta02.c
@@ -127,22 +127,22 @@ static int __init gta02led_probe(struct platform_device *pdev)
switch (lp->gpio) {
case S3C2410_GPB0:
- lp->has_pwm = 0;
+ lp->has_pwm = 1;
lp->pwm.timerid = PWM0;
s3c2410_gpio_cfgpin(lp->gpio, S3C2410_GPB0_TOUT0);
break;
case S3C2410_GPB1:
- lp->has_pwm = 0;
+ lp->has_pwm = 1;
lp->pwm.timerid = PWM1;
s3c2410_gpio_cfgpin(lp->gpio, S3C2410_GPB1_TOUT1);
break;
case S3C2410_GPB2:
- lp->has_pwm = 0;
+ lp->has_pwm = 1;
lp->pwm.timerid = PWM2;
s3c2410_gpio_cfgpin(lp->gpio, S3C2410_GPB2_TOUT2);
break;
case S3C2410_GPB3:
- lp->has_pwm = 0;
+ lp->has_pwm = 1;
lp->pwm.timerid = PWM3;
s3c2410_gpio_cfgpin(lp->gpio, S3C2410_GPB3_TOUT3);
break;
@@ -167,6 +167,7 @@ static int __init gta02led_probe(struct platform_device *pdev)
break;
default:
break;
+ }
mutex_init(&lp->mutex);
rc = led_classdev_register(&pdev->dev, &lp->cdev);
--
1.5.6.3

View file

@ -0,0 +1,167 @@
From a2f39c5197fbea18417722e5c7d362eaa3bc6210 Mon Sep 17 00:00:00 2001
From: Andy Green <andy@openmoko.com>
Date: Fri, 25 Jul 2008 23:06:01 +0100
Subject: [PATCH] introduce-usb-host-power-control.patch
Unless I really really missed the point, there is no support for enabling
USB Host power for USB host mode. This patch adds a /sys node for GTA02
that allows control of the charge pump for 5V out on the USB mini connector
It doesn't change any logical mode in the CPU, just enables (1) and disables
(0) USB host power.
# cat /sys/devices/platform/neo1973-pm-host.0/hostmode
0
# echo 1 > /sys/devices/platform/neo1973-pm-host.0/hostmode
Signed-off-by: Andy Green <andy@openmoko.com>
---
arch/arm/mach-s3c2440/mach-gta02.c | 6 ++
arch/arm/plat-s3c24xx/Makefile | 2 +-
arch/arm/plat-s3c24xx/neo1973_pm_host.c | 101 +++++++++++++++++++++++++++++++
3 files changed, 108 insertions(+), 1 deletions(-)
create mode 100644 arch/arm/plat-s3c24xx/neo1973_pm_host.c
diff --git a/arch/arm/mach-s3c2440/mach-gta02.c b/arch/arm/mach-s3c2440/mach-gta02.c
index f18c8fd..5bd68a6 100644
--- a/arch/arm/mach-s3c2440/mach-gta02.c
+++ b/arch/arm/mach-s3c2440/mach-gta02.c
@@ -1030,6 +1030,11 @@ static struct platform_device gta01_pm_gsm_dev = {
.name = "neo1973-pm-gsm",
};
+static struct platform_device gta02_pm_usbhost_dev = {
+ .name = "neo1973-pm-host",
+};
+
+
/* USB */
static struct s3c2410_hcd_info gta02_usb_info = {
.port[0] = {
@@ -1287,6 +1292,7 @@ static void __init gta02_machine_init(void)
platform_device_register(&s3c_device_spi_acc);
platform_device_register(&gta01_button_dev);
platform_device_register(&gta01_pm_gsm_dev);
+ platform_device_register(&gta02_pm_usbhost_dev);
mangle_pmu_pdata_by_system_rev();
platform_device_register(&gta02_pmu_dev);
diff --git a/arch/arm/plat-s3c24xx/Makefile b/arch/arm/plat-s3c24xx/Makefile
index 6f43aca..d58265f 100644
--- a/arch/arm/plat-s3c24xx/Makefile
+++ b/arch/arm/plat-s3c24xx/Makefile
@@ -29,4 +29,4 @@ obj-$(CONFIG_PM) += pm.o
obj-$(CONFIG_PM) += sleep.o
obj-$(CONFIG_S3C2410_DMA) += dma.o
obj-$(CONFIG_MACH_SMDK) += common-smdk.o
-obj-$(CONFIG_MACH_NEO1973) += neo1973_pm_gsm.o neo1973_pm_gps.o neo1973_pm_bt.o
+obj-$(CONFIG_MACH_NEO1973) += neo1973_pm_host.o neo1973_pm_gsm.o neo1973_pm_gps.o neo1973_pm_bt.o
diff --git a/arch/arm/plat-s3c24xx/neo1973_pm_host.c b/arch/arm/plat-s3c24xx/neo1973_pm_host.c
new file mode 100644
index 0000000..4eae341
--- /dev/null
+++ b/arch/arm/plat-s3c24xx/neo1973_pm_host.c
@@ -0,0 +1,101 @@
+/*
+ * Bluetooth PM code for the FIC Neo1973 GSM Phone
+ *
+ * (C) 2007 by OpenMoko Inc.
+ * Author: Harald Welte <laforge@openmoko.org>
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+
+#ifdef CONFIG_MACH_NEO1973_GTA02
+#include <asm/arch/gta02.h>
+#include <linux/pcf50633.h>
+
+static ssize_t pm_host_read(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ return sprintf(buf, "%d\n",
+ pcf50633_gpio_get(pcf50633_global, PCF50633_GPO));
+}
+
+static ssize_t pm_host_write(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned long on = simple_strtoul(buf, NULL, 10);
+
+ pcf50633_gpio_set(pcf50633_global, PCF50633_GPO, on);
+
+ return count;
+}
+
+static DEVICE_ATTR(hostmode, 0644, pm_host_read, pm_host_write);
+
+static struct attribute *neo1973_pm_host_sysfs_entries[] = {
+ &dev_attr_hostmode.attr,
+ NULL
+};
+
+static struct attribute_group neo1973_pm_host_attr_group = {
+ .name = NULL,
+ .attrs = neo1973_pm_host_sysfs_entries,
+};
+
+static int __init neo1973_pm_host_probe(struct platform_device *pdev)
+{
+ dev_info(&pdev->dev, "starting\n");
+
+ switch (machine_arch_type) {
+#ifdef CONFIG_MACH_NEO1973_GTA01
+ case MACH_TYPE_NEO1973_GTA01:
+ return -EINVAL;
+#endif /* CONFIG_MACH_NEO1973_GTA01 */
+ default:
+ break;
+ }
+
+ return sysfs_create_group(&pdev->dev.kobj, &neo1973_pm_host_attr_group);
+}
+
+static int neo1973_pm_host_remove(struct platform_device *pdev)
+{
+ sysfs_remove_group(&pdev->dev.kobj, &neo1973_pm_host_attr_group);
+ return 0;
+}
+
+static struct platform_driver neo1973_pm_host_driver = {
+ .probe = neo1973_pm_host_probe,
+ .remove = neo1973_pm_host_remove,
+ .driver = {
+ .name = "neo1973-pm-host",
+ },
+};
+
+static int __devinit neo1973_pm_host_init(void)
+{
+ return platform_driver_register(&neo1973_pm_host_driver);
+}
+
+static void neo1973_pm_host_exit(void)
+{
+ platform_driver_unregister(&neo1973_pm_host_driver);
+}
+
+module_init(neo1973_pm_host_init);
+module_exit(neo1973_pm_host_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Andy Green <andy@openmoko.com>");
+MODULE_DESCRIPTION("Neo1973 USB Host Power Management");
+#endif
--
1.5.6.3

View file

@ -0,0 +1,36 @@
From f78f3a4decb7e67b5349a2c088449342398d2114 Mon Sep 17 00:00:00 2001
From: Andy Green <andy@openmoko.com>
Date: Fri, 25 Jul 2008 23:06:01 +0100
Subject: [PATCH] fix-charging-deassert-host-power-1a-detect.patch
We don't take care to stop driving generated USB host power even
when we have a 1A charger connected on the same pins.
Signed-off-by: Andy Green <andy@openmoko.com>
---
drivers/i2c/chips/pcf50633.c | 9 +++++++++
1 files changed, 9 insertions(+), 0 deletions(-)
diff --git a/drivers/i2c/chips/pcf50633.c b/drivers/i2c/chips/pcf50633.c
index 91b9ac3..c14fad0 100644
--- a/drivers/i2c/chips/pcf50633.c
+++ b/drivers/i2c/chips/pcf50633.c
@@ -523,6 +523,15 @@ static void configure_pmu_for_charger(struct pcf50633_data *pcf,
break;
case CHARGER_TYPE_1A:
__reg_write(pcf, PCF50633_REG_MBCC7, PCF50633_MBCC7_USB_1000mA);
+ /*
+ * stop GPO / EN_HOSTUSB power driving out on the same
+ * USB power pins we have a 1A charger on right now!
+ */
+ dev_info(&pcf->client.dev, "Charger -> CHARGER_TYPE_1A\n");
+ __reg_write(pcf, PCF50633_GPO - PCF50633_GPIO1 +
+ PCF50633_REG_GPIO1CFG,
+ __reg_read(pcf, PCF50633_GPO - PCF50633_GPIO1 +
+ PCF50633_REG_GPIO1CFG) & 0xf0);
break;
}
}
--
1.5.6.3

Some files were not shown because too many files have changed in this diff Show more