changed Makefile and profiles, added patches for kernel 2.6.24 (stable-branch of Openmoko)

SVN-Revision: 13613
This commit is contained in:
Mirko Vogt 2008-12-12 11:58:53 +00:00
parent 4a018d2445
commit 614683faf8
589 changed files with 178974 additions and 18 deletions

View file

@ -20,6 +20,5 @@ define Target/Description
endef endef
include $(INCLUDE_DIR)/target.mk include $(INCLUDE_DIR)/target.mk
DEFAULT_PACKAGES += xglamo enlightenment
$(eval $(call BuildTarget)) $(eval $(call BuildTarget))

View file

@ -0,0 +1,597 @@
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_MXC is not set
# CONFIG_ARCH_NETX is not set
# CONFIG_ARCH_NS9XXX is not set
# CONFIG_ARCH_OMAP 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_MSI is not set
# CONFIG_ARCH_VERSATILE is not set
CONFIG_ARM=y
CONFIG_ARM_THUMB=y
# CONFIG_ARPD is not set
# CONFIG_ATM is not set
CONFIG_AUTOFS4_FS=m
CONFIG_BACKLIGHT_CLASS_DEVICE=y
# CONFIG_BACKLIGHT_CORGI is not set
CONFIG_BACKLIGHT_LCD_SUPPORT=y
CONFIG_BASE_SMALL=0
# CONFIG_BATTERY_DS2760 is not set
# CONFIG_BINFMT_AOUT is not set
CONFIG_BITREVERSE=y
# CONFIG_BLK_DEV_CRYPTOLOOP is not set
# CONFIG_BLK_DEV_NBD is not set
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=4096
CONFIG_BLK_DEV_SR=m
# CONFIG_BLK_DEV_SR_VENDOR is not set
CONFIG_BLK_DEV_UB=m
# CONFIG_BONDING is not set
# CONFIG_BOOT_PRINTK_DELAY is not set
CONFIG_BOUNCE=y
# CONFIG_BRIDGE is not set
# CONFIG_BSD_PROCESS_ACCT is not set
# 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_HCIVHCI is not set
CONFIG_CHR_DEV_SG=m
# CONFIG_CIFS_STATS is not set
CONFIG_CIFS_WEAK_PW_HASH=y
CONFIG_CMDLINE="unused -- bootloader passes ATAG list"
CONFIG_CONFIGFS_FS=m
CONFIG_CONNECTOR=m
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_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_CRAMFS=y
# CONFIG_CRC_ITU_T is not set
CONFIG_CRYPTO_ALGAPI=y
CONFIG_CRYPTO_BLKCIPHER=y
CONFIG_CRYPTO_CBC=y
CONFIG_CRYPTO_DES=y
CONFIG_CRYPTO_FCRYPT=m
CONFIG_CRYPTO_GF128MUL=m
CONFIG_CRYPTO_HASH=y
CONFIG_CRYPTO_HMAC=y
CONFIG_CRYPTO_HW=y
CONFIG_CRYPTO_LRW=m
CONFIG_CRYPTO_MANAGER=y
CONFIG_CRYPTO_MD5=y
CONFIG_CRYPTO_PCBC=m
CONFIG_CRYPTO_XCBC=m
CONFIG_DAB=y
CONFIG_DEBUG_BUGVERBOSE=y
# CONFIG_DEBUG_DEVRES is not set
# CONFIG_DEBUG_DRIVER is not set
CONFIG_DEBUG_ERRORS=y
CONFIG_DEBUG_INFO=y
CONFIG_DEBUG_KERNEL=y
# CONFIG_DEBUG_KOBJECT is not set
# CONFIG_DEBUG_LIST is not set
# CONFIG_DEBUG_LL is not set
# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
# CONFIG_DEBUG_LOCK_ALLOC is not set
# CONFIG_DEBUG_MUTEXES is not set
CONFIG_DEBUG_PREEMPT=y
# CONFIG_DEBUG_RT_MUTEXES is not set
CONFIG_DEBUG_S3C_UART=2
# CONFIG_DEBUG_SG is not set
# CONFIG_DEBUG_SHIRQ is not set
# CONFIG_DEBUG_SLAB is not set
# CONFIG_DEBUG_SPINLOCK is not set
# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
# CONFIG_DEBUG_USER is not set
# CONFIG_DEBUG_VM is not set
CONFIG_DEFAULT_TCP_CONG="cubic"
CONFIG_DETECT_SOFTLOCKUP=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_MUST_CHECK=y
CONFIG_EXT2_FS=y
CONFIG_EXT3_FS=y
CONFIG_FAT_FS=y
# CONFIG_FAULT_INJECTION is not set
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_DEFERRED_IO=y
# 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_UVESA is not set
# CONFIG_FB_VIRTUAL is not set
# 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_FORCED_INLINING=y
# 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_FS_POSIX_ACL=y
CONFIG_FUSE_FS=m
CONFIG_FW_LOADER=m
# CONFIG_GENERIC_CLOCKEVENTS is not set
CONFIG_GENERIC_GPIO=y
# CONFIG_GENERIC_TIME is not set
# CONFIG_HAMRADIO is not set
CONFIG_HARDIRQS_SW_RESEND=y
CONFIG_HAS_DMA=y
CONFIG_HAS_IOMEM=y
# CONFIG_HFSPLUS_FS is not set
# CONFIG_HFS_FS is not set
CONFIG_HID=y
CONFIG_HID_SUPPORT=y
CONFIG_HW_CONSOLE=y
# CONFIG_HW_RANDOM is not set
CONFIG_HZ=200
CONFIG_I2C=y
# CONFIG_I2C_ALGOBIT is not set
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_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
CONFIG_INITRAMFS_SOURCE=""
CONFIG_INOTIFY=y
CONFIG_INOTIFY_USER=y
CONFIG_INPUT=y
CONFIG_INPUT_EVDEV=y
# CONFIG_INPUT_GPIO_BUTTONS is not set
CONFIG_INPUT_KEYBOARD=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_INSTRUMENTATION=y
CONFIG_IOSCHED_AS=m
CONFIG_IOSCHED_CFQ=m
# CONFIG_IP6_NF_QUEUE is not set
# CONFIG_IP6_NF_RAW is not set
# CONFIG_IPV6_ROUTER_PREF is not set
CONFIG_IPV6_TUNNEL=m
# CONFIG_IP_NF_ARPTABLES is not set
# 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_CLUSTERIP=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_JBD=y
# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_ALL is not set
CONFIG_KEXEC=y
# CONFIG_KEYBOARD_ATKBD is not set
CONFIG_KEYBOARD_GPIO=m
# CONFIG_KEYBOARD_LKKBD is not set
# CONFIG_KEYBOARD_NEWTON is not set
CONFIG_KEYBOARD_STOWAWAY=m
# CONFIG_KEYBOARD_SUNKBD is not set
# CONFIG_KEYBOARD_XTKBD is not set
CONFIG_KMOD=y
CONFIG_LCD_CLASS_DEVICE=y
# CONFIG_LCD_LTV350QV is not set
CONFIG_LEDS_S3C24XX=m
# CONFIG_LEDS_TRIGGER_HEARTBEAT is not set
# CONFIG_LLC2 is not set
CONFIG_LOCKD=y
CONFIG_LOCK_KERNEL=y
# CONFIG_LOCK_STAT is not set
# CONFIG_LOGO is not set
# CONFIG_MACH_AML_M5900 is not set
# CONFIG_MACH_ANUBIS is not set
# CONFIG_MACH_N30 is not set
# 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_VR1000 is not set
# CONFIG_MACH_VSTMS is not set
CONFIG_MAGIC_SYSRQ=y
# CONFIG_MARKERS is not set
# CONFIG_MINIX_FS is not set
CONFIG_MMC=y
CONFIG_MMC_BLOCK=y
CONFIG_MMC_BLOCK_BOUNCE=y
# CONFIG_MMC_DEBUG is not set
# 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 is not set
# 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=0x8000000
# CONFIG_MTD_PLATRAM is not set
# CONFIG_MTD_RAM is not set
# CONFIG_MTD_REDBOOT_PARTS is not set
# CONFIG_MTD_ROM is not set
# CONFIG_MTD_SLRAM is not set
CONFIG_NETFILTER_NETLINK=m
CONFIG_NETFILTER_NETLINK_LOG=m
CONFIG_NETFILTER_NETLINK_QUEUE=m
# CONFIG_NETFILTER_XT_MATCH_COMMENT is not set
# CONFIG_NETFILTER_XT_MATCH_CONNLIMIT is not set
CONFIG_NETFILTER_XT_MATCH_QUOTA=m
CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
# CONFIG_NETFILTER_XT_MATCH_TIME is not set
# CONFIG_NETFILTER_XT_MATCH_U32 is not set
# CONFIG_NET_CLS_ACT is not set
# CONFIG_NET_CLS_IND is not set
# CONFIG_NET_CLS_POLICE 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_NET_SCH_RR is not set
CONFIG_NFS_FS=y
# CONFIG_NF_CONNTRACK_AMANDA is not set
CONFIG_NF_CONNTRACK_ENABLED=m
CONFIG_NF_CONNTRACK_EVENTS=y
CONFIG_NF_CONNTRACK_NETBIOS_NS=m
CONFIG_NF_CONNTRACK_SANE=m
CONFIG_NF_CT_NETLINK=m
CONFIG_NF_CT_PROTO_SCTP=m
# CONFIG_NF_NAT_AMANDA 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_NVRAM is not set
CONFIG_OABI_COMPAT=y
CONFIG_OPROFILE=m
# CONFIG_OUTER_CACHE is not set
# CONFIG_PARTITION_ADVANCED is not set
# CONFIG_PCI_SYSCALL is not set
# CONFIG_PDA_POWER is not set
CONFIG_PLAT_S3C=y
CONFIG_PLAT_S3C24XX=y
CONFIG_PM=y
CONFIG_PM_DEBUG=y
CONFIG_PM_LEGACY=y
CONFIG_PM_SLEEP=y
# CONFIG_PM_VERBOSE is not set
CONFIG_POWER_SUPPLY=y
# CONFIG_POWER_SUPPLY_DEBUG is not set
# CONFIG_PPPOE is not set
# CONFIG_PPPOL2TP is not set
CONFIG_PREEMPT=y
CONFIG_PROFILING=y
# CONFIG_PROVE_LOCKING is not set
# CONFIG_RCU_TORTURE_TEST is not set
CONFIG_ROMFS_FS=y
CONFIG_ROOT_NFS=y
CONFIG_RPCSEC_GSS_KRB5=y
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_RT_MUTEX_TESTER is not set
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_WATCHDOG=m
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_SCHEDSTATS is not set
# CONFIG_SCHED_DEBUG is not set
# CONFIG_SCSI_MULTI_LUN is not set
CONFIG_SCSI_SCAN_ASYNC=y
CONFIG_SCSI_WAIT_SCAN=m
# CONFIG_SDIO_UART is not set
# 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_SLABINFO=y
# CONFIG_SMC91X is not set
CONFIG_SMDK2440_CPU2440=y
CONFIG_SMDK2440_CPU2442=y
CONFIG_SND_S3C24XX_SOC=m
CONFIG_SND_SOC=m
CONFIG_SND_SUPPORT_OLD_API=y
# CONFIG_SND_USB_AUDIO 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_MASTER=y
CONFIG_SPI_S3C24XX=y
CONFIG_SPI_S3C24XX_GPIO=y
# CONFIG_SPI_SPIDEV is not set
CONFIG_SPLIT_PTLOCK_CPUS=4096
CONFIG_SSB_POSSIBLE=y
CONFIG_SUNRPC=y
CONFIG_SUNRPC_GSS=y
CONFIG_SUSPEND=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_TIMER_STATS=y
# 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_TOUCHRIGHT is not set
# CONFIG_TOUCHSCREEN_TOUCHWIN is not set
# CONFIG_TOUCHSCREEN_UCB1400 is not set
# CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set
CONFIG_UID16=y
CONFIG_USB=y
# CONFIG_USBPCWATCHDOG is not set
# CONFIG_USB_ARCH_HAS_EHCI is not set
CONFIG_USB_BERRY_CHARGE=m
CONFIG_USB_DEVICE_CLASS=y
CONFIG_USB_EPSON2888=y
CONFIG_USB_ETH=m
CONFIG_USB_ETH_RNDIS=y
CONFIG_USB_FILE_STORAGE=m
# CONFIG_USB_FILE_STORAGE_TEST is not set
CONFIG_USB_GADGET=y
CONFIG_USB_GADGETFS=m
# 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 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_PXA2XX is not set
CONFIG_USB_GADGET_S3C2410=y
CONFIG_USB_GADGET_SELECTED=y
CONFIG_USB_G_SERIAL=m
CONFIG_USB_HID=y
CONFIG_USB_HIDDEV=y
CONFIG_USB_IOWARRIOR=m
CONFIG_USB_KC2190=y
CONFIG_USB_LIBUSUAL=y
CONFIG_USB_MIDI_GADGET=m
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=m
# CONFIG_USB_PERSIST is not set
CONFIG_USB_RTL8150=m
CONFIG_USB_S3C2410=y
# CONFIG_USB_S3C2410_DEBUG is not set
# CONFIG_USB_SERIAL_CH341 is not set
# CONFIG_USB_SERIAL_OTI6858 is not set
CONFIG_USB_SUSPEND=y
CONFIG_USB_TRANCEVIBRATOR=m
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_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
# CONFIG_ZISOFS is not set

View file

@ -16,7 +16,7 @@ MAKE += -j5
define Image/BuildKernel 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 $(TARGET_CROSS)objcopy -O binary -R .note -R .comment -S $(LINUX_DIR)/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 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 cp uImage $(BIN_DIR)/openwrt-$(BOARD)-$(KERNEL)-uImage

View file

@ -0,0 +1,29 @@
From bc6ec8d17f2f4dcb70bc1a80ea0630eeb5372406 Mon Sep 17 00:00:00 2001
From: mokopatches <mokopatches@openmoko.org>
Date: Fri, 4 Apr 2008 11:29:03 +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 5ff5406..e2922fc 100644
--- a/arch/arm/kernel/vmlinux.lds.S
+++ b/arch/arm/kernel/vmlinux.lds.S
@@ -105,6 +105,8 @@ SECTIONS
*(.got) /* Global offset table */
}
+ NOTES
+
RODATA
_etext = .; /* End of text and rodata section */
--
1.5.6.5

View file

@ -0,0 +1,60 @@
From 219a4d34b71c37a2a23739718924b0915790f44f Mon Sep 17 00:00:00 2001
From: mokopatches <mokopatches@openmoko.org>
Date: Fri, 4 Apr 2008 11:29:16 +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 66f76e9..355de78 100644
--- a/drivers/mtd/nand/s3c2410.c
+++ b/drivers/mtd/nand/s3c2410.c
@@ -559,17 +559,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.5

View file

