diff options
author | Tom Cherry <tcherry@nvidia.com> | 2012-06-05 11:41:56 -0700 |
---|---|---|
committer | Tom Cherry <tcherry@nvidia.com> | 2012-06-05 11:41:56 -0700 |
commit | b46bcc0a3da47431f2711c3d63e9507cfab18ecd (patch) | |
tree | 6b9355395470108f5161840638bf48af0e10f3c1 /arch | |
parent | 63fb092060747250a0dd305bd11018caebe23d65 (diff) | |
parent | f61bdbde09605793cfa05f7c59545c62b5e08aa6 (diff) |
Merge commit 'main-ics-2012.06.04-A5' into HEAD
Conflicts:
drivers/media/video/tegra/nvavp/nvavp_dev.c
Change-Id: I7779b0ce58004f80cccf6193148ac49551ce5da5
Diffstat (limited to 'arch')
55 files changed, 966 insertions, 448 deletions
diff --git a/arch/arm/configs/tegra3_android_defconfig b/arch/arm/configs/tegra3_android_defconfig index 2b4aee13812b..50da47699f9f 100644 --- a/arch/arm/configs/tegra3_android_defconfig +++ b/arch/arm/configs/tegra3_android_defconfig @@ -292,6 +292,7 @@ CONFIG_SPI_TEGRA=y CONFIG_SPI_SLAVE_TEGRA=y CONFIG_DEBUG_GPIO=y CONFIG_GPIO_SYSFS=y +CONFIG_GPIO_RC5T583=y CONFIG_POWER_SUPPLY=y CONFIG_BATTERY_BQ20Z75=y CONFIG_BATTERY_BQ27x00=y @@ -307,6 +308,7 @@ CONFIG_MFD_TPS6586X=y CONFIG_MFD_TPS65910=y CONFIG_MFD_MAX77663=y CONFIG_MFD_TPS6591X=y +CONFIG_MFD_RC5T583=y CONFIG_MFD_TPS80031=y CONFIG_GPADC_TPS80031=y CONFIG_MFD_RICOH583=y @@ -317,6 +319,7 @@ CONFIG_REGULATOR_GPIO=y CONFIG_REGULATOR_USERSPACE_CONSUMER=y CONFIG_REGULATOR_MAX8973=y CONFIG_REGULATOR_MAX77663=y +CONFIG_REGULATOR_RC5T583=y CONFIG_REGULATOR_TPS6586X=y CONFIG_REGULATOR_TPS65910=y CONFIG_REGULATOR_TPS62360=y @@ -332,6 +335,7 @@ CONFIG_VIDEO_HELPER_CHIPS_AUTO=y # CONFIG_TEGRA_AVP is not set # CONFIG_TEGRA_MEDIASERVER is not set CONFIG_TEGRA_NVAVP=y +CONFIG_TEGRA_NVAVP_AUDIO=y CONFIG_VIDEO_OV5650=y CONFIG_VIDEO_OV5640=y CONFIG_VIDEO_OV9726=y @@ -441,7 +445,7 @@ CONFIG_EFI_PARTITION=y CONFIG_NLS_CODEPAGE_437=y CONFIG_NLS_ISO8859_1=y CONFIG_PRINTK_TIME=y -CONFIG_MAGIC_SYSRQ=y +# CONFIG_MAGIC_SYSRQ is not set CONFIG_DEBUG_SECTION_MISMATCH=y CONFIG_DEBUG_FS=y CONFIG_LOCKUP_DETECTOR=y diff --git a/arch/arm/configs/tegra_android_defconfig b/arch/arm/configs/tegra_android_defconfig index a129a8ee5a10..3cb78ad0741e 100644 --- a/arch/arm/configs/tegra_android_defconfig +++ b/arch/arm/configs/tegra_android_defconfig @@ -371,7 +371,6 @@ CONFIG_EFI_PARTITION=y CONFIG_NLS_CODEPAGE_437=y CONFIG_NLS_ISO8859_1=y CONFIG_PRINTK_TIME=y -CONFIG_MAGIC_SYSRQ=y CONFIG_DEBUG_FS=y CONFIG_LOCKUP_DETECTOR=y # CONFIG_DETECT_HUNG_TASK is not set @@ -384,3 +383,4 @@ CONFIG_CRYPTO_SHA256=y CONFIG_CRYPTO_TWOFISH=y # CONFIG_CRYPTO_ANSI_CPRNG is not set CONFIG_CRYPTO_DEV_TEGRA_AES=y +# CONFIG_MAGIC_SYSRQ is not set diff --git a/arch/arm/configs/tegra_p1852_gnu_linux_defconfig b/arch/arm/configs/tegra_p1852_gnu_linux_defconfig index 6a98b5b8fb49..243eaffccec3 100644 --- a/arch/arm/configs/tegra_p1852_gnu_linux_defconfig +++ b/arch/arm/configs/tegra_p1852_gnu_linux_defconfig @@ -31,6 +31,7 @@ CONFIG_ARCH_TEGRA_3x_SOC=y CONFIG_TEGRA_PCI=y CONFIG_MACH_P1852=y CONFIG_TEGRA_PWM=y +CONFIG_TEGRA_P1852_TDM=y # CONFIG_TEGRA_CPU_DVFS is not set CONFIG_TEGRA_CLOCK_DEBUG_WRITE=y # CONFIG_TEGRA_MC_EARLY_ACK is not set diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig index 82306bc4aff5..c11ea97941a2 100644 --- a/arch/arm/mach-tegra/Kconfig +++ b/arch/arm/mach-tegra/Kconfig @@ -24,6 +24,7 @@ config ARCH_TEGRA_2x_SOC select ARM_ERRATA_716044 select ARM_ERRATA_764369 if SMP select ARCH_HAS_SUSPEND_PAGETABLE + select NVMAP_CACHE_MAINT_BY_SET_WAYS help Support for NVIDIA Tegra AP20 and T20 processors, based on the ARM CortexA9MP CPU and the ARM PL310 L2 cache controller @@ -51,6 +52,7 @@ config ARCH_TEGRA_3x_SOC select TEGRA_LP2_ARM_TWD if HAVE_ARM_TWD && !TEGRA_RAIL_OFF_MULTIPLE_CPUS select CPA select ARCH_HAS_SUSPEND_PAGETABLE + select NVMAP_CACHE_MAINT_BY_SET_WAYS help Support for NVIDIA Tegra 3 family of SoCs, based upon the ARM CortexA9MP CPU and the ARM PL310 L2 cache controller @@ -254,6 +256,14 @@ config TEGRA_FIQ_DEBUGGER help Enables the FIQ serial debugger on Tegra +config TEGRA_P1852_TDM + bool "Enable TDM mode for P1852 SKUs" + default n + depends on MACH_P1852 + help + Enables TDM mode driver for P1852 SKUs. If this + is not defined then I2S mode is selected by default. + config TEGRA_CARDHU_DSI bool "Support DSI panel on Cardhu" depends on MACH_CARDHU diff --git a/arch/arm/mach-tegra/Makefile b/arch/arm/mach-tegra/Makefile index 3153203c6efc..9acb8305a175 100644 --- a/arch/arm/mach-tegra/Makefile +++ b/arch/arm/mach-tegra/Makefile @@ -67,6 +67,7 @@ obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra2_emc.o obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += tegra3_emc.o obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += wakeups-t2.o obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += wakeups-t3.o +obj-y += wakeups.o obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += pm-t2.o obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += pm-t3.o diff --git a/arch/arm/mach-tegra/baseband-xmm-power.c b/arch/arm/mach-tegra/baseband-xmm-power.c index 4da5d412cf41..30aba86f02f1 100644 --- a/arch/arm/mach-tegra/baseband-xmm-power.c +++ b/arch/arm/mach-tegra/baseband-xmm-power.c @@ -187,10 +187,36 @@ static int baseband_modem_power_on(struct baseband_power_platform_data *data) /* set IPC_HSIC_ACTIVE active */ gpio_set_value(data->modem.xmm.ipc_hsic_active, 1); + /* wait 20 ms */ + mdelay(20); + /* reset / power on sequence */ - msleep(40); + mdelay(40); gpio_set_value(data->modem.xmm.bb_rst, 1); mdelay(1); + + gpio_set_value(data->modem.xmm.bb_on, 1); + udelay(70); + gpio_set_value(data->modem.xmm.bb_on, 0); + + return 0; +} + +/* this function can sleep, do not call in atomic context */ +static int baseband_modem_power_on_async( + struct baseband_power_platform_data *data) +{ + /* set IPC_HSIC_ACTIVE active */ + gpio_set_value(data->modem.xmm.ipc_hsic_active, 1); + + /* wait 20 ms */ + msleep(20); + + /* reset / power on sequence */ + msleep(40); + gpio_set_value(data->modem.xmm.bb_rst, 1); + usleep_range(1000, 2000); + gpio_set_value(data->modem.xmm.bb_on, 1); udelay(70); gpio_set_value(data->modem.xmm.bb_on, 0); @@ -251,8 +277,9 @@ static int xmm_power_on(struct platform_device *device) if (pdata->hsic_register) data->hsic_device = pdata->hsic_register(); /* turn on modem */ - pr_debug("%s call baseband_modem_power_on\n", __func__); - baseband_modem_power_on(pdata); + pr_debug("%s call baseband_modem_power_on_async\n", + __func__); + baseband_modem_power_on_async(pdata); } } ret = enable_irq_wake(gpio_to_irq(pdata->modem.xmm.ipc_ap_wake)); @@ -302,11 +329,12 @@ static int xmm_power_off(struct platform_device *device) gpio_set_value(pdata->modem.xmm.ipc_hsic_active, 0); /* wait 20 ms */ - mdelay(20); + msleep(20); /* drive bb_rst low */ gpio_set_value(pdata->modem.xmm.bb_rst, 0); - mdelay(1); + /* sleep 1ms */ + usleep_range(1000, 2000); baseband_xmm_powerstate = BBXMM_PS_UNINIT; modem_sleep_flag = false; @@ -484,6 +512,7 @@ EXPORT_SYMBOL_GPL(baseband_xmm_set_power_status); irqreturn_t xmm_power_ipc_ap_wake_irq(int irq, void *dev_id) { struct baseband_power_platform_data *data = xmm_power_drv_data.pdata; + struct xmm_power_data *drv = &xmm_power_drv_data; int value; value = gpio_get_value(data->modem.xmm.ipc_ap_wake); @@ -521,6 +550,12 @@ irqreturn_t xmm_power_ipc_ap_wake_irq(int irq, void *dev_id) /* modem wakeup part */ if (!value) { pr_debug("%s - falling\n", __func__); + if (drv->hostwake == 0) { + /* AP L2 to L0 wakeup */ + pr_debug("received wakeup ap l2->l0\n"); + drv->hostwake = 1; + wake_up_interruptible(&drv->bb_wait); + } /* First check it a CP ack or CP wake */ value = gpio_get_value(data->modem.xmm.ipc_bb_wake); if (value) { @@ -528,6 +563,7 @@ irqreturn_t xmm_power_ipc_ap_wake_irq(int irq, void *dev_id) ipc_ap_wake_state = IPC_AP_WAKE_L; return IRQ_HANDLED; } + spin_lock(&xmm_lock); wakeup_pending = true; if (system_suspending) { @@ -593,19 +629,19 @@ static void xmm_power_init1_work(struct work_struct *work) } /* wait 100 ms */ - mdelay(100); + msleep(100); /* set IPC_HSIC_ACTIVE low */ gpio_set_value(pdata->modem.xmm.ipc_hsic_active, 0); /* wait 10 ms */ - mdelay(10); + usleep_range(10000, 11000); /* set IPC_HSIC_ACTIVE high */ gpio_set_value(pdata->modem.xmm.ipc_hsic_active, 1); /* wait 20 ms */ - mdelay(20); + msleep(20); pr_debug("%s }\n", __func__); } @@ -654,9 +690,11 @@ static void xmm_power_autopm_resume(struct work_struct *work) static void xmm_power_L2_resume(void) { struct baseband_power_platform_data *pdata = xmm_power_drv_data.pdata; + struct xmm_power_data *drv = &xmm_power_drv_data; int value; - int delay = 10000; /* maxmum delay in msec */ + int delay = 1000; /* maxmum delay in msec */ unsigned long flags; + int ret, rcount = 0; pr_debug("%s\n", __func__); @@ -680,22 +718,30 @@ static void xmm_power_L2_resume(void) pr_info("AP L2->L0\n"); value = gpio_get_value(pdata->modem.xmm.ipc_ap_wake); if (value) { - pr_debug("waiting for host wakeup from CP...\n"); + drv->hostwake = 0; /* wake bb */ gpio_set_value(pdata->modem.xmm.ipc_bb_wake, 1); - do { - mdelay(1); - value = gpio_get_value( - pdata->modem.xmm.ipc_ap_wake); - delay--; - } while ((value) && (delay)); - if (delay) - pr_debug("gpio host wakeup low <-\n"); - else +retry: + /* wait for cp */ + pr_debug("waiting for host wakeup from CP...\n"); + ret = wait_event_interruptible_timeout(drv->bb_wait, + drv->hostwake == 1, msecs_to_jiffies(delay)); + if (ret == 0) { pr_info("!!AP L2->L0 Failed\n"); - } else { + return; + } + if (ret == -ERESTARTSYS) { + if (rcount >= 5) { + pr_info("!!AP L2->L0 Failed\n"); + return; + } + pr_debug("%s: caught signal\n", __func__); + rcount++; + goto retry; + } + pr_debug("Get gpio host wakeup low <-\n"); + } else pr_info("CP already ready\n"); - } } } @@ -723,7 +769,7 @@ static void xmm_power_reset_on(struct baseband_power_platform_data *pdata) gpio_set_value(pdata->modem.xmm.bb_rst, 0); msleep(40); gpio_set_value(pdata->modem.xmm.bb_rst, 1); - mdelay(1); + usleep_range(1000, 2000); gpio_set_value(pdata->modem.xmm.bb_on, 1); udelay(70); gpio_set_value(pdata->modem.xmm.bb_on, 0); @@ -778,6 +824,7 @@ static void xmm_power_work_func(struct work_struct *work) * software directly. */ break; + case BBXMM_WORK_INIT_FLASHLESS_PM_STEP1: pr_debug("BBXMM_WORK_INIT_FLASHLESS_PM_STEP1\n"); pr_info("%s: flashless is not supported here\n", __func__); @@ -915,6 +962,10 @@ static int xmm_power_driver_probe(struct platform_device *device) /* save platform data */ xmm_power_drv_data.pdata = pdata; + /* init wait queue */ + xmm_power_drv_data.hostwake = 1; + init_waitqueue_head(&xmm_power_drv_data.bb_wait); + /* create device file */ err = device_create_file(dev, &dev_attr_xmm_onoff); if (err < 0) { @@ -1041,7 +1092,7 @@ static int xmm_power_driver_handle_resume( struct baseband_power_platform_data *pdata) { int value; - int delay = 1000; /* maxmum delay in msec */ + unsigned long timeout; unsigned long flags; pr_debug("%s\n", __func__); @@ -1064,29 +1115,30 @@ static int xmm_power_driver_handle_resume( value = gpio_get_value(pdata->modem.xmm.ipc_ap_wake); if (value) { pr_info("AP L3 -> L0\n"); - pr_debug("waiting for host wakeup...\n"); /* wake bb */ gpio_set_value(pdata->modem.xmm.ipc_bb_wake, 1); + + /* Wait for max 1 sec */ + timeout = jiffies + HZ; + pr_debug("Current: %lu: timeout %lu\n", jiffies, timeout); do { - mdelay(1); + udelay(100); value = gpio_get_value(pdata->modem.xmm.ipc_ap_wake); - delay--; - } while ((value) && (delay)); - if (delay) + if (!value) + break; + } while (time_before(jiffies, timeout)); + if (!value) pr_debug("gpio host wakeup low <-\n"); else pr_info("!!AP L3->L0 Failed\n"); - - } else { + } else pr_info("CP L3 -> L0\n"); - } + reenable_autosuspend = true; return 0; - } - #ifdef CONFIG_PM static int xmm_power_driver_suspend(struct device *dev) { diff --git a/arch/arm/mach-tegra/baseband-xmm-power.h b/arch/arm/mach-tegra/baseband-xmm-power.h index 1f08e3b6900c..69140891319d 100644 --- a/arch/arm/mach-tegra/baseband-xmm-power.h +++ b/arch/arm/mach-tegra/baseband-xmm-power.h @@ -84,6 +84,9 @@ struct xmm_power_data { struct baseband_power_platform_data *pdata; struct work_struct work; struct platform_device *hsic_device; + wait_queue_head_t bb_wait; + /* host wakeup gpio state*/ + unsigned int hostwake; }; enum baseband_xmm_powerstate_t { diff --git a/arch/arm/mach-tegra/board-aruba-power.c b/arch/arm/mach-tegra/board-aruba-power.c index 4391f6f19b51..b72b82fc144a 100644 --- a/arch/arm/mach-tegra/board-aruba-power.c +++ b/arch/arm/mach-tegra/board-aruba-power.c @@ -26,7 +26,6 @@ #include "pm.h" #include "board.h" -#include "wakeups-t3.h" static int ac_online(void) { diff --git a/arch/arm/mach-tegra/board-cardhu-pm298-power-rails.c b/arch/arm/mach-tegra/board-cardhu-pm298-power-rails.c index f0dc8afa56fe..9168d9719b7c 100644 --- a/arch/arm/mach-tegra/board-cardhu-pm298-power-rails.c +++ b/arch/arm/mach-tegra/board-cardhu-pm298-power-rails.c @@ -1,7 +1,7 @@ /* * arch/arm/mach-tegra/board-cardhu-pm298-power-rails.c * - * Copyright (C) 2011 NVIDIA, Inc. + * Copyright (C) 2011-2012, NVIDIA Corporation. * * 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 @@ -37,7 +37,6 @@ #include "board.h" #include "board-cardhu.h" #include "pm.h" -#include "wakeups-t3.h" #define PMC_CTRL 0x0 #define PMC_CTRL_INTR_LOW BIT(17) @@ -676,7 +675,6 @@ static struct platform_device *fixed_reg_devs_pm269[] = { int __init cardhu_pm298_gpio_switch_regulator_init(void) { - int i; struct board_info board_info; struct platform_device **fixed_reg_devs; int nfixreg_devs; diff --git a/arch/arm/mach-tegra/board-cardhu-pm299-power-rails.c b/arch/arm/mach-tegra/board-cardhu-pm299-power-rails.c index 6d4db73b6ecd..32f07599fea4 100644 --- a/arch/arm/mach-tegra/board-cardhu-pm299-power-rails.c +++ b/arch/arm/mach-tegra/board-cardhu-pm299-power-rails.c @@ -1,7 +1,7 @@ /* * arch/arm/mach-tegra/board-cardhu-pm299-power-rails.c * - * Copyright (C) 2011 NVIDIA, Inc. + * Copyright (C) 2011-2012, NVIDIA Corporation. * * 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 @@ -37,7 +37,6 @@ #include "gpio-names.h" #include "board.h" #include "board-cardhu.h" -#include "wakeups-t3.h" #define PMC_CTRL 0x0 #define PMC_CTRL_INTR_LOW (1 << 17) @@ -666,7 +665,6 @@ static struct platform_device *fixed_reg_devs_pm269[] = { int __init cardhu_pm299_gpio_switch_regulator_init(void) { - int i; struct board_info board_info; struct platform_device **fixed_reg_devs; int nfixreg_devs; diff --git a/arch/arm/mach-tegra/board-cardhu-power.c b/arch/arm/mach-tegra/board-cardhu-power.c index 61b5a15ed5c7..d517d8266204 100644 --- a/arch/arm/mach-tegra/board-cardhu-power.c +++ b/arch/arm/mach-tegra/board-cardhu-power.c @@ -1,7 +1,7 @@ /* * arch/arm/mach-tegra/board-cardhu-power.c * - * Copyright (C) 2011-2012 NVIDIA, Inc. + * Copyright (C) 2011-2012, NVIDIA Corporation. * * 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 @@ -42,7 +42,6 @@ #include "board.h" #include "board-cardhu.h" #include "pm.h" -#include "wakeups-t3.h" #include "tegra3_tsensor.h" #define PMC_CTRL 0x0 @@ -994,7 +993,6 @@ static struct platform_device *fixed_reg_devs_e1291_a04[] = { int __init cardhu_fixed_regulator_init(void) { - int i; struct board_info board_info; struct board_info pmu_board_info; struct board_info display_board_info; diff --git a/arch/arm/mach-tegra/board-cardhu-sdhci.c b/arch/arm/mach-tegra/board-cardhu-sdhci.c index cb0684bcc742..d8be9fe6747f 100644 --- a/arch/arm/mach-tegra/board-cardhu-sdhci.c +++ b/arch/arm/mach-tegra/board-cardhu-sdhci.c @@ -145,6 +145,7 @@ static struct tegra_sdhci_platform_data tegra_sdhci_platform_data2 = { .embedded_sdio = &embedded_sdio_data2, #endif .built_in = 0, + .ocr_mask = MMC_OCR_1V8_MASK, }, #ifndef CONFIG_MMC_EMBEDDED_SDIO .pm_flags = MMC_PM_KEEP_POWER, diff --git a/arch/arm/mach-tegra/board-enterprise-baseband.c b/arch/arm/mach-tegra/board-enterprise-baseband.c index 9143103fd036..f2c94fda7727 100644 --- a/arch/arm/mach-tegra/board-enterprise-baseband.c +++ b/arch/arm/mach-tegra/board-enterprise-baseband.c @@ -69,11 +69,14 @@ static struct gpio modem_gpios[] = { static void baseband_phy_init(void); static void baseband_phy_on(void); -static void baseband_phy_off(void); +static void baseband_pre_phy_off(void); +static void baseband_post_phy_off(void); +static bool ap2mdm_ack_gpio_off = false; static struct tegra_usb_phy_platform_ops ulpi_null_plat_ops = { .init = baseband_phy_init, - .pre_phy_off = baseband_phy_off, + .pre_phy_off = baseband_pre_phy_off, + .post_phy_off = baseband_post_phy_off, .post_phy_on = baseband_phy_on, }; @@ -133,16 +136,65 @@ static void baseband_phy_init(void) pr_info("%s\n", __func__); } -static void baseband_phy_off(void) +static inline void null_phy_set_tristate(bool enable) +{ + int tristate = (enable) ? TEGRA_TRI_TRISTATE : TEGRA_TRI_NORMAL; + + tegra_pinmux_set_tristate(TEGRA_PINGROUP_ULPI_DATA0, tristate); + tegra_pinmux_set_tristate(TEGRA_PINGROUP_ULPI_DATA1, tristate); + tegra_pinmux_set_tristate(TEGRA_PINGROUP_ULPI_DATA2, tristate); + tegra_pinmux_set_tristate(TEGRA_PINGROUP_ULPI_DATA3, tristate); + tegra_pinmux_set_tristate(TEGRA_PINGROUP_ULPI_DATA4, tristate); + tegra_pinmux_set_tristate(TEGRA_PINGROUP_ULPI_DATA5, tristate); + tegra_pinmux_set_tristate(TEGRA_PINGROUP_ULPI_DATA6, tristate); + tegra_pinmux_set_tristate(TEGRA_PINGROUP_ULPI_DATA7, tristate); + tegra_pinmux_set_tristate(TEGRA_PINGROUP_ULPI_NXT, tristate); + + if (enable) + tegra_pinmux_set_tristate(TEGRA_PINGROUP_ULPI_DIR, tristate); +} + + +static void baseband_post_phy_off(void) +{ + null_phy_set_tristate(true); +} + + +static void baseband_pre_phy_off(void) { /* set AP2MDM_ACK2 high */ gpio_set_value(AP2MDM_ACK2, 1); + ap2mdm_ack_gpio_off = true; } static void baseband_phy_on(void) { - /* set AP2MDM_ACK2 low */ - gpio_set_value(AP2MDM_ACK2, 0); + if (ap2mdm_ack_gpio_off) { + + /* driving linestate using GPIO */ + gpio_set_value(ULPI_D0, 0); + gpio_set_value(ULPI_D1, 0); + + /* remove ULPI tristate */ + null_phy_set_tristate(false); + + gpio_set_value(AP2MDM_ACK2, 0); + + if (gpio_is_valid(MDM2AP_ACK2)) { + int retry = 20000; + while (retry) { + /* poll phy_restore_gpio high */ + if (gpio_get_value(MDM2AP_ACK2)) + break; + retry--; + } + + if (retry == 0) + pr_info("phy_restore_gpio timeout\n"); + } + ap2mdm_ack_gpio_off = false; + } } static void baseband_start(void) diff --git a/arch/arm/mach-tegra/board-enterprise-power.c b/arch/arm/mach-tegra/board-enterprise-power.c index c7598ab56139..f32365d808a7 100644 --- a/arch/arm/mach-tegra/board-enterprise-power.c +++ b/arch/arm/mach-tegra/board-enterprise-power.c @@ -44,7 +44,6 @@ #include "board.h" #include "board-enterprise.h" #include "pm.h" -#include "wakeups-t3.h" #include "tegra3_tsensor.h" #define PMC_CTRL 0x0 @@ -298,6 +297,7 @@ static struct tps80031_rtc_platform_data rtc_data = { .tm_min = 2, .tm_sec = 3, }, + .msecure_gpio = TEGRA_GPIO_PF7, }; int battery_charger_init(void *board_data) @@ -746,6 +746,8 @@ int __init enterprise_regulator_init(void) battery_gauge_data.battery_present = 0; } + tegra_gpio_enable(TEGRA_GPIO_PF7); + if (board_info.fab < BOARD_FAB_A03) { tps_platform.num_subdevs = ARRAY_SIZE(tps80031_devs_a02); tps_platform.subdevs = tps80031_devs_a02; diff --git a/arch/arm/mach-tegra/board-enterprise.c b/arch/arm/mach-tegra/board-enterprise.c index d92ac57dd054..e23a9a468081 100644 --- a/arch/arm/mach-tegra/board-enterprise.c +++ b/arch/arm/mach-tegra/board-enterprise.c @@ -684,7 +684,8 @@ static struct tegra_usb_platform_data tegra_udc_pdata = { .phy_intf = TEGRA_USB_PHY_INTF_UTMI, .op_mode = TEGRA_USB_OPMODE_DEVICE, .u_data.dev = { - .vbus_pmu_irq = 0, + .vbus_pmu_irq = ENT_TPS80031_IRQ_BASE + + TPS80031_INT_VBUS_DET, .vbus_gpio = -1, .charging_supported = false, .remote_wakeup_supported = false, diff --git a/arch/arm/mach-tegra/board-kai-kbc.c b/arch/arm/mach-tegra/board-kai-kbc.c index 928e5de707c9..e55383a1028b 100644 --- a/arch/arm/mach-tegra/board-kai-kbc.c +++ b/arch/arm/mach-tegra/board-kai-kbc.c @@ -90,13 +90,6 @@ int __init kai_keys_init(void) pr_info("Registering gpio keys\n"); - /* Enable gpio mode for other pins */ - for (i = 0; i < kai_keys_platform_data.nbuttons; i++) { - if (kai_keys_platform_data.buttons[i].gpio < 0) - continue; - tegra_gpio_enable(kai_keys_platform_data.buttons[i].gpio); - } - platform_device_register(&kai_keys_device); return 0; diff --git a/arch/arm/mach-tegra/board-kai-panel.c b/arch/arm/mach-tegra/board-kai-panel.c index 4073afe2fc8d..45333840ffb7 100644 --- a/arch/arm/mach-tegra/board-kai-panel.c +++ b/arch/arm/mach-tegra/board-kai-panel.c @@ -111,8 +111,6 @@ static int kai_backlight_init(struct device *dev) if (WARN_ON(ARRAY_SIZE(kai_bl_output_measured) != 256)) pr_err("bl_output array does not have 256 elements\n"); - tegra_gpio_disable(kai_bl_pwm); - ret = gpio_request(kai_bl_enb, "backlight_enb"); if (ret < 0) return ret; @@ -120,8 +118,6 @@ static int kai_backlight_init(struct device *dev) ret = gpio_direction_output(kai_bl_enb, 1); if (ret < 0) gpio_free(kai_bl_enb); - else - tegra_gpio_enable(kai_bl_enb); return ret; }; @@ -132,7 +128,6 @@ static void kai_backlight_exit(struct device *dev) /*ret = gpio_request(kai_bl_enb, "backlight_enb");*/ gpio_set_value(kai_bl_enb, 0); gpio_free(kai_bl_enb); - tegra_gpio_disable(kai_bl_enb); return; } @@ -654,35 +649,27 @@ int __init kai_panel_init(void) #endif gpio_request(kai_lvds_avdd_en, "lvds_avdd_en"); gpio_direction_output(kai_lvds_avdd_en, 1); - tegra_gpio_enable(kai_lvds_avdd_en); gpio_request(kai_lvds_stdby, "lvds_stdby"); gpio_direction_output(kai_lvds_stdby, 1); - tegra_gpio_enable(kai_lvds_stdby); gpio_request(kai_lvds_rst, "lvds_rst"); gpio_direction_output(kai_lvds_rst, 1); - tegra_gpio_enable(kai_lvds_rst); if (board_info.fab == BOARD_FAB_A00) { gpio_request(kai_lvds_rs_a00, "lvds_rs"); gpio_direction_output(kai_lvds_rs_a00, 0); - tegra_gpio_enable(kai_lvds_rs_a00); } else { gpio_request(kai_lvds_rs, "lvds_rs"); gpio_direction_output(kai_lvds_rs, 0); - tegra_gpio_enable(kai_lvds_rs); } gpio_request(kai_lvds_lr, "lvds_lr"); gpio_direction_output(kai_lvds_lr, 1); - tegra_gpio_enable(kai_lvds_lr); gpio_request(kai_lvds_shutdown, "lvds_shutdown"); gpio_direction_output(kai_lvds_shutdown, 1); - tegra_gpio_enable(kai_lvds_shutdown); - tegra_gpio_enable(kai_hdmi_hpd); gpio_request(kai_hdmi_hpd, "hdmi_hpd"); gpio_direction_input(kai_hdmi_hpd); diff --git a/arch/arm/mach-tegra/board-kai-pinmux.c b/arch/arm/mach-tegra/board-kai-pinmux.c index fa750f15ca7e..be11d4ef6698 100644 --- a/arch/arm/mach-tegra/board-kai-pinmux.c +++ b/arch/arm/mach-tegra/board-kai-pinmux.c @@ -449,13 +449,9 @@ static __initdata struct tegra_pingroup_config unused_pins_lowpower[] = { static void __init kai_pinmux_audio_init(void) { - tegra_gpio_enable(TEGRA_GPIO_CDC_IRQ); gpio_request(TEGRA_GPIO_CDC_IRQ, "rt5640"); gpio_direction_input(TEGRA_GPIO_CDC_IRQ); - tegra_gpio_enable(TEGRA_GPIO_HP_DET); - tegra_gpio_enable(TEGRA_GPIO_INT_MIC_EN); - tegra_gpio_enable(TEGRA_GPIO_EXT_MIC_EN); } /* We are disabling this code for now. */ @@ -551,7 +547,6 @@ static void set_unused_pin_gpio(struct gpio_init_pin_info *lpm_pin_info, gpio_free(pin_info->gpio_nr); continue; } - tegra_gpio_enable(pin_info->gpio_nr); } } diff --git a/arch/arm/mach-tegra/board-kai-power.c b/arch/arm/mach-tegra/board-kai-power.c index e89b2bd2246d..cc3b35608c98 100644 --- a/arch/arm/mach-tegra/board-kai-power.c +++ b/arch/arm/mach-tegra/board-kai-power.c @@ -40,7 +40,6 @@ #include "board.h" #include "board-kai.h" #include "pm.h" -#include "wakeups-t3.h" #include "tegra3_tsensor.h" #define PMC_CTRL 0x0 @@ -567,8 +566,6 @@ static int __init kai_fixed_regulator_init(void) fixed_reg_devs[i]->dev.platform_data; gpio_nr = fixed_reg_pdata->gpio; - if (gpio_nr < TEGRA_NR_GPIOS) - tegra_gpio_enable(gpio_nr); } return platform_add_devices(fixed_reg_devs, nfixreg_devs); diff --git a/arch/arm/mach-tegra/board-kai-sdhci.c b/arch/arm/mach-tegra/board-kai-sdhci.c index 8d1d4a9bd4a8..0fa39ccf475d 100644 --- a/arch/arm/mach-tegra/board-kai-sdhci.c +++ b/arch/arm/mach-tegra/board-kai-sdhci.c @@ -106,6 +106,7 @@ static struct tegra_sdhci_platform_data tegra_sdhci_platform_data2 = { .mmc_data = { .register_status_notify = kai_wifi_status_register, .built_in = 0, + .ocr_mask = MMC_OCR_1V8_MASK, }, #ifndef CONFIG_MMC_EMBEDDED_SDIO .pm_flags = MMC_PM_KEEP_POWER, @@ -243,9 +244,6 @@ static int __init kai_wifi_init(void) if (rc) pr_err("WLAN_IRQ gpio request failed:%d\n", rc); - tegra_gpio_enable(KAI_WLAN_EN); - tegra_gpio_enable(KAI_WLAN_IRQ); - rc = gpio_direction_output(KAI_WLAN_EN, 0); if (rc) pr_err("WLAN_EN gpio direction configuration failed:%d\n", rc); diff --git a/arch/arm/mach-tegra/board-kai-sensors.c b/arch/arm/mach-tegra/board-kai-sensors.c index 9564aaf0cfde..c545b2d0d786 100644 --- a/arch/arm/mach-tegra/board-kai-sensors.c +++ b/arch/arm/mach-tegra/board-kai-sensors.c @@ -135,9 +135,6 @@ static int kai_nct1008_init(void) pr_err("%s: set gpio to input failed\n", __func__); gpio_free(KAI_TEMP_ALERT_GPIO); } - else - tegra_gpio_enable(KAI_TEMP_ALERT_GPIO); - return ret; } @@ -158,7 +155,6 @@ static int kai_camera_init(void) { int ret; - tegra_gpio_enable(CAM2_POWER_DWN_GPIO); ret = gpio_request(CAM2_POWER_DWN_GPIO, "cam2_power_en"); if (ret < 0) { pr_err("%s: gpio_request failed for gpio %s\n", @@ -168,7 +164,6 @@ static int kai_camera_init(void) gpio_direction_output(CAM2_POWER_DWN_GPIO, 1); mdelay(10); - tegra_gpio_enable(CAM2_RST_GPIO); ret = gpio_request(CAM2_RST_GPIO, "cam2_reset"); if (ret < 0) { pr_err("%s: gpio_request failed for gpio %s\n", @@ -314,7 +309,6 @@ static void mpuirq_init(void) #if (MPU_GYRO_TYPE == MPU_TYPE_MPU3050) #if MPU_ACCEL_IRQ_GPIO /* ACCEL-IRQ assignment */ - tegra_gpio_enable(MPU_ACCEL_IRQ_GPIO); ret = gpio_request(MPU_ACCEL_IRQ_GPIO, MPU_ACCEL_NAME); if (ret < 0) { pr_err("%s: gpio_request failed %d\n", __func__, ret); @@ -331,7 +325,6 @@ static void mpuirq_init(void) #endif /* MPU-IRQ assignment */ - tegra_gpio_enable(MPU_GYRO_IRQ_GPIO); ret = gpio_request(MPU_GYRO_IRQ_GPIO, MPU_GYRO_NAME); if (ret < 0) { pr_err("%s: gpio_request failed %d\n", __func__, ret); diff --git a/arch/arm/mach-tegra/board-kai.c b/arch/arm/mach-tegra/board-kai.c index 193d68632d52..86374cf27271 100644 --- a/arch/arm/mach-tegra/board-kai.c +++ b/arch/arm/mach-tegra/board-kai.c @@ -108,7 +108,6 @@ static noinline void __init kai_bt_st(void) platform_device_register(&wl128x_device); platform_device_register(&btwilink_device); - tegra_gpio_enable(TEGRA_GPIO_PU0); } static struct resource kai_bluesleep_resources[] = { @@ -620,9 +619,6 @@ static int __init kai_touch_init(void) { int touch_id; - tegra_gpio_enable(KAI_TS_ID1); - tegra_gpio_enable(KAI_TS_ID2); - gpio_request(KAI_TS_ID1, "touch-id1"); gpio_direction_input(KAI_TS_ID1); @@ -764,10 +760,6 @@ static void kai_modem_init(void) { int ret; - tegra_gpio_enable(TEGRA_GPIO_W_DISABLE); - tegra_gpio_enable(TEGRA_GPIO_MODEM_RSVD1); - tegra_gpio_enable(TEGRA_GPIO_MODEM_RSVD2); - ret = gpio_request(TEGRA_GPIO_W_DISABLE, "w_disable_gpio"); if (ret < 0) pr_err("%s: gpio_request failed for gpio %d\n", @@ -813,13 +805,6 @@ static void kai_audio_init(void) } } -static void kai_nfc_init(void) -{ - tegra_gpio_enable(TEGRA_GPIO_PX0); - tegra_gpio_enable(TEGRA_GPIO_PS7); - tegra_gpio_enable(TEGRA_GPIO_PR3); -} - static void __init tegra_kai_init(void) { tegra_thermal_init(&thermal_data); @@ -843,7 +828,6 @@ static void __init tegra_kai_init(void) kai_panel_init(); kai_bt_st(); kai_tegra_setup_tibluesleep(); - kai_nfc_init(); kai_sensors_init(); kai_pins_state_init(); kai_emc_init(); diff --git a/arch/arm/mach-tegra/board-p1852-pinmux.c b/arch/arm/mach-tegra/board-p1852-pinmux.c index 1503c80c8269..9133c7daa972 100644 --- a/arch/arm/mach-tegra/board-p1852-pinmux.c +++ b/arch/arm/mach-tegra/board-p1852-pinmux.c @@ -63,14 +63,21 @@ /* !!!FIXME!!!! Update drive strength with characterized value */ static __initdata struct tegra_drive_pingroup_config p1852_drive_pinmux[] = { - SET_DRIVE(DAP2, DISABLE, ENABLE, DIV_1, 31, 31, FASTEST, FASTEST), + /* ATC1 CFG */ + SET_DRIVE(AT1, ENABLE, ENABLE, DIV_1, 0, 0, SLOWEST, SLOWEST), + /* ATC2 CFG */ + SET_DRIVE(AT2, ENABLE, ENABLE, DIV_1, 0, 0, SLOWEST, SLOWEST), + /* ATC3 CFG */ + SET_DRIVE(AT3, ENABLE, ENABLE, DIV_1, 0, 0, SLOWEST, SLOWEST), + /* ATC4 CFG */ + SET_DRIVE(AT4, DISABLE, DISABLE, DIV_1, 0, 0, SLOWEST, SLOWEST), /* All I2C pins are driven to maximum drive strength */ /* GEN1 I2C */ SET_DRIVE(DBG, DISABLE, ENABLE, DIV_1, 31, 31, FASTEST, FASTEST), /* GEN2 I2C */ - SET_DRIVE(AT5, DISABLE, ENABLE, DIV_1, 31, 31, FASTEST, FASTEST), + SET_DRIVE(AT5, DISABLE, ENABLE, DIV_1, 12, 30, FASTEST, FASTEST), /* DDC I2C */ SET_DRIVE(DDC, DISABLE, ENABLE, DIV_1, 31, 31, FASTEST, FASTEST), @@ -83,6 +90,48 @@ static __initdata struct tegra_drive_pingroup_config p1852_drive_pinmux[] = { SET_DRIVE(GMF, DISABLE, ENABLE, DIV_1, 0, 0, SLOWEST, SLOWEST), SET_DRIVE(GMG, DISABLE, ENABLE, DIV_1, 15, 6, SLOWEST, SLOWEST), SET_DRIVE(GMH, DISABLE, ENABLE, DIV_1, 12, 6, SLOWEST, SLOWEST), + + /* LCD */ + SET_DRIVE(LCD1, DISABLE, ENABLE, DIV_1, 31, 31, FASTEST, FASTEST), + SET_DRIVE(LCD2, DISABLE, ENABLE, DIV_1, 2, 2, FASTEST, FASTEST), + + /* DAP2 */ + SET_DRIVE(DAP2, ENABLE, ENABLE, DIV_1, 0, 0, SLOWEST, SLOWEST), + /* DAP4 */ + SET_DRIVE(DAP4, ENABLE, ENABLE, DIV_1, 0, 0, SLOWEST, SLOWEST), + /* DBG */ + SET_DRIVE(DBG, ENABLE, ENABLE, DIV_1, 20, 0, SLOWEST, SLOWEST), + /* SPI */ + SET_DRIVE(SPI, ENABLE, ENABLE, DIV_1, 0, 0, SLOWEST, SLOWEST), + /* UAA */ + SET_DRIVE(UAA, DISABLE, DISABLE, DIV_1, 0, 0, SLOWEST, SLOWEST), + /* UART2 */ + SET_DRIVE(UART2, ENABLE, ENABLE, DIV_1, 0, 0, SLOWEST, SLOWEST), + /* UART3 */ + SET_DRIVE(UART3, ENABLE, ENABLE, DIV_1, 0, 0, SLOWEST, SLOWEST), + /* GME */ + SET_DRIVE(GME, DISABLE, ENABLE, DIV_1, 1, 4, SLOWEST, SLOWEST), + /* GMF */ + SET_DRIVE(GMF, DISABLE, ENABLE, DIV_1, 0, 0, SLOWEST, SLOWEST), + /* GMG */ + SET_DRIVE(GMG, DISABLE, ENABLE, DIV_1, 3, 0, SLOWEST, SLOWEST), + /* GMH */ + SET_DRIVE(GMH, DISABLE, ENABLE, DIV_1, 0, 12, SLOWEST, SLOWEST), + + /* I2S/TDM */ +#ifdef CONFIG_TEGRA_MODS + SET_DRIVE(DAP1, ENABLE, ENABLE, DIV_1, 20, 20, SLOWEST, SLOWEST), + SET_DRIVE(DAP3, ENABLE, ENABLE, DIV_1, 20, 20, SLOWEST, SLOWEST), +#else + SET_DRIVE(DAP1, ENABLE, ENABLE, DIV_1, 3, 3, SLOWEST, SLOWEST), + SET_DRIVE(DAP3, ENABLE, ENABLE, DIV_1, 3, 3, SLOWEST, SLOWEST), +#endif + + /* SPI */ + SET_DRIVE(UAD, DISABLE, ENABLE, DIV_1, 4, 1, SLOWEST, SLOWEST), + SET_DRIVE(UAB, DISABLE, ENABLE, DIV_1, 4, 1, SLOWEST, SLOWEST), + SET_DRIVE(SDIO3, DISABLE, ENABLE, DIV_8, 4, 1, FASTEST, FASTEST), + }; #define DEFAULT_PINMUX(_pingroup, _mux, _pupd, _tri, _io) \ diff --git a/arch/arm/mach-tegra/board-p1852.c b/arch/arm/mach-tegra/board-p1852.c index 71c12756539d..eebbb24a9871 100644 --- a/arch/arm/mach-tegra/board-p1852.c +++ b/arch/arm/mach-tegra/board-p1852.c @@ -200,12 +200,14 @@ static void __init p1852_uart_init(void) ARRAY_SIZE(p1852_uart_devices)); } -static struct tegra_p1852_platform_data p1852_audio_pdata = { +#if defined(CONFIG_TEGRA_P1852_TDM) +static struct tegra_p1852_platform_data p1852_audio_tdm_pdata = { .codec_info[0] = { .codec_dai_name = "dit-hifi", .cpu_dai_name = "tegra30-i2s.0", .codec_name = "spdif-dit.0", .name = "tegra-i2s-1", + .pcm_driver = "tegra-tdm-pcm-audio", .i2s_format = format_tdm, .master = 1, .num_slots = 4, @@ -218,6 +220,7 @@ static struct tegra_p1852_platform_data p1852_audio_pdata = { .cpu_dai_name = "tegra30-i2s.4", .codec_name = "spdif-dit.1", .name = "tegra-i2s-2", + .pcm_driver = "tegra-tdm-pcm-audio", .i2s_format = format_tdm, .master = 1, .num_slots = 8, @@ -225,9 +228,29 @@ static struct tegra_p1852_platform_data p1852_audio_pdata = { .tx_mask = 0xff, .rx_mask = 0xff, }, - }; - +#else +static struct tegra_p1852_platform_data p1852_audio_i2s_pdata = { + .codec_info[0] = { + .codec_dai_name = "dit-hifi", + .cpu_dai_name = "tegra30-i2s.0", + .codec_name = "spdif-dit.0", + .name = "tegra-i2s-1", + .pcm_driver = "tegra-pcm-audio", + .i2s_format = format_i2s, + .master = 1, + }, + .codec_info[1] = { + .codec_dai_name = "dit-hifi", + .cpu_dai_name = "tegra30-i2s.4", + .codec_name = "spdif-dit.1", + .name = "tegra-i2s-2", + .pcm_driver = "tegra-pcm-audio", + .i2s_format = format_i2s, + .master = 0, + }, +}; +#endif static struct platform_device generic_codec_1 = { .name = "spdif-dit", .id = 0, @@ -241,13 +264,18 @@ static struct platform_device tegra_snd_p1852 = { .name = "tegra-snd-p1852", .id = 0, .dev = { - .platform_data = &p1852_audio_pdata, +#if defined(CONFIG_TEGRA_P1852_TDM) + .platform_data = &p1852_audio_tdm_pdata, +#else + .platform_data = &p1852_audio_i2s_pdata, +#endif }, }; static void p1852_i2s_audio_init(void) { platform_device_register(&tegra_pcm_device); + platform_device_register(&tegra_tdm_pcm_device); platform_device_register(&generic_codec_1); platform_device_register(&generic_codec_2); platform_device_register(&tegra_i2s_device0); diff --git a/arch/arm/mach-tegra/board-ventana-panel.c b/arch/arm/mach-tegra/board-ventana-panel.c index f396557411b8..e848441ef7e0 100644 --- a/arch/arm/mach-tegra/board-ventana-panel.c +++ b/arch/arm/mach-tegra/board-ventana-panel.c @@ -1,7 +1,7 @@ /* * arch/arm/mach-tegra/board-ventana-panel.c * - * Copyright (c) 2010-2012, NVIDIA Corporation. + * Copyright (c) 2010-2012 NVIDIA Corporation. * * 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 @@ -63,8 +63,6 @@ static int ventana_backlight_init(struct device *dev) { ret = gpio_direction_output(ventana_bl_enb, 1); if (ret < 0) gpio_free(ventana_bl_enb); - else - tegra_gpio_enable(ventana_bl_enb); return ret; }; @@ -72,7 +70,6 @@ static int ventana_backlight_init(struct device *dev) { static void ventana_backlight_exit(struct device *dev) { gpio_set_value(ventana_bl_enb, 0); gpio_free(ventana_bl_enb); - tegra_gpio_disable(ventana_bl_enb); } static int ventana_backlight_notify(struct device *unused, int brightness) @@ -392,13 +389,10 @@ int __init ventana_panel_init(void) gpio_request(ventana_lvds_shutdown, "lvds_shdn"); gpio_direction_output(ventana_lvds_shutdown, 1); - tegra_gpio_enable(ventana_lvds_shutdown); - tegra_gpio_enable(ventana_hdmi_enb); gpio_request(ventana_hdmi_enb, "hdmi_5v_en"); gpio_direction_output(ventana_hdmi_enb, 1); - tegra_gpio_enable(ventana_hdmi_hpd); gpio_request(ventana_hdmi_hpd, "hdmi_hpd"); gpio_direction_input(ventana_hdmi_hpd); diff --git a/arch/arm/mach-tegra/board-ventana-power.c b/arch/arm/mach-tegra/board-ventana-power.c index 2acfdfed28e4..aa6f4be203ad 100644 --- a/arch/arm/mach-tegra/board-ventana-power.c +++ b/arch/arm/mach-tegra/board-ventana-power.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2012 NVIDIA, Inc. + * Copyright (C) 2010-2012 NVIDIA Corporation. * * 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 @@ -34,7 +34,6 @@ #include "gpio-names.h" #include "fuse.h" #include "pm.h" -#include "wakeups-t2.h" #include "board.h" #include "board-ventana.h" @@ -47,7 +46,6 @@ int __init ventana_charge_init(void) { gpio_request(CHARGING_DISABLE, "chg_disable"); gpio_direction_output(CHARGING_DISABLE, 0); - tegra_gpio_enable(CHARGING_DISABLE); return 0; } @@ -255,14 +253,6 @@ static struct platform_device *fixed_voltage_regulators[] __initdata = { int __init ventana_fixed_voltage_regulator_init(void) { - int i; - - for (i = 0; i < ARRAY_SIZE(fixed_voltage_regulators); ++i) { - struct fixed_voltage_config *fixed_voltage_regulators_pdata = - fixed_voltage_regulators[i]->dev.platform_data; - if (fixed_voltage_regulators_pdata->gpio < TEGRA_NR_GPIOS) - tegra_gpio_enable(fixed_voltage_regulators_pdata->gpio); - } return platform_add_devices(fixed_voltage_regulators, ARRAY_SIZE(fixed_voltage_regulators)); } @@ -317,7 +307,6 @@ static struct platform_device ventana_charger_device = { int __init ventana_charger_init(void) { - tegra_gpio_enable(AC_PRESENT_GPIO); platform_device_register(&ventana_charger_device); return 0; } diff --git a/arch/arm/mach-tegra/board-ventana-sdhci.c b/arch/arm/mach-tegra/board-ventana-sdhci.c index 188335ac98c5..9d426aadff79 100644 --- a/arch/arm/mach-tegra/board-ventana-sdhci.c +++ b/arch/arm/mach-tegra/board-ventana-sdhci.c @@ -1,7 +1,6 @@ /* - * arch/arm/mach-tegra/board-harmony-sdhci.c - * * Copyright (C) 2010 Google, Inc. + * Copyright (C) 2010-2012 NVIDIA Corporation. * * This software is licensed under the terms of the GNU General Public * License version 2, as published by the Free Software Foundation, and @@ -132,6 +131,7 @@ static struct tegra_sdhci_platform_data tegra_sdhci_platform_data0 = { .embedded_sdio = &embedded_sdio_data0, #endif .built_in = 0, + .ocr_mask = MMC_OCR_1V8_MASK, }, #ifndef CONFIG_MMC_EMBEDDED_SDIO .pm_flags = MMC_PM_KEEP_POWER, @@ -257,10 +257,6 @@ static int __init ventana_wifi_init(void) gpio_request(VENTANA_WLAN_RST, "wlan_rst"); gpio_request(VENTANA_WLAN_WOW, "bcmsdh_sdmmc"); - tegra_gpio_enable(VENTANA_WLAN_PWR); - tegra_gpio_enable(VENTANA_WLAN_RST); - tegra_gpio_enable(VENTANA_WLAN_WOW); - gpio_direction_output(VENTANA_WLAN_PWR, 0); gpio_direction_output(VENTANA_WLAN_RST, 0); gpio_direction_input(VENTANA_WLAN_WOW); @@ -274,11 +270,6 @@ static int __init ventana_wifi_init(void) } int __init ventana_sdhci_init(void) { - tegra_gpio_enable(tegra_sdhci_platform_data2.power_gpio); - tegra_gpio_enable(tegra_sdhci_platform_data2.cd_gpio); - tegra_gpio_enable(tegra_sdhci_platform_data2.wp_gpio); - tegra_gpio_enable(tegra_sdhci_platform_data3.power_gpio); - platform_device_register(&tegra_sdhci_device3); platform_device_register(&tegra_sdhci_device2); platform_device_register(&tegra_sdhci_device0); diff --git a/arch/arm/mach-tegra/board-ventana-sensors.c b/arch/arm/mach-tegra/board-ventana-sensors.c index 574bdb25fc2a..be7c179dfad9 100644 --- a/arch/arm/mach-tegra/board-ventana-sensors.c +++ b/arch/arm/mach-tegra/board-ventana-sensors.c @@ -186,7 +186,6 @@ static struct ssl3250a_platform_data ventana_ssl3250a_pdata = { static void ventana_isl29018_init(void) { - tegra_gpio_enable(ISL29018_IRQ_GPIO); gpio_request(ISL29018_IRQ_GPIO, "isl29018"); gpio_direction_input(ISL29018_IRQ_GPIO); } @@ -194,7 +193,6 @@ static void ventana_isl29018_init(void) #ifdef CONFIG_SENSORS_AK8975 static void ventana_akm8975_init(void) { - tegra_gpio_enable(AKM8975_IRQ_GPIO); gpio_request(AKM8975_IRQ_GPIO, "akm8975"); gpio_direction_input(AKM8975_IRQ_GPIO); } @@ -202,7 +200,6 @@ static void ventana_akm8975_init(void) static void ventana_nct1008_init(void) { - tegra_gpio_enable(NCT1008_THERM2_GPIO); gpio_request(NCT1008_THERM2_GPIO, "temp_alert"); gpio_direction_input(NCT1008_THERM2_GPIO); } @@ -379,7 +376,6 @@ static void mpuirq_init(void) #if (MPU_GYRO_TYPE == MPU_TYPE_MPU3050) #if MPU_ACCEL_IRQ_GPIO /* ACCEL-IRQ assignment */ - tegra_gpio_enable(MPU_ACCEL_IRQ_GPIO); ret = gpio_request(MPU_ACCEL_IRQ_GPIO, MPU_ACCEL_NAME); if (ret < 0) { pr_err("%s: gpio_request failed %d\n", __func__, ret); @@ -396,7 +392,6 @@ static void mpuirq_init(void) #endif /* MPU-IRQ assignment */ - tegra_gpio_enable(MPU_GYRO_IRQ_GPIO); ret = gpio_request(MPU_GYRO_IRQ_GPIO, MPU_GYRO_NAME); if (ret < 0) { pr_err("%s: gpio_request failed %d\n", __func__, ret); @@ -465,37 +460,35 @@ int __init ventana_sensors_init(void) struct tegra_camera_gpios { const char *name; int gpio; - bool tegra_internal_gpio; int enabled; }; -#define TEGRA_CAMERA_GPIO(_name, _gpio, _tegra_internal_gpio, _enabled) \ +#define TEGRA_CAMERA_GPIO(_name, _gpio, _enabled) \ { \ .name = _name, \ .gpio = _gpio, \ - .tegra_internal_gpio = _tegra_internal_gpio, \ .enabled = _enabled, \ } static struct tegra_camera_gpios ventana_camera_gpio_keys[] = { - [0] = TEGRA_CAMERA_GPIO("camera_power_en", CAMERA_POWER_GPIO, true, 1), - [1] = TEGRA_CAMERA_GPIO("camera_csi_sel", CAMERA_CSI_MUX_SEL_GPIO, true, 0), - [2] = TEGRA_CAMERA_GPIO("torch_gpio_act", CAMERA_FLASH_ACT_GPIO, true, 0), + [0] = TEGRA_CAMERA_GPIO("camera_power_en", CAMERA_POWER_GPIO, 1), + [1] = TEGRA_CAMERA_GPIO("camera_csi_sel", CAMERA_CSI_MUX_SEL_GPIO, 0), + [2] = TEGRA_CAMERA_GPIO("torch_gpio_act", CAMERA_FLASH_ACT_GPIO, 0), - [3] = TEGRA_CAMERA_GPIO("en_avdd_csi", AVDD_DSI_CSI_ENB_GPIO, false, 1), - [4] = TEGRA_CAMERA_GPIO("cam_i2c_mux_rst_lo", CAM_I2C_MUX_RST_GPIO, false, 1), + [3] = TEGRA_CAMERA_GPIO("en_avdd_csi", AVDD_DSI_CSI_ENB_GPIO, 1), + [4] = TEGRA_CAMERA_GPIO("cam_i2c_mux_rst_lo", CAM_I2C_MUX_RST_GPIO, 1), - [5] = TEGRA_CAMERA_GPIO("cam2_af_pwdn_lo", CAM2_AF_PWR_DN_L_GPIO, false, 0), - [6] = TEGRA_CAMERA_GPIO("cam2_pwdn", CAM2_PWR_DN_GPIO, false, 0), - [7] = TEGRA_CAMERA_GPIO("cam2_rst_lo", CAM2_RST_L_GPIO, false, 1), + [5] = TEGRA_CAMERA_GPIO("cam2_af_pwdn_lo", CAM2_AF_PWR_DN_L_GPIO, 0), + [6] = TEGRA_CAMERA_GPIO("cam2_pwdn", CAM2_PWR_DN_GPIO, 0), + [7] = TEGRA_CAMERA_GPIO("cam2_rst_lo", CAM2_RST_L_GPIO, 1), - [8] = TEGRA_CAMERA_GPIO("cam3_af_pwdn_lo", CAM3_AF_PWR_DN_L_GPIO, false, 0), - [9] = TEGRA_CAMERA_GPIO("cam3_pwdn", CAM3_PWR_DN_GPIO, false, 0), - [10] = TEGRA_CAMERA_GPIO("cam3_rst_lo", CAM3_RST_L_GPIO, false, 1), + [8] = TEGRA_CAMERA_GPIO("cam3_af_pwdn_lo", CAM3_AF_PWR_DN_L_GPIO, 0), + [9] = TEGRA_CAMERA_GPIO("cam3_pwdn", CAM3_PWR_DN_GPIO, 0), + [10] = TEGRA_CAMERA_GPIO("cam3_rst_lo", CAM3_RST_L_GPIO, 1), - [11] = TEGRA_CAMERA_GPIO("cam1_af_pwdn_lo", CAM1_AF_PWR_DN_L_GPIO, false, 0), - [12] = TEGRA_CAMERA_GPIO("cam1_pwdn", CAM1_PWR_DN_GPIO, false, 0), - [13] = TEGRA_CAMERA_GPIO("cam1_rst_lo", CAM1_RST_L_GPIO, false, 1), + [11] = TEGRA_CAMERA_GPIO("cam1_af_pwdn_lo", CAM1_AF_PWR_DN_L_GPIO, 0), + [12] = TEGRA_CAMERA_GPIO("cam1_pwdn", CAM1_PWR_DN_GPIO, 0), + [13] = TEGRA_CAMERA_GPIO("cam1_rst_lo", CAM1_RST_L_GPIO, 1), }; int __init ventana_camera_late_init(void) @@ -522,10 +515,6 @@ int __init ventana_camera_late_init(void) i2c_new_device(i2c_get_adapter(3), ventana_i2c3_board_info_tca6416); for (i = 0; i < ARRAY_SIZE(ventana_camera_gpio_keys); i++) { - - if (ventana_camera_gpio_keys[i].tegra_internal_gpio) - tegra_gpio_enable(ventana_camera_gpio_keys[i].gpio); - ret = gpio_request(ventana_camera_gpio_keys[i].gpio, ventana_camera_gpio_keys[i].name); if (ret < 0) { diff --git a/arch/arm/mach-tegra/board-ventana.c b/arch/arm/mach-tegra/board-ventana.c index 779ffdba0f65..942ca44e2a13 100644 --- a/arch/arm/mach-tegra/board-ventana.c +++ b/arch/arm/mach-tegra/board-ventana.c @@ -1,7 +1,7 @@ /* * arch/arm/mach-tegra/board-ventana.c * - * Copyright (c) 2010-2011, NVIDIA Corporation. + * Copyright (c) 2010-2011 NVIDIA Corporation. * * 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 @@ -119,8 +119,6 @@ static struct platform_device ventana_bluesleep_device = { static void __init ventana_setup_bluesleep(void) { platform_device_register(&ventana_bluesleep_device); - tegra_gpio_enable(TEGRA_GPIO_PU6); - tegra_gpio_enable(TEGRA_GPIO_PU1); return; } @@ -326,7 +324,8 @@ static int ventana_wakeup_key(void) unsigned long status = readl(IO_ADDRESS(TEGRA_PMC_BASE) + PMC_WAKE_STATUS); - return status & TEGRA_WAKE_GPIO_PV2 ? KEY_POWER : KEY_RESERVED; + return (status & (1 << TEGRA_WAKE_GPIO_PV2)) ? + KEY_POWER : KEY_RESERVED; } static struct gpio_keys_platform_data ventana_keys_platform_data = { @@ -342,14 +341,6 @@ static struct platform_device ventana_keys_device = { .platform_data = &ventana_keys_platform_data, }, }; - -static void ventana_keys_init(void) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(ventana_keys); i++) - tegra_gpio_enable(ventana_keys[i].gpio); -} #endif static struct platform_device tegra_camera = { @@ -625,10 +616,6 @@ static void __init tegra_ventana_init(void) ventana_touch_init_panjit(); } -#ifdef CONFIG_KEYBOARD_GPIO - ventana_keys_init(); -#endif - ventana_usb_init(); ventana_gps_init(); ventana_panel_init(); diff --git a/arch/arm/mach-tegra/board-whistler-baseband.c b/arch/arm/mach-tegra/board-whistler-baseband.c index eb50fb2f8237..b602cd3f44c1 100644 --- a/arch/arm/mach-tegra/board-whistler-baseband.c +++ b/arch/arm/mach-tegra/board-whistler-baseband.c @@ -26,8 +26,9 @@ static void baseband_phy_init(void); static void baseband_phy_on(void); -static void baseband_phy_off(void); - +static void baseband_pre_phy_off(void); +static void baseband_post_phy_off(void); +static bool ap2mdm_ack_gpio_off = false; static struct wake_lock mdm_wake_lock; static struct gpio modem_gpios[] = { @@ -58,13 +59,14 @@ static __initdata struct tegra_pingroup_config whistler_null_ulpi_pinmux[] = { static struct tegra_usb_phy_platform_ops ulpi_null_plat_ops = { .init = baseband_phy_init, - .pre_phy_off = baseband_phy_off, + .pre_phy_off = baseband_pre_phy_off, + .post_phy_off = baseband_post_phy_off, .post_phy_on = baseband_phy_on, }; static struct tegra_usb_platform_data tegra_ehci2_ulpi_null_pdata = { .port_otg = false, - .has_hostpc = true, + .has_hostpc = false, .phy_intf = TEGRA_USB_PHY_INTF_ULPI_NULL, .op_mode = TEGRA_USB_OPMODE_HOST, .u_data.host = { @@ -105,6 +107,15 @@ static irqreturn_t mdm_start_thread(int irq, void *data) return IRQ_HANDLED; } +static inline void null_phy_set_tristate(bool enable) +{ + int tristate = (enable) ? TEGRA_TRI_TRISTATE : TEGRA_TRI_NORMAL; + + tegra_pinmux_set_tristate(TEGRA_PINGROUP_UDA, tristate); + tegra_pinmux_set_tristate(TEGRA_PINGROUP_UAA, tristate); + tegra_pinmux_set_tristate(TEGRA_PINGROUP_UAB, tristate); +} + static void baseband_phy_init(void) { static bool phy_init; @@ -117,18 +128,51 @@ static void baseband_phy_init(void) pr_info("%s\n", __func__); } -static void baseband_phy_off(void) +static void baseband_pre_phy_off(void) { /* set AP2MDM_ACK2 high */ gpio_set_value(AP2MDM_ACK2, 1); + ap2mdm_ack_gpio_off = true; +} + +static void baseband_post_phy_off(void) +{ + null_phy_set_tristate(true); } -static void baseband_phy_on (void) +static void baseband_phy_on(void) { - /* set AP2MDM_ACK2 low */ - gpio_set_value(AP2MDM_ACK2, 0); + if (ap2mdm_ack_gpio_off) { + + /* driving linestate using GPIO */ + gpio_set_value(ULPI_D0, 0); + gpio_set_value(ULPI_D1, 0); + + /* driving DIR high */ + gpio_set_value(ULPI_DIR, 1); + + /* remove ULPI tristate */ + null_phy_set_tristate(false); + + gpio_set_value(AP2MDM_ACK2, 0); + + if (gpio_is_valid(MDM2AP_ACK2)) { + int retry = 20000; + while (retry) { + /* poll phy_restore_gpio high */ + if (gpio_get_value(MDM2AP_ACK2)) + break; + retry--; + } + + if (retry == 0) + pr_info("phy_restore_gpio timeout\n"); + } + ap2mdm_ack_gpio_off = false; + } } + static void baseband_start(void) { /* diff --git a/arch/arm/mach-tegra/board-whistler-power.c b/arch/arm/mach-tegra/board-whistler-power.c index a0eb6686b0db..67663252e0d9 100644 --- a/arch/arm/mach-tegra/board-whistler-power.c +++ b/arch/arm/mach-tegra/board-whistler-power.c @@ -31,7 +31,6 @@ #include "gpio-names.h" #include "fuse.h" #include "pm.h" -#include "wakeups-t2.h" #include "board.h" #define PMC_CTRL 0x0 diff --git a/arch/arm/mach-tegra/board-whistler-sdhci.c b/arch/arm/mach-tegra/board-whistler-sdhci.c index 2d2a9c8c01f8..491688052858 100644 --- a/arch/arm/mach-tegra/board-whistler-sdhci.c +++ b/arch/arm/mach-tegra/board-whistler-sdhci.c @@ -168,6 +168,7 @@ static struct tegra_sdhci_platform_data tegra_sdhci_platform_data1 = { .embedded_sdio = &embedded_sdio_data1, #endif .built_in = 0, + .ocr_mask = MMC_OCR_1V8_MASK, }, #ifndef CONFIG_MMC_EMBEDDED_SDIO .pm_flags = MMC_PM_KEEP_POWER, diff --git a/arch/arm/mach-tegra/board-whistler.c b/arch/arm/mach-tegra/board-whistler.c index 874ef18900e7..6156c8a8e51d 100644 --- a/arch/arm/mach-tegra/board-whistler.c +++ b/arch/arm/mach-tegra/board-whistler.c @@ -441,7 +441,7 @@ static struct tegra_usb_platform_data tegra_udc_pdata = { .phy_intf = TEGRA_USB_PHY_INTF_UTMI, .op_mode = TEGRA_USB_OPMODE_DEVICE, .u_data.dev = { - .vbus_pmu_irq = 0, + .vbus_pmu_irq = MAX8907C_INT_BASE + MAX8907C_IRQ_VCHG_DC_R, .vbus_gpio = -1, .charging_supported = false, .remote_wakeup_supported = false, diff --git a/arch/arm/mach-tegra/cpu-tegra3.c b/arch/arm/mach-tegra/cpu-tegra3.c index 86a0b1364b3d..5b9ac4f770a2 100644 --- a/arch/arm/mach-tegra/cpu-tegra3.c +++ b/arch/arm/mach-tegra/cpu-tegra3.c @@ -230,7 +230,8 @@ static void tegra_auto_hotplug_work_func(struct work_struct *work) cpu = tegra_get_slowest_cpu_n(); if (cpu < nr_cpu_ids) { up = false; - } else if (!is_lp_cluster() && !no_lp) { + } else if (!is_lp_cluster() && !no_lp && + !pm_qos_request(PM_QOS_MIN_ONLINE_CPUS)) { if(!clk_set_parent(cpu_clk, cpu_lp_clk)) { hp_stats_update(CONFIG_NR_CPUS, true); hp_stats_update(0, false); @@ -299,10 +300,10 @@ static int min_cpus_notify(struct notifier_block *nb, unsigned long n, void *p) { mutex_lock(tegra3_cpu_lock); - if ((n >= 2) && is_lp_cluster()) { + if ((n >= 1) && is_lp_cluster()) { /* make sure cpu rate is within g-mode range before switching */ - unsigned int speed = max( - tegra_getspeed(0), clk_get_min_rate(cpu_g_clk) / 1000); + unsigned int speed = max((unsigned long)tegra_getspeed(0), + clk_get_min_rate(cpu_g_clk) / 1000); tegra_update_cpu_speed(speed); if (!clk_set_parent(cpu_clk, cpu_g_clk)) { diff --git a/arch/arm/mach-tegra/devices.c b/arch/arm/mach-tegra/devices.c index 377772ff4291..44afd0e63fe4 100644 --- a/arch/arm/mach-tegra/devices.c +++ b/arch/arm/mach-tegra/devices.c @@ -1166,6 +1166,11 @@ struct platform_device tegra_pcm_device = { .id = -1, }; +struct platform_device tegra_tdm_pcm_device = { + .name = "tegra-tdm-pcm-audio", + .id = -1, +}; + static struct resource w1_resources[] = { [0] = { .start = INT_OWR, diff --git a/arch/arm/mach-tegra/devices.h b/arch/arm/mach-tegra/devices.h index 97a0c53ccfce..3d0734d1c688 100644 --- a/arch/arm/mach-tegra/devices.h +++ b/arch/arm/mach-tegra/devices.h @@ -69,6 +69,7 @@ extern struct platform_device spdif_dit_device; extern struct platform_device bluetooth_dit_device; extern struct platform_device baseband_dit_device; extern struct platform_device tegra_pcm_device; +extern struct platform_device tegra_tdm_pcm_device; extern struct platform_device tegra_w1_device; extern struct platform_device tegra_udc_device; extern struct platform_device tegra_ehci1_device; diff --git a/arch/arm/mach-tegra/include/mach/dc.h b/arch/arm/mach-tegra/include/mach/dc.h index 71f1be769507..87af9441c28c 100644 --- a/arch/arm/mach-tegra/include/mach/dc.h +++ b/arch/arm/mach-tegra/include/mach/dc.h @@ -551,7 +551,6 @@ struct tegra_dc_pwm_params { void tegra_dc_config_pwm(struct tegra_dc *dc, struct tegra_dc_pwm_params *cfg); int tegra_dsi_send_panel_short_cmd(struct tegra_dc *dc, u8 *pdata, u8 data_len); -void tegra_dc_host_trigger(struct tegra_dc *dc); int tegra_dc_update_csc(struct tegra_dc *dc, int win_index); diff --git a/arch/arm/mach-tegra/include/mach/sdhci.h b/arch/arm/mach-tegra/include/mach/sdhci.h index 5dc8cd2ddf76..e307506eb40b 100644 --- a/arch/arm/mach-tegra/include/mach/sdhci.h +++ b/arch/arm/mach-tegra/include/mach/sdhci.h @@ -20,6 +20,14 @@ #include <linux/mmc/host.h> #include <asm/mach/mmc.h> +/* + * MMC_OCR_1V8_MASK will be used in board sdhci file + * Example for cardhu it will be used in board-cardhu-sdhci.c + * for built_in = 0 devices enabling ocr_mask to MMC_OCR_1V8_MASK + * sets the voltage to 1.8V + */ +#define MMC_OCR_1V8_MASK 0x8 + struct tegra_sdhci_platform_data { int cd_gpio; int wp_gpio; diff --git a/arch/arm/mach-tegra/include/mach/tegra_p1852_pdata.h b/arch/arm/mach-tegra/include/mach/tegra_p1852_pdata.h index 6bea4e50b915..501d815b881b 100644 --- a/arch/arm/mach-tegra/include/mach/tegra_p1852_pdata.h +++ b/arch/arm/mach-tegra/include/mach/tegra_p1852_pdata.h @@ -35,6 +35,7 @@ struct codec_info_s { char *cpu_dai_name; char *codec_name; /* Name of the Codec Driver */ char *name; /* Name of the Codec-Dai-Link */ + char *pcm_driver; /* Name of the PCM driver */ enum i2s_data_format i2s_format; int master; /* Codec is Master or Slave */ /* TDM format setttings */ diff --git a/arch/arm/mach-tegra/p852/board-p852.h b/arch/arm/mach-tegra/p852/board-p852.h index bb43febb4a2c..8e8f1444029c 100644 --- a/arch/arm/mach-tegra/p852/board-p852.h +++ b/arch/arm/mach-tegra/p852/board-p852.h @@ -55,7 +55,6 @@ #include "../pm.h" #include "../devices.h" #include "../gpio-names.h" -#include "../wakeups-t2.h" #define P852_SKU3 0x030000UL diff --git a/arch/arm/mach-tegra/pcie.c b/arch/arm/mach-tegra/pcie.c index 80a9a121f193..68e0fda385ae 100644 --- a/arch/arm/mach-tegra/pcie.c +++ b/arch/arm/mach-tegra/pcie.c @@ -36,6 +36,8 @@ #include <linux/slab.h> #include <linux/platform_device.h> #include <linux/regulator/consumer.h> +#include <linux/workqueue.h> +#include <linux/gpio.h> #include <asm/sizes.h> #include <asm/mach/pci.h> @@ -308,6 +310,7 @@ struct tegra_pcie_port { char mem_space_name[16]; char prefetch_space_name[20]; struct resource res[3]; + struct pci_bus* bus; }; struct tegra_pcie_info { @@ -319,6 +322,7 @@ struct tegra_pcie_info { struct resource res_mmio; int power_rails_enabled; int pcie_power_enabled; + struct work_struct hotplug_detect; struct regulator *regulator_hvdd; struct regulator *regulator_pexio; @@ -333,8 +337,6 @@ struct tegra_pcie_info { #define pmc_readl(reg) \ __raw_readl((u32)reg_pmc_base + (reg)) -static void __iomem *reg_pmc_base = IO_ADDRESS(TEGRA_PMC_BASE); - static struct tegra_pcie_info tegra_pcie = { .res_mmio = { .name = "PCI IO", @@ -620,6 +622,31 @@ static struct hw_pci tegra_pcie_hw = { .map_irq = tegra_pcie_map_irq, }; +static void work_hotplug_handler(struct work_struct *work) +{ + struct tegra_pcie_info *pcie_driver = + container_of(work, struct tegra_pcie_info, hotplug_detect); + int val; + + if (pcie_driver->plat_data->gpio == -1) + return; + val = gpio_get_value(pcie_driver->plat_data->gpio); + if (val == 0) { + pr_info("Pcie Dock Connected but hotplug functionality not supported yet\n"); + } else { + struct pci_dev *dev = NULL; + + pr_info("Pcie Dock DisConnected\n"); + for_each_pci_dev(dev) + pci_stop_bus_device(dev); + } +} + +static irqreturn_t gpio_pcie_detect_isr(int irq, void *arg) +{ + schedule_work(&tegra_pcie.hotplug_detect); + return IRQ_HANDLED; +} static irqreturn_t tegra_pcie_isr(int irq, void *arg) { @@ -1169,6 +1196,8 @@ static int tegra_pcie_init(void) pcibios_min_mem = 0x03000000ul; pcibios_min_io = 0x10000000ul; #endif + + INIT_WORK(&tegra_pcie.hotplug_detect, work_hotplug_handler); err = tegra_pcie_get_resources(); if (err) return err; @@ -1184,11 +1213,36 @@ static int tegra_pcie_init(void) } tegra_pcie.pcie_power_enabled = 1; + if (tegra_pcie.plat_data->use_dock_detect) { + unsigned int irq; + + pr_info("acquiring dock_detect = %d\n", + tegra_pcie.plat_data->gpio); + gpio_request(tegra_pcie.plat_data->gpio, "pcie_dock_detect"); + gpio_direction_input(tegra_pcie.plat_data->gpio); + irq = gpio_to_irq(tegra_pcie.plat_data->gpio); + if (irq < 0) { + pr_err("Unable to get irq number for dock_detect\n"); + goto err_irq; + } + err = request_irq(irq, + gpio_pcie_detect_isr, + IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, + "pcie_dock_detect", + (void *)tegra_pcie.plat_data); + if (err < 0) { + pr_err("Unable to claim irq number for dock_detect\n"); + goto err_irq; + } + } + if (tegra_pcie.num_ports) pci_common_init(&tegra_pcie_hw); else err = tegra_pcie_power_off(); +err_irq: + return err; } diff --git a/arch/arm/mach-tegra/pinmux-t3-tables.c b/arch/arm/mach-tegra/pinmux-t3-tables.c index 5e50fede625d..90dbf757b909 100644 --- a/arch/arm/mach-tegra/pinmux-t3-tables.c +++ b/arch/arm/mach-tegra/pinmux-t3-tables.c @@ -3,7 +3,7 @@ * * Common pinmux configurations for Tegra 3 SoCs * - * Copyright (C) 2010-2011 NVIDIA Corporation + * Copyright (C) 2010-2012 NVIDIA Corporation * * 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 @@ -64,11 +64,16 @@ const struct tegra_drive_pingroup_desc tegra_soc_drive_pingroups[TEGRA_MAX_DRIVE_PINGROUP] = { DEFAULT_DRIVE_PINGROUP(AO1, 0x868), DEFAULT_DRIVE_PINGROUP(AO2, 0x86c), - DEFAULT_DRIVE_PINGROUP(AT1, 0x870), - DEFAULT_DRIVE_PINGROUP(AT2, 0x874), - DEFAULT_DRIVE_PINGROUP(AT3, 0x878), - DEFAULT_DRIVE_PINGROUP(AT4, 0x87c), - DEFAULT_DRIVE_PINGROUP(AT5, 0x880), + SET_DRIVE_PINGROUP(AT1, 0x870, 14, 0x1f, 19, 0x1f, + 24, 0x3, 28, 0x3), + SET_DRIVE_PINGROUP(AT2, 0x874, 14, 0x1f, 19, 0x1f, + 24, 0x3, 28, 0x3), + SET_DRIVE_PINGROUP(AT3, 0x878, 14, 0x1f, 19, 0x1f, + 28, 0x3, 30, 0x3), + SET_DRIVE_PINGROUP(AT4, 0x87c, 14, 0x1f, 19, 0x1f, + 28, 0x3, 30, 0x3), + SET_DRIVE_PINGROUP(AT5, 0x880, 14, 0x1f, 19, 0x1f, + 28, 0x3, 30, 0x3), DEFAULT_DRIVE_PINGROUP(CDEV1, 0x884), DEFAULT_DRIVE_PINGROUP(CDEV2, 0x888), DEFAULT_DRIVE_PINGROUP(CSUS, 0x88c), @@ -101,10 +106,14 @@ const struct tegra_drive_pingroup_desc tegra_soc_drive_pingroups[TEGRA_MAX_DRIVE 24, 0xf, 28, 0xf), SET_DRIVE_PINGROUP(GMD, 0x90c, 14, 0x1f, 19, 0x1f, 24, 0xf, 28, 0xf), - DEFAULT_DRIVE_PINGROUP(GME, 0x910), - DEFAULT_DRIVE_PINGROUP(GMF, 0x914), - DEFAULT_DRIVE_PINGROUP(GMG, 0x918), - DEFAULT_DRIVE_PINGROUP(GMH, 0x91c), + SET_DRIVE_PINGROUP(GME, 0x910, 14, 0x1f, 19, 0x1f, + 28, 0x3, 30, 0x3), + SET_DRIVE_PINGROUP(GMF, 0x914, 14, 0x1f, 19, 0x1f, + 28, 0x3, 30, 0x3), + SET_DRIVE_PINGROUP(GMG, 0x918, 14, 0x1f, 19, 0x1f, + 28, 0x3, 30, 0x3), + SET_DRIVE_PINGROUP(GMH, 0x91c, 14, 0x1f, 19, 0x1f, + 28, 0x3, 30, 0x3), DEFAULT_DRIVE_PINGROUP(OWR, 0x920), DEFAULT_DRIVE_PINGROUP(UAD, 0x924), DEFAULT_DRIVE_PINGROUP(GPV, 0x928), diff --git a/arch/arm/mach-tegra/pm-irq.c b/arch/arm/mach-tegra/pm-irq.c index 57d21361ca14..9b205f86f8b9 100644 --- a/arch/arm/mach-tegra/pm-irq.c +++ b/arch/arm/mach-tegra/pm-irq.c @@ -29,6 +29,7 @@ #include <mach/iomap.h> #include "pm-irq.h" +#include "wakeups.h" #define PMC_CTRL 0x0 #define PMC_CTRL_LATCH_WAKEUPS (1 << 5) diff --git a/arch/arm/mach-tegra/pm-irq.h b/arch/arm/mach-tegra/pm-irq.h index 8e87b4bba246..639bfe9c4cc9 100644 --- a/arch/arm/mach-tegra/pm-irq.h +++ b/arch/arm/mach-tegra/pm-irq.h @@ -22,8 +22,6 @@ int tegra_pm_irq_set_wake(int irq, int enable); int tegra_pm_irq_set_wake_type(int irq, int flow_type); bool tegra_pm_irq_lp0_allowed(void); -int tegra_irq_to_wake(int irq); -int tegra_wake_to_irq(int wake); #else static inline int tegra_pm_irq_set_wake_type(int irq, int flow_type) { diff --git a/arch/arm/mach-tegra/tegra2_usb_phy.c b/arch/arm/mach-tegra/tegra2_usb_phy.c index 819721c49a29..7b18333cc77c 100644 --- a/arch/arm/mach-tegra/tegra2_usb_phy.c +++ b/arch/arm/mach-tegra/tegra2_usb_phy.c @@ -1545,6 +1545,189 @@ static int ulpi_link_phy_resume(struct tegra_usb_phy *phy) return status; } + +static int ulpi_null_phy_power_off(struct tegra_usb_phy *phy) +{ + DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst); + + if (!phy->phy_clk_on) { + DBG("%s(%d) inst:[%d] phy clk is already off\n", __func__, + __LINE__, phy->inst); + return 0; + } + + phy->phy_clk_on = false; + phy->hw_accessible = false; + + return 0; +} + +static int ulpi_null_phy_irq(struct tegra_usb_phy *phy) +{ + usb_phy_fence_read(phy); + return IRQ_HANDLED; +} + +static int ulpi_null_phy_lp0_resume(struct tegra_usb_phy *phy) +{ + unsigned long val; + void __iomem *base = phy->regs; + + val = readl(base + USB_USBCMD); + val |= USB_USBCMD_RESET; + writel(val, base + USB_USBCMD); + + if (usb_phy_reg_status_wait(base + USB_USBCMD, + USB_USBCMD_RESET, 0, 2500) < 0) { + pr_err("%s: timeout waiting for reset\n", __func__); + } + + val = readl(base + USB_USBMODE_REG_OFFSET); + val &= ~USB_USBMODE_MASK; + val |= USB_USBMODE_HOST; + writel(val, base + USB_USBMODE_REG_OFFSET); + + val = readl(base + USB_USBCMD); + val |= USB_USBCMD_RS; + writel(val, base + USB_USBCMD); + if (usb_phy_reg_status_wait(base + USB_USBCMD, USB_USBCMD_RS, + USB_USBCMD_RS, 2000)) { + pr_err("%s: timeout waiting for USB_USBCMD_RS\n", __func__); + return -ETIMEDOUT; + } + + /* Enable Port Power */ + val = readl(base + USB_PORTSC); + val |= USB_PORTSC_PP; + writel(val, base + USB_PORTSC); + udelay(10); + + /* disable ULPI pinmux bypass */ + val = readl(base + ULPI_TIMING_CTRL_0); + val &= ~ULPI_OUTPUT_PINMUX_BYP; + writel(val, base + ULPI_TIMING_CTRL_0); + + return 0; +} + +static int ulpi_null_phy_power_on(struct tegra_usb_phy *phy) +{ + unsigned long val; + void __iomem *base = phy->regs; + struct tegra_ulpi_config *config = &phy->pdata->u_cfg.ulpi; + static bool cold_boot = true; + + DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst); + if (phy->phy_clk_on) { + DBG("%s(%d) inst:[%d] phy clk is already On\n", __func__, + __LINE__, phy->inst); + return 0; + } + + val = readl(base + USB_SUSP_CTRL); + val |= UHSIC_RESET; + writel(val, base + USB_SUSP_CTRL); + + val = readl(base + ULPI_TIMING_CTRL_0); + val |= ULPI_OUTPUT_PINMUX_BYP | ULPI_CLKOUT_PINMUX_BYP; + writel(val, base + ULPI_TIMING_CTRL_0); + + val = readl(base + USB_SUSP_CTRL); + val |= ULPI_PHY_ENABLE; + writel(val, base + USB_SUSP_CTRL); + udelay(10); + + /* set timming parameters */ + val = readl(base + ULPI_TIMING_CTRL_0); + val |= ULPI_SHADOW_CLK_LOOPBACK_EN; + val |= ULPI_SHADOW_CLK_SEL; + val |= ULPI_LBK_PAD_EN; + val |= ULPI_SHADOW_CLK_DELAY(config->shadow_clk_delay); + val |= ULPI_CLOCK_OUT_DELAY(config->clock_out_delay); + val |= ULPI_LBK_PAD_E_INPUT_OR; + writel(val, base + ULPI_TIMING_CTRL_0); + + writel(0, base + ULPI_TIMING_CTRL_1); + udelay(10); + + /* start internal 60MHz clock */ + val = readl(base + ULPIS2S_CTRL); + val |= ULPIS2S_ENA; + val |= ULPIS2S_SUPPORT_DISCONNECT; + val |= ULPIS2S_SPARE((phy->pdata->op_mode == TEGRA_USB_OPMODE_HOST) ? 3 : 1); + val |= ULPIS2S_PLLU_MASTER_BLASTER60; + writel(val, base + ULPIS2S_CTRL); + + /* select ULPI_CORE_CLK_SEL to SHADOW_CLK */ + val = readl(base + ULPI_TIMING_CTRL_0); + val |= ULPI_CORE_CLK_SEL; + writel(val, base + ULPI_TIMING_CTRL_0); + udelay(10); + + /* enable ULPI null phy clock - can't set the trimmers before this */ + val = readl(base + ULPI_TIMING_CTRL_0); + val |= ULPI_CLK_OUT_ENA; + writel(val, base + ULPI_TIMING_CTRL_0); + udelay(10); + + if (usb_phy_reg_status_wait(base + USB_SUSP_CTRL, USB_PHY_CLK_VALID, + USB_PHY_CLK_VALID, 2500)) { + pr_err("%s: timeout waiting for phy to stabilize\n", __func__); + return -ETIMEDOUT; + } + + /* set ULPI trimmers */ + ulpi_set_trimmer(phy); + + if (cold_boot) { + val = readl(base + ULPI_TIMING_CTRL_0); + val |= ULPI_CLK_PADOUT_ENA; + writel(val, base + ULPI_TIMING_CTRL_0); + cold_boot = false; + } else { + if (!readl(base + USB_ASYNCLISTADDR)) + ulpi_null_phy_lp0_resume(phy); + } + udelay(10); + + phy->phy_clk_on = true; + phy->hw_accessible = true; + + return 0; +} + + +static int ulpi_null_phy_pre_resume(struct tegra_usb_phy *phy, bool remote_wakeup) +{ + DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst); + + usb_phy_wait_for_sof(phy); + return 0; +} + +static int ulpi_null_phy_resume(struct tegra_usb_phy *phy) +{ + unsigned long val; + void __iomem *base = phy->regs; + + if (!readl(base + USB_ASYNCLISTADDR)) { + /* enable ULPI CLK output pad */ + val = readl(base + ULPI_TIMING_CTRL_0); + val |= ULPI_CLK_PADOUT_ENA; + writel(val, base + ULPI_TIMING_CTRL_0); + + /* enable ULPI pinmux bypass */ + val = readl(base + ULPI_TIMING_CTRL_0); + val |= ULPI_OUTPUT_PINMUX_BYP; + writel(val, base + ULPI_TIMING_CTRL_0); + udelay(5); + } + + return 0; +} + + + static struct tegra_usb_phy_ops utmi_phy_ops = { .open = utmi_phy_open, .close = utmi_phy_close, @@ -1578,7 +1761,14 @@ static struct tegra_usb_phy_ops ulpi_link_phy_ops = { .resume = ulpi_link_phy_resume, }; -static struct tegra_usb_phy_ops ulpi_null_phy_ops; +static struct tegra_usb_phy_ops ulpi_null_phy_ops = { + .irq = ulpi_null_phy_irq, + .power_on = ulpi_null_phy_power_on, + .power_off = ulpi_null_phy_power_off, + .pre_resume = ulpi_null_phy_pre_resume, + .resume = ulpi_null_phy_resume, +}; + static struct tegra_usb_phy_ops icusb_phy_ops; diff --git a/arch/arm/mach-tegra/tegra3_dvfs.c b/arch/arm/mach-tegra/tegra3_dvfs.c index 657a6cfd6510..f36bfa774577 100644 --- a/arch/arm/mach-tegra/tegra3_dvfs.c +++ b/arch/arm/mach-tegra/tegra3_dvfs.c @@ -1,7 +1,7 @@ /* * arch/arm/mach-tegra/tegra3_dvfs.c * - * Copyright (C) 2010-2011 NVIDIA Corporation. + * Copyright (C) 2010-2012, NVIDIA Corporation. * * This software is licensed under the terms of the GNU General Public * License version 2, as published by the Free Software Foundation, and @@ -783,8 +783,6 @@ static void core_cap_update(void) static void core_cap_enable(bool enable) { - int i; - if (enable) tegra3_core_cap.refcnt++; else if (tegra3_core_cap.refcnt) diff --git a/arch/arm/mach-tegra/tegra3_usb_phy.c b/arch/arm/mach-tegra/tegra3_usb_phy.c index 5b3e51974d3b..8ada255cad55 100644 --- a/arch/arm/mach-tegra/tegra3_usb_phy.c +++ b/arch/arm/mach-tegra/tegra3_usb_phy.c @@ -888,6 +888,7 @@ static void uhsic_powerup_pmc_wake_detect(struct tegra_usb_phy *phy) mdelay(1); } +#ifdef KERNEL_WARNING static void usb_phy_power_down_pmc(void) { unsigned long val; @@ -931,6 +932,7 @@ static void usb_phy_power_down_pmc(void) UHSIC_MASTER_ENABLE_P0; writel(val, pmc_base + PMC_SLEEP_CFG); } +#endif static int usb_phy_bringup_host_controller(struct tegra_usb_phy *phy) { @@ -1142,10 +1144,6 @@ static void utmi_phy_close(struct tegra_usb_phy *phy) writel(val, base + USB_SUSP_CTRL); } - val = readl(base + USB_PORTSC); - val |= USB_PORTSC_WKCN; - writel(val, base + USB_PORTSC); - clk_put(phy->utmi_pad_clk); } @@ -1341,16 +1339,20 @@ static int utmi_phy_pre_resume(struct tegra_usb_phy *phy, bool remote_wakeup) unsigned int inst = phy->inst; DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst); - - val = (readl(base + HOSTPC1_DEVLC) >> 25) & + phy->port_speed = (readl(base + HOSTPC1_DEVLC) >> 25) & HOSTPC1_DEVLC_PSPD_MASK; - if (val == USB_PHY_PORT_SPEED_HIGH) { + + if (phy->port_speed == USB_PHY_PORT_SPEED_HIGH) { /* Disable interrupts */ writel(0, base + USB_USBINTR); /* Clear the run bit to stop SOFs - 2LS WAR */ val = readl(base + USB_USBCMD); val &= ~USB_USBCMD_RS; writel(val, base + USB_USBCMD); + if (usb_phy_reg_status_wait(base + USB_USBSTS, USB_USBSTS_HCH, + USB_USBSTS_HCH, 2000)) { + pr_err("%s: timeout waiting for USB_USBSTS_HCH\n", __func__); + } } val = readl(pmc_base + PMC_SLEEP_CFG); @@ -1388,6 +1390,21 @@ static int utmi_phy_power_off(struct tegra_usb_phy *phy) val |= UTMIP_PD_CHRG; writel(val, base + UTMIP_BAT_CHRG_CFG0); } else { + phy->port_speed = (readl(base + HOSTPC1_DEVLC) >> 25) & + HOSTPC1_DEVLC_PSPD_MASK; + + /* Disable interrupts */ + writel(0, base + USB_USBINTR); + + /* Clear the run bit to stop SOFs - 2LS WAR */ + val = readl(base + USB_USBCMD); + val &= ~USB_USBCMD_RS; + writel(val, base + USB_USBCMD); + + if (usb_phy_reg_status_wait(base + USB_USBSTS, USB_USBSTS_HCH, + USB_USBSTS_HCH, 2000)) { + pr_err("%s: timeout waiting for USB_USBSTS_HCH\n", __func__); + } utmip_setup_pmc_wake_detect(phy); } @@ -1409,9 +1426,6 @@ static int utmi_phy_power_off(struct tegra_usb_phy *phy) utmi_phy_pad_power_off(phy); - phy->port_speed = (readl(base + HOSTPC1_DEVLC) >> 25) & - HOSTPC1_DEVLC_PSPD_MASK; - if (phy->pdata->u_data.host.hot_plug) { bool enable_hotplug = true; /* if it is OTG port then make sure to enable hot-plug feature @@ -1776,7 +1790,7 @@ static int uhsic_phy_power_on(struct tegra_usb_phy *phy) DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst); - utmip_powerup_pmc_wake_detect(phy); + uhsic_powerup_pmc_wake_detect(phy); if (phy->phy_clk_on) { DBG("%s(%d) inst:[%d] phy clk is already On\n", @@ -1897,7 +1911,7 @@ static int uhsic_phy_power_off(struct tegra_usb_phy *phy) writel(val, base + USB_SUSP_CTRL); udelay(30); - utmip_powerdown_pmc_wake_detect(phy); + uhsic_powerdown_pmc_wake_detect(phy); phy->phy_clk_on = false; phy->hw_accessible = false; @@ -2153,31 +2167,6 @@ static void ulpi_set_host(void __iomem *base) } - -static inline void null_phy_set_tristate(bool enable) -{ -#ifndef CONFIG_ARCH_TEGRA_2x_SOC - int tristate = (enable) ? TEGRA_TRI_TRISTATE : TEGRA_TRI_NORMAL; - DBG("%s(%d) inst:[%s] FIXME enable pin group +++\n", __func__, - __LINE__, enable ? "TRISTATE" : "NORMAL"); - - tegra_pinmux_set_tristate(TEGRA_PINGROUP_ULPI_DATA0, tristate); - tegra_pinmux_set_tristate(TEGRA_PINGROUP_ULPI_DATA1, tristate); - tegra_pinmux_set_tristate(TEGRA_PINGROUP_ULPI_DATA2, tristate); - tegra_pinmux_set_tristate(TEGRA_PINGROUP_ULPI_DATA3, tristate); - tegra_pinmux_set_tristate(TEGRA_PINGROUP_ULPI_DATA4, tristate); - tegra_pinmux_set_tristate(TEGRA_PINGROUP_ULPI_DATA5, tristate); - tegra_pinmux_set_tristate(TEGRA_PINGROUP_ULPI_DATA6, tristate); - tegra_pinmux_set_tristate(TEGRA_PINGROUP_ULPI_DATA7, tristate); - tegra_pinmux_set_tristate(TEGRA_PINGROUP_ULPI_NXT, tristate); - - if (enable) - tegra_pinmux_set_tristate(TEGRA_PINGROUP_ULPI_DIR, tristate); -#endif - -} - - static int ulpi_null_phy_power_off(struct tegra_usb_phy *phy) { DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst); @@ -2188,8 +2177,6 @@ static int ulpi_null_phy_power_off(struct tegra_usb_phy *phy) return 0; } - null_phy_set_tristate(true); - phy->phy_clk_on = false; phy->hw_accessible = false; @@ -2241,6 +2228,52 @@ static int ulpi_null_phy_cmd_reset(struct tegra_usb_phy *phy) return 0; } +static int ulpi_null_phy_lp0_resume(struct tegra_usb_phy *phy) +{ + unsigned long val; + void __iomem *base = phy->regs; + + ulpi_null_phy_init(phy); + + val = readl(base + USB_USBCMD); + val |= USB_CMD_RESET; + writel(val, base + USB_USBCMD); + + if (usb_phy_reg_status_wait(base + USB_USBCMD, + USB_CMD_RESET, 0, 2500) < 0) { + pr_err("%s: timeout waiting for reset\n", __func__); + } + + val = readl(base + USB_USBMODE); + val &= ~USB_USBMODE_MASK; + val |= USB_USBMODE_HOST; + writel(val, base + USB_USBMODE); + + ulpi_null_phy_cmd_reset(phy); + + val = readl(base + USB_USBCMD); + val |= USB_USBCMD_RS; + writel(val, base + USB_USBCMD); + if (usb_phy_reg_status_wait(base + USB_USBCMD, USB_USBCMD_RS, + USB_USBCMD_RS, 2000)) { + pr_err("%s: timeout waiting for USB_USBCMD_RS\n", __func__); + return -ETIMEDOUT; + } + + /* Enable Port Power */ + val = readl(base + USB_PORTSC); + val |= USB_PORTSC_PP; + writel(val, base + USB_PORTSC); + udelay(10); + + /* disable ULPI pinmux bypass */ + val = readl(base + ULPI_TIMING_CTRL_0); + val &= ~ULPI_OUTPUT_PINMUX_BYP; + writel(val, base + ULPI_TIMING_CTRL_0); + + return 0; +} + static int ulpi_null_phy_power_on(struct tegra_usb_phy *phy) { unsigned long val; @@ -2334,6 +2367,9 @@ static int ulpi_null_phy_power_on(struct tegra_usb_phy *phy) val |= ULPI_CLK_PADOUT_ENA; writel(val, base + ULPI_TIMING_CTRL_0); cold_boot = false; + } else { + if (!readl(base + USB_ASYNCLISTADDR)) + ulpi_null_phy_lp0_resume(phy); } udelay(10); @@ -2352,6 +2388,32 @@ int ulpi_null_phy_pre_resume(struct tegra_usb_phy *phy, bool remote_wakeup) return 0; } +static int ulpi_null_phy_resume(struct tegra_usb_phy *phy) +{ + unsigned long val; + void __iomem *base = phy->regs; + + if (!readl(base + USB_ASYNCLISTADDR)) { + /* enable ULPI CLK output pad */ + val = readl(base + ULPI_TIMING_CTRL_0); + val |= ULPI_CLK_PADOUT_ENA; + writel(val, base + ULPI_TIMING_CTRL_0); + + /* enable ULPI pinmux bypass */ + val = readl(base + ULPI_TIMING_CTRL_0); + val |= ULPI_OUTPUT_PINMUX_BYP; + writel(val, base + ULPI_TIMING_CTRL_0); + udelay(5); +#ifndef CONFIG_ARCH_TEGRA_2x_SOC + /* remove DIR tristate */ + tegra_pinmux_set_tristate(TEGRA_PINGROUP_ULPI_DIR, TEGRA_TRI_NORMAL); +#endif + } + return 0; +} + + + static struct tegra_usb_phy_ops utmi_phy_ops = { .open = utmi_phy_open, .close = utmi_phy_close, @@ -2382,6 +2444,7 @@ static struct tegra_usb_phy_ops ulpi_null_phy_ops = { .power_on = ulpi_null_phy_power_on, .power_off = ulpi_null_phy_power_off, .pre_resume = ulpi_null_phy_pre_resume, + .resume = ulpi_null_phy_resume, .reset = ulpi_null_phy_cmd_reset, }; diff --git a/arch/arm/mach-tegra/tegra_usb_phy.h b/arch/arm/mach-tegra/tegra_usb_phy.h index 36b88db94f52..0375b5aac812 100644 --- a/arch/arm/mach-tegra/tegra_usb_phy.h +++ b/arch/arm/mach-tegra/tegra_usb_phy.h @@ -89,6 +89,7 @@ struct tegra_usb_phy { void __iomem *regs; int inst; bool phy_clk_on; + bool ctrl_clk_on; /* used only for pmu irq */ bool phy_power_on; bool remote_wakeup; bool hw_accessible; diff --git a/arch/arm/mach-tegra/usb_phy.c b/arch/arm/mach-tegra/usb_phy.c index 6f568fd2cd29..bfb9abae2c94 100644 --- a/arch/arm/mach-tegra/usb_phy.c +++ b/arch/arm/mach-tegra/usb_phy.c @@ -131,15 +131,25 @@ int tegra_usb_phy_init_ops(struct tegra_usb_phy *phy) static irqreturn_t usb_phy_dev_vbus_pmu_irq_thr(int irq, void *pdata) { - /* FIXME : Need to enable pmu vbus handling */ + struct tegra_usb_phy *phy = pdata; - return IRQ_NONE; + /* clk is disabled during phy power off and not here*/ + if (!phy->ctrl_clk_on) { + clk_enable(phy->ctrlr_clk); + phy->ctrl_clk_on = true; + } + + return IRQ_HANDLED; } static void tegra_usb_phy_release_clocks(struct tegra_usb_phy *phy) { clk_put(phy->emc_clk); clk_put(phy->sys_clk); + if (phy->pdata->op_mode == TEGRA_USB_OPMODE_HOST) + if (phy->pdata->u_data.host.hot_plug || + phy->pdata->u_data.host.remote_wakeup_supported) + clk_disable(phy->ctrlr_clk); clk_put(phy->ctrlr_clk); clk_disable(phy->pllu_clk); clk_put(phy->pllu_clk); @@ -164,6 +174,11 @@ static int tegra_usb_phy_get_clocks(struct tegra_usb_phy *phy) goto fail_ctrlr_clk; } + if (phy->pdata->op_mode == TEGRA_USB_OPMODE_HOST) + if (phy->pdata->u_data.host.hot_plug || + phy->pdata->u_data.host.remote_wakeup_supported) + clk_enable(phy->ctrlr_clk); + phy->sys_clk = clk_get(&phy->pdev->dev, "sclk"); if (IS_ERR(phy->sys_clk)) { dev_err(&phy->pdev->dev, "Can't get sclk clock\n"); @@ -273,6 +288,8 @@ struct tegra_usb_phy *tegra_usb_phy_open(struct platform_device *pdev) phy->inst); goto fail_init; } + } else { + clk_enable(phy->ctrlr_clk); } } else { if (phy->pdata->u_data.host.vbus_reg) { @@ -365,6 +382,8 @@ void tegra_usb_phy_close(struct tegra_usb_phy *phy) if (phy->pdata->op_mode == TEGRA_USB_OPMODE_DEVICE) { if (phy->pdata->u_data.dev.vbus_pmu_irq) free_irq(phy->pdata->u_data.dev.vbus_pmu_irq, phy); + else + clk_disable(phy->ctrlr_clk); } else { usb_host_vbus_enable(phy, false); @@ -379,8 +398,6 @@ void tegra_usb_phy_close(struct tegra_usb_phy *phy) } } - tegra_usb_phy_release_clocks(phy); - if (phy->vdd_reg) { regulator_disable(phy->vdd_reg); regulator_put(phy->vdd_reg); @@ -392,6 +409,8 @@ void tegra_usb_phy_close(struct tegra_usb_phy *phy) if (phy->pdata->ops && phy->pdata->ops->close) phy->pdata->ops->close(); + tegra_usb_phy_release_clocks(phy); + kfree(phy->pdata); kfree(phy); } @@ -439,7 +458,19 @@ int tegra_usb_phy_power_off(struct tegra_usb_phy *phy) clk_disable(phy->emc_clk); clk_disable(phy->sys_clk); - clk_disable(phy->ctrlr_clk); + if (phy->pdata->op_mode == TEGRA_USB_OPMODE_HOST) { + if (!phy->pdata->u_data.host.hot_plug && + !phy->pdata->u_data.host.remote_wakeup_supported) + clk_disable(phy->ctrlr_clk); + } else { + /* In device mode clock is turned on by pmu irq handler + * if pmu irq is not available clocks will not be turned off/on + */ + if (phy->pdata->u_data.dev.vbus_pmu_irq) { + clk_disable(phy->ctrlr_clk); + phy->ctrl_clk_on = false; + } + } phy->phy_power_on = false; @@ -455,7 +486,20 @@ int tegra_usb_phy_power_on(struct tegra_usb_phy *phy) if (phy->phy_power_on) return status; - clk_enable(phy->ctrlr_clk); + /* In device mode clock is turned on by pmu irq handler + * if pmu irq is not available clocks will not be turned off/on + */ + if (phy->pdata->op_mode == TEGRA_USB_OPMODE_HOST) { + if (!phy->pdata->u_data.host.hot_plug && + !phy->pdata->u_data.host.remote_wakeup_supported) + clk_enable(phy->ctrlr_clk); + } else { + if (phy->pdata->u_data.dev.vbus_pmu_irq && + !phy->ctrl_clk_on) { + clk_enable(phy->ctrlr_clk); + phy->ctrl_clk_on = true; + } + } clk_enable(phy->sys_clk); clk_enable(phy->emc_clk); @@ -506,11 +550,7 @@ int tegra_usb_phy_suspend(struct tegra_usb_phy *phy) err = phy->ops->suspend(phy); if (!err && phy->pdata->u_data.host.power_off_on_suspend) { - if (phy->pdata->ops && phy->pdata->ops->pre_phy_off) - phy->pdata->ops->pre_phy_off(); - err = phy->ops->power_off(phy); - if (phy->pdata->ops && phy->pdata->ops->post_phy_off) - phy->pdata->ops->post_phy_off(); + tegra_usb_phy_power_off(phy); } return err; @@ -550,11 +590,7 @@ int tegra_usb_phy_resume(struct tegra_usb_phy *phy) DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst); if (phy->pdata->u_data.host.power_off_on_suspend) { - if (phy->pdata->ops && phy->pdata->ops->pre_phy_on) - phy->pdata->ops->pre_phy_on(); - err = phy->ops->power_on(phy); - if (phy->pdata->ops && phy->pdata->ops->post_phy_on) - phy->pdata->ops->post_phy_on(); + tegra_usb_phy_power_on(phy); } if (!err && phy->ops && phy->ops->resume) diff --git a/arch/arm/mach-tegra/wakeups-t2.c b/arch/arm/mach-tegra/wakeups-t2.c index 7c5d12ac60d4..8079e6820145 100644 --- a/arch/arm/mach-tegra/wakeups-t2.c +++ b/arch/arm/mach-tegra/wakeups-t2.c @@ -22,8 +22,9 @@ #include <mach/gpio.h> #include "gpio-names.h" +#include "wakeups.h" -static int tegra_wake_event_irq[] = { +static int tegra_wake_event_irq_t2[] = { [0] = TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PO5), [1] = TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PV3), [2] = TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PL1), @@ -57,55 +58,5 @@ static int tegra_wake_event_irq[] = { [30] = TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PN2), }; -int tegra_irq_to_wake(int irq) -{ - int i; - int wake_irq; - int search_gpio; - static int last_wake = -1; - - /* Two level wake irq search for gpio based wakeups - - * 1. check for GPIO irq(based on tegra_wake_event_irq table) - * e.g. for a board, wake7 based on GPIO PU6 and irq==358 done first - * 2. check for gpio bank irq assuming search for GPIO irq - * preceded this search. - * e.g. in this step check for gpio bank irq GPIO6 irq==119 - */ - for (i = 0; i < ARRAY_SIZE(tegra_wake_event_irq); i++) { - /* return if step 1 matches */ - if (tegra_wake_event_irq[i] == irq) { - pr_info("Wake%d for irq=%d\n", i, irq); - last_wake = i; - return i; - } - - /* step 2 below uses saved last_wake from step 1 - * in previous call */ - search_gpio = irq_to_gpio( - tegra_wake_event_irq[i]); - if (search_gpio < 0) - continue; - wake_irq = tegra_gpio_get_bank_int_nr(search_gpio); - if (wake_irq < 0) - continue; - if ((last_wake == i) && - (wake_irq == irq)) { - pr_info("gpio bank wake found: wake%d for irq=%d\n", - i, irq); - return i; - } - } - - return -EINVAL; -} - -int tegra_wake_to_irq(int wake) -{ - if (wake < 0) - return -EINVAL; - - if (wake >= ARRAY_SIZE(tegra_wake_event_irq)) - return -EINVAL; - - return tegra_wake_event_irq[wake]; -} +int *tegra_wake_event_irq = tegra_wake_event_irq_t2; +unsigned int tegra_wake_event_irq_size = ARRAY_SIZE(tegra_wake_event_irq_t2); diff --git a/arch/arm/mach-tegra/wakeups-t2.h b/arch/arm/mach-tegra/wakeups-t2.h index eb193c0aaf9e..955b351a71fa 100644 --- a/arch/arm/mach-tegra/wakeups-t2.h +++ b/arch/arm/mach-tegra/wakeups-t2.h @@ -30,36 +30,36 @@ int tegra_irq_to_wake(int irq); int tegra_wake_to_irq(int wake); -#define TEGRA_WAKE_GPIO_PO5 (1 << 0) -#define TEGRA_WAKE_GPIO_PV3 (1 << 1) -#define TEGRA_WAKE_GPIO_PL1 (1 << 2) -#define TEGRA_WAKE_GPIO_PB6 (1 << 3) -#define TEGRA_WAKE_GPIO_PN7 (1 << 4) -#define TEGRA_WAKE_GPIO_PA0 (1 << 5) -#define TEGRA_WAKE_GPIO_PU5 (1 << 6) -#define TEGRA_WAKE_GPIO_PU6 (1 << 7) -#define TEGRA_WAKE_GPIO_PC7 (1 << 8) -#define TEGRA_WAKE_GPIO_PS2 (1 << 9) -#define TEGRA_WAKE_GPIO_PAA1 (1 << 10) -#define TEGRA_WAKE_GPIO_PW3 (1 << 11) -#define TEGRA_WAKE_GPIO_PW2 (1 << 12) -#define TEGRA_WAKE_GPIO_PY6 (1 << 13) -#define TEGRA_WAKE_GPIO_PV6 (1 << 14) -#define TEGRA_WAKE_GPIO_PJ7 (1 << 15) -#define TEGRA_WAKE_RTC_ALARM (1 << 16) -#define TEGRA_WAKE_KBC_EVENT (1 << 17) -#define TEGRA_WAKE_PWR_INT (1 << 18) -#define TEGRA_WAKE_USB1_VBUS (1 << 19) -#define TEGRA_WAKE_USB3_VBUS (1 << 20) -#define TEGRA_WAKE_USB1_ID (1 << 21) -#define TEGRA_WAKE_USB3_ID (1 << 22) -#define TEGRA_WAKE_GPIO_PI5 (1 << 23) -#define TEGRA_WAKE_GPIO_PV2 (1 << 24) -#define TEGRA_WAKE_GPIO_PS4 (1 << 25) -#define TEGRA_WAKE_GPIO_PS5 (1 << 26) -#define TEGRA_WAKE_GPIO_PS0 (1 << 27) -#define TEGRA_WAKE_GPIO_PQ6 (1 << 28) -#define TEGRA_WAKE_GPIO_PQ7 (1 << 29) -#define TEGRA_WAKE_GPIO_PN2 (1 << 30) +#define TEGRA_WAKE_GPIO_PO5 0 +#define TEGRA_WAKE_GPIO_PV3 1 +#define TEGRA_WAKE_GPIO_PL1 2 +#define TEGRA_WAKE_GPIO_PB6 3 +#define TEGRA_WAKE_GPIO_PN7 4 +#define TEGRA_WAKE_GPIO_PA0 5 +#define TEGRA_WAKE_GPIO_PU5 6 +#define TEGRA_WAKE_GPIO_PU6 7 +#define TEGRA_WAKE_GPIO_PC7 8 +#define TEGRA_WAKE_GPIO_PS2 9 +#define TEGRA_WAKE_GPIO_PAA1 10 +#define TEGRA_WAKE_GPIO_PW3 11 +#define TEGRA_WAKE_GPIO_PW2 12 +#define TEGRA_WAKE_GPIO_PY6 13 +#define TEGRA_WAKE_GPIO_PV6 14 +#define TEGRA_WAKE_GPIO_PJ7 15 +#define TEGRA_WAKE_RTC_ALARM 16 +#define TEGRA_WAKE_KBC_EVENT 17 +#define TEGRA_WAKE_PWR_INT 18 +#define TEGRA_WAKE_USB1_VBUS 19 +#define TEGRA_WAKE_USB3_VBUS 20 +#define TEGRA_WAKE_USB1_ID 21 +#define TEGRA_WAKE_USB3_ID 22 +#define TEGRA_WAKE_GPIO_PI5 23 +#define TEGRA_WAKE_GPIO_PV2 24 +#define TEGRA_WAKE_GPIO_PS4 25 +#define TEGRA_WAKE_GPIO_PS5 26 +#define TEGRA_WAKE_GPIO_PS0 27 +#define TEGRA_WAKE_GPIO_PQ6 28 +#define TEGRA_WAKE_GPIO_PQ7 29 +#define TEGRA_WAKE_GPIO_PN2 30 #endif diff --git a/arch/arm/mach-tegra/wakeups-t3.c b/arch/arm/mach-tegra/wakeups-t3.c index 823736204362..33dfb12f7211 100644 --- a/arch/arm/mach-tegra/wakeups-t3.c +++ b/arch/arm/mach-tegra/wakeups-t3.c @@ -22,8 +22,9 @@ #include <mach/gpio.h> #include "gpio-names.h" +#include "wakeups.h" -static int tegra_wake_event_irq[] = { +static int tegra_wake_event_irq_t3[] = { TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PO5), /* wake0 */ TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PV1), /* wake1 */ TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PL1), /* wake2 */ @@ -68,55 +69,5 @@ static int tegra_wake_event_irq[] = { INT_USB3, /* TEGRA_USB3_UTMIP, */ /* wake41 */ }; -int tegra_irq_to_wake(int irq) -{ - int i; - int wake_irq; - int search_gpio; - static int last_wake = -1; - - /* Two level wake irq search for gpio based wakeups - - * 1. check for GPIO irq(based on tegra_wake_event_irq table) - * e.g. for a board, wake7 based on GPIO PU6 and irq==390 done first - * 2. check for gpio bank irq assuming search for GPIO irq - * preceded this search. - * e.g. in this step check for gpio bank irq GPIO6 irq==119 - */ - for (i = 0; i < ARRAY_SIZE(tegra_wake_event_irq); i++) { - /* return if step 1 matches */ - if (tegra_wake_event_irq[i] == irq) { - pr_info("Wake%d for irq=%d\n", i, irq); - last_wake = i; - return i; - } - - /* step 2 below uses saved last_wake from step 1 - * in previous call */ - search_gpio = irq_to_gpio( - tegra_wake_event_irq[i]); - if (search_gpio < 0) - continue; - wake_irq = tegra_gpio_get_bank_int_nr(search_gpio); - if (wake_irq < 0) - continue; - if ((last_wake == i) && - (wake_irq == irq)) { - pr_info("gpio bank wake found: wake%d for irq=%d\n", - i, irq); - return i; - } - } - - return -EINVAL; -} - -int tegra_wake_to_irq(int wake) -{ - if (wake < 0) - return -EINVAL; - - if (wake >= ARRAY_SIZE(tegra_wake_event_irq)) - return -EINVAL; - - return tegra_wake_event_irq[wake]; -} +int *tegra_wake_event_irq = tegra_wake_event_irq_t3; +unsigned int tegra_wake_event_irq_size = ARRAY_SIZE(tegra_wake_event_irq_t3); diff --git a/arch/arm/mach-tegra/wakeups-t3.h b/arch/arm/mach-tegra/wakeups-t3.h index f811d8939387..6c051270cc93 100644 --- a/arch/arm/mach-tegra/wakeups-t3.h +++ b/arch/arm/mach-tegra/wakeups-t3.h @@ -27,45 +27,45 @@ #error "Tegra 3 wakeup sources valid only for CONFIG_ARCH_TEGRA_3x_SOC" #endif -#define TEGRA_WAKE_GPIO_PO5 (1ull << 0) -#define TEGRA_WAKE_GPIO_PV1 (1ull << 1) -#define TEGRA_WAKE_GPIO_PL1 (1ull << 2) -#define TEGRA_WAKE_GPIO_PB6 (1ull << 3) -#define TEGRA_WAKE_GPIO_PN7 (1ull << 4) -#define TEGRA_WAKE_GPIO_PBB6 (1ull << 5) -#define TEGRA_WAKE_GPIO_PU5 (1ull << 6) -#define TEGRA_WAKE_GPIO_PU6 (1ull << 7) -#define TEGRA_WAKE_GPIO_PC7 (1ull << 8) -#define TEGRA_WAKE_GPIO_PS2 (1ull << 9) -#define TEGRA_WAKE_GPIO_PAA1 (1ull << 10) -#define TEGRA_WAKE_GPIO_PW3 (1ull << 11) -#define TEGRA_WAKE_GPIO_PW2 (1ull << 12) -#define TEGRA_WAKE_GPIO_PY6 (1ull << 13) -#define TEGRA_WAKE_GPIO_PDD3 (1ull << 14) -#define TEGRA_WAKE_GPIO_PJ2 (1ull << 15) -#define TEGRA_WAKE_RTC_ALARM (1ull << 16) -#define TEGRA_WAKE_KBC_EVENT (1ull << 17) -#define TEGRA_WAKE_PWR_INT (1ull << 18) -#define TEGRA_WAKE_USB1_VBUS (1ull << 19) -#define TEGRA_WAKE_USB2_VBUS (1ull << 20) -#define TEGRA_WAKE_USB1_ID (1ull << 21) -#define TEGRA_WAKE_USB2_ID (1ull << 22) -#define TEGRA_WAKE_GPIO_PI5 (1ull << 23) -#define TEGRA_WAKE_GPIO_PV0 (1ull << 24) -#define TEGRA_WAKE_GPIO_PS4 (1ull << 25) -#define TEGRA_WAKE_GPIO_PS5 (1ull << 26) -#define TEGRA_WAKE_GPIO_PS0 (1ull << 27) -#define TEGRA_WAKE_GPIO_PS6 (1ull << 28) -#define TEGRA_WAKE_GPIO_PS7 (1ull << 29) -#define TEGRA_WAKE_GPIO_PN2 (1ull << 30) +#define TEGRA_WAKE_GPIO_PO5 0 +#define TEGRA_WAKE_GPIO_PV1 1 +#define TEGRA_WAKE_GPIO_PL1 2 +#define TEGRA_WAKE_GPIO_PB6 3 +#define TEGRA_WAKE_GPIO_PN7 4 +#define TEGRA_WAKE_GPIO_PBB6 5 +#define TEGRA_WAKE_GPIO_PU5 6 +#define TEGRA_WAKE_GPIO_PU6 7 +#define TEGRA_WAKE_GPIO_PC7 8 +#define TEGRA_WAKE_GPIO_PS2 9 +#define TEGRA_WAKE_GPIO_PAA1 10 +#define TEGRA_WAKE_GPIO_PW3 11 +#define TEGRA_WAKE_GPIO_PW2 12 +#define TEGRA_WAKE_GPIO_PY6 13 +#define TEGRA_WAKE_GPIO_PDD3 14 +#define TEGRA_WAKE_GPIO_PJ2 15 +#define TEGRA_WAKE_RTC_ALARM 16 +#define TEGRA_WAKE_KBC_EVENT 17 +#define TEGRA_WAKE_PWR_INT 18 +#define TEGRA_WAKE_USB1_VBUS 19 +#define TEGRA_WAKE_USB2_VBUS 20 +#define TEGRA_WAKE_USB1_ID 21 +#define TEGRA_WAKE_USB2_ID 22 +#define TEGRA_WAKE_GPIO_PI5 23 +#define TEGRA_WAKE_GPIO_PV0 24 +#define TEGRA_WAKE_GPIO_PS4 25 +#define TEGRA_WAKE_GPIO_PS5 26 +#define TEGRA_WAKE_GPIO_PS0 27 +#define TEGRA_WAKE_GPIO_PS6 28 +#define TEGRA_WAKE_GPIO_PS7 29 +#define TEGRA_WAKE_GPIO_PN2 30 /* bit 31 is unused */ -#define TEGRA_WAKE_GPIO_PO4 (1ull << 32) -#define TEGRA_WAKE_GPIO_PJ0 (1ull << 33) -#define TEGRA_WAKE_GPIO_PK2 (1ull << 34) -#define TEGRA_WAKE_GPIO_PI6 (1ull << 35) -#define TEGRA_WAKE_GPIO_PBB1 (1ull << 36) -#define TEGRA_WAKE_USB3_ID (1ull << 37) -#define TEGRA_WAKE_USB3_VBUS (1ull << 38) +#define TEGRA_WAKE_GPIO_PO4 32 +#define TEGRA_WAKE_GPIO_PJ0 33 +#define TEGRA_WAKE_GPIO_PK2 34 +#define TEGRA_WAKE_GPIO_PI6 35 +#define TEGRA_WAKE_GPIO_PBB1 36 +#define TEGRA_WAKE_USB3_ID 37 +#define TEGRA_WAKE_USB3_VBUS 38 #endif diff --git a/arch/arm/mach-tegra/wakeups.c b/arch/arm/mach-tegra/wakeups.c new file mode 100644 index 000000000000..d53563cf22ba --- /dev/null +++ b/arch/arm/mach-tegra/wakeups.c @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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, see <http://www.gnu.org/licenses/>. + */ + +#include <linux/kernel.h> +#include <linux/gpio.h> +#include <linux/init.h> +#include <linux/io.h> +#include <linux/interrupt.h> + +#include <mach/iomap.h> +#include <mach/irqs.h> +#include <mach/gpio.h> + +#include "gpio-names.h" +#include "wakeups.h" + +extern int *tegra_wake_event_irq; +extern unsigned int tegra_wake_event_irq_size; + +int tegra_irq_to_wake(int irq) +{ + int i; + int wake_irq; + int search_gpio; + static int last_wake = -1; + + /* Two level wake irq search for gpio based wakeups - + * 1. check for GPIO irq(based on tegra_wake_event_irq table) + * e.g. for a board, wake7 based on GPIO PU6 and irq==390 done first + * 2. check for gpio bank irq assuming search for GPIO irq + * preceded this search. + * e.g. in this step check for gpio bank irq GPIO6 irq==119 + */ + for (i = 0; i < tegra_wake_event_irq_size; i++) { + /* return if step 1 matches */ + if (tegra_wake_event_irq[i] == irq) { + pr_info("Wake%d for irq=%d\n", i, irq); + last_wake = i; + return i; + } + + /* step 2 below uses saved last_wake from step 1 + * in previous call */ + search_gpio = irq_to_gpio( + tegra_wake_event_irq[i]); + if (search_gpio < 0) + continue; + wake_irq = tegra_gpio_get_bank_int_nr(search_gpio); + if (wake_irq < 0) + continue; + if ((last_wake == i) && + (wake_irq == irq)) { + pr_info("gpio bank wake found: wake%d for irq=%d\n", + i, irq); + return i; + } + } + + return -EINVAL; +} + +int tegra_wake_to_irq(int wake) +{ + if (wake < 0) + return -EINVAL; + + if (wake >= tegra_wake_event_irq_size) + return -EINVAL; + + return tegra_wake_event_irq[wake]; +} + diff --git a/arch/arm/mach-tegra/wakeups.h b/arch/arm/mach-tegra/wakeups.h new file mode 100644 index 000000000000..ab113649d534 --- /dev/null +++ b/arch/arm/mach-tegra/wakeups.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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, see <http://www.gnu.org/licenses/>. + */ + +#ifndef __WAKEUPS_H_ +#define __WAKEUPS_H_ + +/* + * given irq number returns wake source index or negative value for error + */ +int tegra_irq_to_wake(int irq); +/* + * given wake source index, returns irq number or negative value for error + */ +int tegra_wake_to_irq(int wake); + +#endif /* end __WAKEUPS_H_ */ |