aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-omap2
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-omap2')
-rw-r--r--arch/arm/mach-omap2/Kconfig9
-rw-r--r--arch/arm/mach-omap2/Makefile13
-rw-r--r--arch/arm/mach-omap2/board-4430sdp.c2
-rw-r--r--arch/arm/mach-omap2/board-omap4panda.c7
-rw-r--r--arch/arm/mach-omap2/board-tuna-bluetooth.c295
-rw-r--r--arch/arm/mach-omap2/board-tuna-display.c304
-rw-r--r--arch/arm/mach-omap2/board-tuna-emif.c107
-rw-r--r--arch/arm/mach-omap2/board-tuna-input.c210
-rwxr-xr-xarch/arm/mach-omap2/board-tuna-modems.c631
-rw-r--r--arch/arm/mach-omap2/board-tuna-nfc.c112
-rw-r--r--arch/arm/mach-omap2/board-tuna-power.c158
-rwxr-xr-xarch/arm/mach-omap2/board-tuna-sensors.c171
-rw-r--r--arch/arm/mach-omap2/board-tuna-wifi.c367
-rwxr-xr-xarch/arm/mach-omap2/board-tuna.c889
-rw-r--r--arch/arm/mach-omap2/board-tuna.h39
-rw-r--r--arch/arm/mach-omap2/omap_hsi.c418
-rw-r--r--arch/arm/mach-omap2/omap_hwmod_44xx_data.c4
-rw-r--r--arch/arm/mach-omap2/opp4xxx_data.c10
-rw-r--r--arch/arm/mach-omap2/pm44xx.c15
19 files changed, 3749 insertions, 12 deletions
diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig
index 177771b..05b559f 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 7ef7745..be6213e 100644
--- a/arch/arm/mach-omap2/Makefile
+++ b/arch/arm/mach-omap2/Makefile
@@ -249,6 +249,17 @@ 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-nfc.o
+obj-$(CONFIG_MACH_TUNA) += board-tuna-power.o
+obj-$(CONFIG_MACH_TUNA) += board-tuna-sensors.o
+obj-$(CONFIG_MACH_TUNA) += board-tuna-wifi.o
+obj-$(CONFIG_MACH_TUNA) += board-tuna-bluetooth.o \
+ board-tuna-emif.o
obj-$(CONFIG_MACH_OMAP3517EVM) += board-am3517evm.o \
omap_phy_internal.o \
@@ -286,3 +297,5 @@ obj-y += $(disp-m) $(disp-y)
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
diff --git a/arch/arm/mach-omap2/board-4430sdp.c b/arch/arm/mach-omap2/board-4430sdp.c
index eadd153..76adaa7 100644
--- a/arch/arm/mach-omap2/board-4430sdp.c
+++ b/arch/arm/mach-omap2/board-4430sdp.c
@@ -843,7 +843,7 @@ static __initdata struct emif_device_details emif_devices = {
.cs1_device = &lpddr2_elpida_2G_S4_dev
};
-static inline void board_serial_init(void)
+static inline void __init board_serial_init(void)
{
struct omap_board_data bdata;
bdata.flags = 0;
diff --git a/arch/arm/mach-omap2/board-omap4panda.c b/arch/arm/mach-omap2/board-omap4panda.c
index d236f82..ff80bd4 100644
--- a/arch/arm/mach-omap2/board-omap4panda.c
+++ b/arch/arm/mach-omap2/board-omap4panda.c
@@ -572,7 +572,7 @@ static struct omap_board_data serial4_data __initdata = {
.pads_cnt = ARRAY_SIZE(serial4_pads),
};
-static inline void board_serial_init(void)
+static inline void __init board_serial_init(void)
{
struct omap_board_data bdata;
bdata.flags = 0;
@@ -589,7 +589,7 @@ static inline void board_serial_init(void)
#else
#define board_mux NULL
-static inline void board_serial_init(void)
+static inline void __init board_serial_init(void)
{
omap_serial_init();
}
@@ -726,8 +726,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;
@@ -757,7 +755,6 @@ static void __init omap4_panda_init(void)
usb_musb_init(&musb_board_data);
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..ec58454
--- /dev/null
+++ b/arch/arm/mach-omap2/board-tuna-bluetooth.c
@@ -0,0 +1,295 @@
+/*
+ * 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/serial_core.h>
+#include <linux/wakelock.h>
+#include <asm/mach-types.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;
+
+struct bcm_bt_lpm {
+ int wake;
+ int host_wake;
+ bool rx_wake_lock_taken;
+
+ 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) {
+ 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);
+ }
+
+ 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);
+
+void bcm_bt_rx_done_locked(struct uart_port *uport) {
+ if (bt_lpm.host_wake) {
+ // Release wake in 500 ms so that higher layers can take it.
+ wake_lock_timeout(&bt_lpm.wake_lock, HZ/2);
+ bt_lpm.rx_wake_lock_taken = true;
+ }
+}
+EXPORT_SYMBOL(bcm_bt_rx_done_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) {
+ bt_lpm.rx_wake_lock_taken = false;
+ wake_lock(&bt_lpm.wake_lock);
+ } else if (!bt_lpm.rx_wake_lock_taken) {
+ // Failsafe timeout of wakelock.
+ // If the host wake pin is asserted and no data is sent,
+ // when its deasserted we will enter this path
+ 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;
+
+ 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;
+ }
+
+ 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);
+
+ 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)
+{
+ 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-display.c b/arch/arm/mach-omap2/board-tuna-display.c
new file mode 100644
index 0000000..3baf2c4
--- /dev/null
+++ b/arch/arm/mach-omap2/board-tuna-display.c
@@ -0,0 +1,304 @@
+/* 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_LUNCHBOX 35
+#define TUNA_GPIO_MLCD_RST 23
+
+static struct panel_generic_dpi_data tuna_lcd_panel = {
+ .name = "samsung_ams452gn05",
+ .platform_enable = NULL,
+ .platform_disable = NULL,
+};
+
+static struct omap_dss_device tuna_lcd_device = {
+ .name = "lcd",
+ .driver_name = "generic_dpi_panel",
+ .type = OMAP_DISPLAY_TYPE_DPI,
+ .channel = OMAP_DSS_CHANNEL_LCD2,
+ .data = &tuna_lcd_panel,
+ .phy.dpi.data_lines = 24,
+};
+
+struct regulator *tuna_oled_reg;
+
+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 (enable)
+ regulator_enable(tuna_oled_reg);
+ else
+ regulator_disable(tuna_oled_reg);
+}
+
+static const struct s6e8aa0_gamma_entry tuna_oled_gamma_table[] = {
+ { BV_0, { 4500000, 4500000, 4500000, }, },
+ { 1, { 4294200, 4407600, 4210200, }, },
+ { 0x00000400, { 3969486, 4038030, 3955093, }, },
+ { 0x000004C2, { 3964456, 4032059, 3949872, }, },
+ { 0x000005A8, { 3959356, 4026019, 3944574, }, },
+ { 0x000006BA, { 3954160, 4019879, 3939171, }, },
+ { 0x00000800, { 3948872, 4013646, 3933668, }, },
+ { 0x00000983, { 3943502, 4007331, 3928075, }, },
+ { 0x00000B50, { 3938029, 4000909, 3922368, }, },
+ { 0x00000D74, { 3932461, 3994392, 3916558, }, },
+ { 0x00001000, { 3926792, 3987772, 3910636, }, },
+ { 0x00001307, { 3921022, 3981052, 3904605, }, },
+ { 0x000016A1, { 3915146, 3974224, 3898455, }, },
+ { 0x00001AE9, { 3909163, 3967289, 3892189, }, },
+ { 0x00002000, { 3903070, 3960245, 3885801, }, },
+ { 0x0000260E, { 3896860, 3953083, 3879284, }, },
+ { 0x00002D41, { 3890532, 3945805, 3872637, }, },
+ { 0x000035D1, { 3884081, 3938403, 3865854, }, },
+ { 0x00004000, { 3877504, 3930876, 3858930, }, },
+ { 0x00004C1C, { 3870797, 3923221, 3851863, }, },
+ { 0x00005A82, { 3863956, 3915434, 3844649, }, },
+ { 0x00006BA2, { 3856976, 3907510, 3837279, }, },
+ { 0x00008000, { 3849853, 3899444, 3829750, }, },
+ { 0x00009838, { 3842582, 3891234, 3822056, }, },
+ { 0x0000B505, { 3835159, 3882874, 3814193, }, },
+ { 0x0000D745, { 3827577, 3874360, 3806153, }, },
+ { 0x00010000, { 3819832, 3865687, 3797931, }, },
+ { 0x00013070, { 3811918, 3856849, 3789519, }, },
+ { 0x00016A0A, { 3803829, 3847842, 3780912, }, },
+ { 0x0001AE8A, { 3795559, 3838659, 3772102, }, },
+ { 0x00020000, { 3787101, 3829295, 3763080, }, },
+ { 0x000260E0, { 3778447, 3819742, 3753839, }, },
+ { 0x0002D414, { 3769592, 3809996, 3744372, }, },
+ { 0x00035D14, { 3760527, 3800049, 3734667, }, },
+ { 0x00040000, { 3751244, 3789893, 3724717, }, },
+ { 0x0004C1C0, { 3741734, 3779522, 3714512, }, },
+ { 0x0005A828, { 3731990, 3768927, 3704040, }, },
+ { 0x0006BA28, { 3722000, 3758099, 3693292, }, },
+ { 0x00080000, { 3711756, 3747030, 3682254, }, },
+ { 0x0009837F, { 3701247, 3735711, 3670915, }, },
+ { 0x000B504F, { 3690462, 3724131, 3659262, }, },
+ { 0x000D7450, { 3679388, 3712280, 3647281, }, },
+ { 0x00100000, { 3668014, 3700147, 3634957, }, },
+ { 0x001306FE, { 3656325, 3687721, 3622274, }, },
+ { 0x0016A09E, { 3644309, 3674988, 3609216, }, },
+ { 0x001AE8A0, { 3631950, 3661936, 3595765, }, },
+ { 0x00200000, { 3619231, 3648550, 3581902, }, },
+ { 0x00260DFC, { 3606137, 3634817, 3567607, }, },
+ { 0x002D413D, { 3592649, 3620719, 3552859, }, },
+ { 0x0035D13F, { 3578748, 3606240, 3537634, }, },
+ { 0x00400000, { 3564413, 3591361, 3521908, }, },
+ { 0x004C1BF8, { 3549622, 3576065, 3505654, }, },
+ { 0x005A827A, { 3534351, 3560329, 3488845, }, },
+ { 0x006BA27E, { 3518576, 3544131, 3471449, }, },
+ { 0x00800000, { 3502268, 3527448, 3453434, }, },
+ { 0x009837F0, { 3485399, 3510255, 3434765, }, },
+ { 0x00B504F3, { 3467936, 3492523, 3415404, }, },
+ { 0x00D744FD, { 3449847, 3474223, 3395308, }, },
+ { 0x01000000, { 3431093, 3455322, 3374435, }, },
+ { 0x01306FE1, { 3411635, 3435786, 3352735, }, },
+ { 0x016A09E6, { 3391431, 3415578, 3330156, }, },
+ { 0x01AE89FA, { 3370432, 3394655, 3306641, }, },
+ { 0x02000000, { 3348587, 3372974, 3282127, }, },
+ { 0x0260DFC1, { 3325842, 3350485, 3256547, }, },
+ { 0x02D413CD, { 3302134, 3327135, 3229824, }, },
+ { 0x035D13F3, { 3277397, 3302865, 3201879, }, },
+ { 0x04000000, { 3251558, 3277611, 3172620, }, },
+ { 0x04C1BF83, { 3224535, 3251302, 3141948, }, },
+ { 0x05A8279A, { 3196240, 3223858, 3109753, }, },
+ { 0x06BA27E6, { 3166574, 3195192, 3075914, }, },
+ { 0x08000000, { 3135426, 3165207, 3040295, }, },
+ { 0x09837F05, { 3102676, 3133793, 3002744, }, },
+ { 0x0B504F33, { 3068187, 3100829, 2963094, }, },
+ { 0x0D744FCD, { 3031806, 3066175, 2921155, }, },
+ { 0x10000000, { 2993361, 3029675, 2876712, }, },
+ { 0x1306FE0A, { 2952659, 2991153, 2829527, }, },
+ { 0x16A09E66, { 2909480, 2950402, 2779324, }, },
+ { 0x1AE89F99, { 2863575, 2907191, 2725793, }, },
+ { 0x20000000, { 2814655, 2861246, 2668579, }, },
+ { 0x260DFC14, { 2762394, 2812251, 2607272, }, },
+ { 0x2D413CCD, { 2706412, 2759834, 2541403, }, },
+ { 0x35D13F32, { 2646266, 2703554, 2470425, }, },
+ { 0x40000000, { 2581441, 2642883, 2393706, }, },
+ { 0x4C1BF828, { 2511332, 2577183, 2310504, }, },
+ { 0x5A82799A, { 2435220, 2505675, 2219951, }, },
+ { 0x6BA27E65, { 2352250, 2427391, 2121028, }, },
+ { 0x80000000, { 2261395, 2341114, 2012536, }, },
+ { 0x9837F051, { 2161415, 2245288, 1893066, }, },
+ { 0xB504F333, { 2050800, 2137874, 1760986, }, },
+ { 0xD744FCCA, { 1927706, 2016150, 1614437, }, },
+ { 0xFFFFFFFF, { 1789879, 1876363, 1451415, }, },
+};
+
+static struct panel_s6e8aa0_data tuna_oled_data = {
+ .reset_gpio = TUNA_GPIO_MLCD_RST,
+ .set_power = tuna_oled_set_power,
+ .gamma_table = tuna_oled_gamma_table,
+ .gamma_table_size = ARRAY_SIZE(tuna_oled_gamma_table),
+ .factory_v255_regs = {
+ 0x084,
+ 0x083,
+ 0x0b7,
+ },
+};
+
+/* width: 58mm */
+/* height: 102mm */
+static struct omap_dss_device tuna_oled_device = {
+ .name = "lcd",
+ .driver_name = "s6e8aa0",
+ .type = OMAP_DISPLAY_TYPE_DSI,
+ .data = &tuna_oled_data,
+ .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,
+ },
+ .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 = 240, /* DSI_PLL_REGM */
+
+ .regm_dispc = 6, /* PLL_CLK1 (M4) */
+ .regm_dsi = 6, /* PLL_CLK2 (M5) */
+ .lp_clk_div = 14, /* LPDIV */
+
+ .dsi_fclk_src = OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI,
+ },
+ },
+
+ .channel = OMAP_DSS_CHANNEL_LCD,
+};
+
+
+static struct omap_dss_device *tuna_dss_devices[] = {
+ &tuna_oled_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 omap_dss_device *prelunchbox_dss_devices[] = {
+ &tuna_lcd_device,
+};
+
+static struct omap_dss_board_info prelunchbox_dss_data = {
+ .num_devices = ARRAY_SIZE(prelunchbox_dss_devices),
+ .devices = prelunchbox_dss_devices,
+ .default_device = &tuna_lcd_device,
+};
+
+static struct omapfb_platform_data tuna_fb_pdata = {
+ .mem_desc = {
+ .region_cnt = 1,
+ .region = {
+ [0] = {
+ .size = TUNA_FB_RAM_SIZE,
+ },
+ },
+ },
+};
+
+#define MUX_DISPLAY_OUT OMAP_PIN_OUTPUT | OMAP_MUX_MODE5
+void __init omap4_tuna_display_init(void)
+{
+ struct omap_dss_board_info *dss_data;
+
+ if (omap4_tuna_get_revision() == TUNA_REV_PRE_LUNCHBOX) {
+ /* dispc2_data23 - dispc2_data0 */
+ omap_mux_init_signal("usbb2_ulpitll_stp", MUX_DISPLAY_OUT);
+ omap_mux_init_signal("usbb2_ulpitll_dir", MUX_DISPLAY_OUT);
+ omap_mux_init_signal("usbb2_ulpitll_nxt", MUX_DISPLAY_OUT);
+ omap_mux_init_signal("usbb2_ulpitll_dat0", MUX_DISPLAY_OUT);
+ omap_mux_init_signal("usbb2_ulpitll_dat1", MUX_DISPLAY_OUT);
+ omap_mux_init_signal("usbb2_ulpitll_dat2", MUX_DISPLAY_OUT);
+ omap_mux_init_signal("dpm_emu6", MUX_DISPLAY_OUT);
+ omap_mux_init_signal("dpm_emu5", MUX_DISPLAY_OUT);
+ omap_mux_init_signal("usbb2_ulpitll_dat3", MUX_DISPLAY_OUT);
+ omap_mux_init_signal("usbb2_ulpitll_dat4", MUX_DISPLAY_OUT);
+ omap_mux_init_signal("usbb2_ulpitll_dat5", MUX_DISPLAY_OUT);
+ omap_mux_init_signal("usbb2_ulpitll_dat6", MUX_DISPLAY_OUT);
+ omap_mux_init_signal("usbb2_ulpitll_dat7", MUX_DISPLAY_OUT);
+ omap_mux_init_signal("dpm_emu3", MUX_DISPLAY_OUT);
+ omap_mux_init_signal("dpm_emu4", MUX_DISPLAY_OUT);
+ omap_mux_init_signal("dpm_emu11", MUX_DISPLAY_OUT);
+ omap_mux_init_signal("dpm_emu12", MUX_DISPLAY_OUT);
+ omap_mux_init_signal("dpm_emu13", MUX_DISPLAY_OUT);
+ omap_mux_init_signal("dpm_emu14", MUX_DISPLAY_OUT);
+ omap_mux_init_signal("dpm_emu15", MUX_DISPLAY_OUT);
+ omap_mux_init_signal("dpm_emu16", MUX_DISPLAY_OUT);
+ omap_mux_init_signal("dpm_emu17", MUX_DISPLAY_OUT);
+ omap_mux_init_signal("dpm_emu18", MUX_DISPLAY_OUT);
+ omap_mux_init_signal("dpm_emu19", MUX_DISPLAY_OUT);
+ /* dispc2_hsync */
+ omap_mux_init_signal("dpm_emu7", MUX_DISPLAY_OUT);
+ /* dispc2_pclk */
+ omap_mux_init_signal("dpm_emu8", MUX_DISPLAY_OUT);
+ /* dispc2_vsync */
+ omap_mux_init_signal("dpm_emu9", MUX_DISPLAY_OUT);
+ /* dispc2_de */
+ omap_mux_init_signal("dpm_emu10", MUX_DISPLAY_OUT);
+
+ dss_data = &prelunchbox_dss_data;
+ } else {
+ omap4_ctrl_pad_writel(0x1F000000, OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_DSIPHY);
+ if (!omap4_tuna_final_gpios())
+ tuna_oled_data.reset_gpio = TUNA_GPIO_MLCD_RST_LUNCHBOX;
+ omap_mux_init_gpio(tuna_oled_data.reset_gpio, OMAP_PIN_OUTPUT);
+ dss_data = &tuna_dss_data;
+ }
+
+ omap_vram_set_sdram_vram(TUNA_FB_RAM_SIZE, 0);
+ omapfb_set_platform_data(&tuna_fb_pdata);
+ omap_display_init(dss_data);
+}
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..9ee5834
--- /dev/null
+++ b/arch/arm/mach-omap2/board-tuna-input.c
@@ -0,0 +1,210 @@
+/*
+ * 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 const int tuna_keymap[] = {
+ KEY(1, 1, KEY_VOLUMEDOWN),
+ KEY(2, 1, KEY_VOLUMEUP),
+};
+
+static struct matrix_keymap_data tuna_keymap_data = {
+ .keymap = tuna_keymap,
+ .keymap_size = ARRAY_SIZE(tuna_keymap),
+};
+
+static struct omap4_keypad_platform_data tuna_keypad_data = {
+ .keymap_data = &tuna_keymap_data,
+ .rows = 3,
+ .cols = 2,
+};
+
+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,
+ .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,
+ .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 struct mxt_platform_data atmel_mxt_ts_pdata = {
+ .x_line = 19,
+ .y_line = 11,
+ .x_size = 1024,
+ .y_size = 1024,
+ .blen = 0x21,
+ .threshold = 0x28,
+ .voltage = 2800000, /* 2.8V */
+ .orient = MXT_DIAGONAL,
+ .irqflags = IRQF_TRIGGER_FALLING,
+};
+
+static struct i2c_board_info __initdata tuna_i2c3_boardinfo_pre_lunchbox[] = {
+ {
+ I2C_BOARD_INFO("atmel_mxt_ts", 0x4a),
+ .platform_data = &atmel_mxt_ts_pdata,
+ .irq = OMAP_GPIO_IRQ(GPIO_TOUCH_IRQ),
+ },
+};
+
+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 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);
+
+ if (omap4_tuna_final_gpios()) {
+ 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");
+
+ i2c_register_board_info(3, tuna_i2c3_boardinfo_final,
+ ARRAY_SIZE(tuna_i2c3_boardinfo_final));
+ }
+
+ if (omap4_tuna_get_revision() == TUNA_REV_PRE_LUNCHBOX) {
+ i2c_register_board_info(3, tuna_i2c3_boardinfo_pre_lunchbox,
+ ARRAY_SIZE(tuna_i2c3_boardinfo_pre_lunchbox));
+
+ omap_mux_init_signal("kpd_row1.kpd_row1", OMAP_PIN_INPUT_PULLUP);
+ omap_mux_init_signal("kpd_row2.kpd_row2", OMAP_PIN_INPUT_PULLUP);
+ omap_mux_init_signal("kpd_col1.kpd_col1", OMAP_PIN_OUTPUT);
+ omap4_keyboard_init(&tuna_keypad_data);
+ tuna_gpio_keypad_data.info_count = 1;
+ } else {
+ 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-modems.c b/arch/arm/mach-omap2/board-tuna-modems.c
new file mode 100755
index 0000000..d9d6374
--- /dev/null
+++ b/arch/arm/mach-omap2/board-tuna-modems.c
@@ -0,0 +1,631 @@
+/* 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>
+
+/* inlcude platform specific file */
+#include <mach/omap4-common.h>
+#include <linux/platform_data/modem.h>
+#include "mux.h"
+#include "board-tuna.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_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
+
+/* PROXIMA 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,
+ },
+};
+
+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)
+{
+ int err = 0;
+
+ 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_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) {
+ err = gpio_request(gpio_reset_req_n, "RESET_REQ_N");
+ if (err) {
+ printk(KERN_ERR "fail to request gpio %s : %d\n",
+ "RESET_REQ_N", err);
+ }
+ gpio_direction_output(gpio_reset_req_n, 0);
+ }
+
+ if (gpio_cp_on) {
+ err = gpio_request(gpio_cp_on, "CP_ON");
+ if (err) {
+ printk(KERN_ERR "fail to request gpio %s : %d\n",
+ "CP_ON", err);
+ }
+ gpio_direction_output(gpio_cp_on, 0);
+ }
+
+ if (gpio_cp_rst) {
+ err = gpio_request(gpio_cp_rst, "CP_RST");
+ if (err) {
+ printk(KERN_ERR "fail to request gpio %s : %d\n",
+ "CP_RST", err);
+ }
+ gpio_direction_output(gpio_cp_rst, 0);
+ }
+
+ if (gpio_pda_active) {
+ err = gpio_request(gpio_pda_active, "PDA_ACTIVE");
+ if (err) {
+ printk(KERN_ERR "fail to request gpio %s : %d\n",
+ "PDA_ACTIVE", err);
+ }
+ gpio_direction_output(gpio_pda_active, 0);
+ }
+
+ if (gpio_phone_active) {
+ err = gpio_request(gpio_phone_active, "PHONE_ACTIVE");
+ if (err) {
+ printk(KERN_ERR "fail to request gpio %s : %d\n",
+ "PHONE_ACTIVE", err);
+ }
+ gpio_direction_input(gpio_phone_active);
+ }
+
+ if (gpio_cp_dump_int) {
+ err = gpio_request(gpio_cp_dump_int, "CP_DUMP_INT");
+ if (err) {
+ printk(KERN_ERR "fail to request gpio %s : %d\n",
+ "CP_DUMP_INT", err);
+ }
+ gpio_direction_input(gpio_cp_dump_int);
+ }
+
+ if (gpio_flm_uart_sel) {
+ err = gpio_request(gpio_flm_uart_sel, "GPS_UART_SEL");
+ if (err) {
+ printk(KERN_ERR "fail to request gpio %s : %d\n",
+ "GPS_UART_SEL", err);
+ }
+ gpio_direction_output(gpio_reset_req_n, 1);
+ }
+
+ if (gpio_phone_active)
+ irq_set_irq_type(
+ OMAP_GPIO_IRQ(OMAP_GPIO_MIPI_HSI_PHONE_ACTIVE),
+ IRQ_TYPE_LEVEL_HIGH);
+
+ printk(KERN_INFO "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_rmnet0",
+ .id = 0x27,
+ .format = IPC_RAW,
+ .io_type = IODEV_NET,
+ .link = LINKDEV_DPRAM,
+ },
+ [3] = {
+ .name = "cdma_rmnet1",
+ .id = 0x31,
+ .format = IPC_RAW,
+ .io_type = IODEV_NET,
+ .link = LINKDEV_DPRAM,
+ },
+ [4] = {
+ .name = "cdma_rmnet2",
+ .id = 0x33,
+ .format = IPC_RAW,
+ .io_type = IODEV_NET,
+ .link = LINKDEV_DPRAM,
+ },
+
+ [5] = {
+ .name = "cdma_rmnet3",
+ .id = 0x34,
+ .format = IPC_RAW,
+ .io_type = IODEV_NET,
+ .link = LINKDEV_DPRAM,
+ },
+};
+
+
+/* PROXIMA 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,
+
+ .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 cdma_modem_cfg_gpio(void)
+{
+ int err = 0;
+
+ 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;
+
+ /*TODO*/
+ /* gpio mux setting */
+
+ if (gpio_cp_rst) {
+ err = gpio_request(gpio_cp_rst, "CP_RST");
+ if (err) {
+ printk(KERN_ERR "fail to request gpio %s : %d\n",
+ "CP_RST", err);
+ } else
+ gpio_direction_output(gpio_cp_rst, 0);
+ }
+
+ if (gpio_pda_active) {
+ err = gpio_request(gpio_pda_active, "PDA_ACTIVE");
+ if (err) {
+ printk(KERN_ERR "fail to request gpio %s : %d\n",
+ "PDA_ACTIVE", err);
+ } else
+ gpio_direction_output(gpio_pda_active, 0);
+}
+
+ if (gpio_phone_active) {
+ err = gpio_request(gpio_phone_active, "PHONE_ACTIVE");
+ if (err) {
+ printk(KERN_ERR "fail to request gpio %s : %d\n",
+ "PHONE_ACTIVE", err);
+ } else
+ gpio_direction_input(gpio_phone_active);
+ }
+
+ 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 = 0, /* dpram int */
+ .end = 0,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+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,
+ },
+};
+
+
+/* PROXIMA 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,
+ },
+};
+
+/*
+Proxima 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_info("[MODEM_IF] %s IN!\n", __func__);
+
+ omap_mux_init_gpio(OMAP_GPIO_221_PMIC_PWRON, OMAP_PIN_OUTPUT);
+ omap_mux_init_gpio(OMAP_GPIO_221_PMIC_PWRHOLD_OFF , OMAP_PIN_OUTPUT);
+ omap_mux_init_gpio(OMAP_GPIO_CMC_RST, OMAP_PIN_OUTPUT);
+ omap_mux_init_gpio(OMAP_GPIO_AP2CMC_INT1, OMAP_PIN_OUTPUT);
+ omap_mux_init_gpio(OMAP_GPIO_CMC2AP_INT2, OMAP_PIN_INPUT);
+ omap_mux_init_gpio(OMAP_GPIO_AP2CMC_INT2, OMAP_PIN_OUTPUT);
+ omap_mux_init_gpio(OMAP_GPIO_LTE_ACTIVE, OMAP_PIN_INPUT);
+}
+
+static void lte_modem_cfg_gpio(void)
+{
+
+ int err = 0;
+
+ unsigned gpio_cp_on = lte_modem_data.gpio_cp_on;
+ unsigned gpio_cp_rst = lte_modem_data.gpio_cp_reset;
+ /*unsigned gpio_pda_active = lte_modem_data.gpio_pda_active;*/
+ 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) {
+ err = gpio_request(gpio_cp_on, "LTE_ON");
+ if (err) {
+ printk(KERN_ERR "fail to request gpio %s : %d\n",
+ "LTE_ON", err);
+ } else
+ gpio_direction_output(gpio_cp_on, 0);
+}
+
+
+ if (gpio_cp_rst) {
+ err = gpio_request(gpio_cp_rst, "LTE_RST");
+ if (err) {
+ printk(KERN_ERR "fail to request gpio %s : %d\n",
+ "LTE_RST", err);
+ } else
+ gpio_direction_output(gpio_cp_rst, 0);
+ }
+/*
+ if (gpio_pda_active) {
+ err = gpio_request(gpio_pda_active, "PDA_ACTIVE");
+ if (err) {
+ printk("fail to request gpio %s : %d\n",
+ "PDA_ACTIVE", err);
+ } else
+ gpio_direction_output(gpio_pda_active, 0);
+ }
+*/
+ if (gpio_phone_active) {
+ err = gpio_request(gpio_phone_active, "LTE_ACTIVE");
+ if (err) {
+ printk(KERN_ERR "fail to request gpio %s : %d\n",
+ "LTE_ACTIVE", err);
+ } else
+ gpio_direction_input(gpio_phone_active);
+ }
+
+#ifdef CONFIG_LTE_MODEM_CMC221
+ if (gpio_cp_off) {
+ err = gpio_request(gpio_cp_off, "LTE_OFF");
+ if (err) {
+ printk(KERN_ERR "fail to request gpio %s : %d\n",
+ "LTE_OFF", err);
+ } else
+ gpio_direction_output(gpio_cp_off, 0);
+}
+ if (gpio_slave_wakeup) {
+ err = gpio_request(gpio_slave_wakeup, "LTE_SLAVE_WAKEUP");
+ if (err) {
+ printk(KERN_ERR "fail to request gpio %s : %d\n",
+ "LTE_SLAVE_WAKEUP", err);
+ } else
+ gpio_direction_input(gpio_slave_wakeup);
+ }
+
+ if (gpio_host_wakeup) {
+ err = gpio_request(gpio_host_wakeup, "LTE_HOST_WAKEUP");
+ if (err) {
+ printk(KERN_ERR "fail to request gpio %s : %d\n",
+ "LTE_HOST_WAKEUP", err);
+ } else
+ gpio_direction_input(gpio_host_wakeup);
+ }
+
+ if (gpio_host_active) {
+ err = gpio_request(gpio_host_active, "LTE_HOST_ACTIVE");
+ if (err) {
+ printk(KERN_ERR "fail to request gpio %s : %d\n",
+ "LTE_HOST_ACTIVE", err);
+ } else
+ gpio_direction_input(gpio_host_active);
+ }
+#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 = {
+ .name = "modem_if",
+ .id = 2,
+ .num_resources = ARRAY_SIZE(lte_modem_res),
+ .resource = lte_modem_res,
+ .dev = {
+ .platform_data = &lte_modem_data,
+ },
+};
+
+static int __init init_modem(void)
+{
+ printk(KERN_INFO "[MODEM_IF] init_modem\n");
+
+ switch (omap4_tuna_get_type()) {
+ case TUNA_TYPE_MAGURO: /* Proxima_HSPA */
+ /* umts gpios configuration */
+ umts_modem_cfg_gpio();
+ platform_device_register(&umts_modem);
+ break;
+
+ case TUNA_TYPE_TORO: /* Proxima_LTE */
+ /* cdma gpios configuration */
+ /* TODO not supported yet
+ cdma_modem_cfg_gpio();
+ platform_device_register(&cdma_modem);
+ */
+
+ /* lte gpios configuration */
+ /* TODO not supported yet
+ 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..6b7895e
--- /dev/null
+++ b/arch/arm/mach-omap2/board-tuna-nfc.c
@@ -0,0 +1,112 @@
+/* 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 "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
+
+static unsigned int nfc_power;
+
+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);
+
+void __init omap4_tuna_nfc_init(void)
+{
+ struct platform_device *pdev;
+
+ 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);
+
+ 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-power.c b/arch/arm/mach-omap2/board-tuna-power.c
new file mode 100644
index 0000000..cccfe99
--- /dev/null
+++ b/arch/arm/mach-omap2/board-tuna-power.c
@@ -0,0 +1,158 @@
+/* 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/pda_power.h>
+#include <linux/platform_device.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 CHG_CUR_ADJ 102
+
+#define TPS62361_GPIO 7
+
+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 = CHG_CUR_ADJ, .flags = GPIOF_OUT_INIT_LOW, .label = "charge_cur_adj" },
+};
+
+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 charger_set_charge(int state)
+{
+ gpio_set_value(GPIO_CHARGE_N, !state);
+}
+
+static int charger_is_ac_online(void)
+{
+ return !gpio_get_value(GPIO_TA_NCONNECTED);
+}
+
+static int charger_is_charging(void)
+{
+ return !gpio_get_value(GPIO_CHARGING_N);
+}
+
+static const __initdata struct resource charger_resources[] = {
+ {
+ .name = "ac",
+ .start = OMAP_GPIO_IRQ(GPIO_TA_NCONNECTED),
+ .end = OMAP_GPIO_IRQ(GPIO_TA_NCONNECTED),
+ .flags = IORESOURCE_IRQ |
+ IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
+ },
+ {
+ .name = "usb",
+ .start = OMAP_GPIO_IRQ(GPIO_TA_NCONNECTED),
+ .end = OMAP_GPIO_IRQ(GPIO_TA_NCONNECTED),
+ .flags = IORESOURCE_IRQ |
+ IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
+ }
+};
+
+static char *tuna_charger_supplied_to[] = {
+ "battery",
+};
+
+static const __initdata struct pda_power_pdata charger_pdata = {
+ .init = charger_init,
+ .exit = charger_exit,
+ .is_ac_online = charger_is_ac_online,
+ .is_usb_online = charger_is_ac_online,
+ .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),
+};
+
+static struct max17040_platform_data max17043_pdata = {
+ .charger_online = charger_is_ac_online,
+ .charger_enable = charger_is_charging,
+};
+
+static const __initdata struct i2c_board_info max17043_i2c[] = {
+ {
+ I2C_BOARD_INFO("max17040", (0x6C >> 1)),
+ .platform_data = &max17043_pdata,
+ }
+};
+
+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);
+ }
+
+ if (omap4_tuna_get_revision() == TUNA_REV_PRE_LUNCHBOX) {
+ charger_gpios[0].gpio = 11;
+ charger_gpios[1].gpio = 12;
+ } else if (!omap4_tuna_final_gpios()) {
+ charger_gpios[0].gpio = 159;
+ charger_gpios[1].gpio = 160;
+ }
+
+ 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);
+
+ pdev = platform_device_register_resndata(NULL, "pda-power", -1,
+ charger_resources, ARRAY_SIZE(charger_resources),
+ &charger_pdata, sizeof(charger_pdata));
+
+ i2c_register_board_info(4, max17043_i2c, ARRAY_SIZE(max17043_i2c));
+
+ 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..dc59124
--- /dev/null
+++ b/arch/arm/mach-omap2/board-tuna-sensors.c
@@ -0,0 +1,171 @@
+/* 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 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_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,
+};
+
+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 = { 0, 1, 0,
+ 1, 0, 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),
+ },
+};
+
+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_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);
+ /* optical sensor */
+ gp2a_gpio_init();
+
+ if (omap4_tuna_get_type() == TUNA_TYPE_MAGURO &&
+ omap4_tuna_get_revision() >= 2) {
+ rotcpy(mpu_data.orientation, orientation_back_right_90);
+ rotcpy(mpu_data.accel.orientation, orientation_back_180);
+ }
+ if (omap4_tuna_get_type() == TUNA_TYPE_TORO &&
+ omap4_tuna_get_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);
+ }
+
+ i2c_register_board_info(4, tuna_sensors_i2c4_boardinfo,
+ ARRAY_SIZE(tuna_sensors_i2c4_boardinfo));
+}
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..67010b1
--- /dev/null
+++ b/arch/arm/mach-omap2/board-tuna-wifi.c
@@ -0,0 +1,367 @@
+/*
+ * 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 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)
+{
+ pr_debug("%s: %d\n", __func__, on);
+ mdelay(100);
+ gpio_set_value(GPIO_WLAN_PMENA, on);
+ mdelay(200);
+
+ 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 };
+
+#if 0
+static int __init parse_tag_wlan_mac(const struct tag *tag)
+{
+ unsigned char *dptr = (unsigned char *)(&tag->u);
+ unsigned size;
+#ifdef ATAG_TUNA_MAC_DEBUG
+ unsigned i;
+#endif
+
+ size = min((tag->hdr.size - 2) * sizeof(__u32), (unsigned)IFHWADDRLEN);
+#ifdef ATAG_TUNA_MAC_DEBUG
+ printk("WiFi MAC Addr [%d] = 0x%x\n", tag->hdr.size, tag->hdr.tag);
+ for(i=0;(i < size);i++) {
+ printk(" %02x", dptr[i]);
+ }
+ printk("\n");
+#endif
+ memcpy(tuna_mac_addr, dptr, size);
+ return 0;
+}
+
+__tagtable(ATAG_TUNA_MAC, parse_tag_wlan_mac);
+#endif
+
+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;
+}
+
+#if 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 */
+ {"US", "US", 69}, /* input ISO "US" to : US regrev 69 */
+ {"CA", "US", 69}, /* input ISO "CA" to : US regrev 69 */
+ {"EU", "EU", 5}, /* input ISO "EU" to : EU regrev 05 */
+ {"FR", "EU", 5},
+ {"DE", "EU", 5},
+ {"GB", "EU", 5}, /* input ISO "UK" to : EU regrev 05 */
+ {"KR", "XY", 3},
+ {"AU", "XY", 3},
+ {"CN", "XY", 3}, /* input ISO "CN" to : XY regrev 03 */
+ {"TW", "XY", 3},
+ {"AR", "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 NULL;
+}
+#endif
+
+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 = NULL, /* 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 100755
index 0000000..b5f20e8
--- /dev/null
+++ b/arch/arm/mach-omap2/board-tuna.c
@@ -0,0 +1,889 @@
+/* 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 <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.h>
+#include <plat/common.h>
+#include <plat/cpu.h>
+#include <plat/usb.h>
+#include <plat/mmc.h>
+#include "timer-gp.h"
+
+#include "omap4-sar-layout.h"
+#include "hsmmc.h"
+#include "control.h"
+#include "mux.h"
+#include "board-tuna.h"
+
+#define TUNA_RAMCONSOLE_START (PLAT_PHYS_OFFSET + SZ_512M)
+#define TUNA_RAMCONSOLE_SIZE SZ_2M
+
+struct class *sec_class;
+EXPORT_SYMBOL(sec_class);
+
+#define GPIO_AUD_PWRON 127
+#define GPIO_AUD_PWRON_TORO_V1 20
+#define GPIO_MICBIAS_EN 48
+
+/* 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 REBOOT_FLAG_RECOVERY 0x52564352
+#define REBOOT_FLAG_FASTBOOT 0x54534146
+#define REBOOT_FLAG_NORMAL 0x4D524F4E
+
+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",
+ [0x05] = "Toro Pre-Lunchbox",
+};
+
+static const char const *omap4_tuna_hw_name_toro[] = {
+ [0x00] = "Toro Lunchbox #2",
+ [0x01] = "Toro 1st Sample",
+ [0x02] = "Toro 2nd 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];
+}
+
+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;
+
+ pr_info("Tuna HW revision: %02x (%s), cpu %s\n", tuna_hw_rev,
+ omap4_tuna_hw_rev_name(),
+ cpu_is_omap443x() ? "OMAP4430" : "OMAP4460");
+}
+
+bool omap4_tuna_final_gpios(void)
+{
+ int type = omap4_tuna_get_type();
+ int rev = omap4_tuna_get_revision();
+
+ if (type == TUNA_TYPE_TORO ||
+ (rev != TUNA_REV_PRE_LUNCHBOX && rev != TUNA_REV_LUNCHBOX))
+ return true;
+
+ return false;
+}
+
+/* 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_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,
+ },
+};
+
+#define PHYS_ADDR_DUCATI_MEM (0x80000000 + SZ_1G - (SZ_1M * 104))
+
+static struct ion_platform_data tuna_ion_data = {
+ .nr = 3,
+ .heaps = {
+ {
+ .type = ION_HEAP_TYPE_CARVEOUT,
+ .id = OMAP_ION_HEAP_SECURE_INPUT,
+ .name = "secure_input",
+ .base = PHYS_ADDR_DUCATI_MEM - SZ_256M - SZ_64M,
+ .size = SZ_64M,
+ },
+ { .type = OMAP_ION_HEAP_TYPE_TILER,
+ .id = OMAP_ION_HEAP_TILER,
+ .name = "tiler",
+ .base = PHYS_ADDR_DUCATI_MEM - SZ_256M,
+ .size = SZ_256M,
+ },
+ {
+ .type = ION_HEAP_TYPE_CARVEOUT,
+ .id = OMAP_ION_HEAP_LARGE_SURFACES,
+ .name = "large_surfaces",
+ .base = 0x80000000 + SZ_512M + SZ_2M,
+ .size = SZ_32M,
+ },
+ },
+};
+
+static struct platform_device tuna_ion_device = {
+ .name = "ion-omap4",
+ .id = -1,
+ .dev = {
+ .platform_data = &tuna_ion_data,
+ },
+};
+
+static struct platform_device *tuna_devices[] __initdata = {
+ &ramconsole_device,
+ &wl1271_device,
+ &bcm4330_bluetooth_device,
+ &twl6030_madc_device,
+ &tuna_ion_device,
+};
+
+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);
+
+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_GADGET_MUSB_HDRC
+ .mode = MUSB_PERIPHERAL,
+#else
+ .mode = MUSB_OTG,
+#endif
+ .power = 100,
+};
+
+static struct twl4030_usb_data omap4_usbphy_data = {
+ .phy_init = omap4430_phy_init,
+ .phy_exit = omap4430_phy_exit,
+ .phy_power = omap4430_phy_power,
+ .phy_set_clock = omap4430_phy_set_clk,
+ .phy_suspend = omap4430_phy_suspend,
+};
+
+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_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 = 3300000,
+ .max_uV = 3300000,
+ .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_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,
+ },
+};
+
+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_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,
+ },
+};
+
+static struct regulator_init_data tuna_vusb = {
+ .constraints = {
+ .min_uV = 3300000,
+ .max_uV = 3300000,
+ .apply_uV = true,
+ .valid_modes_mask = REGULATOR_MODE_NORMAL
+ | REGULATOR_MODE_STANDBY,
+ .valid_ops_mask = REGULATOR_CHANGE_MODE
+ | REGULATOR_CHANGE_STATUS,
+ },
+};
+
+static struct regulator_init_data tuna_clk32kg = {
+ .constraints = {
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ },
+};
+
+static struct twl4030_codec_audio_data twl6040_audio = {
+ /* Add audio only data */
+};
+
+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,
+ .vana = &tuna_vana,
+ .vcxio = &tuna_vcxio,
+ .vdac = &tuna_vdac,
+ .vusb = &tuna_vusb,
+ .vaux2 = &tuna_vaux2,
+ .vaux3 = &tuna_vaux3,
+ .clk32kg = &tuna_clk32kg,
+ .usb = &omap4_usbphy_data,
+
+ /* children */
+ .codec = &twl6040_codec,
+ .madc = &twl6030_madc,
+};
+
+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_gpio(GPIO_MICBIAS_EN, OMAP_PIN_OUTPUT);
+ gpio_request(GPIO_MICBIAS_EN, "MICBIAS_EN");
+ gpio_direction_output(GPIO_MICBIAS_EN, 1);
+}
+
+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 int __init tuna_i2c_init(void)
+{
+ omap_mux_init_signal("sys_nirq1", OMAP_PIN_INPUT_PULLUP);
+ omap_mux_init_signal("i2c1_scl.i2c1_scl", OMAP_PIN_INPUT_PULLUP);
+ omap_mux_init_signal("i2c1_sda.i2c1_sda", OMAP_PIN_INPUT_PULLUP);
+
+ /*
+ * 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, NULL, 0);
+ omap_register_i2c_bus(3, 400, NULL, 0);
+ omap_register_i2c_bus(4, 400, NULL, 0);
+ 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), /* gpio_135 */
+ OMAP4_MUX(KPD_COL0, OMAP_MUX_MODE3 | OMAP_PIN_INPUT), /* gpio_173 */
+ OMAP4_MUX(GPMC_A19, OMAP_MUX_MODE3 | OMAP_PIN_INPUT), /* 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),
+ { .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 },
+};
+
+static struct omap_device_pad serial2_pads[] __initdata = {
+ OMAP_MUX_STATIC("uart2_cts.uart2_cts",
+ OMAP_PIN_INPUT_PULLUP | OMAP_MUX_MODE0),
+ OMAP_MUX_STATIC("uart2_rts.uart2_rts",
+ OMAP_PIN_OUTPUT | OMAP_MUX_MODE0),
+ OMAP_MUX_STATIC("uart2_rx.uart2_rx",
+ OMAP_PIN_INPUT_PULLUP | OMAP_MUX_MODE0),
+ OMAP_MUX_STATIC("uart2_tx.uart2_tx",
+ OMAP_PIN_OUTPUT | OMAP_MUX_MODE0),
+};
+
+static struct omap_device_pad serial3_pads[] __initdata = {
+ OMAP_MUX_STATIC("uart3_cts_rctx.uart3_cts_rctx",
+ OMAP_PIN_INPUT_PULLUP | OMAP_MUX_MODE0),
+ OMAP_MUX_STATIC("uart3_rts_sd.uart3_rts_sd",
+ OMAP_PIN_OUTPUT | OMAP_MUX_MODE0),
+ OMAP_MUX_STATIC("uart3_rx_irrx.uart3_rx_irrx",
+ OMAP_PIN_INPUT | OMAP_MUX_MODE0),
+ OMAP_MUX_STATIC("uart3_tx_irtx.uart3_tx_irtx",
+ OMAP_PIN_OUTPUT | OMAP_MUX_MODE0),
+};
+
+static struct omap_device_pad serial4_pads[] __initdata = {
+ OMAP_MUX_STATIC("uart4_rx.uart4_rx",
+ OMAP_PIN_INPUT | OMAP_MUX_MODE0),
+ OMAP_MUX_STATIC("uart4_tx.uart4_tx",
+ OMAP_PIN_OUTPUT | OMAP_MUX_MODE0),
+};
+
+static struct omap_board_data serial2_data __initdata = {
+ .id = 1,
+ .pads = serial2_pads,
+ .pads_cnt = ARRAY_SIZE(serial2_pads),
+};
+
+static struct omap_board_data serial3_data __initdata = {
+ .id = 2,
+ .pads = serial3_pads,
+ .pads_cnt = ARRAY_SIZE(serial3_pads),
+};
+
+static struct omap_board_data serial4_data __initdata = {
+ .id = 3,
+ .pads = serial4_pads,
+ .pads_cnt = ARRAY_SIZE(serial4_pads),
+};
+
+static inline void __init board_serial_init(void)
+{
+ struct omap_board_data bdata;
+ bdata.flags = 0;
+ bdata.pads = NULL;
+ bdata.pads_cnt = 0;
+ bdata.id = 0;
+ /* pass dummy data for UART1 */
+ omap_serial_init_port(&bdata);
+
+ omap_serial_init_port(&serial2_data);
+ omap_serial_init_port(&serial3_data);
+ omap_serial_init_port(&serial4_data);
+}
+#else
+#define board_mux NULL
+#define board_wkup_mux NULL
+
+static inline void __init board_serial_init(void)
+{
+ omap_serial_init();
+}
+#endif
+
+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;
+ }
+ }
+
+ /* 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 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_SOC_ATTR_RO(_name, _show) \
+ struct kobj_attribute tuna_soc_prop_attr_##_name = \
+ __ATTR(_name, S_IRUGO, _show, NULL)
+
+static TUNA_SOC_ATTR_RO(family, tuna_soc_family_show);
+static TUNA_SOC_ATTR_RO(revision, tuna_soc_revision_show);
+static TUNA_SOC_ATTR_RO(type, tuna_soc_type_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,
+ NULL,
+};
+
+static struct attribute_group tuna_soc_prop_attr_group = {
+ .attrs = tuna_soc_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(soc_kobj, &tuna_soc_prop_attr_group);
+ if (ret)
+ goto err_sysfs_create;
+ return;
+
+err_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 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();
+
+ register_reboot_notifier(&tuna_reboot_notifier);
+
+ if (omap4_tuna_final_gpios()) {
+ /* 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);
+ } else {
+ /* hsmmc d0-d7 */
+ omap_mux_init_signal("gpmc_ad0", HSMMC2_MUX);
+ omap_mux_init_signal("gpmc_ad1", HSMMC2_MUX);
+ omap_mux_init_signal("gpmc_ad2", HSMMC2_MUX);
+ omap_mux_init_signal("gpmc_ad3", HSMMC2_MUX);
+ omap_mux_init_signal("gpmc_ad4", HSMMC2_MUX);
+ omap_mux_init_signal("gpmc_ad5", HSMMC2_MUX);
+ omap_mux_init_signal("gpmc_ad6", HSMMC2_MUX);
+ omap_mux_init_signal("gpmc_ad7", HSMMC2_MUX);
+ /* hsmmc cmd */
+ omap_mux_init_signal("gpmc_nwe", HSMMC2_MUX);
+ /* hsmmc clk */
+ omap_mux_init_signal("gpmc_noe", HSMMC2_MUX);
+
+ mmc[0].mmc = 2;
+ }
+
+ if (omap4_tuna_get_revision() != TUNA_REV_PRE_LUNCHBOX) {
+ gpio_request(158, "emmc_en");
+ gpio_direction_output(158, 1);
+ omap_mux_init_gpio(158, OMAP_PIN_INPUT_PULLUP);
+ }
+
+ sec_common_init();
+ 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();
+ omap4_tuna_display_init();
+ omap4_tuna_input_init();
+ omap4_tuna_nfc_init();
+ omap4_tuna_power_init();
+ omap4_tuna_sensors_init();
+#ifdef CONFIG_OMAP_HSI_DEVICE
+ if (TUNA_TYPE_MAGURO == omap4_tuna_get_type())
+ omap_hsi_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;
+
+ omap_reserve();
+ memblock_remove(TUNA_RAMCONSOLE_START, TUNA_RAMCONSOLE_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);
+ }
+}
+
+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..f1e604a
--- /dev/null
+++ b/arch/arm/mach-omap2/board-tuna.h
@@ -0,0 +1,39 @@
+/*
+ * 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_PRE_LUNCHBOX 0x5
+#define TUNA_REV_LUNCHBOX 0x0
+#define TUNA_REV_MASK 0xf
+
+#define TUNA_TYPE_TORO 0x10
+#define TUNA_TYPE_MAGURO 0x00
+#define TUNA_TYPE_MASK 0x10
+
+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_nfc_init(void);
+void omap4_tuna_power_init(void);
+void omap4_tuna_sensors_init(void);
+int tuna_wlan_init(void);
+int omap_hsi_init(void);
+void omap4_tuna_emif_init(void);
+
+extern struct mmc_platform_data tuna_wifi_data;
+
+#endif
diff --git a/arch/arm/mach-omap2/omap_hsi.c b/arch/arm/mach-omap2/omap_hsi.c
new file mode 100644
index 0000000..7c27f84
--- /dev/null
+++ b/arch/arm/mach-omap2/omap_hsi.c
@@ -0,0 +1,418 @@
+/*
+ * arch/arm/mach-omap2/hsi.c
+ *
+ * HSI device definition
+ *
+ * Copyright (C) 2011 Texas Instruments, Inc.
+ * Original Author: Sebastien JAN <s-jan@ti.com>
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/gpio.h>
+#include <linux/irq.h>
+#include <linux/jiffies.h>
+#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>
+
+#include <../drivers/omap_hsi/hsi_driver.h>
+#include "clock.h"
+#include "mux.h"
+#include "control.h"
+
+static int omap_hsi_wakeup_enable(int hsi_port);
+static int omap_hsi_wakeup_disable(int hsi_port);
+#define OMAP_HSI_PLATFORM_DEVICE_DRIVER_NAME "omap_hsi"
+#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
+
+
+/* */
+
+#define CA_WAKE_MUX_REG (0x4a1000C2)
+static int omap_mux_read_signal(const char *muxname)
+{
+ u16 val = 0;
+ val = omap_readw(CA_WAKE_MUX_REG);
+ return val;
+}
+
+static int omap_mux_enable_wakeup(const char *muxname)
+{
+ u16 val = 0;
+ val = omap_readw(CA_WAKE_MUX_REG);
+ val |= OMAP44XX_PADCONF_WAKEUPENABLE0;
+ omap_writew(val, CA_WAKE_MUX_REG);
+ return 0;
+}
+
+static int omap_mux_disable_wakeup(const char *muxname)
+{
+ u16 val = 0;
+ val = omap_readw(CA_WAKE_MUX_REG);
+ val &= ~OMAP44XX_PADCONF_WAKEUPENABLE0;
+ omap_writew(val, CA_WAKE_MUX_REG);
+ return 0;
+}
+
+/*
+ * NOTE: We abuse a little bit the struct port_ctx to use it also for
+ * initialization.
+ */
+
+
+static struct port_ctx hsi_port_ctx[] = {
+ [0] = {
+ .hst.mode = HSI_MODE_FRAME,
+ .hst.flow = HSI_FLOW_SYNCHRONIZED,
+ .hst.frame_size = HSI_FRAMESIZE_DEFAULT,
+ .hst.divisor = HSI_DIVISOR_DEFAULT,
+ .hst.channels = HSI_CHANNELS_DEFAULT,
+ .hst.arb_mode = HSI_ARBMODE_ROUNDROBIN,
+ .hsr.mode = HSI_MODE_FRAME,
+ .hsr.flow = HSI_FLOW_SYNCHRONIZED,
+ .hsr.frame_size = HSI_FRAMESIZE_DEFAULT,
+ .hsr.channels = HSI_CHANNELS_DEFAULT,
+ .hsr.divisor = HSI_DIVISOR_DEFAULT,
+ .hsr.counters = HSI_COUNTERS_FT_DEFAULT |
+ HSI_COUNTERS_TB_DEFAULT |
+ HSI_COUNTERS_FB_DEFAULT,
+ },
+};
+
+static struct ctrl_ctx hsi_ctx = {
+ .sysconfig = 0,
+ .gdd_gcr = 0,
+ .dll = 0,
+ .pctx = hsi_port_ctx,
+};
+
+static struct hsi_platform_data omap_hsi_platform_data = {
+ .num_ports = ARRAY_SIZE(hsi_port_ctx),
+ .hsi_gdd_chan_count = HSI_HSI_DMA_CHANNEL_MAX,
+ .default_hsi_fclk = HSI_DEFAULT_FCLK,
+ .ctx = &hsi_ctx,
+ .device_enable = omap_device_enable,
+ .device_idle = omap_device_idle,
+ .device_shutdown = omap_device_shutdown,
+ .wakeup_enable = omap_hsi_wakeup_enable,
+ .wakeup_disable = omap_hsi_wakeup_disable,
+ .wakeup_is_from_hsi = omap_hsi_is_io_wakeup_from_hsi,
+ .board_suspend = omap_hsi_prepare_suspend,
+};
+
+
+static struct platform_device *hsi_get_hsi_platform_device(void)
+{
+ struct device *dev;
+ struct platform_device *pdev;
+
+ /* HSI_TODO: handle platform device id (or port) (0/1) */
+ dev = bus_find_device_by_name(&platform_bus_type, NULL,
+ OMAP_HSI_PLATFORM_DEVICE_NAME);
+ if (!dev) {
+ pr_debug("Could not find platform device %s\n",
+ OMAP_HSI_PLATFORM_DEVICE_NAME);
+ return 0;
+ }
+
+ if (!dev->driver) {
+ /* Could not find driver for platform device. */
+ return 0;
+ }
+
+ pdev = to_platform_device(dev);
+
+ return pdev;
+}
+
+static struct hsi_dev *hsi_get_hsi_controller_data(struct platform_device *pd)
+{
+ struct hsi_dev *hsi_ctrl;
+
+ if (!pd)
+ return 0;
+
+ hsi_ctrl = (struct hsi_dev *) platform_get_drvdata(pd);
+ if (!hsi_ctrl) {
+ pr_err("Could not find HSI controller data\n");
+ return 0;
+ }
+
+ return hsi_ctrl;
+}
+
+/**
+* omap_hsi_is_io_pad_hsi - Indicates if IO Pad has been muxed for HSI CAWAKE
+*
+* 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)
+{
+ u16 val;
+
+ /* Check for IO pad */
+ val = omap_mux_read_signal(OMAP_HSI_PADCONF_CAWAKE_PIN);
+ if (val == -ENODEV)
+ return 0;
+
+ /* Continue only if CAWAKE is muxed */
+ if ((val & OMAP_MUX_MODE_MASK) != OMAP_HSI_PADCONF_CAWAKE_MODE)
+ return 0;
+
+ return 1;
+}
+
+/**
+* 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
+*/
+int omap_hsi_is_io_wakeup_from_hsi(void)
+{
+ u16 val;
+
+ /* Check for IO pad wakeup */
+ val = omap_mux_read_signal(OMAP_HSI_PADCONF_CAWAKE_PIN);
+ if (val == -ENODEV)
+ return 0;
+
+ /* Continue only if CAWAKE is muxed */
+ if ((val & OMAP_MUX_MODE_MASK) != OMAP_HSI_PADCONF_CAWAKE_MODE)
+ return 0;
+
+ if (val & OMAP44XX_PADCONF_WAKEUPEVENT0)
+ return 1;
+
+ return 0;
+}
+
+/**
+* omap_hsi_wakeup_enable - Enable HSI wakeup feature from RET/OFF mode
+*
+* @hsi_port - reference to the HSI port onto which enable wakeup feature.
+*
+* 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)
+{
+ 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");
+
+
+ /* TODO: handle hsi_port param and use it to find the correct Pad */
+ return ret;
+}
+
+/**
+* omap_hsi_wakeup_disable - Disable HSI wakeup feature from RET/OFF mode
+*
+* @hsi_port - reference to the HSI port onto which disable wakeup feature.
+*
+* 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)
+{
+ 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 */
+
+ return ret;
+}
+
+/**
+* omap_hsi_prepare_suspend - Prepare HSI for suspend mode
+*
+* Return value :* 0 if CAWAKE padconf has been configured properly
+* * -ENODEV if CAWAKE is not muxed on padconf.
+*
+*/
+int omap_hsi_prepare_suspend(int hsi_port, bool dev_may_wakeup)
+{
+ int ret;
+
+ if (dev_may_wakeup)
+ ret = omap_hsi_wakeup_enable(hsi_port);
+ else
+ ret = omap_hsi_wakeup_disable(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.
+*/
+int omap_hsi_wakeup(int hsi_port)
+{
+ static struct platform_device *pdev;
+ static struct hsi_dev *hsi_ctrl;
+
+ if (!pdev) {
+ pdev = hsi_get_hsi_platform_device();
+ if (!pdev)
+ return -ENODEV;
+}
+
+ if (!device_may_wakeup(&pdev->dev)) {
+ dev_info(&pdev->dev, "Modem not allowed to wakeup platform");
+ return -EPERM;
+ }
+
+ if (!hsi_ctrl) {
+ 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");
+
+ /* CAWAKE falling or rising edge detected */
+ hsi_ctrl->hsi_port->cawake_off_event = true;
+ tasklet_hi_schedule(&hsi_ctrl->hsi_port->hsi_tasklet);
+
+ /* Disable interrupt until Bottom Half has cleared */
+ /* the IRQ status register */
+ disable_irq_nosync(hsi_ctrl->hsi_port->irq);
+
+ return 0;
+}
+
+/* HSI_TODO : This requires some fine tuning & completion of
+ * activate/deactivate latency values
+ */
+static struct omap_device_pm_latency omap_hsi_latency[] = {
+ [0] = {
+ .deactivate_func = omap_device_idle_hwmods,
+ .activate_func = omap_device_enable_hwmods,
+ .flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
+ },
+};
+
+/* HSI device registration */
+static int __init omap_hsi_register(struct omap_hwmod *oh, void *user)
+{
+ struct omap_device *od;
+ struct hsi_platform_data *pdata = &omap_hsi_platform_data;
+
+ if (!oh) {
+ pr_err("Could not look up %s omap_hwmod\n",
+ OMAP_HSI_HWMOD_NAME);
+ return -EEXIST;
+ }
+
+ od = omap_device_build(OMAP_HSI_PLATFORM_DEVICE_DRIVER_NAME, 0, oh,
+ pdata, sizeof(*pdata), omap_hsi_latency,
+ ARRAY_SIZE(omap_hsi_latency), false);
+ WARN(IS_ERR(od), "Can't build omap_device for %s:%s.\n",
+ OMAP_HSI_PLATFORM_DEVICE_DRIVER_NAME, oh->name);
+
+ pr_info("HSI: device registered as omap_hwmod: %s\n", oh->name);
+ return 0;
+}
+
+static void __init omap_4430hsi_pad_conf(void)
+{
+ /*
+ * HSI pad conf: hsi1_ca/ac_wake/flag/data/ready
+ * Also configure gpio_92/95/157/187 used by modem
+ */
+ /* hsi1_cawake */
+ omap_mux_init_signal("usbb1_ulpitll_clk.hsi1_cawake", \
+ OMAP_PIN_INPUT_PULLDOWN | \
+ OMAP_PIN_OFF_NONE | \
+ OMAP_PIN_OFF_WAKEUPENABLE);
+ /* hsi1_caflag */
+ omap_mux_init_signal("usbb1_ulpitll_dir.hsi1_caflag", \
+ OMAP_PIN_INPUT | \
+ OMAP_PIN_OFF_NONE);
+ /* hsi1_cadata */
+ omap_mux_init_signal("usbb1_ulpitll_stp.hsi1_cadata", \
+ OMAP_PIN_INPUT | \
+ OMAP_PIN_OFF_NONE);
+ /* hsi1_acready */
+ omap_mux_init_signal("usbb1_ulpitll_nxt.hsi1_acready", \
+ OMAP_PIN_OUTPUT | \
+ OMAP_PIN_OFF_OUTPUT_LOW);
+ /* hsi1_acwake */
+ omap_mux_init_signal("usbb1_ulpitll_dat0.hsi1_acwake", \
+ OMAP_PIN_OUTPUT | \
+ OMAP_PIN_OFF_NONE);
+ /* hsi1_acdata */
+ omap_mux_init_signal("usbb1_ulpitll_dat1.hsi1_acdata", \
+ OMAP_PIN_OUTPUT | \
+ OMAP_PIN_OFF_NONE);
+ /* hsi1_acflag */
+ omap_mux_init_signal("usbb1_ulpitll_dat2.hsi1_acflag", \
+ OMAP_PIN_OUTPUT | \
+ OMAP_PIN_OFF_NONE);
+ /* hsi1_caready */
+ omap_mux_init_signal("usbb1_ulpitll_dat3.hsi1_caready", \
+ OMAP_PIN_INPUT | \
+ OMAP_PIN_OFF_NONE);
+ /* gpio_92 */
+ omap_mux_init_signal("usbb1_ulpitll_dat4.gpio_92", \
+ OMAP_PULL_ENA);
+ /* gpio_95 */
+ omap_mux_init_signal("usbb1_ulpitll_dat7.gpio_95", \
+ OMAP_PIN_INPUT_PULLDOWN | \
+ OMAP_PIN_OFF_NONE);
+ /* gpio_157 */
+ omap_mux_init_signal("usbb2_ulpitll_clk.gpio_157", \
+ OMAP_PIN_OUTPUT | \
+ OMAP_PIN_OFF_NONE);
+ /* gpio_187 */
+ omap_mux_init_signal("sys_boot3.gpio_187", \
+ OMAP_PIN_OUTPUT | \
+ OMAP_PIN_OFF_NONE);
+}
+
+/* HSI devices registration */
+int __init omap_hsi_init(void)
+{
+ omap_4430hsi_pad_conf();
+ /* Keep this for genericity, although there is only one hwmod for HSI */
+ return omap_hwmod_for_each_by_class(OMAP_HSI_HWMOD_CLASSNAME,
+ omap_hsi_register, NULL);
+}
diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
index eadc88e..2614dd3 100644
--- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
@@ -2683,7 +2683,7 @@ static struct omap_hwmod_class_sysconfig omap44xx_hsi_sysc = {
SYSC_HAS_SOFTRESET | SYSS_HAS_RESET_STATUS),
.idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
SIDLE_SMART_WKUP | MSTANDBY_FORCE | MSTANDBY_NO |
- MSTANDBY_SMART),
+ MSTANDBY_SMART | MSTANDBY_SMART_WKUP),
.sysc_fields = &omap_hwmod_sysc_type1,
};
@@ -5624,7 +5624,7 @@ static __initdata struct omap_hwmod *omap44xx_hwmods[] = {
&omap44xx_gpio6_hwmod,
/* hsi class */
-/* &omap44xx_hsi_hwmod, */
+ &omap44xx_hsi_hwmod,
/* gpu class */
&omap44xx_gpu_hwmod,
diff --git a/arch/arm/mach-omap2/opp4xxx_data.c b/arch/arm/mach-omap2/opp4xxx_data.c
index 0eec22a..2d70bd1 100644
--- a/arch/arm/mach-omap2/opp4xxx_data.c
+++ b/arch/arm/mach-omap2/opp4xxx_data.c
@@ -141,7 +141,10 @@ static struct omap_opp_def __initdata omap443x_opp_def_list[] = {
OPP_INITIALIZER("dsp", "dpll_iva_m4x2_ck", "iva", true, 465500000, OMAP4430_VDD_IVA_OPP100_UV),
/* DSP OPP3 - OPPTB */
OPP_INITIALIZER("dsp", "dpll_iva_m4x2_ck", "iva", false, 496000000, OMAP4430_VDD_IVA_OPPTURBO_UV),
-
+ /* HSI OPP1 - OPP50 */
+ OPP_INITIALIZER("hsi", "hsi_fck", "core", true, 96000000, OMAP4430_VDD_CORE_OPP50_UV),
+ /* HSI OPP2 - OPP100 */
+ OPP_INITIALIZER("hsi", "hsi_fck", "core", true, 96000000, OMAP4430_VDD_CORE_OPP100_UV),
/* TODO: add aess */
};
@@ -257,7 +260,6 @@ static struct omap_opp_def __initdata omap446x_opp_def_list[] = {
OPP_INITIALIZER("gpu", "dpll_per_m7x2_ck", "core", true, 307200000, OMAP4460_VDD_CORE_OPP100_UV),
/* SGX OPP3 - OPPOV */
OPP_INITIALIZER("gpu", "dpll_per_m7x2_ck", "core", true, 384000000, OMAP4460_VDD_CORE_OPP100_OV_UV),
-
/* FDIF OPP1 - OPP25 */
OPP_INITIALIZER("fdif", "fdif_fck", "core", true, 32000000, OMAP4430_VDD_CORE_OPP50_UV),
/* FDIF OPP2 - OPP50 */
@@ -270,6 +272,10 @@ static struct omap_opp_def __initdata omap446x_opp_def_list[] = {
OPP_INITIALIZER("dsp", "dpll_iva_m4x2_ck", "iva", true, 465500000, OMAP4430_VDD_IVA_OPP100_UV),
/* DSP OPP3 - OPPTB */
OPP_INITIALIZER("dsp", "dpll_iva_m4x2_ck", "iva", false, 496000000, OMAP4430_VDD_IVA_OPPTURBO_UV),
+ /* HSI OPP1 - OPP50 */
+ OPP_INITIALIZER("hsi", "hsi_fck", "core", true, 96000000, OMAP4460_VDD_CORE_OPP50_UV),
+ /* HSI OPP2 - OPP100 */
+ OPP_INITIALIZER("hsi", "hsi_fck", "core", true, 96000000, OMAP4460_VDD_CORE_OPP100_UV),
/* TODO: add aess */
};
diff --git a/arch/arm/mach-omap2/pm44xx.c b/arch/arm/mach-omap2/pm44xx.c
index fae39a6..7496b32 100644
--- a/arch/arm/mach-omap2/pm44xx.c
+++ b/arch/arm/mach-omap2/pm44xx.c
@@ -94,14 +94,14 @@ void omap4_enter_sleep(unsigned int cpu, unsigned int power_state)
omap_uart_prepare_idle(1);
omap_uart_prepare_idle(2);
omap_uart_prepare_idle(3);
- omap2_gpio_prepare_for_idle(0);
+ //omap2_gpio_prepare_for_idle(0);
omap4_trigger_ioctrl();
}
omap4_enter_lowpower(cpu, power_state);
if (core_next_state < PWRDM_POWER_ON) {
- omap2_gpio_resume_after_idle();
+ //omap2_gpio_resume_after_idle();
omap_uart_resume_idle(0);
omap_uart_resume_idle(1);
omap_uart_resume_idle(2);
@@ -304,6 +304,17 @@ 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 */
+ #define CA_WAKE_MUX_REG (0x4a1000C2)
+ #define CM_L3INIT_HSI_CLKCTRL (0x4a009338)
+ #define HSI_SYSCONFIG (0x4a058010)
+ if (omap_readw(CA_WAKE_MUX_REG) & (1<<15)) {
+ /* Enable HSI module */
+ omap_writel(omap_readl(CM_L3INIT_HSI_CLKCTRL) | 0x1, CM_L3INIT_HSI_CLKCTRL);
+ /* Put HSI in: No-standby and No-idle */
+ omap_writel( (1<<3) | (1<<12), HSI_SYSCONFIG);
+ }
omap4_trigger_ioctrl();
}