@ -0,0 +1,56 @@
From ad7705d9145d87c6e94006d48d12372bb319f4e7 Mon Sep 17 00:00:00 2001
From: mokopatches <mokopatches@openmoko.org>
Date: Fri, 4 Apr 2008 11:29:27 +0100
Subject: [PATCH] neo1973-soc-include-fix.patch
[PATCH] Fix s3c24xx include file path changes in asoc driver
Signed-off-by: Harald Welte <laforge@openmoko.org>
---
sound/soc/s3c24xx/neo1973_wm8753.c | 4 +++-
sound/soc/s3c24xx/s3c24xx-i2s.c | 3 ++-
2 files changed, 5 insertions(+), 2 deletions(-)
diff --git a/sound/soc/s3c24xx/neo1973_wm8753.c b/sound/soc/s3c24xx/neo1973_wm8753.c
index d5a8fc2..679b99d 100644
--- a/sound/soc/s3c24xx/neo1973_wm8753.c
+++ b/sound/soc/s3c24xx/neo1973_wm8753.c
@@ -30,13 +30,15 @@
#include <asm/mach-types.h>
#include <asm/hardware/scoop.h>
-#include <asm/arch/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/plat-s3c24xx/regs-iis.h>
+
#include "../codecs/wm8753.h"
#include "lm4857.h"
#include "s3c24xx-pcm.h"
diff --git a/sound/soc/s3c24xx/s3c24xx-i2s.c b/sound/soc/s3c24xx/s3c24xx-i2s.c
index cd89c41..fe30e0d 100644
--- a/sound/soc/s3c24xx/s3c24xx-i2s.c
+++ b/sound/soc/s3c24xx/s3c24xx-i2s.c
@@ -33,13 +33,14 @@
#include <asm/hardware.h>
#include <asm/io.h>
-#include <asm/arch/regs-iis.h>
#include <asm/arch/regs-gpio.h>
#include <asm/arch/regs-clock.h>
#include <asm/arch/audio.h>
#include <asm/dma.h>
#include <asm/arch/dma.h>
+#include <asm/plat-s3c24xx/regs-iis.h>
+
#include "s3c24xx-pcm.h"
#include "s3c24xx-i2s.h"
--
1.5.6.5

View file

@ -0,0 +1,62 @@
From dee63031aaa4377dea64113b0f6789ea053087fd Mon Sep 17 00:00:00 2001
From: mokopatches <mokopatches@openmoko.org>
Date: Fri, 4 Apr 2008 11:29:38 +0100
Subject: [PATCH] asoc-neo1973_wm8753-power.patch
---
sound/soc/s3c24xx/neo1973_wm8753.c | 32 ++++++++++++++++++++++++++++++++
1 files changed, 32 insertions(+), 0 deletions(-)
diff --git a/sound/soc/s3c24xx/neo1973_wm8753.c b/sound/soc/s3c24xx/neo1973_wm8753.c
index 679b99d..0289d1d 100644
--- a/sound/soc/s3c24xx/neo1973_wm8753.c
+++ b/sound/soc/s3c24xx/neo1973_wm8753.c
@@ -617,6 +617,35 @@ static int lm4857_i2c_attach(struct i2c_adapter *adap)
return i2c_probe(adap, &addr_data, lm4857_amp_probe);
}
+static u8 lm4857_state;
+
+static int lm4857_suspend(struct i2c_client *dev, pm_message_t state)
+{
+ dev_dbg(&dev->dev, "lm4857_suspend\n");
+ lm4857_state = lm4857_regs[LM4857_CTRL] & 0xf;
+ if (lm4857_state) {
+ lm4857_regs[LM4857_CTRL] &= 0xf0;
+ lm4857_write_regs();
+ }
+ return 0;
+}
+
+static int lm4857_resume(struct i2c_client *dev)
+{
+ if (lm4857_state) {
+ lm4857_regs[LM4857_CTRL] |= (lm4857_state & 0x0f);
+ lm4857_write_regs();
+ }
+ return 0;
+}
+
+static void lm4857_shutdown(struct i2c_client *dev)
+{
+ dev_dbg(&dev->dev, "lm4857_shutdown\n");
+ lm4857_regs[LM4857_CTRL] &= 0xf0;
+ lm4857_write_regs();
+}
+
/* corgi i2c codec control layer */
static struct i2c_driver lm4857_i2c_driver = {
.driver = {
@@ -624,6 +653,9 @@ static struct i2c_driver lm4857_i2c_driver = {
.owner = THIS_MODULE,
},
.id = I2C_DRIVERID_LM4857,
+ .suspend = lm4857_suspend,
+ .resume = lm4857_resume,
+ .shutdown = lm4857_shutdown,
.attach_adapter = lm4857_i2c_attach,
.detach_client = lm4857_i2c_detach,
.command = NULL,
--
1.5.6.5

View file

@ -0,0 +1,52 @@
From 3ebb4e58d6f7a9f2710a4e174a3c8b59f9fa9bd5 Mon Sep 17 00:00:00 2001
From: mokopatches <mokopatches@openmoko.org>
Date: Fri, 1 Jun 2007 12:56:55 +0100
Subject: [PATCH] asoc-core-suspend_resume.patch
From 6c868238a5e083dca4d74439a7fd467b5c7726b0 Mon Sep 17 00:00:00 2001
Subject: [PATCH] This fixes a bug whereby PCM's were not being suspended when the rest of the audio subsystem was suspended.
---
include/sound/soc.h | 3 +++
sound/soc/soc-core.c | 5 +++++
2 files changed, 8 insertions(+), 0 deletions(-)
diff --git a/include/sound/soc.h b/include/sound/soc.h
index f47ef1f..aedb348 100644
--- a/include/sound/soc.h
+++ b/include/sound/soc.h
@@ -410,6 +410,9 @@ struct snd_soc_dai_link {
/* codec/machine specific init - e.g. add machine controls */
int (*init)(struct snd_soc_codec *codec);
+
+ /* DAI pcm */
+ struct snd_pcm *pcm;
};
/* SoC machine */
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index e6a67b5..25f7818 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -639,6 +639,10 @@ static int soc_suspend(struct platform_device *pdev, pm_message_t state)
dai->dai_ops.digital_mute(dai, 1);
}
+ /* suspend all pcm's */
+ for(i = 0; i < machine->num_links; i++)
+ snd_pcm_suspend_all(machine->dai_link[i].pcm);
+
if (machine->suspend_pre)
machine->suspend_pre(pdev, state);
@@ -873,6 +877,7 @@ static int soc_new_pcm(struct snd_soc_device *socdev,
return ret;
}
+ dai_link->pcm = pcm;
pcm->private_data = rtd;
soc_pcm_ops.mmap = socdev->platform->pcm_ops->mmap;
soc_pcm_ops.pointer = socdev->platform->pcm_ops->pointer;
--
1.5.6.5

View file

@ -0,0 +1,115 @@
From d3063c1ec65b37b45e808313133196185ea4901f Mon Sep 17 00:00:00 2001
From: mokopatches <mokopatches@openmoko.org>
Date: Fri, 4 Apr 2008 11:30:03 +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 | 35 ++++++++++++++++++++++++++++++++++-
1 files changed, 34 insertions(+), 1 deletions(-)
diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c
index c44ada5..5ac8309 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);
}
@@ -282,7 +292,7 @@ static int i2s_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat)
case STATE_STOP:
dev_err(i2c->dev, "%s: called in STATE_STOP\n", __FUNCTION__);
- s3c24xx_i2c_disable_irq(i2c);
+ s3c24xx_i2c_disable_irq(i2c);
goto out_ack;
case STATE_START:
@@ -502,6 +512,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);
@@ -886,6 +904,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);
@@ -893,6 +922,8 @@ static int s3c24xx_i2c_resume(struct platform_device *dev)
if (i2c != NULL)
s3c24xx_i2c_init(i2c);
+ i2c->suspended--;
+
return 0;
}
@@ -905,6 +936,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,
@@ -915,6 +947,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.5

View file

@ -0,0 +1,45 @@
From fa1e8c2fc849472cddb65bc3138944382b320589 Mon Sep 17 00:00:00 2001
From: mokopatches <mokopatches@openmoko.org>
Date: Fri, 4 Apr 2008 11:30:15 +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 2ec1daa..c11d0dd 100644
--- a/arch/arm/plat-s3c24xx/time.c
+++ b/arch/arm/plat-s3c24xx/time.c
@@ -255,8 +255,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.5

View file

@ -0,0 +1,40 @@
From 2f6a766ce9bfa4e593b1f88b564f91486cd96f80 Mon Sep 17 00:00:00 2001
From: mokopatches <mokopatches@openmoko.org>
Date: Fri, 4 Apr 2008 11:30:27 +0100
Subject: [PATCH] wm8753-rout2-inv.patch
---
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 efced93..52207d5 100644
--- a/sound/soc/codecs/wm8753.c
+++ b/sound/soc/codecs/wm8753.c
@@ -198,6 +198,7 @@ static const char *wm8753_mic_sel[] = {"Mic 1", "Mic 2", "Mic 3"};
static const char *wm8753_dai_mode[] = {"DAI 0", "DAI 1", "DAI 2", "DAI 3"};
static const char *wm8753_dat_sel[] = {"Stereo", "Left ADC", "Right ADC",
"Channel Swap"};
+static const char *wm8753_rout2_phase[] = {"Non Inverted", "Inverted"};
static const struct soc_enum wm8753_enum[] = {
SOC_ENUM_SINGLE(WM8753_BASS, 7, 2, wm8753_base),
@@ -228,6 +229,7 @@ SOC_ENUM_SINGLE(WM8753_ADC, 4, 2, wm8753_adc_filter),
SOC_ENUM_SINGLE(WM8753_MICBIAS, 6, 3, wm8753_mic_sel),
SOC_ENUM_SINGLE(WM8753_IOCTL, 2, 4, wm8753_dai_mode),
SOC_ENUM_SINGLE(WM8753_ADC, 7, 4, wm8753_dat_sel),
+SOC_ENUM_SINGLE(WM8753_OUTCTL, 2, 2, wm8753_rout2_phase),
};
@@ -328,6 +330,7 @@ SOC_SINGLE("Mic1 Capture Volume", WM8753_INCTL1, 5, 3, 0),
SOC_ENUM_EXT("DAI Mode", wm8753_enum[26], wm8753_get_dai, wm8753_set_dai),
SOC_ENUM("ADC Data Select", wm8753_enum[27]),
+SOC_ENUM("ROUT2 Phase", wm8753_enum[28]),
};
/* add non dapm controls */
--
1.5.6.5

View file

@ -0,0 +1,54 @@
From 8e01740813dc6a1d804e61d303549b04e160d153 Mon Sep 17 00:00:00 2001
From: mokopatches <mokopatches@openmoko.org>
Date: Fri, 4 Apr 2008 11:30:37 +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 355de78..770306c 100644
--- a/drivers/mtd/nand/s3c2410.c
+++ b/drivers/mtd/nand/s3c2410.c
@@ -612,9 +612,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 8816f7f..cb87f9e 100644
--- a/include/asm-arm/plat-s3c/nand.h
+++ b/include/asm-arm/plat-s3c/nand.h
@@ -21,9 +21,12 @@
* partitions = mtd partition list
*/
+#define S3C2410_NAND_BBT 0x0001
+
struct s3c2410_nand_set {
int nr_chips;
int nr_partitions;
+ unsigned int flags;
char *name;
int *nr_map;
struct mtd_partition *partitions;
--
1.5.6.5

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,822 @@
From 4b0762543b611b44e96ace4feb80e2b4775ea000 Mon Sep 17 00:00:00 2001
From: mokopatches <mokopatches@openmoko.org>
Date: Fri, 4 Apr 2008 11:31:03 +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 | 1 +
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, 750 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 2340cfb..4538694 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1536,6 +1536,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 e2079cf..a2acd65 100644
--- a/arch/arm/mach-s3c2410/Kconfig
+++ b/arch/arm/mach-s3c2410/Kconfig
@@ -110,5 +110,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 3e7a855..8952a8d 100644
--- a/arch/arm/mach-s3c2410/Makefile
+++ b/arch/arm/mach-s3c2410/Makefile
@@ -29,3 +29,4 @@ obj-$(CONFIG_MACH_AML_M5900) += mach-amlm5900.o
obj-$(CONFIG_BAST_PC104_IRQ) += bast-irq.o
obj-$(CONFIG_MACH_VR1000) += mach-vr1000.o usb-simtec.o
obj-$(CONFIG_MACH_QT2410) += mach-qt2410.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.5

View file

@ -0,0 +1,748 @@
From 6887823c9ab409a15ea73bda8a8b0523cebbe444 Mon Sep 17 00:00:00 2001
From: mokopatches <mokopatches@openmoko.org>
Date: Fri, 4 Apr 2008 11:31:13 +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 a2acd65..ff339e1 100644
--- a/arch/arm/mach-s3c2410/Kconfig
+++ b/arch/arm/mach-s3c2410/Kconfig
@@ -107,6 +107,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.5

View file

@ -0,0 +1,298 @@
From 042ef688ad9f49101fcb5a195a5ecdbad8fde2f8 Mon Sep 17 00:00:00 2001
From: mokopatches <mokopatches@openmoko.org>
Date: Fri, 4 Apr 2008 11:31:24 +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 086d58c..3b9990e 100644
--- a/drivers/input/keyboard/Kconfig
+++ b/drivers/input/keyboard/Kconfig
@@ -293,4 +293,16 @@ config KEYBOARD_BFIN
To compile this driver as a module, choose M here: the
module will be called bf54x-keys.
+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 e97455f..68ecfc5 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_HIL) += hil_kbd.o
obj-$(CONFIG_KEYBOARD_HIL_OLD) += hilkbd.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.5

View file

@ -0,0 +1,976 @@
From b627ce9e57a5263ddcc4e6db49625057b6461ad3 Mon Sep 17 00:00:00 2001
From: mokopatches <mokopatches@openmoko.org>
Date: Fri, 4 Apr 2008 11:31:35 +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 8e5ccaa..7192912 100644
--- a/arch/arm/plat-s3c24xx/Makefile
+++ b/arch/arm/plat-s3c24xx/Makefile
@@ -28,3 +28,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.5

View file

@ -0,0 +1,322 @@
From e9db29d62cbcef7974099c3a4deac69ad2a72190 Mon Sep 17 00:00:00 2001
From: mokopatches <mokopatches@openmoko.org>
Date: Fri, 4 Apr 2008 11:31:44 +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 | 6 +
arch/arm/mach-s3c2410/Makefile | 1 +
arch/arm/mach-s3c2410/pwm.c | 214 ++++++++++++++++++++++++++++++++++++
include/asm-arm/arch-s3c2410/pwm.h | 40 +++++++
4 files changed, 261 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 ff339e1..e42195f 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
@@ -37,6 +38,11 @@ config S3C2410_CLOCK
help
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"
diff --git a/arch/arm/mach-s3c2410/Makefile b/arch/arm/mach-s3c2410/Makefile
index 8952a8d..bb577f4 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.5

View file

