diff options
Diffstat (limited to 'arch/arm/mach-omap2')
-rw-r--r-- | arch/arm/mach-omap2/Kconfig | 9 | ||||
-rw-r--r-- | arch/arm/mach-omap2/Makefile | 13 | ||||
-rw-r--r-- | arch/arm/mach-omap2/board-4430sdp.c | 2 | ||||
-rw-r--r-- | arch/arm/mach-omap2/board-omap4panda.c | 7 | ||||
-rw-r--r-- | arch/arm/mach-omap2/board-tuna-bluetooth.c | 295 | ||||
-rw-r--r-- | arch/arm/mach-omap2/board-tuna-display.c | 304 | ||||
-rw-r--r-- | arch/arm/mach-omap2/board-tuna-emif.c | 107 | ||||
-rw-r--r-- | arch/arm/mach-omap2/board-tuna-input.c | 210 | ||||
-rwxr-xr-x | arch/arm/mach-omap2/board-tuna-modems.c | 631 | ||||
-rw-r--r-- | arch/arm/mach-omap2/board-tuna-nfc.c | 112 | ||||
-rw-r--r-- | arch/arm/mach-omap2/board-tuna-power.c | 158 | ||||
-rwxr-xr-x | arch/arm/mach-omap2/board-tuna-sensors.c | 171 | ||||
-rw-r--r-- | arch/arm/mach-omap2/board-tuna-wifi.c | 367 | ||||
-rwxr-xr-x | arch/arm/mach-omap2/board-tuna.c | 889 | ||||
-rw-r--r-- | arch/arm/mach-omap2/board-tuna.h | 39 | ||||
-rw-r--r-- | arch/arm/mach-omap2/omap_hsi.c | 418 | ||||
-rw-r--r-- | arch/arm/mach-omap2/omap_hwmod_44xx_data.c | 4 | ||||
-rw-r--r-- | arch/arm/mach-omap2/opp4xxx_data.c | 10 | ||||
-rw-r--r-- | arch/arm/mach-omap2/pm44xx.c | 15 |
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 = <e_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(<e_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(); } |