aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm')
-rw-r--r--arch/arm/configs/tuna_defconfig382
-rw-r--r--arch/arm/mach-omap2/Kconfig9
-rw-r--r--arch/arm/mach-omap2/Makefile17
-rw-r--r--arch/arm/mach-omap2/board-omap4panda.c3
-rw-r--r--arch/arm/mach-omap2/board-tuna-bluetooth.c306
-rw-r--r--arch/arm/mach-omap2/board-tuna-connector.c774
-rw-r--r--arch/arm/mach-omap2/board-tuna-display.c955
-rw-r--r--arch/arm/mach-omap2/board-tuna-emif.c107
-rw-r--r--arch/arm/mach-omap2/board-tuna-input.c183
-rw-r--r--arch/arm/mach-omap2/board-tuna-jack.c152
-rwxr-xr-xarch/arm/mach-omap2/board-tuna-modems.c749
-rw-r--r--arch/arm/mach-omap2/board-tuna-nfc.c147
-rw-r--r--arch/arm/mach-omap2/board-tuna-pogo.c282
-rw-r--r--arch/arm/mach-omap2/board-tuna-power.c509
-rwxr-xr-xarch/arm/mach-omap2/board-tuna-sensors.c212
-rw-r--r--arch/arm/mach-omap2/board-tuna-usbhost.c85
-rwxr-xr-xarch/arm/mach-omap2/board-tuna-vibrator.c185
-rw-r--r--arch/arm/mach-omap2/board-tuna-wifi.c419
-rw-r--r--arch/arm/mach-omap2/board-tuna.c1362
-rw-r--r--arch/arm/mach-omap2/board-tuna.h47
-rw-r--r--arch/arm/mach-omap2/dpll44xx.c6
-rw-r--r--arch/arm/mach-omap2/emif.c14
-rw-r--r--arch/arm/mach-omap2/include/mach/emif.h1
-rw-r--r--arch/arm/mach-omap2/include/mach/omap4-common.h1
-rw-r--r--arch/arm/mach-omap2/include/mach/tf_mshield.h11
-rw-r--r--arch/arm/mach-omap2/io.c4
-rw-r--r--arch/arm/mach-omap2/omap-smp.c2
-rw-r--r--arch/arm/mach-omap2/omap2plus-cpufreq.c94
-rw-r--r--arch/arm/mach-omap2/omap4-common.c2
-rw-r--r--arch/arm/mach-omap2/omap4-mpuss-lowpower.c9
-rw-r--r--arch/arm/mach-omap2/omap_hsi.c189
-rw-r--r--arch/arm/mach-omap2/omap_hwmod_44xx_data.c4
-rw-r--r--arch/arm/mach-omap2/omap_l3_noc.c9
-rw-r--r--arch/arm/mach-omap2/opp4xxx_data.c5
-rw-r--r--arch/arm/mach-omap2/pm44xx.c20
-rw-r--r--arch/arm/plat-omap/include/plat/board-tuna-bluetooth.h30
-rw-r--r--arch/arm/plat-omap/include/plat/omap_hsi.h14
-rw-r--r--arch/arm/plat-omap/include/plat/uncompress.h1
38 files changed, 7230 insertions, 71 deletions
diff --git a/arch/arm/configs/tuna_defconfig b/arch/arm/configs/tuna_defconfig
new file mode 100644
index 0000000..48713fa
--- /dev/null
+++ b/arch/arm/configs/tuna_defconfig
@@ -0,0 +1,382 @@
+CONFIG_EXPERIMENTAL=y
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_CGROUPS=y
+CONFIG_CGROUP_DEBUG=y
+CONFIG_CGROUP_FREEZER=y
+CONFIG_CGROUP_CPUACCT=y
+CONFIG_RESOURCE_COUNTERS=y
+CONFIG_CGROUP_SCHED=y
+CONFIG_RT_GROUP_SCHED=y
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_PANIC_TIMEOUT=5
+CONFIG_KALLSYMS_ALL=y
+CONFIG_ASHMEM=y
+# CONFIG_AIO is not set
+CONFIG_EMBEDDED=y
+CONFIG_MODULES=y
+CONFIG_MODULE_FORCE_LOAD=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+# CONFIG_BLK_DEV_BSG is not set
+CONFIG_ARCH_OMAP=y
+CONFIG_OMAP_SMARTREFLEX=y
+CONFIG_OMAP_SMARTREFLEX_CLASS3=y
+CONFIG_OMAP_RESET_CLOCKS=y
+CONFIG_OMAP_TEMP_SENSOR=y
+CONFIG_OMAP_REMOTEPROC_MEMPOOL_SIZE=0x0
+# CONFIG_ARCH_OMAP2 is not set
+# CONFIG_ARCH_OMAP3 is not set
+# CONFIG_MACH_OMAP_4430SDP is not set
+CONFIG_OMAP_ALLOW_OSWR=y
+CONFIG_ARM_THUMBEE=y
+CONFIG_PL310_ERRATA_727915=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_SMP=y
+CONFIG_NR_CPUS=2
+CONFIG_PREEMPT=y
+CONFIG_HIGHMEM=y
+CONFIG_ARM_FLUSH_CONSOLE_ON_RESTART=y
+CONFIG_CMDLINE="console= mem=1G vmalloc=768M omap_wdt.timer_margin=30 no_console_suspend"
+CONFIG_CMDLINE_EXTEND=y
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_DEFAULT_GOV_INTERACTIVE=y
+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
+CONFIG_CPU_FREQ_GOV_HOTPLUG=y
+CONFIG_CPU_IDLE=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_BINFMT_MISC=y
+CONFIG_WAKELOCK=y
+CONFIG_PM_DEBUG=y
+CONFIG_SUSPEND_TIME=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+CONFIG_INET_ESP=y
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+CONFIG_IPV6=y
+CONFIG_IPV6_PRIVACY=y
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_OPTIMISTIC_DAD=y
+CONFIG_INET6_AH=y
+CONFIG_INET6_ESP=y
+CONFIG_INET6_IPCOMP=y
+CONFIG_IPV6_MIP6=y
+CONFIG_IPV6_TUNNEL=y
+CONFIG_IPV6_MULTIPLE_TABLES=y
+CONFIG_NETFILTER=y
+CONFIG_NF_CONNTRACK=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+CONFIG_NF_CT_PROTO_DCCP=y
+CONFIG_NF_CT_PROTO_SCTP=y
+CONFIG_NF_CT_PROTO_UDPLITE=y
+CONFIG_NF_CONNTRACK_AMANDA=y
+CONFIG_NF_CONNTRACK_FTP=y
+CONFIG_NF_CONNTRACK_H323=y
+CONFIG_NF_CONNTRACK_IRC=y
+CONFIG_NF_CONNTRACK_NETBIOS_NS=y
+CONFIG_NF_CONNTRACK_PPTP=y
+CONFIG_NF_CONNTRACK_SANE=y
+CONFIG_NF_CONNTRACK_TFTP=y
+CONFIG_NF_CT_NETLINK=y
+CONFIG_NETFILTER_TPROXY=y
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=y
+CONFIG_NETFILTER_XT_TARGET_MARK=y
+CONFIG_NETFILTER_XT_TARGET_NFLOG=y
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y
+CONFIG_NETFILTER_XT_TARGET_TPROXY=y
+CONFIG_NETFILTER_XT_TARGET_TRACE=y
+CONFIG_NETFILTER_XT_MATCH_COMMENT=y
+CONFIG_NETFILTER_XT_MATCH_CONNBYTES=y
+CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=y
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=y
+CONFIG_NETFILTER_XT_MATCH_HELPER=y
+CONFIG_NETFILTER_XT_MATCH_IPRANGE=y
+CONFIG_NETFILTER_XT_MATCH_LENGTH=y
+CONFIG_NETFILTER_XT_MATCH_LIMIT=y
+CONFIG_NETFILTER_XT_MATCH_MAC=y
+CONFIG_NETFILTER_XT_MATCH_MARK=y
+CONFIG_NETFILTER_XT_MATCH_POLICY=y
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y
+CONFIG_NETFILTER_XT_MATCH_QTAGUID=y
+CONFIG_NETFILTER_XT_MATCH_QUOTA=y
+CONFIG_NETFILTER_XT_MATCH_QUOTA2=y
+CONFIG_NETFILTER_XT_MATCH_QUOTA2_LOG=y
+CONFIG_NETFILTER_XT_MATCH_SOCKET=y
+CONFIG_NETFILTER_XT_MATCH_STATE=y
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=y
+CONFIG_NETFILTER_XT_MATCH_STRING=y
+CONFIG_NETFILTER_XT_MATCH_TIME=y
+CONFIG_NETFILTER_XT_MATCH_U32=y
+CONFIG_NF_CONNTRACK_IPV4=y
+CONFIG_IP_NF_IPTABLES=y
+CONFIG_IP_NF_MATCH_AH=y
+CONFIG_IP_NF_MATCH_ECN=y
+CONFIG_IP_NF_MATCH_TTL=y
+CONFIG_IP_NF_FILTER=y
+CONFIG_IP_NF_TARGET_REJECT=y
+CONFIG_IP_NF_TARGET_REJECT_SKERR=y
+CONFIG_IP_NF_TARGET_LOG=y
+CONFIG_NF_NAT=y
+CONFIG_IP_NF_TARGET_MASQUERADE=y
+CONFIG_IP_NF_TARGET_NETMAP=y
+CONFIG_IP_NF_TARGET_REDIRECT=y
+CONFIG_IP_NF_MANGLE=y
+CONFIG_IP_NF_RAW=y
+CONFIG_IP_NF_ARPTABLES=y
+CONFIG_IP_NF_ARPFILTER=y
+CONFIG_IP_NF_ARP_MANGLE=y
+CONFIG_NF_CONNTRACK_IPV6=y
+CONFIG_IP6_NF_IPTABLES=y
+CONFIG_IP6_NF_TARGET_LOG=y
+CONFIG_IP6_NF_FILTER=y
+CONFIG_IP6_NF_TARGET_REJECT=y
+CONFIG_IP6_NF_TARGET_REJECT_SKERR=y
+CONFIG_IP6_NF_MANGLE=y
+CONFIG_IP6_NF_RAW=y
+CONFIG_BRIDGE=y
+# CONFIG_BRIDGE_IGMP_SNOOPING is not set
+CONFIG_PHONET=y
+CONFIG_NET_SCHED=y
+CONFIG_NET_SCH_HTB=y
+CONFIG_NET_SCH_INGRESS=y
+CONFIG_NET_CLS_U32=y
+CONFIG_NET_EMATCH=y
+CONFIG_NET_EMATCH_U32=y
+CONFIG_NET_CLS_ACT=y
+CONFIG_NET_ACT_POLICE=y
+CONFIG_NET_ACT_GACT=y
+CONFIG_NET_ACT_MIRRED=y
+CONFIG_BT=y
+CONFIG_BT_L2CAP=y
+CONFIG_BT_SCO=y
+CONFIG_BT_RFCOMM=y
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=y
+CONFIG_BT_HIDP=y
+CONFIG_BT_HCIUART=y
+CONFIG_BT_HCIUART_H4=y
+CONFIG_CFG80211=y
+CONFIG_NL80211_TESTMODE=y
+# CONFIG_CFG80211_WEXT is not set
+CONFIG_CFG80211_ALLOW_RECONNECT=y
+CONFIG_RFKILL=y
+CONFIG_RFKILL_INPUT=y
+CONFIG_MTD=y
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_M25P80=y
+CONFIG_MTD_NAND_IDS=y
+CONFIG_MTD_ONENAND=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_MISC_DEVICES=y
+# CONFIG_ANDROID_PMEM is not set
+CONFIG_KERNEL_DEBUGGER_CORE=y
+CONFIG_SAMSUNG_JACK=y
+CONFIG_UID_STAT=y
+CONFIG_BMP180=y
+CONFIG_USB_SWITCH_FSA9480=y
+CONFIG_OMAP_DIE_TEMP_SENSOR=y
+CONFIG_LEDS_AN30259A=y
+CONFIG_MPU_SENSORS_TIMERIRQ=y
+CONFIG_INV_SENSORS=y
+CONFIG_MPU_SENSORS_MPU3050=y
+CONFIG_MPU_SENSORS_BMA250=y
+CONFIG_MPU_SENSORS_YAS530=y
+CONFIG_SEC_MODEM=y
+CONFIG_UMTS_LINK_MIPI=y
+CONFIG_UMTS_MODEM_XMM6260=y
+CONFIG_CDMA_LINK_DPRAM=y
+CONFIG_CDMA_MODEM_CBP71=y
+CONFIG_LTE_LINK_USB=y
+CONFIG_LTE_MODEM_CMC221=y
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_SG=y
+CONFIG_MD=y
+CONFIG_BLK_DEV_DM=y
+CONFIG_DM_DEBUG=y
+CONFIG_DM_CRYPT=y
+CONFIG_DM_UEVENT=y
+CONFIG_NETDEVICES=y
+CONFIG_IFB=y
+CONFIG_TUN=y
+CONFIG_WIFI_CONTROL_FUNC=y
+CONFIG_BCMDHD=y
+CONFIG_BCMDHD_FW_PATH="/system/vendor/firmware/fw_bcmdhd.bin"
+CONFIG_PPP=y
+CONFIG_PPP_DEFLATE=y
+CONFIG_PPP_BSDCOMP=y
+CONFIG_PPP_MPPE=y
+CONFIG_PPPOLAC=y
+CONFIG_PPPOPNS=y
+CONFIG_INPUT_EVDEV=y
+CONFIG_INPUT_KEYRESET=y
+CONFIG_KEYBOARD_OMAP4=y
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_ATMEL_MXT=y
+CONFIG_TOUCHSCREEN_MMS=y
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_KEYCHORD=y
+CONFIG_INPUT_UINPUT=y
+CONFIG_INPUT_GPIO=y
+CONFIG_OPTICAL_GP2A=y
+# CONFIG_VT is not set
+# CONFIG_LEGACY_PTYS is not set
+CONFIG_HW_RANDOM=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_GPIO=y
+CONFIG_SPI=y
+CONFIG_SPI_OMAP24XX=y
+CONFIG_GPIO_SYSFS=y
+CONFIG_GPIO_TWL4030=y
+CONFIG_POWER_SUPPLY=y
+CONFIG_PDA_POWER=y
+CONFIG_BATTERY_MAX17040=y
+# CONFIG_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_OMAP_WATCHDOG=y
+CONFIG_TWL6030_POWER=y
+CONFIG_TWL6030_PWM=y
+CONFIG_TWL6030_MADC=y
+CONFIG_REGULATOR_TWL4030=y
+CONFIG_MEDIA_SUPPORT=y
+# CONFIG_RC_CORE is not set
+CONFIG_PVR_SGX=y
+CONFIG_PVR_NEED_PVR_DPF=y
+CONFIG_PVR_USSE_EDM_STATUS_DEBUG=y
+CONFIG_ION=y
+CONFIG_ION_OMAP=y
+CONFIG_FB=y
+CONFIG_SII9234=y
+CONFIG_FB_OMAP_BOOTLOADER_INIT=y
+CONFIG_OMAP2_DSS=y
+CONFIG_OMAP2_VRAM_SIZE=16
+# CONFIG_OMAP2_DSS_DPI is not set
+# CONFIG_OMAP2_DSS_VENC is not set
+CONFIG_OMAP2_DSS_DSI=y
+CONFIG_FB_OMAP2=y
+CONFIG_PANEL_S6E8AA0=y
+CONFIG_OMAP4_HDCP=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+# CONFIG_LCD_CLASS_DEVICE is not set
+CONFIG_DISPLAY_SUPPORT=y
+CONFIG_SOUND=y
+CONFIG_SND=y
+CONFIG_SND_SOC=y
+CONFIG_SND_OMAP_SOC=y
+CONFIG_SND_OMAP_SOC_SDP4430=y
+CONFIG_SND_OMAP_SOC_OMAP4_HDMI=y
+CONFIG_HID_A4TECH=y
+CONFIG_HID_APPLE=y
+CONFIG_HID_BELKIN=y
+CONFIG_HID_CHERRY=y
+CONFIG_HID_CHICONY=y
+CONFIG_HID_CYPRESS=y
+CONFIG_HID_DRAGONRISE=y
+CONFIG_HID_EZKEY=y
+CONFIG_HID_KYE=y
+CONFIG_HID_GYRATION=y
+CONFIG_HID_TWINHAN=y
+CONFIG_HID_KENSINGTON=y
+CONFIG_HID_LOGITECH=y
+CONFIG_HID_MAGICMOUSE=y
+CONFIG_HID_MICROSOFT=y
+CONFIG_HID_MONTEREY=y
+CONFIG_HID_NTRIG=y
+CONFIG_HID_ORTEK=y
+CONFIG_HID_PANTHERLORD=y
+CONFIG_HID_PETALYNX=y
+CONFIG_HID_PICOLCD=y
+CONFIG_HID_QUANTA=y
+CONFIG_HID_ROCCAT_KONE=y
+CONFIG_HID_SAMSUNG=y
+CONFIG_HID_SONY=y
+CONFIG_HID_SUNPLUS=y
+CONFIG_HID_GREENASIA=y
+CONFIG_HID_SMARTJOYPLUS=y
+CONFIG_HID_TOPSEED=y
+CONFIG_HID_THRUSTMASTER=y
+CONFIG_HID_WACOM=y
+CONFIG_HID_ZEROPLUS=y
+CONFIG_HID_ZYDACRON=y
+CONFIG_USB=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+CONFIG_USB_DEVICEFS=y
+CONFIG_USB_SUSPEND=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_MUSB_HDRC=y
+CONFIG_USB_MUSB_OMAP2PLUS=y
+CONFIG_USB_MUSB_PERIPHERAL=y
+CONFIG_USB_GADGET_MUSB_HDRC=y
+CONFIG_USB_ACM=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_SERIAL=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_VBUS_DRAW=500
+CONFIG_USB_G_ANDROID=y
+CONFIG_USB_OTG_WAKELOCK=y
+CONFIG_MMC=y
+CONFIG_MMC_UNSAFE_RESUME=y
+CONFIG_MMC_EMBEDDED_SDIO=y
+CONFIG_MMC_PARANOID_SD_INIT=y
+CONFIG_MMC_OMAP=y
+CONFIG_MMC_OMAP_HS=y
+CONFIG_SWITCH=y
+CONFIG_SWITCH_GPIO=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_TWL4030=y
+CONFIG_STAGING=y
+CONFIG_ANDROID=y
+CONFIG_ANDROID_BINDER_IPC=y
+CONFIG_ANDROID_LOGGER=y
+CONFIG_ANDROID_RAM_CONSOLE=y
+CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION=y
+CONFIG_ANDROID_TIMED_GPIO=y
+CONFIG_ANDROID_LOW_MEMORY_KILLER=y
+CONFIG_OMAP_HSI=y
+CONFIG_EXT2_FS=y
+CONFIG_EXT4_FS=y
+# CONFIG_EXT4_FS_XATTR is not set
+# CONFIG_DNOTIFY is not set
+CONFIG_FUSE_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+# CONFIG_NETWORK_FILESYSTEMS is not set
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_EFI_PARTITION=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_PRINTK_TIME=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_FS=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_DETECT_HUNG_TASK=y
+# CONFIG_DEBUG_PREEMPT is not set
+CONFIG_DEBUG_SPINLOCK_SLEEP=y
+CONFIG_DEBUG_INFO=y
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+# CONFIG_ARM_UNWIND is not set
+CONFIG_DEBUG_USER=y
+CONFIG_SECURITY_MIDDLEWARE_COMPONENT=y
+# CONFIG_SMC_KERNEL_CRYPTO is not set
+CONFIG_CRYPTO_SHA256=y
+CONFIG_CRYPTO_TWOFISH=y
+CONFIG_CRC_CCITT=y
diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig
index 1cf7d51..8d3cb45 100644
--- a/arch/arm/mach-omap2/Kconfig
+++ b/arch/arm/mach-omap2/Kconfig
@@ -325,6 +325,15 @@ config MACH_OMAP4_PANDA
select OMAP_PACKAGE_CBS
select REGULATOR_FIXED_VOLTAGE
+config MACH_TUNA
+ bool "Tuna Board"
+ default y
+ depends on ARCH_OMAP4
+ select OMAP_PACKAGE_CBL
+ select OMAP_PACKAGE_CBS
+ select REGULATOR_FIXED_VOLTAGE
+ select OMAP_TPS6236X
+
config OMAP3_EMU
bool "OMAP3 debugging peripherals"
depends on ARCH_OMAP3
diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
index c0f2be2..961a34f 100644
--- a/arch/arm/mach-omap2/Makefile
+++ b/arch/arm/mach-omap2/Makefile
@@ -253,6 +253,22 @@ obj-$(CONFIG_MACH_OMAP_4430SDP) += board-4430sdp.o \
obj-$(CONFIG_MACH_OMAP4_PANDA) += board-omap4panda.o \
hsmmc.o \
omap_phy_internal.o
+obj-$(CONFIG_MACH_TUNA) += board-tuna.o \
+ hsmmc.o \
+ omap_phy_internal.o
+obj-$(CONFIG_MACH_TUNA) += board-tuna-display.o
+obj-$(CONFIG_MACH_TUNA) += board-tuna-input.o
+obj-$(CONFIG_MACH_TUNA) += board-tuna-jack.o
+obj-$(CONFIG_MACH_TUNA) += board-tuna-nfc.o
+obj-$(CONFIG_MACH_TUNA) += board-tuna-power.o
+obj-$(CONFIG_MACH_TUNA) += board-tuna-sensors.o
+obj-$(CONFIG_MACH_TUNA) += board-tuna-vibrator.o
+obj-$(CONFIG_MACH_TUNA) += board-tuna-wifi.o
+obj-$(CONFIG_MACH_TUNA) += board-tuna-bluetooth.o \
+ board-tuna-emif.o
+obj-$(CONFIG_MACH_TUNA) += board-tuna-connector.o
+obj-$(CONFIG_MACH_TUNA) += board-tuna-pogo.o
+obj-$(CONFIG_MACH_TUNA) += board-tuna-usbhost.o
obj-$(CONFIG_MACH_OMAP3517EVM) += board-am3517evm.o \
omap_phy_internal.o \
@@ -291,4 +307,5 @@ obj-y += common-board-devices.o
obj-$(CONFIG_OMAP_REMOTE_PROC) += remoteproc.o
obj-$(CONFIG_OMAP_HSI_DEVICE) += omap_hsi.o
+obj-$(CONFIG_SEC_MODEM) += board-tuna-modems.o
obj-$(CONFIG_ARCH_OMAP4) += omap_dmm.o
diff --git a/arch/arm/mach-omap2/board-omap4panda.c b/arch/arm/mach-omap2/board-omap4panda.c
index 4fcd26a..5a00efc 100644
--- a/arch/arm/mach-omap2/board-omap4panda.c
+++ b/arch/arm/mach-omap2/board-omap4panda.c
@@ -680,8 +680,6 @@ void omap4_panda_display_init(void)
omap_display_init(&omap4_panda_dss_data);
}
-extern void __init omap4_panda_android_init(void);
-
static void __init omap4_panda_init(void)
{
int package = OMAP_PACKAGE_CBS;
@@ -712,7 +710,6 @@ static void __init omap4_panda_init(void)
omap_dmm_init();
omap4_panda_display_init();
-
}
static void __init omap4_panda_map_io(void)
diff --git a/arch/arm/mach-omap2/board-tuna-bluetooth.c b/arch/arm/mach-omap2/board-tuna-bluetooth.c
new file mode 100644
index 0000000..67a2ac6
--- /dev/null
+++ b/arch/arm/mach-omap2/board-tuna-bluetooth.c
@@ -0,0 +1,306 @@
+/*
+ * Bluetooth Broadcomm and low power control via GPIO
+ *
+ * Copyright (C) 2011 Google, Inc.
+ *
+ * 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/module.h>
+#include <linux/init.h>
+#include <linux/gpio.h>
+#include <linux/hrtimer.h>
+#include <linux/irq.h>
+#include <linux/rfkill.h>
+#include <linux/platform_device.h>
+#include <linux/wakelock.h>
+#include <asm/mach-types.h>
+#include <plat/serial.h>
+#include <plat/board-tuna-bluetooth.h>
+#include <linux/regulator/driver.h>
+
+#define BT_REG_GPIO 103
+#define BT_RESET_GPIO 42
+
+#define BT_WAKE_GPIO 27
+#define BT_HOST_WAKE_GPIO 177
+
+static struct rfkill *bt_rfkill;
+static struct regulator *clk32kaudio_reg;
+static bool bt_enabled;
+
+struct bcm_bt_lpm {
+ int wake;
+ int host_wake;
+
+ struct hrtimer enter_lpm_timer;
+ ktime_t enter_lpm_delay;
+
+ struct uart_port *uport;
+
+ struct wake_lock wake_lock;
+ char wake_lock_name[100];
+} bt_lpm;
+
+static int bcm4330_bt_rfkill_set_power(void *data, bool blocked)
+{
+ // rfkill_ops callback. Turn transmitter on when blocked is false
+ if (!blocked) {
+ if (clk32kaudio_reg && !bt_enabled)
+ regulator_enable(clk32kaudio_reg);
+
+ gpio_set_value(BT_REG_GPIO, 1);
+ gpio_set_value(BT_RESET_GPIO, 1);
+
+ } else {
+ gpio_set_value(BT_RESET_GPIO, 0);
+ gpio_set_value(BT_REG_GPIO, 0);
+ if (clk32kaudio_reg && bt_enabled)
+ regulator_disable(clk32kaudio_reg);
+ }
+
+ bt_enabled = !blocked;
+
+ return 0;
+}
+
+static const struct rfkill_ops bcm4330_bt_rfkill_ops = {
+ .set_block = bcm4330_bt_rfkill_set_power,
+};
+
+static void set_wake_locked(int wake)
+{
+ bt_lpm.wake = wake;
+
+ if (!wake)
+ wake_unlock(&bt_lpm.wake_lock);
+
+ gpio_set_value(BT_WAKE_GPIO, wake);
+}
+
+static enum hrtimer_restart enter_lpm(struct hrtimer *timer) {
+ unsigned long flags;
+ spin_lock_irqsave(&bt_lpm.uport->lock, flags);
+ set_wake_locked(0);
+ spin_unlock_irqrestore(&bt_lpm.uport->lock, flags);
+
+ return HRTIMER_NORESTART;
+}
+
+void bcm_bt_lpm_exit_lpm_locked(struct uart_port *uport) {
+ bt_lpm.uport = uport;
+
+ hrtimer_try_to_cancel(&bt_lpm.enter_lpm_timer);
+
+ set_wake_locked(1);
+
+ hrtimer_start(&bt_lpm.enter_lpm_timer, bt_lpm.enter_lpm_delay,
+ HRTIMER_MODE_REL);
+}
+EXPORT_SYMBOL(bcm_bt_lpm_exit_lpm_locked);
+
+static void update_host_wake_locked(int host_wake)
+{
+ if (host_wake == bt_lpm.host_wake)
+ return;
+
+ bt_lpm.host_wake = host_wake;
+
+ if (host_wake) {
+ wake_lock(&bt_lpm.wake_lock);
+ } else {
+ // Take a timed wakelock, so that upper layers can take it.
+ // The chipset deasserts the hostwake lock, when there is no
+ // more data to send.
+ wake_lock_timeout(&bt_lpm.wake_lock, HZ/2);
+ }
+
+}
+
+static irqreturn_t host_wake_isr(int irq, void *dev)
+{
+ int host_wake;
+ unsigned long flags;
+
+ /* wakeup uart by enabling the uart module */
+ omap_uart_wake(2);
+
+ host_wake = gpio_get_value(BT_HOST_WAKE_GPIO);
+ irq_set_irq_type(irq, host_wake ? IRQF_TRIGGER_LOW : IRQF_TRIGGER_HIGH);
+
+ if (!bt_lpm.uport) {
+ bt_lpm.host_wake = host_wake;
+ return IRQ_HANDLED;
+ }
+
+ spin_lock_irqsave(&bt_lpm.uport->lock, flags);
+ update_host_wake_locked(host_wake);
+ spin_unlock_irqrestore(&bt_lpm.uport->lock, flags);
+
+ return IRQ_HANDLED;
+}
+
+static int bcm_bt_lpm_init(struct platform_device *pdev)
+{
+ int irq;
+ int ret;
+ int rc;
+
+ rc = gpio_request(BT_WAKE_GPIO, "bcm4330_wake_gpio");
+ if (unlikely(rc)) {
+ return rc;
+ }
+
+ rc = gpio_request(BT_HOST_WAKE_GPIO, "bcm4330_host_wake_gpio");
+ if (unlikely(rc)) {
+ gpio_free(BT_WAKE_GPIO);
+ return rc;
+ }
+
+ hrtimer_init(&bt_lpm.enter_lpm_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+ bt_lpm.enter_lpm_delay = ktime_set(1, 0); /* 1 sec */
+ bt_lpm.enter_lpm_timer.function = enter_lpm;
+
+ bt_lpm.host_wake = 0;
+
+ irq = gpio_to_irq(BT_HOST_WAKE_GPIO);
+ ret = request_irq(irq, host_wake_isr, IRQF_TRIGGER_HIGH,
+ "bt host_wake", NULL);
+ if (ret) {
+ gpio_free(BT_WAKE_GPIO);
+ gpio_free(BT_HOST_WAKE_GPIO);
+ return ret;
+ }
+
+ ret = irq_set_irq_wake(irq, 1);
+ if (ret) {
+ gpio_free(BT_WAKE_GPIO);
+ gpio_free(BT_HOST_WAKE_GPIO);
+ return ret;
+ }
+
+ gpio_direction_output(BT_WAKE_GPIO, 0);
+ gpio_direction_input(BT_HOST_WAKE_GPIO);
+
+ snprintf(bt_lpm.wake_lock_name, sizeof(bt_lpm.wake_lock_name),
+ "BTLowPower");
+ wake_lock_init(&bt_lpm.wake_lock, WAKE_LOCK_SUSPEND,
+ bt_lpm.wake_lock_name);
+ return 0;
+}
+
+static int bcm4330_bluetooth_probe(struct platform_device *pdev)
+{
+ int rc = 0;
+ int ret = 0;
+
+ rc = gpio_request(BT_RESET_GPIO, "bcm4330_nreset_gpip");
+ if (unlikely(rc)) {
+ return rc;
+ }
+
+ rc = gpio_request(BT_REG_GPIO, "bcm4330_nshutdown_gpio");
+ if (unlikely(rc)) {
+ gpio_free(BT_RESET_GPIO);
+ return rc;
+ }
+
+ clk32kaudio_reg = regulator_get(0, "clk32kaudio");
+ if (IS_ERR(clk32kaudio_reg)) {
+ pr_err("clk32kaudio reg not found!\n");
+ clk32kaudio_reg = NULL;
+ }
+
+ gpio_direction_output(BT_REG_GPIO, 1);
+ gpio_direction_output(BT_RESET_GPIO, 1);
+
+ bt_rfkill = rfkill_alloc("bcm4330 Bluetooth", &pdev->dev,
+ RFKILL_TYPE_BLUETOOTH, &bcm4330_bt_rfkill_ops,
+ NULL);
+
+ if (unlikely(!bt_rfkill)) {
+ gpio_free(BT_RESET_GPIO);
+ gpio_free(BT_REG_GPIO);
+ return -ENOMEM;
+ }
+
+ rc = rfkill_register(bt_rfkill);
+
+ if (unlikely(rc)) {
+ rfkill_destroy(bt_rfkill);
+ gpio_free(BT_RESET_GPIO);
+ gpio_free(BT_REG_GPIO);
+ return -1;
+ }
+
+ rfkill_set_states(bt_rfkill, true, false);
+ bcm4330_bt_rfkill_set_power(NULL, true);
+
+ ret = bcm_bt_lpm_init(pdev);
+ if (ret) {
+ rfkill_unregister(bt_rfkill);
+ rfkill_destroy(bt_rfkill);
+
+ gpio_free(BT_RESET_GPIO);
+ gpio_free(BT_REG_GPIO);
+ }
+
+ return ret;
+}
+
+static int bcm4330_bluetooth_remove(struct platform_device *pdev)
+{
+ rfkill_unregister(bt_rfkill);
+ rfkill_destroy(bt_rfkill);
+
+ gpio_free(BT_REG_GPIO);
+ gpio_free(BT_RESET_GPIO);
+ gpio_free(BT_WAKE_GPIO);
+ gpio_free(BT_HOST_WAKE_GPIO);
+ regulator_put(clk32kaudio_reg);
+
+ wake_lock_destroy(&bt_lpm.wake_lock);
+ return 0;
+}
+
+static struct platform_driver bcm4330_bluetooth_platform_driver = {
+ .probe = bcm4330_bluetooth_probe,
+ .remove = bcm4330_bluetooth_remove,
+ .driver = {
+ .name = "bcm4330_bluetooth",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init bcm4330_bluetooth_init(void)
+{
+ bt_enabled = false;
+ return platform_driver_register(&bcm4330_bluetooth_platform_driver);
+}
+
+static void __exit bcm4330_bluetooth_exit(void)
+{
+ platform_driver_unregister(&bcm4330_bluetooth_platform_driver);
+}
+
+
+module_init(bcm4330_bluetooth_init);
+module_exit(bcm4330_bluetooth_exit);
+
+MODULE_ALIAS("platform:bcm4330");
+MODULE_DESCRIPTION("bcm4330_bluetooth");
+MODULE_AUTHOR("Jaikumar Ganesh <jaikumar@google.com>");
+MODULE_LICENSE("GPL");
diff --git a/arch/arm/mach-omap2/board-tuna-connector.c b/arch/arm/mach-omap2/board-tuna-connector.c
new file mode 100644
index 0000000..9b1f23a
--- /dev/null
+++ b/arch/arm/mach-omap2/board-tuna-connector.c
@@ -0,0 +1,774 @@
+/*
+ * Copyright (C) 2011 Samsung, Inc.
+ * Copyright (C) 2011 Google Inc.
+ *
+ * Author: Adam Hampson <ahampson@sta.samsung.com>
+ * Dima Zavin <dima@android.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+
+#define pr_fmt(fmt) "%s: " fmt, __func__
+
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/platform_data/fsa9480.h>
+#include <linux/regulator/consumer.h>
+#include <linux/usb/otg.h>
+#include <linux/delay.h>
+#include <linux/sii9234.h>
+#include <linux/mutex.h>
+
+#include <plat/usb.h>
+
+#include "mux.h"
+#include "board-tuna.h"
+
+#define GPIO_JACK_INT_N 4
+#define GPIO_CP_USB_ON 22
+#define GPIO_MHL_SEL 96
+#define GPIO_AP_SEL 97
+#define GPIO_MUX3_SEL0 139
+#define GPIO_MUX3_SEL1 140
+#define GPIO_USB_ID_SEL 191
+#define GPIO_IF_UART_SEL 101
+
+#define GPIO_MHL_RST 161
+#define GPIO_MHL_WAKEUP 64
+#define GPIO_MHL_INT 175
+#define GPIO_HDMI_EN 100
+
+#define MUX3_SEL0_AP 1
+#define MUX3_SEL1_AP 1
+#define MUX3_SEL0_MHL 1
+#define MUX3_SEL1_MHL 0
+#define MUX3_SEL0_FSA 0
+#define MUX3_SEL1_FSA 1
+
+#define FSA3200_AP_SEL_AP 0
+#define FSA3200_MHL_SEL_AP 0
+#define FSA3200_AP_SEL_FSA 1
+#define FSA3200_MHL_SEL_FSA 0
+#define FSA3200_AP_SEL_MHL 1
+#define FSA3200_MHL_SEL_MHL 1
+
+#define USB_ID_SEL_FSA 0
+#define USB_ID_SEL_MHL 1
+
+#define IF_UART_SEL_DEFAULT 1
+#define IF_UART_SEL_AP 1
+#define IF_UART_SEL_CP 0
+
+#define TUNA_MANUAL_USB_NONE 0
+#define TUNA_MANUAL_USB_MODEM 1
+#define TUNA_MANUAL_USB_AP 2
+
+#define TUNA_MANUAL_UART_NONE 0
+#define TUNA_MANUAL_UART_MODEM 1
+#define TUNA_MANUAL_UART_LTE 2
+#define TUNA_MANUAL_UART_AP 3
+
+#define TUNA_OTG_ID_FSA9480_PRIO INT_MIN
+#define TUNA_OTG_ID_SII9234_PRIO INT_MIN + 1
+#define TUNA_OTG_ID_FSA9480_LAST_PRIO INT_MAX
+
+struct tuna_otg {
+ struct otg_transceiver otg;
+ struct device dev;
+
+ struct regulator *vusb;
+ struct mutex lock;
+
+ bool reg_on;
+ int usb_manual_mode;
+ int uart_manual_mode;
+ int current_device;
+};
+static struct tuna_otg tuna_otg_xceiv;
+
+enum {
+ TUNA_USB_MUX_FSA = 0,
+ TUNA_USB_MUX_MHL,
+ TUNA_USB_MUX_AP,
+ NUM_TUNA_USB_MUX,
+
+ TUNA_USB_MUX_DEFAULT = TUNA_USB_MUX_FSA,
+};
+
+static struct {
+ int mux3_sel0;
+ int mux3_sel1;
+} tuna_usb_mux_states[] = {
+ [TUNA_USB_MUX_FSA] = { MUX3_SEL0_FSA, MUX3_SEL1_FSA },
+ [TUNA_USB_MUX_MHL] = { MUX3_SEL0_MHL, MUX3_SEL1_MHL },
+ [TUNA_USB_MUX_AP] = { MUX3_SEL0_AP, MUX3_SEL1_AP },
+};
+
+static struct {
+ int ap_sel;
+ int mhl_sel;
+} tuna_fsa3200_mux_pair_states[] = {
+ [TUNA_USB_MUX_FSA] = { FSA3200_AP_SEL_FSA, FSA3200_MHL_SEL_FSA },
+ [TUNA_USB_MUX_MHL] = { FSA3200_AP_SEL_MHL, FSA3200_MHL_SEL_MHL },
+ [TUNA_USB_MUX_AP] = { FSA3200_AP_SEL_AP, FSA3200_MHL_SEL_AP },
+};
+
+static int tuna_usb_id_mux_states[] = {
+ [TUNA_USB_MUX_FSA] = USB_ID_SEL_FSA,
+ [TUNA_USB_MUX_MHL] = USB_ID_SEL_MHL,
+ [TUNA_USB_MUX_AP] = USB_ID_SEL_FSA,
+};
+
+static ssize_t tuna_otg_usb_sel_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf);
+static ssize_t tuna_otg_usb_sel_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size);
+static ssize_t tuna_otg_uart_switch_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf);
+static ssize_t tuna_otg_uart_switch_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size);
+
+static DEVICE_ATTR(usb_sel, S_IRUSR | S_IWUSR,
+ tuna_otg_usb_sel_show, tuna_otg_usb_sel_store);
+static DEVICE_ATTR(uart_sel, S_IRUSR | S_IWUSR,
+ tuna_otg_uart_switch_show, tuna_otg_uart_switch_store);
+
+static struct attribute *manual_mode_attributes[] = {
+ &dev_attr_usb_sel.attr,
+ &dev_attr_uart_sel.attr,
+ NULL,
+};
+
+static const struct attribute_group manual_mode_group = {
+ .attrs = manual_mode_attributes,
+};
+
+static void tuna_mux_usb(int state)
+{
+ BUG_ON(state >= NUM_TUNA_USB_MUX);
+
+ pr_debug("mux to %d\n", state);
+ gpio_direction_output(GPIO_MUX3_SEL0,
+ tuna_usb_mux_states[state].mux3_sel0);
+ gpio_direction_output(GPIO_MUX3_SEL1,
+ tuna_usb_mux_states[state].mux3_sel1);
+}
+
+static void tuna_mux_usb_id(int state)
+{
+ BUG_ON(state >= NUM_TUNA_USB_MUX);
+
+ pr_debug("mux to %d\n", state);
+ gpio_direction_output(GPIO_USB_ID_SEL, tuna_usb_id_mux_states[state]);
+}
+
+static void tuna_fsa3200_mux_pair(int state)
+{
+ BUG_ON(state >= NUM_TUNA_USB_MUX);
+
+ pr_debug("mux to %d\n", state);
+ gpio_direction_output(GPIO_AP_SEL,
+ tuna_fsa3200_mux_pair_states[state].ap_sel);
+ gpio_direction_output(GPIO_MHL_SEL,
+ tuna_fsa3200_mux_pair_states[state].mhl_sel);
+}
+
+static void tuna_mux_usb_to_fsa(bool enable)
+{
+ if (omap4_tuna_get_revision() >= 3) {
+ tuna_fsa3200_mux_pair(enable ? TUNA_USB_MUX_FSA :
+ TUNA_USB_MUX_DEFAULT);
+ } else {
+ tuna_mux_usb(enable ? TUNA_USB_MUX_FSA : TUNA_USB_MUX_DEFAULT);
+
+ /* When switching ID away from FSA, we want to ensure we switch
+ * it off FSA, and force it to MHL. Ideally, we'd just say mux
+ * to default, but FSA is likely the default mux position and
+ * there's no way to force the ID pin to float to the FSA.
+ */
+ tuna_mux_usb_id(enable ? TUNA_USB_MUX_FSA : TUNA_USB_MUX_MHL);
+ }
+}
+
+static void tuna_mux_usb_to_mhl(bool enable)
+{
+ if (omap4_tuna_get_revision() >= 3) {
+ tuna_fsa3200_mux_pair(enable ? TUNA_USB_MUX_MHL :
+ TUNA_USB_MUX_DEFAULT);
+ } else {
+ tuna_mux_usb(enable ? TUNA_USB_MUX_MHL : TUNA_USB_MUX_DEFAULT);
+ tuna_mux_usb_id(enable ? TUNA_USB_MUX_MHL : TUNA_USB_MUX_DEFAULT);
+ }
+}
+
+static void tuna_vusb_enable(struct tuna_otg *tuna_otg, bool enable)
+{
+ /* delay getting the regulator until later */
+ if (IS_ERR_OR_NULL(tuna_otg->vusb)) {
+ tuna_otg->vusb = regulator_get(&tuna_otg->dev, "vusb");
+ if (IS_ERR(tuna_otg->vusb)) {
+ dev_err(&tuna_otg->dev, "cannot get vusb regulator\n");
+ return;
+ }
+ }
+
+ if (enable) {
+ regulator_enable(tuna_otg->vusb);
+ tuna_otg->reg_on = true;
+ } else if (tuna_otg->reg_on) {
+ regulator_disable(tuna_otg->vusb);
+ tuna_otg->reg_on = false;
+ }
+}
+
+static void tuna_ap_usb_attach(struct tuna_otg *tuna_otg)
+{
+ tuna_vusb_enable(tuna_otg, true);
+
+ if (omap4_tuna_get_revision() >= 3) {
+ tuna_fsa3200_mux_pair(TUNA_USB_MUX_AP);
+ } else {
+ tuna_mux_usb(TUNA_USB_MUX_AP);
+ tuna_mux_usb_id(TUNA_USB_MUX_FSA);
+ }
+
+ tuna_otg->otg.state = OTG_STATE_B_IDLE;
+ tuna_otg->otg.default_a = false;
+ tuna_otg->otg.last_event = USB_EVENT_VBUS;
+ atomic_notifier_call_chain(&tuna_otg->otg.notifier,
+ USB_EVENT_VBUS,
+ tuna_otg->otg.gadget);
+}
+
+static void tuna_ap_usb_detach(struct tuna_otg *tuna_otg)
+{
+ tuna_vusb_enable(tuna_otg, false);
+
+ tuna_otg->otg.state = OTG_STATE_B_IDLE;
+ tuna_otg->otg.default_a = false;
+ tuna_otg->otg.last_event = USB_EVENT_NONE;
+ atomic_notifier_call_chain(&tuna_otg->otg.notifier,
+ USB_EVENT_NONE,
+ tuna_otg->otg.gadget);
+}
+
+static void tuna_cp_usb_attach(struct tuna_otg *tuna_otg)
+{
+ if (omap4_tuna_get_type() == TUNA_TYPE_MAGURO)
+ gpio_set_value(GPIO_CP_USB_ON, 1);
+
+ tuna_mux_usb_to_fsa(true);
+}
+
+static void tuna_cp_usb_detach(struct tuna_otg *tuna_otg)
+{
+ if (omap4_tuna_get_type() == TUNA_TYPE_MAGURO)
+ gpio_set_value(GPIO_CP_USB_ON, 0);
+}
+
+static void tuna_ap_uart_actions(struct tuna_otg *tuna_otg)
+{
+ tuna_mux_usb_to_fsa(true);
+ gpio_set_value(GPIO_IF_UART_SEL, IF_UART_SEL_AP);
+}
+
+static void tuna_cp_uart_actions(struct tuna_otg *tuna_otg)
+{
+ tuna_mux_usb_to_fsa(true);
+ gpio_set_value(GPIO_IF_UART_SEL, IF_UART_SEL_CP);
+}
+
+static void tuna_lte_uart_actions(struct tuna_otg *tuna_otg)
+{
+ tuna_mux_usb_to_fsa(true);
+
+ /* The LTE modem's UART lines are connected to the V_AUDIO_L and
+ * V_AUDIO_R pins on the FSA9480. The RIL will configure the FSA9480
+ * separately to set manual routing.
+ */
+}
+
+static void tuna_fsa_usb_detected(int device)
+{
+ struct tuna_otg *tuna_otg = &tuna_otg_xceiv;
+ int old_device;
+
+ mutex_lock(&tuna_otg->lock);
+
+ old_device = tuna_otg->current_device;
+ tuna_otg->current_device = device;
+
+ pr_debug("detected %x\n", device);
+ switch (device) {
+ case FSA9480_DETECT_USB:
+ if (tuna_otg->usb_manual_mode == TUNA_MANUAL_USB_MODEM)
+ tuna_cp_usb_attach(tuna_otg);
+ else
+ tuna_ap_usb_attach(tuna_otg);
+ break;
+ case FSA9480_DETECT_CHARGER:
+ tuna_mux_usb_to_fsa(true);
+
+ tuna_otg->otg.state = OTG_STATE_B_IDLE;
+ tuna_otg->otg.default_a = false;
+ tuna_otg->otg.last_event = USB_EVENT_CHARGER;
+ atomic_notifier_call_chain(&tuna_otg->otg.notifier,
+ USB_EVENT_CHARGER,
+ tuna_otg->otg.gadget);
+ break;
+ case FSA9480_DETECT_USB_HOST:
+ tuna_vusb_enable(tuna_otg, true);
+
+ if (omap4_tuna_get_revision() >= 3) {
+ tuna_fsa3200_mux_pair(TUNA_USB_MUX_AP);
+ } else {
+ tuna_mux_usb(TUNA_USB_MUX_AP);
+ tuna_mux_usb_id(TUNA_USB_MUX_FSA);
+ }
+
+ tuna_otg->otg.state = OTG_STATE_A_IDLE;
+ tuna_otg->otg.default_a = true;
+ tuna_otg->otg.last_event = USB_EVENT_ID;
+ atomic_notifier_call_chain(&tuna_otg->otg.notifier,
+ USB_EVENT_ID,
+ tuna_otg->otg.gadget);
+ break;
+ case FSA9480_DETECT_NONE:
+ tuna_mux_usb_to_fsa(true);
+
+ switch (old_device) {
+ case FSA9480_DETECT_JIG:
+ if (tuna_otg->uart_manual_mode == TUNA_MANUAL_UART_NONE)
+ tuna_ap_uart_actions(tuna_otg);
+ break;
+ case FSA9480_DETECT_USB:
+ if (tuna_otg->usb_manual_mode == TUNA_MANUAL_USB_MODEM)
+ tuna_cp_usb_detach(tuna_otg);
+ else
+ tuna_ap_usb_detach(tuna_otg);
+ break;
+ case FSA9480_DETECT_UART:
+ break;
+ case FSA9480_DETECT_USB_HOST:
+ case FSA9480_DETECT_CHARGER:
+ default:
+ tuna_ap_usb_detach(tuna_otg);
+ break;
+ };
+ break;
+ case FSA9480_DETECT_JIG:
+ switch (tuna_otg->uart_manual_mode) {
+ case TUNA_MANUAL_UART_AP:
+ tuna_ap_uart_actions(tuna_otg);
+ break;
+ case TUNA_MANUAL_UART_LTE:
+ tuna_lte_uart_actions(tuna_otg);
+ break;
+ case TUNA_MANUAL_UART_MODEM:
+ default:
+ tuna_cp_uart_actions(tuna_otg);
+ break;
+ };
+ break;
+ case FSA9480_DETECT_UART:
+ break;
+ }
+
+ mutex_unlock(&tuna_otg->lock);
+}
+
+static struct fsa9480_detect_set fsa_detect_sets[] = {
+ {
+ .prio = TUNA_OTG_ID_FSA9480_PRIO,
+ .mask = FSA9480_DETECT_ALL & ~FSA9480_DETECT_USB_HOST,
+ },
+ {
+ .prio = TUNA_OTG_ID_FSA9480_LAST_PRIO,
+ .mask = FSA9480_DETECT_USB_HOST,
+ .fallback = true,
+ },
+};
+
+static struct fsa9480_platform_data tuna_fsa9480_pdata = {
+ .detect_time = 500,
+ .detect_sets = fsa_detect_sets,
+ .num_sets = ARRAY_SIZE(fsa_detect_sets),
+
+ .enable = tuna_mux_usb_to_fsa,
+ .detected = tuna_fsa_usb_detected,
+};
+
+static struct i2c_board_info __initdata tuna_connector_i2c4_boardinfo[] = {
+ {
+ I2C_BOARD_INFO("fsa9480", 0x4A >> 1),
+ .irq = OMAP_GPIO_IRQ(GPIO_JACK_INT_N),
+ .platform_data = &tuna_fsa9480_pdata,
+ },
+};
+
+static int tuna_otg_set_host(struct otg_transceiver *otg, struct usb_bus *host)
+{
+ otg->host = host;
+ if (!host)
+ otg->state = OTG_STATE_UNDEFINED;
+ return 0;
+}
+
+static int tuna_otg_set_peripheral(struct otg_transceiver *otg,
+ struct usb_gadget *gadget)
+{
+ otg->gadget = gadget;
+ if (!gadget)
+ otg->state = OTG_STATE_UNDEFINED;
+ return 0;
+}
+
+static int tuna_otg_set_vbus(struct otg_transceiver *otg, bool enabled)
+{
+ dev_dbg(otg->dev, "vbus %s\n", enabled ? "on" : "off");
+ return 0;
+}
+
+static int tuna_otg_phy_init(struct otg_transceiver *otg)
+{
+ if (otg->last_event == USB_EVENT_ID)
+ omap4430_phy_power(otg->dev, 1, 1);
+ else
+ omap4430_phy_power(otg->dev, 0, 1);
+ return 0;
+}
+
+static void tuna_otg_phy_shutdown(struct otg_transceiver *otg)
+{
+ omap4430_phy_power(otg->dev, 0, 0);
+}
+
+static int tuna_otg_set_suspend(struct otg_transceiver *otg, int suspend)
+{
+ return omap4430_phy_suspend(otg->dev, suspend);
+}
+
+static ssize_t tuna_otg_usb_sel_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct tuna_otg *tuna_otg = dev_get_drvdata(dev);
+ const char* mode;
+
+ switch (tuna_otg->usb_manual_mode) {
+ case TUNA_MANUAL_USB_AP:
+ mode = "PDA";
+ break;
+ case TUNA_MANUAL_USB_MODEM:
+ mode = "MODEM";
+ break;
+ default:
+ mode = "NONE";
+ };
+
+ return sprintf(buf, "%s\n", mode);
+}
+
+static ssize_t tuna_otg_usb_sel_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ struct tuna_otg *tuna_otg = dev_get_drvdata(dev);
+ size_t len = strlen(buf);
+ int old_mode;
+
+ mutex_lock(&tuna_otg->lock);
+
+ old_mode = tuna_otg->usb_manual_mode;
+
+ if (!strncasecmp(buf, "PDA", 3) && len == 4) {
+ tuna_otg->usb_manual_mode = TUNA_MANUAL_USB_AP;
+
+ /* If we are transitioning from CP USB to AP USB then notify the
+ * USB stack that is now attached.
+ */
+ if (tuna_otg->current_device == FSA9480_DETECT_USB &&
+ old_mode == TUNA_MANUAL_USB_MODEM) {
+ tuna_cp_usb_detach(tuna_otg);
+ tuna_ap_usb_attach(tuna_otg);
+ }
+ } else if (!strncasecmp(buf, "MODEM", 5) && len == 6) {
+ tuna_otg->usb_manual_mode = TUNA_MANUAL_USB_MODEM;
+
+ /* If we are transitioning from AP USB to CP USB then notify the
+ * USB stack that is has been detached.
+ */
+ if (tuna_otg->current_device == FSA9480_DETECT_USB &&
+ (old_mode == TUNA_MANUAL_USB_AP ||
+ old_mode == TUNA_MANUAL_USB_NONE)) {
+ tuna_ap_usb_detach(tuna_otg);
+ tuna_cp_usb_attach(tuna_otg);
+ }
+ } else if (!strncasecmp(buf, "NONE", 5) && len == 5) {
+ tuna_otg->usb_manual_mode = TUNA_MANUAL_USB_NONE;
+
+ /* If we are transitioning from CP USB to AP USB then notify the
+ * USB stack that it is now attached.
+ */
+ if (tuna_otg->current_device == FSA9480_DETECT_USB &&
+ old_mode == TUNA_MANUAL_USB_MODEM) {
+ tuna_cp_usb_detach(tuna_otg);
+ tuna_ap_usb_attach(tuna_otg);
+ }
+ }
+
+ mutex_unlock(&tuna_otg->lock);
+
+ return len;
+}
+
+static ssize_t tuna_otg_uart_switch_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct tuna_otg *tuna_otg = dev_get_drvdata(dev);
+ const char* mode;
+
+ switch (tuna_otg->uart_manual_mode) {
+ case TUNA_MANUAL_UART_AP:
+ mode = "PDA";
+ break;
+ case TUNA_MANUAL_UART_MODEM:
+ mode = "MODEM";
+ break;
+ case TUNA_MANUAL_UART_LTE:
+ mode = "LTEMODEM";
+ break;
+ default:
+ mode = "NONE";
+ };
+
+ return sprintf(buf, "%s\n", mode);
+}
+
+static ssize_t tuna_otg_uart_switch_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ struct tuna_otg *tuna_otg = dev_get_drvdata(dev);
+ size_t len = strlen(buf);
+
+ mutex_lock(&tuna_otg->lock);
+
+ if (!strncasecmp(buf, "PDA", 3) && len == 4) {
+ tuna_otg->uart_manual_mode = TUNA_MANUAL_UART_AP;
+
+ if (tuna_otg->current_device == FSA9480_DETECT_JIG)
+ tuna_ap_uart_actions(tuna_otg);
+ } else if (!strncasecmp(buf, "MODEM", 5) && len == 6) {
+ tuna_otg->uart_manual_mode = TUNA_MANUAL_UART_MODEM;
+
+ if (tuna_otg->current_device == FSA9480_DETECT_JIG)
+ tuna_cp_uart_actions(tuna_otg);
+ } else if (!strncasecmp(buf, "LTEMODEM", 8) && len == 9 &&
+ omap4_tuna_get_type() == TUNA_TYPE_TORO) {
+ tuna_otg->uart_manual_mode = TUNA_MANUAL_UART_LTE;
+
+ if (tuna_otg->current_device == FSA9480_DETECT_JIG)
+ tuna_lte_uart_actions(tuna_otg);
+ } else if (!strncasecmp(buf, "NONE", 5) && len == 5) {
+ tuna_otg->uart_manual_mode = TUNA_MANUAL_UART_NONE;
+
+ if (tuna_otg->current_device == FSA9480_DETECT_JIG)
+ tuna_ap_uart_actions(tuna_otg);
+ }
+
+ mutex_unlock(&tuna_otg->lock);
+
+ return len;
+}
+
+#define OMAP_HDMI_HPD_ADDR 0x4A100098
+#define OMAP_HDMI_PULLTYPE_MASK 0x00000010
+static void sii9234_power(int on)
+{
+ struct omap_mux_partition *p = omap_mux_get("core");
+
+ u16 mux;
+
+ mux = omap_mux_read(p, OMAP4_CTRL_MODULE_PAD_HDMI_HPD_OFFSET);
+
+ if (on) {
+ gpio_set_value(GPIO_HDMI_EN, 1);
+ msleep(20);
+ gpio_set_value(GPIO_MHL_RST, 1);
+
+ omap_mux_write(p, mux | OMAP_PULL_UP,
+ OMAP4_CTRL_MODULE_PAD_HDMI_HPD_OFFSET);
+ } else {
+ omap_mux_write(p, mux & ~OMAP_PULL_UP,
+ OMAP4_CTRL_MODULE_PAD_HDMI_HPD_OFFSET);
+
+ gpio_set_value(GPIO_HDMI_EN, 0);
+ gpio_set_value(GPIO_MHL_RST, 0);
+
+ }
+}
+
+static void sii9234_enable_vbus(bool enable)
+{
+
+}
+
+static void sii9234_vbus_present(bool on)
+{
+ struct tuna_otg *tuna_otg = &tuna_otg_xceiv;
+
+ tuna_otg->otg.state = OTG_STATE_B_IDLE;
+ tuna_otg->otg.default_a = false;
+ tuna_otg->otg.last_event = on ? USB_EVENT_VBUS : USB_EVENT_NONE;
+ atomic_notifier_call_chain(&tuna_otg->otg.notifier,
+ on ? USB_EVENT_VBUS : USB_EVENT_NONE,
+ tuna_otg->otg.gadget);
+}
+
+static struct sii9234_platform_data sii9234_pdata = {
+ .prio = TUNA_OTG_ID_SII9234_PRIO,
+ .enable = tuna_mux_usb_to_mhl,
+ .power = sii9234_power,
+ .enable_vbus = sii9234_enable_vbus,
+ .vbus_present = sii9234_vbus_present,
+};
+
+static struct i2c_board_info __initdata tuna_i2c5_boardinfo[] = {
+ {
+ I2C_BOARD_INFO("sii9234_mhl_tx", 0x72>>1),
+ .irq = OMAP_GPIO_IRQ(GPIO_MHL_INT),
+ .platform_data = &sii9234_pdata,
+ },
+ {
+ I2C_BOARD_INFO("sii9234_tpi", 0x7A>>1),
+ .platform_data = &sii9234_pdata,
+ },
+ {
+ I2C_BOARD_INFO("sii9234_hdmi_rx", 0x92>>1),
+ .platform_data = &sii9234_pdata,
+ },
+ {
+ I2C_BOARD_INFO("sii9234_cbus", 0xC8>>1),
+ .platform_data = &sii9234_pdata,
+ },
+};
+
+int __init omap4_tuna_connector_init(void)
+{
+ struct tuna_otg *tuna_otg = &tuna_otg_xceiv;
+ int ret;
+
+ if (omap4_tuna_get_revision() >= 3) {
+ gpio_request(GPIO_MHL_SEL, "fsa3200_mhl_sel");
+ gpio_request(GPIO_AP_SEL, "fsa3200_ap_sel");
+
+ tuna_fsa3200_mux_pair(TUNA_USB_MUX_DEFAULT);
+
+ omap_mux_init_gpio(GPIO_MHL_SEL, OMAP_PIN_OUTPUT);
+ omap_mux_init_gpio(GPIO_AP_SEL, OMAP_PIN_OUTPUT);
+ } else {
+ gpio_request(GPIO_MUX3_SEL0, "usb_mux3_sel0");
+ gpio_request(GPIO_MUX3_SEL1, "usb_mux3_sel1");
+ gpio_request(GPIO_USB_ID_SEL, "usb_id_sel");
+
+ tuna_mux_usb(TUNA_USB_MUX_DEFAULT);
+ tuna_mux_usb_id(TUNA_USB_MUX_DEFAULT);
+
+ omap_mux_init_gpio(GPIO_MUX3_SEL0, OMAP_PIN_OUTPUT);
+ omap_mux_init_gpio(GPIO_MUX3_SEL1, OMAP_PIN_OUTPUT);
+ omap_mux_init_gpio(GPIO_USB_ID_SEL, OMAP_PIN_OUTPUT);
+ }
+
+ if (omap4_tuna_get_type() == TUNA_TYPE_MAGURO) {
+ gpio_request(GPIO_CP_USB_ON, "cp_usb_on");
+ omap_mux_init_gpio(GPIO_CP_USB_ON, OMAP_PIN_OUTPUT);
+ gpio_direction_output(GPIO_CP_USB_ON, 0);
+ }
+
+ omap_mux_init_gpio(GPIO_IF_UART_SEL, OMAP_PIN_OUTPUT);
+ gpio_request(GPIO_IF_UART_SEL, "uart_sel");
+ gpio_direction_output(GPIO_IF_UART_SEL, IF_UART_SEL_DEFAULT);
+
+ omap_mux_init_gpio(GPIO_JACK_INT_N,
+ OMAP_PIN_INPUT_PULLUP |
+ OMAP_PIN_OFF_INPUT_PULLUP);
+
+ mutex_init(&tuna_otg->lock);
+
+ device_initialize(&tuna_otg->dev);
+ dev_set_name(&tuna_otg->dev, "%s", "tuna_otg");
+ ret = device_add(&tuna_otg->dev);
+ if (ret) {
+ pr_err("%s: cannot reg device '%s' (%d)\n", __func__,
+ dev_name(&tuna_otg->dev), ret);
+ return ret;
+ }
+
+ dev_set_drvdata(&tuna_otg->dev, tuna_otg);
+
+ tuna_otg->otg.dev = &tuna_otg->dev;
+ tuna_otg->otg.label = "tuna_otg_xceiv";
+ tuna_otg->otg.set_host = tuna_otg_set_host;
+ tuna_otg->otg.set_peripheral = tuna_otg_set_peripheral;
+ tuna_otg->otg.set_suspend = tuna_otg_set_suspend;
+ tuna_otg->otg.set_vbus = tuna_otg_set_vbus;
+ tuna_otg->otg.init = tuna_otg_phy_init;
+ tuna_otg->otg.shutdown = tuna_otg_phy_shutdown;
+
+ ATOMIC_INIT_NOTIFIER_HEAD(&tuna_otg->otg.notifier);
+
+ ret = otg_set_transceiver(&tuna_otg->otg);
+ if (ret)
+ pr_err("tuna_otg: cannot set transceiver (%d)\n", ret);
+
+ omap4430_phy_init(&tuna_otg->dev);
+ tuna_otg_set_suspend(&tuna_otg->otg, 0);
+
+ i2c_register_board_info(4, tuna_connector_i2c4_boardinfo,
+ ARRAY_SIZE(tuna_connector_i2c4_boardinfo));
+
+ ret = sysfs_create_group(&tuna_otg->dev.kobj, &manual_mode_group);
+ if (ret)
+ pr_err("tuna_otg: Unable to create manual mode sysfs group"
+ "(%d)\n", ret);
+
+ gpio_request(GPIO_HDMI_EN, NULL);
+ omap_mux_init_gpio(GPIO_HDMI_EN, OMAP_PIN_OUTPUT);
+ gpio_direction_output(GPIO_HDMI_EN, 0);
+
+ gpio_request(GPIO_MHL_RST, NULL);
+ omap_mux_init_gpio(GPIO_MHL_RST, OMAP_PIN_OUTPUT);
+ gpio_direction_output(GPIO_MHL_RST, 0);
+
+ gpio_request(GPIO_MHL_INT, NULL);
+ omap_mux_init_gpio(GPIO_MHL_INT, OMAP_PIN_INPUT);
+ gpio_direction_input(GPIO_MHL_INT);
+
+ gpio_request(TUNA_GPIO_HDMI_HPD, NULL);
+ omap_mux_init_gpio(TUNA_GPIO_HDMI_HPD, OMAP_PIN_INPUT | OMAP_PULL_ENA);
+ gpio_direction_input(TUNA_GPIO_HDMI_HPD);
+
+ i2c_register_board_info(5, tuna_i2c5_boardinfo,
+ ARRAY_SIZE(tuna_i2c5_boardinfo));
+
+ return 0;
+}
diff --git a/arch/arm/mach-omap2/board-tuna-display.c b/arch/arm/mach-omap2/board-tuna-display.c
new file mode 100644
index 0000000..f975b08
--- /dev/null
+++ b/arch/arm/mach-omap2/board-tuna-display.c
@@ -0,0 +1,955 @@
+/* Display panel support for Samsung Tuna Board.
+ *
+ * Copyright (C) 2011 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ */
+
+#include <linux/err.h>
+#include <linux/gpio.h>
+#include <linux/kernel.h>
+#include <linux/omapfb.h>
+#include <linux/regulator/consumer.h>
+
+#include <linux/platform_data/panel-s6e8aa0.h>
+
+#include <plat/vram.h>
+
+#include <video/omapdss.h>
+#include <video/omap-panel-generic-dpi.h>
+
+#include "board-tuna.h"
+#include "control.h"
+#include "mux.h"
+
+#define TUNA_FB_RAM_SIZE SZ_16M /* ~1280*720*4 * 2 */
+
+#define TUNA_GPIO_MLCD_RST 23
+
+/* 4.65" Panel ID Info (D1h 1st Para) */
+#define M3 0xA1
+#define SM2 0x12
+
+static unsigned int panel_id;
+struct regulator *tuna_oled_reg;
+struct regulator *tuna_oled_reg_iovcc;
+
+
+static void tuna_oled_set_power(bool enable)
+{
+ if (IS_ERR_OR_NULL(tuna_oled_reg)) {
+ tuna_oled_reg = regulator_get(NULL, "vlcd");
+ if (IS_ERR_OR_NULL(tuna_oled_reg)) {
+ pr_err("Can't get vlcd for display!\n");
+ return;
+ }
+ }
+
+ if (omap4_tuna_get_revision() >= 5) {
+ if (IS_ERR_OR_NULL(tuna_oled_reg_iovcc)) {
+ tuna_oled_reg_iovcc = regulator_get(NULL, "vlcd-iovcc");
+ if (IS_ERR_OR_NULL(tuna_oled_reg_iovcc)) {
+ pr_err("Can't get vlcd for display!\n");
+ return;
+ }
+ }
+
+ if (enable) {
+ regulator_enable(tuna_oled_reg_iovcc);
+ regulator_enable(tuna_oled_reg);
+ } else {
+ regulator_disable(tuna_oled_reg);
+ regulator_disable(tuna_oled_reg_iovcc);
+ }
+ } else {
+ if (enable)
+ regulator_enable(tuna_oled_reg);
+ else
+ regulator_disable(tuna_oled_reg);
+ }
+}
+
+static const struct s6e8aa0_acl_parameters tuna_oled_acl[] = {
+ {
+ .cd = 40,
+ .acl_val = 43,
+ .regs = {
+ 0xC1, /* ACL Control2 Register */
+ 0x47,
+ 0x53,
+ 0x13,
+ 0x53,
+ 0x00,
+ 0x00,
+ 0x02,
+ 0xCF,
+ 0x00,
+ 0x00,
+ 0x04,
+ 0xFF,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x01,
+ 0x07,
+ 0x0D,
+ 0x14,
+ 0x1A,
+ 0x20,
+ 0x26,
+ 0x2C,
+ 0x33,
+ 0x39,
+ 0x3F,
+ },
+ },
+ {
+ .cd = 300,
+ .acl_val = 45,
+ .regs = {
+ 0xC1, /* ACL Control2 Register */
+ 0x47,
+ 0x53,
+ 0x13,
+ 0x53,
+ 0x00,
+ 0x00,
+ 0x02,
+ 0xCF,
+ 0x00,
+ 0x00,
+ 0x04,
+ 0xFF,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x01,
+ 0x07,
+ 0x0E,
+ 0x14,
+ 0x1B,
+ 0x21,
+ 0x27,
+ 0x2E,
+ 0x34,
+ 0x3B,
+ 0x41,
+ },
+ },
+};
+
+static const struct s6e8aa0_elvss_parameters tuna_oled_elvss[] = {
+ {
+ .cd = 100,
+ .elvss_val = 0x11,
+ },
+ {
+ .cd = 160,
+ .elvss_val = 0x0D,
+ },
+ {
+ .cd = 200,
+ .elvss_val = 0x08,
+ },
+ {
+ .cd = 300,
+ .elvss_val = 0x00,
+ },
+};
+
+static const u8 tuna_oled_cmd_init_pre0[] = {
+ 0xF0,
+ 0x5A,
+ 0x5A,
+};
+
+static const u8 tuna_oled_cmd_init_pre1[] = {
+ 0xF1,
+ 0x5A,
+ 0x5A,
+};
+
+static const u8 tuna_oled_cmd_sleep_out[] = {
+ 0x11,
+};
+
+static const u8 tuna_oled_cmd_init_panel_m3[] = {
+ 0xF8, /* Panel Condition Set */
+ 0x3D, /* DOTC[0:1], GTCON[2:4], SS, DOTC_H[6:7] */
+ 0x35, /* FLTE[0:7] */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x8D,
+ 0x00,
+ 0x4C, /* SCTE[0:7] */
+ 0x6E,
+ 0x10,
+ 0x27,
+ 0x7D, /* INTE[0:7] */
+ 0x3F, /* INWE[0:7] */
+ 0x10,
+ 0x00,
+ 0x00,
+ 0x20,
+ 0x04, /* E_FLWE_H[0:7] */
+ 0x08, /* E_SCTE[0:7] */
+ 0x6E, /* E_SCWE[0:7] */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x02,
+ 0x08,
+ 0x08,
+ 0x23,
+ 0x23,
+ 0xC0,
+ 0xC8, /* CLK2_CON[0:2], CLK1_CON[3:5], CLK2_DC, CLK1_DC */
+ 0x08, /* INT2_CON[0:2], INT1_CON[3:5], INT2_DC, INT1_DC */
+ 0x48, /* BICTLB_CON[0:2], BICTL_CON[3:5], BICTLB_DC, BICTL_DC */
+ 0xC1,
+ 0x00,
+ 0xC3, /* EM_FLM_CON[0:2], ACL_FLM_CON[3:5], EM_FLM_DC, ACL_FLM_DC */
+ 0xFF, /* EM_CLK1B_CON[0:2], EM_CLK1_CON[3:5], EM_CLK1B_DC, EM_CLK1_DC */
+ 0xFF, /* EM_CLK2B_CON[0:2], EM_CLK2_CON[3:5], EM_CLK2B_DC, EM_CLK2_DC */
+ 0xC8, /* EM_INT2_CON[0:2], EM_INT1_CON[3:5], EM_INT2_DC, EM_INT1_DC */
+};
+
+static const u8 tuna_oled_cmd_init_panel_sm2[] = {
+ 0xF8, /* Panel Condition Set */
+ 0x3D, /* DOTC[0:1], GTCON[2:4], SS, DOTC_H[6:7] */
+ 0x35, /* FLTE[0:7] */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x93, /* FLWE */
+ 0x00,
+ 0x3C, /* SCTE[0:7] */
+ 0x7D, /* SCWE */
+ 0x08, /* INTE */
+ 0x27,
+ 0x7D, /* INTE[0:7] */
+ 0x3F, /* INWE[0:7] */
+ 0x00, /* EMPS */
+ 0x00,
+ 0x00,
+ 0x20,
+ 0x04, /* E_FLWE_H[0:7] */
+ 0x08, /* E_SCTE[0:7] */
+ 0x6E, /* E_SCWE[0:7] */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x02,
+ 0x08,
+ 0x08,
+ 0x23,
+ 0x23,
+ 0xC0,
+ 0xC8, /* CLK2_CON[0:2], CLK1_CON[3:5], CLK2_DC, CLK1_DC */
+ 0x08, /* INT2_CON[0:2], INT1_CON[3:5], INT2_DC, INT1_DC */
+ 0x48, /* BICTLB_CON[0:2], BICTL_CON[3:5], BICTLB_DC, BICTL_DC */
+ 0xC1,
+ 0x00,
+ 0xC1, /* EM_FLM_CON[0:2], ACL_FLM_CON[3:5], EM_FLM_DC, ACL_FLM_DC */
+ 0xFF, /* EM_CLK1B_CON[0:2], EM_CLK1_CON[3:5], EM_CLK1B_DC, EM_CLK1_DC */
+ 0xFF, /* EM_CLK2B_CON[0:2], EM_CLK2_CON[3:5], EM_CLK2B_DC, EM_CLK2_DC */
+ 0xC8, /* EM_INT2_CON[0:2], EM_INT1_CON[3:5], EM_INT2_DC, EM_INT1_DC */
+};
+
+static const u8 tuna_oled_cmd_init_display[] = {
+ 0xF2, /* Display Condition set */
+ 0x80, /* Display area */
+ 0x03, /* VBP : 3 HsYNC */
+ 0x0D, /* VFP : 13HSYNC */
+};
+
+static const struct s6e8aa0_sequence_entry tuna_oled_seq_display_set_m3[] = {
+ {
+ .cmd = tuna_oled_cmd_init_pre0,
+ .cmd_len = ARRAY_SIZE(tuna_oled_cmd_init_pre0),
+ },
+ {
+ .cmd = tuna_oled_cmd_sleep_out,
+ .cmd_len = ARRAY_SIZE(tuna_oled_cmd_sleep_out),
+ },
+ {
+ .cmd = tuna_oled_cmd_init_panel_m3,
+ .cmd_len = ARRAY_SIZE(tuna_oled_cmd_init_panel_m3),
+ },
+ {
+ .cmd = tuna_oled_cmd_init_display,
+ .cmd_len = ARRAY_SIZE(tuna_oled_cmd_init_display),
+ },
+};
+
+static const struct s6e8aa0_sequence_entry tuna_oled_seq_display_set_sm2[] = {
+ {
+ .cmd = tuna_oled_cmd_init_pre0,
+ .cmd_len = ARRAY_SIZE(tuna_oled_cmd_init_pre0),
+ },
+ {
+ .cmd = tuna_oled_cmd_init_pre1,
+ .cmd_len = ARRAY_SIZE(tuna_oled_cmd_init_pre1),
+ },
+ {
+ .cmd = tuna_oled_cmd_sleep_out,
+ .cmd_len = ARRAY_SIZE(tuna_oled_cmd_sleep_out),
+ },
+ {
+ .cmd = tuna_oled_cmd_init_panel_sm2,
+ .cmd_len = ARRAY_SIZE(tuna_oled_cmd_init_panel_sm2),
+ },
+ {
+ .cmd = tuna_oled_cmd_init_display,
+ .cmd_len = ARRAY_SIZE(tuna_oled_cmd_init_display),
+ },
+};
+
+static const u8 tuna_oled_cmd_gamma_ltps_update[] = {
+ 0xF7,
+ 0x03, /* Gamma/LTPS update */
+};
+
+static const u8 tuna_oled_cmd_init_post0[] = {
+ 0xF6,
+ 0x00,
+ 0x02,
+ 0x00,
+};
+
+static const u8 tuna_oled_cmd_init_post1[] = {
+ 0xB6,
+ 0x0C,
+ 0x02,
+ 0x03,
+ 0x32,
+ 0xFF,
+ 0x44,
+ 0x44,
+ 0xC0,
+ 0x00,
+};
+
+static const u8 tuna_oled_cmd_init_post2_m3[] = {
+ 0xD9,
+ 0x14,
+ 0x40,
+ 0x0C,
+ 0xCB,
+ 0xCE,
+ 0x6E,
+ 0xC4,
+ 0x07, /* COLUMN_CHOP, FRAME_CHOP, LINE_CHOP, CHOP_EN */
+ 0x40,
+ 0x40, /* ELVSS_CON : 0 */
+ 0xD0, /* ELVSS -4.9V */
+ 0x00,
+ 0x60,
+ 0x19,
+};
+
+static const u8 tuna_oled_cmd_power_ctrl_m3[] = {
+ 0xF4, /* Power Control */
+ 0xCF,
+ 0x0A,
+ 0x0F, /* Vreg1 : 4.5V(default) */
+ 0x10, /* VGH : 5.2v(default) */
+ 0x19, /* VGL : -7.0v(default) */
+ 0x33,
+ 0x02,
+};
+
+static const u8 tuna_oled_cmd_init_post2_sm2[] = {
+ 0xD9,
+ 0x14,
+ 0x40,
+ 0x0C,
+ 0xCB,
+ 0xCE,
+ 0x6E,
+ 0xC4,
+ 0x07, /* COLUMN_CHOP, FRAME_CHOP, LINE_CHOP, CHOP_EN */
+ 0x40,
+ 0x41, /* ELVSS_CON : 1 */
+ 0xD0, /* ELVSS -4.9V */
+ 0x00,
+ 0x60,
+ 0x19,
+};
+
+static const u8 tuna_oled_cmd_power_ctrl_sm2[] = {
+ 0xF4, /* Power Control */
+ 0xCF,
+ 0x0A,
+ 0x12, /* Vreg1 : 4.6V */
+ 0x10, /* VGH : 5.2v(default) */
+ 0x1E, /* VGL : -8.0v */
+ 0x33,
+ 0x02,
+};
+
+static const u8 tuna_oled_cmd_display_on[] = {
+ 0x29,
+};
+
+static const struct s6e8aa0_sequence_entry tuna_oled_seq_etc_set_m3[] = {
+ {
+ .cmd = tuna_oled_cmd_gamma_ltps_update,
+ .cmd_len = ARRAY_SIZE(tuna_oled_cmd_gamma_ltps_update),
+ },
+ {
+ .cmd = tuna_oled_cmd_init_post0,
+ .cmd_len = ARRAY_SIZE(tuna_oled_cmd_init_post0),
+ },
+ {
+ .cmd = tuna_oled_cmd_init_post1,
+ .cmd_len = ARRAY_SIZE(tuna_oled_cmd_init_post1),
+ },
+ {
+ .cmd = tuna_oled_cmd_init_post2_m3,
+ .cmd_len = ARRAY_SIZE(tuna_oled_cmd_init_post2_m3),
+ },
+ {
+ .cmd = tuna_oled_cmd_power_ctrl_m3,
+ .cmd_len = ARRAY_SIZE(tuna_oled_cmd_power_ctrl_m3),
+ .msleep = 120,
+ },
+ {
+ .cmd = tuna_oled_cmd_display_on,
+ .cmd_len = ARRAY_SIZE(tuna_oled_cmd_display_on),
+ },
+};
+
+static const struct s6e8aa0_sequence_entry tuna_oled_seq_etc_set_sm2[] = {
+ {
+ .cmd = tuna_oled_cmd_gamma_ltps_update,
+ .cmd_len = ARRAY_SIZE(tuna_oled_cmd_gamma_ltps_update),
+ },
+ {
+ .cmd = tuna_oled_cmd_init_post0,
+ .cmd_len = ARRAY_SIZE(tuna_oled_cmd_init_post0),
+ },
+ {
+ .cmd = tuna_oled_cmd_init_post1,
+ .cmd_len = ARRAY_SIZE(tuna_oled_cmd_init_post1),
+ },
+ {
+ .cmd = tuna_oled_cmd_init_post2_sm2,
+ .cmd_len = ARRAY_SIZE(tuna_oled_cmd_init_post2_sm2),
+ },
+ {
+ .cmd = tuna_oled_cmd_power_ctrl_sm2,
+ .cmd_len = ARRAY_SIZE(tuna_oled_cmd_power_ctrl_sm2),
+ .msleep = 120,
+ },
+ {
+ .cmd = tuna_oled_cmd_display_on,
+ .cmd_len = ARRAY_SIZE(tuna_oled_cmd_display_on),
+ },
+};
+
+static const struct s6e8aa0_gamma_entry tuna_oled_gamma_table_m3[] = {
+ { BV_0, { 4500000, 4500000, 4500000, }, },
+ { 0x00000001, { 4350000, 4350000, 4350000, }, },
+ { 0x0001F8F0, { 4320166, 4338185, 4200000, }, },
+ { 0x0002F71F, { 4305148, 4332238, 4102500, }, },
+ { 0x00038485, { 4296793, 4328930, 4065000, }, },
+ { 0x00053C55, { 4270807, 4318639, 3982500, }, },
+ { 0x00060EEF, { 4258364, 4313711, 3960000, }, },
+ { 0x00075444, { 4239141, 4306099, 3930000, }, },
+ { 0x00095733, { 4208717, 4294050, 3892500, }, },
+ { 0x000EC060, { 4126874, 4261640, 3810000, }, },
+ { 0x00129EAB, { 4068363, 4238469, 3757500, }, },
+ { 0x00179214, { 3993478, 4208813, 3720000, }, },
+ { 0x001A47A0, { 3952500, 4192586, 3712500, }, },
+ { 0x0025E12C, { 3802500, 4123103, 3682500, }, },
+ { 0x002D413D, { 3756465, 4078926, 3673450, }, },
+ { 0x0035D13F, { 3741586, 4027637, 3659844, }, },
+ { 0x00400000, { 3726401, 3966643, 3645758, }, },
+ { 0x004C1BF8, { 3710894, 3894110, 3631166, }, },
+ { 0x005A827A, { 3695052, 3855649, 3616042, }, },
+ { 0x006BA27E, { 3678859, 3823316, 3600360, }, },
+ { 0x00800000, { 3662298, 3794488, 3584091, }, },
+ { 0x009837F0, { 3645351, 3767841, 3567202, }, },
+ { 0x00B504F3, { 3627999, 3742607, 3549662, }, },
+ { 0x00D744FD, { 3610220, 3718295, 3531434, }, },
+ { 0x01000000, { 3591992, 3694568, 3512481, }, },
+ { 0x01306FE1, { 3573291, 3671183, 3492761, }, },
+ { 0x016A09E6, { 3554089, 3647957, 3472232, }, },
+ { 0x01AE89FA, { 3534358, 3624743, 3450847, }, },
+ { 0x02000000, { 3514065, 3601422, 3428554, }, },
+ { 0x0260DFC1, { 3493177, 3577893, 3405301, }, },
+ { 0x02D413CD, { 3471654, 3554067, 3381029, }, },
+ { 0x035D13F3, { 3449455, 3529864, 3355676, }, },
+ { 0x04000000, { 3426534, 3505211, 3329174, }, },
+ { 0x04C1BF83, { 3402839, 3480034, 3301451, }, },
+ { 0x05A8279A, { 3378312, 3454264, 3272429, }, },
+ { 0x06BA27E6, { 3352890, 3427831, 3242021, }, },
+ { 0x08000000, { 3326501, 3400661, 3210138, }, },
+ { 0x09837F05, { 3299062, 3372679, 3176678, }, },
+ { 0x0B504F33, { 3270483, 3343804, 3141535, }, },
+ { 0x0D744FCD, { 3240658, 3313948, 3104592, }, },
+ { 0x10000000, { 3209466, 3283015, 3065722, }, },
+ { 0x1306FE0A, { 3176767, 3250899, 3024787, }, },
+ { 0x16A09E66, { 3142400, 3217481, 2981638, }, },
+ { 0x1AE89F99, { 3106171, 3182624, 2936111, }, },
+ { 0x20000000, { 3067855, 3146174, 2888031, }, },
+ { 0x260DFC14, { 3027178, 3107951, 2837203, }, },
+ { 0x2D413CCD, { 2983809, 3067744, 2783420, }, },
+ { 0x35D13F32, { 2937340, 3025303, 2726454, }, },
+ { 0x40000000, { 2887259, 2980328, 2666057, }, },
+ { 0x4C1BF828, { 2832912, 2932454, 2601961, }, },
+ { 0x5A82799A, { 2773444, 2881230, 2533878, }, },
+ { 0x6BA27E65, { 2707706, 2826086, 2461495, }, },
+ { 0x80000000, { 2639098, 2766291, 2384478, }, },
+ { 0x9837F051, { 2560291, 2700878, 2302469, }, },
+ { 0xB504F333, { 2472698, 2628531, 2215093, }, },
+ { 0xD744FCCA, { 2375331, 2547389, 2121959, }, },
+ { 0xFFFFFFFF, { 2266945, 2454682, 2022667, }, },
+};
+
+static const struct s6e8aa0_gamma_entry tuna_oled_gamma_table_sm2[] = {
+ { BV_0, { 4600000, 4600000, 4600000, }, },
+ { 0x00000001, { 4561667, 4561667, 4561667, }, },
+ { 0x000004C2, { 4102930, 4561654, 4561115, }, },
+ { 0x000005A8, { 4093308, 4561651, 3799195, }, },
+ { 0x000006BA, { 4083466, 4561645, 3793888, }, },
+ { 0x00000800, { 4073413, 4561639, 3788484, }, },
+ { 0x00000983, { 4063166, 4561630, 3782992, }, },
+ { 0x00000B50, { 4052685, 4561618, 3777391, }, },
+ { 0x00000D74, { 4041989, 4561602, 3771689, }, },
+ { 0x00001000, { 4031064, 4561582, 3765880, }, },
+ { 0x00001307, { 4019915, 4561555, 3759964, }, },
+ { 0x000016A1, { 4008527, 4561519, 3753935, }, },
+ { 0x00001AE9, { 3996905, 4561472, 3747792, }, },
+ { 0x00002000, { 3985042, 4561410, 3741533, }, },
+ { 0x0000260E, { 3972926, 4561328, 3735148, }, },
+ { 0x00002D41, { 3960557, 4561219, 3728639, }, },
+ { 0x000035D1, { 3947926, 4561076, 3721998, }, },
+ { 0x00004000, { 3935029, 4560888, 3715222, }, },
+ { 0x00004C1C, { 3921862, 4560639, 3708307, }, },
+ { 0x00005A82, { 3908420, 4560310, 3701250, }, },
+ { 0x00006BA2, { 3894694, 4559877, 3694045, }, },
+ { 0x00008000, { 3880678, 4559305, 3686685, }, },
+ { 0x00009838, { 3866369, 4558550, 3679168, }, },
+ { 0x0000B505, { 3851759, 4557554, 3671487, }, },
+ { 0x0000D745, { 3836842, 4556240, 3663637, }, },
+ { 0x00010000, { 3821612, 4554507, 3655612, }, },
+ { 0x00013070, { 3806062, 4552219, 3647405, }, },
+ { 0x00016A0A, { 3790185, 4549200, 3639010, }, },
+ { 0x0001AE8A, { 3773975, 4545217, 3630420, }, },
+ { 0x00020000, { 3757424, 4539961, 3621628, }, },
+ { 0x000260E0, { 3740525, 4533026, 3612625, }, },
+ { 0x0002D414, { 3723271, 4523876, 3603405, }, },
+ { 0x00035D14, { 3705654, 4511801, 3593959, }, },
+ { 0x00040000, { 3687668, 4495869, 3584277, }, },
+ { 0x0004C1C0, { 3669303, 4474845, 3574351, }, },
+ { 0x0005A828, { 3650553, 4447106, 3564170, }, },
+ { 0x0006BA28, { 3631408, 4410503, 3553725, }, },
+ { 0x00080000, { 3611862, 4362204, 3543003, }, },
+ { 0x0009837F, { 3591904, 4298475, 3531993, }, },
+ { 0x000B504F, { 3571527, 4214383, 3520683, }, },
+ { 0x000D7450, { 3557593, 4103423, 3509060, }, },
+ { 0x00100000, { 3544015, 4010592, 3497110, }, },
+ { 0x001306FE, { 3530633, 3962306, 3484817, }, },
+ { 0x0016A09E, { 3517328, 3926468, 3472166, }, },
+ { 0x001AE8A0, { 3504007, 3896492, 3459141, }, },
+ { 0x00200000, { 3490597, 3869832, 3445722, }, },
+ { 0x00260DFC, { 3477036, 3845220, 3431893, }, },
+ { 0x002D413D, { 3463269, 3821929, 3417630, }, },
+ { 0x0035D13F, { 3449251, 3799494, 3402914, }, },
+ { 0x00400000, { 3434937, 3777603, 3387721, }, },
+ { 0x004C1BF8, { 3420287, 3756027, 3372025, }, },
+ { 0x005A827A, { 3405262, 3734596, 3355799, }, },
+ { 0x006BA27E, { 3389824, 3713176, 3339016, }, },
+ { 0x00800000, { 3373936, 3691658, 3321643, }, },
+ { 0x009837F0, { 3357560, 3669948, 3303646, }, },
+ { 0x00B504F3, { 3340656, 3647968, 3284991, }, },
+ { 0x00D744FD, { 3323186, 3625646, 3265636, }, },
+ { 0x01000000, { 3305106, 3602915, 3245540, }, },
+ { 0x01306FE1, { 3286372, 3579714, 3224657, }, },
+ { 0x016A09E6, { 3266937, 3555983, 3202935, }, },
+ { 0x01AE89FA, { 3246751, 3531662, 3180321, }, },
+ { 0x02000000, { 3225759, 3506692, 3156754, }, },
+ { 0x0260DFC1, { 3203902, 3481011, 3132167, }, },
+ { 0x02D413CD, { 3181115, 3454554, 3106490, }, },
+ { 0x035D13F3, { 3157329, 3427255, 3079643, }, },
+ { 0x04000000, { 3132467, 3399041, 3051538, }, },
+ { 0x04C1BF83, { 3106444, 3369833, 3022078, }, },
+ { 0x05A8279A, { 3079166, 3339546, 2991155, }, },
+ { 0x06BA27E6, { 3050528, 3308086, 2958650, }, },
+ { 0x08000000, { 3020414, 3275348, 2924429, }, },
+ { 0x09837F05, { 2988694, 3241215, 2888342, }, },
+ { 0x0B504F33, { 2955220, 3205555, 2850219, }, },
+ { 0x0D744FCD, { 2919827, 3168219, 2809871, }, },
+ { 0x10000000, { 2882325, 3129034, 2767081, }, },
+ { 0x1306FE0A, { 2842499, 3087803, 2721603, }, },
+ { 0x16A09E66, { 2800102, 3044294, 2673154, }, },
+ { 0x1AE89F99, { 2754846, 2998238, 2621408, }, },
+ { 0x20000000, { 2706399, 2949314, 2565989, }, },
+ { 0x260DFC14, { 2654372, 2897137, 2506458, }, },
+ { 0x2D413CCD, { 2598304, 2841239, 2442298, }, },
+ { 0x35D13F32, { 2537647, 2781048, 2372900, }, },
+ { 0x40000000, { 2471743, 2715846, 2297536, }, },
+ { 0x4C1BF828, { 2399793, 2644720, 2215328, }, },
+ { 0x5A82799A, { 2320814, 2566484, 2125212, }, },
+ { 0x6BA27E65, { 2233581, 2479554, 2025874, }, },
+ { 0x80000000, { 2136547, 2381755, 1915679, }, },
+ { 0x9837F051, { 2027719, 2269975, 1792556, }, },
+ { 0xB504F333, { 1904479, 2139541, 1653843, }, },
+ { 0xD744FCCA, { 1763299, 1982960, 1496041, }, },
+ { 0xFFFFFFFF, { 1599291, 1787064, 1314455, }, },
+};
+
+static struct s6e8aa0_factory_calibration_info tuna_oled_factory_info_old = {
+ .regs = {
+ [1][0][6] = 0x090,
+ [1][1][6] = 0x081,
+ [1][2][6] = 0x0c5,
+ },
+ .brightness = {
+ [1][6] = BV_255, /* 300 cd/m2 */
+ },
+ .color_adj = {
+ /* Convert from 8500K to D65, assuming:
+ * Rx 0.66950, Ry 0.33100
+ * Gx 0.18800, Gy 0.74350
+ * Bx 0.14142, By 0.04258
+ */
+ .mult = {
+ 2318372099U,
+ 2117262806U,
+ 1729744557U,
+ },
+ .rshift = 31,
+ },
+};
+
+static struct s6e8aa0_factory_calibration_info tuna_oled_factory_info_m2t1 = {
+ .regs = {
+ [1][0][6] = 0x090,
+ [1][1][6] = 0x081,
+ [1][2][6] = 0x0c5,
+ },
+ .brightness = {
+ [1][6] = BV_255, /* 300 cd/m2 */
+ },
+};
+
+static struct s6e8aa0_factory_calibration_info tuna_oled_factory_info_8500k = {
+ .regs = {
+ [1][0][0] = 0x0f,
+ [1][1][0] = 0x0f,
+ [1][2][0] = 0x0f,
+
+ [1][0][1] = 0xcc,
+ [1][1][1] = 0x9c,
+ [1][2][1] = 0xd7,
+
+ [1][0][2] = 0xc1,
+ [1][1][2] = 0xba,
+ [1][2][2] = 0xc1,
+
+ [1][0][3] = 0xcf,
+ [1][1][3] = 0xcd,
+ [1][2][3] = 0xcf,
+
+ [1][0][4] = 0xaa,
+ [1][1][4] = 0xaa,
+ [1][2][4] = 0xa7,
+
+ [1][0][5] = 0xbe,
+ [1][1][5] = 0xbe,
+ [1][2][5] = 0xba,
+
+ [1][0][6] = 0x090,
+ [1][1][6] = 0x081,
+ [1][2][6] = 0x0c5,
+ },
+ .brightness = {
+ [1][4] = 403193777, /* 28.16275996 cd/m2 */
+ [1][6] = BV_255, /* 300 cd/m2 */
+ },
+ .color_adj = {
+ /* Convert from 8500K to D65, assuming:
+ * Rx 0.66950, Ry 0.33100
+ * Gx 0.18800, Gy 0.74350
+ * Bx 0.14142, By 0.04258
+ *
+ * These values are adjusted down by x 0.9333 to bring
+ * maximum brightness down from 300 cd/m2 to 280.
+ */
+ .mult = {
+ 2163736680U,
+ 1976041377U,
+ 1614370595U,
+ },
+ .rshift = 31,
+ },
+};
+
+static struct s6e8aa0_factory_calibration_info tuna_oled_factory_info_6500k = {
+ .regs = {
+ [1][0][0] = 0x7c, /* sRGB Gamma 300cd, 6500K */
+ [1][1][0] = 0x3c,
+ [1][2][0] = 0x87,
+
+ [1][0][1] = 0xbb,
+ [1][1][1] = 0xd4,
+ [1][2][1] = 0xa8,
+
+ [1][0][2] = 0xac,
+ [1][1][2] = 0xc0,
+ [1][2][2] = 0xa1,
+
+ [1][0][3] = 0xb8,
+ [1][1][3] = 0xc8,
+ [1][2][3] = 0xb2,
+
+ [1][0][4] = 0x8c,
+ [1][1][4] = 0x9f,
+ [1][2][4] = 0x84,
+
+ [1][0][5] = 0xa7,
+ [1][1][5] = 0xb2,
+ [1][2][5] = 0xa3,
+
+ [1][0][6] = 0x0d8,
+ [1][1][6] = 0x0bd,
+ [1][2][6] = 0x0f7,
+ },
+ .brightness = {
+ [1][1] = BV_15, /* 1.43 cd/m2 */
+ [1][2] = BV_35, /* 5.04 cd/m2 */
+ [1][3] = BV_59, /* 13.12 cd/m2 */
+ [1][4] = BV_87, /* 28.59 cd/m2 */
+ [1][5] = BV_171, /* 122.17 cd/m2 */
+ [1][6] = BV_255, /* 300 cd/m2 */
+ },
+ .color_adj = {
+ /*
+ * These values are adjusted down by x 0.9333 to bring
+ * maximum brightness down from 300 cd/m2 to 280.
+ */
+ .mult = {
+ 2004318071U,
+ 2004318071U,
+ 2004318071U,
+ },
+ .rshift = 31,
+ },
+};
+
+static struct panel_s6e8aa0_data tuna_oled_data_m3 = {
+ .reset_gpio = TUNA_GPIO_MLCD_RST,
+ .set_power = tuna_oled_set_power,
+ .seq_display_set = tuna_oled_seq_display_set_m3,
+ .seq_display_set_size = ARRAY_SIZE(tuna_oled_seq_display_set_m3),
+ .seq_etc_set = tuna_oled_seq_etc_set_m3,
+ .seq_etc_set_size = ARRAY_SIZE(tuna_oled_seq_etc_set_m3),
+ .gamma_table = tuna_oled_gamma_table_m3,
+ .gamma_table_size = ARRAY_SIZE(tuna_oled_gamma_table_m3),
+ .factory_info = &tuna_oled_factory_info_8500k,
+ .acl_table = tuna_oled_acl,
+ .acl_table_size = ARRAY_SIZE(tuna_oled_acl),
+ .acl_average = 6, /* use 20 frame Y average accumulation count */
+};
+
+static struct panel_s6e8aa0_data tuna_oled_data_sm2 = {
+ .reset_gpio = TUNA_GPIO_MLCD_RST,
+ .set_power = tuna_oled_set_power,
+ .seq_display_set = tuna_oled_seq_display_set_sm2,
+ .seq_display_set_size = ARRAY_SIZE(tuna_oled_seq_display_set_sm2),
+ .seq_etc_set = tuna_oled_seq_etc_set_sm2,
+ .seq_etc_set_size = ARRAY_SIZE(tuna_oled_seq_etc_set_sm2),
+ .gamma_table = tuna_oled_gamma_table_sm2,
+ .gamma_table_size = ARRAY_SIZE(tuna_oled_gamma_table_sm2),
+ .factory_info = &tuna_oled_factory_info_6500k,
+ .acl_table = tuna_oled_acl,
+ .acl_table_size = ARRAY_SIZE(tuna_oled_acl),
+ .acl_average = 6, /* use 20 frame Y average accumulation count */
+ .elvss_table = tuna_oled_elvss,
+ .elvss_table_size = ARRAY_SIZE(tuna_oled_elvss),
+};
+
+static struct omap_dss_device tuna_oled_device = {
+ .name = "lcd",
+ .driver_name = "s6e8aa0",
+ .type = OMAP_DISPLAY_TYPE_DSI,
+ .data = &tuna_oled_data_m3,
+ .phy.dsi = {
+ .type = OMAP_DSS_DSI_TYPE_VIDEO_MODE,
+ .clk_lane = 1,
+ .clk_pol = 0,
+ .data1_lane = 2,
+ .data1_pol = 0,
+ .data2_lane = 3,
+ .data2_pol = 0,
+ .data3_lane = 4,
+ .data3_pol = 0,
+ .data4_lane = 5,
+ .data4_pol = 0,
+ },
+ .panel = {
+ .width_in_um = 58000,
+ .height_in_um = 102000,
+ },
+ .clocks = {
+ .dispc = {
+ .channel = {
+ .lck_div = 1, /* LCD */
+ .pck_div = 2, /* PCD */
+ .lcd_clk_src
+ = OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC,
+ },
+ .dispc_fclk_src = OMAP_DSS_CLK_SRC_FCK,
+ },
+ .dsi = {
+ .regn = 19, /* DSI_PLL_REGN */
+ .regm = 236, /* DSI_PLL_REGM */
+
+ .regm_dispc = 6, /* PLL_CLK1 (M4) */
+ .regm_dsi = 6, /* PLL_CLK2 (M5) */
+ .lp_clk_div = 8, /* LPDIV */
+ .offset_ddr_clk = 122, /* DDR PRE & DDR POST
+ * offset increase
+ */
+
+ .dsi_fclk_src = OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI,
+ },
+ },
+
+ .channel = OMAP_DSS_CHANNEL_LCD,
+#ifdef CONFIG_FB_OMAP_BOOTLOADER_INIT
+ .skip_init = true,
+#else
+ .skip_init = false,
+#endif
+};
+
+static void tuna_hdmi_mux_init(void)
+{
+ u32 r;
+
+ /* PAD0_HDMI_HPD_PAD1_HDMI_CEC */
+ omap_mux_init_signal("hdmi_hpd.hdmi_hpd",
+ OMAP_PIN_INPUT_PULLDOWN);
+ omap_mux_init_signal("gpmc_wait2.gpio_100",
+ OMAP_PIN_INPUT_PULLDOWN);
+ omap_mux_init_signal("hdmi_cec.hdmi_cec",
+ OMAP_PIN_INPUT_PULLUP);
+ /* PAD0_HDMI_DDC_SCL_PAD1_HDMI_DDC_SDA */
+ omap_mux_init_signal("hdmi_ddc_scl.hdmi_ddc_scl",
+ OMAP_PIN_INPUT_PULLUP);
+ omap_mux_init_signal("hdmi_ddc_sda.hdmi_ddc_sda",
+ OMAP_PIN_INPUT_PULLUP);
+
+ /* strong pullup on DDC lines using unpublished register */
+ r = ((1 << 24) | (1 << 28)) ;
+ omap4_ctrl_pad_writel(r, OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_I2C_1);
+
+}
+
+static struct omap_dss_device tuna_hdmi_device = {
+ .name = "hdmi",
+ .driver_name = "hdmi_panel",
+ .type = OMAP_DISPLAY_TYPE_HDMI,
+ .clocks = {
+ .dispc = {
+ .dispc_fclk_src = OMAP_DSS_CLK_SRC_FCK,
+ },
+ .hdmi = {
+ .regn = 15,
+ .regm2 = 1,
+ .max_pixclk_khz = 75000,
+ },
+ },
+ .hpd_gpio = TUNA_GPIO_HDMI_HPD,
+ .channel = OMAP_DSS_CHANNEL_DIGIT,
+};
+
+static struct omap_dss_device *tuna_dss_devices[] = {
+ &tuna_oled_device,
+ &tuna_hdmi_device,
+};
+
+static struct omap_dss_board_info tuna_dss_data = {
+ .num_devices = ARRAY_SIZE(tuna_dss_devices),
+ .devices = tuna_dss_devices,
+ .default_device = &tuna_oled_device,
+};
+
+static struct omapfb_platform_data tuna_fb_pdata = {
+ .mem_desc = {
+ .region_cnt = 1,
+ .region = {
+ [0] = {
+ .size = TUNA_FB_RAM_SIZE,
+ },
+ },
+ },
+};
+
+void __init omap4_tuna_display_init(void)
+{
+ struct panel_s6e8aa0_data *panel;
+
+ if (omap4_tuna_get_revision() ==
+ (omap4_tuna_get_type() == TUNA_TYPE_MAGURO ? 2 : 1)) {
+ /*
+ * Older devices were not calibrated the same way as newer
+ * devices. These values are probably not correct, but the older
+ * devices tested look closer to the newer devices with these
+ * values than they do using the same register values as the
+ * newer devices.
+ */
+ tuna_oled_data_m3.factory_info = &tuna_oled_factory_info_m2t1;
+ } else if (omap4_tuna_get_revision() <= 1) {
+ tuna_oled_data_m3.factory_info = &tuna_oled_factory_info_old;
+ }
+
+ if (panel_id == SM2)
+ panel = &tuna_oled_data_sm2;
+ else
+ panel = &tuna_oled_data_m3;
+
+ tuna_oled_device.data = panel;
+
+ omap4_ctrl_pad_writel(0x1FF80000,
+ OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_DSIPHY);
+ omap_mux_init_gpio(panel->reset_gpio, OMAP_PIN_OUTPUT);
+
+ pr_info("Using %ps\n", panel->factory_info);
+
+ omap_vram_set_sdram_vram(TUNA_FB_RAM_SIZE, 0);
+ omapfb_set_platform_data(&tuna_fb_pdata);
+ tuna_hdmi_mux_init();
+ omap_display_init(&tuna_dss_data);
+}
+
+static int __init get_panel_id(char *str)
+{
+ long value;
+ int ret;
+
+ ret = strict_strtol(str, 0, &value);
+ if (ret < 0)
+ return ret;
+
+ panel_id = (unsigned int)value;
+ return 0;
+}
+__setup("mms_ts.panel_id=", get_panel_id);
+
diff --git a/arch/arm/mach-omap2/board-tuna-emif.c b/arch/arm/mach-omap2/board-tuna-emif.c
new file mode 100644
index 0000000..f7050ae
--- /dev/null
+++ b/arch/arm/mach-omap2/board-tuna-emif.c
@@ -0,0 +1,107 @@
+/*
+ * LPDDR2 data as per SAMSUNG data sheet
+ *
+ * Copyright (C) 2011 Texas Instruments, Inc.
+ *
+ * Santosh Shilimkar <santosh.shilimkar@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+
+#include <mach/emif.h>
+#include "board-tuna.h"
+
+const struct lpddr2_timings lpddr2_samsung_timings_400_mhz = {
+ .max_freq = 400000000,
+ .RL = 6,
+ .tRPab = 21,
+ .tRCD = 18,
+ .tWR = 15,
+ .tRASmin = 42,
+ .tRRD = 10,
+ .tWTRx2 = 15,
+ .tXSR = 140,
+ .tXPx2 = 15,
+ .tRFCab = 130,
+ .tRTPx2 = 15,
+ .tCKE = 3,
+ .tCKESR = 15,
+ .tZQCS = 90,
+ .tZQCL = 360,
+ .tZQINIT = 1000,
+ .tDQSCKMAXx2 = 11,
+ .tRASmax = 70,
+ .tFAW = 50
+};
+
+const struct lpddr2_timings lpddr2_samsung_timings_200_mhz = {
+ .max_freq = 200000000,
+ .RL = 3,
+ .tRPab = 21,
+ .tRCD = 18,
+ .tWR = 15,
+ .tRASmin = 42,
+ .tRRD = 10,
+ .tWTRx2 = 20,
+ .tXSR = 140,
+ .tXPx2 = 15,
+ .tRFCab = 130,
+ .tRTPx2 = 15,
+ .tCKE = 3,
+ .tCKESR = 15,
+ .tZQCS = 90,
+ .tZQCL = 360,
+ .tZQINIT = 1000,
+ .tDQSCKMAXx2 = 11,
+ .tRASmax = 70,
+ .tFAW = 50
+};
+
+const struct lpddr2_min_tck lpddr2_samsung_min_tck = {
+ .tRL = 3,
+ .tRP_AB = 3,
+ .tRCD = 3,
+ .tWR = 3,
+ .tRAS_MIN = 3,
+ .tRRD = 2,
+ .tWTR = 2,
+ .tXP = 2,
+ .tRTP = 2,
+ .tCKE = 3,
+ .tCKESR = 3,
+ .tFAW = 8
+};
+
+struct lpddr2_device_info lpddr2_samsung_4G_S4_dev = {
+ .device_timings = {
+ &lpddr2_samsung_timings_200_mhz,
+ &lpddr2_samsung_timings_400_mhz
+ },
+ .min_tck = &lpddr2_samsung_min_tck,
+ .type = LPDDR2_TYPE_S4,
+ .density = LPDDR2_DENSITY_4Gb,
+ .io_width = LPDDR2_IO_WIDTH_32
+};
+
+/*
+ * LPDDR2 Configuration Data:
+ * The memory organisation is as below :
+ * EMIF1 - CS0 - 4 Gb
+ * EMIF2 - CS0 - 4 Gb
+ * --------------------
+ * TOTAL - 8 Gb
+ *
+ * Same devices installed on EMIF1 and EMIF2
+ */
+static __initdata struct emif_device_details emif_devices = {
+ .cs0_device = &lpddr2_samsung_4G_S4_dev,
+};
+
+void __init omap4_tuna_emif_init(void)
+{
+ omap_emif_setup_device_details(&emif_devices, &emif_devices);
+}
diff --git a/arch/arm/mach-omap2/board-tuna-input.c b/arch/arm/mach-omap2/board-tuna-input.c
new file mode 100644
index 0000000..8d4d164
--- /dev/null
+++ b/arch/arm/mach-omap2/board-tuna-input.c
@@ -0,0 +1,183 @@
+/*
+ * Copyright (C) 2011 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ */
+
+#include <linux/platform_device.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/keyreset.h>
+#include <linux/gpio_event.h>
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+#include <linux/i2c/atmel_mxt_ts.h>
+#include <linux/platform_data/mms_ts.h>
+#include <asm/mach-types.h>
+#include <plat/omap4-keypad.h>
+
+#include "board-tuna.h"
+#include "mux.h"
+
+#define GPIO_TOUCH_EN 19
+#define GPIO_TOUCH_IRQ 46
+
+/* touch is on i2c3 */
+#define GPIO_TOUCH_SCL 130
+#define GPIO_TOUCH_SDA 131
+
+static int mms_ts_panel_id;
+
+static struct gpio_event_direct_entry tuna_gpio_keypad_keys_map_high[] = {
+ {
+ .code = KEY_POWER,
+ .gpio = 3,
+ },
+};
+
+static struct gpio_event_input_info tuna_gpio_keypad_keys_info_high = {
+ .info.func = gpio_event_input_func,
+ .info.no_suspend = true,
+ .type = EV_KEY,
+ .keymap = tuna_gpio_keypad_keys_map_high,
+ .keymap_size = ARRAY_SIZE(tuna_gpio_keypad_keys_map_high),
+ .flags = GPIOEDF_ACTIVE_HIGH,
+};
+
+static struct gpio_event_direct_entry tuna_gpio_keypad_keys_map_low[] = {
+ {
+ .code = KEY_VOLUMEDOWN,
+ .gpio = 8,
+ },
+ {
+ .code = KEY_VOLUMEUP,
+ .gpio = 30,
+ },
+};
+
+static struct gpio_event_input_info tuna_gpio_keypad_keys_info_low = {
+ .info.func = gpio_event_input_func,
+ .info.no_suspend = true,
+ .type = EV_KEY,
+ .keymap = tuna_gpio_keypad_keys_map_low,
+ .keymap_size = ARRAY_SIZE(tuna_gpio_keypad_keys_map_low),
+};
+
+static struct gpio_event_info *tuna_gpio_keypad_info[] = {
+ &tuna_gpio_keypad_keys_info_high.info,
+ &tuna_gpio_keypad_keys_info_low.info,
+};
+
+static struct gpio_event_platform_data tuna_gpio_keypad_data = {
+ .name = "tuna-gpio-keypad",
+ .info = tuna_gpio_keypad_info,
+ .info_count = ARRAY_SIZE(tuna_gpio_keypad_info)
+};
+
+static struct platform_device tuna_gpio_keypad_device = {
+ .name = GPIO_EVENT_DEV_NAME,
+ .id = 0,
+ .dev = {
+ .platform_data = &tuna_gpio_keypad_data,
+ },
+};
+
+static int melfas_mux_fw_flash(bool to_gpios)
+{
+ /* TOUCH_EN is always an output */
+ if (to_gpios) {
+ gpio_direction_output(GPIO_TOUCH_IRQ, 0);
+ omap_mux_set_gpio(
+ OMAP_PIN_INPUT | OMAP_MUX_MODE3,
+ GPIO_TOUCH_IRQ);
+
+ gpio_direction_output(GPIO_TOUCH_SCL, 0);
+ omap_mux_set_gpio(OMAP_PIN_INPUT | OMAP_MUX_MODE3,
+ GPIO_TOUCH_SCL);
+
+ gpio_direction_output(GPIO_TOUCH_SDA, 0);
+ omap_mux_set_gpio(OMAP_PIN_INPUT | OMAP_MUX_MODE3,
+ GPIO_TOUCH_SDA);
+ } else {
+ gpio_direction_output(GPIO_TOUCH_IRQ, 1);
+ gpio_direction_input(GPIO_TOUCH_IRQ);
+ omap_mux_set_gpio(
+ OMAP_PIN_INPUT_PULLUP | OMAP_MUX_MODE3,
+ GPIO_TOUCH_IRQ);
+
+ gpio_direction_output(GPIO_TOUCH_SCL, 1);
+ gpio_direction_input(GPIO_TOUCH_SCL);
+ omap_mux_set_gpio(OMAP_PIN_INPUT | OMAP_MUX_MODE0,
+ GPIO_TOUCH_SCL);
+
+ gpio_direction_output(GPIO_TOUCH_SDA, 1);
+ gpio_direction_input(GPIO_TOUCH_SDA);
+ omap_mux_set_gpio(OMAP_PIN_INPUT | OMAP_MUX_MODE0,
+ GPIO_TOUCH_SDA);
+ }
+
+ return 0;
+}
+
+static int __init mms_ts_panel_id_setup(char *str)
+{
+ mms_ts_panel_id = simple_strtol(str, NULL, 0);
+ return 1;
+}
+__setup("mms_ts.panel_id=", mms_ts_panel_id_setup);
+
+static struct mms_ts_platform_data mms_ts_pdata = {
+ .max_x = 720,
+ .max_y = 1280,
+ .mux_fw_flash = melfas_mux_fw_flash,
+ .gpio_resetb = GPIO_TOUCH_IRQ,
+ .gpio_vdd_en = GPIO_TOUCH_EN,
+ .gpio_scl = GPIO_TOUCH_SCL,
+ .gpio_sda = GPIO_TOUCH_SDA,
+};
+
+static struct i2c_board_info __initdata tuna_i2c3_boardinfo_final[] = {
+ {
+ I2C_BOARD_INFO("mms_ts", 0x48),
+ .flags = I2C_CLIENT_WAKE,
+ .platform_data = &mms_ts_pdata,
+ .irq = OMAP_GPIO_IRQ(GPIO_TOUCH_IRQ),
+ },
+};
+
+void __init omap4_tuna_input_init(void)
+{
+ gpio_request(GPIO_TOUCH_IRQ, "tsp_int_n");
+ gpio_direction_input(GPIO_TOUCH_IRQ);
+ omap_mux_init_gpio(GPIO_TOUCH_IRQ,
+ OMAP_PIN_INPUT_PULLUP);
+
+ gpio_request(GPIO_TOUCH_EN, "tsp_en");
+ gpio_direction_output(GPIO_TOUCH_EN, 1);
+ omap_mux_init_gpio(GPIO_TOUCH_EN, OMAP_PIN_OUTPUT);
+ gpio_request(GPIO_TOUCH_SCL, "ap_i2c3_scl");
+ gpio_request(GPIO_TOUCH_SDA, "ap_i2c3_sda");
+
+ /* 0x12 == FPCB 3.2
+ * 0xa1 == FPCB 3.1
+ */
+ if (mms_ts_panel_id == 0x12)
+ mms_ts_pdata.fw_name = "mms144_ts_rev32.fw";
+ else
+ mms_ts_pdata.fw_name = "mms144_ts_rev31.fw";
+
+ i2c_register_board_info(3, tuna_i2c3_boardinfo_final,
+ ARRAY_SIZE(tuna_i2c3_boardinfo_final));
+
+ omap_mux_init_gpio(8, OMAP_PIN_INPUT);
+ omap_mux_init_gpio(30, OMAP_PIN_INPUT);
+
+ platform_device_register(&tuna_gpio_keypad_device);
+}
diff --git a/arch/arm/mach-omap2/board-tuna-jack.c b/arch/arm/mach-omap2/board-tuna-jack.c
new file mode 100644
index 0000000..b292bce
--- /dev/null
+++ b/arch/arm/mach-omap2/board-tuna-jack.c
@@ -0,0 +1,152 @@
+/* Board support file for Samsung Tuna Board.
+ *
+ * Copyright (C) 2011 Google, Inc.
+ * Copyright (C) 2010 Texas Instruments
+ *
+ * Based on mach-omap2/board-omap4panda.c
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+#include <linux/input.h>
+#include <linux/i2c/twl6030-madc.h>
+#include <linux/sec_jack.h>
+
+#include "mux.h"
+#include "board-tuna.h"
+
+#define GPIO_EAR_MICBIAS_EN 49
+#define GPIO_DET_35 0
+#define GPIO_EAR_SEND_END 1
+
+#define ADC_CHANNEL_JACK 2
+
+static void sec_jack_set_micbias_state(bool on)
+{
+ gpio_set_value(GPIO_EAR_MICBIAS_EN, on);
+}
+
+static struct sec_jack_zone sec_jack_zones[] = {
+ {
+ /* adc < 50, unstable zone, default to 3pole if it stays
+ * in this range for a half second (20ms delays, 25 samples)
+ */
+ .adc_high = 50,
+ .delay_ms = 20,
+ .check_count = 25,
+ .jack_type = SEC_HEADSET_3POLE,
+ },
+ {
+ /* 50 < adc <= 450, unstable zone, default to 3pole if it stays
+ * in this range for a second (10ms delays, 100 samples)
+ */
+ .adc_high = 450,
+ .delay_ms = 10,
+ .check_count = 100,
+ .jack_type = SEC_HEADSET_3POLE,
+ },
+ {
+ /* 450 < adc <= 900, unstable zone, default to 4pole if it
+ * stays in this range for a second (10ms delays, 100 samples)
+ */
+ .adc_high = 900,
+ .delay_ms = 10,
+ .check_count = 100,
+ .jack_type = SEC_HEADSET_4POLE,
+ },
+ {
+ /* 900 < adc <= 1500, 4 pole zone, default to 4pole if it
+ * stays in this range for 200ms (20ms delays, 10 samples)
+ */
+ .adc_high = 1500,
+ .delay_ms = 20,
+ .check_count = 10,
+ .jack_type = SEC_HEADSET_4POLE,
+ },
+ {
+ /* adc > 1500, unstable zone, default to 3pole if it stays
+ * in this range for a second (10ms delays, 100 samples)
+ */
+ .adc_high = 0x7fffffff,
+ .delay_ms = 10,
+ .check_count = 100,
+ .jack_type = SEC_HEADSET_3POLE,
+ },
+};
+
+/* To support 3-buttons earjack */
+static struct sec_jack_buttons_zone sec_jack_buttons_zones[] = {
+ {
+ /* 0 <= adc <= 93, stable zone */
+ .code = KEY_MEDIA,
+ .adc_low = 0,
+ .adc_high = 93,
+ },
+ {
+ /* 94 <= adc <= 198, stable zone */
+ .code = KEY_PREVIOUSSONG,
+ .adc_low = 94,
+ .adc_high = 198,
+ },
+ {
+ /* 199 <= adc <= 370, stable zone */
+ .code = KEY_NEXTSONG,
+ .adc_low = 199,
+ .adc_high = 370,
+ },
+};
+
+static int sec_jack_get_adc_value(void)
+{
+ int value;
+
+ value = twl6030_get_madc_conversion(ADC_CHANNEL_JACK);
+ return (int)(1800*value) / 1024;
+}
+
+struct sec_jack_platform_data sec_jack_pdata = {
+ .set_micbias_state = sec_jack_set_micbias_state,
+ .get_adc_value = sec_jack_get_adc_value,
+ .zones = sec_jack_zones,
+ .num_zones = ARRAY_SIZE(sec_jack_zones),
+ .buttons_zones = sec_jack_buttons_zones,
+ .num_buttons_zones = ARRAY_SIZE(sec_jack_buttons_zones),
+ .det_gpio = GPIO_DET_35,
+ .send_end_gpio = GPIO_EAR_SEND_END,
+};
+
+static struct platform_device sec_device_jack = {
+ .name = "sec_jack",
+ .id = 1, /* will be used also for gpio_event id */
+ .dev.platform_data = &sec_jack_pdata,
+};
+
+void __init omap4_tuna_jack_init(void)
+{
+ omap_mux_init_signal("sim_io.gpio_wk0", OMAP_PIN_INPUT);
+ gpio_request(GPIO_DET_35, "det_35_en");
+ gpio_direction_input(GPIO_DET_35);
+
+ omap_mux_init_signal("sim_clk.gpio_wk1", OMAP_PIN_INPUT);
+ gpio_request(GPIO_EAR_SEND_END, "ear_send_end");
+ gpio_direction_input(GPIO_EAR_SEND_END);
+
+ omap_mux_init_signal("gpmc_a25.gpio_49", OMAP_PIN_OUTPUT | OMAP_MUX_MODE3);
+ gpio_request(GPIO_EAR_MICBIAS_EN, "ear_micbias_en");
+ gpio_direction_output(GPIO_EAR_MICBIAS_EN, 0);
+
+ gpio_free(GPIO_DET_35);
+ gpio_free(GPIO_EAR_SEND_END);
+ platform_device_register(&sec_device_jack);
+}
diff --git a/arch/arm/mach-omap2/board-tuna-modems.c b/arch/arm/mach-omap2/board-tuna-modems.c
new file mode 100755
index 0000000..c244ff9
--- /dev/null
+++ b/arch/arm/mach-omap2/board-tuna-modems.c
@@ -0,0 +1,749 @@
+/* linux/arch/arm/mach-xxxx/board-tuna-modems.c
+ * Copyright (C) 2010 Samsung Electronics. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/irq.h>
+#include <linux/gpio.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/delay.h>
+
+#include <mach/omap4-common.h>
+#include <linux/platform_data/modem.h>
+#include "board-tuna.h"
+#include "mux.h"
+
+#define OMAP_GPIO_MIPI_HSI_CP_ON 53
+#define OMAP_GPIO_MIPI_HSI_RESET_REQ_N 50
+#define OMAP_GPIO_MIPI_HSI_CP_RST 15
+#define OMAP_GPIO_MIPI_HSI_PDA_ACTIVE 119
+#define OMAP_GPIO_MIPI_HSI_PHONE_ACTIVE 120
+#define OMAP_GPIO_MIPI_HSI_CP_DUMP_INT 95
+#define OMAP_GPIO_MIPI_HSI_GPS_UART_SEL 164
+
+#define OMAP_GPIO_DPRAM_VIA_RST 15
+#define OMAP_GPIO_DPRAM_PDA_ACTIVE 119
+#define OMAP_GPIO_DPRAM_PHONE_ACTIVE 120
+#define OMAP_GPIO_DPRAM_PWRHOLD_OFF 53
+#define OMAP_GPIO_DPRAM_INT_N 62
+
+#define OMAP_GPIO_CMC_SPI_CLK_ACK 178
+#define OMAP_GPIO_CMC_SPI_CLK_REQ 164
+#define OMAP_GPIO_CMC_SPI_WAKEUP_INT 134
+#define OMAP_GPIO_LTE_ACTIVE 47
+#define OMAP_GPIO_CMC2AP_INT1 61
+#define OMAP_GPIO_CMC2AP_INT2 160
+#define OMAP_GPIO_AP2CMC_INT1 18
+#define OMAP_GPIO_AP2CMC_INT2 28
+#define OMAP_GPIO_221_PMIC_PWRON 41
+#define OMAP_GPIO_CMC_RST 50
+#define OMAP_GPIO_221_PMIC_PWRHOLD_OFF 163
+
+#define DPRAM_START_ADDRESS 0x04000000
+#define DPRAM_SIZE 0x4000
+#define DPRAM_END_ADDRESS (DPRAM_START_ADDRESS + DPRAM_SIZE - 1)
+
+#define GPMC_CONTROL_BASE_ADDR 0x50000000
+#define GPMC_CONFIG1_1 (GPMC_CONTROL_BASE_ADDR + 0x90)
+#define GPMC_CONFIG2_1 (GPMC_CONTROL_BASE_ADDR + 0x94)
+#define GPMC_CONFIG3_1 (GPMC_CONTROL_BASE_ADDR + 0x98)
+#define GPMC_CONFIG4_1 (GPMC_CONTROL_BASE_ADDR + 0x9C)
+#define GPMC_CONFIG5_1 (GPMC_CONTROL_BASE_ADDR + 0xA0)
+#define GPMC_CONFIG6_1 (GPMC_CONTROL_BASE_ADDR + 0xA4)
+#define GPMC_CONFIG7_1 (GPMC_CONTROL_BASE_ADDR + 0xA8)
+
+#define DPRAM_GPMC_CONFIG1 0x00001201
+#define DPRAM_GPMC_CONFIG2 0x000f1200
+#define DPRAM_GPMC_CONFIG3 0x44040400
+#define DPRAM_GPMC_CONFIG4 0x0e05f155
+#define DPRAM_GPMC_CONFIG5 0x000e1016
+#define DPRAM_GPMC_CONFIG6 0x060603c3
+#define DPRAM_GPMC_CONFIG7 0x00000F44
+
+/* umts target platform data */
+static struct modem_io_t umts_io_devices[] = {
+ [0] = {
+ .name = "umts_ipc0",
+ .id = 0x1,
+ .format = IPC_FMT,
+ .io_type = IODEV_MISC,
+ .link = LINKDEV_MIPI,
+ },
+ [1] = {
+ .name = "umts_rfs0",
+ .id = 0x41,
+ .format = IPC_RFS,
+ .io_type = IODEV_MISC,
+ .link = LINKDEV_MIPI,
+ },
+ [2] = {
+ .name = "rmnet0",
+ .id = 0x2A,
+ .format = IPC_RAW,
+ .io_type = IODEV_NET,
+ .link = LINKDEV_MIPI,
+ },
+ [3] = {
+ .name = "umts_boot0",
+ .id = 0x0,
+ .format = IPC_BOOT,
+ .io_type = IODEV_MISC,
+ .link = LINKDEV_MIPI,
+ },
+ [4] = {
+ .name = "rmnet1",
+ .id = 0x2B,
+ .format = IPC_RAW,
+ .io_type = IODEV_NET,
+ .link = LINKDEV_MIPI,
+ },
+ [5] = {
+ .name = "rmnet2",
+ .id = 0x2C,
+ .format = IPC_RAW,
+ .io_type = IODEV_NET,
+ .link = LINKDEV_MIPI,
+ },
+ [6] = {
+ .name = "multipdp",
+ .id = 0x1,
+ .format = IPC_MULTI_RAW,
+ .io_type = IODEV_DUMMY,
+ .link = LINKDEV_MIPI,
+ },
+ [7] = {
+ .name = "umts_ramdump0",
+ .id = 0x0,
+ .format = IPC_RAMDUMP,
+ .io_type = IODEV_MISC,
+ .link = LINKDEV_MIPI,
+ },
+};
+
+static struct modem_data umts_modem_data = {
+ .name = "xmm6260",
+
+ .gpio_cp_on = OMAP_GPIO_MIPI_HSI_CP_ON,
+ .gpio_reset_req_n = OMAP_GPIO_MIPI_HSI_RESET_REQ_N,
+ .gpio_cp_reset = OMAP_GPIO_MIPI_HSI_CP_RST,
+ .gpio_pda_active = OMAP_GPIO_MIPI_HSI_PDA_ACTIVE,
+ .gpio_phone_active = OMAP_GPIO_MIPI_HSI_PHONE_ACTIVE,
+ .gpio_cp_dump_int = OMAP_GPIO_MIPI_HSI_CP_DUMP_INT,
+ .gpio_flm_uart_sel = OMAP_GPIO_MIPI_HSI_GPS_UART_SEL,
+ .gpio_cp_warm_reset = 0,
+
+ .modem_type = IMC_XMM6260,
+ .link_type = LINKDEV_MIPI,
+ .modem_net = UMTS_NETWORK,
+
+ .num_iodevs = ARRAY_SIZE(umts_io_devices),
+ .iodevs = umts_io_devices,
+};
+
+static void umts_modem_cfg_gpio(void)
+{
+ unsigned gpio_reset_req_n = umts_modem_data.gpio_reset_req_n;
+ unsigned gpio_cp_on = umts_modem_data.gpio_cp_on;
+ unsigned gpio_cp_rst = umts_modem_data.gpio_cp_reset;
+ unsigned gpio_pda_active = umts_modem_data.gpio_pda_active;
+ unsigned gpio_phone_active = umts_modem_data.gpio_phone_active;
+ unsigned gpio_cp_dump_int = umts_modem_data.gpio_cp_dump_int;
+ unsigned gpio_flm_uart_sel = umts_modem_data.gpio_flm_uart_sel;
+
+ /* gpio mux setting */
+ omap_mux_init_signal("gpmc_ncs0.gpio_50", OMAP_PIN_OUTPUT);
+ omap_mux_init_signal("gpmc_ncs3.gpio_53", OMAP_PIN_OUTPUT);
+ omap_mux_init_signal("dpm_emu4.gpio_15", OMAP_PIN_OUTPUT);
+ omap_mux_init_signal("abe_dmic_clk1.gpio_119", OMAP_PIN_OUTPUT |
+ OMAP_PIN_OFF_OUTPUT_LOW);
+ omap_mux_init_signal("abe_dmic_din1.gpio_120", OMAP_PIN_INPUT);
+ omap_mux_init_signal("usbb1_ulpitll_dat7.gpio_95", OMAP_PIN_INPUT);
+ omap_mux_init_signal("usbb2_ulpitll_dat3.gpio_164", OMAP_PIN_OUTPUT);
+ omap_mux_init_signal("uart3_cts_rctx.uart1_tx", OMAP_PIN_INPUT);
+ omap_mux_init_signal("mcspi1_cs1.uart1_rx", OMAP_PIN_INPUT);
+
+ if (gpio_reset_req_n) {
+ gpio_request(gpio_reset_req_n, "RESET_REQ_N");
+ gpio_direction_output(gpio_reset_req_n, 0);
+ }
+
+ if (gpio_cp_on) {
+ gpio_request(gpio_cp_on, "CP_ON");
+ gpio_direction_output(gpio_cp_on, 0);
+ }
+
+ if (gpio_cp_rst) {
+ gpio_request(gpio_cp_rst, "CP_RST");
+ gpio_direction_output(gpio_cp_rst, 0);
+ }
+
+ if (gpio_pda_active) {
+ gpio_request(gpio_pda_active, "PDA_ACTIVE");
+ gpio_direction_output(gpio_pda_active, 0);
+ }
+
+ if (gpio_phone_active) {
+ gpio_request(gpio_phone_active, "PHONE_ACTIVE");
+ gpio_direction_input(gpio_phone_active);
+ }
+
+ if (gpio_cp_dump_int) {
+ gpio_request(gpio_cp_dump_int, "CP_DUMP_INT");
+ gpio_direction_input(gpio_cp_dump_int);
+ }
+
+ if (gpio_flm_uart_sel) {
+ gpio_request(gpio_flm_uart_sel, "GPS_UART_SEL");
+ gpio_direction_output(gpio_flm_uart_sel, 1);
+ }
+
+ if (gpio_phone_active)
+ irq_set_irq_type(
+ OMAP_GPIO_IRQ(OMAP_GPIO_MIPI_HSI_PHONE_ACTIVE),
+ IRQ_TYPE_LEVEL_HIGH);
+
+ pr_debug("umts_modem_cfg_gpio done\n");
+}
+
+/* To get modem state, register phone active irq using resource */
+static struct resource umts_modem_res[] = {
+ [0] = {
+ .name = "umts_phone_active",
+ .start = OMAP_GPIO_IRQ(OMAP_GPIO_MIPI_HSI_PHONE_ACTIVE),
+ .end = OMAP_GPIO_IRQ(OMAP_GPIO_MIPI_HSI_PHONE_ACTIVE),
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+/* if use more than one modem device, then set id num */
+static struct platform_device umts_modem = {
+ .name = "modem_if",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(umts_modem_res),
+ .resource = umts_modem_res,
+ .dev = {
+ .platform_data = &umts_modem_data,
+ },
+};
+
+static struct modem_io_t cdma_io_devices[] = {
+ [0] = {
+ .name = "multipdp",
+ .id = 0x1,
+ .format = IPC_MULTI_RAW,
+ .io_type = IODEV_DUMMY,
+ .link = LINKDEV_DPRAM,
+ },
+ [1] = {
+ .name = "cdma_ipc0",
+ .id = 0x1,
+ .format = IPC_FMT,
+ .io_type = IODEV_MISC,
+ .link = LINKDEV_DPRAM,
+ },
+ [2] = {
+ .name = "cdma_boot0",
+ .id = 0x1,
+ .format = IPC_BOOT,
+ .io_type = IODEV_MISC,
+ .link = LINKDEV_DPRAM,
+ },
+ [3] = {
+ .name = "cdma_rmnet0",
+ .id = 0x2A,
+ .format = IPC_RAW,
+ .io_type = IODEV_NET,
+ .link = LINKDEV_DPRAM,
+ },
+ [4] = {
+ .name = "cdma_rmnet1",
+ .id = 0x2B,
+ .format = IPC_RAW,
+ .io_type = IODEV_NET,
+ .link = LINKDEV_DPRAM,
+ },
+ [5] = {
+ .name = "cdma_rmnet2",
+ .id = 0x2C,
+ .format = IPC_RAW,
+ .io_type = IODEV_NET,
+ .link = LINKDEV_DPRAM,
+ },
+ [6] = {
+ .name = "cdma_rmnet3",
+ .id = 0x2D,
+ .format = IPC_RAW,
+ .io_type = IODEV_NET,
+ .link = LINKDEV_DPRAM,
+ },
+ [7] = {
+ .name = "cdma_rmnet4",
+ .id = 0x27,
+ .format = IPC_RAW,
+ .io_type = IODEV_NET,
+ .link = LINKDEV_DPRAM,
+ },
+ [8] = {
+ .name = "cdma_rmnet5", /* DM Port io-device */
+ .id = 0x3A,
+ .format = IPC_RAW,
+ .io_type = IODEV_MISC,
+ .link = LINKDEV_DPRAM,
+ },
+ [9] = {
+ .name = "cdma_ramdump0",
+ .id = 0x1,
+ .format = IPC_RAMDUMP,
+ .io_type = IODEV_MISC,
+ .link = LINKDEV_DPRAM,
+ },
+ [10] = {
+ .name = "cdma_rmnet6", /* AT CMD io-device */
+ .id = 0x31,
+ .format = IPC_RAW,
+ .io_type = IODEV_MISC,
+ .link = LINKDEV_DPRAM,
+ },
+};
+
+/* cdma target platform data */
+static struct modem_data cdma_modem_data = {
+ .name = "cbp7.1",
+
+ /*ToDo: always power on vbat 3.3v it is not cennected GPIO*/
+ .gpio_cp_on = 0,
+ .gpio_reset_req_n = 0,
+ .gpio_cp_reset = OMAP_GPIO_DPRAM_VIA_RST,
+ .gpio_pda_active = OMAP_GPIO_DPRAM_PDA_ACTIVE,
+ .gpio_phone_active = OMAP_GPIO_DPRAM_PHONE_ACTIVE,
+ .gpio_cp_dump_int = 0, /*ToDo:*/
+ .gpio_cp_warm_reset = 0,
+ .gpio_cp_off = OMAP_GPIO_DPRAM_PWRHOLD_OFF,
+
+ .modem_type = VIA_CBP71,
+ .link_type = LINKDEV_DPRAM,
+ .modem_net = CDMA_NETWORK,
+
+ .num_iodevs = ARRAY_SIZE(cdma_io_devices),
+ .iodevs = cdma_io_devices,
+};
+
+static void dpram_cfg_gpio(void)
+{
+ int nRetry = 0;
+ int resetdone;
+
+ omap_mux_init_signal("gpmc_ad0", OMAP_PULL_ENA|OMAP_PULL_UP|OMAP_INPUT_EN);
+ omap_mux_init_signal("gpmc_ad1", OMAP_PULL_ENA|OMAP_PULL_UP|OMAP_INPUT_EN);
+ omap_mux_init_signal("gpmc_ad2", OMAP_PULL_ENA|OMAP_PULL_UP|OMAP_INPUT_EN);
+ omap_mux_init_signal("gpmc_ad3", OMAP_PULL_ENA|OMAP_PULL_UP|OMAP_INPUT_EN);
+ omap_mux_init_signal("gpmc_ad4", OMAP_PULL_ENA|OMAP_PULL_UP|OMAP_INPUT_EN);
+ omap_mux_init_signal("gpmc_ad5", OMAP_PULL_ENA|OMAP_PULL_UP|OMAP_INPUT_EN);
+ omap_mux_init_signal("gpmc_ad6", OMAP_PULL_ENA|OMAP_PULL_UP|OMAP_INPUT_EN);
+ omap_mux_init_signal("gpmc_ad7", OMAP_PULL_ENA|OMAP_PULL_UP|OMAP_INPUT_EN);
+ omap_mux_init_signal("gpmc_ad8", OMAP_PULL_ENA|OMAP_PULL_UP|OMAP_INPUT_EN);
+ omap_mux_init_signal("gpmc_ad9", OMAP_PULL_ENA|OMAP_PULL_UP|OMAP_INPUT_EN);
+ omap_mux_init_signal("gpmc_ad10", OMAP_PULL_ENA|OMAP_PULL_UP|OMAP_INPUT_EN);
+ omap_mux_init_signal("gpmc_ad11", OMAP_PULL_ENA|OMAP_PULL_UP|OMAP_INPUT_EN);
+ omap_mux_init_signal("gpmc_ad12", OMAP_PULL_ENA|OMAP_PULL_UP|OMAP_INPUT_EN);
+ omap_mux_init_signal("gpmc_ad13", OMAP_PULL_ENA|OMAP_PULL_UP|OMAP_INPUT_EN);
+ omap_mux_init_signal("gpmc_ad14", OMAP_PULL_ENA|OMAP_PULL_UP|OMAP_INPUT_EN);
+ omap_mux_init_signal("gpmc_ad15", OMAP_PULL_ENA|OMAP_PULL_UP|OMAP_INPUT_EN);
+
+ omap_mux_init_signal("gpmc_nadv_ale", 0);
+ omap_mux_init_signal("gpmc_nwe", 0);
+ omap_mux_init_signal("gpmc_nbe0_cle", 0);
+ omap_mux_init_signal("gpmc_ncs1", 0);
+ omap_mux_init_signal("gpmc_nbe1", 0);
+
+ omap_mux_init_signal("gpmc_wait1.gpio_62", OMAP_WAKEUP_EN | OMAP_INPUT_EN);
+ omap_mux_init_signal("dpm_emu3", OMAP_MUX_MODE3);
+ omap_mux_init_signal("gpmc_ncs3.gpio_53", OMAP_PIN_OUTPUT);
+
+ gpio_request(OMAP_GPIO_DPRAM_INT_N, "dpram_int");
+ gpio_direction_input(OMAP_GPIO_DPRAM_INT_N);
+ irq_set_irq_type(OMAP_GPIO_IRQ(OMAP_GPIO_DPRAM_INT_N),
+ IRQ_TYPE_LEVEL_LOW);
+
+ /*dpram platform init setting*/
+ __raw_writel(0x02, OMAP4_GPMC_IO_ADDRESS((OMAP44XX_GPMC_BASE + 0x10)));
+
+ while (nRetry < 100) {
+ msleep(20);
+ resetdone = __raw_readl(OMAP4_GPMC_IO_ADDRESS(OMAP44XX_GPMC_BASE
+ + 0x14));
+ if (resetdone == 0x1)
+ break;
+
+ nRetry++;
+ }
+
+ __raw_writel(0x10, OMAP4_GPMC_IO_ADDRESS((OMAP44XX_GPMC_BASE + 0x10)));
+
+ __raw_writel((u32)DPRAM_GPMC_CONFIG1,
+ OMAP4_GPMC_IO_ADDRESS(GPMC_CONFIG1_1));
+ __raw_writel((u32)DPRAM_GPMC_CONFIG2,
+ OMAP4_GPMC_IO_ADDRESS(GPMC_CONFIG2_1));
+ __raw_writel((u32)DPRAM_GPMC_CONFIG3,
+ OMAP4_GPMC_IO_ADDRESS(GPMC_CONFIG3_1));
+ __raw_writel((u32)DPRAM_GPMC_CONFIG4,
+ OMAP4_GPMC_IO_ADDRESS(GPMC_CONFIG4_1));
+ __raw_writel((u32)DPRAM_GPMC_CONFIG5,
+ OMAP4_GPMC_IO_ADDRESS(GPMC_CONFIG5_1));
+ __raw_writel((u32)DPRAM_GPMC_CONFIG6,
+ OMAP4_GPMC_IO_ADDRESS(GPMC_CONFIG6_1));
+
+ __raw_writel((u32)0xF04, OMAP4_GPMC_IO_ADDRESS(GPMC_CONFIG7_1));
+ msleep(50);
+ __raw_writel((u32)(0xF04 | 0x040),
+ OMAP4_GPMC_IO_ADDRESS(GPMC_CONFIG7_1));
+}
+
+static int dpram_cfg_gpmc_clk(void)
+{
+ struct clk *dpram_gpmc_ck;
+ struct clk *dpram_gpmc_ick;
+
+ dpram_gpmc_ck = clk_get(NULL, "gpmc_ck");
+ if (IS_ERR(dpram_gpmc_ck)) {
+ pr_err("Could not get GPMC clock gpmc_ck\n");
+ return -ENOENT;
+ }
+ clk_enable(dpram_gpmc_ck);
+
+ dpram_gpmc_ick = clk_get(NULL, "gpmc_ick");
+ if (IS_ERR(dpram_gpmc_ick)) {
+ clk_disable(dpram_gpmc_ck);
+ pr_err("Could not get GPMC clock gpmc_ick\n");
+ return -ENOENT;
+ }
+ clk_enable(dpram_gpmc_ick);
+
+ return 0;
+}
+
+static void cdma_modem_cfg_gpio(void)
+{
+ unsigned gpio_cp_rst = cdma_modem_data.gpio_cp_reset;
+ unsigned gpio_pda_active = cdma_modem_data.gpio_pda_active;
+ unsigned gpio_phone_active = cdma_modem_data.gpio_phone_active;
+ unsigned gpio_cp_off = cdma_modem_data.gpio_cp_off;
+
+ dpram_cfg_gpio();
+ if (dpram_cfg_gpmc_clk()) {
+ pr_err("fail to enable GPMC clock\n");
+ return;
+ }
+
+ omap_mux_init_signal("abe_dmic_din1.gpio_120", OMAP_PIN_INPUT);
+ omap_mux_init_signal("abe_dmic_clk1.gpio_119", OMAP_PIN_OUTPUT |
+ OMAP_PIN_OFF_OUTPUT_LOW);
+
+ /* gpio mux setting */
+ if (gpio_cp_rst) {
+ gpio_request(gpio_cp_rst, "CP_RST");
+ gpio_direction_output(gpio_cp_rst, 0);
+ }
+
+ if (gpio_pda_active) {
+ gpio_request(gpio_pda_active, "PDA_ACTIVE");
+ gpio_direction_output(gpio_pda_active, 0);
+ }
+
+ if (gpio_phone_active) {
+ gpio_request(gpio_phone_active, "PHONE_ACTIVE");
+ gpio_direction_input(gpio_phone_active);
+ }
+
+ if (gpio_cp_off) {
+ gpio_request(gpio_cp_off, "VIA_OFF");
+ gpio_direction_output(gpio_cp_off, 1);
+ }
+
+ if (gpio_phone_active)
+ irq_set_irq_type(
+ OMAP_GPIO_IRQ(OMAP_GPIO_DPRAM_PHONE_ACTIVE),
+ IRQ_TYPE_LEVEL_HIGH);
+}
+
+static struct resource cdma_modem_res[] = {
+ [0] = {
+ .name = "cdma_phone_active",
+ .start = OMAP_GPIO_IRQ(OMAP_GPIO_DPRAM_PHONE_ACTIVE),
+ .end = OMAP_GPIO_IRQ(OMAP_GPIO_DPRAM_PHONE_ACTIVE),
+ .flags = IORESOURCE_IRQ,
+ },
+ [1] = {
+ .name = "cdma_dpram_int",
+ .start = OMAP_GPIO_IRQ(OMAP_GPIO_DPRAM_INT_N),
+ .end = OMAP_GPIO_IRQ(OMAP_GPIO_DPRAM_INT_N),
+ .flags = IORESOURCE_IRQ,
+ },
+ [2] = {
+ .name = "cdma_dpram",
+ .start = DPRAM_START_ADDRESS,
+ .end = DPRAM_END_ADDRESS,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct platform_device cdma_modem = {
+ .name = "modem_if",
+ .id = 1,
+ .num_resources = ARRAY_SIZE(cdma_modem_res),
+ .resource = cdma_modem_res,
+ .dev = {
+ .platform_data = &cdma_modem_data,
+ },
+};
+
+/* lte target platform data */
+static struct modem_io_t lte_io_devices[] = {
+ [0] = {
+ .name = "lte_ipc0",
+ .id = 0x1,
+ .format = IPC_FMT,
+ .io_type = IODEV_MISC,
+ .link = LINKDEV_USB,
+ },
+ [1] = {
+ .name = "lte_rmnet0",
+ .id = 0x2A,
+ .format = IPC_RAW,
+ .io_type = IODEV_NET,
+ .link = LINKDEV_USB,
+ },
+ [2] = {
+ .name = "lte_rfs0",
+ .id = 0x0,
+ .format = IPC_RFS,
+ .io_type = IODEV_MISC,
+ .link = LINKDEV_USB,
+ },
+ [3] = {
+ .name = "lte_boot0",
+ .id = 0x0,
+ .format = IPC_BOOT,
+ .io_type = IODEV_MISC,
+ .link = LINKDEV_USB,
+ },
+ [4] = {
+ .name = "lte_rmnet1",
+ .id = 0x2B,
+ .format = IPC_RAW,
+ .io_type = IODEV_NET,
+ .link = LINKDEV_USB,
+ },
+ [5] = {
+ .name = "lte_rmnet2",
+ .id = 0x2C,
+ .format = IPC_RAW,
+ .io_type = IODEV_NET,
+ .link = LINKDEV_USB,
+ },
+ [6] = {
+ .name = "lte_rmnet3",
+ .id = 0x2D,
+ .format = IPC_RAW,
+ .io_type = IODEV_NET,
+ .link = LINKDEV_USB,
+ },
+ [7] = {
+ .name = "lte_multipdp",
+ .id = 0x1,
+ .format = IPC_MULTI_RAW,
+ .io_type = IODEV_DUMMY,
+ .link = LINKDEV_USB,
+ },
+ [8] = {
+ .name = "lte_rmnet4", /* DM Port io-device */
+ .id = 0x3F,
+ .format = IPC_RAW,
+ .io_type = IODEV_MISC,
+ .link = LINKDEV_USB,
+ },
+ [9] = {
+ .name = "lte_ramdump0",
+ .id = 0x0,
+ .format = IPC_RAMDUMP,
+ .io_type = IODEV_MISC,
+ .link = LINKDEV_USB,
+ },
+};
+
+/*
+Prime vs P4 usage
+CMC2AP_INT1 vs CMC2AP_STATUS
+AP2CMC_INT1 vs AP2CMC_STATUS
+CMC2AP_INT2 vs CMC2AP_WAKEUP
+AP2CMC_INT2 vs AP2CMC_WAKEUP
+*/
+static struct modem_data lte_modem_data = {
+ .name = "cmc221",
+
+ .gpio_cp_on = OMAP_GPIO_221_PMIC_PWRON,
+ .gpio_reset_req_n = 0,
+ .gpio_cp_reset = OMAP_GPIO_CMC_RST,
+ .gpio_pda_active = 0,/*NOT YET CONNECTED*/
+ .gpio_phone_active = OMAP_GPIO_LTE_ACTIVE,
+ .gpio_cp_dump_int = OMAP_GPIO_LTE_ACTIVE,/*TO BE CHECKED*/
+
+ .gpio_cp_warm_reset = 0,
+#ifdef CONFIG_LTE_MODEM_CMC221
+ .gpio_cp_off = OMAP_GPIO_221_PMIC_PWRHOLD_OFF,
+ .gpio_slave_wakeup = OMAP_GPIO_AP2CMC_INT2,
+ .gpio_host_wakeup = OMAP_GPIO_CMC2AP_INT2,
+ .gpio_host_active = OMAP_GPIO_AP2CMC_INT1,
+#endif
+
+ .modem_type = SEC_CMC221,
+ .link_type = LINKDEV_USB,
+ .modem_net = LTE_NETWORK,
+
+ .num_iodevs = ARRAY_SIZE(lte_io_devices),
+ .iodevs = lte_io_devices,
+};
+
+static void omap_lte_mux_init(void)
+{
+ pr_debug("[MODEM_IF] %s IN!\n", __func__);
+
+ omap_mux_init_signal("gpmc_a17.gpio_41", OMAP_PIN_OUTPUT);
+ omap_mux_init_signal("usbb2_ulpitll_dat2.gpio_163", OMAP_PIN_OUTPUT);
+ omap_mux_init_signal("gpmc_ncs0.gpio_50", OMAP_PIN_OUTPUT);
+ omap_mux_init_signal("dpm_emu7.gpio_18", OMAP_PIN_OUTPUT);
+ omap_mux_init_signal("usbb2_ulpitll_nxt.gpio_160",
+ OMAP_PIN_INPUT | OMAP_PIN_OFF_WAKEUPENABLE);
+ omap_mux_init_signal("dpm_emu17.gpio_28", OMAP_PIN_OUTPUT);
+ omap_mux_init_signal("gpmc_a23.gpio_47", OMAP_PIN_INPUT_PULLDOWN);
+}
+
+static void lte_modem_cfg_gpio(void)
+{
+ unsigned gpio_cp_on = lte_modem_data.gpio_cp_on;
+ unsigned gpio_cp_rst = lte_modem_data.gpio_cp_reset;
+ unsigned gpio_phone_active = lte_modem_data.gpio_phone_active;
+#ifdef CONFIG_LTE_MODEM_CMC221
+ unsigned gpio_cp_off = lte_modem_data.gpio_cp_off;
+ unsigned gpio_slave_wakeup = lte_modem_data.gpio_slave_wakeup;
+ unsigned gpio_host_wakeup = lte_modem_data.gpio_host_wakeup;
+ unsigned gpio_host_active = lte_modem_data.gpio_host_active;
+#endif
+
+ omap_lte_mux_init();
+ if (gpio_cp_on) {
+ gpio_request(gpio_cp_on, "LTE_ON");
+ gpio_direction_output(gpio_cp_on, 0);
+ }
+
+ if (gpio_cp_rst) {
+ gpio_request(gpio_cp_rst, "LTE_RST");
+ gpio_direction_output(gpio_cp_rst, 0);
+ }
+
+ if (gpio_phone_active) {
+ gpio_request(gpio_phone_active, "LTE_ACTIVE");
+ gpio_direction_input(gpio_phone_active);
+ }
+
+#ifdef CONFIG_LTE_MODEM_CMC221
+ if (gpio_cp_off) {
+ gpio_request(gpio_cp_off, "LTE_OFF");
+ gpio_direction_output(gpio_cp_off, 1);
+ }
+
+ if (gpio_slave_wakeup) {
+ gpio_request(gpio_slave_wakeup, "LTE_SLAVE_WAKEUP");
+ gpio_direction_output(gpio_slave_wakeup, 0);
+ }
+
+ if (gpio_host_wakeup) {
+ gpio_request(gpio_host_wakeup, "LTE_HOST_WAKEUP");
+ gpio_direction_input(gpio_host_wakeup);
+ }
+
+ if (gpio_host_active) {
+ gpio_request(gpio_host_active, "LTE_HOST_ACTIVE");
+ gpio_direction_output(gpio_host_active, 1);
+ }
+#endif
+}
+
+static struct resource lte_modem_res[] = {
+ [0] = {
+ .name = "lte_phone_active",
+ /* phone active irq */
+ .start = OMAP_GPIO_IRQ(OMAP_GPIO_LTE_ACTIVE),
+ .end = OMAP_GPIO_IRQ(OMAP_GPIO_LTE_ACTIVE),
+ .flags = IORESOURCE_IRQ,
+ },
+ [1] = {
+ .name = "lte_host_wakeup",
+ /* host wakeup irq */
+ .start = OMAP_GPIO_IRQ(OMAP_GPIO_CMC2AP_INT2),
+ .end = OMAP_GPIO_IRQ(OMAP_GPIO_CMC2AP_INT2),
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device lte_modem_wake = {
+ .name = "modem_lte_wake",
+ .id = -1,
+};
+
+static struct platform_device lte_modem = {
+ .name = "modem_if",
+ .id = 2,
+ .num_resources = ARRAY_SIZE(lte_modem_res),
+ .resource = lte_modem_res,
+ .dev = {
+ .platform_data = &lte_modem_data,
+ },
+};
+
+/* lte_modem_wake must be registered before the ehci driver */
+void __init modem_toro_init(void)
+{
+ lte_modem_wake.dev.platform_data = &lte_modem_data;
+ platform_device_register(&lte_modem_wake);
+}
+
+static int __init init_modem(void)
+{
+ pr_debug("[MODEM_IF] init_modem\n");
+
+ switch (omap4_tuna_get_type()) {
+ case TUNA_TYPE_MAGURO: /* HSPA */
+ /* umts gpios configuration */
+ umts_modem_cfg_gpio();
+ platform_device_register(&umts_modem);
+ break;
+
+ case TUNA_TYPE_TORO: /* LTE */
+ /* cdma gpios configuration */
+ cdma_modem_cfg_gpio();
+ platform_device_register(&cdma_modem);
+
+ /* lte gpios configuration */
+ lte_modem_cfg_gpio();
+ platform_device_register(&lte_modem);
+ break;
+
+ default:
+ break;
+ }
+ return 0;
+}
+late_initcall(init_modem);
diff --git a/arch/arm/mach-omap2/board-tuna-nfc.c b/arch/arm/mach-omap2/board-tuna-nfc.c
new file mode 100644
index 0000000..2294433
--- /dev/null
+++ b/arch/arm/mach-omap2/board-tuna-nfc.c
@@ -0,0 +1,147 @@
+/* Control power to pn544
+ *
+ * Copyright (C) 2011 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/err.h>
+#include <linux/types.h>
+#include <linux/gpio.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/printk.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/wakelock.h>
+#include <plat/serial.h>
+
+#include "mux.h"
+
+#define GPIO_NFC_EN 173
+#define GPIO_NFC_FW 172
+#define GPIO_NFC_IRQ 17
+
+#define PWR_OFF 0
+#define PWR_ON 1
+#define PWR_ON_FW 2
+
+#define NFC_UART_NUM 4 /* omap_uart_wake() counts from 1 */
+
+static unsigned int nfc_power;
+static struct wake_lock nfc_wake_lock;
+
+static void nfc_power_apply(void) {
+ switch (nfc_power) {
+ case PWR_OFF:
+ pr_info("%s OFF\n", __func__);
+ gpio_set_value(GPIO_NFC_FW, 0);
+ gpio_set_value(GPIO_NFC_EN, 0);
+ msleep(60);
+ break;
+ case PWR_ON:
+ pr_info("%s ON\n", __func__);
+ gpio_set_value(GPIO_NFC_FW, 0);
+ gpio_set_value(GPIO_NFC_EN, 1);
+ msleep(20);
+ break;
+ case PWR_ON_FW:
+ pr_info("%s ON (firmware download)\n", __func__);
+ gpio_set_value(GPIO_NFC_FW, 1);
+ gpio_set_value(GPIO_NFC_EN, 1);
+ msleep(20);
+ gpio_set_value(GPIO_NFC_EN, 0); /* fw mode requires reset */
+ msleep(60);
+ gpio_set_value(GPIO_NFC_EN, 1);
+ msleep(20);
+ break;
+ }
+}
+
+static ssize_t nfc_power_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "%u\n", nfc_power);
+}
+
+static ssize_t nfc_power_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ int rc;
+ unsigned int val;
+
+ rc = kstrtouint(buf, 0, &val);
+ if (rc < 0)
+ return rc;
+ if (val > PWR_ON_FW)
+ return -EINVAL;
+ nfc_power = val;
+ nfc_power_apply();
+ return count;
+}
+
+static DEVICE_ATTR(nfc_power, S_IWUSR | S_IRUGO, nfc_power_show,
+ nfc_power_store);
+
+static irqreturn_t nfc_irq_isr(int irq, void *dev)
+{
+ omap_uart_wake(NFC_UART_NUM);
+
+ /*
+ * take a 500ms wakelock, to give time for higher layers
+ * to either take their own wakelock or finish processing
+ */
+ wake_lock_timeout(&nfc_wake_lock, msecs_to_jiffies(500));
+
+ return IRQ_HANDLED;
+}
+
+void __init omap4_tuna_nfc_init(void)
+{
+ struct platform_device *pdev;
+ int irq;
+
+ gpio_request(GPIO_NFC_FW, "nfc_fw");
+ gpio_direction_output(GPIO_NFC_FW, 0);
+ omap_mux_init_gpio(GPIO_NFC_FW, OMAP_PIN_OUTPUT);
+
+ gpio_request(GPIO_NFC_EN, "nfc_en");
+ gpio_direction_output(GPIO_NFC_EN, 0);
+ omap_mux_init_gpio(GPIO_NFC_EN, OMAP_PIN_OUTPUT);
+
+ gpio_request(GPIO_NFC_IRQ, "nfc_irq");
+ gpio_direction_input(GPIO_NFC_IRQ);
+ omap_mux_init_gpio(GPIO_NFC_IRQ, OMAP_PIN_INPUT_PULLUP);
+
+ wake_lock_init(&nfc_wake_lock, WAKE_LOCK_SUSPEND, "nfc");
+
+ irq = gpio_to_irq(GPIO_NFC_IRQ);
+ if (request_irq(irq, nfc_irq_isr, IRQF_TRIGGER_RISING, "nfc_irq",
+ NULL)) {
+ pr_err("%s: request_irq() failed\n", __func__);
+ return;
+ }
+
+ if (enable_irq_wake(irq)) {
+ pr_err("%s: irq_set_irq_wake() failed\n", __func__);
+ return;
+ }
+
+ nfc_power = PWR_OFF;
+
+ pdev = platform_device_register_simple("nfc-power", -1, NULL, 0);
+ if (IS_ERR(pdev)) {
+ pr_err("%s: platform_device_register_simple() failed\n", __func__);
+ return;
+ }
+ if (device_create_file(&pdev->dev, &dev_attr_nfc_power))
+ pr_err("%s: device_create_file() failed\n", __func__);
+}
diff --git a/arch/arm/mach-omap2/board-tuna-pogo.c b/arch/arm/mach-omap2/board-tuna-pogo.c
new file mode 100644
index 0000000..b235a33
--- /dev/null
+++ b/arch/arm/mach-omap2/board-tuna-pogo.c
@@ -0,0 +1,282 @@
+/*
+ * Copyright (C) 2011 Samsung, Inc.
+ *
+ * Author: Adam Hampson <ahampson@sta.samsung.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+
+#define pr_fmt(fmt) "%s: " fmt, __func__
+
+#include <linux/kernel.h>
+#include <linux/err.h>
+#include <linux/gpio.h>
+#include <linux/delay.h>
+#include <linux/switch.h>
+#include <linux/wakelock.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/sched.h>
+#include <linux/completion.h>
+
+#include <asm/div64.h>
+
+#include "mux.h"
+#include "control.h"
+#include "board-tuna.h"
+
+#define GPIO_POGO_DATA 121
+#define GPIO_POGO_DET 169
+
+/* The below constants are in milliseconds */
+#define POGO_WAKE_PERIOD 100
+#define POGO_ID_PERIOD_TIMEOUT 750
+#define POGO_ID_CARDOCK 100
+#define POGO_ID_DESKDOCK 200
+#define POGO_ENTER_SPDIF_PERIOD 100
+#define POGO_ENTER_SPDIF_WAIT_PERIOD 100
+#define POGO_ID_PERIOD_TOLERANCE 20
+
+#define POGO_DOCK_ID_MAX_RETRY 10
+
+#define POGO_AUDIO_DISCONNECTED 0
+#define POGO_AUDIO_CONNECTED 2
+
+#define POGO_DOCK_UNDOCKED 0
+#define POGO_DOCK_DESK 1
+#define POGO_DOCK_CAR 2
+
+
+struct tuna_pogo {
+ struct switch_dev dock_switch;
+ struct switch_dev audio_switch;
+ struct wake_lock wake_lock;
+ struct completion completion;
+ struct timespec rise_time;
+ struct timespec fall_time;
+ int det_irq;
+ int data_irq;
+ int dock_type;
+ bool fall_detected;
+};
+static struct tuna_pogo tuna_pogo;
+
+static void pogo_send_pulse(unsigned int duration_in_ms)
+{
+ gpio_direction_output(GPIO_POGO_DATA, 1);
+ msleep(duration_in_ms);
+ gpio_direction_output(GPIO_POGO_DATA, 0);
+}
+
+static int pogo_read_id_period(struct tuna_pogo *pogo,
+ unsigned int timeout_in_ms)
+{
+ struct timespec temp;
+ int ret;
+
+ pogo->rise_time.tv_sec = 0;
+ pogo->rise_time.tv_nsec = 0;
+ pogo->fall_time.tv_sec = 0;
+ pogo->fall_time.tv_nsec = 0;
+ pogo->fall_detected = false;
+
+ gpio_direction_input(GPIO_POGO_DATA);
+
+ enable_irq(pogo->data_irq);
+
+ ret = wait_for_completion_timeout(&pogo->completion,
+ msecs_to_jiffies(timeout_in_ms));
+ if (ret <= 0) {
+ if (!pogo->fall_detected)
+ pr_debug("No response to wake within timeout\n");
+ else
+ pr_debug("ID period did not conclude within timeout\n");
+ disable_irq(pogo->data_irq);
+ return -1;
+ }
+
+ temp = timespec_sub(pogo->fall_time, pogo->rise_time);
+ return temp.tv_nsec / NSEC_PER_MSEC;
+}
+
+static irqreturn_t pogo_det_irq_thread(int irq, void *data)
+{
+ struct tuna_pogo *pogo = data;
+ int id_period;
+ unsigned int retry = 0;
+
+ if (gpio_get_value(GPIO_POGO_DET)) {
+ wake_lock(&pogo->wake_lock);
+
+ while (gpio_get_value(GPIO_POGO_DET) &&
+ retry++ <= POGO_DOCK_ID_MAX_RETRY) {
+
+ /* Start the detection process by sending a wake pulse
+ * to the dock.
+ */
+ pogo_send_pulse(POGO_WAKE_PERIOD);
+
+ id_period = pogo_read_id_period(pogo,
+ POGO_ID_PERIOD_TIMEOUT);
+ if (id_period == -1)
+ continue;
+
+ /* The length of the ID period will indicate the type of
+ * dock that is attached.
+ */
+ if (abs(id_period - POGO_ID_CARDOCK) <=
+ POGO_ID_PERIOD_TOLERANCE) {
+ pr_info("POGO Car Dock Detected, ID period"
+ " %dms\n",
+ id_period);
+ pogo->dock_type = POGO_DOCK_CAR;
+ switch_set_state(&pogo->dock_switch,
+ POGO_DOCK_CAR);
+ switch_set_state(&pogo->audio_switch,
+ POGO_AUDIO_CONNECTED);
+ break;
+ } else if (abs(id_period - POGO_ID_DESKDOCK) <=
+ POGO_ID_PERIOD_TOLERANCE) {
+ pr_info("POGO Desk Dock Detected, ID period"
+ " %dms\n",
+ id_period);
+ pogo->dock_type = POGO_DOCK_DESK;
+ switch_set_state(&pogo->dock_switch,
+ POGO_DOCK_DESK);
+ switch_set_state(&pogo->audio_switch,
+ POGO_AUDIO_CONNECTED);
+ break;
+ } else {
+ pr_err("Unknown POGO dock detected, ID period"
+ " %ums\n",
+ id_period);
+ }
+ }
+
+ if (pogo->dock_type == POGO_DOCK_UNDOCKED) {
+ wake_unlock(&pogo->wake_lock);
+ pr_err("Unable to identify pogo dock, giving up\n");
+ return IRQ_HANDLED;
+ }
+
+ /* Instruct the dock to enter SPDIF mode */
+ pogo_send_pulse(POGO_ENTER_SPDIF_PERIOD);
+
+ msleep(POGO_ENTER_SPDIF_WAIT_PERIOD);
+
+ omap_mux_set_gpio(OMAP_MUX_MODE2 | OMAP_PIN_OUTPUT,
+ GPIO_POGO_DATA);
+
+ wake_unlock(&pogo->wake_lock);
+ } else {
+ if (pogo->dock_type != POGO_DOCK_UNDOCKED) {
+ pogo->dock_type = POGO_DOCK_UNDOCKED;
+ pr_info("POGO Dock Detached\n");
+ switch_set_state(&pogo->dock_switch,
+ POGO_DOCK_UNDOCKED);
+ switch_set_state(&pogo->audio_switch,
+ POGO_AUDIO_DISCONNECTED);
+ }
+
+ omap_mux_set_gpio(OMAP_MUX_MODE3 | OMAP_PIN_INPUT_PULLDOWN,
+ GPIO_POGO_DATA);
+ }
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t pogo_data_irq(int irq, void *data)
+{
+ struct tuna_pogo *pogo = data;
+
+ if (gpio_get_value(GPIO_POGO_DATA)) {
+ ktime_get_ts(&pogo->rise_time);
+ irq_set_irq_type(pogo->data_irq,
+ IRQF_TRIGGER_LOW | IRQF_ONESHOT);
+ } else {
+ ktime_get_ts(&pogo->fall_time);
+ pogo->fall_detected = true;
+ irq_set_irq_type(pogo->data_irq,
+ IRQF_TRIGGER_HIGH | IRQF_ONESHOT);
+ complete(&pogo->completion);
+ disable_irq_nosync(pogo->data_irq);
+ }
+ return IRQ_HANDLED;
+}
+
+void __init omap4_tuna_pogo_init(void)
+{
+ struct tuna_pogo *pogo = &tuna_pogo;
+ unsigned int r;
+ int ret;
+
+ omap_mux_init_signal("usbb2_hsic_data.gpio_169",
+ OMAP_PIN_INPUT_PULLDOWN | OMAP_MUX_MODE3);
+
+ /* The pullup/pulldown controls in the mux register are not the controls
+ * that you are looking for. The usbb2_hsic_data signal has a separate
+ * special control in the CONTROL_USBB_HSIC register.
+ */
+ r = omap4_ctrl_pad_readl(OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_USBB_HSIC);
+ r &= ~OMAP4_USBB2_HSIC_DATA_WD_MASK;
+ omap4_ctrl_pad_writel(r, OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_USBB_HSIC);
+
+ ret = gpio_request(GPIO_POGO_DET, "pogo_det");
+ if (ret < 0)
+ pr_err("request for pogo_det gpio failed, err %d\n", ret);
+
+ gpio_direction_input(GPIO_POGO_DET);
+
+ omap_mux_init_signal("abe_dmic_din2.gpio_121",
+ OMAP_PIN_INPUT_PULLDOWN | OMAP_MUX_MODE3);
+ ret = gpio_request(GPIO_POGO_DATA, "pogo_data");
+ if (ret < 0)
+ pr_err("request for pogo_data gpio failed, err %d\n", ret);
+
+ gpio_direction_output(GPIO_POGO_DATA, 0);
+
+ pogo->dock_switch.name = "dock";
+
+ /* The POGO dock does not involve USB but we are reusing the existing
+ * usb audio switch report the availabilty of SPDIF audio through the
+ * POGO dock.
+ */
+ pogo->audio_switch.name = "usb_audio";
+
+ switch_dev_register(&pogo->dock_switch);
+
+ switch_dev_register(&pogo->audio_switch);
+
+ wake_lock_init(&pogo->wake_lock, WAKE_LOCK_IDLE, "pogo");
+
+ init_completion(&pogo->completion);
+
+ pogo->det_irq = gpio_to_irq(GPIO_POGO_DET);
+
+ ret = request_threaded_irq(pogo->det_irq, NULL,
+ pogo_det_irq_thread,
+ IRQF_TRIGGER_RISING |
+ IRQF_TRIGGER_FALLING |
+ IRQF_ONESHOT,
+ "pogo_det", pogo);
+ if (ret < 0)
+ pr_err("Unable to register pogo_det interrupt (%d)\n", ret);
+
+ pogo->data_irq = gpio_to_irq(GPIO_POGO_DATA);
+
+ ret = request_irq(pogo->data_irq, pogo_data_irq,
+ IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
+ "pogo_data", pogo);
+ if (ret < 0)
+ pr_err("Unable to register pogo_data interrupt (%d)\n", ret);
+
+ disable_irq(pogo->data_irq);
+}
diff --git a/arch/arm/mach-omap2/board-tuna-power.c b/arch/arm/mach-omap2/board-tuna-power.c
new file mode 100644
index 0000000..924cc17
--- /dev/null
+++ b/arch/arm/mach-omap2/board-tuna-power.c
@@ -0,0 +1,509 @@
+/* Power support for Samsung Tuna Board.
+ *
+ * Copyright (C) 2011 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ */
+
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/gpio.h>
+#include <linux/max17040_battery.h>
+#include <linux/moduleparam.h>
+#include <linux/pda_power.h>
+#include <linux/platform_device.h>
+#include <linux/i2c/twl6030-madc.h>
+#include <linux/delay.h>
+
+#include <plat/cpu.h>
+
+#include "board-tuna.h"
+#include "mux.h"
+#include "pm.h"
+
+/* These will be different on pre-lunchbox, lunchbox, and final */
+#define GPIO_CHARGING_N 83
+#define GPIO_TA_NCONNECTED 142
+#define GPIO_CHARGE_N 13
+#define GPIO_CHG_CUR_ADJ 102
+#define GPIO_FUEL_ALERT 44
+
+#define TPS62361_GPIO 7
+#define ADC_NUM_SAMPLES 5
+#define ADC_LIMIT_ERR_COUNT 5
+#define ISET_ADC_CHANNEL 3
+#define TEMP_ADC_CHANNEL 1
+
+#define CHARGE_FULL_ADC 203
+
+#define HIGH_BLOCK_TEMP_MAGURO 500
+#define HIGH_RECOVER_TEMP_MAGURO 420
+#define LOW_BLOCK_TEMP_MAGURO (-50)
+#define LOW_RECOVER_TEMP_MAGURO 0
+
+#define HIGH_BLOCK_TEMP_TORO 470
+#define HIGH_RECOVER_TEMP_TORO 400
+#define LOW_BLOCK_TEMP_TORO (-30)
+#define LOW_RECOVER_TEMP_TORO 0
+
+/**
+** temp_adc_table_data
+** @adc_value : thermistor adc value
+** @temperature : temperature(C) * 10
+**/
+struct temp_adc_table_data {
+ int adc_value;
+ int temperature;
+};
+
+static DEFINE_SPINLOCK(charge_en_lock);
+static int charger_state;
+
+static struct temp_adc_table_data temper_table_maguro[] = {
+ /* ADC, Temperature (C/10) */
+ { 75, 700 },
+ { 78, 690 },
+ { 82, 680 },
+ { 84, 670 },
+ { 87, 660 },
+ { 89, 650 },
+ { 92, 640 },
+ { 95, 630 },
+ { 99, 620 },
+ { 102, 610 },
+ { 105, 600 },
+ { 109, 590 },
+ { 113, 580 },
+ { 117, 570 },
+ { 121, 560 },
+ { 124, 550 },
+ { 127, 540 },
+ { 135, 530 },
+ { 139, 520 },
+ { 143, 510 },
+ { 147, 500 },
+ { 153, 490 },
+ { 158, 480 },
+ { 163, 470 },
+ { 169, 460 },
+ { 175, 450 },
+ { 181, 440 },
+ { 187, 430 },
+ { 193, 420 },
+ { 199, 410 },
+ { 205, 400 },
+ { 212, 390 },
+ { 218, 380 },
+ { 227, 370 },
+ { 233, 360 },
+ { 240, 350 },
+ { 249, 340 },
+ { 258, 330 },
+ { 267, 320 },
+ { 276, 310 },
+ { 285, 300 },
+ { 299, 290 },
+ { 308, 280 },
+ { 313, 270 },
+ { 322, 260 },
+ { 331, 250 },
+ { 342, 240 },
+ { 355, 230 },
+ { 363, 220 },
+ { 373, 210 },
+ { 383, 200 },
+ { 394, 190 },
+ { 407, 180 },
+ { 417, 170 },
+ { 427, 160 },
+ { 437, 150 },
+ { 450, 140 },
+ { 465, 130 },
+ { 475, 120 },
+ { 487, 110 },
+ { 500, 100 },
+ { 514, 90 },
+ { 526, 80 },
+ { 540, 70 },
+ { 552, 60 },
+ { 565, 50 },
+ { 577, 40 },
+ { 589, 30 },
+ { 603, 20 },
+ { 614, 10 },
+ { 628, 0 },
+ { 639, (-10) },
+ { 664, (-20) },
+ { 689, (-30) },
+ { 717, (-40) },
+ { 744, (-50) },
+ { 754, (-60) },
+ { 765, (-70) },
+ { 776, (-80) },
+ { 787, (-90) },
+ { 798, (-100) },
+};
+
+static struct temp_adc_table_data temper_table_toro[] = {
+ /* ADC, Temperature (C/10) */
+ { 63, 700 },
+ { 66, 690 },
+ { 67, 680 },
+ { 71, 670 },
+ { 73, 660 },
+ { 75, 650 },
+ { 79, 640 },
+ { 81, 630 },
+ { 83, 620 },
+ { 86, 610 },
+ { 89, 600 },
+ { 92, 590 },
+ { 95, 580 },
+ { 98, 570 },
+ { 102, 560 },
+ { 106, 550 },
+ { 110, 540 },
+ { 114, 530 },
+ { 118, 520 },
+ { 122, 510 },
+ { 126, 500 },
+ { 130, 490 },
+ { 134, 480 },
+ { 139, 470 },
+ { 144, 460 },
+ { 150, 450 },
+ { 155, 440 },
+ { 160, 430 },
+ { 165, 420 },
+ { 171, 410 },
+ { 176, 400 },
+ { 185, 390 },
+ { 191, 380 },
+ { 198, 370 },
+ { 205, 360 },
+ { 211, 350 },
+ { 218, 340 },
+ { 225, 330 },
+ { 232, 320 },
+ { 240, 310 },
+ { 248, 300 },
+ { 256, 290 },
+ { 265, 280 },
+ { 274, 270 },
+ { 283, 260 },
+ { 292, 250 },
+ { 302, 240 },
+ { 313, 230 },
+ { 323, 220 },
+ { 334, 210 },
+ { 344, 200 },
+ { 354, 190 },
+ { 365, 180 },
+ { 375, 170 },
+ { 386, 160 },
+ { 396, 150 },
+ { 410, 140 },
+ { 423, 130 },
+ { 436, 120 },
+ { 449, 110 },
+ { 462, 100 },
+ { 473, 90 },
+ { 484, 80 },
+ { 495, 70 },
+ { 506, 60 },
+ { 517, 50 },
+ { 530, 40 },
+ { 543, 30 },
+ { 557, 20 },
+ { 570, 10 },
+ { 582, 0 },
+ { 596, (-10) },
+ { 610, (-20) },
+ { 623, (-30) },
+ { 636, (-40) },
+ { 650, (-50) },
+ { 663, (-60) },
+ { 676, (-70) },
+ { 686, (-80) },
+ { 696, (-90) },
+ { 716, (-100) },
+};
+
+static struct temp_adc_table_data *temper_table = temper_table_maguro;
+static int temper_table_size = ARRAY_SIZE(temper_table_maguro);
+
+static bool enable_sr = true;
+module_param(enable_sr, bool, S_IRUSR | S_IRGRP | S_IROTH);
+
+static struct gpio charger_gpios[] = {
+ { .gpio = GPIO_CHARGING_N, .flags = GPIOF_IN, .label = "charging_n" },
+ { .gpio = GPIO_TA_NCONNECTED, .flags = GPIOF_IN, .label = "charger_n" },
+ { .gpio = GPIO_CHARGE_N, .flags = GPIOF_OUT_INIT_HIGH, .label = "charge_n" },
+ { .gpio = GPIO_CHG_CUR_ADJ, .flags = GPIOF_OUT_INIT_LOW, .label = "charge_cur_adj" },
+};
+
+static int twl6030_get_adc_data(int ch)
+{
+ int adc_data;
+ int adc_max = -1;
+ int adc_min = 1 << 11;
+ int adc_total = 0;
+ int i, j;
+
+ for (i = 0; i < ADC_NUM_SAMPLES; i++) {
+ adc_data = twl6030_get_madc_conversion(ch);
+ if (adc_data == -EAGAIN) {
+ for (j = 0; j < ADC_LIMIT_ERR_COUNT; j++) {
+ msleep(20);
+ adc_data = twl6030_get_madc_conversion(ch);
+ if (adc_data > 0)
+ break;
+ }
+ if (j >= ADC_LIMIT_ERR_COUNT) {
+ pr_err("%s: Retry count exceeded[ch:%d]\n",
+ __func__, ch);
+ return adc_data;
+ }
+ } else if (adc_data < 0) {
+ pr_err("%s: Failed read adc value : %d [ch:%d]\n",
+ __func__, adc_data, ch);
+ return adc_data;
+ }
+
+ if (adc_data > adc_max)
+ adc_max = adc_data;
+ if (adc_data < adc_min)
+ adc_min = adc_data;
+
+ adc_total += adc_data;
+ }
+ return (adc_total - adc_max - adc_min) / (ADC_NUM_SAMPLES - 2);
+}
+
+static int iset_adc_value(void)
+{
+ return twl6030_get_adc_data(ISET_ADC_CHANNEL);
+}
+
+static int temp_adc_value(void)
+{
+ return twl6030_get_adc_data(TEMP_ADC_CHANNEL);
+}
+
+static bool check_charge_full(void)
+{
+ int ret;
+
+ ret = iset_adc_value();
+ if (ret < 0) {
+ pr_err("%s: invalid iset adc value [%d]\n",
+ __func__, ret);
+ return false;
+ }
+ pr_debug("%s : iset adc value : %d\n", __func__, ret);
+
+ return ret < CHARGE_FULL_ADC;
+}
+
+static int get_bat_temp_by_adc(int *batt_temp)
+{
+ int array_size = temper_table_size;
+ int temp_adc = temp_adc_value();
+ int mid;
+ int left_side = 0;
+ int right_side = array_size - 1;
+ int temp = 0;
+
+ if (temp_adc < 0) {
+ pr_err("%s : Invalid temperature adc value [%d]\n",
+ __func__, temp_adc);
+ return temp_adc;
+ }
+
+ while (left_side <= right_side) {
+ mid = (left_side + right_side) / 2;
+ if (mid == 0 || mid == array_size - 1 ||
+ (temper_table[mid].adc_value <= temp_adc &&
+ temper_table[mid+1].adc_value > temp_adc)) {
+ temp = temper_table[mid].temperature;
+ break;
+ } else if (temp_adc - temper_table[mid].adc_value > 0) {
+ left_side = mid + 1;
+ } else {
+ right_side = mid - 1;
+ }
+ }
+
+ pr_debug("%s: temp adc : %d, temp : %d\n", __func__, temp_adc, temp);
+ *batt_temp = temp;
+ return 0;
+}
+
+static int charger_init(struct device *dev)
+{
+ return gpio_request_array(charger_gpios, ARRAY_SIZE(charger_gpios));
+}
+
+static void charger_exit(struct device *dev)
+{
+ gpio_free_array(charger_gpios, ARRAY_SIZE(charger_gpios));
+}
+
+static void set_charge_en(int state)
+{
+ gpio_set_value(GPIO_CHARGE_N, !state);
+}
+
+static void charger_set_charge(int state)
+{
+ gpio_set_value(GPIO_CHG_CUR_ADJ, !!(state & PDA_POWER_CHARGE_AC));
+ spin_lock(&charge_en_lock);
+ charger_state = state;
+ set_charge_en(state);
+ spin_unlock(&charge_en_lock);
+}
+
+static void charger_set_only_charge(int state)
+{
+ spin_lock(&charge_en_lock);
+ if (charger_state)
+ set_charge_en(state);
+ spin_unlock(&charge_en_lock);
+ /* CHG_ING_N level changed after set charge_en and 150ms */
+ msleep(150);
+}
+
+static int charger_is_online(void)
+{
+ return !gpio_get_value(GPIO_TA_NCONNECTED);
+}
+
+static int charger_is_charging(void)
+{
+ return !gpio_get_value(GPIO_CHARGING_N);
+}
+
+static char *tuna_charger_supplied_to[] = {
+ "battery",
+};
+
+static const __initdata struct pda_power_pdata charger_pdata = {
+ .init = charger_init,
+ .exit = charger_exit,
+ .set_charge = charger_set_charge,
+ .wait_for_status = 500,
+ .wait_for_charger = 500,
+ .supplied_to = tuna_charger_supplied_to,
+ .num_supplicants = ARRAY_SIZE(tuna_charger_supplied_to),
+ .use_otg_notifier = true,
+};
+
+static struct max17040_platform_data max17043_pdata = {
+ .charger_online = charger_is_online,
+ .charger_enable = charger_is_charging,
+ .allow_charging = charger_set_only_charge,
+ .skip_reset = true,
+ .min_capacity = 3,
+ .is_full_charge = check_charge_full,
+ .get_bat_temp = get_bat_temp_by_adc,
+ .high_block_temp = HIGH_BLOCK_TEMP_MAGURO,
+ .high_recover_temp = HIGH_RECOVER_TEMP_MAGURO,
+ .low_block_temp = LOW_BLOCK_TEMP_MAGURO,
+ .low_recover_temp = LOW_RECOVER_TEMP_MAGURO,
+ .fully_charged_vol = 4150000,
+ .recharge_vol = 4140000,
+ .limit_charging_time = 21600, /* 6 hours */
+ .limit_recharging_time = 5400, /* 90 min */
+};
+
+static const __initdata struct i2c_board_info max17043_i2c[] = {
+ {
+ I2C_BOARD_INFO("max17040", (0x6C >> 1)),
+ .platform_data = &max17043_pdata,
+ .irq = OMAP_GPIO_IRQ(GPIO_FUEL_ALERT),
+ }
+};
+
+void __init omap4_tuna_power_init(void)
+{
+ struct platform_device *pdev;
+ int status;
+
+ /* Vsel0 = gpio, vsel1 = gnd */
+ status = omap_tps6236x_board_setup(true, TPS62361_GPIO, -1,
+ OMAP_PIN_OFF_OUTPUT_HIGH, -1);
+ if (status)
+ pr_err("TPS62361 initialization failed: %d\n", status);
+ /*
+ * Some Tuna devices have a 4430 chip on a 4460 board, manually
+ * tweak the power tree to the 4460 style with the TPS regulator.
+ */
+ if (cpu_is_omap443x()) {
+ /* Disable 4430 mapping */
+ omap_twl_pmic_update("mpu", CHIP_IS_OMAP443X, 0x0);
+ omap_twl_pmic_update("core", CHIP_IS_OMAP443X, 0x0);
+ /* make 4460 map usable for 4430 */
+ omap_twl_pmic_update("core", CHIP_IS_OMAP446X, CHIP_IS_OMAP443X);
+ omap_tps6236x_update("mpu", CHIP_IS_OMAP446X, CHIP_IS_OMAP443X);
+ }
+
+ /* Update temperature data from board type */
+ if (omap4_tuna_get_type() == TUNA_TYPE_TORO) {
+ temper_table = temper_table_toro;
+ temper_table_size = ARRAY_SIZE(temper_table_toro);
+
+ max17043_pdata.high_block_temp = HIGH_BLOCK_TEMP_TORO;
+ max17043_pdata.high_recover_temp = HIGH_RECOVER_TEMP_TORO;
+ max17043_pdata.low_block_temp = LOW_BLOCK_TEMP_TORO;
+ max17043_pdata.low_recover_temp = LOW_RECOVER_TEMP_TORO;
+ }
+
+ /* Update oscillator information */
+ if (omap4_tuna_get_revision() <= 0x3) {
+ /*
+ * until sample 4 (Toro and Maguro), we used KC2520B38:
+ * ST = 10ms
+ * Output Disable time = 100ns
+ * Output enable time = 5ms
+ * tstart = 10ms + 5ms = 15ms.
+ * tshut = 1us (rounded)
+ */
+ omap_pm_set_osc_lp_time(15000, 1);
+ } else {
+ /*
+ * sample 5 onwards (Toro and Maguro), we use SQ200384:
+ * ST = 10ms
+ * Output Disable time = 100ns
+ * Output enable time = 10ms
+ * tstart = 10ms + 10ms = 20ms.
+ * tshut = 1us (rounded)
+ */
+ omap_pm_set_osc_lp_time(20000, 1);
+ }
+
+ omap_mux_init_gpio(charger_gpios[0].gpio, OMAP_PIN_INPUT);
+ omap_mux_init_gpio(charger_gpios[1].gpio, OMAP_PIN_INPUT);
+ omap_mux_init_gpio(charger_gpios[2].gpio, OMAP_PIN_OUTPUT);
+ omap_mux_init_gpio(charger_gpios[3].gpio, OMAP_PIN_OUTPUT);
+ omap_mux_init_gpio(GPIO_FUEL_ALERT, OMAP_PIN_INPUT);
+
+ pdev = platform_device_register_resndata(NULL, "pda-power", -1,
+ NULL, 0, &charger_pdata, sizeof(charger_pdata));
+ if (IS_ERR_OR_NULL(pdev))
+ pr_err("cannot register pda-power\n");
+
+ i2c_register_board_info(4, max17043_i2c, ARRAY_SIZE(max17043_i2c));
+
+ if (enable_sr)
+ omap_enable_smartreflex_on_init();
+}
diff --git a/arch/arm/mach-omap2/board-tuna-sensors.c b/arch/arm/mach-omap2/board-tuna-sensors.c
new file mode 100755
index 0000000..f818aad
--- /dev/null
+++ b/arch/arm/mach-omap2/board-tuna-sensors.c
@@ -0,0 +1,212 @@
+/* Sensor support for Samsung Tuna Board.
+ *
+ * Copyright (C) 2011 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+#include <linux/mpu.h>
+#include <linux/gp2a.h>
+#include <linux/i2c/twl6030-madc.h>
+
+#include "mux.h"
+#include "board-tuna.h"
+
+#define GPIO_GYRO_INT 45
+#define GPIO_ACC_INT 122
+#define GPIO_MAG_INT 176
+#define GPIO_PS_ON 25
+#define GPIO_PS_VOUT 21
+#define GPIO_MSENSE_IRQ 157
+
+#define GP2A_LIGHT_ADC_CHANNEL 4
+
+static int gp2a_light_adc_value(void)
+{
+ return twl6030_get_madc_conversion(GP2A_LIGHT_ADC_CHANNEL);
+}
+
+static void gp2a_power(bool on)
+{
+ /* this controls the power supply rail to the gp2a IC */
+ gpio_set_value(GPIO_PS_ON, on);
+}
+
+static void gp2a_gpio_init(void)
+{
+ int ret = gpio_request(GPIO_PS_ON, "gp2a_power_supply_on");
+ if (ret) {
+ pr_err("%s Failed to request gpio gp2a power supply\n",
+ __func__);
+ return;
+ }
+ /* set power pin to output, initially powered off*/
+ ret = gpio_direction_output(GPIO_PS_ON, 0);
+ if (ret) {
+ pr_err("%s Failed in gpio_direction_output, value 0 with error %d\n",
+ __func__, ret);
+ }
+}
+
+static s8 orientation_back[] = {
+ -1, 0, 0,
+ 0, 1, 0,
+ 0, 0, -1,
+};
+
+static s8 orientation_back_right_90[] = {
+ 0, -1, 0,
+ -1, 0, 0,
+ 0, 0, -1,
+};
+
+static s8 orientation_back_left_90[] = {
+ 0, 1, 0,
+ 1, 0, 0,
+ 0, 0, -1,
+};
+
+static s8 orientation_back_180[] = {
+ 1, 0, 0,
+ 0, -1, 0,
+ 0, 0, -1,
+};
+
+/*
+ * A correction matrix for YAS530
+ * which takes care of soft iron effect in TORO
+ */
+static s32 compass_correction_matrix_toro[] = {
+ 1072, -51, -22,
+ -30, 910, -4,
+ -23, -63, 1024,
+};
+
+static void rotcpy(s8 dst[3 * 3], const s8 src[3 * 3])
+{
+ memcpy(dst, src, 3 * 3);
+}
+
+static struct mpu_platform_data mpu_data = {
+ .int_config = 0x10,
+ .orientation = { 1, 0, 0,
+ 0, 1, 0,
+ 0, 0, 1 },
+ /* accel */
+ .accel = {
+ .irq = OMAP_GPIO_IRQ(GPIO_ACC_INT),
+ .adapt_num = 4,
+ .bus = EXT_SLAVE_BUS_SECONDARY,
+ .address = 0x18,
+ .orientation = { 1, 0, 0,
+ 0, 1, 0,
+ 0, 0, 1 },
+ },
+ /* compass */
+ .compass = {
+ .irq = OMAP_GPIO_IRQ(GPIO_MAG_INT),
+ .adapt_num = 4,
+ .bus = EXT_SLAVE_BUS_PRIMARY,
+ .address = 0x2E,
+ .orientation = { 1, 0, 0,
+ 0, 1, 0,
+ 0, 0, 1 },
+ },
+};
+
+static struct gp2a_platform_data gp2a_pdata = {
+ .power = gp2a_power,
+ .p_out = GPIO_PS_VOUT,
+ .light_adc_value = gp2a_light_adc_value,
+};
+
+static struct i2c_board_info __initdata tuna_sensors_i2c4_boardinfo[] = {
+ {
+ I2C_BOARD_INFO("mpu3050", 0x68),
+ .irq = OMAP_GPIO_IRQ(GPIO_GYRO_INT),
+ .platform_data = &mpu_data,
+ },
+ {
+ I2C_BOARD_INFO("bma250", 0x18),
+ .irq = OMAP_GPIO_IRQ(GPIO_ACC_INT),
+ .platform_data = &mpu_data.accel,
+ },
+ {
+ I2C_BOARD_INFO("yas530", 0x2e),
+ .irq = OMAP_GPIO_IRQ(GPIO_MAG_INT),
+ .platform_data = &mpu_data.compass,
+ },
+ {
+ I2C_BOARD_INFO("gp2a", 0x44),
+ .platform_data = &gp2a_pdata,
+ },
+ {
+ I2C_BOARD_INFO("bmp180", 0x77),
+ },
+};
+
+static void omap4_tuna_fixup_orientations_maguro(int revision)
+{
+ if (revision >= 3) {
+ rotcpy(mpu_data.orientation, orientation_back_right_90);
+ rotcpy(mpu_data.accel.orientation, orientation_back_left_90);
+ } else if (revision >= 2) {
+ rotcpy(mpu_data.orientation, orientation_back_right_90);
+ rotcpy(mpu_data.accel.orientation, orientation_back_180);
+ } else if (revision == 1) {
+ rotcpy(mpu_data.accel.orientation, orientation_back_left_90);
+ }
+}
+
+static void omap4_tuna_fixup_orientations_toro(int revision)
+{
+ if (revision >= 2) {
+ rotcpy(mpu_data.orientation, orientation_back_left_90);
+ rotcpy(mpu_data.accel.orientation, orientation_back);
+ rotcpy(mpu_data.compass.orientation, orientation_back_180);
+ } else if (revision >= 1) {
+ rotcpy(mpu_data.orientation, orientation_back_left_90);
+ rotcpy(mpu_data.accel.orientation, orientation_back_180);
+ rotcpy(mpu_data.compass.orientation, orientation_back_left_90);
+ }
+}
+
+void __init omap4_tuna_sensors_init(void)
+{
+ omap_mux_init_gpio(GPIO_GYRO_INT, OMAP_PIN_INPUT);
+ omap_mux_init_gpio(GPIO_ACC_INT, OMAP_PIN_INPUT);
+ omap_mux_init_gpio(GPIO_MAG_INT, OMAP_PIN_INPUT);
+ omap_mux_init_gpio(GPIO_PS_ON, OMAP_PIN_OUTPUT);
+ omap_mux_init_gpio(GPIO_PS_VOUT, OMAP_WAKEUP_EN | OMAP_PIN_INPUT);
+
+ gpio_request(GPIO_GYRO_INT, "GYRO_INT");
+ gpio_direction_input(GPIO_GYRO_INT);
+ gpio_request(GPIO_ACC_INT, "ACC_INT");
+ gpio_direction_input(GPIO_ACC_INT);
+ gpio_request(GPIO_MAG_INT, "MAG_INT");
+ gpio_direction_input(GPIO_MAG_INT);
+ gpio_request(GPIO_MSENSE_IRQ, "MSENSE_IRQ");
+ gpio_direction_output(GPIO_MSENSE_IRQ, 1);
+ /* optical sensor */
+ gp2a_gpio_init();
+
+ if (omap4_tuna_get_type() == TUNA_TYPE_MAGURO) {
+ omap4_tuna_fixup_orientations_maguro(omap4_tuna_get_revision());
+ } else if (omap4_tuna_get_type() == TUNA_TYPE_TORO) {
+ omap4_tuna_fixup_orientations_toro(omap4_tuna_get_revision());
+ mpu_data.compass.private_data = compass_correction_matrix_toro;
+ }
+
+ i2c_register_board_info(4, tuna_sensors_i2c4_boardinfo,
+ ARRAY_SIZE(tuna_sensors_i2c4_boardinfo));
+}
diff --git a/arch/arm/mach-omap2/board-tuna-usbhost.c b/arch/arm/mach-omap2/board-tuna-usbhost.c
new file mode 100644
index 0000000..39905fd
--- /dev/null
+++ b/arch/arm/mach-omap2/board-tuna-usbhost.c
@@ -0,0 +1,85 @@
+/* USB Host (EHCI) support for Samsung Tuna Board.
+ *
+ * Copyright (C) 2011 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ */
+
+#include <linux/gpio.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+
+#include <plat/usb.h>
+
+#include "board-tuna.h"
+#include "mux.h"
+
+#define GPIO_USB3333_RESETB 159
+
+static struct usbhs_omap_board_data usbhs_bdata = {
+ .port_mode[0] = OMAP_EHCI_PORT_MODE_PHY,
+ .port_mode[1] = OMAP_USBHS_PORT_MODE_UNUSED,
+ .port_mode[2] = OMAP_USBHS_PORT_MODE_UNUSED,
+ .phy_reset = false,
+ .reset_gpio_port[0] = -EINVAL,
+ .reset_gpio_port[1] = -EINVAL,
+ .reset_gpio_port[2] = -EINVAL
+};
+
+void __init omap4_ehci_init(void)
+{
+ int ret = 0;
+ struct clk *phy_ref_clk;
+
+ omap_mux_init_gpio(GPIO_USB3333_RESETB, OMAP_PIN_OUTPUT |
+ OMAP_PIN_OFF_OUTPUT_HIGH);
+
+ ret = gpio_request(GPIO_USB3333_RESETB, "usb3333_resetb");
+ if (ret) {
+ pr_err("omap: ehci: Cannot request GPIO %d",
+ GPIO_USB3333_RESETB);
+ return;
+ }
+ gpio_direction_output(GPIO_USB3333_RESETB, 0);
+ gpio_set_value(GPIO_USB3333_RESETB, 0);
+
+ /* FREF_CLK3 provides the 19.2 MHz reference clock to the PHY */
+ omap_mux_init_signal("fref_clk3_out", OMAP_PIN_OUTPUT | OMAP_MUX_MODE0);
+
+ phy_ref_clk = clk_get(NULL, "auxclk3_ck");
+ if (IS_ERR(phy_ref_clk)) {
+ pr_err("omap: ehci: Cannot request auxclk3");
+ return;
+ }
+ ret = clk_set_rate(phy_ref_clk, 19200000);
+ if (ret < 0) {
+ pr_err("omap: ehci: Cannot clk_set_rate auxclk3 err %d", ret);
+ return;
+ }
+ ret = clk_enable(phy_ref_clk);
+ if (ret < 0) {
+ pr_err("omap: ehci: Cannot clk_enable auxclk3 err %d", ret);
+ return;
+ }
+
+ udelay(100);
+ gpio_set_value(GPIO_USB3333_RESETB, 1);
+
+ /* Everything went well with phy clock, pass it to ehci driver for
+ * low power managment now
+ */
+ usbhs_bdata.transceiver_clk[0] = phy_ref_clk;
+
+ usbhs_init(&usbhs_bdata);
+
+ pr_info("usb:ehci initialized");
+ return;
+}
diff --git a/arch/arm/mach-omap2/board-tuna-vibrator.c b/arch/arm/mach-omap2/board-tuna-vibrator.c
new file mode 100755
index 0000000..de1d5e7
--- /dev/null
+++ b/arch/arm/mach-omap2/board-tuna-vibrator.c
@@ -0,0 +1,185 @@
+/* arch/arm/mach-omap2/board-tuna-vibrator.c
+ *
+ * Copyright (C) 2011 Samsung Electronics Co. Ltd. All Rights Reserved.
+ * Author: Rom Lemarchand <rlemarchand@sta.samsung.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+
+#include <linux/hrtimer.h>
+#include <linux/gpio.h>
+#include <linux/wakelock.h>
+#include <linux/mutex.h>
+#include <asm/mach-types.h>
+#include <plat/dmtimer.h>
+
+#include <../../../drivers/staging/android/timed_output.h>
+
+#include "mux.h"
+#include "board-tuna.h"
+
+/* Vibrator enable pin is changed on Rev 05 to block not intended vibration. */
+#define GPIO_MOTOR_EN 162
+#define GPIO_MOTOR_EN_REV05 54
+
+#define VIB_GPTIMER_NUM 10
+#define PWM_DUTY_MAX 1450
+#define MAX_TIMEOUT 10000 /* 10s */
+
+static struct vibrator {
+ struct wake_lock wklock;
+ struct hrtimer timer;
+ struct mutex lock;
+ struct omap_dm_timer *gptimer;
+ bool enabled;
+ unsigned gpio_en;
+} vibdata;
+
+static void vibrator_off(void)
+{
+ if (!vibdata.enabled)
+ return;
+ omap_dm_timer_stop(vibdata.gptimer);
+ gpio_set_value(vibdata.gpio_en, 0);
+ vibdata.enabled = false;
+ wake_unlock(&vibdata.wklock);
+}
+
+static int vibrator_get_time(struct timed_output_dev *dev)
+{
+ if (hrtimer_active(&vibdata.timer)) {
+ ktime_t r = hrtimer_get_remaining(&vibdata.timer);
+ return ktime_to_ms(r);
+ }
+
+ return 0;
+}
+
+static void vibrator_enable(struct timed_output_dev *dev, int value)
+{
+ mutex_lock(&vibdata.lock);
+
+ /* cancel previous timer and set GPIO according to value */
+ hrtimer_cancel(&vibdata.timer);
+
+ if (value) {
+ wake_lock(&vibdata.wklock);
+
+ gpio_set_value(vibdata.gpio_en, 1);
+ omap_dm_timer_start(vibdata.gptimer);
+
+ vibdata.enabled = true;
+
+ if (value > 0) {
+ if (value > MAX_TIMEOUT)
+ value = MAX_TIMEOUT;
+
+ hrtimer_start(&vibdata.timer,
+ ns_to_ktime((u64)value * NSEC_PER_MSEC),
+ HRTIMER_MODE_REL);
+ }
+ } else {
+ vibrator_off();
+ }
+
+ mutex_unlock(&vibdata.lock);
+}
+
+static struct timed_output_dev to_dev = {
+ .name = "vibrator",
+ .get_time = vibrator_get_time,
+ .enable = vibrator_enable,
+};
+
+static enum hrtimer_restart vibrator_timer_func(struct hrtimer *timer)
+{
+ vibrator_off();
+ return HRTIMER_NORESTART;
+}
+
+static int __init vibrator_init(void)
+{
+ int ret;
+
+ vibdata.enabled = false;
+
+ hrtimer_init(&vibdata.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+ vibdata.timer.function = vibrator_timer_func;
+
+ vibdata.gptimer = omap_dm_timer_request_specific(VIB_GPTIMER_NUM);
+ if (vibdata.gptimer == NULL)
+ return -1;
+
+ ret = omap_dm_timer_set_source(vibdata.gptimer,
+ OMAP_TIMER_SRC_SYS_CLK);
+ if (ret < 0)
+ goto err_dm_timer_src;
+
+ omap_dm_timer_set_load(vibdata.gptimer, 1, -PWM_DUTY_MAX);
+ omap_dm_timer_set_match(vibdata.gptimer, 1, -PWM_DUTY_MAX+10);
+ omap_dm_timer_set_pwm(vibdata.gptimer, 0, 1,
+ OMAP_TIMER_TRIGGER_OVERFLOW_AND_COMPARE);
+ omap_dm_timer_enable(vibdata.gptimer);
+ omap_dm_timer_write_counter(vibdata.gptimer, -2);
+ omap_dm_timer_disable(vibdata.gptimer);
+
+ wake_lock_init(&vibdata.wklock, WAKE_LOCK_SUSPEND, "vibrator");
+ mutex_init(&vibdata.lock);
+
+ ret = timed_output_dev_register(&to_dev);
+ if (ret < 0)
+ goto err_to_dev_reg;
+
+ return 0;
+
+err_to_dev_reg:
+ mutex_destroy(&vibdata.lock);
+ wake_lock_destroy(&vibdata.wklock);
+
+err_dm_timer_src:
+ omap_dm_timer_free(vibdata.gptimer);
+ vibdata.gptimer = NULL;
+
+ return -1;
+}
+
+static int __init omap4_tuna_vibrator_init(void)
+{
+ int ret;
+
+ if (!machine_is_tuna())
+ return 0;
+
+ vibdata.gpio_en = (omap4_tuna_get_revision() >= 5) ?
+ GPIO_MOTOR_EN_REV05 : GPIO_MOTOR_EN;
+
+ omap_mux_init_gpio(vibdata.gpio_en, OMAP_PIN_OUTPUT |
+ OMAP_PIN_OFF_OUTPUT_LOW);
+ omap_mux_init_signal("dpm_emu18.dmtimer10_pwm_evt", OMAP_PIN_OUTPUT);
+
+ ret = gpio_request(vibdata.gpio_en, "vibrator-en");
+ if (ret)
+ return ret;
+
+ gpio_direction_output(vibdata.gpio_en, 0);
+
+ ret = vibrator_init();
+ if (ret < 0)
+ gpio_free(vibdata.gpio_en);
+
+ return ret;
+}
+
+/*
+ * This is needed because the vibrator is dependent on omap_dm_timers which get
+ * initialized at device_init time
+ */
+late_initcall(omap4_tuna_vibrator_init);
diff --git a/arch/arm/mach-omap2/board-tuna-wifi.c b/arch/arm/mach-omap2/board-tuna-wifi.c
new file mode 100644
index 0000000..2c8909d
--- /dev/null
+++ b/arch/arm/mach-omap2/board-tuna-wifi.c
@@ -0,0 +1,419 @@
+/*
+ * Copyright (C) 2011 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <asm/mach-types.h>
+#include <asm/gpio.h>
+#include <asm/io.h>
+#include <asm/setup.h>
+#include <linux/if.h>
+#include <linux/skbuff.h>
+#include <linux/wlan_plat.h>
+#include <linux/pm_runtime.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/fixed.h>
+#include <plat/mmc.h>
+
+#include <linux/random.h>
+#include <linux/jiffies.h>
+
+#include "hsmmc.h"
+#include "control.h"
+#include "mux.h"
+#include "board-tuna.h"
+
+#define GPIO_WLAN_PMENA 104
+#define GPIO_WLAN_IRQ 2
+
+#define ATAG_TUNA_MAC 0x57464d41
+/* #define ATAG_TUNA_MAC_DEBUG */
+
+#define PREALLOC_WLAN_NUMBER_OF_SECTIONS 4
+#define PREALLOC_WLAN_NUMBER_OF_BUFFERS 160
+#define PREALLOC_WLAN_SECTION_HEADER 24
+
+#define WLAN_SECTION_SIZE_0 (PREALLOC_WLAN_NUMBER_OF_BUFFERS * 128)
+#define WLAN_SECTION_SIZE_1 (PREALLOC_WLAN_NUMBER_OF_BUFFERS * 128)
+#define WLAN_SECTION_SIZE_2 (PREALLOC_WLAN_NUMBER_OF_BUFFERS * 512)
+#define WLAN_SECTION_SIZE_3 (PREALLOC_WLAN_NUMBER_OF_BUFFERS * 1024)
+
+#define WLAN_SKB_BUF_NUM 16
+
+static struct sk_buff *wlan_static_skb[WLAN_SKB_BUF_NUM];
+
+typedef struct wifi_mem_prealloc_struct {
+ void *mem_ptr;
+ unsigned long size;
+} wifi_mem_prealloc_t;
+
+static wifi_mem_prealloc_t wifi_mem_array[PREALLOC_WLAN_NUMBER_OF_SECTIONS] = {
+ { NULL, (WLAN_SECTION_SIZE_0 + PREALLOC_WLAN_SECTION_HEADER) },
+ { NULL, (WLAN_SECTION_SIZE_1 + PREALLOC_WLAN_SECTION_HEADER) },
+ { NULL, (WLAN_SECTION_SIZE_2 + PREALLOC_WLAN_SECTION_HEADER) },
+ { NULL, (WLAN_SECTION_SIZE_3 + PREALLOC_WLAN_SECTION_HEADER) }
+};
+
+static void *tuna_wifi_mem_prealloc(int section, unsigned long size)
+{
+ if (section == PREALLOC_WLAN_NUMBER_OF_SECTIONS)
+ return wlan_static_skb;
+ if ((section < 0) || (section > PREALLOC_WLAN_NUMBER_OF_SECTIONS))
+ return NULL;
+ if (wifi_mem_array[section].size < size)
+ return NULL;
+ return wifi_mem_array[section].mem_ptr;
+}
+
+int __init tuna_init_wifi_mem(void)
+{
+ int i;
+
+ for(i=0;( i < WLAN_SKB_BUF_NUM );i++) {
+ if (i < (WLAN_SKB_BUF_NUM/2))
+ wlan_static_skb[i] = dev_alloc_skb(4096);
+ else
+ wlan_static_skb[i] = dev_alloc_skb(8192);
+ }
+ for(i=0;( i < PREALLOC_WLAN_NUMBER_OF_SECTIONS );i++) {
+ wifi_mem_array[i].mem_ptr = kmalloc(wifi_mem_array[i].size,
+ GFP_KERNEL);
+ if (wifi_mem_array[i].mem_ptr == NULL)
+ return -ENOMEM;
+ }
+ return 0;
+}
+
+static struct resource tuna_wifi_resources[] = {
+ [0] = {
+ .name = "bcmdhd_wlan_irq",
+ .start = OMAP_GPIO_IRQ(GPIO_WLAN_IRQ),
+ .end = OMAP_GPIO_IRQ(GPIO_WLAN_IRQ),
+ .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL | IORESOURCE_IRQ_SHAREABLE,
+ },
+};
+
+#if 0
+/* BCM4329 returns wrong sdio_vsn(1) when we read cccr,
+ * we use predefined value (sdio_vsn=2) here to initial sdio driver well
+ */
+static struct embedded_sdio_data tuna_wifi_emb_data = {
+ .cccr = {
+ .sdio_vsn = 2,
+ .multi_block = 1,
+ .low_speed = 0,
+ .wide_bus = 0,
+ .high_power = 1,
+ .high_speed = 1,
+ },
+};
+#endif
+
+static int tuna_wifi_cd = 0; /* WIFI virtual 'card detect' status */
+static void (*wifi_status_cb)(int card_present, void *dev_id);
+static void *wifi_status_cb_devid;
+static struct regulator *clk32kaudio_reg;
+
+static int tuna_wifi_status_register(
+ void (*callback)(int card_present, void *dev_id),
+ void *dev_id)
+{
+ if (wifi_status_cb)
+ return -EAGAIN;
+ wifi_status_cb = callback;
+ wifi_status_cb_devid = dev_id;
+ return 0;
+}
+
+static unsigned int tuna_wifi_status(struct device *dev)
+{
+ return tuna_wifi_cd;
+}
+
+struct mmc_platform_data tuna_wifi_data = {
+ .ocr_mask = MMC_VDD_165_195 | MMC_VDD_20_21,
+ .built_in = 1,
+ .status = tuna_wifi_status,
+ .card_present = 0,
+ .register_status_notify = tuna_wifi_status_register,
+};
+
+static int tuna_wifi_set_carddetect(int val)
+{
+ pr_debug("%s: %d\n", __func__, val);
+ tuna_wifi_cd = val;
+ if (wifi_status_cb) {
+ wifi_status_cb(val, wifi_status_cb_devid);
+ } else
+ pr_warning("%s: Nobody to notify\n", __func__);
+ return 0;
+}
+
+static int tuna_wifi_power_state;
+
+struct fixed_voltage_data {
+ struct regulator_desc desc;
+ struct regulator_dev *dev;
+ int microvolts;
+ int gpio;
+ unsigned startup_delay;
+ bool enable_high;
+ bool is_enabled;
+};
+
+static struct regulator_consumer_supply tuna_vmmc5_supply = {
+ .supply = "vmmc",
+ .dev_name = "omap_hsmmc.4",
+};
+
+static struct regulator_init_data tuna_vmmc5 = {
+ .constraints = {
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ },
+ .num_consumer_supplies = 1,
+ .consumer_supplies = &tuna_vmmc5_supply,
+};
+
+static struct fixed_voltage_config tuna_vwlan = {
+ .supply_name = "vwl1271",
+ .microvolts = 2000000, /* 2.0V */
+ .gpio = GPIO_WLAN_PMENA,
+ .startup_delay = 70000, /* 70msec */
+ .enable_high = 1,
+ .enabled_at_boot = 0,
+ .init_data = &tuna_vmmc5,
+};
+
+static struct platform_device omap_vwlan_device = {
+ .name = "reg-fixed-voltage",
+ .id = 1,
+ .dev = {
+ .platform_data = &tuna_vwlan,
+ },
+};
+
+static int tuna_wifi_power(int on)
+{
+ if (!clk32kaudio_reg) {
+ clk32kaudio_reg = regulator_get(0, "clk32kaudio");
+ if (IS_ERR(clk32kaudio_reg)) {
+ pr_err("%s: clk32kaudio reg not found!\n", __func__);
+ clk32kaudio_reg = NULL;
+ }
+ }
+
+ if (clk32kaudio_reg && on && !tuna_wifi_power_state)
+ regulator_enable(clk32kaudio_reg);
+
+ pr_debug("%s: %d\n", __func__, on);
+ mdelay(100);
+ gpio_set_value(GPIO_WLAN_PMENA, on);
+ mdelay(200);
+
+ if (clk32kaudio_reg && !on && tuna_wifi_power_state)
+ regulator_disable(clk32kaudio_reg);
+
+ tuna_wifi_power_state = on;
+ return 0;
+}
+
+static int tuna_wifi_reset_state;
+
+static int tuna_wifi_reset(int on)
+{
+ pr_debug("%s: do nothing\n", __func__);
+ tuna_wifi_reset_state = on;
+ return 0;
+}
+
+static unsigned char tuna_mac_addr[IFHWADDRLEN] = { 0,0x90,0x4c,0,0,0 };
+
+static int __init tuna_mac_addr_setup(char *str)
+{
+ char macstr[IFHWADDRLEN*3];
+ char *macptr = macstr;
+ char *token;
+ int i = 0;
+
+ if (!str)
+ return 0;
+ pr_debug("wlan MAC = %s\n", str);
+ if (strlen(str) >= sizeof(macstr))
+ return 0;
+ strcpy(macstr, str);
+
+ while ((token = strsep(&macptr, ":")) != NULL) {
+ unsigned long val;
+ int res;
+
+ if (i >= IFHWADDRLEN)
+ break;
+ res = strict_strtoul(token, 0x10, &val);
+ if (res < 0)
+ return 0;
+ tuna_mac_addr[i++] = (u8)val;
+ }
+
+ return 1;
+}
+
+__setup("androidboot.macaddr=", tuna_mac_addr_setup);
+
+static int tuna_wifi_get_mac_addr(unsigned char *buf)
+{
+ int type = omap4_tuna_get_type();
+ uint rand_mac;
+
+ if (type != TUNA_TYPE_TORO)
+ return -EINVAL;
+
+ if (!buf)
+ return -EFAULT;
+
+ if ((tuna_mac_addr[4] == 0) && (tuna_mac_addr[5] == 0)) {
+ srandom32((uint)jiffies);
+ rand_mac = random32();
+ tuna_mac_addr[3] = (unsigned char)rand_mac;
+ tuna_mac_addr[4] = (unsigned char)(rand_mac >> 8);
+ tuna_mac_addr[5] = (unsigned char)(rand_mac >> 16);
+ }
+ memcpy(buf, tuna_mac_addr, IFHWADDRLEN);
+ return 0;
+}
+
+/* Customized Locale table : OPTIONAL feature */
+#define WLC_CNTRY_BUF_SZ 4
+typedef struct cntry_locales_custom {
+ char iso_abbrev[WLC_CNTRY_BUF_SZ];
+ char custom_locale[WLC_CNTRY_BUF_SZ];
+ int custom_locale_rev;
+} cntry_locales_custom_t;
+
+static cntry_locales_custom_t tuna_wifi_translate_custom_table[] = {
+/* Table should be filled out based on custom platform regulatory requirement */
+ {"", "XY", 4}, /* universal */
+ {"US", "US", 69}, /* input ISO "US" to : US regrev 69 */
+ {"CA", "US", 69}, /* input ISO "CA" to : US regrev 69 */
+ {"EU", "EU", 5}, /* European union countries */
+ {"AT", "EU", 5},
+ {"BE", "EU", 5},
+ {"BG", "EU", 5},
+ {"CY", "EU", 5},
+ {"CZ", "EU", 5},
+ {"DK", "EU", 5},
+ {"EE", "EU", 5},
+ {"FI", "EU", 5},
+ {"FR", "EU", 5},
+ {"DE", "EU", 5},
+ {"GR", "EU", 5},
+ {"HU", "EU", 5},
+ {"IE", "EU", 5},
+ {"IT", "EU", 5},
+ {"LV", "EU", 5},
+ {"LI", "EU", 5},
+ {"LT", "EU", 5},
+ {"LU", "EU", 5},
+ {"MT", "EU", 5},
+ {"NL", "EU", 5},
+ {"PL", "EU", 5},
+ {"PT", "EU", 5},
+ {"RO", "EU", 5},
+ {"SK", "EU", 5},
+ {"SI", "EU", 5},
+ {"ES", "EU", 5},
+ {"SE", "EU", 5},
+ {"GB", "EU", 5}, /* input ISO "GB" to : EU regrev 05 */
+ {"IL", "IL", 0},
+ {"CH", "CH", 0},
+ {"TR", "TR", 0},
+ {"NO", "NO", 0},
+ {"KR", "XY", 3},
+ {"AU", "XY", 3},
+ {"CN", "XY", 3}, /* input ISO "CN" to : XY regrev 03 */
+ {"TW", "XY", 3},
+ {"AR", "XY", 3},
+ {"MX", "XY", 3}
+};
+
+static void *tuna_wifi_get_country_code(char *ccode)
+{
+ int size = ARRAY_SIZE(tuna_wifi_translate_custom_table);
+ int i;
+
+ if (!ccode)
+ return NULL;
+
+ for (i = 0; i < size; i++)
+ if (strcmp(ccode, tuna_wifi_translate_custom_table[i].iso_abbrev) == 0)
+ return &tuna_wifi_translate_custom_table[i];
+ return &tuna_wifi_translate_custom_table[0];
+}
+
+static struct wifi_platform_data tuna_wifi_control = {
+ .set_power = tuna_wifi_power,
+ .set_reset = tuna_wifi_reset,
+ .set_carddetect = tuna_wifi_set_carddetect,
+ .mem_prealloc = tuna_wifi_mem_prealloc,
+ .get_mac_addr = tuna_wifi_get_mac_addr,
+ .get_country_code = tuna_wifi_get_country_code,
+};
+
+static struct platform_device tuna_wifi_device = {
+ .name = "bcmdhd_wlan",
+ .id = 1,
+ .num_resources = ARRAY_SIZE(tuna_wifi_resources),
+ .resource = tuna_wifi_resources,
+ .dev = {
+ .platform_data = &tuna_wifi_control,
+ },
+};
+
+static void __init tuna_wlan_gpio(void)
+{
+ pr_debug("%s: start\n", __func__);
+
+ /* WLAN SDIO: MMC5 CMD */
+ omap_mux_init_signal("sdmmc5_cmd", OMAP_PIN_INPUT_PULLUP);
+ /* WLAN SDIO: MMC5 CLK */
+ omap_mux_init_signal("sdmmc5_clk", OMAP_PIN_INPUT_PULLUP);
+ /* WLAN SDIO: MMC5 DAT[0-3] */
+ omap_mux_init_signal("sdmmc5_dat0", OMAP_PIN_INPUT_PULLUP);
+ omap_mux_init_signal("sdmmc5_dat1", OMAP_PIN_INPUT_PULLUP);
+ omap_mux_init_signal("sdmmc5_dat2", OMAP_PIN_INPUT_PULLUP);
+ omap_mux_init_signal("sdmmc5_dat3", OMAP_PIN_INPUT_PULLUP);
+ /* WLAN OOB - BCM4330 - GPIO 16 or GPIO 2 */
+ omap_mux_init_signal("sim_reset.gpio_wk2", OMAP_PIN_INPUT);
+ omap_mux_init_signal("kpd_row1.safe_mode", 0);
+ /* WLAN PMENA - GPIO 104 */
+ omap_mux_init_signal("gpmc_ncs7.gpio_104", OMAP_PIN_OUTPUT);
+ /* Enable power to gpio_wk0-gpio_wk2 */
+ omap4_ctrl_wk_pad_writel(0xb0000000,
+ OMAP4_CTRL_MODULE_PAD_WKUP_CONTROL_USIMIO);
+
+ /* gpio_enable(GPIO_WLAN_IRQ); */
+ gpio_request(GPIO_WLAN_IRQ, "wlan_irq");
+ gpio_direction_input(GPIO_WLAN_IRQ);
+}
+
+int __init tuna_wlan_init(void)
+{
+ pr_debug("%s: start\n", __func__);
+
+ tuna_wlan_gpio();
+ tuna_init_wifi_mem();
+ platform_device_register(&omap_vwlan_device);
+ return platform_device_register(&tuna_wifi_device);
+}
diff --git a/arch/arm/mach-omap2/board-tuna.c b/arch/arm/mach-omap2/board-tuna.c
new file mode 100644
index 0000000..3e0ff9a
--- /dev/null
+++ b/arch/arm/mach-omap2/board-tuna.c
@@ -0,0 +1,1362 @@
+/* Board support file for Samsung Tuna Board.
+ *
+ * Copyright (C) 2011 Google, Inc.
+ * Copyright (C) 2010 Texas Instruments
+ *
+ * Based on mach-omap2/board-omap4panda.c
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/ion.h>
+#include <linux/leds.h>
+#include <linux/gpio.h>
+#include <linux/memblock.h>
+#include <linux/omap_ion.h>
+#include <linux/usb/otg.h>
+#include <linux/i2c/twl.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/fixed.h>
+#include <linux/wl12xx.h>
+#include <linux/reboot.h>
+#include <linux/memblock.h>
+#include <linux/sysfs.h>
+#include <linux/uaccess.h>
+#include <linux/proc_fs.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/flash.h>
+#include <linux/platform_data/lte_modem_bootloader.h>
+#include <plat/mcspi.h>
+#include <linux/i2c-gpio.h>
+
+#include <mach/hardware.h>
+#include <mach/omap4-common.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+
+#include <plat/board-tuna-bluetooth.h>
+#include <plat/omap-serial.h>
+#include <plat/board.h>
+#include <plat/common.h>
+#include <plat/cpu.h>
+#include <plat/usb.h>
+#include <plat/mmc.h>
+#include <plat/remoteproc.h>
+#include <plat/omap-serial.h>
+
+#include <mach/id.h>
+#include "timer-gp.h"
+
+#include "omap4-sar-layout.h"
+#include "hsmmc.h"
+#include "control.h"
+#include "mux.h"
+#include "board-tuna.h"
+#include <mach/dmm.h>
+
+#define TUNA_RAMCONSOLE_START (PLAT_PHYS_OFFSET + SZ_512M)
+#define TUNA_RAMCONSOLE_SIZE SZ_2M
+
+struct class *sec_class;
+EXPORT_SYMBOL(sec_class);
+
+/* For LTE(CMC221) */
+#define OMAP_GPIO_LTE_ACTIVE 47
+#define OMAP_GPIO_CMC2AP_INT1 61
+
+#define GPIO_AUD_PWRON 127
+#define GPIO_AUD_PWRON_TORO_V1 20
+
+/* GPS GPIO Setting */
+#define GPIO_AP_AGPS_TSYNC 18
+#define GPIO_GPS_nRST 136
+#define GPIO_GPS_PWR_EN 137
+#define GPIO_GPS_UART_SEL 164
+
+#define GPIO_MHL_SCL_18V 99
+#define GPIO_MHL_SDA_18V 98
+
+#define REBOOT_FLAG_RECOVERY 0x52564352
+#define REBOOT_FLAG_FASTBOOT 0x54534146
+#define REBOOT_FLAG_NORMAL 0x4D524F4E
+#define REBOOT_FLAG_POWER_OFF 0x46464F50
+
+#define UART_NUM_FOR_GPS 0
+
+static int tuna_hw_rev;
+
+static struct gpio tuna_hw_rev_gpios[] = {
+ {76, GPIOF_IN, "hw_rev0"},
+ {75, GPIOF_IN, "hw_rev1"},
+ {74, GPIOF_IN, "hw_rev2"},
+ {73, GPIOF_IN, "hw_rev3"},
+ {170, GPIOF_IN, "hw_rev4"},
+};
+
+static const char const *omap4_tuna_hw_name_maguro[] = {
+ [0x00] = "Toro Lunchbox #1",
+ [0x01] = "Maguro 1st Sample",
+ [0x02] = "Maguro 2nd Sample",
+ [0x03] = "Maguro 4th Sample",
+ [0x05] = "Maguro 5th sample",
+};
+
+static const char const *omap4_tuna_hw_name_toro[] = {
+ [0x00] = "Toro Lunchbox #2",
+ [0x01] = "Toro 1st Sample",
+ [0x02] = "Toro 2nd Sample",
+ [0x03] = "Toro 4th Sample",
+ [0x05] = "Toro 5th Sample",
+};
+
+int omap4_tuna_get_revision(void)
+{
+ return tuna_hw_rev & TUNA_REV_MASK;
+}
+
+int omap4_tuna_get_type(void)
+{
+ return tuna_hw_rev & TUNA_TYPE_MASK;
+}
+
+
+static const char *omap4_tuna_hw_rev_name(void) {
+ const char *ret;
+ const char **names;
+ int num;
+ int rev;
+
+ if (omap4_tuna_get_type() == TUNA_TYPE_MAGURO) {
+ names = omap4_tuna_hw_name_maguro;
+ num = ARRAY_SIZE(omap4_tuna_hw_name_maguro);
+ ret = "Maguro unknown";
+ } else {
+ names = omap4_tuna_hw_name_toro;
+ num = ARRAY_SIZE(omap4_tuna_hw_name_toro);
+ ret = "Toro unknown";
+ }
+
+ rev = omap4_tuna_get_revision();
+ if (rev >= num || !names[rev])
+ return ret;
+
+ return names[rev];
+}
+
+/*
+ * Store a handy board information string which we can use elsewhere like
+ * like in panic situation
+ */
+static char omap4_tuna_bd_info_string[255];
+static void omap4_tuna_init_hw_rev(void)
+{
+ int ret;
+ int i;
+ u32 r;
+
+ /* Disable weak driver pulldown on usbb2_hsic_strobe */
+ r = omap4_ctrl_pad_readl(OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_USBB_HSIC);
+ r &= ~OMAP4_USBB2_HSIC_STROBE_WD_MASK;
+ omap4_ctrl_pad_writel(r, OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_USBB_HSIC);
+
+ ret = gpio_request_array(tuna_hw_rev_gpios,
+ ARRAY_SIZE(tuna_hw_rev_gpios));
+
+ BUG_ON(ret);
+
+ for (i = 0; i < ARRAY_SIZE(tuna_hw_rev_gpios); i++)
+ tuna_hw_rev |= gpio_get_value(tuna_hw_rev_gpios[i].gpio) << i;
+
+ snprintf(omap4_tuna_bd_info_string,
+ ARRAY_SIZE(omap4_tuna_bd_info_string),
+ "Tuna HW revision: %02x (%s), cpu %s ES%d.%d ",
+ tuna_hw_rev,
+ omap4_tuna_hw_rev_name(),
+ cpu_is_omap443x() ? "OMAP4430" : "OMAP4460",
+ (GET_OMAP_REVISION() >> 4) & 0xf,
+ GET_OMAP_REVISION() & 0xf);
+
+ pr_info("%s\n", omap4_tuna_bd_info_string);
+ mach_panic_string = omap4_tuna_bd_info_string;
+}
+
+/* wl127x BT, FM, GPS connectivity chip */
+static int wl1271_gpios[] = {46, -1, -1};
+static struct platform_device wl1271_device = {
+ .name = "kim",
+ .id = -1,
+ .dev = {
+ .platform_data = &wl1271_gpios,
+ },
+};
+
+static struct resource ramconsole_resources[] = {
+ {
+ .flags = IORESOURCE_MEM,
+ .start = TUNA_RAMCONSOLE_START,
+ .end = TUNA_RAMCONSOLE_START + TUNA_RAMCONSOLE_SIZE - 1,
+ },
+};
+
+static struct platform_device ramconsole_device = {
+ .name = "ram_console",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(ramconsole_resources),
+ .resource = ramconsole_resources,
+};
+
+static struct platform_device bcm4330_bluetooth_device = {
+ .name = "bcm4330_bluetooth",
+ .id = -1,
+};
+
+static void __init tuna_bt_init(void)
+{
+ /* BT_EN - GPIO 104 */
+ omap_mux_init_signal("gpmc_ncs6.gpio_103", OMAP_PIN_OUTPUT);
+ /*BT_nRST - GPIO 42 */
+ omap_mux_init_signal("gpmc_a18.gpio_42", OMAP_PIN_OUTPUT);
+ /* BT_WAKE - GPIO 27 */
+ omap_mux_init_signal("dpm_emu16.gpio_27", OMAP_PIN_OUTPUT);
+ /* BT_HOST_WAKE - GPIO 177 */
+ omap_mux_init_signal("kpd_row5.gpio_177", OMAP_WAKEUP_EN | OMAP_PIN_INPUT);
+}
+
+static struct twl4030_madc_platform_data twl6030_madc = {
+ .irq_line = -1,
+};
+
+static struct platform_device twl6030_madc_device = {
+ .name = "twl6030_madc",
+ .id = -1,
+ .dev = {
+ .platform_data = &twl6030_madc,
+ },
+};
+
+
+static struct i2c_gpio_platform_data tuna_gpio_i2c5_pdata = {
+ .sda_pin = GPIO_MHL_SDA_18V,
+ .scl_pin = GPIO_MHL_SCL_18V,
+ .udelay = 3,
+ .timeout = 0,
+};
+
+static struct platform_device tuna_gpio_i2c5_device = {
+ .name = "i2c-gpio",
+ .id = 5,
+ .dev = {
+ .platform_data = &tuna_gpio_i2c5_pdata,
+ }
+};
+
+#define OMAP_TUNA_ION_HEAP_SECURE_INPUT_SIZE (SZ_1M * 90)
+#define OMAP_TUNA_ION_HEAP_TILER_SIZE (SZ_128M - SZ_32M)
+#define OMAP_TUNA_ION_HEAP_NONSECURE_TILER_SIZE SZ_32M
+#define OMAP_TUNA_ION_HEAP_LARGE_SURFACES_SIZE SZ_32M
+#define PHYS_ADDR_SMC_SIZE (SZ_1M * 3)
+#define PHYS_ADDR_SMC_MEM (0x80000000 + SZ_1G - PHYS_ADDR_SMC_SIZE)
+#define PHYS_ADDR_DUCATI_SIZE (SZ_1M * 105)
+#define PHYS_ADDR_DUCATI_MEM (PHYS_ADDR_SMC_MEM - PHYS_ADDR_DUCATI_SIZE -\
+ OMAP_TUNA_ION_HEAP_SECURE_INPUT_SIZE)
+
+static struct ion_platform_data tuna_ion_data = {
+ .nr = 4,
+ .heaps = {
+ {
+ .type = ION_HEAP_TYPE_CARVEOUT,
+ .id = OMAP_ION_HEAP_SECURE_INPUT,
+ .name = "secure_input",
+ .base = PHYS_ADDR_SMC_MEM -
+ OMAP_TUNA_ION_HEAP_SECURE_INPUT_SIZE,
+ .size = OMAP_TUNA_ION_HEAP_SECURE_INPUT_SIZE,
+ },
+ { .type = OMAP_ION_HEAP_TYPE_TILER,
+ .id = OMAP_ION_HEAP_TILER,
+ .name = "tiler",
+ .base = PHYS_ADDR_DUCATI_MEM -
+ OMAP_TUNA_ION_HEAP_TILER_SIZE,
+ .size = OMAP_TUNA_ION_HEAP_TILER_SIZE,
+ },
+ {
+ .type = ION_HEAP_TYPE_CARVEOUT,
+ .id = OMAP_ION_HEAP_LARGE_SURFACES,
+ .name = "large_surfaces",
+ .base = 0x80000000 + SZ_512M + SZ_2M,
+ .size = OMAP_TUNA_ION_HEAP_LARGE_SURFACES_SIZE,
+ },
+ { .type = OMAP_ION_HEAP_TYPE_TILER,
+ .id = OMAP_ION_HEAP_NONSECURE_TILER,
+ .name = "nonsecure_tiler",
+ .base = 0x80000000 + SZ_512M + SZ_2M +
+ OMAP_TUNA_ION_HEAP_LARGE_SURFACES_SIZE,
+ .size = OMAP_TUNA_ION_HEAP_NONSECURE_TILER_SIZE,
+ },
+ },
+};
+
+static struct platform_device tuna_ion_device = {
+ .name = "ion-omap4",
+ .id = -1,
+ .dev = {
+ .platform_data = &tuna_ion_data,
+ },
+};
+
+static struct platform_device tuna_mcasp_device = {
+ .name = "omap-mcasp-dai",
+ .id = 0,
+};
+
+static struct platform_device tuna_spdif_dit_device = {
+ .name = "spdif-dit",
+ .id = 0,
+};
+
+static struct platform_device *tuna_devices[] __initdata = {
+ &ramconsole_device,
+ &wl1271_device,
+ &bcm4330_bluetooth_device,
+ &twl6030_madc_device,
+ &tuna_ion_device,
+ &tuna_gpio_i2c5_device,
+ &tuna_mcasp_device,
+ &tuna_spdif_dit_device,
+};
+
+/*
+ * The UART1 is for GPS, and CSR GPS chip should control uart1 rts level
+ * for gps firmware download.
+ */
+static int uart1_rts_ctrl_write(struct file *file, const char __user *buffer,
+ size_t count, loff_t *offs)
+{
+ char buf[10] = {0,};
+
+ if (omap4_tuna_get_revision() < TUNA_REV_SAMPLE_4)
+ return -ENXIO;
+ if (count > sizeof(buf) - 1)
+ return -EINVAL;
+ if (copy_from_user(buf, buffer, count))
+ return -EFAULT;
+
+ if (!strncmp(buf, "1", 1)) {
+ omap_rts_mux_write(OMAP_PIN_INPUT_PULLUP | OMAP_MUX_MODE7,
+ UART_NUM_FOR_GPS);
+ } else if (!strncmp(buf, "0", 1)) {
+ omap_rts_mux_write(OMAP_PIN_OUTPUT | OMAP_MUX_MODE1,
+ UART_NUM_FOR_GPS);
+ }
+
+ return count;
+}
+
+static const struct file_operations uart1_rts_ctrl_proc_fops = {
+ .write = uart1_rts_ctrl_write,
+};
+
+static int __init tuna_gps_rts_ctrl_init(void)
+{
+ struct proc_dir_entry *p_entry;
+
+ p_entry = proc_create("mcspi1_cs3_ctrl", 0666, NULL,
+ &uart1_rts_ctrl_proc_fops);
+
+ if (!p_entry)
+ return -ENOMEM;
+
+ return 0;
+}
+
+static void tuna_gsd4t_gps_gpio(void)
+{
+ /* AP_AGPS_TSYNC - GPIO 18 */
+ omap_mux_init_signal("dpm_emu7.gpio_18", OMAP_PIN_OUTPUT);
+ /* GPS_nRST - GPIO 136 */
+ omap_mux_init_signal("mcspi1_simo.gpio_136", OMAP_PIN_OUTPUT);
+ /* GPS_PWR_EN - GPIO 137 */
+ omap_mux_init_signal("mcspi1_cs0.gpio_137", OMAP_PIN_OUTPUT);
+ /* GPS_UART_SEL - GPIO 164 */
+ omap_mux_init_signal("usbb2_ulpitll_dat3.gpio_164", OMAP_PIN_OUTPUT);
+}
+
+static void tuna_gsd4t_gps_init(void)
+{
+ struct device *gps_dev;
+
+ gps_dev = device_create(sec_class, NULL, 0, NULL, "gps");
+ if (IS_ERR(gps_dev)) {
+ pr_err("Failed to create device(gps)!\n");
+ goto err;
+ }
+ tuna_gsd4t_gps_gpio();
+
+ gpio_request(GPIO_AP_AGPS_TSYNC, "AP_AGPS_TSYNC");
+ gpio_direction_output(GPIO_AP_AGPS_TSYNC, 0);
+
+ gpio_request(GPIO_GPS_nRST, "GPS_nRST");
+ gpio_direction_output(GPIO_GPS_nRST, 1);
+
+ gpio_request(GPIO_GPS_PWR_EN, "GPS_PWR_EN");
+ gpio_direction_output(GPIO_GPS_PWR_EN, 0);
+
+ gpio_request(GPIO_GPS_UART_SEL , "GPS_UART_SEL");
+ gpio_direction_output(GPIO_GPS_UART_SEL , 0);
+
+ gpio_export(GPIO_GPS_nRST, 1);
+ gpio_export(GPIO_GPS_PWR_EN, 1);
+
+ gpio_export_link(gps_dev, "GPS_nRST", GPIO_GPS_nRST);
+ gpio_export_link(gps_dev, "GPS_PWR_EN", GPIO_GPS_PWR_EN);
+
+ tuna_gps_rts_ctrl_init();
+
+err:
+ return;
+}
+
+static int __init sec_common_init(void)
+{
+ sec_class = class_create(THIS_MODULE, "sec");
+ if (IS_ERR(sec_class))
+ pr_err("Failed to create class(sec)!\n");
+
+ return 0;
+}
+
+static void __init tuna_init_early(void)
+{
+ omap2_init_common_infrastructure();
+ omap2_init_common_devices(NULL, NULL);
+}
+
+static struct omap_musb_board_data musb_board_data = {
+ .interface_type = MUSB_INTERFACE_UTMI,
+#ifdef CONFIG_USB_MUSB_OTG
+ .mode = MUSB_OTG,
+#else
+ .mode = MUSB_PERIPHERAL,
+#endif
+ .power = 100,
+};
+
+static struct omap2_hsmmc_info mmc[] = {
+ {
+ .mmc = 1,
+ .nonremovable = true,
+ .caps = MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
+ .ocr_mask = MMC_VDD_165_195,
+ .gpio_wp = -EINVAL,
+ .gpio_cd = -EINVAL,
+ },
+ {
+ .name = "omap_wlan",
+ .mmc = 5,
+ .caps = MMC_CAP_4_BIT_DATA,
+ .gpio_wp = -EINVAL,
+ .gpio_cd = -EINVAL,
+ .ocr_mask = MMC_VDD_165_195 | MMC_VDD_20_21,
+ .nonremovable = false,
+ .mmc_data = &tuna_wifi_data,
+ },
+ {} /* Terminator */
+};
+
+static struct regulator_consumer_supply tuna_vmmc_supply[] = {
+ {
+ .supply = "vmmc",
+ .dev_name = "omap_hsmmc.0",
+ },
+ {
+ .supply = "vmmc",
+ .dev_name = "omap_hsmmc.1",
+ },
+};
+
+static struct regulator_init_data tuna_vaux1 = {
+ .constraints = {
+ .min_uV = 3000000,
+ .max_uV = 3000000,
+ .apply_uV = true,
+ .valid_modes_mask = REGULATOR_MODE_NORMAL
+ | REGULATOR_MODE_STANDBY,
+ .valid_ops_mask = REGULATOR_CHANGE_MODE
+ | REGULATOR_CHANGE_STATUS,
+ .always_on = true,
+ },
+};
+
+static struct regulator_init_data tuna_vaux2 = {
+ .constraints = {
+ .min_uV = 1200000,
+ .max_uV = 2800000,
+ .apply_uV = true,
+ .valid_modes_mask = REGULATOR_MODE_NORMAL
+ | REGULATOR_MODE_STANDBY,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE
+ | REGULATOR_CHANGE_MODE
+ | REGULATOR_CHANGE_STATUS,
+ },
+};
+
+static struct regulator_consumer_supply tuna_vaux3_supplies[] = {
+ {
+ .supply = "vlcd",
+ },
+};
+
+static struct regulator_init_data tuna_vaux3 = {
+ .constraints = {
+ .min_uV = 3100000,
+ .max_uV = 3100000,
+ .apply_uV = true,
+ .valid_modes_mask = REGULATOR_MODE_NORMAL
+ | REGULATOR_MODE_STANDBY,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE
+ | REGULATOR_CHANGE_MODE
+ | REGULATOR_CHANGE_STATUS,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(tuna_vaux3_supplies),
+ .consumer_supplies = tuna_vaux3_supplies,
+};
+
+static struct regulator_init_data tuna_vmmc = {
+ .constraints = {
+ .min_uV = 1800000,
+ .max_uV = 1800000,
+ .apply_uV = true,
+ .valid_modes_mask = REGULATOR_MODE_NORMAL
+ | REGULATOR_MODE_STANDBY,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE
+ | REGULATOR_CHANGE_MODE
+ | REGULATOR_CHANGE_STATUS,
+ },
+ .num_consumer_supplies = 2,
+ .consumer_supplies = tuna_vmmc_supply,
+};
+
+static struct regulator_init_data tuna_vpp = {
+ .constraints = {
+ .min_uV = 1800000,
+ .max_uV = 2500000,
+ .apply_uV = true,
+ .valid_modes_mask = REGULATOR_MODE_NORMAL
+ | REGULATOR_MODE_STANDBY,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE
+ | REGULATOR_CHANGE_MODE
+ | REGULATOR_CHANGE_STATUS,
+ },
+};
+
+static struct regulator_consumer_supply tuna_vusim_supplies[] = {
+ {
+ .supply = "vlcd-iovcc",
+ },
+};
+
+static struct regulator_init_data tuna_vusim = {
+ .constraints = {
+ .min_uV = 2200000,
+ .max_uV = 2200000,
+ .valid_modes_mask = REGULATOR_MODE_NORMAL
+ | REGULATOR_MODE_STANDBY,
+ .valid_ops_mask = REGULATOR_CHANGE_MODE
+ | REGULATOR_CHANGE_STATUS,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(tuna_vusim_supplies),
+ .consumer_supplies = tuna_vusim_supplies,
+};
+
+static struct regulator_init_data tuna_vana = {
+ .constraints = {
+ .min_uV = 2100000,
+ .max_uV = 2100000,
+ .valid_modes_mask = REGULATOR_MODE_NORMAL
+ | REGULATOR_MODE_STANDBY,
+ .valid_ops_mask = REGULATOR_CHANGE_MODE
+ | REGULATOR_CHANGE_STATUS,
+ .always_on = true,
+ },
+};
+
+static struct regulator_consumer_supply tuna_vcxio_supply[] = {
+ REGULATOR_SUPPLY("vdds_dsi", "omapdss_dss"),
+ REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi1"),
+};
+
+static struct regulator_init_data tuna_vcxio = {
+ .constraints = {
+ .min_uV = 1800000,
+ .max_uV = 1800000,
+ .valid_modes_mask = REGULATOR_MODE_NORMAL
+ | REGULATOR_MODE_STANDBY,
+ .valid_ops_mask = REGULATOR_CHANGE_MODE
+ | REGULATOR_CHANGE_STATUS,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(tuna_vcxio_supply),
+ .consumer_supplies = tuna_vcxio_supply,
+
+};
+
+static struct regulator_consumer_supply tuna_vdac_supply[] = {
+ {
+ .supply = "hdmi_vref",
+ },
+};
+
+static struct regulator_init_data tuna_vdac = {
+ .constraints = {
+ .min_uV = 1800000,
+ .max_uV = 1800000,
+ .valid_modes_mask = REGULATOR_MODE_NORMAL
+ | REGULATOR_MODE_STANDBY,
+ .valid_ops_mask = REGULATOR_CHANGE_MODE
+ | REGULATOR_CHANGE_STATUS,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(tuna_vdac_supply),
+ .consumer_supplies = tuna_vdac_supply,
+};
+
+static struct regulator_consumer_supply tuna_vusb_supply[] = {
+ REGULATOR_SUPPLY("vusb", "tuna_otg"),
+};
+
+static struct regulator_init_data tuna_vusb = {
+ .constraints = {
+ .min_uV = 3300000,
+ .max_uV = 3300000,
+ .valid_modes_mask = REGULATOR_MODE_NORMAL
+ | REGULATOR_MODE_STANDBY,
+ .valid_ops_mask = REGULATOR_CHANGE_MODE
+ | REGULATOR_CHANGE_STATUS,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(tuna_vusb_supply),
+ .consumer_supplies = tuna_vusb_supply,
+};
+
+/* clk32kg is a twl6030 32khz clock modeled as a regulator, used by GPS */
+static struct regulator_init_data tuna_clk32kg = {
+ .constraints = {
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ .always_on = true,
+ },
+};
+
+static struct regulator_consumer_supply tuna_clk32kaudio_supply[] = {
+ {
+ .supply = "clk32kaudio",
+ },
+ {
+ .supply = "twl6040_clk32k",
+ }
+};
+
+static struct regulator_init_data tuna_clk32kaudio = {
+ .constraints = {
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ .boot_on = true,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(tuna_clk32kaudio_supply),
+ .consumer_supplies = tuna_clk32kaudio_supply,
+};
+
+
+static struct regulator_init_data tuna_vdd3 = {
+ .constraints = {
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ },
+};
+
+/*
+ * VMEM is unused. Register it to regulator framework and let it
+ * be in disabled state.
+ */
+static struct regulator_init_data tuna_vmem = {
+ .constraints = {
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ },
+};
+
+static struct regulator_init_data tuna_v2v1 = {
+ .constraints = {
+ .min_uV = 2100000,
+ .max_uV = 2100000,
+ .valid_modes_mask = REGULATOR_MODE_NORMAL
+ | REGULATOR_MODE_STANDBY,
+ .valid_ops_mask = REGULATOR_CHANGE_MODE
+ | REGULATOR_CHANGE_STATUS,
+ .always_on = true,
+ },
+};
+
+static struct twl4030_codec_audio_data twl6040_audio = {
+ /* single-step ramp for headset and handsfree */
+ .hs_left_step = 0x0f,
+ .hs_right_step = 0x0f,
+ .hf_left_step = 0x1d,
+ .hf_right_step = 0x1d,
+ .ep_step = 0x0f,
+};
+
+static struct twl4030_codec_data twl6040_codec = {
+ .audio = &twl6040_audio,
+ .naudint_irq = OMAP44XX_IRQ_SYS_2N,
+ .irq_base = TWL6040_CODEC_IRQ_BASE,
+};
+
+static struct twl4030_platform_data tuna_twldata = {
+ .irq_base = TWL6030_IRQ_BASE,
+ .irq_end = TWL6030_IRQ_END,
+
+ /* Regulators */
+ .vmmc = &tuna_vmmc,
+ .vpp = &tuna_vpp,
+ .vusim = &tuna_vusim,
+ .vana = &tuna_vana,
+ .vcxio = &tuna_vcxio,
+ .vdac = &tuna_vdac,
+ .vusb = &tuna_vusb,
+ .vaux1 = &tuna_vaux1,
+ .vaux2 = &tuna_vaux2,
+ .vaux3 = &tuna_vaux3,
+ .clk32kg = &tuna_clk32kg,
+ .clk32kaudio = &tuna_clk32kaudio,
+
+ /* children */
+ .codec = &twl6040_codec,
+ .madc = &twl6030_madc,
+
+ /* SMPS */
+ .vdd3 = &tuna_vdd3,
+ .vmem = &tuna_vmem,
+ .v2v1 = &tuna_v2v1,
+};
+
+static void tuna_audio_init(void)
+{
+ unsigned int aud_pwron;
+
+ /* twl6040 naudint */
+ omap_mux_init_signal("sys_nirq2.sys_nirq2", \
+ OMAP_PIN_INPUT_PULLUP);
+
+ /* aud_pwron */
+ if (omap4_tuna_get_type() == TUNA_TYPE_TORO &&
+ omap4_tuna_get_revision() >= 1)
+ aud_pwron = GPIO_AUD_PWRON_TORO_V1;
+ else
+ aud_pwron = GPIO_AUD_PWRON;
+ omap_mux_init_gpio(aud_pwron, OMAP_PIN_OUTPUT);
+ twl6040_codec.audpwron_gpio = aud_pwron;
+
+ omap_mux_init_signal("gpmc_a24.gpio_48", OMAP_PIN_OUTPUT | OMAP_MUX_MODE3);
+ omap_mux_init_signal("kpd_col3.gpio_171", OMAP_PIN_OUTPUT | OMAP_MUX_MODE3);
+}
+
+static struct i2c_board_info __initdata tuna_i2c1_boardinfo[] = {
+ {
+ I2C_BOARD_INFO("twl6030", 0x48),
+ .flags = I2C_CLIENT_WAKE,
+ .irq = OMAP44XX_IRQ_SYS_1N,
+ .platform_data = &tuna_twldata,
+ },
+};
+
+static struct i2c_board_info __initdata tuna_i2c2_boardinfo[] = {
+ {
+ I2C_BOARD_INFO("ducati", 0x20),
+ .irq = OMAP44XX_IRQ_I2C2,
+ .ext_master = true,
+ },
+};
+
+static struct i2c_board_info __initdata tuna_i2c4_boardinfo[] = {
+ {
+ I2C_BOARD_INFO("an30259a", 0x30),
+ },
+};
+
+static int __init tuna_i2c_init(void)
+{
+ u32 r;
+
+ omap_mux_init_signal("sys_nirq1", OMAP_PIN_INPUT_PULLUP |
+ OMAP_WAKEUP_EN);
+ omap_mux_init_signal("i2c1_scl.i2c1_scl", OMAP_PIN_INPUT_PULLUP);
+ omap_mux_init_signal("i2c1_sda.i2c1_sda", OMAP_PIN_INPUT_PULLUP);
+
+ /*
+ * This will allow unused regulator to be shutdown. This flag
+ * should be set in the board file. Before regulators are registered.
+ */
+ regulator_has_full_constraints();
+
+ /*
+ * Phoenix Audio IC needs I2C1 to
+ * start with 400 KHz or less
+ */
+ omap_register_i2c_bus(1, 400, tuna_i2c1_boardinfo,
+ ARRAY_SIZE(tuna_i2c1_boardinfo));
+ omap_register_i2c_bus(2, 400, tuna_i2c2_boardinfo,
+ ARRAY_SIZE(tuna_i2c2_boardinfo));
+ omap_register_i2c_bus(3, 400, NULL, 0);
+
+ /* Disable internal pullup on i2c.4 line:
+ * as external 2.2K is already present
+ */
+ r = omap4_ctrl_pad_readl(OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_I2C_0);
+ r |= (1 << OMAP4_I2C4_SDA_PULLUPRESX_SHIFT);
+ omap4_ctrl_pad_writel(r, OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_I2C_0);
+
+ omap_register_i2c_bus(4, 400, NULL, 0);
+
+ /*
+ * Drive MSECURE high for TWL6030 write access.
+ */
+ omap_mux_init_signal("fref_clk0_out.gpio_wk6", OMAP_PIN_OUTPUT);
+ gpio_request(6, "msecure");
+ gpio_direction_output(6, 1);
+
+ return 0;
+}
+
+#ifdef CONFIG_OMAP_MUX
+static struct omap_board_mux board_mux[] __initdata = {
+ /* camera gpios */
+ OMAP4_MUX(MCSPI1_SOMI,
+ OMAP_MUX_MODE3 | OMAP_PIN_INPUT_PULLDOWN), /* gpio_135 */
+ OMAP4_MUX(KPD_COL0,
+ OMAP_MUX_MODE3 | OMAP_PIN_INPUT_PULLDOWN), /* gpio_173 */
+ OMAP4_MUX(GPMC_A19,
+ OMAP_MUX_MODE3 | OMAP_PIN_INPUT_PULLDOWN), /* gpio_43 */
+ /* hwrev */
+ OMAP4_MUX(CSI21_DY4, OMAP_MUX_MODE3 | OMAP_PIN_INPUT),
+ OMAP4_MUX(CSI21_DX4, OMAP_MUX_MODE3 | OMAP_PIN_INPUT),
+ OMAP4_MUX(CSI21_DY3, OMAP_MUX_MODE3 | OMAP_PIN_INPUT),
+ OMAP4_MUX(CSI21_DX3, OMAP_MUX_MODE3 | OMAP_PIN_INPUT),
+ OMAP4_MUX(USBB2_HSIC_STROBE, OMAP_MUX_MODE3 | OMAP_PIN_INPUT),
+ /* fRom */
+ OMAP4_MUX(USBB2_ULPITLL_DAT4,
+ OMAP_MUX_MODE4 | OMAP_PIN_INPUT), /* mcpsi3_somi */
+ OMAP4_MUX(USBB2_ULPITLL_DAT5,
+ OMAP_MUX_MODE4 | OMAP_PIN_INPUT_PULLDOWN), /* mcpsi3_cs0 */
+ OMAP4_MUX(USBB2_ULPITLL_DAT6,
+ OMAP_MUX_MODE4 | OMAP_PIN_INPUT), /* mcpsi3_simo */
+ OMAP4_MUX(USBB2_ULPITLL_DAT7,
+ OMAP_MUX_MODE4 | OMAP_PIN_INPUT), /* mcpsi3_clk */
+ { .reg_offset = OMAP_MUX_TERMINATOR },
+};
+
+static struct omap_board_mux board_wkup_mux[] __initdata = {
+ /* power button */
+ OMAP4_MUX(SIM_CD, OMAP_MUX_MODE3 | OMAP_PIN_INPUT),
+ { .reg_offset = OMAP_MUX_TERMINATOR },
+};
+
+#else
+#define board_mux NULL
+#define board_wkup_mux NULL
+#endif
+
+/* sample4+ adds gps rts/cts lines */
+static struct omap_device_pad tuna_uart1_pads_sample4[] __initdata = {
+ {
+ .name = "mcspi1_cs3.uart1_rts",
+ .enable = OMAP_PIN_OUTPUT | OMAP_MUX_MODE1,
+ },
+ {
+ .name = "mcspi1_cs2.uart1_cts",
+ .enable = OMAP_PIN_INPUT_PULLUP | OMAP_MUX_MODE1,
+ },
+ {
+ .name = "uart3_cts_rctx.uart1_tx",
+ .enable = OMAP_PIN_OUTPUT | OMAP_MUX_MODE1,
+ },
+ {
+ .name = "mcspi1_cs1.uart1_rx",
+ .flags = OMAP_DEVICE_PAD_REMUX | OMAP_DEVICE_PAD_WAKEUP,
+ .enable = OMAP_PIN_INPUT_PULLUP | OMAP_MUX_MODE1,
+ .idle = OMAP_PIN_INPUT_PULLUP | OMAP_MUX_MODE1,
+ },
+};
+
+static struct omap_device_pad tuna_uart1_pads[] __initdata = {
+ {
+ .name = "uart3_cts_rctx.uart1_tx",
+ .enable = OMAP_PIN_OUTPUT | OMAP_MUX_MODE1,
+ },
+ {
+ .name = "mcspi1_cs1.uart1_rx",
+ .flags = OMAP_DEVICE_PAD_REMUX | OMAP_DEVICE_PAD_WAKEUP,
+ .enable = OMAP_PIN_INPUT_PULLUP | OMAP_MUX_MODE1,
+ .idle = OMAP_PIN_INPUT_PULLUP | OMAP_MUX_MODE1,
+ },
+};
+
+static struct omap_device_pad tuna_uart2_pads[] __initdata = {
+ {
+ .name = "uart2_cts.uart2_cts",
+ .enable = OMAP_PIN_INPUT_PULLUP | OMAP_MUX_MODE0,
+ },
+ {
+ .name = "uart2_rts.uart2_rts",
+ .enable = OMAP_PIN_OUTPUT | OMAP_MUX_MODE0,
+ },
+ {
+ .name = "uart2_tx.uart2_tx",
+ .enable = OMAP_PIN_OUTPUT | OMAP_MUX_MODE0,
+ },
+ {
+ .name = "uart2_rx.uart2_rx",
+ .enable = OMAP_PIN_INPUT_PULLUP | OMAP_MUX_MODE0,
+ },
+};
+
+static struct omap_device_pad tuna_uart3_pads[] __initdata = {
+ {
+ .name = "uart3_tx_irtx.uart3_tx_irtx",
+ .enable = OMAP_PIN_OUTPUT | OMAP_MUX_MODE0,
+ },
+ {
+ .name = "uart3_rx_irrx.uart3_rx_irrx",
+ .flags = OMAP_DEVICE_PAD_REMUX | OMAP_DEVICE_PAD_WAKEUP,
+ .enable = OMAP_PIN_INPUT | OMAP_MUX_MODE0,
+ .idle = OMAP_PIN_INPUT | OMAP_MUX_MODE0,
+ },
+};
+
+static struct omap_device_pad tuna_uart4_pads[] __initdata = {
+ {
+ .name = "uart4_tx.uart4_tx",
+ .enable = OMAP_PIN_OUTPUT | OMAP_MUX_MODE0,
+ },
+ {
+ .name = "uart4_rx.uart4_rx",
+ .enable = OMAP_PIN_INPUT | OMAP_MUX_MODE0,
+ },
+};
+
+static struct omap_uart_port_info tuna_uart2_info __initdata = {
+ .use_dma = 0,
+ .dma_rx_buf_size = DEFAULT_RXDMA_BUFSIZE,
+ .dma_rx_poll_rate = DEFAULT_RXDMA_POLLRATE,
+ .dma_rx_timeout = DEFAULT_RXDMA_TIMEOUT,
+ .auto_sus_timeout = DEFAULT_AUTOSUSPEND_DELAY,
+ .wake_peer = bcm_bt_lpm_exit_lpm_locked,
+ .rts_mux_driver_control = 1,
+};
+
+static inline void __init board_serial_init(void)
+{
+ struct omap_device_pad *uart1_pads;
+ int uart1_pads_sz;
+
+ if (omap4_tuna_get_revision() >= TUNA_REV_SAMPLE_4) {
+ uart1_pads = tuna_uart1_pads_sample4;
+ uart1_pads_sz = ARRAY_SIZE(tuna_uart1_pads_sample4);
+ } else {
+ uart1_pads = tuna_uart1_pads;
+ uart1_pads_sz = ARRAY_SIZE(tuna_uart1_pads);
+ }
+
+ omap_serial_init_port_pads(0, uart1_pads, uart1_pads_sz, NULL);
+ omap_serial_init_port_pads(1, tuna_uart2_pads,
+ ARRAY_SIZE(tuna_uart2_pads), &tuna_uart2_info);
+ omap_serial_init_port_pads(2, tuna_uart3_pads,
+ ARRAY_SIZE(tuna_uart3_pads), NULL);
+ omap_serial_init_port_pads(3, tuna_uart4_pads,
+ ARRAY_SIZE(tuna_uart4_pads), NULL);
+}
+
+/* SPI flash memory in camera module */
+#define F_ROM_SPI_BUS_NUM 3
+#define F_ROM_SPI_CS 0
+#define F_ROM_SPI_SPEED_HZ 24000000
+
+static const struct flash_platform_data w25q80_pdata = {
+ .name = "w25q80",
+ .type = "w25q80",
+};
+
+static struct omap2_mcspi_device_config f_rom_mcspi_config = {
+ .turbo_mode = 0,
+ .single_channel = 1, /* 0: slave, 1: master */
+ .swap_datalines = 1,
+};
+
+static struct spi_board_info tuna_f_rom[] __initdata = {
+ {
+ .modalias = "m25p80",
+ .controller_data = &f_rom_mcspi_config,
+ .platform_data = &w25q80_pdata,
+ .bus_num = F_ROM_SPI_BUS_NUM,
+ .chip_select = F_ROM_SPI_CS,
+ .max_speed_hz = F_ROM_SPI_SPEED_HZ,
+ .mode = SPI_MODE_0,
+ },
+};
+
+static void tuna_from_init(void)
+{
+ int err;
+
+ if (tuna_hw_rev >= 0x07)
+ f_rom_mcspi_config.swap_datalines = 0;
+
+ err = spi_register_board_info(tuna_f_rom, ARRAY_SIZE(tuna_f_rom));
+ if (err)
+ pr_err("failed to register SPI F-ROM\n");
+}
+
+/*SPI for LTE modem bootloader*/
+#define LTE_MODEM_SPI_BUS_NUM 4
+#define LTE_MODEM_SPI_CS 0
+#define LTE_MODEM_SPI_MAX_HZ 1500000
+
+struct lte_modem_bootloader_platform_data lte_modem_bootloader_pdata = {
+ .name = "lte_modem_int",
+ .gpio_lte2ap_status = OMAP_GPIO_CMC2AP_INT1,
+};
+
+static struct omap2_mcspi_device_config lte_mcspi_config = {
+ .turbo_mode = 0,
+ .single_channel = 1, /* 0: slave, 1: master */
+};
+
+static struct spi_board_info tuna_lte_modem[] __initdata = {
+ {
+ .modalias = "lte_modem_spi",
+ .controller_data = &lte_mcspi_config,
+ .platform_data = &lte_modem_bootloader_pdata,
+ .max_speed_hz = LTE_MODEM_SPI_MAX_HZ,
+ .bus_num = LTE_MODEM_SPI_BUS_NUM,
+ .chip_select = LTE_MODEM_SPI_CS,
+ .mode = SPI_MODE_0,
+ },
+};
+
+static int tuna_notifier_call(struct notifier_block *this,
+ unsigned long code, void *_cmd)
+{
+ void __iomem *sar_base;
+ unsigned int flag = REBOOT_FLAG_NORMAL;
+
+ sar_base = omap4_get_sar_ram_base();
+
+ if (!sar_base)
+ return notifier_from_errno(-ENOMEM);
+
+ if (code == SYS_RESTART) {
+ if (_cmd) {
+ if (!strcmp(_cmd, "recovery"))
+ flag = REBOOT_FLAG_RECOVERY;
+ else if (!strcmp(_cmd, "bootloader"))
+ flag = REBOOT_FLAG_FASTBOOT;
+ }
+ } else if (code == SYS_POWER_OFF) {
+ flag = REBOOT_FLAG_POWER_OFF;
+ }
+
+ /* The Samsung LOKE bootloader will look for the boot flag at a fixed
+ * offset from the end of the 1st SAR bank.
+ */
+ writel(flag, sar_base + SAR_BANK2_OFFSET - 0xC);
+
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block tuna_reboot_notifier = {
+ .notifier_call = tuna_notifier_call,
+};
+
+static ssize_t tuna_soc_family_show(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buf)
+{
+ return sprintf(buf, "OMAP%04x\n", GET_OMAP_TYPE);
+}
+
+static ssize_t tuna_soc_revision_show(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buf)
+{
+ return sprintf(buf, "ES%d.%d\n", (GET_OMAP_REVISION() >> 4) & 0xf,
+ GET_OMAP_REVISION() & 0xf);
+}
+
+static ssize_t tuna_soc_die_id_show(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buf)
+{
+ struct omap_die_id oid;
+ omap_get_die_id(&oid);
+ return sprintf(buf, "%08X-%08X-%08X-%08X\n", oid.id_3, oid.id_2,
+ oid.id_1, oid.id_0);
+}
+
+static ssize_t tuna_soc_prod_id_show(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buf)
+{
+ struct omap_die_id oid;
+ omap_get_production_id(&oid);
+ return sprintf(buf, "%08X-%08X\n", oid.id_1, oid.id_0);
+}
+
+static ssize_t tuna_soc_msv_show(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buf)
+{
+ return sprintf(buf, "%08X\n", omap_ctrl_readl(0x013c));
+}
+
+static const char *omap_types[] = {
+ [OMAP2_DEVICE_TYPE_TEST] = "TST",
+ [OMAP2_DEVICE_TYPE_EMU] = "EMU",
+ [OMAP2_DEVICE_TYPE_SEC] = "HS",
+ [OMAP2_DEVICE_TYPE_GP] = "GP",
+ [OMAP2_DEVICE_TYPE_BAD] = "BAD",
+};
+
+static ssize_t tuna_soc_type_show(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buf)
+{
+ return sprintf(buf, "%s\n", omap_types[omap_type()]);
+}
+
+#define TUNA_ATTR_RO(_type, _name, _show) \
+ struct kobj_attribute tuna_##_type##_prop_attr_##_name = \
+ __ATTR(_name, S_IRUGO, _show, NULL)
+
+static TUNA_ATTR_RO(soc, family, tuna_soc_family_show);
+static TUNA_ATTR_RO(soc, revision, tuna_soc_revision_show);
+static TUNA_ATTR_RO(soc, type, tuna_soc_type_show);
+static TUNA_ATTR_RO(soc, die_id, tuna_soc_die_id_show);
+static TUNA_ATTR_RO(soc, production_id, tuna_soc_prod_id_show);
+static TUNA_ATTR_RO(soc, msv, tuna_soc_msv_show);
+
+static struct attribute *tuna_soc_prop_attrs[] = {
+ &tuna_soc_prop_attr_family.attr,
+ &tuna_soc_prop_attr_revision.attr,
+ &tuna_soc_prop_attr_type.attr,
+ &tuna_soc_prop_attr_die_id.attr,
+ &tuna_soc_prop_attr_production_id.attr,
+ &tuna_soc_prop_attr_msv.attr,
+ NULL,
+};
+
+static struct attribute_group tuna_soc_prop_attr_group = {
+ .attrs = tuna_soc_prop_attrs,
+};
+
+static ssize_t tuna_board_revision_show(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buf)
+{
+ return sprintf(buf, "%s (0x%02x)\n", omap4_tuna_hw_rev_name(),
+ tuna_hw_rev);
+}
+
+static TUNA_ATTR_RO(board, revision, tuna_board_revision_show);
+static struct attribute *tuna_board_prop_attrs[] = {
+ &tuna_board_prop_attr_revision.attr,
+ NULL,
+};
+
+static struct attribute_group tuna_board_prop_attr_group = {
+ .attrs = tuna_board_prop_attrs,
+};
+
+static void __init omap4_tuna_create_board_props(void)
+{
+ struct kobject *board_props_kobj;
+ struct kobject *soc_kobj;
+ int ret = 0;
+
+ board_props_kobj = kobject_create_and_add("board_properties", NULL);
+ if (!board_props_kobj)
+ goto err_board_obj;
+
+ soc_kobj = kobject_create_and_add("soc", board_props_kobj);
+ if (!soc_kobj)
+ goto err_soc_obj;
+
+ ret = sysfs_create_group(board_props_kobj, &tuna_board_prop_attr_group);
+ if (ret)
+ goto err_board_sysfs_create;
+
+ ret = sysfs_create_group(soc_kobj, &tuna_soc_prop_attr_group);
+ if (ret)
+ goto err_soc_sysfs_create;
+
+ return;
+
+err_soc_sysfs_create:
+ sysfs_remove_group(board_props_kobj, &tuna_board_prop_attr_group);
+err_board_sysfs_create:
+ kobject_put(soc_kobj);
+err_soc_obj:
+ kobject_put(board_props_kobj);
+err_board_obj:
+ if (!board_props_kobj || !soc_kobj || ret)
+ pr_err("failed to create board_properties\n");
+}
+
+#define HSMMC2_MUX (OMAP_MUX_MODE1 | OMAP_PIN_INPUT_PULLUP)
+#define HSMMC1_MUX OMAP_PIN_INPUT_PULLUP
+
+static void __init omap4_tuna_led_init(void)
+{
+ i2c_register_board_info(4, tuna_i2c4_boardinfo,
+ ARRAY_SIZE(tuna_i2c4_boardinfo));
+}
+
+/* always reboot into charger mode on "power-off". Let the bootloader
+ * figure out if we should truly power-off or not.
+ */
+static void tuna_power_off(void)
+{
+ printk(KERN_EMERG "Rebooting into bootloader for power-off.\n");
+ arm_pm_restart('c', NULL);
+}
+
+static void __init tuna_init(void)
+{
+ int package = OMAP_PACKAGE_CBS;
+
+ if (omap_rev() == OMAP4430_REV_ES1_0)
+ package = OMAP_PACKAGE_CBL;
+ omap4_mux_init(board_mux, board_wkup_mux, package);
+
+ omap4_tuna_init_hw_rev();
+
+ omap4_tuna_emif_init();
+
+ pm_power_off = tuna_power_off;
+
+ register_reboot_notifier(&tuna_reboot_notifier);
+
+ /* hsmmc d0-d7 */
+ omap_mux_init_signal("sdmmc1_dat0.sdmmc1_dat0", HSMMC1_MUX);
+ omap_mux_init_signal("sdmmc1_dat1.sdmmc1_dat1", HSMMC1_MUX);
+ omap_mux_init_signal("sdmmc1_dat2.sdmmc1_dat2", HSMMC1_MUX);
+ omap_mux_init_signal("sdmmc1_dat3.sdmmc1_dat3", HSMMC1_MUX);
+ omap_mux_init_signal("sdmmc1_dat4.sdmmc1_dat4", HSMMC1_MUX);
+ omap_mux_init_signal("sdmmc1_dat5.sdmmc1_dat5", HSMMC1_MUX);
+ omap_mux_init_signal("sdmmc1_dat6.sdmmc1_dat6", HSMMC1_MUX);
+ omap_mux_init_signal("sdmmc1_dat7.sdmmc1_dat7", HSMMC1_MUX);
+ /* hsmmc cmd */
+ omap_mux_init_signal("sdmmc1_cmd.sdmmc1_cmd", HSMMC1_MUX);
+ /* hsmmc clk */
+ omap_mux_init_signal("sdmmc1_clk.sdmmc1_clk", HSMMC1_MUX);
+
+ gpio_request(158, "emmc_en");
+ gpio_direction_output(158, 1);
+ omap_mux_init_gpio(158, OMAP_PIN_INPUT_PULLUP);
+
+ omap_mux_init_gpio(GPIO_MHL_SDA_18V, OMAP_PIN_INPUT_PULLUP);
+ omap_mux_init_gpio(GPIO_MHL_SCL_18V, OMAP_PIN_INPUT_PULLUP);
+
+ sec_common_init();
+
+ if (TUNA_TYPE_TORO == omap4_tuna_get_type()) {
+ omap_mux_init_signal("gpmc_wait0",
+ OMAP_MUX_MODE3 | OMAP_PIN_INPUT_PULLDOWN);
+ gpio_request(OMAP_GPIO_CMC2AP_INT1, "gpio_61");
+ gpio_direction_input(OMAP_GPIO_CMC2AP_INT1);
+
+ omap_mux_init_signal("mcspi4_clk", OMAP_MUX_MODE0);
+ omap_mux_init_signal("mcspi4_simo", OMAP_MUX_MODE0);
+ omap_mux_init_signal("mcspi4_somi", OMAP_MUX_MODE0);
+ omap_mux_init_signal("mcspi4_cs0", OMAP_MUX_MODE0);
+ }
+
+ tuna_wlan_init();
+ tuna_audio_init();
+ tuna_i2c_init();
+ tuna_bt_init();
+ tuna_gsd4t_gps_init();
+ platform_add_devices(tuna_devices, ARRAY_SIZE(tuna_devices));
+ board_serial_init();
+ omap2_hsmmc_init(mmc);
+ usb_musb_init(&musb_board_data);
+ omap4_tuna_create_board_props();
+ if (TUNA_TYPE_TORO == omap4_tuna_get_type()) {
+ spi_register_board_info(tuna_lte_modem,
+ ARRAY_SIZE(tuna_lte_modem));
+ }
+ tuna_from_init();
+ omap_dmm_init();
+ omap4_tuna_display_init();
+ omap4_tuna_input_init();
+ omap4_tuna_nfc_init();
+ omap4_tuna_power_init();
+ omap4_tuna_jack_init();
+ omap4_tuna_sensors_init();
+ omap4_tuna_led_init();
+ omap4_tuna_pogo_init();
+ omap4_tuna_connector_init();
+#ifdef CONFIG_OMAP_HSI_DEVICE
+ if (TUNA_TYPE_MAGURO == omap4_tuna_get_type())
+ omap_hsi_init();
+#endif
+#ifdef CONFIG_USB_EHCI_HCD_OMAP
+ if (TUNA_TYPE_TORO == omap4_tuna_get_type()) {
+#ifdef CONFIG_SEC_MODEM
+ modem_toro_init();
+#endif
+ omap4_ehci_init();
+ }
+#endif
+}
+
+static void __init tuna_map_io(void)
+{
+ omap2_set_globals_443x();
+ omap44xx_map_common_io();
+}
+
+static void __init tuna_reserve(void)
+{
+ int i;
+ int ret;
+
+ /* do the static reservations first */
+ memblock_remove(TUNA_RAMCONSOLE_START, TUNA_RAMCONSOLE_SIZE);
+ memblock_remove(PHYS_ADDR_SMC_MEM, PHYS_ADDR_SMC_SIZE);
+ memblock_remove(PHYS_ADDR_DUCATI_MEM, PHYS_ADDR_DUCATI_SIZE);
+
+ for (i = 0; i < tuna_ion_data.nr; i++)
+ if (tuna_ion_data.heaps[i].type == ION_HEAP_TYPE_CARVEOUT ||
+ tuna_ion_data.heaps[i].type == OMAP_ION_HEAP_TYPE_TILER) {
+ ret = memblock_remove(tuna_ion_data.heaps[i].base,
+ tuna_ion_data.heaps[i].size);
+ if (ret)
+ pr_err("memblock remove of %x@%lx failed\n",
+ tuna_ion_data.heaps[i].size,
+ tuna_ion_data.heaps[i].base);
+ }
+
+ /* ipu needs to recognize secure input buffer area as well */
+ omap_ipu_set_static_mempool(PHYS_ADDR_DUCATI_MEM, PHYS_ADDR_DUCATI_SIZE +
+ OMAP_TUNA_ION_HEAP_SECURE_INPUT_SIZE);
+ omap_reserve();
+}
+
+MACHINE_START(TUNA, "Tuna")
+ /* Maintainer: Google, Inc */
+ .boot_params = 0x80000100,
+ .reserve = tuna_reserve,
+ .map_io = tuna_map_io,
+ .init_early = tuna_init_early,
+ .init_irq = gic_init_irq,
+ .init_machine = tuna_init,
+ .timer = &omap_timer,
+MACHINE_END
diff --git a/arch/arm/mach-omap2/board-tuna.h b/arch/arm/mach-omap2/board-tuna.h
new file mode 100644
index 0000000..5f2ec1c
--- /dev/null
+++ b/arch/arm/mach-omap2/board-tuna.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2011 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ */
+
+#ifndef _MACH_OMAP2_BOARD_TUNA_H_
+#define _MACH_OMAP2_BOARD_TUNA_H_
+
+#define TUNA_REV_MASK 0xf
+#define TUNA_REV_03 0x3
+#define TUNA_REV_SAMPLE_4 0x3
+
+#define TUNA_TYPE_TORO 0x10
+#define TUNA_TYPE_MAGURO 0x00
+#define TUNA_TYPE_MASK 0x10
+
+#define TUNA_GPIO_HDMI_HPD 63
+
+int omap4_tuna_get_revision(void);
+int omap4_tuna_get_type(void);
+bool omap4_tuna_final_gpios(void);
+void omap4_tuna_display_init(void);
+void omap4_tuna_input_init(void);
+void omap4_tuna_jack_init(void);
+void omap4_tuna_nfc_init(void);
+void omap4_tuna_power_init(void);
+void omap4_tuna_sensors_init(void);
+void omap4_tuna_pogo_init(void);
+int omap4_tuna_connector_init(void);
+int tuna_wlan_init(void);
+int omap_hsi_init(void);
+void omap4_tuna_emif_init(void);
+void omap4_ehci_init(void);
+void modem_toro_init(void);
+
+extern struct mmc_platform_data tuna_wifi_data;
+extern struct class *sec_class;
+
+#endif
diff --git a/arch/arm/mach-omap2/dpll44xx.c b/arch/arm/mach-omap2/dpll44xx.c
index 94c9f64..a54bf6b 100644
--- a/arch/arm/mach-omap2/dpll44xx.c
+++ b/arch/arm/mach-omap2/dpll44xx.c
@@ -164,6 +164,12 @@ int omap4_prcm_freq_update(void)
if (i == MAX_FREQ_UPDATE_TIMEOUT) {
pr_err("%s: Frequency update failed (call from %pF)\n",
__func__, (void *)_RET_IP_);
+ pr_err("CLKCTRL: EMIF_1=0x%x EMIF_2=0x%x DMM=0x%x\n",
+ __raw_readl(OMAP4430_CM_MEMIF_EMIF_1_CLKCTRL),
+ __raw_readl(OMAP4430_CM_MEMIF_EMIF_2_CLKCTRL),
+ __raw_readl(OMAP4430_CM_MEMIF_DMM_CLKCTRL));
+ emif_dump(0);
+ emif_dump(1);
return -1;
}
diff --git a/arch/arm/mach-omap2/emif.c b/arch/arm/mach-omap2/emif.c
index f634083..4905ac4 100644
--- a/arch/arm/mach-omap2/emif.c
+++ b/arch/arm/mach-omap2/emif.c
@@ -60,6 +60,20 @@ static struct omap_device_pm_latency omap_emif_latency[] = {
},
};
+static u32 get_temperature_level(u32 emif_nr);
+
+void emif_dump(int emif_nr)
+{
+ void __iomem *base = emif[emif_nr].base;
+
+ printk("EMIF%d s=0x%x is_sys=0x%x is_ll=0x%x temp=0x%02x\n",
+ emif_nr + 1,
+ __raw_readl(base + OMAP44XX_EMIF_STATUS),
+ __raw_readl(base + OMAP44XX_EMIF_IRQSTATUS_SYS),
+ __raw_readl(base + OMAP44XX_EMIF_IRQSTATUS_LL),
+ get_temperature_level(emif_nr));
+}
+
static void do_cancel_out(u32 *num, u32 *den, u32 factor)
{
while (1) {
diff --git a/arch/arm/mach-omap2/include/mach/emif.h b/arch/arm/mach-omap2/include/mach/emif.h
index e6860b7..14d0eb7 100644
--- a/arch/arm/mach-omap2/include/mach/emif.h
+++ b/arch/arm/mach-omap2/include/mach/emif.h
@@ -286,4 +286,5 @@ int omap_emif_setup_device_details(
const struct emif_device_details *emif2_devices);
void emif_clear_irq(int emif_id);
+void emif_dump(int emif_nr);
#endif
diff --git a/arch/arm/mach-omap2/include/mach/omap4-common.h b/arch/arm/mach-omap2/include/mach/omap4-common.h
index 0489ebe..3c1b505 100644
--- a/arch/arm/mach-omap2/include/mach/omap4-common.h
+++ b/arch/arm/mach-omap2/include/mach/omap4-common.h
@@ -25,6 +25,7 @@
/*
* Secure HAL, PPA services available
*/
+#define PPA_SERVICE_0 0x21
#define PPA_SERVICE_PL310_POR 0x23
#define PPA_SERVICE_DEFAULT_POR_NS_SMP 0x25
/*
diff --git a/arch/arm/mach-omap2/include/mach/tf_mshield.h b/arch/arm/mach-omap2/include/mach/tf_mshield.h
new file mode 100644
index 0000000..52f98bf
--- /dev/null
+++ b/arch/arm/mach-omap2/include/mach/tf_mshield.h
@@ -0,0 +1,11 @@
+/**
+ * Copyright (c) 2010 Trusted Logic S.A.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifdef CONFIG_SECURITY_MIDDLEWARE_COMPONENT
+void tf_allocate_workspace(void);
+#endif
diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c
index b5c8e80..6694dfb 100644
--- a/arch/arm/mach-omap2/io.c
+++ b/arch/arm/mach-omap2/io.c
@@ -44,6 +44,7 @@
#include "clockdomain.h"
#include <plat/omap_hwmod.h>
#include <plat/multi.h>
+#include <mach/tf_mshield.h>
/*
* The machine specific code may provide the extra mapping besides the
@@ -251,6 +252,9 @@ static void __init _omap2_map_common_io(void)
omap2_check_revision();
omap_sram_init();
+#ifdef CONFIG_SECURITY_MIDDLEWARE_COMPONENT
+ tf_allocate_workspace();
+#endif
}
#ifdef CONFIG_SOC_OMAP2420
diff --git a/arch/arm/mach-omap2/omap-smp.c b/arch/arm/mach-omap2/omap-smp.c
index 4fbb782..a4aa753 100644
--- a/arch/arm/mach-omap2/omap-smp.c
+++ b/arch/arm/mach-omap2/omap-smp.c
@@ -45,7 +45,7 @@ void __cpuinit platform_secondary_init(unsigned int cpu)
{
/* Enable NS access to SMP bit for this CPU on HS devices */
if (cpu_is_omap443x() && (omap_type() != OMAP2_DEVICE_TYPE_GP))
- omap4_secure_dispatcher(PPA_SERVICE_DEFAULT_POR_NS_SMP, 4, 0, 0, 0, 0, 0);
+ omap4_secure_dispatcher(PPA_SERVICE_DEFAULT_POR_NS_SMP, FLAG_START_CRITICAL, 0, 0, 0, 0, 0);
/*
* If any interrupts are already enabled for the primary
diff --git a/arch/arm/mach-omap2/omap2plus-cpufreq.c b/arch/arm/mach-omap2/omap2plus-cpufreq.c
index 85a34a5..8264509 100644
--- a/arch/arm/mach-omap2/omap2plus-cpufreq.c
+++ b/arch/arm/mach-omap2/omap2plus-cpufreq.c
@@ -27,6 +27,7 @@
#include <linux/io.h>
#include <linux/opp.h>
#include <linux/cpu.h>
+#include <linux/earlysuspend.h>
#include <asm/system.h>
#include <asm/smp_plat.h>
@@ -58,8 +59,10 @@ static struct device *mpu_dev;
static DEFINE_MUTEX(omap_cpufreq_lock);
static unsigned int max_thermal;
+static unsigned int max_capped;
static unsigned int max_freq;
static unsigned int current_target_freq;
+static unsigned int screen_off_max_freq;
static bool omap_cpufreq_ready;
static unsigned int omap_getspeed(unsigned int cpu)
@@ -89,6 +92,9 @@ static int omap_cpufreq_scale(unsigned int target_freq, unsigned int cur_freq)
if (freqs.new > max_thermal)
freqs.new = max_thermal;
+ if (max_capped && freqs.new > max_capped)
+ freqs.new = max_capped;
+
if ((freqs.old == freqs.new) && (cur_freq = freqs.new))
return 0;
@@ -244,6 +250,46 @@ static int omap_target(struct cpufreq_policy *policy,
return ret;
}
+static void omap_cpu_early_suspend(struct early_suspend *h)
+{
+ unsigned int cur;
+
+ mutex_lock(&omap_cpufreq_lock);
+
+ if (screen_off_max_freq) {
+ max_capped = screen_off_max_freq;
+
+ cur = omap_getspeed(0);
+ if (cur > max_capped)
+ omap_cpufreq_scale(max_capped, cur);
+ }
+
+ mutex_unlock(&omap_cpufreq_lock);
+}
+
+static void omap_cpu_late_resume(struct early_suspend *h)
+{
+ unsigned int cur;
+
+ mutex_lock(&omap_cpufreq_lock);
+
+ if (max_capped) {
+ max_capped = 0;
+
+ cur = omap_getspeed(0);
+ if (cur != current_target_freq)
+ omap_cpufreq_scale(current_target_freq, cur);
+ }
+
+ mutex_unlock(&omap_cpufreq_lock);
+}
+
+static struct early_suspend omap_cpu_early_suspend_handler = {
+ .level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN,
+ .suspend = omap_cpu_early_suspend,
+ .resume = omap_cpu_late_resume,
+};
+
static inline void freq_table_free(void)
{
if (atomic_dec_and_test(&freq_table_users))
@@ -320,8 +366,52 @@ static int omap_cpu_exit(struct cpufreq_policy *policy)
return 0;
}
+static ssize_t show_screen_off_freq(struct cpufreq_policy *policy, char *buf)
+{
+ return sprintf(buf, "%u\n", screen_off_max_freq);
+}
+
+static ssize_t store_screen_off_freq(struct cpufreq_policy *policy,
+ const char *buf, size_t count)
+{
+ unsigned int freq = 0;
+ int ret;
+ int index;
+
+ if (!freq_table)
+ return -EINVAL;
+
+ ret = sscanf(buf, "%u", &freq);
+ if (ret != 1)
+ return -EINVAL;
+
+ mutex_lock(&omap_cpufreq_lock);
+
+ ret = cpufreq_frequency_table_target(policy, freq_table, freq,
+ CPUFREQ_RELATION_H, &index);
+ if (ret)
+ goto out;
+
+ screen_off_max_freq = freq_table[index].frequency;
+
+ ret = count;
+
+out:
+ mutex_unlock(&omap_cpufreq_lock);
+ return ret;
+}
+
+struct freq_attr omap_cpufreq_attr_screen_off_freq = {
+ .attr = { .name = "screen_off_max_freq",
+ .mode = 0644,
+ },
+ .show = show_screen_off_freq,
+ .store = store_screen_off_freq,
+};
+
static struct freq_attr *omap_cpufreq_attr[] = {
&cpufreq_freq_attr_scaling_available_freqs,
+ &omap_cpufreq_attr_screen_off_freq,
NULL,
};
@@ -360,6 +450,8 @@ static int __init omap_cpufreq_init(void)
return -EINVAL;
}
+ register_early_suspend(&omap_cpu_early_suspend_handler);
+
ret = cpufreq_register_driver(&omap_driver);
omap_cpufreq_ready = !ret;
return ret;
@@ -368,6 +460,8 @@ static int __init omap_cpufreq_init(void)
static void __exit omap_cpufreq_exit(void)
{
cpufreq_unregister_driver(&omap_driver);
+
+ unregister_early_suspend(&omap_cpu_early_suspend_handler);
}
MODULE_DESCRIPTION("cpufreq driver for OMAP2PLUS SOCs");
diff --git a/arch/arm/mach-omap2/omap4-common.c b/arch/arm/mach-omap2/omap4-common.c
index 9f040c8..b5775a5 100644
--- a/arch/arm/mach-omap2/omap4-common.c
+++ b/arch/arm/mach-omap2/omap4-common.c
@@ -273,6 +273,7 @@ static int __init omap_barriers_init(void)
}
core_initcall(omap_barriers_init);
+#ifndef CONFIG_SECURITY_MIDDLEWARE_COMPONENT
/*
* omap4_sec_dispatcher: Routine to dispatch low power secure
* service routines
@@ -323,3 +324,4 @@ u32 omap4_secure_dispatcher(u32 idx, u32 flag, u32 nargs, u32 arg1, u32 arg2,
return ret;
}
+#endif
diff --git a/arch/arm/mach-omap2/omap4-mpuss-lowpower.c b/arch/arm/mach-omap2/omap4-mpuss-lowpower.c
index c4855d9..4179e2e 100644
--- a/arch/arm/mach-omap2/omap4-mpuss-lowpower.c
+++ b/arch/arm/mach-omap2/omap4-mpuss-lowpower.c
@@ -586,7 +586,7 @@ cpu_prepare:
*/
wakeup_cpu = hard_smp_processor_id();
set_cpu_next_pwrst(wakeup_cpu, PWRDM_POWER_ON);
-
+ omap4_secure_dispatcher(PPA_SERVICE_0, FLAG_START_CRITICAL, 0, 0, 0, 0, 0);
if (cpu)
gic_restore_ppi();
@@ -625,7 +625,12 @@ cpu_prepare:
if ((omap4_device_prev_state_off()) &&
(omap_type() != OMAP2_DEVICE_TYPE_GP)) {
- omap4_secure_dispatcher(0x21, 4, 0, 0, 0, 0, 0);
+ /*
+ * Dummy dispatcher call after resuming from off mode.
+ * Restore the right return Kernel address (with MMU on) for subsequent
+ * calls to secure ROM after we have hit OFF.
+ */
+ omap4_secure_dispatcher(PPA_SERVICE_0, FLAG_START_CRITICAL, 0, 0, 0, 0, 0);
restore_ivahd_tesla_regs();
restore_l3instr_regs();
}
diff --git a/arch/arm/mach-omap2/omap_hsi.c b/arch/arm/mach-omap2/omap_hsi.c
index ce8fa54..87d8bcf 100644
--- a/arch/arm/mach-omap2/omap_hsi.c
+++ b/arch/arm/mach-omap2/omap_hsi.c
@@ -25,8 +25,6 @@
#include <linux/notifier.h>
#include <linux/hsi_driver_if.h>
-#include <asm/clkdev.h>
-
#include <plat/omap_hsi.h>
#include <plat/omap_hwmod.h>
#include <plat/omap_device.h>
@@ -35,6 +33,8 @@
#include "clock.h"
#include "mux.h"
#include "control.h"
+#include "pm.h"
+#include "dvfs.h"
static int omap_hsi_wakeup_enable(int hsi_port);
static int omap_hsi_wakeup_disable(int hsi_port);
@@ -42,8 +42,6 @@ static int omap_hsi_wakeup_disable(int hsi_port);
#define OMAP_HSI_PLATFORM_DEVICE_NAME "omap_hsi.0"
#define OMAP_HSI_HWMOD_NAME "hsi"
#define OMAP_HSI_HWMOD_CLASSNAME "hsi"
-#define OMAP_HSI_PADCONF_CAWAKE_PIN "usbb1_ulpitll_clk.hsi1_cawake"
-#define OMAP_HSI_PADCONF_CAWAKE_MODE OMAP_MUX_MODE1
#define OMAP_MUX_MODE_MASK 0x7
@@ -85,8 +83,9 @@ static int omap_mux_disable_wakeup(const char *muxname)
*/
-static struct port_ctx hsi_port_ctx[] = {
+static struct hsi_port_ctx omap_hsi_port_ctx[] = {
[0] = {
+ .port_number = 1,
.hst.mode = HSI_MODE_FRAME,
.hst.flow = HSI_FLOW_SYNCHRONIZED,
.hst.frame_size = HSI_FRAMESIZE_DEFAULT,
@@ -101,24 +100,28 @@ static struct port_ctx hsi_port_ctx[] = {
.hsr.counters = HSI_COUNTERS_FT_DEFAULT |
HSI_COUNTERS_TB_DEFAULT |
HSI_COUNTERS_FB_DEFAULT,
+ .cawake_padconf_name = "usbb1_ulpitll_clk.hsi1_cawake",
+ .cawake_padconf_hsi_mode = OMAP_MUX_MODE1,
},
};
-static struct ctrl_ctx hsi_ctx = {
+static struct hsi_ctrl_ctx omap_hsi_ctrl_ctx = {
.sysconfig = 0,
.gdd_gcr = 0,
.dll = 0,
- .pctx = hsi_port_ctx,
+ .pctx = omap_hsi_port_ctx,
};
static struct hsi_platform_data omap_hsi_platform_data = {
- .num_ports = ARRAY_SIZE(hsi_port_ctx),
+ .num_ports = ARRAY_SIZE(omap_hsi_port_ctx),
.hsi_gdd_chan_count = HSI_HSI_DMA_CHANNEL_MAX,
.default_hsi_fclk = HSI_DEFAULT_FCLK,
- .ctx = &hsi_ctx,
+ .fifo_mapping_strategy = HSI_FIFO_MAPPING_ALL_PORT1,
+ .ctx = &omap_hsi_ctrl_ctx,
.device_enable = omap_device_enable,
.device_idle = omap_device_idle,
.device_shutdown = omap_device_shutdown,
+ .device_scale = omap_device_scale,
.wakeup_enable = omap_hsi_wakeup_enable,
.wakeup_disable = omap_hsi_wakeup_disable,
.wakeup_is_from_hsi = omap_hsi_is_io_wakeup_from_hsi,
@@ -167,23 +170,49 @@ static struct hsi_dev *hsi_get_hsi_controller_data(struct platform_device *pd)
}
/**
+* hsi_get_hsi_port_ctx_data - Returns a pointer on the port context
+*
+* @hsi_port - port number to obtain context. Range [1, 2]
+*
+* Return value :* If success: pointer on the HSI port context requested
+* * else NULL
+*/
+static struct hsi_port_ctx *hsi_get_hsi_port_ctx_data(int hsi_port)
+{
+ int i;
+
+ for (i = 0; i < omap_hsi_platform_data.num_ports; i++)
+ if (omap_hsi_platform_data.ctx->pctx[i].port_number == hsi_port)
+ return &omap_hsi_platform_data.ctx->pctx[i];
+
+ return NULL;
+}
+
+/**
* omap_hsi_is_io_pad_hsi - Indicates if IO Pad has been muxed for HSI CAWAKE
*
+* @hsi_port - port number to check for HSI muxing. Range [1, 2]
+*
* Return value :* 0 if CAWAKE Padconf has not been found or CAWAKE not muxed for
* CAWAKE
* * else 1
*/
-static int omap_hsi_is_io_pad_hsi(void)
+static int omap_hsi_is_io_pad_hsi(int hsi_port)
{
+ struct hsi_port_ctx *port_ctx;
u16 val;
+ port_ctx = hsi_get_hsi_port_ctx_data(hsi_port);
+ if (!port_ctx)
+ return 0;
+
/* Check for IO pad */
- val = omap_mux_read_signal(OMAP_HSI_PADCONF_CAWAKE_PIN);
+ val = omap_mux_read_signal(port_ctx->cawake_padconf_name);
if (val == -ENODEV)
return 0;
/* Continue only if CAWAKE is muxed */
- if ((val & OMAP_MUX_MODE_MASK) != OMAP_HSI_PADCONF_CAWAKE_MODE)
+ if ((val & OMAP_MUX_MODE_MASK) != port_ctx->cawake_padconf_hsi_mode)
return 0;
return 1;
@@ -192,49 +221,66 @@ static int omap_hsi_is_io_pad_hsi(void)
/**
* omap_hsi_is_io_wakeup_from_hsi - Indicates an IO wakeup from HSI CAWAKE
*
-* Return value :* 0 if CAWAKE Padconf has not been found or no IOWAKEUP event
-* occured for CAWAKE
-* * else 1
-* TODO : return value should indicate the HSI port which has awaken
+* @hsi_port - returns port number which triggered wakeup. Range [1, 2].
+* Only valid if return value is 1 (HSI wakeup detected)
+*
+* Return value :* false if CAWAKE Padconf has not been found or no IOWAKEUP event
+* occured for CAWAKE.
+* * true if HSI wakeup detected on port *hsi_port
*/
-int omap_hsi_is_io_wakeup_from_hsi(void)
+bool omap_hsi_is_io_wakeup_from_hsi(int *hsi_port)
{
+ struct hsi_port_ctx *port_ctx;
u16 val;
+ int i;
+
+ for (i = 0; i < omap_hsi_platform_data.num_ports; i++) {
+ port_ctx = &omap_hsi_platform_data.ctx->pctx[i];
/* Check for IO pad wakeup */
- val = omap_mux_read_signal(OMAP_HSI_PADCONF_CAWAKE_PIN);
+ val = omap_mux_read_signal(port_ctx->cawake_padconf_name);
if (val == -ENODEV)
- return 0;
+ continue;
/* Continue only if CAWAKE is muxed */
- if ((val & OMAP_MUX_MODE_MASK) != OMAP_HSI_PADCONF_CAWAKE_MODE)
- return 0;
+ if ((val & OMAP_MUX_MODE_MASK) !=
+ port_ctx->cawake_padconf_hsi_mode)
+ continue;
+
+ if (val & OMAP44XX_PADCONF_WAKEUPEVENT0) {
+ *hsi_port = port_ctx->port_number;
+ return true;
+ }
+ }
- if (val & OMAP44XX_PADCONF_WAKEUPEVENT0)
- return 1;
+ *hsi_port = 0;
- return 0;
+ return false;
}
/**
* omap_hsi_wakeup_enable - Enable HSI wakeup feature from RET/OFF mode
*
* @hsi_port - reference to the HSI port onto which enable wakeup feature.
+* Range [1, 2]
*
* Return value :* 0 if CAWAKE has been configured to wakeup platform
* * -ENODEV if CAWAKE is not muxed on padconf
*/
static int omap_hsi_wakeup_enable(int hsi_port)
{
+ struct hsi_port_ctx *port_ctx;
int ret = -ENODEV;
- if (omap_hsi_is_io_pad_hsi())
- ret = omap_mux_enable_wakeup(OMAP_HSI_PADCONF_CAWAKE_PIN);
- else
- pr_debug("Trying to enable HSI IO wakeup on non HSI board\n");
-
+ if (omap_hsi_is_io_pad_hsi(hsi_port)) {
+ port_ctx = hsi_get_hsi_port_ctx_data(hsi_port);
+ ret = omap_mux_enable_wakeup(port_ctx->cawake_padconf_name);
+ omap4_trigger_ioctrl();
+ } else {
+ pr_debug("HSI port %d not muxed, failed to enable IO wakeup\n",
+ hsi_port);
+ }
- /* TODO: handle hsi_port param and use it to find the correct Pad */
return ret;
}
@@ -242,21 +288,24 @@ static int omap_hsi_wakeup_enable(int hsi_port)
* omap_hsi_wakeup_disable - Disable HSI wakeup feature from RET/OFF mode
*
* @hsi_port - reference to the HSI port onto which disable wakeup feature.
+* Range [1, 2]
*
* Return value :* 0 if CAWAKE has been configured to not wakeup platform
* * -ENODEV if CAWAKE is not muxed on padconf
*/
static int omap_hsi_wakeup_disable(int hsi_port)
{
+ struct hsi_port_ctx *port_ctx;
int ret = -ENODEV;
- if (omap_hsi_is_io_pad_hsi())
- ret = omap_mux_disable_wakeup(OMAP_HSI_PADCONF_CAWAKE_PIN);
- else
- pr_debug("Trying to disable HSI IO wakeup on non HSI board\n");
-
-
- /* TODO: handle hsi_port param and use it to find the correct Pad */
+ if (omap_hsi_is_io_pad_hsi(hsi_port)) {
+ port_ctx = hsi_get_hsi_port_ctx_data(hsi_port);
+ ret = omap_mux_disable_wakeup(port_ctx->cawake_padconf_name);
+ omap4_trigger_ioctrl();
+ } else {
+ pr_debug("HSI port %d not muxed, failed to disable IO wakeup\n",
+ hsi_port);
+ }
return ret;
}
@@ -264,6 +313,9 @@ static int omap_hsi_wakeup_disable(int hsi_port)
/**
* omap_hsi_prepare_suspend - Prepare HSI for suspend mode
*
+* @hsi_port - reference to the HSI port. Range [1, 2]
+* @dev_may_wakeup - value of sysfs flag indicating device wakeup capability
+*
* Return value :* 0 if CAWAKE padconf has been configured properly
* * -ENODEV if CAWAKE is not muxed on padconf.
*
@@ -281,42 +333,79 @@ int omap_hsi_prepare_suspend(int hsi_port, bool dev_may_wakeup)
}
/**
+* omap_hsi_io_wakeup_check - Check if IO wakeup is from HSI and schedule HSI
+* processing tasklet
+*
+* Return value : * 0 if HSI tasklet scheduled.
+* * negative value else.
+*/
+int omap_hsi_io_wakeup_check(void)
+{
+ int hsi_port, ret = -1;
+
+ /* Modem HSI wakeup */
+ if (omap_hsi_is_io_wakeup_from_hsi(&hsi_port))
+ ret = omap_hsi_wakeup(hsi_port);
+
+ return ret;
+}
+
+/**
* omap_hsi_wakeup - Prepare HSI for wakeup from suspend mode (RET/OFF)
*
-* Return value : 1 if IO wakeup source is HSI
-* 0 if IO wakeup source is not HSI.
+* @hsi_port - reference to the HSI port which triggered wakeup.
+* Range [1, 2]
+*
+* Return value : * 0 if HSI tasklet scheduled.
+* * negative value else.
*/
int omap_hsi_wakeup(int hsi_port)
{
static struct platform_device *pdev;
static struct hsi_dev *hsi_ctrl;
+ int i;
if (!pdev) {
- pdev = hsi_get_hsi_platform_device();
+ pdev = hsi_get_hsi_platform_device();
if (!pdev)
- return -ENODEV;
-}
+ return -ENODEV;
+ }
if (!device_may_wakeup(&pdev->dev)) {
- dev_info(&pdev->dev, "Modem not allowed to wakeup platform");
+ dev_info(&pdev->dev, "Modem not allowed to wakeup platform\n");
return -EPERM;
}
if (!hsi_ctrl) {
- hsi_ctrl = hsi_get_hsi_controller_data(pdev);
- if (!hsi_ctrl)
- return -ENODEV;
+ hsi_ctrl = hsi_get_hsi_controller_data(pdev);
+ if (!hsi_ctrl)
+ return -ENODEV;
}
- dev_dbg(hsi_ctrl->dev, "Modem wakeup detected from HSI CAWAKE Pad");
+ for (i = 0; i < omap_hsi_platform_data.num_ports; i++) {
+ if (omap_hsi_platform_data.ctx->pctx[i].port_number == hsi_port)
+ break;
+ }
+
+ if (i == omap_hsi_platform_data.num_ports)
+ return -ENODEV;
+
+
+ /* Check no other interrupt handler has already scheduled the tasklet */
+ if (test_and_set_bit(HSI_FLAGS_TASKLET_LOCK,
+ &hsi_ctrl->hsi_port[i].flags))
+ return -EBUSY;
+
+ dev_dbg(hsi_ctrl->dev, "Modem wakeup detected from HSI CAWAKE Pad port "
+ "%d\n", hsi_port);
/* CAWAKE falling or rising edge detected */
- hsi_ctrl->hsi_port->cawake_off_event = true;
- tasklet_hi_schedule(&hsi_ctrl->hsi_port->hsi_tasklet);
+ hsi_ctrl->hsi_port[i].cawake_off_event = true;
+ tasklet_hi_schedule(&hsi_ctrl->hsi_port[i].hsi_tasklet);
/* Disable interrupt until Bottom Half has cleared */
/* the IRQ status register */
- disable_irq_nosync(hsi_ctrl->hsi_port->irq);
+ disable_irq_nosync(hsi_ctrl->hsi_port[i].irq);
return 0;
}
diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
index 12f729d..8c5bb89 100644
--- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
@@ -1059,7 +1059,7 @@ static struct omap_hwmod_class omap44xx_ctrl_module_hwmod_class = {
static struct omap_hwmod omap44xx_ctrl_module_core_hwmod;
static struct omap_hwmod_irq_info omap44xx_ctrl_module_core_irqs[] = {
{ .name = "sec_evts", .irq = 8 + OMAP44XX_IRQ_GIC_START },
- { .name = "thermal_alert", .irq = 126 + OMAP44XX_IRQ_GIC_START },
+ { .name = "thermal_alert", .irq = 127 + OMAP44XX_IRQ_GIC_START },
};
static struct omap_hwmod_addr_space omap44xx_ctrl_module_core_addrs[] = {
@@ -1106,7 +1106,7 @@ static struct omap_hwmod_class omap44xx_thermal_sensor_hwmod_class = {
};
static struct omap_hwmod_irq_info omap44xx_thermal_sensor_irqs[] = {
- { .name = "thermal_alert", .irq = 126 + OMAP44XX_IRQ_GIC_START },
+ { .name = "thermal_alert", .irq = 127 + OMAP44XX_IRQ_GIC_START },
};
static struct omap_hwmod_addr_space omap44xx_thermal_sensor_addrs[] = {
diff --git a/arch/arm/mach-omap2/omap_l3_noc.c b/arch/arm/mach-omap2/omap_l3_noc.c
index 9d152de..b90bfb0 100644
--- a/arch/arm/mach-omap2/omap_l3_noc.c
+++ b/arch/arm/mach-omap2/omap_l3_noc.c
@@ -28,11 +28,14 @@
#include <linux/slab.h>
#include "omap_l3_noc.h"
+#include "board-tuna.h"
#define NUM_OF_L3_MASTERS ARRAY_SIZE(l3_masters)
static void l3_dump_targ_context(u32 baseaddr)
{
+ extern void print_async_list(void);
+
pr_err("COREREG : 0x%08x\n", readl(baseaddr + L3_COREREG));
pr_err("VERSIONREG : 0x%08x\n", readl(baseaddr + L3_VERSIONREG));
pr_err("MAINCTLREG : 0x%08x\n", readl(baseaddr + L3_MAINCTLREG));
@@ -50,6 +53,12 @@ static void l3_dump_targ_context(u32 baseaddr)
pr_err("CUSTOMINFO_MSTADDR: 0x%08x\n", readl(baseaddr + L3_CUSTOMINFO_MSTADDR));
pr_err("CUSTOMINFO_OPCODE : 0x%08x\n", readl(baseaddr + L3_CUSTOMINFO_OPCODE));
pr_err("ADDRSPACESIZELOG : 0x%08x\n", readl(baseaddr + L3_ADDRSPACESIZELOG));
+
+ /* Identified as USBHOST EHCI error */
+ if ((readl(baseaddr + L3_MSTADDR) == 0xc0) &&
+ (readl(baseaddr + L3_SLVADDR) == 0x3))
+ if (omap4_tuna_get_type() == TUNA_TYPE_TORO)
+ print_async_list();
}
/*
diff --git a/arch/arm/mach-omap2/opp4xxx_data.c b/arch/arm/mach-omap2/opp4xxx_data.c
index 255f132..c0fd100 100644
--- a/arch/arm/mach-omap2/opp4xxx_data.c
+++ b/arch/arm/mach-omap2/opp4xxx_data.c
@@ -324,8 +324,9 @@ int __init omap4_opp_init(void)
if (!r) {
if (omap4_has_mpu_1_2ghz())
omap4_mpu_opp_enable(1200000000);
- if (omap4_has_mpu_1_5ghz())
- omap4_mpu_opp_enable(1500000000);
+ /* The tuna PCB doesn't support 1.5GHz, so disable it for now */
+ /*if (omap4_has_mpu_1_5ghz())
+ omap4_mpu_opp_enable(1500000000);*/
}
return r;
diff --git a/arch/arm/mach-omap2/pm44xx.c b/arch/arm/mach-omap2/pm44xx.c
index 6cfd501..7025e3a 100644
--- a/arch/arm/mach-omap2/pm44xx.c
+++ b/arch/arm/mach-omap2/pm44xx.c
@@ -76,8 +76,15 @@ static struct powerdomain *tesla_pwrdm;
/* Yet un-named erratum which requires AUTORET to be disabled for IVA PD */
#define OMAP4_PM_ERRATUM_IVA_AUTO_RET_iXXX BIT(1)
+/*
+* HSI - OMAP4430-2.2BUG00055:
+* HSI: DSP Swakeup generated is the same than MPU Swakeup.
+* System can’t enter in off mode due to the DSP.
+*/
+#define OMAP4_PM_ERRATUM_HSI_SWAKEUP_iXXX BIT(2)
+
-static u8 pm44xx_errata;
+u8 pm44xx_errata;
#define is_pm44xx_erratum(erratum) (pm44xx_errata & OMAP4_PM_ERRATUM_##erratum)
#define MAX_IOPAD_LATCH_TIME 1000
@@ -872,7 +879,7 @@ static void __init prcm_setup_regs(void)
*
* Bug ref is HSI-C1BUG00106 : dsp swakeup generated by HSI same as mpu swakeup
*/
-static void omap_pm_clear_dsp_wake_up(void)
+void omap_pm_clear_dsp_wake_up(void)
{
int ret;
int timeout = 10;
@@ -927,6 +934,7 @@ static void omap_pm_clear_dsp_wake_up(void)
static irqreturn_t prcm_interrupt_handler (int irq, void *dev_id)
{
u32 irqenable_mpu, irqstatus_mpu;
+ int hsi_port;
irqenable_mpu = omap4_prm_read_inst_reg(OMAP4430_PRM_OCP_SOCKET_INST,
OMAP4_PRM_IRQENABLE_MPU_OFFSET);
@@ -936,9 +944,8 @@ static irqreturn_t prcm_interrupt_handler (int irq, void *dev_id)
/* Check if a IO_ST interrupt */
if (irqstatus_mpu & OMAP4430_IO_ST_MASK) {
/* Check if HSI caused the IO wakeup */
- if (omap_hsi_is_io_wakeup_from_hsi()) {
- omap_pm_clear_dsp_wake_up();
- omap_hsi_wakeup(0);
+ if (omap_hsi_is_io_wakeup_from_hsi(&hsi_port)) {
+ omap_hsi_wakeup(hsi_port);
}
omap_uart_resume_idle();
usbhs_wakeup();
@@ -1044,7 +1051,8 @@ static void __init omap4_pm_setup_errata(void)
* all OMAP4 silica
*/
if (cpu_is_omap44xx())
- pm44xx_errata |= OMAP4_PM_ERRATUM_IVA_AUTO_RET_iXXX;
+ pm44xx_errata |= OMAP4_PM_ERRATUM_IVA_AUTO_RET_iXXX |
+ OMAP4_PM_ERRATUM_HSI_SWAKEUP_iXXX;
}
/**
diff --git a/arch/arm/plat-omap/include/plat/board-tuna-bluetooth.h b/arch/arm/plat-omap/include/plat/board-tuna-bluetooth.h
new file mode 100644
index 0000000..c74de05
--- /dev/null
+++ b/arch/arm/plat-omap/include/plat/board-tuna-bluetooth.h
@@ -0,0 +1,30 @@
+/*
+ * Bluetooth Broadcomm and low power control via GPIO
+ *
+ * Copyright (C) 2011 Samsung, Inc.
+ * Copyright (C) 2011 Google, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#ifndef __BOARD_TUNA_BLUETOOTH_H__
+#define __BOARD_TUNA_BLUETOOTH_H__
+
+#include <linux/serial_core.h>
+
+extern void bcm_bt_lpm_exit_lpm_locked(struct uart_port *uport);
+
+#endif /* __BOARD_TUNA_BLUETOOTH_H__ */
diff --git a/arch/arm/plat-omap/include/plat/omap_hsi.h b/arch/arm/plat-omap/include/plat/omap_hsi.h
index 1a75ed4..ba2c8e3 100644
--- a/arch/arm/plat-omap/include/plat/omap_hsi.h
+++ b/arch/arm/plat-omap/include/plat/omap_hsi.h
@@ -259,6 +259,11 @@
#define HSI_HSR_ERROR_TBE (1 << 4) /* HSI only */
#define HSI_HSR_ERROR_RME (1 << 7) /* HSI only */
#define HSI_HSR_ERROR_TME (1 << 11) /* HSI only */
+#define HSI_HSR_ERROR_ALL (HSI_HSR_ERROR_SIG | \
+ HSI_HSR_ERROR_FTE | \
+ HSI_HSR_ERROR_TBE | \
+ HSI_HSR_ERROR_RME | \
+ HSI_HSR_ERROR_TME)
#define HSI_HSR_ERRORACK_REG(port) (HSI_HSR_BASE(port) + 0x0024)
@@ -479,16 +484,15 @@ extern int omap_hsi_config(struct omap_hsi_board_config *hsi_config);
#ifdef CONFIG_OMAP_HSI
extern int omap_hsi_prepare_suspend(int hsi_port, bool dev_may_wakeup);
-extern int omap_hsi_prepare_idle(void);
+extern int omap_hsi_io_wakeup_check(void);
extern int omap_hsi_wakeup(int hsi_port);
-extern int omap_hsi_is_io_wakeup_from_hsi(void);
+extern bool omap_hsi_is_io_wakeup_from_hsi(int *hsi_port);
#else
inline int omap_hsi_prepare_suspend(int hsi_port,
bool dev_may_wakeup) { return -ENOSYS; }
-inline int omap_hsi_prepare_idle(void) { return -ENOSYS; }
+inline int omap_hsi_io_wakeup_check(void) { return -ENOSYS; }
inline int omap_hsi_wakeup(int hsi_port) { return -ENOSYS; }
-inline int omap_hsi_is_io_wakeup_from_hsi(void) { return -ENOSYS; }
-
+inline bool omap_hsi_is_io_wakeup_from_hsi(int *hsi_port) { return false; }
#endif
#endif /* __OMAP_HSI_H__ */
diff --git a/arch/arm/plat-omap/include/plat/uncompress.h b/arch/arm/plat-omap/include/plat/uncompress.h
index ac4b60d..cf07178 100644
--- a/arch/arm/plat-omap/include/plat/uncompress.h
+++ b/arch/arm/plat-omap/include/plat/uncompress.h
@@ -164,6 +164,7 @@ static inline void __arch_decomp_setup(unsigned long arch_id)
/* omap4 based boards using UART3 */
DEBUG_LL_OMAP4(3, omap_4430sdp);
DEBUG_LL_OMAP4(3, omap4_panda);
+ DEBUG_LL_OMAP4(3, tuna);
/* zoom2/3 external uart */
DEBUG_LL_ZOOM(omap_zoom2);