@ -0,0 +1,244 @@
From f7ad7d5e90a4ab68e7e25df3bd4a56b6c23f5e45 Mon Sep 17 00:00:00 2001
From: mokopatches <mokopatches@openmoko.org>
Date: Fri, 4 Apr 2008 11:31:55 +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 ec568fa..4579a88 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -57,7 +57,7 @@ config LEDS_TOSA
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.
@@ -114,6 +114,12 @@ config LEDS_CM_X270
help
This option enables support for the CM-X270 LEDs.
+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 a60de1b..f64332d 100644
--- a/drivers/leds/Makefile
+++ b/drivers/leds/Makefile
@@ -19,6 +19,7 @@ obj-$(CONFIG_LEDS_COBALT_QUBE) += leds-cobalt-qube.o
obj-$(CONFIG_LEDS_COBALT_RAQ) += leds-cobalt-raq.o
obj-$(CONFIG_LEDS_GPIO) += leds-gpio.o
obj-$(CONFIG_LEDS_CM_X270) += leds-cm-x270.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.5

View file

@ -0,0 +1,309 @@
From e6e1c20bc96cc397812ab07f0ccd0a16360f2e24 Mon Sep 17 00:00:00 2001
From: mokopatches <mokopatches@openmoko.org>
Date: Fri, 4 Apr 2008 11:32:08 +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 | 8 +
drivers/video/backlight/Makefile | 1 +
drivers/video/backlight/gta01_bl.c | 255 ++++++++++++++++++++++++++++++++++++
3 files changed, 264 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 9609a6c..b954d15 100644
--- a/drivers/video/backlight/Kconfig
+++ b/drivers/video/backlight/Kconfig
@@ -67,6 +67,14 @@ config BACKLIGHT_LOCOMO
If you have a Sharp Zaurus SL-5500 (Collie) or SL-5600 (Poodle) say y to
enable the LCD/backlight driver.
+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 965a78b..8b489f2 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_PROGEAR) += progear_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.5

View file

@ -0,0 +1,636 @@
From 04cce88d3d6753ae23ec36cf383f81aaed5fc71b Mon Sep 17 00:00:00 2001
From: mokopatches <mokopatches@openmoko.org>
Date: Fri, 4 Apr 2008 11:32:18 +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 3444b13..b9389b9 100644
--- a/arch/arm/plat-s3c24xx/s3c244x.c
+++ b/arch/arm/plat-s3c24xx/s3c244x.c
@@ -67,6 +67,7 @@ void __init s3c244x_map_io(struct map_desc *mach_desc, int size)
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 90e8e92..b94fa62 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 35d4097..6558e63 100644
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -19,3 +19,4 @@ obj-$(CONFIG_TOUCHSCREEN_PENMOUNT) += penmount.o
obj-$(CONFIG_TOUCHSCREEN_TOUCHRIGHT) += touchright.o
obj-$(CONFIG_TOUCHSCREEN_TOUCHWIN) += touchwin.o
obj-$(CONFIG_TOUCHSCREEN_UCB1400) += ucb1400_ts.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.5

View file

@ -0,0 +1,53 @@
From 31fc0f2354bb65ac59ccc1e257fdbd622bda9aef Mon Sep 17 00:00:00 2001
From: mokopatches <mokopatches@openmoko.org>
Date: Fri, 4 Apr 2008 11:32:30 +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.5

View file

@ -0,0 +1,33 @@
From ae0e6a5c9e4cc1786c8b798ac19259a339476121 Mon Sep 17 00:00:00 2001
From: mokopatches <mokopatches@openmoko.org>
Date: Fri, 4 Apr 2008 11:32:41 +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 b5e13e4..2c802de 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -941,11 +941,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.5

View file

@ -0,0 +1,34 @@
From 00f10ad5e63625961028479e4814953ff443dfff Mon Sep 17 00:00:00 2001
From: mokopatches <mokopatches@openmoko.org>
Date: Fri, 4 Apr 2008 11:32:51 +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 9e732bf..a7f38b6 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.5

View file

@ -0,0 +1,44 @@
From f741358022646f390154cfc922bece654df26741 Mon Sep 17 00:00:00 2001
From: mokopatches <mokopatches@openmoko.org>
Date: Fri, 4 Apr 2008 11:33:02 +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 a7f38b6..6efbb44 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.5

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,97 @@
From 948f60af720f34294629041773d9947bcefc0a9a Mon Sep 17 00:00:00 2001
From: mokopatches <mokopatches@openmoko.org>
Date: Fri, 4 Apr 2008 11:33:24 +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.5

View file

@ -0,0 +1,143 @@
From cddfb6f606768265f2b36658761ea9467f098f0a Mon Sep 17 00:00:00 2001
From: mokopatches <mokopatches@openmoko.org>
Date: Fri, 4 Apr 2008 11:33:44 +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>
---
Documentation/arm/Samsung-S3C24XX/NAND.txt | 30 +++++++++++++++++++
Documentation/arm/Samsung-S3C24XX/Overview.txt | 2 +
drivers/mtd/nand/s3c2410.c | 38 ++++++++++++++++++++---
3 files changed, 65 insertions(+), 5 deletions(-)
create mode 100644 Documentation/arm/Samsung-S3C24XX/NAND.txt
diff --git a/Documentation/arm/Samsung-S3C24XX/NAND.txt b/Documentation/arm/Samsung-S3C24XX/NAND.txt
new file mode 100644
index 0000000..bc478a3
--- /dev/null
+++ b/Documentation/arm/Samsung-S3C24XX/NAND.txt
@@ -0,0 +1,30 @@
+ S3C24XX NAND Support
+ ====================
+
+Introduction
+------------
+
+Small Page NAND
+---------------
+
+The driver uses a 512 byte (1 page) ECC code for this setup. The
+ECC code is not directly compatible with the default kernel ECC
+code, so the driver enforces its own OOB layout and ECC parameters
+
+Large Page NAND
+---------------
+
+The driver is capable of handling NAND flash with a 2KiB page
+size, with support for hardware ECC generation and correction.
+
+Unlike the 512byte page mode, the driver generates ECC data for
+each 256 byte block in an 2KiB page. This means that more than
+one error in a page can be rectified. It also means that the
+OOB layout remains the default kernel layout for these flashes.
+
+
+Document Author
+---------------
+
+Ben Dooks, Copyright 2007 Simtec Electronics
+
diff --git a/Documentation/arm/Samsung-S3C24XX/Overview.txt b/Documentation/arm/Samsung-S3C24XX/Overview.txt
index c31b76f..d04e1e3 100644
--- a/Documentation/arm/Samsung-S3C24XX/Overview.txt
+++ b/Documentation/arm/Samsung-S3C24XX/Overview.txt
@@ -156,6 +156,8 @@ NAND
controller. If there are any problems the latest linux-mtd
code can be found from http://www.linux-mtd.infradead.org/
+ For more information see Documentation/arm/Samsung-S3C24XX/NAND.txt
+
Serial
------
diff --git a/drivers/mtd/nand/s3c2410.c b/drivers/mtd/nand/s3c2410.c
index 770306c..5c1c09d 100644
--- a/drivers/mtd/nand/s3c2410.c
+++ b/drivers/mtd/nand/s3c2410.c
@@ -473,7 +473,7 @@ static int s3c2440_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u
ecc_code[1] = ecc >> 8;
ecc_code[2] = ecc >> 16;
- pr_debug("%s: returning ecc %06lx\n", __func__, ecc);
+ pr_debug("%s: returning ecc %06lx\n", __func__, ecc & 0xffffff);
return 0;
}
@@ -662,9 +662,6 @@ static void s3c2410_nand_init_chip(struct s3c2410_nand_info *info,
chip->ecc.calculate = s3c2410_nand_calculate_ecc;
chip->ecc.correct = s3c2410_nand_correct_data;
chip->ecc.mode = NAND_ECC_HW;
- chip->ecc.size = 512;
- chip->ecc.bytes = 3;
- chip->ecc.layout = &nand_hw_eccoob;
switch (info->cpu_type) {
case TYPE_S3C2410:
@@ -688,6 +685,34 @@ static void s3c2410_nand_init_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
@@ -794,9 +819,12 @@ static int s3c24xx_nand_probe(struct platform_device *pdev,
s3c2410_nand_init_chip(info, nmtd, sets);
- nmtd->scan_res = nand_scan(&nmtd->mtd, (sets) ? sets->nr_chips : 1);
+ nmtd->scan_res = nand_scan_ident(&nmtd->mtd,
+ (sets) ? sets->nr_chips : 1);
if (nmtd->scan_res == 0) {
+ s3c2410_nand_update_chip(info, nmtd);
+ nand_scan_tail(&nmtd->mtd);
s3c2410_nand_add_partition(info, nmtd, sets);
}
--
1.5.6.5

View file

@ -0,0 +1,61 @@
From d8310bb7e4ee4a9f3433a9a1e0e87567337299cb Mon Sep 17 00:00:00 2001
From: mokopatches <mokopatches@openmoko.org>
Date: Fri, 4 Apr 2008 11:33:55 +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 4ce050c..d4a17af 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.5

View file

@ -0,0 +1,453 @@
From 23b8a1e056b74101ae9d51ccbab2d208e46c01a4 Mon Sep 17 00:00:00 2001
From: mokopatches <mokopatches@openmoko.org>
Date: Fri, 4 Apr 2008 11:34:06 +0100
Subject: [PATCH] hxd8-core.patch
This patch adds another machine, the FIC HXD8
---
arch/arm/mach-s3c2440/Kconfig | 6 +
arch/arm/mach-s3c2440/Makefile | 1 +
arch/arm/mach-s3c2440/mach-hxd8.c | 381 +++++++++++++++++++++++++++++++++++
include/asm-arm/arch-s3c2440/hxd8.h | 16 ++
4 files changed, 404 insertions(+), 0 deletions(-)
create mode 100644 arch/arm/mach-s3c2440/mach-hxd8.c
create mode 100644 include/asm-arm/arch-s3c2440/hxd8.h
diff --git a/arch/arm/mach-s3c2440/Kconfig b/arch/arm/mach-s3c2440/Kconfig
index f1915bd..6798d9c 100644
--- a/arch/arm/mach-s3c2440/Kconfig
+++ b/arch/arm/mach-s3c2440/Kconfig
@@ -67,6 +67,12 @@ config SMDK2440_CPU2440
default y if ARCH_S3C2440
select CPU_S3C2440
+config MACH_HXD8
+ bool "FIC HXD8"
+ select CPU_S3C2440
+ select SENSORS_PCF50606
+ help
+ Say Y here if you are using the FIC Neo1973 GSM Phone
endmenu
diff --git a/arch/arm/mach-s3c2440/Makefile b/arch/arm/mach-s3c2440/Makefile
index c81ed62..6f590d4 100644
--- a/arch/arm/mach-s3c2440/Makefile
+++ b/arch/arm/mach-s3c2440/Makefile
@@ -21,3 +21,4 @@ obj-$(CONFIG_MACH_OSIRIS) += mach-osiris.o
obj-$(CONFIG_MACH_RX3715) += mach-rx3715.o
obj-$(CONFIG_ARCH_S3C2440) += mach-smdk2440.o
obj-$(CONFIG_MACH_NEXCODER_2440) += mach-nexcoder.o
+obj-$(CONFIG_MACH_HXD8) += mach-hxd8.o
diff --git a/arch/arm/mach-s3c2440/mach-hxd8.c b/arch/arm/mach-s3c2440/mach-hxd8.c
new file mode 100644
index 0000000..3400ed3
--- /dev/null
+++ b/arch/arm/mach-s3c2440/mach-hxd8.c
@@ -0,0 +1,381 @@
+/* linux/arch/arm/mach-s3c2440/mach-hxd8.c
+ *
+ * S3C2440 Machine Support for the FIC HXD8
+ *
+ * Copyright (c) 2007 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/serial_core.h>
+#include <linux/platform_device.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/pcf50606.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/hardware.h>
+#include <asm/hardware/iomd.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/mach-types.h>
+
+//#include <asm/debug-ll.h>
+#include <asm/arch/regs-gpio.h>
+#include <asm/arch/regs-lcd.h>
+#include <asm/arch/idle.h>
+#include <asm/arch/fb.h>
+#include <asm/arch/mci.h>
+#include <asm/arch/ts.h>
+#include <asm/arch/spi.h>
+#include <asm/arch/spi-gpio.h>
+#include <asm/arch/usb-control.h>
+
+#include <asm/arch-s3c2440/hxd8.h>
+#include <asm/arch/gta01.h>
+
+//#include "s3c2410.h"
+//#include "s3c2440.h"
+//#include "clock.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 hxd8_iodesc[] __initdata = {
+ /* ISA IO Space map (memory space selected by A24) */
+
+ {
+ .virtual = (u32)S3C24XX_VA_ISA_WORD,
+ .pfn = __phys_to_pfn(S3C2410_CS2),
+ .length = 0x10000,
+ .type = MT_DEVICE,
+ }, {
+ .virtual = (u32)S3C24XX_VA_ISA_WORD + 0x10000,
+ .pfn = __phys_to_pfn(S3C2410_CS2 + (1<<24)),
+ .length = SZ_4M,
+ .type = MT_DEVICE,
+ }, {
+ .virtual = (u32)S3C24XX_VA_ISA_BYTE,
+ .pfn = __phys_to_pfn(S3C2410_CS2),
+ .length = 0x10000,
+ .type = MT_DEVICE,
+ }, {
+ .virtual = (u32)S3C24XX_VA_ISA_BYTE + 0x10000,
+ .pfn = __phys_to_pfn(S3C2410_CS2 + (1<<24)),
+ .length = SZ_4M,
+ .type = MT_DEVICE,
+ }
+};
+
+#define UCON S3C2410_UCON_DEFAULT | S3C2410_UCON_UCLK
+#define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB
+#define UFCON S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE
+
+static struct s3c2410_uartcfg hxd8_uartcfgs[] __initdata = {
+ [0] = {
+ .hwport = 0,
+ .flags = 0,
+ .ucon = 0x3c5,
+ .ulcon = 0x03,
+ .ufcon = 0x51,
+ },
+ [1] = {
+ .hwport = 1,
+ .flags = 0,
+ .ucon = 0x3c5,
+ .ulcon = 0x03,
+ .ufcon = 0x51,
+ },
+ [2] = {
+ .hwport = 2,
+ .flags = 0,
+ .ucon = 0x3c5,
+ .ulcon = 0x03,
+ .ufcon = 0x51,
+ }
+};
+
+static struct s3c2410_nand_set hxd8_nand_sets[] = {
+ [0] = {
+ .name = "hxd8-nand",
+ .nr_chips = 1,
+ .flags = S3C2410_NAND_BBT,
+ },
+ [1] = {
+ .name = "hxd8-nand-1",
+ .nr_chips = 1,
+ .flags = S3C2410_NAND_BBT,
+ },
+ [2] = {
+ .name = "hxd8-nand-2",
+ .nr_chips = 1,
+ .flags = S3C2410_NAND_BBT,
+ },
+};
+
+/* choose a set of timings which should suit most 512Mbit
+ * chips and beyond.
+*/
+
+static struct s3c2410_platform_nand hxd8_nand_info = {
+ .tacls = 20,
+ .twrph0 = 60,
+ .twrph1 = 20,
+ .nr_sets = ARRAY_SIZE(hxd8_nand_sets),
+ .sets = hxd8_nand_sets,
+};
+
+/* PMU configuration */
+
+static struct pcf50606_platform_data hxd8_pcf_pdata = {
+ .used_features = PCF50606_FEAT_EXTON |
+ PCF50606_FEAT_BBC |
+ PCF50606_FEAT_WDT |
+ PCF50606_FEAT_RTC |
+ PCF50606_FEAT_PWM |
+ PCF50606_FEAT_PWM_BL |
+ PCF50606_FEAT_BATVOLT,
+ .onkey_seconds_required = 5,
+ .init_brightness = 8,
+ .rails = {
+ [PCF50606_REGULATOR_D1REG] = {
+ .name = "rc_3v3",
+ .voltage = {
+ .init = 3300,
+ .max = 3300,
+ },
+ },
+ [PCF50606_REGULATOR_D2REG] = {
+ .name = "gps_3v3",
+ .voltage = {
+ .init = 3300,
+ .max = 3300,
+ },
+ },
+ [PCF50606_REGULATOR_D3REG] = {
+ .name = "io2_3v3",
+ .voltage = {
+ .init = 3300,
+ .max = 3300,
+ },
+ },
+ [PCF50606_REGULATOR_DCD] = {
+ .name = "core_1v3",
+ .voltage = {
+ .init = 1300,
+ .max = 1500,
+ },
+ },
+ [PCF50606_REGULATOR_DCDE] = {
+ .name = "io1_3v3",
+ .voltage = {
+ .init = 3300,
+ .max = 3300,
+ },
+ },
+ [PCF50606_REGULATOR_DCUD] = {
+ .name = "rf_3v3",
+ .voltage = {
+ .init = 3300,
+ .max = 3300,
+ },
+ },
+ [PCF50606_REGULATOR_IOREG] = {
+ .name = "audio_3v3",
+ .voltage = {
+ .init = 3300,
+ .max = 3300,
+ },
+ },
+ [PCF50606_REGULATOR_LPREG] = {
+ .name = "lcm_3v3",
+ .voltage = {
+ .init = 3300,
+ .max = 3300,
+ },
+ },
+ },
+};
+
+static struct resource hxd8_pmu_resources[] = {
+ [0] = {
+ .flags = IORESOURCE_IRQ,
+ .start = HXD8_IRQ_PCF50606,
+ .end = HXD8_IRQ_PCF50606,
+ },
+};
+
+static struct platform_device hxd8_pmu_dev = {
+ .name = "pcf50606",
+ .num_resources = ARRAY_SIZE(hxd8_pmu_resources),
+ .resource = hxd8_pmu_resources,
+ .dev = {
+ .platform_data = &hxd8_pcf_pdata,
+ },
+};
+
+/* LCD driver info */
+
+static struct s3c2410fb_display hxd8_displays[] __initdata = {
+ {
+ .type = S3C2410_LCDCON1_TFT,
+ .width = 480,
+ .height = 272,
+ .xres = 480,
+ .yres = 272,
+ .bpp = 16,
+
+ .pixclock = 40000, /* HCLK/4 */
+ .left_margin = 2,
+ .right_margin = 2,
+ .hsync_len = 41,
+ .upper_margin = 2,
+ .lower_margin = 2,
+ .vsync_len = 10,
+ .lcdcon5 = S3C2410_LCDCON5_FRM565 |
+ S3C2410_LCDCON5_INVVLINE |
+ S3C2410_LCDCON5_INVVFRAME,
+ },
+};
+
+static struct s3c2410fb_mach_info hxd8_lcd_cfg __initdata = {
+ .displays = hxd8_displays,
+ .num_displays = ARRAY_SIZE(hxd8_displays),
+ .default_display = 1,
+
+ .lpcsel = ((0xCE6) & ~7),
+};
+
+static struct platform_device hxd8_pm_gsm_dev = {
+ .name = "neo1973-pm-gsm",
+};
+
+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(HXD8_GPIO_USB_PULLUP, 1);
+ break;
+ case S3C2410_UDC_P_DISABLE:
+ s3c2410_gpio_setpin(HXD8_GPIO_USB_PULLUP, 0);
+ break;
+ case S3C2410_UDC_P_RESET:
+ /* FIXME! */
+ break;
+ default:
+ break;
+ }
+}
+
+/* USB Charger */
+
+static void hxd8_udc_vbus_draw(unsigned int ma)
+{
+ if (ma >= 500) {
+ /* enable fast charge */
+ printk(KERN_DEBUG "udc: enabling fast charge\n");
+ s3c2410_gpio_setpin(HXD8_GPIO_USB_CUR_SEL, 1);
+ } else {
+ /* disable fast charge */
+ printk(KERN_DEBUG "udc: disabling fast charge\n");
+ s3c2410_gpio_setpin(HXD8_GPIO_USB_CUR_SEL, 0);
+ }
+}
+
+static struct s3c2410_udc_mach_info hxd8_udc_cfg = {
+ .vbus_draw = hxd8_udc_vbus_draw,
+};
+
+/* Touch Screen */
+static struct s3c2410_ts_mach_info hxd8_ts_cfg = {
+ .delay = 10000,
+ .presc = 49,
+ .oversampling_shift = 4,
+};
+
+static struct platform_device *hxd8_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,
+ &s3c_device_ts,
+};
+
+static void __init hxd8_map_io(void)
+{
+ s3c24xx_init_io(hxd8_iodesc, ARRAY_SIZE(hxd8_iodesc));
+ s3c24xx_init_clocks(16934400);
+ s3c24xx_init_uarts(hxd8_uartcfgs, ARRAY_SIZE(hxd8_uartcfgs));
+}
+
+static void __init hxd8_machine_init(void)
+{
+ hxd8_udc_cfg.udc_command = gta01_udc_command;
+ s3c_device_nand.dev.platform_data = &hxd8_nand_info;
+
+ s3c24xx_fb_set_platdata(&hxd8_lcd_cfg);
+
+ s3c24xx_udc_set_platdata(&hxd8_udc_cfg);
+ set_s3c2410ts_info(&hxd8_ts_cfg);
+
+ //platform_device_register(&gta01_button_dev);
+ platform_device_register(&hxd8_pm_gsm_dev);
+
+ platform_device_register(&hxd8_pmu_dev);
+
+ platform_add_devices(hxd8_devices, ARRAY_SIZE(hxd8_devices));
+
+ s3c2410_pm_init();
+}
+
+MACHINE_START(HXD8, "HXD8")
+ /* Maintainer: Harald Welte <laforge@openmoko.org> */
+ .phys_io = S3C2410_PA_UART,
+ .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
+ .boot_params = S3C2410_SDRAM_PA + 0x100,
+
+ .init_irq = s3c24xx_init_irq,
+ .map_io = hxd8_map_io,
+ .init_machine = hxd8_machine_init,
+ .timer = &s3c24xx_timer,
+MACHINE_END
diff --git a/include/asm-arm/arch-s3c2440/hxd8.h b/include/asm-arm/arch-s3c2440/hxd8.h
new file mode 100644
index 0000000..50e9c11
--- /dev/null
+++ b/include/asm-arm/arch-s3c2440/hxd8.h
@@ -0,0 +1,16 @@
+#ifndef _HXD8_H
+#define _HXD8_H
+
+#include <asm/arch/regs-gpio.h>
+#include <asm/arch/irqs.h>
+
+#define HXD8v1_SYSTEM_REV 0x00000110
+
+#define HXD8_GPIO_USB_CUR_SEL S3C2410_GPA0
+#define HXD8_GPIO_BACKLIGHT S3C2410_GPB0
+#define HXD8_GPIO_USB_PULLUP S3C2410_GPB9
+#define HXD8_GPIO_PCF50606 S3C2410_GPF6
+
+#define HXD8_IRQ_PCF50606 IRQ_EINT6
+
+#endif
--
1.5.6.5

View file

@ -0,0 +1,537 @@
From d238d3347d19a6df97670624bd0712e61b83b666 Mon Sep 17 00:00:00 2001
From: mokopatches <mokopatches@openmoko.org>
Date: Fri, 4 Apr 2008 11:34:17 +0100
Subject: [PATCH] hxd8-tsl256x.patch
---
drivers/i2c/chips/Kconfig | 10 ++
drivers/i2c/chips/Makefile | 1 +
drivers/i2c/chips/tsl256x.c | 310 +++++++++++++++++++++++++++++++++++++++++++
drivers/i2c/chips/tsl256x.h | 154 +++++++++++++++++++++
include/linux/i2c-id.h | 1 +
5 files changed, 476 insertions(+), 0 deletions(-)
create mode 100644 drivers/i2c/chips/tsl256x.c
create mode 100644 drivers/i2c/chips/tsl256x.h
diff --git a/drivers/i2c/chips/Kconfig b/drivers/i2c/chips/Kconfig
index c0011fc..bf0da3a 100644
--- a/drivers/i2c/chips/Kconfig
+++ b/drivers/i2c/chips/Kconfig
@@ -174,4 +174,14 @@ config MENELAUS
and other features that are often used in portable devices like
cell phones and PDAs.
+config SENSORS_TSL256X
+ tristate "Texas TSL256X Ambient Light Sensor"
+ depends on I2C
+ help
+ If you say yes here you get support for the Texas TSL256X
+ ambient light sensor chip.
+
+ This driver can also be built as a module. If so, the module
+ will be called tsl256x.
+
endmenu
diff --git a/drivers/i2c/chips/Makefile b/drivers/i2c/chips/Makefile
index 864e6cf..a4772c7 100644
--- a/drivers/i2c/chips/Makefile
+++ b/drivers/i2c/chips/Makefile
@@ -16,6 +16,7 @@ obj-$(CONFIG_ISP1301_OMAP) += isp1301_omap.o
obj-$(CONFIG_TPS65010) += tps65010.o
obj-$(CONFIG_MENELAUS) += menelaus.o
obj-$(CONFIG_SENSORS_TSL2550) += tsl2550.o
+obj-$(CONFIG_SENSORS_TSL256X) += tsl256x.o
ifeq ($(CONFIG_I2C_DEBUG_CHIP),y)
EXTRA_CFLAGS += -DDEBUG
diff --git a/drivers/i2c/chips/tsl256x.c b/drivers/i2c/chips/tsl256x.c
new file mode 100644
index 0000000..455ec5e
--- /dev/null
+++ b/drivers/i2c/chips/tsl256x.c
@@ -0,0 +1,310 @@
+/*
+ * tsl256x.c -- TSL256x Light Sensor driver
+ *
+ * Copyright 2007 by Fiwin.
+ * Author: Alec Tsai <alec_tsai@fiwin.com.tw>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This I2C client driver refers to pcf50606.c.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/i2c.h>
+#include <linux/types.h>
+#include <linux/input.h>
+
+#include "tsl256x.h"
+
+static unsigned short normal_i2c[] = { 0x39, I2C_CLIENT_END };
+/* Magic definition of all other variables and things */
+I2C_CLIENT_INSMOD;
+
+struct tsl256x_data {
+ struct i2c_client client;
+ struct mutex lock;
+ struct input_dev *input_dev;
+};
+
+static struct i2c_driver tsl256x_driver;
+
+/******************************************************************************
+ * Low-Level routines
+ *****************************************************************************/
+static inline int __reg_write(struct tsl256x_data *tsl, u_int8_t reg,
+ u_int8_t val)
+{
+ return i2c_smbus_write_byte_data(&tsl->client, reg, val);
+}
+
+static int reg_write(struct tsl256x_data *tsl, u_int8_t reg, u_int8_t val)
+{
+ int ret;
+
+ mutex_lock(&tsl->lock);
+ ret = __reg_write(tsl, reg, val);
+ mutex_unlock(&tsl->lock);
+
+ return ret;
+}
+
+static inline int32_t __reg_read(struct tsl256x_data *tsl, u_int8_t reg)
+{
+ int32_t ret;
+
+ ret = i2c_smbus_read_byte_data(&tsl->client, reg);
+
+ return ret;
+}
+
+static u_int8_t reg_read(struct tsl256x_data *tsl, u_int8_t reg)
+{
+ int32_t ret;
+
+ mutex_lock(&tsl->lock);
+ ret = __reg_read(tsl, reg);
+ mutex_unlock(&tsl->lock);
+
+ return ret & 0xff;
+}
+
+u_int32_t calculate_lux(u_int32_t iGain, u_int32_t iType, u_int32_t ch0,
+ u_int32_t ch1)
+{
+ u_int32_t channel0 = ch0 * 636 / 10;
+ u_int32_t channel1 = ch1 * 636 / 10;
+ u_int32_t lux_value = 0;
+ u_int32_t ratio = (channel1 * (2^RATIO_SCALE)) / channel0;
+ u_int32_t b = 0, m = 0;
+
+ if (0 == ch0)
+ return 0;
+ else {
+ if (ratio > (13 * (2^RATIO_SCALE) / 10))
+ return 0;
+ }
+
+ switch (iType) {
+ case 0: // T package
+ if ((ratio >= 0) && (ratio <= K1T)) {
+ b = B1T;
+ m = M1T;
+ } else if (ratio <= K2T) {
+ b = B2T;
+ m = M2T;
+ } else if (ratio <= K3T) {
+ b = B3T;
+ m = M3T;
+ } else if (ratio <= K4T) {
+ b = B4T;
+ m = M4T;
+ } else if (ratio <= K5T) {
+ b = B5T;
+ m = M5T;
+ } else if (ratio <= K6T) {
+ b = B6T;
+ m = M6T;
+ } else if (ratio <= K7T) {
+ b = B7T;
+ m = M7T;
+ } else if (ratio > K8T) {
+ b = B8T;
+ m = M8T;
+ }
+ break;
+ case 1:// CS package
+ if ((ratio >= 0) && (ratio <= K1C)) {
+ b = B1C;
+ m = M1C;
+ } else if (ratio <= K2C) {
+ b = B2C;
+ m = M2C;
+ } else if (ratio <= K3C) {
+ b = B3C;
+ m = M3C;
+ } else if (ratio <= K4C) {
+ b = B4C;
+ m = M4C;
+ } else if (ratio <= K5C) {
+ b = B5C;
+ m = M5C;
+ } else if (ratio <= K6C) {
+ b = B6C;
+ m = M6C;
+ } else if (ratio <= K7C) {
+ b = B7C;
+ m = M7C;
+ } else if (ratio > K8C) {
+ b = B8C;
+ m = M8C;
+ }
+ break;
+ default:
+ return 0;
+ break;
+ }
+
+ lux_value = ((channel0 * b) - (channel1 * m)) / 16384;
+ return(lux_value);
+}
+
+static ssize_t tsl256x_show_light_lux(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct tsl256x_data *tsl = i2c_get_clientdata(client);
+ u_int8_t low_byte_of_ch0 = 0, high_byte_of_ch0 = 0;
+ u_int8_t low_byte_of_ch1 = 0, high_byte_of_ch1 = 0;
+ u_int32_t adc_value_ch0, adc_value_ch1, adc_value;
+
+ low_byte_of_ch0 = reg_read(tsl, TSL256X_REG_DATA0LOW);
+ high_byte_of_ch0 = reg_read(tsl, TSL256X_REG_DATA0HIGH);
+ low_byte_of_ch1 = reg_read(tsl, TSL256X_REG_DATA1LOW);
+ high_byte_of_ch1 = reg_read(tsl, TSL256X_REG_DATA1HIGH);
+
+ adc_value_ch0 = (high_byte_of_ch0 * 256 + low_byte_of_ch0) * 16;
+ adc_value_ch1 = (high_byte_of_ch1 * 256 + low_byte_of_ch1) * 16;
+
+ adc_value = calculate_lux(0, 0, adc_value_ch0, adc_value_ch1);
+ return sprintf(buf, "%d\n", adc_value);
+}
+
+static DEVICE_ATTR(light_lux, S_IRUGO, tsl256x_show_light_lux, NULL);
+
+static int tsl256x_detect(struct i2c_adapter *adapter, int address, int kind)
+{
+ struct i2c_client *new_client = NULL;
+ struct tsl256x_data *tsl256x = NULL;
+ u_int8_t id = 0;
+ int res = 0;
+
+ if (!(tsl256x = kzalloc(sizeof(*tsl256x), GFP_KERNEL)))
+ return -ENOMEM;
+
+ mutex_init(&tsl256x->lock);
+ new_client = &tsl256x->client;
+ i2c_set_clientdata(new_client, tsl256x);
+ new_client->addr = address;
+ new_client->adapter = adapter;
+ new_client->driver = &tsl256x_driver;
+ new_client->flags = 0;
+ strlcpy(new_client->name, "tsl256x", I2C_NAME_SIZE);
+
+ /* now we try to detect the chip */
+ /* register with i2c core */
+ res = i2c_attach_client(new_client);
+ if (res) {
+ printk(KERN_DEBUG "[%s]Error: during i2c_attach_client()\n",
+ new_client->name);
+ goto exit_free;
+ } else {
+ printk(KERN_INFO "TSL256X is attached to I2C bus.\n");
+ }
+
+ /* Configure TSL256X. */
+ {
+ /* Power up TSL256X. */
+ reg_write(tsl256x, TSL256X_REG_CONTROL, 0x03);
+
+ /* Check TSL256X ID. */
+ id = reg_read(tsl256x, TSL256X_REG_ID);
+ if (TSL2561_ID == (id & 0xF0)) {
+ /* Configuring the Timing Register.
+ High Gain (16x), integration time of 101ms. */
+ reg_write(tsl256x, TSL256X_REG_TIMING, 0x11);
+ } else {
+ goto exit_free;
+ }
+ }
+
+ res = device_create_file(&new_client->dev, &dev_attr_light_lux);
+ if (res)
+ goto exit_detach;
+
+ return 0;
+
+exit_free:
+ kfree(tsl256x);
+ return res;
+exit_detach:
+ i2c_detach_client(new_client);
+ return res;
+}
+
+static int tsl256x_attach_adapter(struct i2c_adapter *adapter)
+{
+ return i2c_probe(adapter, &addr_data, &tsl256x_detect);
+}
+
+static int tsl256x_detach_client(struct i2c_client *client)
+{
+ struct tsl256x_data *tsl256x = i2c_get_clientdata(client);
+
+ printk(KERN_INFO "Detach TSL256X from I2C bus.\n");
+
+ /* Power down TSL256X. */
+ reg_write(tsl256x, TSL256X_REG_CONTROL, 0x00);
+
+ device_remove_file(&client->dev, &dev_attr_light_lux);
+ kfree(tsl256x);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int tsl256x_suspend(struct device *dev, pm_message_t state)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct tsl256x_data *tsl256x = i2c_get_clientdata(client);
+
+ /* Power down TSL256X. */
+ reg_write(tsl256x, TSL256X_REG_CONTROL, 0x00);
+
+ return 0;
+}
+
+static int tsl256x_resume(struct device *dev)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct tsl256x_data *tsl256x = i2c_get_clientdata(client);
+
+ /* Power up TSL256X. */
+ reg_write(tsl256x, TSL256X_REG_CONTROL, 0x03);
+
+ return 0;
+}
+#endif
+
+static struct i2c_driver tsl256x_driver = {
+ .driver = {
+ .name = "tsl256x",
+ .owner = THIS_MODULE,
+#ifdef CONFIG_PM
+ .suspend = tsl256x_suspend,
+ .resume = tsl256x_resume,
+#endif
+ },
+ .id = I2C_DRIVERID_TSL256X,
+ .attach_adapter = tsl256x_attach_adapter,
+ .detach_client = tsl256x_detach_client,
+};
+
+static int __init tsl256x_init(void)
+{
+ return i2c_add_driver(&tsl256x_driver);
+}
+
+static void __exit tsl256x_exit(void)
+{
+ i2c_del_driver(&tsl256x_driver);
+}
+
+MODULE_AUTHOR("Alec Tsai <alec_tsai@fiwin.com.tw>");
+MODULE_LICENSE("GPL");
+
+module_init(tsl256x_init);
+module_exit(tsl256x_exit);
+
diff --git a/drivers/i2c/chips/tsl256x.h b/drivers/i2c/chips/tsl256x.h
new file mode 100644
index 0000000..88de0c6
--- /dev/null
+++ b/drivers/i2c/chips/tsl256x.h
@@ -0,0 +1,154 @@
+/*
+ * tsl256x.h -- TSL256x Light Sensor driver
+ *
+ * Copyright 2007 by Fiwin.
+ * Author: Alec Tsai <alec_tsai@fiwin.com.tw>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * The contents of header file is copied from TSL256x Datasheet.
+ */
+
+#ifndef _TSL256X_H
+#define _TSL256X_H
+
+#define TSL2560_ID 0x00
+#define TSL2561_ID 0x10
+
+#define LUX_SCALE 14 /* scale by 2^14 */
+#define RATIO_SCALE 9 /*scale ratio by 2^9 */
+
+/******************************************************************************
+ * Integration time scaling factors
+ *****************************************************************************/
+#define CH_SCALE 10 /* scale channel values by 2^10 */
+#define CHSCALE_TINT0 0x7517 /* 322/11 * 2^CH_SCALE */
+#define CHSCALE_TINT1 0x0fe7 /* 322/81 * 2^CH_SCALE */
+
+/******************************************************************************
+ * T Package coefficients
+ *****************************************************************************/
+/*
+ * For Ch1/Ch0=0.00 to 0.50
+ * Lux/Ch0=0.0304.0.062*((Ch1/Ch0)^1.4)
+ * piecewise approximation
+ * For Ch1/Ch0=0.00 to 0.125:
+ * Lux/Ch0=0.0304.0.0272*(Ch1/Ch0)
+ *
+ * For Ch1/Ch0=0.125 to 0.250:
+ * Lux/Ch0=0.0325.0.0440*(Ch1/Ch0)
+ *
+ * For Ch1/Ch0=0.250 to 0.375:
+ * Lux/Ch0=0.0351.0.0544*(Ch1/Ch0)
+ *
+ * For Ch1/Ch0=0.375 to 0.50:
+ * Lux/Ch0=0.0381.0.0624*(Ch1/Ch0)
+ *
+ * For Ch1/Ch0=0.50 to 0.61:
+ * Lux/Ch0=0.0224.0.031*(Ch1/Ch0)
+ *
+ * For Ch1/Ch0=0.61 to 0.80:
+ * Lux/Ch0=0.0128.0.0153*(Ch1/Ch0)
+ *
+ * For Ch1/Ch0=0.80 to 1.30:
+ * Lux/Ch0=0.00146.0.00112*(Ch1/Ch0)
+ *
+ * For Ch1/Ch0>1.3:
+ * Lux/Ch0=0
+ */
+#define K1T 0x0040 /* 0.125 * 2^RATIO_SCALE */
+#define B1T 0x01f2 /* 0.0304 * 2^LUX_SCALE */
+#define M1T 0x01be /* 0.0272 * 2^LUX_SCALE */
+#define K2T 0x0080 /* 0.250 * 2^RATIO_SCALE */
+#define B2T 0x0214 /* 0.0325 * 2^LUX_SCALE */
+#define M2T 0x02d1 /* 0.0440 * 2^LUX_SCALE */
+#define K3T 0x00c0 /* 0.375 * 2^RATIO_SCALE */
+#define B3T 0x023f /* 0.0351 * 2^LUX_SCALE */
+#define M3T 0x037b /* 0.0544 * 2^LUX_SCALE */
+#define K4T 0x0100 /* 0.50 * 2^RATIO_SCALE */
+#define B4T 0x0270 /* 0.0381 * 2^LUX_SCALE */
+#define M4T 0x03fe /* 0.0624 * 2^LUX_SCALE */
+#define K5T 0x0138 /* 0.61 * 2^RATIO_SCALE */
+#define B5T 0x016f /* 0.0224 * 2^LUX_SCALE */
+#define M5T 0x01fc /* 0.0310 * 2^LUX_SCALE */
+#define K6T 0x019a /* 0.80 * 2^RATIO_SCALE */
+#define B6T 0x00d2 /* 0.0128 * 2^LUX_SCALE */
+#define M6T 0x00fb /* 0.0153 * 2^LUX_SCALE */
+#define K7T 0x029a /* 1.3 * 2^RATIO_SCALE */
+#define B7T 0x0018 /* 0.00146 * 2^LUX_SCALE */
+#define M7T 0x0012 /* 0.00112 * 2^LUX_SCALE */
+#define K8T 0x029a /* 1.3 * 2^RATIO_SCALE */
+#define B8T 0x0000 /* 0.000 * 2^LUX_SCALE */
+#define M8T 0x0000 /* 0.000 * 2^LUX_SCALE */
+
+/******************************************************************************
+ * CS package coefficients
+ *****************************************************************************/
+/*
+ * For 0 <= Ch1/Ch0 <= 0.52
+ * Lux/Ch0 = 0.0315.0.0593*((Ch1/Ch0)^1.4)
+ * piecewise approximation
+ * For 0 <= Ch1/Ch0 <= 0.13
+ * Lux/Ch0 = 0.0315.0.0262*(Ch1/Ch0)
+ * For 0.13 <= Ch1/Ch0 <= 0.26
+ * Lux/Ch0 = 0.0337.0.0430*(Ch1/Ch0)
+ * For 0.26 <= Ch1/Ch0 <= 0.39
+ * Lux/Ch0 = 0.0363.0.0529*(Ch1/Ch0)
+ * For 0.39 <= Ch1/Ch0 <= 0.52
+ * Lux/Ch0 = 0.0392.0.0605*(Ch1/Ch0)
+ * For 0.52 < Ch1/Ch0 <= 0.65
+ * Lux/Ch0 = 0.0229.0.0291*(Ch1/Ch0)
+ * For 0.65 < Ch1/Ch0 <= 0.80
+ * Lux/Ch0 = 0.00157.0.00180*(Ch1/Ch0)
+ * For 0.80 < Ch1/Ch0 <= 1.30
+ * Lux/Ch0 = 0.00338.0.00260*(Ch1/Ch0)
+ * For Ch1/Ch0 > 1.30
+ * Lux = 0
+ */
+#define K1C 0x0043 /* 0.130 * 2^RATIO_SCALE */
+#define B1C 0x0204 /* 0.0315 * 2^LUX_SCALE */
+#define M1C 0x01ad /* 0.0262 * 2^LUX_SCALE */
+#define K2C 0x0085 /* 0.260 * 2^RATIO_SCALE */
+#define B2C 0x0228 /* 0.0337 * 2^LUX_SCALE */
+#define M2C 0x02c1 /* 0.0430 * 2^LUX_SCALE */
+#define K3C 0x00c8 /* 0.390 * 2^RATIO_SCALE */
+#define B3C 0x0253 /* 0.0363 * 2^LUX_SCALE */
+#define M3C 0x0363 /* 0.0529 * 2^LUX_SCALE */
+#define K4C 0x010a /* 0.520 * 2^RATIO_SCALE */
+#define B4C 0x0282 /* 0.0392 * 2^LUX_SCALE */
+#define M4C 0x03df /* 0.0605 * 2^LUX_SCALE */
+#define K5C 0x014d /* 0.65 * 2^RATIO_SCALE */
+#define B5C 0x0177 /* 0.0229 * 2^LUX_SCALE */
+#define M5C 0x01dd /* 0.0291 * 2^LUX_SCALE */
+#define K6C 0x019a /* 0.80 * 2^RATIO_SCALE */
+#define B6C 0x0101 /* 0.0157 * 2^LUX_SCALE */
+#define M6C 0x0127 /* 0.0180 * 2^LUX_SCALE */
+#define K7C 0x029a /* 1.3 * 2^RATIO_SCALE */
+#define B7C 0x0037 /* 0.00338 * 2^LUX_SCALE */
+#define M7C 0x002b /* 0.00260 * 2^LUX_SCALE */
+#define K8C 0x029a /* 1.3 * 2^RATIO_SCALE */
+#define B8C 0x0000 /* 0.000 * 2^LUX_SCALE */
+#define M8C 0x0000 /* 0.000 * 2^LUX_SCALE */
+
+/* TSL256x registers definition . */
+enum tsl256x_regs {
+ TSL256X_REG_CONTROL = 0x80, /* Control of basic functions */
+ TSL256X_REG_TIMING = 0x81, /* Integration time/gain control */
+ TSL256X_REG_THRESHLOWLOW = 0x82, /* Low byte of low interrupt threshold */
+ TSL256X_REG_THRESHLOWHIGH = 0x83, /* High byte of low interrupt threshold */
+ TSL256X_REG_THRESHHIGHLOW = 0x84, /* Low byte of high interrupt threshold */
+ TSL256X_REG_THRESHHIGHHIGH = 0x85, /* High byte of high interrupt threshold */
+ TSL256X_REG_INTERRUPT = 0x86, /* Interrupt control */
+ TSL256X_REG_CRC = 0x88, /* Factory test - not a user register */
+ TSL256X_REG_ID = 0x8A, /* Part number/ Rev ID */
+ TSL256X_REG_DATA0LOW = 0x8C, /* Low byte of ADC channel 0 */
+ TSL256X_REG_DATA0HIGH = 0x8D, /* High byte of ADC channel 0 */
+ TSL256X_REG_DATA1LOW = 0x8E, /* Low byte of ADC channel 1 */
+ TSL256X_REG_DATA1HIGH = 0x8F, /* High byte of ADC channel 1 */
+ __NUM_TSL256X_REGS
+};
+
+#endif /* _TSL256X_H */
+
diff --git a/include/linux/i2c-id.h b/include/linux/i2c-id.h
index 9b8ae78..a089554 100644
--- a/include/linux/i2c-id.h
+++ b/include/linux/i2c-id.h
@@ -168,6 +168,7 @@
#define I2C_DRIVERID_W83L785TS 1047
#define I2C_DRIVERID_OV7670 1048 /* Omnivision 7670 camera */
#define I2C_DRIVERID_PCF50606 1049
+#define I2C_DRIVERID_TSL256X 1050
/*
* ---- Adapter types ----------------------------------------------------
--
1.5.6.5

View file

@ -0,0 +1,56 @@
From 6635f1fbaf19b1d50e355bec73974faab070e46f Mon Sep 17 00:00:00 2001
From: mokopatches <mokopatches@openmoko.org>
Date: Fri, 4 Apr 2008 11:34:27 +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 f513ab0..bebbc14 100644
--- a/arch/arm/plat-s3c24xx/cpu.c
+++ b/arch/arm/plat-s3c24xx/cpu.c
@@ -68,6 +68,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";
@@ -119,6 +120,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.5

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,45 @@
From 56b25d1ddc3662594f9344bac89f08bcf993cc61 Mon Sep 17 00:00:00 2001
From: mokopatches <mokopatches@openmoko.org>
Date: Fri, 4 Apr 2008 11:34:44 +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.5

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 a9206f415e86249bfecccd8b6dd86ab9ee362e07 Mon Sep 17 00:00:00 2001
From: mokopatches <mokopatches@openmoko.org>
Date: Fri, 4 Apr 2008 11:35:24 +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.5

View file

@ -0,0 +1,772 @@
From c7b72aecf04a0a51e04f7d9346757c7068e0a74d Mon Sep 17 00:00:00 2001
From: mokopatches <mokopatches@openmoko.org>
Date: Fri, 4 Apr 2008 11:35:32 +0100
Subject: [PATCH] gta02-sound.patch
---
include/sound/soc-dapm.h | 2 +
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, 705 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 2b1ae8e..204be0b 100644
--- a/include/sound/soc-dapm.h
+++ b/include/sound/soc-dapm.h
@@ -206,6 +206,8 @@ int snd_soc_dapm_sys_add(struct device *dev);
/* 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 */
diff --git a/sound/soc/s3c24xx/Kconfig b/sound/soc/s3c24xx/Kconfig
index 5632a2e..4146ac4 100644
--- a/sound/soc/s3c24xx/Kconfig
+++ b/sound/soc/s3c24xx/Kconfig
@@ -25,6 +25,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 13c92f0..e356071 100644
--- a/sound/soc/s3c24xx/Makefile
+++ b/sound/soc/s3c24xx/Makefile
@@ -10,6 +10,9 @@ obj-$(CONFIG_SND_S3C2443_SOC_AC97) += snd-soc-s3c2443-ac97.o
# S3C24XX Machine Support
snd-soc-neo1973-wm8753-objs := neo1973_wm8753.o
snd-soc-smdk2443-wm9710-objs := smdk2443_wm9710.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_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 29a546f..84fa860 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -1305,6 +1305,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.5

View file

@ -0,0 +1,781 @@
From e31bab42367386736c07638683acb4da3c775eaf Mon Sep 17 00:00:00 2001
From: mokopatches <mokopatches@openmoko.org>
Date: Fri, 4 Apr 2008 11:35:42 +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 | 1 +
drivers/input/misc/lis302dl.c | 633 ++++++++++++++++++++++++++++++++++++
include/linux/lis302dl.h | 11 +
5 files changed, 699 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 8f5c7b9..5a15edd 100644
--- a/drivers/input/misc/Kconfig
+++ b/drivers/input/misc/Kconfig
@@ -183,4 +183,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 3585b50..f197a67 100644
--- a/drivers/input/misc/Makefile
+++ b/drivers/input/misc/Makefile
@@ -18,3 +18,4 @@ obj-$(CONFIG_INPUT_POWERMATE) += powermate.o
obj-$(CONFIG_INPUT_YEALINK) += yealink.o
obj-$(CONFIG_HP_SDC_RTC) += hp_sdc_rtc.o
obj-$(CONFIG_INPUT_UINPUT) += uinput.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.5

View file

@ -0,0 +1,276 @@
From b265be540c1169a5d6c32c5b09bb3f7b72a96a9d Mon Sep 17 00:00:00 2001
From: mokopatches <mokopatches@openmoko.org>
Date: Fri, 4 Apr 2008 11:35:53 +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 4579a88..2f95707 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -120,6 +120,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 f64332d..c4ff826 100644
--- a/drivers/leds/Makefile
+++ b/drivers/leds/Makefile
@@ -20,6 +20,7 @@ obj-$(CONFIG_LEDS_COBALT_RAQ) += leds-cobalt-raq.o
obj-$(CONFIG_LEDS_GPIO) += leds-gpio.o
obj-$(CONFIG_LEDS_CM_X270) += leds-cm-x270.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.5

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,200 @@
From 825154a75730a9505750384cda1dc47c6edb3a1d Mon Sep 17 00:00:00 2001
From: mokopatches <mokopatches@openmoko.org>
Date: Fri, 4 Apr 2008 11:36:10 +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.5

View file

@ -0,0 +1,209 @@
From c3baf8bae35ec67edb89c07cd8367040c95cca74 Mon Sep 17 00:00:00 2001
From: mokopatches <mokopatches@openmoko.org>
Date: Fri, 4 Apr 2008 11:36:19 +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.5

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,60 @@
From 29296aa9ec0140894c77b076806217fd19c0ce9d Mon Sep 17 00:00:00 2001
From: mokopatches <mokopatches@openmoko.org>
Date: Sun, 13 Apr 2008 07:23:47 +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 2e3a0d4..ed913da 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.5

View file

@ -0,0 +1,28 @@
From 2ea3a6a1337ce1ad496db7e650ac6301f7be34dd Mon Sep 17 00:00:00 2001
From: mokopatches <mokopatches@openmoko.org>
Date: Sun, 13 Apr 2008 07:23:47 +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 691ffb6..86ba4f1 100644
--- a/drivers/base/power/main.c
+++ b/drivers/base/power/main.c
@@ -40,9 +40,9 @@ int (*platform_enable_wakeup)(struct device *dev, int is_on);
void device_pm_add(struct device *dev)
{
- 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);
list_add_tail(&dev->power.entry, &dpm_active);
mutex_unlock(&dpm_list_mtx);
--
1.5.6.5

View file

@ -0,0 +1,40 @@
From b2b07b5cf12c430ad74b44602b098e7b711a2b72 Mon Sep 17 00:00:00 2001
From: mokopatches <mokopatches@openmoko.org>
Date: Sun, 13 Apr 2008 07:23:48 +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 e773c8e..6c93a1b 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.5

View file

@ -0,0 +1,37 @@
From 5c2f325aefe9280ae6f1220200bf40281d218fda Mon Sep 17 00:00:00 2001
From: mokopatches <mokopatches@openmoko.org>
Date: Sun, 13 Apr 2008 07:23:48 +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 be83516..0ae06bb 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.5

View file

@ -0,0 +1,28 @@
From 1d89da736ed33d3f7c398fb9f8dfddecb7c7c7a9 Mon Sep 17 00:00:00 2001
From: mokopatches <mokopatches@openmoko.org>
Date: Sun, 13 Apr 2008 07:23:48 +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 5c1c09d..f83bed9 100644
--- a/drivers/mtd/nand/s3c2410.c
+++ b/drivers/mtd/nand/s3c2410.c
@@ -658,7 +658,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.5

View file

@ -0,0 +1,74 @@
From a1ad9949db4fa268e152e9b2efb2fa5932596d63 Mon Sep 17 00:00:00 2001
From: mokopatches <mokopatches@openmoko.org>
Date: Sun, 13 Apr 2008 07:23:49 +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 9af05a2..272e0ec 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -1209,7 +1209,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,
@@ -1385,7 +1385,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 5717509..c6235e1 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[] __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[] __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.5

View file

@ -0,0 +1,311 @@
From 9deba66bfaf3a3293436e405830a666df8f36ed6 Mon Sep 17 00:00:00 2001
From: mokopatches <mokopatches@openmoko.org>
Date: Sun, 13 Apr 2008 07:23:49 +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 3b9990e..a61ca45 100644
--- a/drivers/input/keyboard/Kconfig
+++ b/drivers/input/keyboard/Kconfig
@@ -304,5 +304,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 68ecfc5..34bfc33 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_HIL) += hil_kbd.o
obj-$(CONFIG_KEYBOARD_HIL_OLD) += hilkbd.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.5

View file

@ -0,0 +1,27 @@
From 13a8a1f0848115f23553d15f15aa2b836f459614 Mon Sep 17 00:00:00 2001
From: mokopatches <mokopatches@openmoko.org>
Date: Sun, 13 Apr 2008 07:23:49 +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.5

View file

@ -0,0 +1,26 @@
From f8c4e2db8608131a88c6c0f17d55cbd540d32ec8 Mon Sep 17 00:00:00 2001
From: mokopatches <mokopatches@openmoko.org>
Date: Sun, 13 Apr 2008 07:23:50 +0100
Subject: [PATCH] montour-audio.patch
http://bugzilla.openmoko.org/cgi-bin/bugzilla/show_bug.cgi?id=1190
---
sound/soc/codecs/wm8753.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c
index 52207d5..3df5b44 100644
--- a/sound/soc/codecs/wm8753.c
+++ b/sound/soc/codecs/wm8753.c
@@ -279,7 +279,7 @@ SOC_DOUBLE_R("Speaker Playback ZC Switch", WM8753_LOUT2V, WM8753_ROUT2V, 7, 1, 0
SOC_SINGLE("Mono Bypass Playback Volume", WM8753_MOUTM1, 4, 7, 1),
SOC_SINGLE("Mono Sidetone Playback Volume", WM8753_MOUTM2, 4, 7, 1),
-SOC_SINGLE("Mono Voice Playback Volume", WM8753_MOUTM2, 4, 7, 1),
+SOC_SINGLE("Mono Voice Playback Volume", WM8753_MOUTM2, 0, 7, 1),
SOC_SINGLE("Mono Playback ZC Switch", WM8753_MOUTV, 7, 1, 0),
SOC_ENUM("Bass Boost", wm8753_enum[0]),
--
1.5.6.5

View file

@ -0,0 +1,601 @@
From f83b2007a1e3552a5f15faacf42f7383cd73129a Mon Sep 17 00:00:00 2001
From: mokopatches <mokopatches@openmoko.org>
Date: Sun, 13 Apr 2008 07:23:50 +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/arch-s3c2410/irqs.h | 4 +
include/asm-arm/plat-s3c24xx/irq.h | 20 ++
9 files changed, 426 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 1fab1c0..f7bea5d 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 5305fdb..e3ca9e3 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 8fbc884..82f0b04 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/arch-s3c2410/irqs.h b/include/asm-arm/arch-s3c2410/irqs.h
index 9522cd1..ab50ffb 100644
--- a/include/asm-arm/arch-s3c2410/irqs.h
+++ b/include/asm-arm/arch-s3c2410/irqs.h
@@ -188,4 +188,8 @@
#define IRQ_GLAMO_MMC IRQ_GLAMO(7)
#define IRQ_GLAMO_RISC IRQ_GLAMO(8)
+/* offset for FIQ IRQ numbers - used by arm fiq.c */
+
+#define FIQ_START 0
+
#endif /* __ASM_ARCH_IRQ_H */
diff --git a/include/asm-arm/plat-s3c24xx/irq.h b/include/asm-arm/plat-s3c24xx/irq.h
index 8af6d95..f70b1fc 100644
--- a/include/asm-arm/plat-s3c24xx/irq.h
+++ b/include/asm-arm/plat-s3c24xx/irq.h
@@ -23,8 +23,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));
@@ -37,6 +44,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
}
@@ -45,8 +55,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));
@@ -55,6 +72,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.5

View file

@ -0,0 +1,220 @@
From 4ef3bf9d0e7ffd1e70f24e47b7ede98258c8b8f4 Mon Sep 17 00:00:00 2001
From: mokopatches <mokopatches@openmoko.org>
Date: Sun, 13 Apr 2008 07:23:51 +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.5

View file

@ -0,0 +1,243 @@
From b1b2748dd58ae925df4b4e98921db373a7777e9b Mon Sep 17 00:00:00 2001
From: mokopatches <mokopatches@openmoko.org>
Date: Sun, 13 Apr 2008 07:23:52 +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 2f95707..77aa3bd 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -117,6 +117,7 @@ config LEDS_CM_X270
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.5

View file

@ -0,0 +1,606 @@
From 7ffc881aa6a039b2e353449b97dca8a64ee3969a Mon Sep 17 00:00:00 2001
From: mokopatches <mokopatches@openmoko.org>
Date: Sun, 13 Apr 2008 07:23:52 +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.5

View file

@ -0,0 +1,510 @@
From 40d5d4e980e0d4a5d00759f7fa2a18488f95a0ef Mon Sep 17 00:00:00 2001
From: mokopatches <mokopatches@openmoko.org>
Date: Sun, 13 Apr 2008 07:23:52 +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 f7bea5d..71719ac 100644
--- a/arch/arm/mach-s3c2440/Kconfig
+++ b/arch/arm/mach-s3c2440/Kconfig
@@ -85,6 +85,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.5

View file

@ -0,0 +1,95 @@
From a6b37451a52ae7d30c2493b9cc14b8604e81587d Mon Sep 17 00:00:00 2001
From: mokopatches <mokopatches@openmoko.org>
Date: Sun, 13 Apr 2008 07:23:53 +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 e5b4e9b..2f3d825 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();
@@ -135,14 +132,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;
@@ -150,12 +148,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;
}
@@ -230,7 +228,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.5

View file

@ -0,0 +1,75 @@
From 148a1026b1975e3a50981cf7df3d4aae2b34611e Mon Sep 17 00:00:00 2001
From: mokopatches <mokopatches@openmoko.org>
Date: Sun, 13 Apr 2008 07:23:53 +0100
Subject: [PATCH] iis-suspend.patch
---
sound/soc/s3c24xx/s3c24xx-i2s.c | 38 ++++++++++++++++++++++++++++++++++++++
1 files changed, 38 insertions(+), 0 deletions(-)
diff --git a/sound/soc/s3c24xx/s3c24xx-i2s.c b/sound/soc/s3c24xx/s3c24xx-i2s.c
index fe30e0d..4d74cc0 100644
--- a/sound/soc/s3c24xx/s3c24xx-i2s.c
+++ b/sound/soc/s3c24xx/s3c24xx-i2s.c
@@ -76,6 +76,10 @@ static struct s3c24xx_pcm_dma_params s3c24xx_i2s_pcm_stereo_in = {
struct s3c24xx_i2s_info {
void __iomem *regs;
struct clk *iis_clk;
+ u32 iiscon;
+ u32 iismod;
+ u32 iisfcon;
+ u32 iispsr;
};
static struct s3c24xx_i2s_info s3c24xx_i2s;
@@ -406,6 +410,38 @@ static int s3c24xx_i2s_probe(struct platform_device *pdev)
return 0;
}
+#ifdef CONFIG_PM
+int s3c24xx_i2s_suspend(struct platform_device *pdev,
+ struct snd_soc_cpu_dai *cpu_dai)
+{
+ s3c24xx_i2s.iiscon = readl(s3c24xx_i2s.regs + S3C2410_IISCON);
+ s3c24xx_i2s.iismod = readl(s3c24xx_i2s.regs + S3C2410_IISMOD);
+ s3c24xx_i2s.iisfcon = readl(s3c24xx_i2s.regs + S3C2410_IISFCON);
+ s3c24xx_i2s.iispsr = readl(s3c24xx_i2s.regs + S3C2410_IISPSR);
+
+ clk_disable(s3c24xx_i2s.iis_clk);
+
+ return 0;
+}
+
+int s3c24xx_i2s_resume(struct platform_device *pdev,
+ struct snd_soc_cpu_dai *cpu_dai)
+{
+ clk_enable(s3c24xx_i2s.iis_clk);
+
+ writel(s3c24xx_i2s.iiscon, s3c24xx_i2s.regs + S3C2410_IISCON);
+ writel(s3c24xx_i2s.iismod, s3c24xx_i2s.regs + S3C2410_IISMOD);
+ writel(s3c24xx_i2s.iisfcon, s3c24xx_i2s.regs + S3C2410_IISFCON);
+ writel(s3c24xx_i2s.iispsr, s3c24xx_i2s.regs + S3C2410_IISPSR);
+
+ return 0;
+}
+#else
+#define s3c24xx_i2s_suspend NULL
+#define s3c24xx_i2s_resume NULL
+#endif
+
+
#define S3C24XX_I2S_RATES \
(SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | SNDRV_PCM_RATE_16000 | \
SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \
@@ -416,6 +452,8 @@ struct snd_soc_cpu_dai s3c24xx_i2s_dai = {
.id = 0,
.type = SND_SOC_DAI_I2S,
.probe = s3c24xx_i2s_probe,
+ .suspend = s3c24xx_i2s_suspend,
+ .resume = s3c24xx_i2s_resume,
.playback = {
.channels_min = 2,
.channels_max = 2,
--
1.5.6.5

View file

@ -0,0 +1,85 @@
From 1179eb1bf9d827aaa2b4b6adc4ba135bf9074bcc Mon Sep 17 00:00:00 2001
From: mokopatches <mokopatches@openmoko.org>
Date: Sun, 13 Apr 2008 07:23:53 +0100
Subject: [PATCH] s3c24xx-pcm-suspend.patch
---
sound/soc/s3c24xx/s3c24xx-pcm.c | 48 ++++++++++++++++++++------------------
1 files changed, 25 insertions(+), 23 deletions(-)
diff --git a/sound/soc/s3c24xx/s3c24xx-pcm.c b/sound/soc/s3c24xx/s3c24xx-pcm.c
index 4107a87..e9f3b60 100644
--- a/sound/soc/s3c24xx/s3c24xx-pcm.c
+++ b/sound/soc/s3c24xx/s3c24xx-pcm.c
@@ -49,7 +49,9 @@ static const struct snd_pcm_hardware s3c24xx_pcm_hardware = {
.info = SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER |
SNDRV_PCM_INFO_MMAP |
- SNDRV_PCM_INFO_MMAP_VALID,
+ SNDRV_PCM_INFO_MMAP_VALID |
+ SNDRV_PCM_INFO_PAUSE |
+ SNDRV_PCM_INFO_RESUME,
.formats = SNDRV_PCM_FMTBIT_S16_LE |
SNDRV_PCM_FMTBIT_U16_LE |
SNDRV_PCM_FMTBIT_U8 |
@@ -176,28 +178,6 @@ static int s3c24xx_pcm_hw_params(struct snd_pcm_substream *substream,
}
}
- /* channel needs configuring for mem=>device, increment memory addr,
- * sync to pclk, half-word transfers to the IIS-FIFO. */
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
- s3c2410_dma_devconfig(prtd->params->channel,
- S3C2410_DMASRC_MEM, S3C2410_DISRCC_INC |
- S3C2410_DISRCC_APB, prtd->params->dma_addr);
-
- s3c2410_dma_config(prtd->params->channel,
- prtd->params->dma_size,
- S3C2410_DCON_SYNC_PCLK |
- S3C2410_DCON_HANDSHAKE);
- } else {
- s3c2410_dma_config(prtd->params->channel,
- prtd->params->dma_size,
- S3C2410_DCON_HANDSHAKE |
- S3C2410_DCON_SYNC_PCLK);
-
- s3c2410_dma_devconfig(prtd->params->channel,
- S3C2410_DMASRC_HW, 0x3,
- prtd->params->dma_addr);
- }
-
s3c2410_dma_set_buffdone_fn(prtd->params->channel,
s3c24xx_audio_buffdone);
@@ -246,6 +226,28 @@ static int s3c24xx_pcm_prepare(struct snd_pcm_substream *substream)
if (!prtd->params)
return 0;
+ /* channel needs configuring for mem=>device, increment memory addr,
+ * sync to pclk, half-word transfers to the IIS-FIFO. */
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ s3c2410_dma_devconfig(prtd->params->channel,
+ S3C2410_DMASRC_MEM, S3C2410_DISRCC_INC |
+ S3C2410_DISRCC_APB, prtd->params->dma_addr);
+
+ s3c2410_dma_config(prtd->params->channel,
+ prtd->params->dma_size,
+ S3C2410_DCON_SYNC_PCLK |
+ S3C2410_DCON_HANDSHAKE);
+ } else {
+ s3c2410_dma_config(prtd->params->channel,
+ prtd->params->dma_size,
+ S3C2410_DCON_HANDSHAKE |
+ S3C2410_DCON_SYNC_PCLK);
+
+ s3c2410_dma_devconfig(prtd->params->channel,
+ S3C2410_DMASRC_HW, 0x3,
+ prtd->params->dma_addr);
+ }
+
/* flush the DMA channel */
s3c2410_dma_ctrl(prtd->params->channel, S3C2410_DMAOP_FLUSH);
prtd->dma_loaded = 0;
--
1.5.6.5

View file

@ -0,0 +1,89 @@
From e98d739947484f7ca2cf0fe017fda73cab63067a Mon Sep 17 00:00:00 2001
From: mokopatches <mokopatches@openmoko.org>
Date: Sun, 13 Apr 2008 07:23:54 +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 44b79e8..68f5689 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.5

View file

@ -0,0 +1,46 @@
From 30659e6b5f8c44bc80a0e79ae2b40e7208ac2b51 Mon Sep 17 00:00:00 2001
From: mokopatches <mokopatches@openmoko.org>
Date: Sun, 13 Apr 2008 07:23:54 +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 e50ebcf..60d2b1b 100644
--- a/drivers/pnp/resource.c
+++ b/drivers/pnp/resource.c
@@ -431,6 +431,7 @@ int pnp_check_dma(struct pnp_dev *dev, int idx)
}
}
+#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) {
@@ -438,6 +439,7 @@ int pnp_check_dma(struct pnp_dev *dev, int idx)
return 0;
free_dma(*dma);
}
+#endif
/* check for conflicts with other pnp devices */
pnp_for_each_dev(tdev) {
--
1.5.6.5

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,66 @@
From b6817bed9516a65276ee92437697cb46136df882 Mon Sep 17 00:00:00 2001
From: mokopatches <mokopatches@openmoko.org>
Date: Sun, 13 Apr 2008 07:23:57 +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 | 28 +++++++++++++---------------
1 files changed, 13 insertions(+), 15 deletions(-)
diff --git a/drivers/mtd/nand/s3c2410.c b/drivers/mtd/nand/s3c2410.c
index f83bed9..f7dd4e0 100644
--- a/drivers/mtd/nand/s3c2410.c
+++ b/drivers/mtd/nand/s3c2410.c
@@ -364,23 +364,21 @@ static int s3c2410_nand_correct_data(struct mtd_info *mtd, u_char *dat,
((diff2 ^ (diff2 >> 1)) & 0x55) == 0x55) {
/* calculate the bit position of the error */
- bit = (diff2 >> 2) & 1;
- bit |= (diff2 >> 3) & 2;
- bit |= (diff2 >> 4) & 4;
+ bit = ((diff2 >> 3) & 1) |
+ ((diff2 >> 4) & 2) |
+ ((diff2 >> 5) & 4);
/* calculate the byte position of the error */
- byte = (diff1 << 1) & 0x80;
- byte |= (diff1 << 2) & 0x40;
- byte |= (diff1 << 3) & 0x20;
- byte |= (diff1 << 4) & 0x10;
-
- byte |= (diff0 >> 3) & 0x08;
- byte |= (diff0 >> 2) & 0x04;
- byte |= (diff0 >> 1) & 0x02;
- byte |= (diff0 >> 0) & 0x01;
-
- byte |= (diff2 << 8) & 0x100;
+ byte = ((diff2 << 7) & 0x100) |
+ ((diff1 << 0) & 0x80) |
+ ((diff1 << 1) & 0x40) |
+ ((diff1 << 2) & 0x20) |
+ ((diff1 << 3) & 0x10) |
+ ((diff0 >> 4) & 0x08) |
+ ((diff0 >> 3) & 0x04) |
+ ((diff0 >> 2) & 0x02) |
+ ((diff0 >> 1) & 0x01);
dev_dbg(info->device, "correcting error bit %d, byte %d\n",
bit, byte);
@@ -399,7 +397,7 @@ static int s3c2410_nand_correct_data(struct mtd_info *mtd, u_char *dat,
if ((diff0 & ~(1<<fls(diff0))) == 0)
return 1;
- return 0;
+ return -EBADMSG;
}
/* ECC functions
--
1.5.6.5

View file

@ -0,0 +1,83 @@
From 530be0418a0d05cad538ff62ae16b43d2d4462e3 Mon Sep 17 00:00:00 2001
From: mokopatches <mokopatches@openmoko.org>
Date: Sun, 13 Apr 2008 07:23:57 +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.5

View file

@ -0,0 +1,86 @@
From 5a95dab616822e33d6526965b46eae98717537ea Mon Sep 17 00:00:00 2001
From: mokopatches <mokopatches@openmoko.org>
Date: Sun, 13 Apr 2008 07:23:58 +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.5

View file

@ -0,0 +1,44 @@
From f76a7a9e4e1cf2224e028e78a6869d3e8375dbe3 Mon Sep 17 00:00:00 2001
From: mokopatches <mokopatches@openmoko.org>
Date: Sun, 13 Apr 2008 07:23:58 +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 6c93a1b..b566f42 100644
--- a/drivers/serial/s3c2410.c
+++ b/drivers/serial/s3c2410.c
@@ -1717,9 +1717,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.5

View file

@ -0,0 +1,316 @@
From 68bcfea9ab5d8947f711a97dcc291cb9da47c7da Mon Sep 17 00:00:00 2001
From: mokopatches <mokopatches@openmoko.org>
Date: Sun, 13 Apr 2008 07:23:59 +0100
Subject: [PATCH] kexec-atags.patch
Leapfrogged from upstream (ARM Linux)
http://www.arm.linux.org.uk/developer/patches/viewpatch.php?id=4736/1
---
arch/arm/Kconfig | 7 +++
arch/arm/kernel/Makefile | 1 +
arch/arm/kernel/atags.c | 86 +++++++++++++++++++++++++++++++++++++
arch/arm/kernel/atags.h | 5 ++
arch/arm/kernel/machine_kexec.c | 2 +
arch/arm/kernel/relocate_kernel.S | 30 ++-----------
arch/arm/kernel/setup.c | 32 +-------------
include/asm-arm/kexec.h | 3 +
8 files changed, 110 insertions(+), 56 deletions(-)
create mode 100644 arch/arm/kernel/atags.c
create mode 100644 arch/arm/kernel/atags.h
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 23e3d6b..ef7b9ff 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -865,6 +865,13 @@ config KEXEC
initially work for you. It may help to enable device hotplugging
support.
+config ATAGS_PROC
+ bool "Export atags in procfs"
+ default n
+ help
+ Should the atags used to boot the kernel be exported in an "atags"
+ file in procfs. Useful with kexec.
+
endmenu
if (ARCH_SA1100 || ARCH_INTEGRATOR || ARCH_OMAP || ARCH_IMX )
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
index 593b565..5cf694c 100644
--- a/arch/arm/kernel/Makefile
+++ b/arch/arm/kernel/Makefile
@@ -19,6 +19,7 @@ obj-$(CONFIG_ISA_DMA) += dma-isa.o
obj-$(CONFIG_PCI) += bios32.o isa.o
obj-$(CONFIG_SMP) += smp.o
obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o
+obj-$(CONFIG_ATAGS_PROC) += atags.o
obj-$(CONFIG_OABI_COMPAT) += sys_oabi-compat.o
obj-$(CONFIG_CRUNCH) += crunch.o crunch-bits.o
diff --git a/arch/arm/kernel/atags.c b/arch/arm/kernel/atags.c
new file mode 100644
index 0000000..e2e934c
--- /dev/null
+++ b/arch/arm/kernel/atags.c
@@ -0,0 +1,86 @@
+#include <linux/slab.h>
+#include <linux/kexec.h>
+#include <linux/proc_fs.h>
+#include <asm/setup.h>
+#include <asm/types.h>
+#include <asm/page.h>
+
+struct buffer {
+ size_t size;
+ char *data;
+};
+static struct buffer tags_buffer;
+
+static int
+read_buffer(char* page, char** start, off_t off, int count,
+ int* eof, void* data)
+{
+ struct buffer *buffer = (struct buffer *)data;
+
+ if (off >= buffer->size) {
+ *eof = 1;
+ return 0;
+ }
+
+ count = min((int) (buffer->size - off), count);
+
+ memcpy(page, &buffer->data[off], count);
+
+ return count;
+}
+
+
+static int
+create_proc_entries(void)
+{
+ struct proc_dir_entry* tags_entry;
+
+ tags_entry = create_proc_read_entry("atags", 0400, &proc_root, read_buffer, &tags_buffer);
+ if (!tags_entry)
+ return -ENOMEM;
+
+ return 0;
+}
+
+
+static char __initdata atags_copy_buf[KEXEC_BOOT_PARAMS_SIZE];
+static char __initdata *atags_copy;
+
+void __init save_atags(const struct tag *tags)
+{
+ atags_copy = atags_copy_buf;
+ memcpy(atags_copy, tags, KEXEC_BOOT_PARAMS_SIZE);
+}
+
+
+static int __init init_atags_procfs(void)
+{
+ struct tag *tag;
+ int error;
+
+ if (!atags_copy) {
+ printk(KERN_WARNING "Exporting ATAGs: No saved tags found\n");
+ return -EIO;
+ }
+
+ for (tag = (struct tag *) atags_copy; tag->hdr.size; tag = tag_next(tag))
+ ;
+
+ tags_buffer.size = ((char *) tag - atags_copy) + sizeof(tag->hdr);
+ tags_buffer.data = kmalloc(tags_buffer.size, GFP_KERNEL);
+ if (tags_buffer.data == NULL)
+ return -ENOMEM;
+ memcpy(tags_buffer.data, atags_copy, tags_buffer.size);
+
+ error = create_proc_entries();
+ if (error) {
+ printk(KERN_ERR "Exporting ATAGs: not enough memory\n");
+ kfree(tags_buffer.data);
+ tags_buffer.size = 0;
+ tags_buffer.data = NULL;
+ }
+
+ return error;
+}
+
+arch_initcall(init_atags_procfs);
diff --git a/arch/arm/kernel/atags.h b/arch/arm/kernel/atags.h
new file mode 100644
index 0000000..e5f028d
--- /dev/null
+++ b/arch/arm/kernel/atags.h
@@ -0,0 +1,5 @@
+#ifdef CONFIG_ATAGS_PROC
+extern void save_atags(struct tag *tags);
+#else
+static inline void save_atags(struct tag *tags) { }
+#endif
diff --git a/arch/arm/kernel/machine_kexec.c b/arch/arm/kernel/machine_kexec.c
index 863c664..db8f54a 100644
--- a/arch/arm/kernel/machine_kexec.c
+++ b/arch/arm/kernel/machine_kexec.c
@@ -21,6 +21,7 @@ extern void setup_mm_for_reboot(char mode);
extern unsigned long kexec_start_address;
extern unsigned long kexec_indirection_page;
extern unsigned long kexec_mach_type;
+extern unsigned long kexec_boot_atags;
/*
* Provide a dummy crash_notes definition while crash dump arrives to arm.
@@ -62,6 +63,7 @@ void machine_kexec(struct kimage *image)
kexec_start_address = image->start;
kexec_indirection_page = page_list;
kexec_mach_type = machine_arch_type;
+ kexec_boot_atags = image->start - KEXEC_ARM_ZIMAGE_OFFSET + KEXEC_ARM_ATAGS_OFFSET;
/* copy our kernel relocation code to the control code page */
memcpy(reboot_code_buffer,
diff --git a/arch/arm/kernel/relocate_kernel.S b/arch/arm/kernel/relocate_kernel.S
index 062c111..61930eb 100644
--- a/arch/arm/kernel/relocate_kernel.S
+++ b/arch/arm/kernel/relocate_kernel.S
@@ -7,23 +7,6 @@
.globl relocate_new_kernel
relocate_new_kernel:
- /* Move boot params back to where the kernel expects them */
-
- ldr r0,kexec_boot_params_address
- teq r0,#0
- beq 8f
-
- ldr r1,kexec_boot_params_copy
- mov r6,#KEXEC_BOOT_PARAMS_SIZE/4
-7:
- ldr r5,[r1],#4
- str r5,[r0],#4
- subs r6,r6,#1
- bne 7b
-
-8:
- /* Boot params moved, now go on with the kernel */
-
ldr r0,kexec_indirection_page
ldr r1,kexec_start_address
@@ -67,7 +50,7 @@ relocate_new_kernel:
mov lr,r1
mov r0,#0
ldr r1,kexec_mach_type
- ldr r2,kexec_boot_params_address
+ ldr r2,kexec_boot_atags
mov pc,lr
.globl kexec_start_address
@@ -82,14 +65,9 @@ kexec_indirection_page:
kexec_mach_type:
.long 0x0
- /* phy addr where new kernel will expect to find boot params */
- .globl kexec_boot_params_address
-kexec_boot_params_address:
- .long 0x0
-
- /* phy addr where old kernel put a copy of orig boot params */
- .globl kexec_boot_params_copy
-kexec_boot_params_copy:
+ /* phy addr of the atags for the new kernel */
+ .globl kexec_boot_atags
+kexec_boot_atags:
.long 0x0
relocate_new_kernel_end:
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index bf56eb3..ae3712d 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -24,7 +24,6 @@
#include <linux/interrupt.h>
#include <linux/smp.h>
#include <linux/fs.h>
-#include <linux/kexec.h>
#include <asm/cpu.h>
#include <asm/elf.h>
@@ -39,6 +38,7 @@
#include <asm/mach/time.h>
#include "compat.h"
+#include "atags.h"
#ifndef MEM_SIZE
#define MEM_SIZE (16*1024*1024)
@@ -784,23 +784,6 @@ static int __init customize_machine(void)
}
arch_initcall(customize_machine);
-#ifdef CONFIG_KEXEC
-
-/* Physical addr of where the boot params should be for this machine */
-extern unsigned long kexec_boot_params_address;
-
-/* Physical addr of the buffer into which the boot params are copied */
-extern unsigned long kexec_boot_params_copy;
-
-/* Pointer to the boot params buffer, for manipulation and display */
-unsigned long kexec_boot_params;
-EXPORT_SYMBOL(kexec_boot_params);
-
-/* The buffer itself - make sure it is sized correctly */
-static unsigned long kexec_boot_params_buf[(KEXEC_BOOT_PARAMS_SIZE + 3) / 4];
-
-#endif
-
void __init setup_arch(char **cmdline_p)
{
struct tag *tags = (struct tag *)&init_tags;
@@ -819,18 +802,6 @@ void __init setup_arch(char **cmdline_p)
else if (mdesc->boot_params)
tags = phys_to_virt(mdesc->boot_params);
-#ifdef CONFIG_KEXEC
- kexec_boot_params_copy = virt_to_phys(kexec_boot_params_buf);
- kexec_boot_params = (unsigned long)kexec_boot_params_buf;
- if (__atags_pointer) {
- kexec_boot_params_address = __atags_pointer;
- memcpy((void *)kexec_boot_params, tags, KEXEC_BOOT_PARAMS_SIZE);
- } else if (mdesc->boot_params) {
- kexec_boot_params_address = mdesc->boot_params;
- memcpy((void *)kexec_boot_params, tags, KEXEC_BOOT_PARAMS_SIZE);
- }
-#endif
-
/*
* If we have the old style parameters, convert them to
* a tag list.
@@ -846,6 +817,7 @@ void __init setup_arch(char **cmdline_p)
if (tags->hdr.tag == ATAG_CORE) {
if (meminfo.nr_banks != 0)
squash_mem_tags(tags);
+ save_atags(tags);
parse_tags(tags);
}
diff --git a/include/asm-arm/kexec.h b/include/asm-arm/kexec.h
index 46dcc4d..1ee17b6 100644
--- a/include/asm-arm/kexec.h
+++ b/include/asm-arm/kexec.h
@@ -16,6 +16,9 @@
#define KEXEC_BOOT_PARAMS_SIZE 1536
+#define KEXEC_ARM_ATAGS_OFFSET 0x1000
+#define KEXEC_ARM_ZIMAGE_OFFSET 0x8000
+
#ifndef __ASSEMBLY__
struct kimage;
--
1.5.6.5

View file

@ -0,0 +1,98 @@
From a3ce0f5da32538cdf96c1dc1d6dc8b7452b096d2 Mon Sep 17 00:00:00 2001
From: mokopatches <mokopatches@openmoko.org>
Date: Sun, 13 Apr 2008 07:23:59 +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 2c802de..405c957 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
@@ -136,10 +135,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)
@@ -148,10 +153,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.5

View file

@ -0,0 +1,29 @@
From 627dc473972450148330e4c4c3c2dd43798c1c26 Mon Sep 17 00:00:00 2001
From: mokopatches <mokopatches@openmoko.org>
Date: Sun, 13 Apr 2008 07:23:59 +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 3df5b44..e9ad1aa 100644
--- a/sound/soc/codecs/wm8753.c
+++ b/sound/soc/codecs/wm8753.c
@@ -1585,6 +1585,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.5

View file

@ -0,0 +1,81 @@
From ce8eaeee7875e668be4c2888fa05a61a5af0dd98 Mon Sep 17 00:00:00 2001
From: mokopatches <mokopatches@openmoko.org>
Date: Sun, 13 Apr 2008 07:23:59 +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.5

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,53 @@
From 3801eb47f3ce58d2f8b64089ab01d85edf19f441 Mon Sep 17 00:00:00 2001
From: warmcat <andy@warmcat.com>
Date: Sun, 13 Apr 2008 07:25:44 +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.5

View file

@ -0,0 +1,31 @@
From 2f8f225597218a1b838f70dc8f7d9216c40cd4c0 Mon Sep 17 00:00:00 2001
From: warmcat <andy@warmcat.com>
Date: Sun, 13 Apr 2008 07:25:44 +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.5

View file

@ -0,0 +1,72 @@
From fb75c4b67418f06a86a1a8f07614c618e496bc14 Mon Sep 17 00:00:00 2001
From: warmcat <andy@warmcat.com>
Date: Sun, 13 Apr 2008 07:25:45 +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.5

View file

@ -0,0 +1,44 @@
From 7eb5d3249a17af091630b6fa8392ed1e268962f6 Mon Sep 17 00:00:00 2001
From: warmcat <andy@openmoko.com>
Date: Sun, 13 Apr 2008 07:25:45 +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.5

View file

@ -0,0 +1,155 @@
From e1f4e75f4f146f534f659f2c9cf525387d4d734a Mon Sep 17 00:00:00 2001
From: warmcat <andy@warmcat.com>
Date: Sun, 13 Apr 2008 07:25:46 +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.5

View file

@ -0,0 +1,36 @@
From b0eec76126c38ed02f0af80ebf65801d46e6e261 Mon Sep 17 00:00:00 2001
From: warmcat <andy@openmoko.com>
Date: Sun, 13 Apr 2008 07:25:46 +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.5

View file

@ -0,0 +1,34 @@
From 5c6c019690dac8b5f8d76732c8fd387ff7a27f2d Mon Sep 17 00:00:00 2001
From: warmcat <andy@warmcat.com>
Date: Sun, 13 Apr 2008 07:25:46 +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.5

View file

@ -0,0 +1,25 @@
From 9f90b78f834e3d18520c03af4644ff239a2e891b Mon Sep 17 00:00:00 2001
From: warmcat <andy@warmcat.com>
Date: Sun, 13 Apr 2008 07:25:46 +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.5

View file

@ -0,0 +1,108 @@
From 293025ae0e971da194ecb58be304835f246b6c9e Mon Sep 17 00:00:00 2001
From: Mike Montour <mail@mmontour.net>
Date: Sun, 13 Apr 2008 07:25:47 +0100
Subject: [PATCH] contrib-fix-chgstate-array-bloat.patch
--- linux-2.6.22/drivers/i2c/chips/pcf50606.c.orig 2008-01-17 22:30:16.000000000 -0800
+++ linux-2.6.22/drivers/i2c/chips/pcf50606.c 2008-01-17 22:31:43.000000000 -0800
@@ -71,12 +71,19 @@
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
@@ -1026,12 +1033,12 @@
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,
---
drivers/i2c/chips/pcf50606.c | 31 +++++++++++++++++++------------
1 files changed, 19 insertions(+), 12 deletions(-)
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.5

View file

@ -0,0 +1,43 @@
From e05285e4b6a3fa1134d40e91c5a345392e7efba0 Mon Sep 17 00:00:00 2001
From: warmcat <andy@openmoko.com>
Date: Sun, 13 Apr 2008 07:25:47 +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.5

View file

@ -0,0 +1,31 @@
From 41b2c45d068da0467272ca843e05a13f0e262be6 Mon Sep 17 00:00:00 2001
From: warmcat <andy@openmoko.com>
Date: Sun, 13 Apr 2008 07:25:47 +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.5

View file

@ -0,0 +1,87 @@
From ab6e925546e3d3361ab59c2b090eccf0cb411c7b Mon Sep 17 00:00:00 2001
From: Andy Green <andy@openmoko.com>
Date: Sun, 13 Apr 2008 07:25:48 +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.5

View file

@ -0,0 +1,73 @@
From 7b70de51df68659d3789481cf2446f8bc01e5387 Mon Sep 17 00:00:00 2001
From: Andy Green <andy@openmoko.com>
Date: Sun, 13 Apr 2008 07:25:48 +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.5

View file

@ -0,0 +1,451 @@
From 475826b7d7ef66e80b64d97ea9e8aca56d97e313 Mon Sep 17 00:00:00 2001
From: Andy Green <andy@openmoko.com>
Date: Sun, 13 Apr 2008 07:25:49 +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 | 420 ++++++++++++++++++++++++++++++++++++++++++
1 files changed, 420 insertions(+), 0 deletions(-)
diff --git a/arch/arm/plat-s3c24xx/gpio.c b/arch/arm/plat-s3c24xx/gpio.c
index ec3a09c..7cab212 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)
{
@@ -186,3 +187,422 @@ int s3c2410_gpio_getirq(unsigned int pin)
}
EXPORT_SYMBOL(s3c2410_gpio_getirq);
+
+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.5

View file

@ -0,0 +1,128 @@
From 6ce7c9b239314f4ee9f86164da8aaf5f78c0d1f1 Mon Sep 17 00:00:00 2001
From: warmcat <andy@warmcat.com>
Date: Sun, 13 Apr 2008 07:25:49 +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 c11d0dd..6989eea 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
@@ -201,9 +202,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;
@@ -212,6 +216,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 */
@@ -247,10 +256,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.5

View file

@ -0,0 +1,97 @@
From f5cedbb7cda510235de0783fea77ad8e028d1002 Mon Sep 17 00:00:00 2001
From: warmcat <andy@warmcat.com>
Date: Sun, 13 Apr 2008 07:25:49 +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.5

View file

@ -0,0 +1,73 @@
From 99fbe6e31e09c9000668b50a87b3bbb834a145d0 Mon Sep 17 00:00:00 2001
From: Andy Green <andy@openmoko.com>
Date: Sun, 13 Apr 2008 07:25:50 +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.5

View file

@ -0,0 +1,286 @@
From bcf06c774c2c55fbd05b74ea01f1a2a6b3de2dc7 Mon Sep 17 00:00:00 2001
From: warmcat <andy@warmcat.com>
Date: Sun, 13 Apr 2008 07:25:50 +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.5

View file

@ -0,0 +1,141 @@
From a8ee32310d3ed6fe66e639314ccae72d2fbbc886 Mon Sep 17 00:00:00 2001
From: warmcat <andy@warmcat.com>
Date: Sun, 13 Apr 2008 07:25:50 +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.5

View file

@ -0,0 +1,51 @@
From a320183ac1d4bd8a430ef9f3e3b957ed4177454b Mon Sep 17 00:00:00 2001
From: Willie <willie_chen@openmoko.com>
Date: Sun, 13 Apr 2008 07:25:50 +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.5

View file

@ -0,0 +1,58 @@
From 565f2987435711c4ac154e7cc12a03eedce2bfdb Mon Sep 17 00:00:00 2001
From: warmcat <andy@warmcat.com>
Date: Sun, 13 Apr 2008 07:25:50 +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.5

View file

@ -0,0 +1,167 @@
From 20369a802d4df104489daeb85388554f79e7e281 Mon Sep 17 00:00:00 2001
From: Andy Green <andy@openmoko.com>
Date: Sun, 13 Apr 2008 07:25:51 +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 7192912..e1686a0 100644
--- a/arch/arm/plat-s3c24xx/Makefile
+++ b/arch/arm/plat-s3c24xx/Makefile
@@ -28,4 +28,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.5

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